From f86076d885b29b71064ef3a1f5b1ada1bd92866c Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 16 Apr 2019 17:39:26 +0200 Subject: efi_loader: efi_setup_loaded_image() handle missing file name This is a preparatory patch. efi_dp_split_file_path() is used to create device_path and file_path from file_path for efi_setup_loaded_image(). In a special case, however, of HARDWARE_DEVICE/MEMORY, it doesn't work expectedly since this path doesn't contain any FILE_PATH sub-type. This patch makes a workaround. Signed-off-by: AKASHI Takahiro Adjust the logic such that for all paths that do no end on a media file path we return NULL as file_path. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_device_path.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/efi_loader') diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index d8c052d6ec5..6104c7d33b7 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -917,14 +917,14 @@ struct efi_device_path *efi_dp_from_mem(uint32_t memory_type, * * @full_path: device path including device and file path * @device_path: path of the device - * @file_path: relative path of the file + * @file_path: relative path of the file or NULL if there is none * Return: status code */ efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path, struct efi_device_path **device_path, struct efi_device_path **file_path) { - struct efi_device_path *p, *dp, *fp; + struct efi_device_path *p, *dp, *fp = NULL; *device_path = NULL; *file_path = NULL; @@ -935,7 +935,7 @@ efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path, while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) { p = efi_dp_next(p); if (!p) - return EFI_INVALID_PARAMETER; + goto out; } fp = efi_dp_dup(p); if (!fp) @@ -944,6 +944,7 @@ efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path, p->sub_type = DEVICE_PATH_SUB_TYPE_END; p->length = sizeof(*p); +out: *device_path = dp; *file_path = fp; return EFI_SUCCESS; -- cgit v1.2.3 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 --- lib/efi_loader/efi_root_node.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/efi_loader') diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c index 392f5c49513..e0fcbb85a4d 100644 --- a/lib/efi_loader/efi_root_node.c +++ b/lib/efi_loader/efi_root_node.c @@ -11,6 +11,8 @@ const efi_guid_t efi_u_boot_guid = U_BOOT_GUID; +efi_handle_t efi_root = NULL; + struct efi_root_dp { struct efi_device_path_vendor vendor; struct efi_device_path end; @@ -26,7 +28,6 @@ struct efi_root_dp { */ efi_status_t efi_root_node_register(void) { - efi_handle_t root = NULL; struct efi_root_dp *dp; /* Create device path protocol */ @@ -46,7 +47,7 @@ efi_status_t efi_root_node_register(void) dp->end.length = sizeof(struct efi_device_path); /* Create root node and install protocols */ - return EFI_CALL(efi_install_multiple_protocol_interfaces(&root, + return EFI_CALL(efi_install_multiple_protocol_interfaces(&efi_root, /* Device path protocol */ &efi_guid_device_path, dp, /* Device path to text protocol */ -- cgit v1.2.3 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 --- 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 +- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'lib/efi_loader') 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; -- cgit v1.2.3 From 1e15a9cb7f2d616325cd855895b5f1283c1ac911 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 20 Apr 2019 19:24:43 +0000 Subject: efi_loader: correctly split device path of loaded image When the LoadImage() service is called for an image that is already loaded to memory the file path may be NULL or it will contain both a device path as well as a media path. We should not assume that there is no media path. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'lib/efi_loader') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index abc295e392e..72897dc2c84 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1699,19 +1699,11 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy, &source_size); if (ret != EFI_SUCCESS) goto error; - /* - * split file_path which contains both the device and - * file parts: - */ - efi_dp_split_file_path(file_path, &dp, &fp); } else { - /* In this case, file_path is the "device" path, i.e. - * something like a HARDWARE_DEVICE:MEMORY_MAPPED - */ dest_buffer = source_buffer; - dp = file_path; - fp = NULL; } + /* split file_path which contains both the device and file parts */ + efi_dp_split_file_path(file_path, &dp, &fp); ret = efi_setup_loaded_image(dp, fp, image_obj, &info); if (ret == EFI_SUCCESS) ret = efi_load_pe(*image_obj, dest_buffer, info); -- cgit v1.2.3 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 --- lib/efi_loader/efi_bootmgr.c | 42 ++++++++++++++++++++++-------------------- lib/efi_loader/efi_boottime.c | 2 ++ 2 files changed, 24 insertions(+), 20 deletions(-) (limited to 'lib/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.2.3 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 --- lib/efi_loader/efi_memory.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/efi_loader') 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.2.3 From 7d1e4b73e3f321cd4f0e039aa0387484cf97b25c Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 23 Apr 2019 00:51:01 +0200 Subject: efi_loader: check length in CreateDeviceNode() When creating a device path node ensure that the size of the allocated memory at lest matches the size of the node header. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_device_path.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/efi_loader') diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 6104c7d33b7..10f890f44f6 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -335,6 +335,9 @@ struct efi_device_path *efi_dp_create_device_node(const u8 type, { struct efi_device_path *ret; + if (length < sizeof(struct efi_device_path)) + return NULL; + ret = dp_alloc(length); if (!ret) return ret; -- cgit v1.2.3