\EFI\BOOT\BOOTx64.EFI is only the default file path for x86_64. It's different for other architectures and even for x86_64, the EFI loader may be configured to execute a differently named file. Fix this by querying the EFI loader for the file name instead of hardcoding it and while at it, we add debug prints for the loaded image and its parent to make it easier to debug in future. On the off chance, that the EFI firmware doesn't inform us of a file name this way, we revert back to a hardcoded value, that is architecture-dependent. Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> --- efi/Kconfig | 10 ++++++++++ efi/devicepath.c | 39 +++++++++++++++++++++++++++++++++------ efi/payload/init.c | 23 ++++++++++++++++++----- include/efi.h | 1 + 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/efi/Kconfig b/efi/Kconfig index 35a57a3a42de..3bda02600c94 100644 --- a/efi/Kconfig +++ b/efi/Kconfig @@ -35,4 +35,14 @@ config EFI_GUID config EFI_DEVICEPATH bool +config EFI_PAYLOAD_DEFAULT_PATH + string + default "EFI/BOOT/BOOTARM.EFI" if CPU_32 + default "EFI/BOOT/BOOTAA64.EFI" if CPU_64 + default "EFI/BOOT/BOOTIA32.EFI" if X86_32 + default "EFI/BOOT/BOOTx64.EFI" if X86_64 + default "EFI/BOOT/BOOTRISCV32.EFI" if ARCH_RV32I + default "EFI/BOOT/BOOTRISCV64.EFI" if ARCH_RV64I + default "EFI/BOOT/BAREBOX.EFI" + endmenu diff --git a/efi/devicepath.c b/efi/devicepath.c index 0c2fc4d86927..98aba6289e18 100644 --- a/efi/devicepath.c +++ b/efi/devicepath.c @@ -83,15 +83,23 @@ const struct efi_device_path end_instance_device_path = { const struct efi_device_path * device_path_from_handle(efi_handle_t Handle) { + const efi_guid_t *const protocols[] = { + &efi_loaded_image_device_path_guid, + &efi_device_path_protocol_guid, + NULL + }; + const efi_guid_t * const*proto; efi_status_t Status; - const struct efi_device_path *device_path; - Status = BS->handle_protocol(Handle, &efi_device_path_protocol_guid, - (void *) &device_path); - if (EFI_ERROR(Status)) - device_path = NULL; + for (proto = protocols; *proto; proto++) { + const struct efi_device_path *device_path; - return device_path; + Status = BS->handle_protocol(Handle, *proto, (void *) &device_path); + if (!EFI_ERROR(Status) && device_path) + return device_path; + } + + return NULL; } static struct efi_device_path * @@ -871,3 +879,22 @@ char *device_path_to_partuuid(const struct efi_device_path *dev_path) return NULL; } +char *device_path_to_filepath(const struct efi_device_path *dev_path) +{ + struct filepath_device_path *fp = NULL; + char *path; + + dev_path = unpack_device_path(dev_path); + + while ((dev_path = device_path_next_compatible_node(dev_path, + MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP))) { + fp = container_of(dev_path, struct filepath_device_path, header); + dev_path = next_device_path_node(&fp->header); + } + + path = strdup_wchar_to_char(fp->path_name); + if (!path) + return NULL; + + return strreplace(path, '\\', '/'); +} diff --git a/efi/payload/init.c b/efi/payload/init.c index d5ec86fafe1a..0f518d4954cb 100644 --- a/efi/payload/init.c +++ b/efi/payload/init.c @@ -300,7 +300,10 @@ core_efi_initcall(efi_core_init); static int efi_postcore_init(void) { - char *uuid; + const struct efi_device_path *parent_image_dp, *loaded_image_dp; + char *bbu_path = "/boot/" CONFIG_EFI_PAYLOAD_DEFAULT_PATH; + + char *filepath, *uuid; static const uint64_t loader_features = EFI_LOADER_FEATURE_DEVICETREE; @@ -322,8 +325,10 @@ static int efi_postcore_init(void) efi_set_variable_uint64_le("LoaderFeatures", &efi_systemd_vendor_guid, loader_features); - uuid = device_path_to_partuuid(device_path_from_handle( - efi_loaded_image->device_handle)); + loaded_image_dp = device_path_from_handle(efi_loaded_image->device_handle); + pr_debug("loaded-image: %pD\n", loaded_image_dp); + + uuid = device_path_to_partuuid(loaded_image_dp); if (uuid) { wchar_t *uuid16 = xstrdup_char_to_wchar(uuid); efi_set_variable("LoaderDevicePartUUID", @@ -335,8 +340,16 @@ static int efi_postcore_init(void) free(uuid16); } - bbu_register_std_file_update("fat", 0, "/boot/EFI/BOOT/BOOTx64.EFI", - filetype_exe); + parent_image_dp = device_path_from_handle(efi_parent_image); + pr_debug("parent-image: %pD\n", parent_image_dp); + + filepath = device_path_to_filepath(parent_image_dp); + if (filepath) { + bbu_path = basprintf("/boot/%s", filepath); + free(filepath); + } + + bbu_register_std_file_update("fat", 0, bbu_path, filetype_exe); return 0; } diff --git a/include/efi.h b/include/efi.h index 45e4080fac08..6bb5f8cb0a30 100644 --- a/include/efi.h +++ b/include/efi.h @@ -884,6 +884,7 @@ size_t device_path_to_str_buf(const struct efi_device_path *dev_path, char buf[] u8 device_path_to_type(const struct efi_device_path *dev_path); u8 device_path_to_subtype(const struct efi_device_path *dev_path); char *device_path_to_partuuid(const struct efi_device_path *dev_path); +char *device_path_to_filepath(const struct efi_device_path *dev_path); const char *efi_guid_string(efi_guid_t *g); -- 2.39.2