[RFC PATCH 09/20] boot: fit: support on-demand loading in fit_image_load()
Daniel Golle
daniel at makrotopia.org
Mon Feb 16 22:22:42 CET 2026
Add an on-demand loading path to fit_image_load() for use when
images->loader is set (storage-backed boot).
For external-data FIT images, the new path avoids dereferencing
fit + data_offset (which would point into unmapped memory) and
instead:
1. Extracts the data offset and size from FDT properties
(data-position / data-offset + data-size) -- metadata only,
no payload access.
2. Returns early for IH_TYPE_FILESYSTEM sub-images, which stay on
storage and are never loaded into RAM (e.g. squashfs rootfs).
3. Determines the RAM destination:
- If the sub-image has a load address, loads directly there
via image_loader_map_to() (zero-copy).
- Otherwise, allocates scratch RAM via image_loader_map().
4. Verifies the hash/signature in-place using
fit_image_verify_with_data(), which is address-agnostic.
5. Jumps to the common tail, skipping the normal
fit_image_get_data() + memcpy() sequence since data is already
at its final location.
The entire path is gated by 'if (images->loader && external)' and
USE_HOSTCC, so the existing in-memory flow is completely unchanged
when no loader is set or when building host tools.
For inline-data FIT images (no data-position/data-offset), the FDT
structure loaded during format detection already contains all sub-
image data, so the existing path handles them correctly.
Also adds a 'struct image_loader *loader' member to struct
bootm_headers (initialised to NULL).
Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
boot/image-fit.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++
include/image.h | 4 ++
2 files changed, 100 insertions(+)
diff --git a/boot/image-fit.c b/boot/image-fit.c
index 3ed69b5f7bc..73d3bf7df08 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -24,6 +24,7 @@ extern void *aligned_alloc(size_t alignment, size_t size);
#include <linux/sizes.h>
#include <errno.h>
#include <log.h>
+#include <image-loader.h>
#include <mapmem.h>
#include <asm/io.h>
#include <malloc.h>
@@ -2166,6 +2167,100 @@ int fit_image_load(struct bootm_headers *images, ulong addr,
printf(" Trying '%s' %s subimage\n", fit_uname, prop_name);
+#if !defined(USE_HOSTCC) && CONFIG_IS_ENABLED(IMAGE_LOADER)
+ /*
+ * Storage-backed path: when an image_loader is active and the
+ * sub-image uses external data, load the payload from storage
+ * instead of dereferencing fit + data_offset. The FDT structure
+ * (containing all metadata, hashes, and signatures) is already
+ * in RAM; only the payload is on storage.
+ *
+ * Sequence:
+ * 1. Print image info (fit_image_select with verify=0)
+ * 2. Extract data location from FDT properties (no data access)
+ * 3. Skip IH_TYPE_FILESYSTEM sub-images — they stay on storage
+ * 4. Determine RAM destination (load address or scratch area)
+ * 5. Read payload via image_loader_map_to() / image_loader_map()
+ * 6. Verify hash/signature in-place
+ * 7. Jump to common tail (FDT validation, output params)
+ */
+ if (images && images->loader) {
+ int data_off = 0, data_sz = 0;
+ bool external = false;
+ u8 img_type;
+
+ if (!fit_image_get_data_position(fit, noffset, &data_off)) {
+ external = true;
+ } else if (!fit_image_get_data_offset(fit, noffset, &data_off)) {
+ external = true;
+ data_off += ALIGN(fdt_totalsize(fit), 4);
+ }
+
+ if (external && !fit_image_get_data_size(fit, noffset, &data_sz)) {
+ /* Print image info without verifying data */
+ ret = fit_image_select(fit, noffset, 0);
+ if (ret) {
+ bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH);
+ return ret;
+ }
+
+ /* Skip filesystem images — they stay on storage */
+ if (!fit_image_get_type(fit, noffset, &img_type) &&
+ img_type == IH_TYPE_FILESYSTEM) {
+ *datap = 0;
+ *lenp = 0;
+ return noffset;
+ }
+
+ len = data_sz;
+ comp = IH_COMP_NONE;
+ fit_image_get_comp(fit, noffset, &comp);
+
+ /* Determine the RAM destination */
+ if (load_op == FIT_LOAD_IGNORED) {
+ loadbuf = image_loader_map(images->loader,
+ data_off, len);
+ } else if (!fit_image_get_load(fit, noffset, &load)) {
+ printf(" Loading %s from storage to 0x%08lx\n",
+ prop_name, load);
+ loadbuf = map_sysmem(load, len);
+ loadbuf = image_loader_map_to(images->loader,
+ data_off, len,
+ loadbuf);
+ } else if (load_op == FIT_LOAD_REQUIRED) {
+ printf("Can't get %s subimage load address!\n",
+ prop_name);
+ return -EBADF;
+ } else {
+ loadbuf = image_loader_map(images->loader,
+ data_off, len);
+ }
+
+ if (!loadbuf) {
+ printf("Failed to load %s from storage\n",
+ prop_name);
+ return -EIO;
+ }
+
+ load = map_to_sysmem(loadbuf);
+
+ /* Verify hash/signature in-place */
+ if (images->verify) {
+ puts(" Verifying Hash Integrity ... ");
+ if (!fit_image_verify_with_data(fit, noffset,
+ gd_fdt_blob(),
+ loadbuf, len)) {
+ puts("Bad Data Hash\n");
+ return -EACCES;
+ }
+ puts("OK\n");
+ }
+
+ goto storage_loaded;
+ }
+ }
+#endif /* !USE_HOSTCC && CONFIG_IMAGE_LOADER */
+
ret = fit_image_select(fit, noffset, images->verify);
if (ret) {
bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH);
@@ -2325,6 +2420,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr,
puts("WARNING: 'compression' nodes for ramdisks are deprecated,"
" please fix your .its file!\n");
+storage_loaded:
/* verify that image data is a proper FDT blob */
if (load_op != FIT_LOAD_IGNORED && image_type == IH_TYPE_FLATDT &&
fdt_check_header(loadbuf)) {
diff --git a/include/image.h b/include/image.h
index 34efac6056d..ecb3fec26c0 100644
--- a/include/image.h
+++ b/include/image.h
@@ -345,6 +345,8 @@ struct image_info {
uint8_t arch; /* CPU architecture */
};
+struct image_loader;
+
/*
* Legacy and FIT format headers used by do_bootm() and do_bootm_<os>()
* routines.
@@ -400,6 +402,8 @@ struct bootm_headers {
int verify; /* env_get("verify")[0] != 'n' */
+ struct image_loader *loader; /* on-demand storage loader, or NULL */
+
#define BOOTM_STATE_START 0x00000001
#define BOOTM_STATE_FINDOS 0x00000002
#define BOOTM_STATE_FINDOTHER 0x00000004
--
2.53.0
More information about the U-Boot
mailing list