host_dev.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Driver for sandbox host interface, used to access files on the host which
  4. * contain partitions and filesystem
  5. *
  6. * Copyright 2022 Google LLC
  7. * Written by Simon Glass <sjg@chromium.org>
  8. */
  9. #define LOG_CATEGORY UCLASS_HOST
  10. #include <common.h>
  11. #include <blk.h>
  12. #include <bootdev.h>
  13. #include <dm.h>
  14. #include <log.h>
  15. #include <malloc.h>
  16. #include <os.h>
  17. #include <sandbox_host.h>
  18. #include <dm/device-internal.h>
  19. static int host_sb_attach_file(struct udevice *dev, const char *filename)
  20. {
  21. struct host_sb_plat *plat = dev_get_plat(dev);
  22. struct blk_desc *desc;
  23. struct udevice *blk;
  24. int ret, fd;
  25. off_t size;
  26. char *fname;
  27. if (!filename)
  28. return -EINVAL;
  29. if (plat->fd)
  30. return log_msg_ret("fd", -EEXIST);
  31. /* Sanity check that host_sb_bind() has been used */
  32. ret = blk_find_from_parent(dev, &blk);
  33. if (ret)
  34. return ret;
  35. fd = os_open(filename, OS_O_RDWR);
  36. if (fd == -1) {
  37. printf("Failed to access host backing file '%s', trying read-only\n",
  38. filename);
  39. fd = os_open(filename, OS_O_RDONLY);
  40. if (fd == -1) {
  41. printf("- still failed\n");
  42. return log_msg_ret("open", -ENOENT);
  43. }
  44. }
  45. fname = strdup(filename);
  46. if (!fname) {
  47. ret = -ENOMEM;
  48. goto err_fname;
  49. }
  50. size = os_filesize(fd);
  51. desc = dev_get_uclass_plat(blk);
  52. desc->lba = size / desc->blksz;
  53. /* write this in last, when nothing can go wrong */
  54. plat = dev_get_plat(dev);
  55. plat->fd = fd;
  56. plat->filename = fname;
  57. return 0;
  58. err_fname:
  59. os_close(fd);
  60. return ret;
  61. }
  62. int host_sb_detach_file(struct udevice *dev)
  63. {
  64. struct host_sb_plat *plat = dev_get_plat(dev);
  65. int ret;
  66. if (!plat->fd)
  67. return log_msg_ret("fd", -ENOENT);
  68. ret = device_remove(dev, DM_REMOVE_NORMAL);
  69. if (ret)
  70. return log_msg_ret("rem", ret);
  71. /* Unbind all children */
  72. ret = device_chld_unbind(dev, NULL);
  73. if (ret)
  74. return log_msg_ret("unb", ret);
  75. os_close(plat->fd);
  76. plat->fd = 0;
  77. free(plat->filename);
  78. free(plat->label);
  79. return 0;
  80. }
  81. static int host_sb_bind(struct udevice *dev)
  82. {
  83. struct udevice *blk, *bdev;
  84. struct blk_desc *desc;
  85. int ret;
  86. ret = blk_create_devicef(dev, "sandbox_host_blk", "blk", UCLASS_HOST,
  87. dev_seq(dev), 512, 0, &blk);
  88. if (ret)
  89. return log_msg_ret("blk", ret);
  90. desc = dev_get_uclass_plat(blk);
  91. snprintf(desc->vendor, BLK_VEN_SIZE, "U-Boot");
  92. snprintf(desc->product, BLK_PRD_SIZE, "hostfile");
  93. snprintf(desc->revision, BLK_REV_SIZE, "1.0");
  94. if (CONFIG_IS_ENABLED(BOOTSTD)) {
  95. ret = bootdev_bind(dev, "host_bootdev", "bootdev", &bdev);
  96. if (ret)
  97. return log_msg_ret("bd", ret);
  98. }
  99. return 0;
  100. }
  101. struct host_ops host_sb_ops = {
  102. .attach_file = host_sb_attach_file,
  103. .detach_file = host_sb_detach_file,
  104. };
  105. static const struct udevice_id host_ids[] = {
  106. { .compatible = "sandbox,host" },
  107. { }
  108. };
  109. U_BOOT_DRIVER(host_sb_drv) = {
  110. .name = "host_sb_drv",
  111. .id = UCLASS_HOST,
  112. .of_match = host_ids,
  113. .ops = &host_sb_ops,
  114. .bind = host_sb_bind,
  115. .plat_auto = sizeof(struct host_sb_plat),
  116. };