From bf03333d09669371ed2ee90a8ccddccc7d8aaa24 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 24 May 2024 14:54:26 +0200 Subject: efi_loader: allow concatenation with contained end node Allow appending a device-path to a device-path that contains an end node as separator. We need this feature for creating boot options specifying kernel, initrd, and dtb. Signed-off-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- lib/efi_loader/efi_bootmgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/efi_loader/efi_bootmgr.c') diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 7da3139f917..b0bf21cf841 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -130,7 +130,7 @@ static efi_status_t try_load_from_file_path(efi_handle_t *fs_handles, if (!dp) continue; - dp = efi_dp_concat(dp, fp, false); + dp = efi_dp_concat(dp, fp, 0); if (!dp) continue; -- cgit v1.2.3 From 39bac24a48bb7d1c45497a25626fd0d604938516 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 26 Apr 2024 16:13:17 +0200 Subject: efi_loader: load device-tree specified in boot option We allow to specify the triple of binary, initrd, and device-tree in boot options. Add the code to actually load the specified device-tree. Signed-off-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- lib/efi_loader/efi_bootmgr.c | 70 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'lib/efi_loader/efi_bootmgr.c') diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index b0bf21cf841..2c140bb70cd 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -1185,6 +1185,59 @@ out: return ret; } +/** + * load_fdt_from_load_option - load device-tree from load option + * + * @fdt: pointer to loaded device-tree or NULL + * Return: status code + */ +static efi_status_t load_fdt_from_load_option(void **fdt) +{ + struct efi_device_path *dp = NULL; + struct efi_file_handle *f = NULL; + efi_uintn_t filesize; + efi_status_t ret; + + *fdt = NULL; + + dp = efi_get_dp_from_boot(&efi_guid_fdt); + if (!dp) + return EFI_SUCCESS; + + /* Open file */ + f = efi_file_from_path(dp); + if (!f) { + log_err("Can't find %pD specified in Boot####\n", dp); + ret = EFI_NOT_FOUND; + goto out; + } + + /* Get file size */ + ret = efi_file_size(f, &filesize); + if (ret != EFI_SUCCESS) + goto out; + + *fdt = calloc(1, filesize); + if (!*fdt) { + log_err("Out of memory\n"); + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + ret = EFI_CALL(f->read(f, &filesize, *fdt)); + if (ret != EFI_SUCCESS) { + log_err("Can't read fdt\n"); + free(*fdt); + *fdt = NULL; + } + +out: + efi_free_pool(dp); + if (f) + EFI_CALL(f->close(f)); + + return ret; +} + /** * efi_bootmgr_run() - execute EFI boot manager * @fdt: Flat device tree @@ -1200,6 +1253,7 @@ efi_status_t efi_bootmgr_run(void *fdt) efi_handle_t handle; void *load_options; efi_status_t ret; + void *fdt_lo; /* Initialize EFI drivers */ ret = efi_init_obj_list(); @@ -1215,7 +1269,23 @@ efi_status_t efi_bootmgr_run(void *fdt) return ret; } + if (!IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { + ret = load_fdt_from_load_option(&fdt_lo); + if (ret != EFI_SUCCESS) + return ret; + if (fdt_lo) + fdt = fdt_lo; + } + + /* + * Needed in ACPI case to create reservations based on + * control device-tree. + */ ret = efi_install_fdt(fdt); + + if (!IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) + free(fdt_lo); + if (ret != EFI_SUCCESS) { if (EFI_CALL(efi_unload_image(handle)) == EFI_SUCCESS) free(load_options); -- cgit v1.2.3 From e91b68fd6b83d6e4c862000630d240b339cc5a7b Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 26 Apr 2024 16:13:21 +0200 Subject: efi_loader: load distro dtb in bootmgr If no device-tree is specified, try to load a device-tree from the boot device use the $fdtfile concatenated to either of the paths '/dtb/', '/', '/dtb/current/'. Signed-off-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- lib/efi_loader/efi_bootmgr.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'lib/efi_loader/efi_bootmgr.c') diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 2c140bb70cd..304ed43595c 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -1253,7 +1253,8 @@ efi_status_t efi_bootmgr_run(void *fdt) efi_handle_t handle; void *load_options; efi_status_t ret; - void *fdt_lo; + void *fdt_lo, *fdt_distro = NULL; + efi_uintn_t fdt_size; /* Initialize EFI drivers */ ret = efi_init_obj_list(); @@ -1275,6 +1276,10 @@ efi_status_t efi_bootmgr_run(void *fdt) return ret; if (fdt_lo) fdt = fdt_lo; + if (!fdt) { + efi_load_distro_fdt(&fdt_distro, &fdt_size); + fdt = fdt_distro; + } } /* @@ -1283,8 +1288,12 @@ efi_status_t efi_bootmgr_run(void *fdt) */ ret = efi_install_fdt(fdt); - if (!IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) + if (!IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { free(fdt_lo); + if (fdt_distro) + efi_free_pages((uintptr_t)fdt_distro, + efi_size_in_pages(fdt_size)); + } if (ret != EFI_SUCCESS) { if (EFI_CALL(efi_unload_image(handle)) == EFI_SUCCESS) -- cgit v1.2.3