vbe_simple_fw.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Verified Boot for Embedded (VBE) loading firmware phases
  4. *
  5. * Copyright 2022 Google LLC
  6. * Written by Simon Glass <sjg@chromium.org>
  7. */
  8. #define LOG_CATEGORY LOGC_BOOT
  9. #include <common.h>
  10. #include <bloblist.h>
  11. #include <bootdev.h>
  12. #include <bootflow.h>
  13. #include <bootmeth.h>
  14. #include <bootstage.h>
  15. #include <dm.h>
  16. #include <image.h>
  17. #include <log.h>
  18. #include <mapmem.h>
  19. #include <memalign.h>
  20. #include <mmc.h>
  21. #include <spl.h>
  22. #include <vbe.h>
  23. #include <dm/device-internal.h>
  24. #include "vbe_simple.h"
  25. /**
  26. * vbe_simple_read_bootflow_fw() - Create a bootflow for firmware
  27. *
  28. * Locates and loads the firmware image (FIT) needed for the next phase. The FIT
  29. * should ideally use external data, to reduce the amount of it that needs to be
  30. * read.
  31. *
  32. * @bdev: bootdev device containing the firmwre
  33. * @meth: VBE simple bootmeth
  34. * @blow: Place to put the created bootflow, on success
  35. * @return 0 if OK, -ve on error
  36. */
  37. int vbe_simple_read_bootflow_fw(struct udevice *dev, struct bootflow *bflow)
  38. {
  39. ALLOC_CACHE_ALIGN_BUFFER(u8, sbuf, MMC_MAX_BLOCK_LEN);
  40. struct udevice *media = dev_get_parent(bflow->dev);
  41. struct udevice *meth = bflow->method;
  42. struct simple_priv *priv = dev_get_priv(meth);
  43. const char *fit_uname, *fit_uname_config;
  44. struct bootm_headers images = {};
  45. ulong offset, size, blknum, addr, len, load_addr, num_blks;
  46. enum image_phase_t phase;
  47. struct blk_desc *desc;
  48. struct udevice *blk;
  49. int node, ret;
  50. void *buf;
  51. log_debug("media=%s\n", media->name);
  52. ret = blk_get_from_parent(media, &blk);
  53. if (ret)
  54. return log_msg_ret("med", ret);
  55. log_debug("blk=%s\n", blk->name);
  56. desc = dev_get_uclass_plat(blk);
  57. offset = priv->area_start + priv->skip_offset;
  58. /* read in one block to find the FIT size */
  59. blknum = offset / desc->blksz;
  60. log_debug("read at %lx, blknum %lx\n", offset, blknum);
  61. ret = blk_read(blk, blknum, 1, sbuf);
  62. if (ret < 0)
  63. return log_msg_ret("rd", ret);
  64. ret = fdt_check_header(sbuf);
  65. if (ret < 0)
  66. return log_msg_ret("fdt", -EINVAL);
  67. size = fdt_totalsize(sbuf);
  68. if (size > priv->area_size)
  69. return log_msg_ret("fdt", -E2BIG);
  70. log_debug("FIT size %lx\n", size);
  71. /*
  72. * Load the FIT into the SPL memory. This is typically a FIT with
  73. * external data, so this is quite small, perhaps a few KB.
  74. */
  75. addr = CONFIG_VAL(TEXT_BASE);
  76. buf = map_sysmem(addr, size);
  77. num_blks = DIV_ROUND_UP(size, desc->blksz);
  78. log_debug("read %lx, %lx blocks to %lx / %p\n", size, num_blks, addr,
  79. buf);
  80. ret = blk_read(blk, blknum, num_blks, buf);
  81. if (ret < 0)
  82. return log_msg_ret("rd", ret);
  83. /* figure out the phase to load */
  84. phase = IS_ENABLED(CONFIG_VPL_BUILD) ? IH_PHASE_SPL : IH_PHASE_U_BOOT;
  85. /*
  86. * Load the image from the FIT. We ignore any load-address information
  87. * so in practice this simply locates the image in the external-data
  88. * region and returns its address and size. Since we only loaded the FIT
  89. * itself, only a part of the image will be present, at best.
  90. */
  91. fit_uname = NULL;
  92. fit_uname_config = NULL;
  93. log_debug("loading FIT\n");
  94. ret = fit_image_load(&images, addr, &fit_uname, &fit_uname_config,
  95. IH_ARCH_SANDBOX, image_ph(phase, IH_TYPE_FIRMWARE),
  96. BOOTSTAGE_ID_FIT_SPL_START, FIT_LOAD_IGNORED,
  97. &load_addr, &len);
  98. if (ret < 0)
  99. return log_msg_ret("ld", ret);
  100. node = ret;
  101. log_debug("loaded to %lx\n", load_addr);
  102. /* For FIT external data, read in the external data */
  103. if (load_addr + len > addr + size) {
  104. ulong base, full_size;
  105. void *base_buf;
  106. /* Find the start address to load from */
  107. base = ALIGN_DOWN(load_addr, desc->blksz);
  108. /*
  109. * Get the total number of bytes to load, taking care of
  110. * block alignment
  111. */
  112. full_size = load_addr + len - base;
  113. /*
  114. * Get the start block number, number of blocks and the address
  115. * to load to, then load the blocks
  116. */
  117. blknum = (offset + base - addr) / desc->blksz;
  118. num_blks = DIV_ROUND_UP(full_size, desc->blksz);
  119. base_buf = map_sysmem(base, full_size);
  120. ret = blk_read(blk, blknum, num_blks, base_buf);
  121. log_debug("read %lx %lx, %lx blocks to %lx / %p: ret=%d\n",
  122. blknum, full_size, num_blks, base, base_buf, ret);
  123. if (ret < 0)
  124. return log_msg_ret("rd", ret);
  125. }
  126. /* set up the bootflow with the info we obtained */
  127. bflow->name = strdup(fdt_get_name(buf, node, NULL));
  128. if (!bflow->name)
  129. return log_msg_ret("name", -ENOMEM);
  130. bflow->blk = blk;
  131. bflow->buf = map_sysmem(load_addr, len);
  132. bflow->size = len;
  133. return 0;
  134. }
  135. static int simple_load_from_image(struct spl_image_info *spl_image,
  136. struct spl_boot_device *bootdev)
  137. {
  138. struct udevice *meth, *bdev;
  139. struct simple_priv *priv;
  140. struct bootflow bflow;
  141. struct vbe_handoff *handoff;
  142. int ret;
  143. if (spl_phase() != PHASE_VPL && spl_phase() != PHASE_SPL)
  144. return -ENOENT;
  145. ret = bloblist_ensure_size(BLOBLISTT_VBE, sizeof(struct vbe_handoff),
  146. 0, (void **)&handoff);
  147. if (ret)
  148. return log_msg_ret("ro", ret);
  149. vbe_find_first_device(&meth);
  150. if (!meth)
  151. return log_msg_ret("vd", -ENODEV);
  152. log_debug("vbe dev %s\n", meth->name);
  153. ret = device_probe(meth);
  154. if (ret)
  155. return log_msg_ret("probe", ret);
  156. priv = dev_get_priv(meth);
  157. log_debug("simple %s\n", priv->storage);
  158. ret = bootdev_find_by_label(priv->storage, &bdev, NULL);
  159. if (ret)
  160. return log_msg_ret("bd", ret);
  161. log_debug("bootdev %s\n", bdev->name);
  162. bootflow_init(&bflow, bdev, meth);
  163. ret = bootmeth_read_bootflow(meth, &bflow);
  164. log_debug("\nfw ret=%d\n", ret);
  165. if (ret)
  166. return log_msg_ret("rd", ret);
  167. /* jump to the image */
  168. spl_image->flags = SPL_SANDBOXF_ARG_IS_BUF;
  169. spl_image->arg = bflow.buf;
  170. spl_image->size = bflow.size;
  171. log_debug("Image: %s at %p size %x\n", bflow.name, bflow.buf,
  172. bflow.size);
  173. /* this is not used from now on, so free it */
  174. bootflow_free(&bflow);
  175. /* Record that VBE was used in this phase */
  176. handoff->phases |= 1 << spl_phase();
  177. return 0;
  178. }
  179. SPL_LOAD_IMAGE_METHOD("vbe_simple", 5, BOOT_DEVICE_VBE,
  180. simple_load_from_image);