[U-Boot] [PATCH v3 10/11] efi_loader: support device tree for bootefi selftest
Heinrich Schuchardt
xypron.glpk at gmx.de
Sat Mar 3 14:29:03 UTC 2018
The second argument of the bootefi command should always be usable to
specify a device tree. This was missing for bootefi selftest and
bootefi hello.
Proper error handling is added.
Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
v3
Mention fdt address as argument in online help of bootefi selftest
v2
new patch
---
cmd/bootefi.c | 111 ++++++++++++++++++++++++------------------
include/efi_loader.h | 2 +
lib/efi_loader/efi_boottime.c | 2 +
3 files changed, 68 insertions(+), 47 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 0eb9a1baab..6de7d8c743 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -178,11 +178,49 @@ static efi_status_t efi_run_in_el2(EFIAPI efi_status_t (*entry)(
}
#endif
+static efi_status_t efi_install_fdt(void *fdt)
+{
+ bootm_headers_t img = { 0 };
+ ulong fdt_pages, fdt_size, fdt_start, fdt_end;
+ efi_status_t ret;
+
+ if (fdt_check_header(fdt)) {
+ printf("ERROR: invalid device tree\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ /* Prepare fdt for payload */
+ fdt = copy_fdt(fdt);
+ if (!fdt)
+ return EFI_OUT_OF_RESOURCES;
+
+ if (image_setup_libfdt(&img, fdt, 0, NULL)) {
+ printf("ERROR: failed to process device tree\n");
+ return EFI_LOAD_ERROR;
+ }
+
+ /* Link to it in the efi tables */
+ ret = efi_install_configuration_table(&efi_guid_fdt, fdt);
+ if (ret != EFI_SUCCESS)
+ return EFI_OUT_OF_RESOURCES;
+
+ /* And reserve the space in the memory map */
+ fdt_start = ((ulong)fdt) & ~EFI_PAGE_MASK;
+ fdt_end = ((ulong)fdt) + fdt_totalsize(fdt);
+ fdt_size = (fdt_end - fdt_start) + EFI_PAGE_MASK;
+ fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
+ /* Give a bootloader the chance to modify the device tree */
+ fdt_pages += 2;
+ ret = efi_add_memory_map(fdt_start, fdt_pages,
+ EFI_BOOT_SERVICES_DATA, true);
+ return ret;
+}
+
/*
* Load an EFI payload into a newly allocated piece of memory, register all
* EFI objects it would want to access and jump to it.
*/
-static efi_status_t do_bootefi_exec(void *efi, void *fdt,
+static efi_status_t do_bootefi_exec(void *efi,
struct efi_device_path *device_path,
struct efi_device_path *image_path)
{
@@ -193,9 +231,6 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt,
EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
struct efi_system_table *st);
- ulong fdt_pages, fdt_size, fdt_start, fdt_end;
- const efi_guid_t fdt_guid = EFI_FDT_GUID;
- bootm_headers_t img = { 0 };
/*
* Special case for efi payload not loaded from disk, such as
@@ -220,32 +255,6 @@ static efi_status_t do_bootefi_exec(void *efi, void *fdt,
*/
efi_save_gd();
- if (fdt && !fdt_check_header(fdt)) {
- /* Prepare fdt for payload */
- fdt = copy_fdt(fdt);
-
- if (image_setup_libfdt(&img, fdt, 0, NULL)) {
- printf("ERROR: Failed to process device tree\n");
- return -EINVAL;
- }
-
- /* Link to it in the efi tables */
- efi_install_configuration_table(&fdt_guid, fdt);
-
- /* And reserve the space in the memory map */
- fdt_start = ((ulong)fdt) & ~EFI_PAGE_MASK;
- fdt_end = ((ulong)fdt) + fdt_totalsize(fdt);
- fdt_size = (fdt_end - fdt_start) + EFI_PAGE_MASK;
- fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
- /* Give a bootloader the chance to modify the device tree */
- fdt_pages += 2;
- efi_add_memory_map(fdt_start, fdt_pages,
- EFI_BOOT_SERVICES_DATA, true);
- } else {
- printf("WARNING: Invalid device tree, expect boot to fail\n");
- efi_install_configuration_table(&fdt_guid, NULL);
- }
-
/* Transfer environment variable bootargs as load options */
set_load_options(&loaded_image_info, "bootargs");
/* Load the EFI payload */
@@ -301,7 +310,7 @@ exit:
return ret;
}
-static int do_bootefi_bootmgr_exec(unsigned long fdt_addr)
+static int do_bootefi_bootmgr_exec(void)
{
struct efi_device_path *device_path, *file_path;
void *addr;
@@ -318,7 +327,7 @@ static int do_bootefi_bootmgr_exec(unsigned long fdt_addr)
return 1;
printf("## Starting EFI application at %p ...\n", addr);
- r = do_bootefi_exec(addr, (void *)fdt_addr, device_path, file_path);
+ r = do_bootefi_exec(addr, device_path, file_path);
printf("## Application terminated, r = %lu\n",
r & ~EFI_ERROR_MASK);
@@ -331,9 +340,10 @@ static int do_bootefi_bootmgr_exec(unsigned long fdt_addr)
/* Interpreter command to boot an arbitrary EFI image from memory */
static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- char *saddr, *sfdt;
- unsigned long addr, fdt_addr = 0;
+ unsigned long addr;
+ char *saddr;
efi_status_t r;
+ void *fdt_addr;
/* Initialize EFI drivers */
r = efi_init_obj_list();
@@ -345,6 +355,22 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (argc < 2)
return CMD_RET_USAGE;
+
+ if (argc > 2) {
+ fdt_addr = (void *)simple_strtoul(argv[2], NULL, 16);
+ if (!fdt_addr && *argv[2] != '0')
+ return CMD_RET_USAGE;
+ /* Install device tree */
+ r = efi_install_fdt(fdt_addr);
+ if (r != EFI_SUCCESS) {
+ printf("ERROR: failed to install device tree\n");
+ return CMD_RET_FAILURE;
+ }
+ } else {
+ /* Remove device tree. EFI_NOT_FOUND can be ignored here */
+ efi_install_configuration_table(&efi_guid_fdt, NULL);
+ printf("WARNING: booting without device tree\n");
+ }
#ifdef CONFIG_CMD_BOOTEFI_HELLO
if (!strcmp(argv[1], "hello")) {
ulong size = __efi_helloworld_end - __efi_helloworld_begin;
@@ -390,12 +416,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
} else
#endif
if (!strcmp(argv[1], "bootmgr")) {
- unsigned long fdt_addr = 0;
-
- if (argc > 2)
- fdt_addr = simple_strtoul(argv[2], NULL, 16);
-
- return do_bootefi_bootmgr_exec(fdt_addr);
+ return do_bootefi_bootmgr_exec();
} else {
saddr = argv[1];
@@ -404,15 +425,11 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (!addr && *saddr != '0')
return CMD_RET_USAGE;
- if (argc > 2) {
- sfdt = argv[2];
- fdt_addr = simple_strtoul(sfdt, NULL, 16);
- }
}
printf("## Starting EFI application at %08lx ...\n", addr);
- r = do_bootefi_exec((void *)addr, (void *)fdt_addr,
- bootefi_device_path, bootefi_image_path);
+ r = do_bootefi_exec((void *)addr, bootefi_device_path,
+ bootefi_image_path);
printf("## Application terminated, r = %lu\n",
r & ~EFI_ERROR_MASK);
@@ -433,7 +450,7 @@ static char bootefi_help_text[] =
" - boot a sample Hello World application stored within U-Boot\n"
#endif
#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
- "bootefi selftest\n"
+ "bootefi selftest [fdt address]\n"
" - boot an EFI selftest application stored within U-Boot\n"
" Use environment variable efi_selftest to select a single test.\n"
" Use 'setenv efi_selftest list' to enumerate all tests.\n"
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 85a47ca2f5..3ccbb98aaf 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -93,6 +93,8 @@ extern const efi_guid_t efi_guid_console_control;
extern const efi_guid_t efi_guid_device_path;
/* GUID of the EFI_DRIVER_BINDING_PROTOCOL */
extern const efi_guid_t efi_guid_driver_binding_protocol;
+/* GUID of the device tree table */
+extern const efi_guid_t efi_guid_fdt;
extern const efi_guid_t efi_guid_loaded_image;
extern const efi_guid_t efi_guid_device_path_to_text_protocol;
extern const efi_guid_t efi_simple_file_system_protocol_guid;
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index b80f59fd92..2f67030151 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -56,6 +56,8 @@ static volatile void *efi_gd, *app_gd;
static int entry_count;
static int nesting_level;
+/* GUID of the device tree table */
+const efi_guid_t efi_guid_fdt = EFI_FDT_GUID;
/* GUID of the EFI_DRIVER_BINDING_PROTOCOL */
const efi_guid_t efi_guid_driver_binding_protocol =
EFI_DRIVER_BINDING_PROTOCOL_GUID;
--
2.14.2
More information about the U-Boot
mailing list