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

Reply via email to