From: Simon Glass <sjg@chromium.org>
To: U-Boot Mailing List <u-boot@lists.denx.de>
Cc: Tom Rini <trini@konsulko.com>, Simon Glass <sjg@chromium.org>
Subject: [PATCH 02/15] vbe: Split out reading a FIT into a common file
Date: Thu, 9 Jan 2025 05:29:57 -0700 [thread overview]
Message-ID: <20250109123010.4005298-3-sjg@chromium.org> (raw)
In-Reply-To: <20250109123010.4005298-1-sjg@chromium.org>
Loading a FIT is useful for other VBE methods, such as ABrec. Create a
new function to handling reading it.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
boot/vbe_common.c | 103 +++++++++++++++++++++++++++++++++++++++++++
boot/vbe_common.h | 28 ++++++++++++
boot/vbe_simple_fw.c | 94 ++-------------------------------------
3 files changed, 135 insertions(+), 90 deletions(-)
diff --git a/boot/vbe_common.c b/boot/vbe_common.c
index 5f31cde0288..c009337ef3f 100644
--- a/boot/vbe_common.c
+++ b/boot/vbe_common.c
@@ -18,6 +18,109 @@
#include <u-boot/crc.h>
#include "vbe_common.h"
+int vbe_read_fit(struct udevice *blk, ulong area_offset, ulong area_size,
+ ulong *load_addrp, ulong *lenp, char **namep)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(u8, sbuf, MMC_MAX_BLOCK_LEN);
+ ulong size, blknum, addr, len, load_addr, num_blks;
+ const char *fit_uname, *fit_uname_config;
+ struct bootm_headers images = {};
+ enum image_phase_t phase;
+ struct blk_desc *desc;
+ int node, ret;
+ void *buf;
+
+ desc = dev_get_uclass_plat(blk);
+
+ /* read in one block to find the FIT size */
+ blknum = area_offset / desc->blksz;
+ log_debug("read at %lx, blknum %lx\n", area_offset, blknum);
+ ret = blk_read(blk, blknum, 1, sbuf);
+ if (ret < 0)
+ return log_msg_ret("rd", ret);
+
+ ret = fdt_check_header(sbuf);
+ if (ret < 0)
+ return log_msg_ret("fdt", -EINVAL);
+ size = fdt_totalsize(sbuf);
+ if (size > area_size)
+ return log_msg_ret("fdt", -E2BIG);
+ log_debug("FIT size %lx\n", size);
+
+ /*
+ * Load the FIT into the SPL memory. This is typically a FIT with
+ * external data, so this is quite small, perhaps a few KB.
+ */
+ addr = CONFIG_VAL(TEXT_BASE);
+ buf = map_sysmem(addr, size);
+ num_blks = DIV_ROUND_UP(size, desc->blksz);
+ log_debug("read %lx, %lx blocks to %lx / %p\n", size, num_blks, addr,
+ buf);
+ ret = blk_read(blk, blknum, num_blks, buf);
+ if (ret < 0)
+ return log_msg_ret("rd", ret);
+
+ /* figure out the phase to load */
+ phase = IS_ENABLED(CONFIG_VPL_BUILD) ? IH_PHASE_SPL : IH_PHASE_U_BOOT;
+
+ /*
+ * Load the image from the FIT. We ignore any load-address information
+ * so in practice this simply locates the image in the external-data
+ * region and returns its address and size. Since we only loaded the FIT
+ * itself, only a part of the image will be present, at best.
+ */
+ fit_uname = NULL;
+ fit_uname_config = NULL;
+ log_debug("loading FIT\n");
+ ret = fit_image_load(&images, addr, &fit_uname, &fit_uname_config,
+ IH_ARCH_SANDBOX, image_ph(phase, IH_TYPE_FIRMWARE),
+ BOOTSTAGE_ID_FIT_SPL_START, FIT_LOAD_IGNORED,
+ &load_addr, &len);
+ if (ret < 0)
+ return log_msg_ret("ld", ret);
+ node = ret;
+ log_debug("loaded to %lx\n", load_addr);
+
+ /* For FIT external data, read in the external data */
+ if (load_addr + len > addr + size) {
+ ulong base, full_size;
+ void *base_buf;
+
+ /* Find the start address to load from */
+ base = ALIGN_DOWN(load_addr, desc->blksz);
+
+ /*
+ * Get the total number of bytes to load, taking care of
+ * block alignment
+ */
+ full_size = load_addr + len - base;
+
+ /*
+ * Get the start block number, number of blocks and the address
+ * to load to, then load the blocks
+ */
+ blknum = (area_offset + base - addr) / desc->blksz;
+ num_blks = DIV_ROUND_UP(full_size, desc->blksz);
+ base_buf = map_sysmem(base, full_size);
+ ret = blk_read(blk, blknum, num_blks, base_buf);
+ log_debug("read %lx %lx, %lx blocks to %lx / %p: ret=%d\n",
+ blknum, full_size, num_blks, base, base_buf, ret);
+ if (ret < 0)
+ return log_msg_ret("rd", ret);
+ }
+ if (load_addrp)
+ *load_addrp = load_addr;
+ if (lenp)
+ *lenp = len;
+ if (namep) {
+ *namep = strdup(fdt_get_name(buf, node, NULL));
+ if (!namep)
+ return log_msg_ret("nam", -ENOMEM);
+ }
+
+ return 0;
+}
+
int vbe_read_version(struct udevice *blk, ulong offset, char *version,
int max_size)
{
diff --git a/boot/vbe_common.h b/boot/vbe_common.h
index df133fbf05f..403391ff1ea 100644
--- a/boot/vbe_common.h
+++ b/boot/vbe_common.h
@@ -140,4 +140,32 @@ int vbe_read_version(struct udevice *blk, ulong offset, char *version,
*/
int vbe_get_blk(const char *storage, struct udevice **blkp);
+/**
+ * vbe_read_fit() - Read an image from a FIT
+ *
+ * This handles most of the VBE logic for reading from a FIT. It reads the FIT
+ * metadata, decides which image to load and loads it to a suitable address,
+ * ready for jumping to the next phase of VBE.
+ *
+ * This supports transition from VPL to SPL as well as SPL to U-Boot proper. For
+ * now, TPL->VPL is not supported.
+ *
+ * Both embedded and external data are supported for the FIT
+ *
+ * @blk: Block device containing FIT
+ * @area_offset: Byte offset of the VBE area in @blk containing the FIT
+ * @area_size: Size of the VBE area
+ * @load_addrp: If non-null, returns the address where the image was loaded
+ * @lenp: If non-null, returns the size of the image loaded, in bytes
+ * @namep: If non-null, returns the name of the FIT-image node that was loaded
+ * (allocated by this function)
+ * Return: 0 if OK, -EINVAL if the area does not contain an FDT (the underlying
+ * format for FIT), -E2BIG if the FIT extends past @area_size, -ENOMEM if there
+ * was not space to allocate the image-node name, other error if a read error
+ * occurred (see blk_read()), or something went wrong with the actually
+ * FIT-parsing (see fit_image_load()).
+ */
+int vbe_read_fit(struct udevice *blk, ulong area_offset, ulong area_size,
+ ulong *load_addrp, ulong *lenp, char **namep);
+
#endif /* __VBE_ABREC_H */
diff --git a/boot/vbe_simple_fw.c b/boot/vbe_simple_fw.c
index da9701f9eb9..0bf25ccad23 100644
--- a/boot/vbe_simple_fw.c
+++ b/boot/vbe_simple_fw.c
@@ -38,109 +38,23 @@
*/
int vbe_simple_read_bootflow_fw(struct udevice *dev, struct bootflow *bflow)
{
- ALLOC_CACHE_ALIGN_BUFFER(u8, sbuf, MMC_MAX_BLOCK_LEN);
struct udevice *media = dev_get_parent(bflow->dev);
struct udevice *meth = bflow->method;
struct simple_priv *priv = dev_get_priv(meth);
- const char *fit_uname, *fit_uname_config;
- struct bootm_headers images = {};
- ulong offset, size, blknum, addr, len, load_addr, num_blks;
- enum image_phase_t phase;
- struct blk_desc *desc;
+ ulong len, load_addr;
struct udevice *blk;
- int node, ret;
- void *buf;
+ int ret;
log_debug("media=%s\n", media->name);
ret = blk_get_from_parent(media, &blk);
if (ret)
return log_msg_ret("med", ret);
log_debug("blk=%s\n", blk->name);
- desc = dev_get_uclass_plat(blk);
-
- offset = priv->area_start + priv->skip_offset;
-
- /* read in one block to find the FIT size */
- blknum = offset / desc->blksz;
- log_debug("read at %lx, blknum %lx\n", offset, blknum);
- ret = blk_read(blk, blknum, 1, sbuf);
- if (ret < 0)
- return log_msg_ret("rd", ret);
-
- ret = fdt_check_header(sbuf);
- if (ret < 0)
- return log_msg_ret("fdt", -EINVAL);
- size = fdt_totalsize(sbuf);
- if (size > priv->area_size)
- return log_msg_ret("fdt", -E2BIG);
- log_debug("FIT size %lx\n", size);
-
- /*
- * Load the FIT into the SPL memory. This is typically a FIT with
- * external data, so this is quite small, perhaps a few KB.
- */
- addr = CONFIG_VAL(TEXT_BASE);
- buf = map_sysmem(addr, size);
- num_blks = DIV_ROUND_UP(size, desc->blksz);
- log_debug("read %lx, %lx blocks to %lx / %p\n", size, num_blks, addr,
- buf);
- ret = blk_read(blk, blknum, num_blks, buf);
- if (ret < 0)
- return log_msg_ret("rd", ret);
- /* figure out the phase to load */
- phase = IS_ENABLED(CONFIG_VPL_BUILD) ? IH_PHASE_SPL : IH_PHASE_U_BOOT;
-
- /*
- * Load the image from the FIT. We ignore any load-address information
- * so in practice this simply locates the image in the external-data
- * region and returns its address and size. Since we only loaded the FIT
- * itself, only a part of the image will be present, at best.
- */
- fit_uname = NULL;
- fit_uname_config = NULL;
- log_debug("loading FIT\n");
- ret = fit_image_load(&images, addr, &fit_uname, &fit_uname_config,
- IH_ARCH_SANDBOX, image_ph(phase, IH_TYPE_FIRMWARE),
- BOOTSTAGE_ID_FIT_SPL_START, FIT_LOAD_IGNORED,
- &load_addr, &len);
- if (ret < 0)
- return log_msg_ret("ld", ret);
- node = ret;
- log_debug("loaded to %lx\n", load_addr);
-
- /* For FIT external data, read in the external data */
- if (load_addr + len > addr + size) {
- ulong base, full_size;
- void *base_buf;
-
- /* Find the start address to load from */
- base = ALIGN_DOWN(load_addr, desc->blksz);
-
- /*
- * Get the total number of bytes to load, taking care of
- * block alignment
- */
- full_size = load_addr + len - base;
-
- /*
- * Get the start block number, number of blocks and the address
- * to load to, then load the blocks
- */
- blknum = (offset + base - addr) / desc->blksz;
- num_blks = DIV_ROUND_UP(full_size, desc->blksz);
- base_buf = map_sysmem(base, full_size);
- ret = blk_read(blk, blknum, num_blks, base_buf);
- log_debug("read %lx %lx, %lx blocks to %lx / %p: ret=%d\n",
- blknum, full_size, num_blks, base, base_buf, ret);
- if (ret < 0)
- return log_msg_ret("rd", ret);
- }
+ ret = vbe_read_fit(blk, priv->area_start + priv->skip_offset,
+ priv->area_size, &load_addr, &len, &bflow->name);
/* set up the bootflow with the info we obtained */
- bflow->name = strdup(fdt_get_name(buf, node, NULL));
- if (!bflow->name)
- return log_msg_ret("name", -ENOMEM);
bflow->blk = blk;
bflow->buf = map_sysmem(load_addr, len);
bflow->size = len;
--
2.34.1
next prev parent reply other threads:[~2025-01-09 12:30 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-09 12:29 [PATCH 00/15] vbe: Series part F Simon Glass
2025-01-09 12:29 ` [PATCH 01/15] vbe: Split out some VBE code into a common file Simon Glass
2025-01-14 1:22 ` Tom Rini
2025-01-14 12:58 ` Simon Glass
2025-01-14 13:26 ` Simon Glass
2025-01-14 16:58 ` Tom Rini
2025-01-14 17:33 ` Tom Rini
2025-01-15 1:18 ` Simon Glass
2025-01-15 1:41 ` Tom Rini
2025-01-15 2:48 ` Simon Glass
2025-01-15 14:10 ` Simon Glass
2025-01-09 12:29 ` Simon Glass [this message]
2025-01-11 22:54 ` [PATCH 02/15] vbe: Split out reading a FIT " Tom Rini
2025-01-13 20:03 ` Simon Glass
2025-01-13 20:44 ` Tom Rini
2025-01-14 0:13 ` Simon Glass
2025-01-14 1:22 ` Tom Rini
2025-01-15 14:43 ` Tom Rini
2025-01-15 23:21 ` Simon Glass
2025-01-09 12:29 ` [PATCH 03/15] vbe: Allocate space for the FIT header Simon Glass
2025-01-09 12:29 ` [PATCH 04/15] vbe: Allow VBE to load FITs on any architecture Simon Glass
2025-01-09 12:30 ` [PATCH 05/15] vbe: Tidy up error checking with blk_read() Simon Glass
2025-01-09 12:30 ` [PATCH 06/15] vbe: Handle loading from an unaligned offset Simon Glass
2025-01-09 12:30 ` [PATCH 07/15] vbe: Allow loading loadables if there is no firmware Simon Glass
2025-01-09 12:30 ` [PATCH 08/15] vbe: Support loading an FDT from the FIT Simon Glass
2025-01-09 12:30 ` [PATCH 09/15] spl: Add fields for VBE Simon Glass
2025-01-09 12:30 ` [PATCH 10/15] spl: Add a type for the jumper function Simon Glass
2025-01-09 12:30 ` [PATCH 11/15] spl: Add support for a relocating jump to the next phase Simon Glass
2025-01-09 12:30 ` [PATCH 12/15] spl: Plumb in the relocating loader Simon Glass
2025-01-09 12:30 ` [PATCH 13/15] vbe: Support loading an FDT with " Simon Glass
2025-01-09 12:30 ` [PATCH 14/15] vbe: Support loading SPL images Simon Glass
2025-01-09 12:30 ` [PATCH 15/15] vbe: Update simple-fw to support using the SPL loader Simon Glass
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250109123010.4005298-3-sjg@chromium.org \
--to=sjg@chromium.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.