Hi Daniel,
On Mon, 16 Feb 2026 at 14:22, Daniel Golle <[email protected]> wrote:
>
> 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 <[email protected]>
> ---
> 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)
This function is far too long so this code should go in its own
function. Also use if() and tools_build()
> + /*
> + * 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;
Should add a comment here about why you are not doing verification. I
assume the FS is protected with dm-verify, iwc should the root hash be
stored in the FIT?
> + }
> +
> + 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
Regards,
Simon