aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2018-03-03 15:29:03 +0100
committerAlexander Graf <agraf@suse.de>2018-04-04 11:00:06 +0200
commitbc4f9133edb4baf5f68689a03137bb2c336e2026 (patch)
tree53c7af9775ee69c14fc2cf69ecc37a545af23464 /cmd
parentfc225e60822e3fd18a56b546eb683d6818d3f9c4 (diff)
downloadu-boot-bc4f9133edb4baf5f68689a03137bb2c336e2026.zip
u-boot-bc4f9133edb4baf5f68689a03137bb2c336e2026.tar.gz
u-boot-bc4f9133edb4baf5f68689a03137bb2c336e2026.tar.bz2
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.c111
1 files changed, 64 insertions, 47 deletions
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 025a3dd..6afece1 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"