diff mbox series

[RFC,2/3] efi_loader: bootmgr: add booting from removable media

Message ID 20211109013233.72902-3-takahiro.akashi@linaro.org
State New
Headers show
Series efi_loader: bootmgr itself should support removable media | expand

Commit Message

AKASHI Takahiro Nov. 9, 2021, 1:32 a.m. UTC
Under the current implementation, booting from removal media using
a architecture-specific default image name, say BOOTAA64.EFI, is
supported only in distro_bootcmd script. See the commit 74522c898b35
("efi_loader: Add distro boot script for removable media").

This is, however, half-baked implementation because
1) UEFI specification requires this feature to be implemented as part
   of Boot Manager's responsibility:

  3 - Boot Manager
  3.5.1 Boot via the Simple File Protocol
  When booting via the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, the FilePath will
  start with a device path that points to the device that implements the
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL or the EFI_BLOCK_IO_PROTOCOL. The next
  part of the FilePath may point to the file name, including
  subdirectories, which contain the bootable image. If the file name is
  a null device path, the file name must be generated from the rules
  defined below.
  ...
  3.5.1.1 Removable Media Boot Behavior
  To generate a file name when none is present in the FilePath, the
  firmware must append a default file name in the form
  \EFI\BOOT\BOOT{machine type short-name}.EFI ...

2) So (1) entails the hehavior that the user's preference of boot media
   order should be determined by Boot#### and BootOrder variables.

With this patch, the semantics mentioned above is fully implemented.
For example, if you want to boot the system from USB and SCSI in this
order,
* define Boot0001 which contains only a device path to the USB device
  (without any file path/name)
* define Boot0002 which contains only a device path to the SCSI device,
and
* set BootOrder to Boot0001:Boot0002

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 lib/efi_loader/efi_bootmgr.c | 65 +++++++++++++++++++++++++++++++++++-
 1 file changed, 64 insertions(+), 1 deletion(-)

Comments

Heinrich Schuchardt Nov. 9, 2021, 9:14 a.m. UTC | #1
On 11/9/21 02:32, AKASHI Takahiro wrote:
> Under the current implementation, booting from removal media using
> a architecture-specific default image name, say BOOTAA64.EFI, is
> supported only in distro_bootcmd script. See the commit 74522c898b35
> ("efi_loader: Add distro boot script for removable media").
> 
> This is, however, half-baked implementation because
> 1) UEFI specification requires this feature to be implemented as part
>     of Boot Manager's responsibility:
> 
>    3 - Boot Manager
>    3.5.1 Boot via the Simple File Protocol
>    When booting via the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, the FilePath will
>    start with a device path that points to the device that implements the
>    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL or the EFI_BLOCK_IO_PROTOCOL. The next
>    part of the FilePath may point to the file name, including
>    subdirectories, which contain the bootable image. If the file name is
>    a null device path, the file name must be generated from the rules
>    defined below.
>    ...
>    3.5.1.1 Removable Media Boot Behavior
>    To generate a file name when none is present in the FilePath, the
>    firmware must append a default file name in the form
>    \EFI\BOOT\BOOT{machine type short-name}.EFI ...
> 
> 2) So (1) entails the hehavior that the user's preference of boot media
>     order should be determined by Boot#### and BootOrder variables.
> 
> With this patch, the semantics mentioned above is fully implemented.
> For example, if you want to boot the system from USB and SCSI in this
> order,
> * define Boot0001 which contains only a device path to the USB device
>    (without any file path/name)
> * define Boot0002 which contains only a device path to the SCSI device,
> and
> * set BootOrder to Boot0001:Boot0002
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>   lib/efi_loader/efi_bootmgr.c | 65 +++++++++++++++++++++++++++++++++++-
>   1 file changed, 64 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
> index 1fe19237f9a6..1d9d5858561f 100644
> --- a/lib/efi_loader/efi_bootmgr.c
> +++ b/lib/efi_loader/efi_bootmgr.c
> @@ -30,6 +30,66 @@ static const struct efi_runtime_services *rs;
>    * should do normal or recovery boot.
>    */
>   
> +#if defined(CONFIG_ARM64)
> +#define BOOTEFI_NAME "bootaa64.efi"
> +#elif defined(CONFIG_ARM)
> +#define BOOTEFI_NAME "bootarm.efi"
> +#elif defined(CONFIG_X86_RUN_32BIT)

CONFIG_X86. Check it after CONFIG_X86_64.

> +#define BOOTEFI_NAME "bootia32.efi"
> +#elif defined(CONFIG_X86_RUN_64BIT)

%s/X86_RUN_64BIT/X86_64/

Check this before CONFIG_X86

> +#define BOOTEFI_NAME "bootx64.efi"
> +#elif defined(CONFIG_ARCH_RV32I)
> +#define BOOTEFI_NAME "bootriscv32.efi"
> +#elif defined(CONFIG_ARCH_RV64I)
> +#define BOOTEFI_NAME "bootriscv64.efi"
> +#else
> +#define BOOTEFI_NAME "dummy.efi"

This should result in a build error.

#error Unsupported UEFI architecture

> +#endif

I think this belongs into an include file.
According to the UEFI specification the file names are capitalized.

> +
> +/**
> + * expand_media_path() - expand a device path for default file name
> + * @device_path:	device path to check against
> + *
> + * If @device_path is a media or disk partition which houses a file
> + * system, this function returns a full device path which contains
> + * an architecture-specific default file name for removable media.
> + *
> + * Return:	a newly allocated device path
> + */
> +static
> +struct efi_device_path *expand_media_path(struct efi_device_path *device_path)
> +{
> +	struct efi_device_path *dp, *full_path;
> +	efi_handle_t handle;
> +	efi_status_t ret;
> +
> +	if (!device_path)
> +		return NULL;
> +
> +	/*
> +	 * If device_path is a (removable) media or partition which provides
> +	 * simple file system protocol, append a default file name to support
> +	 * booting from removable media.
> +	 */
> +	dp = device_path;
> +	ret = efi_locate_device_path(&efi_simple_file_system_protocol_guid,
> +				     &dp, &handle);
> +	if (ret == EFI_SUCCESS) {
> +		if (dp->type == DEVICE_PATH_TYPE_END) {
> +			dp = efi_dp_from_file(NULL, 0,
> +					      "/efi/boot/" BOOTEFI_NAME);

capitalized:
/EFI/BOOT/

Best regards

Heinrich

> +			full_path = efi_dp_append(device_path, dp);
> +		} else {
> +			full_path = efi_dp_dup(device_path);
> +		}
> +		efi_free_pool(dp);
> +	} else {
> +		full_path = efi_dp_dup(device_path);
> +	}
> +
> +	return full_path;
> +}
> +
>   /**
>    * try_load_entry() - try to load image for boot option
>    *
> @@ -68,13 +128,16 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
>   	}
>   
>   	if (lo.attributes & LOAD_OPTION_ACTIVE) {
> +		struct efi_device_path *file_path;
>   		u32 attributes;
>   
>   		log_debug("%s: trying to load \"%ls\" from %pD\n",
>   			  __func__, lo.label, lo.file_path);
>   
> -		ret = EFI_CALL(efi_load_image(true, efi_root, lo.file_path,
> +		file_path = expand_media_path(lo.file_path);
> +		ret = EFI_CALL(efi_load_image(true, efi_root, file_path,
>   					      NULL, 0, handle));
> +		efi_free_pool(file_path);
>   		if (ret != EFI_SUCCESS) {
>   			log_warning("Loading %ls '%ls' failed\n",
>   				    varname, lo.label);
>
Mark Kettenis Nov. 9, 2021, 1:53 p.m. UTC | #2
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Date: Tue,  9 Nov 2021 10:32:32 +0900

Hi Takahiro,

> Under the current implementation, booting from removal media using
> a architecture-specific default image name, say BOOTAA64.EFI, is
> supported only in distro_bootcmd script. See the commit 74522c898b35
> ("efi_loader: Add distro boot script for removable media").
> 
> This is, however, half-baked implementation because
> 1) UEFI specification requires this feature to be implemented as part
>    of Boot Manager's responsibility:
> 
>   3 - Boot Manager
>   3.5.1 Boot via the Simple File Protocol
>   When booting via the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, the FilePath will
>   start with a device path that points to the device that implements the
>   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL or the EFI_BLOCK_IO_PROTOCOL. The next
>   part of the FilePath may point to the file name, including
>   subdirectories, which contain the bootable image. If the file name is
>   a null device path, the file name must be generated from the rules
>   defined below.
>   ...
>   3.5.1.1 Removable Media Boot Behavior
>   To generate a file name when none is present in the FilePath, the
>   firmware must append a default file name in the form
>   \EFI\BOOT\BOOT{machine type short-name}.EFI ...
> 
> 2) So (1) entails the hehavior that the user's preference of boot media
>    order should be determined by Boot#### and BootOrder variables.
> 
> With this patch, the semantics mentioned above is fully implemented.
> For example, if you want to boot the system from USB and SCSI in this
> order,
> * define Boot0001 which contains only a device path to the USB device
>   (without any file path/name)
> * define Boot0002 which contains only a device path to the SCSI device,
> and
> * set BootOrder to Boot0001:Boot0002

The problem with this approach is that EFI device paths are
complicated things and I don't think we can expect users to do what
you describe above all by hand.  All x86 machines I've seen have a
more user-friendly way to configure the desired boot order, and also a
way to specify which device to boot from after automatic boot has been
interrupted.

With the current distroboot scripts one can simply do:

  setenv boot_targets usb0 mmc0 pxe dhcp

and I think we need to have something simple like that.  Maybe the
code can automatically create Boot#### and BootOrder variables based
on the boot_targets environment variables if they're not defined?

Another idea is to accept U-Boot device names (e.g. usb0, mmc0) as
aliases for EFI device paths and automatically expand them?

> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  lib/efi_loader/efi_bootmgr.c | 65 +++++++++++++++++++++++++++++++++++-
>  1 file changed, 64 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
> index 1fe19237f9a6..1d9d5858561f 100644
> --- a/lib/efi_loader/efi_bootmgr.c
> +++ b/lib/efi_loader/efi_bootmgr.c
> @@ -30,6 +30,66 @@ static const struct efi_runtime_services *rs;
>   * should do normal or recovery boot.
>   */
>  
> +#if defined(CONFIG_ARM64)
> +#define BOOTEFI_NAME "bootaa64.efi"
> +#elif defined(CONFIG_ARM)
> +#define BOOTEFI_NAME "bootarm.efi"
> +#elif defined(CONFIG_X86_RUN_32BIT)
> +#define BOOTEFI_NAME "bootia32.efi"
> +#elif defined(CONFIG_X86_RUN_64BIT)
> +#define BOOTEFI_NAME "bootx64.efi"
> +#elif defined(CONFIG_ARCH_RV32I)
> +#define BOOTEFI_NAME "bootriscv32.efi"
> +#elif defined(CONFIG_ARCH_RV64I)
> +#define BOOTEFI_NAME "bootriscv64.efi"
> +#else
> +#define BOOTEFI_NAME "dummy.efi"
> +#endif
> +
> +/**
> + * expand_media_path() - expand a device path for default file name
> + * @device_path:	device path to check against
> + *
> + * If @device_path is a media or disk partition which houses a file
> + * system, this function returns a full device path which contains
> + * an architecture-specific default file name for removable media.
> + *
> + * Return:	a newly allocated device path
> + */
> +static
> +struct efi_device_path *expand_media_path(struct efi_device_path *device_path)
> +{
> +	struct efi_device_path *dp, *full_path;
> +	efi_handle_t handle;
> +	efi_status_t ret;
> +
> +	if (!device_path)
> +		return NULL;
> +
> +	/*
> +	 * If device_path is a (removable) media or partition which provides
> +	 * simple file system protocol, append a default file name to support
> +	 * booting from removable media.
> +	 */
> +	dp = device_path;
> +	ret = efi_locate_device_path(&efi_simple_file_system_protocol_guid,
> +				     &dp, &handle);
> +	if (ret == EFI_SUCCESS) {
> +		if (dp->type == DEVICE_PATH_TYPE_END) {
> +			dp = efi_dp_from_file(NULL, 0,
> +					      "/efi/boot/" BOOTEFI_NAME);
> +			full_path = efi_dp_append(device_path, dp);
> +		} else {
> +			full_path = efi_dp_dup(device_path);
> +		}
> +		efi_free_pool(dp);
> +	} else {
> +		full_path = efi_dp_dup(device_path);
> +	}
> +
> +	return full_path;
> +}
> +
>  /**
>   * try_load_entry() - try to load image for boot option
>   *
> @@ -68,13 +128,16 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
>  	}
>  
>  	if (lo.attributes & LOAD_OPTION_ACTIVE) {
> +		struct efi_device_path *file_path;
>  		u32 attributes;
>  
>  		log_debug("%s: trying to load \"%ls\" from %pD\n",
>  			  __func__, lo.label, lo.file_path);
>  
> -		ret = EFI_CALL(efi_load_image(true, efi_root, lo.file_path,
> +		file_path = expand_media_path(lo.file_path);
> +		ret = EFI_CALL(efi_load_image(true, efi_root, file_path,
>  					      NULL, 0, handle));
> +		efi_free_pool(file_path);
>  		if (ret != EFI_SUCCESS) {
>  			log_warning("Loading %ls '%ls' failed\n",
>  				    varname, lo.label);
> -- 
> 2.33.0
> 
>
AKASHI Takahiro Nov. 10, 2021, 5:38 a.m. UTC | #3
Hi Heinrich,

Overall, do you agree to add this feature?

On Tue, Nov 09, 2021 at 10:14:47AM +0100, Heinrich Schuchardt wrote:
> 
> 
> On 11/9/21 02:32, AKASHI Takahiro wrote:
> > Under the current implementation, booting from removal media using
> > a architecture-specific default image name, say BOOTAA64.EFI, is
> > supported only in distro_bootcmd script. See the commit 74522c898b35
> > ("efi_loader: Add distro boot script for removable media").
> > 
> > This is, however, half-baked implementation because
> > 1) UEFI specification requires this feature to be implemented as part
> >     of Boot Manager's responsibility:
> > 
> >    3 - Boot Manager
> >    3.5.1 Boot via the Simple File Protocol
> >    When booting via the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, the FilePath will
> >    start with a device path that points to the device that implements the
> >    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL or the EFI_BLOCK_IO_PROTOCOL. The next
> >    part of the FilePath may point to the file name, including
> >    subdirectories, which contain the bootable image. If the file name is
> >    a null device path, the file name must be generated from the rules
> >    defined below.
> >    ...
> >    3.5.1.1 Removable Media Boot Behavior
> >    To generate a file name when none is present in the FilePath, the
> >    firmware must append a default file name in the form
> >    \EFI\BOOT\BOOT{machine type short-name}.EFI ...
> > 
> > 2) So (1) entails the hehavior that the user's preference of boot media
> >     order should be determined by Boot#### and BootOrder variables.
> > 
> > With this patch, the semantics mentioned above is fully implemented.
> > For example, if you want to boot the system from USB and SCSI in this
> > order,
> > * define Boot0001 which contains only a device path to the USB device
> >    (without any file path/name)
> > * define Boot0002 which contains only a device path to the SCSI device,
> > and
> > * set BootOrder to Boot0001:Boot0002
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >   lib/efi_loader/efi_bootmgr.c | 65 +++++++++++++++++++++++++++++++++++-
> >   1 file changed, 64 insertions(+), 1 deletion(-)
> > 
> > diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
> > index 1fe19237f9a6..1d9d5858561f 100644
> > --- a/lib/efi_loader/efi_bootmgr.c
> > +++ b/lib/efi_loader/efi_bootmgr.c
> > @@ -30,6 +30,66 @@ static const struct efi_runtime_services *rs;
> >    * should do normal or recovery boot.
> >    */
> > +#if defined(CONFIG_ARM64)
> > +#define BOOTEFI_NAME "bootaa64.efi"
> > +#elif defined(CONFIG_ARM)
> > +#define BOOTEFI_NAME "bootarm.efi"
> > +#elif defined(CONFIG_X86_RUN_32BIT)
> 
> CONFIG_X86. Check it after CONFIG_X86_64.
> 
> > +#define BOOTEFI_NAME "bootia32.efi"
> > +#elif defined(CONFIG_X86_RUN_64BIT)
> 
> %s/X86_RUN_64BIT/X86_64/
> 
> Check this before CONFIG_X86

OK, so

  #elif defined(CONFIG_X86_64)
    ...
  #elif defined(CONFIG_X86)
    ...

> > +#define BOOTEFI_NAME "bootx64.efi"
> > +#elif defined(CONFIG_ARCH_RV32I)
> > +#define BOOTEFI_NAME "bootriscv32.efi"
> > +#elif defined(CONFIG_ARCH_RV64I)
> > +#define BOOTEFI_NAME "bootriscv64.efi"
> > +#else
> > +#define BOOTEFI_NAME "dummy.efi"
> 
> This should result in a build error.
> 
> #error Unsupported UEFI architecture

OK.

> > +#endif
> 
> I think this belongs into an include file.

OK, but the only drawback is that this will make efi_api.h, which
I would like to move those definitions to, target-dependent.

As we have discussed somewhere else[1], if we want to use those include files,
we should remove sich dependencies.

Can you also make your comment on this thread[1], please?

[1] https://lists.denx.de/pipermail/u-boot/2021-November/466465.html


> According to the UEFI specification the file names are capitalized.

OK.

> > +
> > +/**
> > + * expand_media_path() - expand a device path for default file name
> > + * @device_path:	device path to check against
> > + *
> > + * If @device_path is a media or disk partition which houses a file
> > + * system, this function returns a full device path which contains
> > + * an architecture-specific default file name for removable media.
> > + *
> > + * Return:	a newly allocated device path
> > + */
> > +static
> > +struct efi_device_path *expand_media_path(struct efi_device_path *device_path)
> > +{
> > +	struct efi_device_path *dp, *full_path;
> > +	efi_handle_t handle;
> > +	efi_status_t ret;
> > +
> > +	if (!device_path)
> > +		return NULL;
> > +
> > +	/*
> > +	 * If device_path is a (removable) media or partition which provides
> > +	 * simple file system protocol, append a default file name to support
> > +	 * booting from removable media.
> > +	 */
> > +	dp = device_path;
> > +	ret = efi_locate_device_path(&efi_simple_file_system_protocol_guid,
> > +				     &dp, &handle);
> > +	if (ret == EFI_SUCCESS) {
> > +		if (dp->type == DEVICE_PATH_TYPE_END) {
> > +			dp = efi_dp_from_file(NULL, 0,
> > +					      "/efi/boot/" BOOTEFI_NAME);
> 
> capitalized:
> /EFI/BOOT/

OK

-Takahiro Akashi

> Best regards
> 
> Heinrich
> 
> > +			full_path = efi_dp_append(device_path, dp);
> > +		} else {
> > +			full_path = efi_dp_dup(device_path);
> > +		}
> > +		efi_free_pool(dp);
> > +	} else {
> > +		full_path = efi_dp_dup(device_path);
> > +	}
> > +
> > +	return full_path;
> > +}
> > +
> >   /**
> >    * try_load_entry() - try to load image for boot option
> >    *
> > @@ -68,13 +128,16 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
> >   	}
> >   	if (lo.attributes & LOAD_OPTION_ACTIVE) {
> > +		struct efi_device_path *file_path;
> >   		u32 attributes;
> >   		log_debug("%s: trying to load \"%ls\" from %pD\n",
> >   			  __func__, lo.label, lo.file_path);
> > -		ret = EFI_CALL(efi_load_image(true, efi_root, lo.file_path,
> > +		file_path = expand_media_path(lo.file_path);
> > +		ret = EFI_CALL(efi_load_image(true, efi_root, file_path,
> >   					      NULL, 0, handle));
> > +		efi_free_pool(file_path);
> >   		if (ret != EFI_SUCCESS) {
> >   			log_warning("Loading %ls '%ls' failed\n",
> >   				    varname, lo.label);
> >
AKASHI Takahiro Nov. 10, 2021, 5:52 a.m. UTC | #4
Hi Mark,

Thank you for your comments.

On Tue, Nov 09, 2021 at 02:53:14PM +0100, Mark Kettenis wrote:
> > From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > Date: Tue,  9 Nov 2021 10:32:32 +0900
> 
> Hi Takahiro,
> 
> > Under the current implementation, booting from removal media using
> > a architecture-specific default image name, say BOOTAA64.EFI, is
> > supported only in distro_bootcmd script. See the commit 74522c898b35
> > ("efi_loader: Add distro boot script for removable media").
> > 
> > This is, however, half-baked implementation because
> > 1) UEFI specification requires this feature to be implemented as part
> >    of Boot Manager's responsibility:
> > 
> >   3 - Boot Manager
> >   3.5.1 Boot via the Simple File Protocol
> >   When booting via the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, the FilePath will
> >   start with a device path that points to the device that implements the
> >   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL or the EFI_BLOCK_IO_PROTOCOL. The next
> >   part of the FilePath may point to the file name, including
> >   subdirectories, which contain the bootable image. If the file name is
> >   a null device path, the file name must be generated from the rules
> >   defined below.
> >   ...
> >   3.5.1.1 Removable Media Boot Behavior
> >   To generate a file name when none is present in the FilePath, the
> >   firmware must append a default file name in the form
> >   \EFI\BOOT\BOOT{machine type short-name}.EFI ...
> > 
> > 2) So (1) entails the hehavior that the user's preference of boot media
> >    order should be determined by Boot#### and BootOrder variables.
> > 
> > With this patch, the semantics mentioned above is fully implemented.
> > For example, if you want to boot the system from USB and SCSI in this
> > order,
> > * define Boot0001 which contains only a device path to the USB device
> >   (without any file path/name)
> > * define Boot0002 which contains only a device path to the SCSI device,
> > and
> > * set BootOrder to Boot0001:Boot0002
> 
> The problem with this approach is that EFI device paths are
> complicated things and I don't think we can expect users to do what
> you describe above all by hand.  All x86 machines I've seen have a
> more user-friendly way to configure the desired boot order, and also a
> way to specify which device to boot from after automatic boot has been
> interrupted.

I know most x86 prodcuction systems have GUI's, but such interfaces
can be implemented on top of the current UEFI implementation.
One of candidates, if not the best, is EDK-II's UiApp which is
expected to provide more friendly CUI. We'd better move this way.
(I mean that we should implement UI applications rather than expand
U-Boot itself.)
UiApp, however, doesn't work for now on U-Boot due to some issue.

> With the current distroboot scripts one can simply do:
> 
>   setenv boot_targets usb0 mmc0 pxe dhcp
> 
> and I think we need to have something simple like that.  Maybe the
> code can automatically create Boot#### and BootOrder variables based
> on the boot_targets environment variables if they're not defined?
> 
> Another idea is to accept U-Boot device names (e.g. usb0, mmc0) as
> aliases for EFI device paths and automatically expand them?

Yeah, those ideas are worth considering, but there are some problems
in generating internal device paths for them.
Let's continue to discuss this topic in patch#3 thread.

Thanks,
-Takahiro Akashi


> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  lib/efi_loader/efi_bootmgr.c | 65 +++++++++++++++++++++++++++++++++++-
> >  1 file changed, 64 insertions(+), 1 deletion(-)
> > 
> > diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
> > index 1fe19237f9a6..1d9d5858561f 100644
> > --- a/lib/efi_loader/efi_bootmgr.c
> > +++ b/lib/efi_loader/efi_bootmgr.c
> > @@ -30,6 +30,66 @@ static const struct efi_runtime_services *rs;
> >   * should do normal or recovery boot.
> >   */
> >  
> > +#if defined(CONFIG_ARM64)
> > +#define BOOTEFI_NAME "bootaa64.efi"
> > +#elif defined(CONFIG_ARM)
> > +#define BOOTEFI_NAME "bootarm.efi"
> > +#elif defined(CONFIG_X86_RUN_32BIT)
> > +#define BOOTEFI_NAME "bootia32.efi"
> > +#elif defined(CONFIG_X86_RUN_64BIT)
> > +#define BOOTEFI_NAME "bootx64.efi"
> > +#elif defined(CONFIG_ARCH_RV32I)
> > +#define BOOTEFI_NAME "bootriscv32.efi"
> > +#elif defined(CONFIG_ARCH_RV64I)
> > +#define BOOTEFI_NAME "bootriscv64.efi"
> > +#else
> > +#define BOOTEFI_NAME "dummy.efi"
> > +#endif
> > +
> > +/**
> > + * expand_media_path() - expand a device path for default file name
> > + * @device_path:	device path to check against
> > + *
> > + * If @device_path is a media or disk partition which houses a file
> > + * system, this function returns a full device path which contains
> > + * an architecture-specific default file name for removable media.
> > + *
> > + * Return:	a newly allocated device path
> > + */
> > +static
> > +struct efi_device_path *expand_media_path(struct efi_device_path *device_path)
> > +{
> > +	struct efi_device_path *dp, *full_path;
> > +	efi_handle_t handle;
> > +	efi_status_t ret;
> > +
> > +	if (!device_path)
> > +		return NULL;
> > +
> > +	/*
> > +	 * If device_path is a (removable) media or partition which provides
> > +	 * simple file system protocol, append a default file name to support
> > +	 * booting from removable media.
> > +	 */
> > +	dp = device_path;
> > +	ret = efi_locate_device_path(&efi_simple_file_system_protocol_guid,
> > +				     &dp, &handle);
> > +	if (ret == EFI_SUCCESS) {
> > +		if (dp->type == DEVICE_PATH_TYPE_END) {
> > +			dp = efi_dp_from_file(NULL, 0,
> > +					      "/efi/boot/" BOOTEFI_NAME);
> > +			full_path = efi_dp_append(device_path, dp);
> > +		} else {
> > +			full_path = efi_dp_dup(device_path);
> > +		}
> > +		efi_free_pool(dp);
> > +	} else {
> > +		full_path = efi_dp_dup(device_path);
> > +	}
> > +
> > +	return full_path;
> > +}
> > +
> >  /**
> >   * try_load_entry() - try to load image for boot option
> >   *
> > @@ -68,13 +128,16 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
> >  	}
> >  
> >  	if (lo.attributes & LOAD_OPTION_ACTIVE) {
> > +		struct efi_device_path *file_path;
> >  		u32 attributes;
> >  
> >  		log_debug("%s: trying to load \"%ls\" from %pD\n",
> >  			  __func__, lo.label, lo.file_path);
> >  
> > -		ret = EFI_CALL(efi_load_image(true, efi_root, lo.file_path,
> > +		file_path = expand_media_path(lo.file_path);
> > +		ret = EFI_CALL(efi_load_image(true, efi_root, file_path,
> >  					      NULL, 0, handle));
> > +		efi_free_pool(file_path);
> >  		if (ret != EFI_SUCCESS) {
> >  			log_warning("Loading %ls '%ls' failed\n",
> >  				    varname, lo.label);
> > -- 
> > 2.33.0
> > 
> >
diff mbox series

Patch

diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index 1fe19237f9a6..1d9d5858561f 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -30,6 +30,66 @@  static const struct efi_runtime_services *rs;
  * should do normal or recovery boot.
  */
 
+#if defined(CONFIG_ARM64)
+#define BOOTEFI_NAME "bootaa64.efi"
+#elif defined(CONFIG_ARM)
+#define BOOTEFI_NAME "bootarm.efi"
+#elif defined(CONFIG_X86_RUN_32BIT)
+#define BOOTEFI_NAME "bootia32.efi"
+#elif defined(CONFIG_X86_RUN_64BIT)
+#define BOOTEFI_NAME "bootx64.efi"
+#elif defined(CONFIG_ARCH_RV32I)
+#define BOOTEFI_NAME "bootriscv32.efi"
+#elif defined(CONFIG_ARCH_RV64I)
+#define BOOTEFI_NAME "bootriscv64.efi"
+#else
+#define BOOTEFI_NAME "dummy.efi"
+#endif
+
+/**
+ * expand_media_path() - expand a device path for default file name
+ * @device_path:	device path to check against
+ *
+ * If @device_path is a media or disk partition which houses a file
+ * system, this function returns a full device path which contains
+ * an architecture-specific default file name for removable media.
+ *
+ * Return:	a newly allocated device path
+ */
+static
+struct efi_device_path *expand_media_path(struct efi_device_path *device_path)
+{
+	struct efi_device_path *dp, *full_path;
+	efi_handle_t handle;
+	efi_status_t ret;
+
+	if (!device_path)
+		return NULL;
+
+	/*
+	 * If device_path is a (removable) media or partition which provides
+	 * simple file system protocol, append a default file name to support
+	 * booting from removable media.
+	 */
+	dp = device_path;
+	ret = efi_locate_device_path(&efi_simple_file_system_protocol_guid,
+				     &dp, &handle);
+	if (ret == EFI_SUCCESS) {
+		if (dp->type == DEVICE_PATH_TYPE_END) {
+			dp = efi_dp_from_file(NULL, 0,
+					      "/efi/boot/" BOOTEFI_NAME);
+			full_path = efi_dp_append(device_path, dp);
+		} else {
+			full_path = efi_dp_dup(device_path);
+		}
+		efi_free_pool(dp);
+	} else {
+		full_path = efi_dp_dup(device_path);
+	}
+
+	return full_path;
+}
+
 /**
  * try_load_entry() - try to load image for boot option
  *
@@ -68,13 +128,16 @@  static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
 	}
 
 	if (lo.attributes & LOAD_OPTION_ACTIVE) {
+		struct efi_device_path *file_path;
 		u32 attributes;
 
 		log_debug("%s: trying to load \"%ls\" from %pD\n",
 			  __func__, lo.label, lo.file_path);
 
-		ret = EFI_CALL(efi_load_image(true, efi_root, lo.file_path,
+		file_path = expand_media_path(lo.file_path);
+		ret = EFI_CALL(efi_load_image(true, efi_root, file_path,
 					      NULL, 0, handle));
+		efi_free_pool(file_path);
 		if (ret != EFI_SUCCESS) {
 			log_warning("Loading %ls '%ls' failed\n",
 				    varname, lo.label);