On 10/6/25 6:15 AM, [email protected] wrote:
> From: Ahmad Fatoum <[email protected]>
> 
> Extend the EFI payload boot flow to support loading kernel, initrd,
> and devicetree directly from a FIT image. When a FIT is present,
> the loader extracts the relevant subimages ("kernel", "ramdisk",
> and "fdt") also support falling back to external files when possible.
> 
> Signed-off-by: Chali Anis <[email protected]>

Reviewed-by: Ahmad Fatoum <[email protected]>

> ---
>  efi/payload/Kconfig |   1 +
>  efi/payload/bootm.c | 125 ++++++++++++++++++++++++++++++++++++--------
>  2 files changed, 104 insertions(+), 22 deletions(-)
> 
> diff --git a/efi/payload/Kconfig b/efi/payload/Kconfig
> index e3a6a72d6a1c..4fb866210a69 100644
> --- a/efi/payload/Kconfig
> +++ b/efi/payload/Kconfig
> @@ -32,6 +32,7 @@ config EFI_HANDOVER_PROTOCOL
>  
>  config EFI_PAYLOAD_BOOTM
>       bool "EFI bootm protocol"
> +     select BOOTM_FITIMAGE
>       default !X86
>  
>  endif
> diff --git a/efi/payload/bootm.c b/efi/payload/bootm.c
> index d0e995be5d7c..3e9ccd42bf7f 100644
> --- a/efi/payload/bootm.c
> +++ b/efi/payload/bootm.c
> @@ -34,11 +34,74 @@
>  #include "image.h"
>  #include "setup_header.h"
>  
> +static bool ramdisk_is_fit(struct image_data *data)
> +{
> +     struct stat st;
> +
> +     if (bootm_signed_images_are_forced())
> +             return true;
> +
> +     if (data->initrd_file) {
> +             if (!stat(data->initrd_file, &st) && st.st_size > 0)
> +                     return false;
> +     }
> +
> +     return data->os_fit ? fit_has_image(data->os_fit,
> +                     data->fit_config, "ramdisk") > 0 : false;
> +}
> +
> +static bool fdt_is_fit(struct image_data *data)
> +{
> +     struct stat st;
> +
> +     if (bootm_signed_images_are_forced())
> +             return true;
> +
> +     if (data->oftree_file) {
> +             if (!stat(data->oftree_file, &st) && st.st_size > 0)
> +                     return false;
> +     }
> +
> +     return data->os_fit ? fit_has_image(data->os_fit,
> +                     data->fit_config, "fdt") > 0 : false;
> +}
> +
>  static int efi_load_os(struct image_data *data,
>                      struct efi_loaded_image **loaded_image,
>                      efi_handle_t *handle)
>  {
> -     return efi_load_image(data->os_file, loaded_image, handle);
> +     efi_status_t efiret;
> +     efi_handle_t h;
> +
> +     if (!data->os_fit)
> +             return efi_load_image(data->os_file, loaded_image, handle);
> +
> +     if (!data->fit_kernel)
> +             return -ENOENT;
> +
> +     efiret = BS->load_image(false, efi_parent_image, efi_device_path,
> +                             (void *)data->fit_kernel, 
> data->fit_kernel_size, &h);
> +     if (EFI_ERROR(efiret)) {
> +             pr_err("failed to LoadImage: %s\n", efi_strerror(efiret));
> +             goto out_mem;
> +     };
> +
> +     efiret = BS->open_protocol(h, &efi_loaded_image_protocol_guid,
> +                                (void **)loaded_image, efi_parent_image,
> +                                NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
> +     if (EFI_ERROR(efiret)) {
> +             pr_err("failed to OpenProtocol: %s\n", efi_strerror(efiret));
> +             goto out_unload;
> +     }
> +
> +     *handle = h;
> +
> +     return 0;
> +
> +out_unload:
> +     BS->unload_image(h);
> +out_mem:
> +     return -efi_errno(efiret);
>  }
>  
>  static int efi_load_ramdisk(struct image_data *data, void **initrd)
> @@ -47,17 +110,26 @@ static int efi_load_ramdisk(struct image_data *data, 
> void **initrd)
>       void *initrd_mem;
>       int ret;
>  
> -     if (!data->initrd_file)
> -             return 0;
> -
> -     pr_info("Loading ramdisk from '%s'\n", data->initrd_file);
> -
> -     initrd_mem = read_file(data->initrd_file, &initrd_size);
> -     if (!initrd_mem) {
> -             ret = -errno;
> -             pr_err("Failed to read initrd from file '%s': %m\n",
> -                    data->initrd_file);
> -             return ret;
> +     if (ramdisk_is_fit(data)) {
> +             ret = fit_open_image(data->os_fit, data->fit_config, "ramdisk",
> +                                  (const void **)&initrd_mem, &initrd_size);
> +             if (ret) {
> +                     pr_err("Cannot open ramdisk image in FIT image: %m\n");
> +                     return ret;
> +             }
> +     } else {
> +             if (!data->initrd_file)
> +                     return 0;
> +
> +             pr_info("Loading ramdisk from '%s'\n", data->initrd_file);
> +
> +             initrd_mem = read_file(data->initrd_file, &initrd_size);
> +             if (!initrd_mem) {
> +                     ret = -errno;
> +                     pr_err("Failed to read initrd from file '%s': %m\n",
> +                            data->initrd_file);
> +                     return ret;
> +             }
>       }
>  
>       ret = efi_initrd_register(initrd_mem, initrd_size);
> @@ -84,16 +156,25 @@ static int efi_load_fdt(struct image_data *data, void 
> **fdt)
>       unsigned long of_size;
>       int ret;
>  
> -     if (!data->oftree_file)
> -             return 0;
> -
> -     pr_info("Loading devicetree from '%s'\n", data->oftree_file);
> -
> -     of_tree = read_file(data->oftree_file, &of_size);
> -     if (!of_tree) {
> -             ret = -errno;
> -             pr_err("Failed to read oftree: %m\n");
> -             return ret;
> +     if (fdt_is_fit(data)) {
> +             ret = fit_open_image(data->os_fit, data->fit_config, "fdt",
> +                                  (const void **)&of_tree, &of_size);
> +             if (ret) {
> +                     pr_err("Cannot open FDT image in FIT image: %m\n");
> +                     return ret;
> +             }
> +     } else {
> +             if (!data->oftree_file)
> +                     return 0;
> +
> +             pr_info("Loading devicetree from '%s'\n", data->oftree_file);
> +
> +             of_tree = read_file(data->oftree_file, &of_size);
> +             if (!of_tree) {
> +                     ret = -errno;
> +                     pr_err("Failed to read oftree: %m\n");
> +                     return ret;
> +             }
>       }
>  
>       efiret = BS->allocate_pages(EFI_ALLOCATE_ANY_PAGES,

-- 
Pengutronix e.K.                  |                             |
Steuerwalder Str. 21              | http://www.pengutronix.de/  |
31137 Hildesheim, Germany         | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686  | Fax:   +49-5121-206917-5555 |


Reply via email to