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 <heinrich.schuchardt@canonical.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
This commit is contained in:
Heinrich Schuchardt
2024-06-10 11:43:36 +02:00
parent d9f7f42451
commit 39bac24a48
+70
View File
@@ -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);