[PATCH 092/112] efi: payload: dynamically determine bootloader file name
Ahmad Fatoum
a.fatoum at pengutronix.de
Wed Jan 3 10:12:52 PST 2024
\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 at pengutronix.de>
---
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 6c790c680602..354120b11a86 100644
--- a/efi/payload/init.c
+++ b/efi/payload/init.c
@@ -299,7 +299,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;
@@ -321,8 +324,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",
@@ -334,8 +339,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
More information about the barebox
mailing list