diff options
author | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2018-03-03 15:29:03 +0100 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2018-04-04 11:00:06 +0200 |
commit | bc4f9133edb4baf5f68689a03137bb2c336e2026 (patch) | |
tree | 53c7af9775ee69c14fc2cf69ecc37a545af23464 /cmd | |
parent | fc225e60822e3fd18a56b546eb683d6818d3f9c4 (diff) |
efi_loader: support device tree for bootefi selftest
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@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/bootefi.c | 111 |
1 files changed, 64 insertions, 47 deletions
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 025a3dd1718..6afece10bc1 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" |