[PATCH 1/3] efi_loader: efi_load_initrd: provide a memory mapped initrd

Heinrich Schuchardt xypron.glpk at gmx.de
Fri Apr 11 09:47:36 CEST 2025


On 3/18/25 14:23, Adriano Cordova wrote:
> U-Boot can pass an initrd to subsequent boot stages via the
> EFI_LOAD_FILE2_PROTOCOL. The current implementation only supports
> this functionality via the efi boot manager: the initrd is taken
> from the load options of the BootCurrent variable. This commit adds
> support for registering a memory mapped initrd, e.g. loaded from a
> FIT image. For now this new method takes precedence over loading the
> initrd from the BootCurrent variable (if both are present) because
> the BootCurrent variable is not cleared on exiting the boot manager.
>
> Signed-off-by: Adriano Cordova <adriano.cordova at canonical.com>
> ---
>   include/efi_loader.h             |  2 +-
>   lib/efi_loader/efi_bootmgr.c     |  2 +-
>   lib/efi_loader/efi_load_initrd.c | 71 +++++++++++++++++++++++++++-----
>   3 files changed, 62 insertions(+), 13 deletions(-)
>
> diff --git a/include/efi_loader.h b/include/efi_loader.h
> index e9c10819ba2..cc732dc4807 100644
> --- a/include/efi_loader.h
> +++ b/include/efi_loader.h
> @@ -667,7 +667,7 @@ efi_status_t efi_http_register(const efi_handle_t handle,
>   			       struct efi_service_binding_protocol *http_service_binding);
>   /* Called by bootefi to make the watchdog available */
>   efi_status_t efi_watchdog_register(void);
> -efi_status_t efi_initrd_register(void);
> +efi_status_t efi_initrd_register(struct efi_device_path *dp_initrd);
>   efi_status_t efi_initrd_deregister(void);
>   /* Called by bootefi to make SMBIOS tables available */
>   /**
> diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
> index c6124c590d9..6e66cf3793c 100644
> --- a/lib/efi_loader/efi_bootmgr.c
> +++ b/lib/efi_loader/efi_bootmgr.c
> @@ -670,7 +670,7 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
>
>   	/* try to register load file2 for initrd's */
>   	if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) {
> -		ret = efi_initrd_register();
> +		ret = efi_initrd_register(NULL);
>   		if (ret != EFI_SUCCESS)
>   			goto error;
>   	}
> diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c
> index fb8cc7bcbe3..74b92f8bd66 100644
> --- a/lib/efi_loader/efi_load_initrd.c
> +++ b/lib/efi_loader/efi_load_initrd.c
> @@ -42,6 +42,7 @@ static const struct efi_lo_dp_prefix dp_lf2_handle = {
>   };
>
>   static efi_handle_t efi_initrd_handle;
> +static struct efi_device_path *efi_initrd_dp;
>
>   /**
>    * get_initrd_fp() - Get initrd device path from a FilePathList device path
> @@ -72,6 +73,41 @@ static efi_status_t get_initrd_fp(struct efi_device_path **initrd_fp)
>   	return EFI_SUCCESS;
>   }
>
> +/**
> + * efi_initrd_from_mem() - load initial RAM disk from memory
> + *
> + * This function copies the initrd from the memory mapped device
> + * path pointed to by efi_initrd_dp
> + *
> + * @buffer_size:		size of allocated buffer
> + * @buffer:			buffer to load the file
> + *
> + * Return:			status code
> + */
> +static efi_status_t efi_initrd_from_mem(efi_uintn_t *buffer_size, void *buffer)
> +{
> +	efi_status_t ret = EFI_NOT_FOUND;
> +	efi_uintn_t bs;
> +	struct efi_device_path_memory *mdp;
> +
> +	mdp = (struct efi_device_path_memory *)efi_initrd_dp;
> +	if (!mdp)
> +		return ret;
> +
> +	bs = mdp->end_address - mdp->start_address;
> +
> +	if (!buffer || *buffer_size < bs) {
> +		ret = EFI_BUFFER_TOO_SMALL;
> +		*buffer_size = bs;
> +	} else {
> +		memcpy(buffer, (void *)mdp->start_address, bs);

This fails to build on 32bit:

+lib/efi_loader/efi_load_initrd.c: In function 'efi_initrd_from_mem':
+lib/efi_loader/efi_load_initrd.c:103:32: error: cast to pointer from
integer of different size [-Werror=int-to-pointer-cast]
+  103 |                 memcpy(buffer, (void *)mdp->start_address, bs);
+      |                                ^

start_address is of type u64.

(void *)(uinptr_t) is the correct conversion.

Best regards

Heinrich

> +		*buffer_size = bs;
> +		ret = EFI_SUCCESS;
> +	}
> +
> +	return ret;
> +}
> +
>   /**
>    * efi_load_file2_initrd() - load initial RAM disk
>    *
> @@ -118,6 +154,9 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this,
>   		goto out;
>   	}
>
> +	if (efi_initrd_dp)
> +		return EFI_EXIT(efi_initrd_from_mem(buffer_size, buffer));
> +
>   	ret = get_initrd_fp(&initrd_fp);
>   	if (ret != EFI_SUCCESS)
>   		goto out;
> @@ -209,6 +248,9 @@ efi_status_t efi_initrd_deregister(void)
>   							 NULL);
>   	efi_initrd_handle = NULL;
>
> +	efi_free_pool(efi_initrd_dp);
> +	efi_initrd_dp = NULL;
> +
>   	return ret;
>   }
>
> @@ -234,24 +276,31 @@ static void EFIAPI efi_initrd_return_notify(struct efi_event *event,
>    * This function creates a new handle and installs a Linux specific vendor
>    * device path and an EFI_LOAD_FILE2_PROTOCOL. Linux uses the device path
>    * to identify the handle and then calls the LoadFile service of the
> - * EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk.
> + * EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk. If dp_initrd is
> + * not provided, the initrd will be taken from the BootCurrent variable
> + *
> + * @dp_initrd:	optional device path containing an initrd
>    *
>    * Return:	status code
>    */
> -efi_status_t efi_initrd_register(void)
> +efi_status_t efi_initrd_register(struct efi_device_path *dp_initrd)
>   {
>   	efi_status_t ret;
>   	struct efi_event *event;
>
> -	/*
> -	 * Allow the user to continue if Boot#### file path is not set for
> -	 * an initrd
> -	 */
> -	ret = check_initrd();
> -	if (ret == EFI_INVALID_PARAMETER)
> -		return EFI_SUCCESS;
> -	if (ret != EFI_SUCCESS)
> -		return ret;
> +	if (dp_initrd) {
> +		efi_initrd_dp = dp_initrd;
> +	} else {
> +		/*
> +		* Allow the user to continue if Boot#### file path is not set for
> +		* an initrd
> +		*/
> +		ret = check_initrd();
> +		if (ret == EFI_INVALID_PARAMETER)
> +			return EFI_SUCCESS;
> +		if (ret != EFI_SUCCESS)
> +			return ret;
> +	}
>
>   	ret = efi_install_multiple_protocol_interfaces(&efi_initrd_handle,
>   						       /* initramfs */



More information about the U-Boot mailing list