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>
This commit is contained in:
parent
fc225e6082
commit
bc4f9133ed
111
cmd/bootefi.c
111
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"
|
||||
|
@ -96,6 +96,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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user