From a2a4bc3b09fc956ae58572430a019781425baf9c Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 16 Apr 2019 13:24:20 +0900 Subject: efi_loader: export root node handle This is a preparatory patch. The root node handle will be used as a dummy parent handle when invoking an EFI image from bootefi/bootmgr command. Signed-off-by: AKASHI Takahiro Rebased. Signed-off-by: Heinrich Schuchardt --- include/efi_loader.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/efi_loader.h b/include/efi_loader.h index f7bf7328271..93f7672aecb 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -25,6 +25,9 @@ EFI_GUID(0xe61d73b9, 0xa384, 0x4acc, \ 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3, 0x62, 0x8b) +/* Root node */ +extern efi_handle_t efi_root; + int __efi_entry_check(void); int __efi_exit_check(void); const char *__efi_nesting(void); -- cgit v1.3.1 From dec88e41e022ac06c0054ca48807db0d95f917f6 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 20 Apr 2019 07:39:11 +0200 Subject: efi_loader: consistent naming of protocol GUIDs We should consistently use the same name for protocol GUIDs as defined in the UEFI specification. Not adhering to this rule has led to duplicate definitions for the EFI_LOADED_IMAGE_PROTOCOL_GUID. Adjust misnamed protocol GUIDs. Adjust the text for the graphics output protocol in the output of the `efidebug dh` command. Signed-off-by: Heinrich Schuchardt --- cmd/efidebug.c | 10 +++++----- include/efi_api.h | 18 +++++++----------- lib/efi/efi.c | 2 +- lib/efi/efi_stub.c | 2 +- lib/efi_loader/efi_disk.c | 2 +- lib/efi_loader/efi_gop.c | 2 +- lib/efi_loader/efi_image_loader.c | 8 ++++---- lib/efi_loader/efi_net.c | 4 ++-- lib/efi_loader/helloworld.c | 2 +- lib/efi_selftest/efi_selftest_bitblt.c | 2 +- lib/efi_selftest/efi_selftest_block_device.c | 4 ++-- lib/efi_selftest/efi_selftest_devicepath.c | 2 +- lib/efi_selftest/efi_selftest_gop.c | 2 +- lib/efi_selftest/efi_selftest_loadimage.c | 2 +- lib/efi_selftest/efi_selftest_miniapp_exit.c | 2 +- lib/efi_selftest/efi_selftest_snp.c | 2 +- 16 files changed, 31 insertions(+), 35 deletions(-) (limited to 'include') diff --git a/cmd/efidebug.c b/cmd/efidebug.c index db96682c5a4..4bf91ed2484 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -185,7 +185,7 @@ static const struct { } guid_list[] = { { "Device Path", - DEVICE_PATH_GUID, + EFI_DEVICE_PATH_PROTOCOL_GUID, }, { "Device Path To Text", @@ -217,7 +217,7 @@ static const struct { }, { "Block IO", - BLOCK_IO_GUID, + EFI_BLOCK_IO_PROTOCOL_GUID, }, { "Simple File System", @@ -225,11 +225,11 @@ static const struct { }, { "Loaded Image", - LOADED_IMAGE_PROTOCOL_GUID, + EFI_LOADED_IMAGE_PROTOCOL_GUID, }, { - "GOP", - EFI_GOP_GUID, + "Graphics Output", + EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, }, }; diff --git a/include/efi_api.h b/include/efi_api.h index 5b0a1006354..472160cb300 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -290,10 +290,6 @@ struct efi_runtime_services { EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, \ 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c) -#define LOADED_IMAGE_PROTOCOL_GUID \ - EFI_GUID(0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, \ - 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) - #define EFI_FDT_GUID \ EFI_GUID(0xb1b621d5, 0xf19c, 0x41a5, \ 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0) @@ -329,11 +325,11 @@ struct efi_system_table { struct efi_configuration_table *tables; }; -#define LOADED_IMAGE_GUID \ +#define EFI_LOADED_IMAGE_PROTOCOL_GUID \ EFI_GUID(0x5b1b31a1, 0x9562, 0x11d2, \ 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) -#define LOADED_IMAGE_DEVICE_PATH_GUID \ +#define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID \ EFI_GUID(0xbc62157e, 0x3e33, 0x4fec, \ 0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf) @@ -355,7 +351,7 @@ struct efi_loaded_image { unsigned long unload; }; -#define DEVICE_PATH_GUID \ +#define EFI_DEVICE_PATH_PROTOCOL_GUID \ EFI_GUID(0x09576e91, 0x6d3f, 0x11d2, \ 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) @@ -478,7 +474,7 @@ struct efi_device_path_file_path { u16 str[]; } __packed; -#define BLOCK_IO_GUID \ +#define EFI_BLOCK_IO_PROTOCOL_GUID \ EFI_GUID(0x964e5b21, 0x6459, 0x11d2, \ 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) @@ -1123,7 +1119,7 @@ struct efi_hii_config_access_protocol { efi_browser_action_request_t *action_request); }; -#define EFI_GOP_GUID \ +#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ EFI_GUID(0x9042a9de, 0x23dc, 0x4a38, \ 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a) @@ -1175,7 +1171,7 @@ struct efi_gop { struct efi_gop_mode *mode; }; -#define EFI_SIMPLE_NETWORK_GUID \ +#define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \ EFI_GUID(0xa19832b9, 0xac25, 0x11d3, \ 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) @@ -1268,7 +1264,7 @@ struct efi_simple_network { struct efi_simple_network_mode *mode; }; -#define EFI_PXE_GUID \ +#define EFI_PXE_BASE_CODE_PROTOCOL_GUID \ EFI_GUID(0x03c4e603, 0xac28, 0x11d3, \ 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) diff --git a/lib/efi/efi.c b/lib/efi/efi.c index 2c6a50824fd..7cba57b131f 100644 --- a/lib/efi/efi.c +++ b/lib/efi/efi.c @@ -53,7 +53,7 @@ void efi_puts(struct efi_priv *priv, const char *str) int efi_init(struct efi_priv *priv, const char *banner, efi_handle_t image, struct efi_system_table *sys_table) { - efi_guid_t loaded_image_guid = LOADED_IMAGE_PROTOCOL_GUID; + efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; struct efi_boot_services *boot = sys_table->boottime; struct efi_loaded_image *loaded_image; int ret; diff --git a/lib/efi/efi_stub.c b/lib/efi/efi_stub.c index 12e3d637dda..6dd93ff435a 100644 --- a/lib/efi/efi_stub.c +++ b/lib/efi/efi_stub.c @@ -278,7 +278,7 @@ efi_status_t EFIAPI efi_main(efi_handle_t image, struct efi_gop *gop; struct efi_entry_gopmode mode; struct efi_entry_systable table; - efi_guid_t efi_gop_guid = EFI_GOP_GUID; + efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; efi_uintn_t key, desc_size, size; efi_status_t ret; u32 version; diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index c037526ad2d..7a6b06821a4 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -12,7 +12,7 @@ #include #include -const efi_guid_t efi_block_io_guid = BLOCK_IO_GUID; +const efi_guid_t efi_block_io_guid = EFI_BLOCK_IO_PROTOCOL_GUID; /** * struct efi_disk_obj - EFI disk object diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index d62ce459127..e003823b606 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -14,7 +14,7 @@ DECLARE_GLOBAL_DATA_PTR; -static const efi_guid_t efi_gop_guid = EFI_GOP_GUID; +static const efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; /** * struct efi_gop_obj - graphical output protocol object diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 93feefd366c..f8092b62026 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -12,10 +12,10 @@ #include const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; -const efi_guid_t efi_guid_device_path = DEVICE_PATH_GUID; -const efi_guid_t efi_guid_loaded_image = LOADED_IMAGE_GUID; -const efi_guid_t efi_guid_loaded_image_device_path - = LOADED_IMAGE_DEVICE_PATH_GUID; +const efi_guid_t efi_guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; +const efi_guid_t efi_guid_loaded_image = EFI_LOADED_IMAGE_PROTOCOL_GUID; +const efi_guid_t efi_guid_loaded_image_device_path = + EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID; const efi_guid_t efi_simple_file_system_protocol_guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID; diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index c7d9da8521a..e0e222a70bf 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -9,8 +9,8 @@ #include #include -static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_GUID; -static const efi_guid_t efi_pxe_guid = EFI_PXE_GUID; +static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; +static const efi_guid_t efi_pxe_guid = EFI_PXE_BASE_CODE_PROTOCOL_GUID; static struct efi_pxe_packet *dhcp_ack; static bool new_rx_packet; static void *new_tx_packet; diff --git a/lib/efi_loader/helloworld.c b/lib/efi_loader/helloworld.c index 426f276361a..9ae2ee33898 100644 --- a/lib/efi_loader/helloworld.c +++ b/lib/efi_loader/helloworld.c @@ -12,7 +12,7 @@ #include #include -static const efi_guid_t loaded_image_guid = LOADED_IMAGE_GUID; +static const efi_guid_t loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; static const efi_guid_t fdt_guid = EFI_FDT_GUID; static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID; static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID; diff --git a/lib/efi_selftest/efi_selftest_bitblt.c b/lib/efi_selftest/efi_selftest_bitblt.c index 9033109807c..fb33150c4b2 100644 --- a/lib/efi_selftest/efi_selftest_bitblt.c +++ b/lib/efi_selftest/efi_selftest_bitblt.c @@ -23,7 +23,7 @@ static const struct efi_gop_pixel DARK_BLUE = {128, 0, 0, 0}; static const struct efi_gop_pixel LIGHT_BLUE = {255, 192, 192, 0}; static struct efi_boot_services *boottime; -static efi_guid_t efi_gop_guid = EFI_GOP_GUID; +static efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; static struct efi_gop *gop; static struct efi_gop_pixel *bitmap; static struct efi_event *event; diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c index 21409aed6f5..29ac0ce6510 100644 --- a/lib/efi_selftest/efi_selftest_block_device.c +++ b/lib/efi_selftest/efi_selftest_block_device.c @@ -24,8 +24,8 @@ static struct efi_boot_services *boottime; -static const efi_guid_t block_io_protocol_guid = BLOCK_IO_GUID; -static const efi_guid_t guid_device_path = DEVICE_PATH_GUID; +static const efi_guid_t block_io_protocol_guid = EFI_BLOCK_IO_PROTOCOL_GUID; +static const efi_guid_t guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; static const efi_guid_t guid_simple_file_system_protocol = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; static const efi_guid_t guid_file_system_info = EFI_FILE_SYSTEM_INFO_GUID; diff --git a/lib/efi_selftest/efi_selftest_devicepath.c b/lib/efi_selftest/efi_selftest_devicepath.c index 105ce2c92b3..4ce3fad8959 100644 --- a/lib/efi_selftest/efi_selftest_devicepath.c +++ b/lib/efi_selftest/efi_selftest_devicepath.c @@ -20,7 +20,7 @@ struct interface { void (EFIAPI * inc)(void); } interface; -static efi_guid_t guid_device_path = DEVICE_PATH_GUID; +static efi_guid_t guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; static efi_guid_t guid_device_path_to_text_protocol = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; diff --git a/lib/efi_selftest/efi_selftest_gop.c b/lib/efi_selftest/efi_selftest_gop.c index 5b0e2a96059..4ad043c5974 100644 --- a/lib/efi_selftest/efi_selftest_gop.c +++ b/lib/efi_selftest/efi_selftest_gop.c @@ -10,7 +10,7 @@ #include static struct efi_boot_services *boottime; -static efi_guid_t efi_gop_guid = EFI_GOP_GUID; +static efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; static struct efi_gop *gop; /* diff --git a/lib/efi_selftest/efi_selftest_loadimage.c b/lib/efi_selftest/efi_selftest_loadimage.c index 96faa67a157..449b6bfcace 100644 --- a/lib/efi_selftest/efi_selftest_loadimage.c +++ b/lib/efi_selftest/efi_selftest_loadimage.c @@ -27,7 +27,7 @@ static struct efi_boot_services *boottime; static efi_handle_t handle_image; static efi_handle_t handle_volume; -static const efi_guid_t guid_device_path = DEVICE_PATH_GUID; +static const efi_guid_t guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; static const efi_guid_t guid_simple_file_system_protocol = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; static const efi_guid_t guid_file_info = EFI_FILE_INFO_GUID; diff --git a/lib/efi_selftest/efi_selftest_miniapp_exit.c b/lib/efi_selftest/efi_selftest_miniapp_exit.c index d63b9e3addf..b3ca109d811 100644 --- a/lib/efi_selftest/efi_selftest_miniapp_exit.c +++ b/lib/efi_selftest/efi_selftest_miniapp_exit.c @@ -11,7 +11,7 @@ #include #include -static efi_guid_t loaded_image_protocol_guid = LOADED_IMAGE_GUID; +static efi_guid_t loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; /** * check_loaded_image_protocol() - check image_base/image_size diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c index f1e23c4921c..d7350e2158d 100644 --- a/lib/efi_selftest/efi_selftest_snp.c +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -66,7 +66,7 @@ struct dhcp { static struct efi_boot_services *boottime; static struct efi_simple_network *net; static struct efi_event *timer; -static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_GUID; +static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; /* IP packet ID */ static unsigned int net_ip_id; -- cgit v1.3.1 From 6b95b38c41a6a56d48b51b192dac7365ce0a8024 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Fri, 19 Apr 2019 12:22:35 +0900 Subject: efi_loader: rework bootmgr/bootefi using load_image API In the current implementation, bootefi command and EFI boot manager don't use load_image API, instead, use more primitive and internal functions. This will introduce duplicated code and potentially unknown bugs as well as inconsistent behaviours. With this patch, do_efibootmgr() and do_boot_efi() are completely overhauled and re-implemented using load_image API. Signed-off-by: AKASHI Takahiro Use efi_root as parent handle for the loaded image. LoadImage() should be called with BootPolicy = true by the boot manager. Avoid duplicate free_pool(). Eliminate variable memdp which is not needed after anymore due to "efi_loader: correctly split device path of loaded image". Reviewed-by: Heinrich Schuchardt Signed-off-by: Heinrich Schuchardt --- cmd/bootefi.c | 180 ++++++++++++++++++++++-------------------- include/efi_loader.h | 5 +- lib/efi_loader/efi_bootmgr.c | 42 +++++----- lib/efi_loader/efi_boottime.c | 2 + 4 files changed, 119 insertions(+), 110 deletions(-) (limited to 'include') diff --git a/cmd/bootefi.c b/cmd/bootefi.c index d62e9969acb..be557518309 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -242,89 +242,36 @@ static efi_status_t efi_install_fdt(const char *fdt_opt) /** * do_bootefi_exec() - execute EFI binary * - * @efi: address of the binary - * @device_path: path of the device from which the binary was loaded - * @image_path: device path of the binary + * @handle: handle of loaded image * Return: status code * * Load the EFI binary into a newly assigned memory unwinding the relocation * information, install the loaded image protocol, and call the binary. */ -static efi_status_t do_bootefi_exec(void *efi, - struct efi_device_path *device_path, - struct efi_device_path *image_path) +static efi_status_t do_bootefi_exec(efi_handle_t handle) { - efi_handle_t mem_handle = NULL; - struct efi_device_path *memdp = NULL; efi_status_t ret; - struct efi_loaded_image_obj *image_obj = NULL; - struct efi_loaded_image *loaded_image_info = NULL; - - /* - * Special case for efi payload not loaded from disk, such as - * 'bootefi hello' or for example payload loaded directly into - * memory via JTAG, etc: - */ - if (!device_path && !image_path) { - printf("WARNING: using memory device/image path, this may confuse some payloads!\n"); - /* actual addresses filled in after efi_load_pe() */ - memdp = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, 0, 0); - device_path = image_path = memdp; - /* - * Grub expects that the device path of the loaded image is - * installed on a handle. - */ - ret = efi_create_handle(&mem_handle); - if (ret != EFI_SUCCESS) - return ret; /* TODO: leaks device_path */ - ret = efi_add_protocol(mem_handle, &efi_guid_device_path, - device_path); - if (ret != EFI_SUCCESS) - goto err_add_protocol; - } else { - assert(device_path && image_path); - } - - ret = efi_setup_loaded_image(device_path, image_path, &image_obj, - &loaded_image_info); - if (ret) - goto err_prepare; /* Transfer environment variable as load options */ - ret = set_load_options((efi_handle_t)image_obj, "bootargs"); - if (ret != EFI_SUCCESS) - goto err_prepare; - - /* Load the EFI payload */ - ret = efi_load_pe(image_obj, efi, loaded_image_info); + ret = set_load_options(handle, "bootargs"); if (ret != EFI_SUCCESS) - goto err_prepare; - - if (memdp) { - struct efi_device_path_memory *mdp = (void *)memdp; - mdp->memory_type = loaded_image_info->image_code_type; - mdp->start_address = (uintptr_t)loaded_image_info->image_base; - mdp->end_address = mdp->start_address + - loaded_image_info->image_size; - } + return ret; /* we don't support much: */ env_set("efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported", "{ro,boot}(blob)0000000000000000"); /* Call our payload! */ - debug("%s: Jumping to 0x%p\n", __func__, image_obj->entry); - ret = EFI_CALL(efi_start_image(&image_obj->header, NULL, NULL)); + ret = EFI_CALL(efi_start_image(handle, NULL, NULL)); -err_prepare: - /* image has returned, loaded-image obj goes *poof*: */ efi_restore_gd(); - free(loaded_image_info->load_options); - efi_delete_handle(&image_obj->header); -err_add_protocol: - if (mem_handle) - efi_delete_handle(mem_handle); + /* + * FIXME: Who is responsible for + * free(loaded_image_info->load_options); + * Once efi_exit() is implemented correctly, + * handle itself doesn't exist here. + */ return ret; } @@ -339,8 +286,7 @@ err_add_protocol: */ static int do_efibootmgr(const char *fdt_opt) { - struct efi_device_path *device_path, *file_path; - void *addr; + efi_handle_t handle; efi_status_t ret; /* Allow unaligned memory access */ @@ -362,19 +308,19 @@ static int do_efibootmgr(const char *fdt_opt) else if (ret != EFI_SUCCESS) return CMD_RET_FAILURE; - addr = efi_bootmgr_load(&device_path, &file_path); - if (!addr) - return 1; + ret = efi_bootmgr_load(&handle); + if (ret != EFI_SUCCESS) { + printf("EFI boot manager: Cannot load any image\n"); + return CMD_RET_FAILURE; + } - printf("## Starting EFI application at %p ...\n", addr); - ret = do_bootefi_exec(addr, device_path, file_path); - printf("## Application terminated, r = %lu\n", - ret & ~EFI_ERROR_MASK); + ret = do_bootefi_exec(handle); + printf("## Application terminated, r = %lu\n", ret & ~EFI_ERROR_MASK); if (ret != EFI_SUCCESS) - return 1; + return CMD_RET_FAILURE; - return 0; + return CMD_RET_SUCCESS; } /* @@ -389,7 +335,12 @@ static int do_efibootmgr(const char *fdt_opt) */ static int do_bootefi_image(const char *image_opt, const char *fdt_opt) { - unsigned long addr; + void *image_buf; + struct efi_device_path *device_path, *image_path; + struct efi_device_path *file_path = NULL; + unsigned long addr, size; + const char *size_str; + efi_handle_t mem_handle = NULL, handle; efi_status_t ret; /* Allow unaligned memory access */ @@ -414,33 +365,83 @@ static int do_bootefi_image(const char *image_opt, const char *fdt_opt) #ifdef CONFIG_CMD_BOOTEFI_HELLO if (!strcmp(image_opt, "hello")) { char *saddr; - ulong size = __efi_helloworld_end - __efi_helloworld_begin; saddr = env_get("loadaddr"); + size = __efi_helloworld_end - __efi_helloworld_begin; + if (saddr) addr = simple_strtoul(saddr, NULL, 16); else addr = CONFIG_SYS_LOAD_ADDR; - memcpy(map_sysmem(addr, size), __efi_helloworld_begin, size); + + image_buf = map_sysmem(addr, size); + memcpy(image_buf, __efi_helloworld_begin, size); + + device_path = NULL; + image_path = NULL; } else #endif { + size_str = env_get("filesize"); + if (size_str) + size = simple_strtoul(size_str, NULL, 16); + else + size = 0; + addr = simple_strtoul(image_opt, NULL, 16); /* Check that a numeric value was passed */ if (!addr && *image_opt != '0') return CMD_RET_USAGE; + + image_buf = map_sysmem(addr, size); + + device_path = bootefi_device_path; + image_path = bootefi_image_path; } - printf("## Starting EFI application at %08lx ...\n", addr); - ret = do_bootefi_exec(map_sysmem(addr, 0), bootefi_device_path, - bootefi_image_path); - printf("## Application terminated, r = %lu\n", - ret & ~EFI_ERROR_MASK); + if (!device_path && !image_path) { + /* + * Special case for efi payload not loaded from disk, + * such as 'bootefi hello' or for example payload + * loaded directly into memory via JTAG, etc: + */ + file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, + (uintptr_t)image_buf, size); + /* + * Make sure that device for device_path exist + * in load_image(). Otherwise, shell and grub will fail. + */ + ret = efi_create_handle(&mem_handle); + if (ret != EFI_SUCCESS) + goto out; + + ret = efi_add_protocol(mem_handle, &efi_guid_device_path, + file_path); + if (ret != EFI_SUCCESS) + goto out; + } else { + assert(device_path && image_path); + file_path = efi_dp_append(device_path, image_path); + } + + ret = EFI_CALL(efi_load_image(false, efi_root, + file_path, image_buf, size, &handle)); + if (ret != EFI_SUCCESS) + goto out; + + ret = do_bootefi_exec(handle); + printf("## Application terminated, r = %lu\n", ret & ~EFI_ERROR_MASK); + +out: + if (mem_handle) + efi_delete_handle(mem_handle); + if (file_path) + efi_free_pool(file_path); if (ret != EFI_SUCCESS) return CMD_RET_FAILURE; - else - return CMD_RET_SUCCESS; + + return CMD_RET_SUCCESS; } #ifdef CONFIG_CMD_BOOTEFI_SELFTEST @@ -598,7 +599,7 @@ static char bootefi_help_text[] = " Use environment variable efi_selftest to select a single test.\n" " Use 'setenv efi_selftest list' to enumerate all tests.\n" #endif - "bootefi bootmgr [fdt addr]\n" + "bootefi bootmgr [fdt address]\n" " - load and boot EFI payload based on BootOrder/BootXXXX variables.\n" "\n" " If specified, the device tree located at gets\n" @@ -623,6 +624,13 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path) ret = efi_dp_from_name(dev, devnr, path, &device, &image); if (ret == EFI_SUCCESS) { bootefi_device_path = device; + if (image) { + /* FIXME: image should not contain device */ + struct efi_device_path *image_tmp = image; + + efi_dp_split_file_path(image, &device, &image); + efi_free_pool(image_tmp); + } bootefi_image_path = image; } else { bootefi_device_path = NULL; diff --git a/include/efi_loader.h b/include/efi_loader.h index 93f7672aecb..39ed8a6fa59 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -412,8 +412,6 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path, struct efi_loaded_image_obj **handle_ptr, struct efi_loaded_image **info_ptr); -efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, - void **buffer, efi_uintn_t *size); /* Print information about all loaded images */ void efi_print_image_infos(void *pc); @@ -567,8 +565,7 @@ struct efi_load_option { void efi_deserialize_load_option(struct efi_load_option *lo, u8 *data); unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data); -void *efi_bootmgr_load(struct efi_device_path **device_path, - struct efi_device_path **file_path); +efi_status_t efi_bootmgr_load(efi_handle_t *handle); #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 4fccadc5483..4ccba228757 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -120,14 +120,14 @@ static void *get_var(u16 *name, const efi_guid_t *vendor, * if successful. This checks that the EFI_LOAD_OPTION is active (enabled) * and that the specified file to boot exists. */ -static void *try_load_entry(uint16_t n, struct efi_device_path **device_path, - struct efi_device_path **file_path) +static efi_status_t try_load_entry(u16 n, efi_handle_t *handle) { struct efi_load_option lo; u16 varname[] = L"Boot0000"; u16 hexmap[] = L"0123456789ABCDEF"; - void *load_option, *image = NULL; + void *load_option; efi_uintn_t size; + efi_status_t ret; varname[4] = hexmap[(n & 0xf000) >> 12]; varname[5] = hexmap[(n & 0x0f00) >> 8]; @@ -136,19 +136,18 @@ static void *try_load_entry(uint16_t n, struct efi_device_path **device_path, load_option = get_var(varname, &efi_global_variable_guid, &size); if (!load_option) - return NULL; + return EFI_LOAD_ERROR; efi_deserialize_load_option(&lo, load_option); if (lo.attributes & LOAD_OPTION_ACTIVE) { u32 attributes; - efi_status_t ret; debug("%s: trying to load \"%ls\" from %pD\n", __func__, lo.label, lo.file_path); - ret = efi_load_image_from_path(lo.file_path, &image, &size); - + ret = EFI_CALL(efi_load_image(true, efi_root, lo.file_path, + NULL, 0, handle)); if (ret != EFI_SUCCESS) goto error; @@ -159,17 +158,22 @@ static void *try_load_entry(uint16_t n, struct efi_device_path **device_path, L"BootCurrent", (efi_guid_t *)&efi_global_variable_guid, attributes, size, &n)); - if (ret != EFI_SUCCESS) + if (ret != EFI_SUCCESS) { + if (EFI_CALL(efi_unload_image(*handle)) + != EFI_SUCCESS) + printf("Unloading image failed\n"); goto error; + } printf("Booting: %ls\n", lo.label); - efi_dp_split_file_path(lo.file_path, device_path, file_path); + } else { + ret = EFI_LOAD_ERROR; } error: free(load_option); - return image; + return ret; } /* @@ -177,12 +181,10 @@ error: * EFI variable, the available load-options, finding and returning * the first one that can be loaded successfully. */ -void *efi_bootmgr_load(struct efi_device_path **device_path, - struct efi_device_path **file_path) +efi_status_t efi_bootmgr_load(efi_handle_t *handle) { u16 bootnext, *bootorder; efi_uintn_t size; - void *image = NULL; int i, num; efi_status_t ret; @@ -209,10 +211,9 @@ void *efi_bootmgr_load(struct efi_device_path **device_path, /* load BootNext */ if (ret == EFI_SUCCESS) { if (size == sizeof(u16)) { - image = try_load_entry(bootnext, device_path, - file_path); - if (image) - return image; + ret = try_load_entry(bootnext, handle); + if (ret == EFI_SUCCESS) + return ret; } } else { printf("Deleting BootNext failed\n"); @@ -223,19 +224,20 @@ void *efi_bootmgr_load(struct efi_device_path **device_path, bootorder = get_var(L"BootOrder", &efi_global_variable_guid, &size); if (!bootorder) { printf("BootOrder not defined\n"); + ret = EFI_NOT_FOUND; goto error; } num = size / sizeof(uint16_t); for (i = 0; i < num; i++) { debug("%s: trying to load Boot%04X\n", __func__, bootorder[i]); - image = try_load_entry(bootorder[i], device_path, file_path); - if (image) + ret = try_load_entry(bootorder[i], handle); + if (ret == EFI_SUCCESS) break; } free(bootorder); error: - return image; + return ret; } diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 72897dc2c84..601b0a2cb88 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1591,6 +1591,7 @@ failure: * @size: size of the loaded image * Return: status code */ +static efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, void **buffer, efi_uintn_t *size) { @@ -2656,6 +2657,7 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, } current_image = image_handle; + EFI_PRINT("Jumping into 0x%p\n", image_obj->entry); ret = EFI_CALL(image_obj->entry(image_handle, &systab)); /* -- cgit v1.3.1 From f12bcc9149c32a01dac687718ad126d4d3ba29ba Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 23 Apr 2019 00:30:53 +0200 Subject: efi_loader: check memory type in AllocatePages() The UEFI specification prescribes that AllocatePages() checks the memory type. Signed-off-by: Heinrich Schuchardt --- include/efi.h | 4 ++++ lib/efi_loader/efi_memory.c | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'include') diff --git a/include/efi.h b/include/efi.h index 3c9d20f8c0b..5f415a99cc9 100644 --- a/include/efi.h +++ b/include/efi.h @@ -168,6 +168,10 @@ enum efi_mem_type { * part of the processor. */ EFI_PAL_CODE, + /* + * Non-volatile memory. + */ + EFI_PERSISTENT_MEMORY_TYPE, EFI_MAX_MEMORY_TYPE, EFI_TABLE_END, /* For efi_build_mem_table() */ diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 46681dc2082..987cc6dc5f6 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -376,6 +376,10 @@ efi_status_t efi_allocate_pages(int type, int memory_type, efi_status_t r = EFI_SUCCESS; uint64_t addr; + /* Check import parameters */ + if (memory_type >= EFI_PERSISTENT_MEMORY_TYPE && + memory_type <= 0x6FFFFFFF) + return EFI_INVALID_PARAMETER; if (!memory) return EFI_INVALID_PARAMETER; -- cgit v1.3.1