From 470fa190f35006e2641d775d4befbd74108837bc Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 9 Dec 2020 07:38:46 +0100 Subject: efi_loader: don't set EFI_RT_SUPPORTED_UPDATE_CAPSULE The EFI_RT_PROPERTIES_TABLE configuration table indicates which runtime services are available at runtime. Even if CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y, we neither support UpdateCapsule() nor QueryCapsuleCapabilities() at runtime. Thus we should not set the corresponding flags EFI_RT_SUPPORTED_UPDATE_CAPSULE and EFI_RT_SUPPORTED_QUERY_CAPSULE_CAPABILITIES in RuntimeServicesSupported. Fixes: 2bc27ca8a04a ("efi_loader: define UpdateCapsule api") Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_runtime.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib/efi_loader') diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 0b171c1ff7b..93c9478b225 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -133,10 +133,6 @@ efi_status_t efi_init_runtime_supported(void) #ifdef CONFIG_EFI_HAVE_RUNTIME_RESET rt_table->runtime_services_supported |= EFI_RT_SUPPORTED_RESET_SYSTEM; #endif - if (IS_ENABLED(CONFIG_EFI_RUNTIME_UPDATE_CAPSULE)) - rt_table->runtime_services_supported |= - (EFI_RT_SUPPORTED_UPDATE_CAPSULE | - EFI_RT_SUPPORTED_QUERY_CAPSULE_CAPABILITIES); ret = efi_install_configuration_table(&efi_rt_properties_table_guid, rt_table); -- cgit v1.3.1 From 861072b2a88497366a5b33017c4496406f0084b2 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 7 Dec 2020 18:20:57 +0100 Subject: efi_loader: remove EFI_HII_CONFIG_ROUTING_PROTOCOL Our implementation of the EFI_HII_CONFIG_ROUTING_PROTOCOL is a mere stub, where all services return an error code. The protocol is neither needed for the EFI shell nor for the UEFI SCT. To reduce the code size remove it from the U-Boot binary. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/Makefile | 2 +- lib/efi_loader/efi_hii_config.c | 10 +++++++--- lib/efi_loader/efi_root_node.c | 3 --- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'lib/efi_loader') diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 0afcaf48132..462d4d9ac45 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -30,7 +30,7 @@ obj-y += efi_device_path.o obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o obj-y += efi_device_path_utilities.o obj-y += efi_file.o -obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o efi_hii_config.o +obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o obj-y += efi_image_loader.o obj-y += efi_memory.o obj-y += efi_root_node.o diff --git a/lib/efi_loader/efi_hii_config.c b/lib/efi_loader/efi_hii_config.c index 26ea4b9bc0a..237e8acf840 100644 --- a/lib/efi_loader/efi_hii_config.c +++ b/lib/efi_loader/efi_hii_config.c @@ -1,9 +1,13 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * EFI Human Interface Infrastructure ... Configuration + * EFI Human Interface Infrastructure ... Configuration * - * Copyright (c) 2017 Leif Lindholm - * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited + * Copyright (c) 2017 Leif Lindholm + * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited + * + * As this is still a non-working stub and the protocol is neither required + * by the EFI shell nor by the UEFI SCT this module has been removed from + * the Makefile. */ #include diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c index f68b0fdc610..b17db312f78 100644 --- a/lib/efi_loader/efi_root_node.c +++ b/lib/efi_loader/efi_root_node.c @@ -77,9 +77,6 @@ efi_status_t efi_root_node_register(void) /* HII database protocol */ &efi_guid_hii_database_protocol, (void *)&efi_hii_database, - /* HII configuration routing protocol */ - &efi_guid_hii_config_routing_protocol, - (void *)&efi_hii_config_routing, #endif NULL)); efi_root->type = EFI_OBJECT_TYPE_U_BOOT_FIRMWARE; -- cgit v1.3.1 From 0e9d2d7bc25bd3114e8f6ff0d18cdf9ee675909c Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 4 Dec 2020 03:02:03 +0100 Subject: efi_loader: resequence functions in efi_boottime.c For implementing support for the EFI_LOAD_FILE_PROTOCOL in the LoadImage() service we will have to call the LocateDevicePath() service. To avoid a forward declaration resequence the functions. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 164 +++++++++++++++++++++--------------------- 1 file changed, 82 insertions(+), 82 deletions(-) (limited to 'lib/efi_loader') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 246b59d3b35..4f7479d4dfd 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1769,6 +1769,88 @@ failure: return ret; } +/** + * efi_locate_device_path() - Get the device path and handle of an device + * implementing a protocol + * @protocol: GUID of the protocol + * @device_path: device path + * @device: handle of the device + * + * This function implements the LocateDevicePath service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * Return: status code + */ +static efi_status_t EFIAPI efi_locate_device_path( + const efi_guid_t *protocol, + struct efi_device_path **device_path, + efi_handle_t *device) +{ + struct efi_device_path *dp; + size_t i; + struct efi_handler *handler; + efi_handle_t *handles; + size_t len, len_dp; + size_t len_best = 0; + efi_uintn_t no_handles; + u8 *remainder; + efi_status_t ret; + + EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device); + + if (!protocol || !device_path || !*device_path) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + /* Find end of device path */ + len = efi_dp_instance_size(*device_path); + + /* Get all handles implementing the protocol */ + ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL, + &no_handles, &handles)); + if (ret != EFI_SUCCESS) + goto out; + + for (i = 0; i < no_handles; ++i) { + /* Find the device path protocol */ + ret = efi_search_protocol(handles[i], &efi_guid_device_path, + &handler); + if (ret != EFI_SUCCESS) + continue; + dp = (struct efi_device_path *)handler->protocol_interface; + len_dp = efi_dp_instance_size(dp); + /* + * This handle can only be a better fit + * if its device path length is longer than the best fit and + * if its device path length is shorter of equal the searched + * device path. + */ + if (len_dp <= len_best || len_dp > len) + continue; + /* Check if dp is a subpath of device_path */ + if (memcmp(*device_path, dp, len_dp)) + continue; + if (!device) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + *device = handles[i]; + len_best = len_dp; + } + if (len_best) { + remainder = (u8 *)*device_path + len_best; + *device_path = (struct efi_device_path *)remainder; + ret = EFI_SUCCESS; + } else { + ret = EFI_NOT_FOUND; + } +out: + return EFI_EXIT(ret); +} + /** * efi_load_image_from_path() - load an image using a file path * @@ -2403,88 +2485,6 @@ found: return EFI_EXIT(EFI_SUCCESS); } -/** - * efi_locate_device_path() - Get the device path and handle of an device - * implementing a protocol - * @protocol: GUID of the protocol - * @device_path: device path - * @device: handle of the device - * - * This function implements the LocateDevicePath service. - * - * See the Unified Extensible Firmware Interface (UEFI) specification for - * details. - * - * Return: status code - */ -static efi_status_t EFIAPI efi_locate_device_path( - const efi_guid_t *protocol, - struct efi_device_path **device_path, - efi_handle_t *device) -{ - struct efi_device_path *dp; - size_t i; - struct efi_handler *handler; - efi_handle_t *handles; - size_t len, len_dp; - size_t len_best = 0; - efi_uintn_t no_handles; - u8 *remainder; - efi_status_t ret; - - EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device); - - if (!protocol || !device_path || !*device_path) { - ret = EFI_INVALID_PARAMETER; - goto out; - } - - /* Find end of device path */ - len = efi_dp_instance_size(*device_path); - - /* Get all handles implementing the protocol */ - ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL, - &no_handles, &handles)); - if (ret != EFI_SUCCESS) - goto out; - - for (i = 0; i < no_handles; ++i) { - /* Find the device path protocol */ - ret = efi_search_protocol(handles[i], &efi_guid_device_path, - &handler); - if (ret != EFI_SUCCESS) - continue; - dp = (struct efi_device_path *)handler->protocol_interface; - len_dp = efi_dp_instance_size(dp); - /* - * This handle can only be a better fit - * if its device path length is longer than the best fit and - * if its device path length is shorter of equal the searched - * device path. - */ - if (len_dp <= len_best || len_dp > len) - continue; - /* Check if dp is a subpath of device_path */ - if (memcmp(*device_path, dp, len_dp)) - continue; - if (!device) { - ret = EFI_INVALID_PARAMETER; - goto out; - } - *device = handles[i]; - len_best = len_dp; - } - if (len_best) { - remainder = (u8 *)*device_path + len_best; - *device_path = (struct efi_device_path *)remainder; - ret = EFI_SUCCESS; - } else { - ret = EFI_NOT_FOUND; - } -out: - return EFI_EXIT(ret); -} - /** * efi_install_multiple_protocol_interfaces() - Install multiple protocol * interfaces -- cgit v1.3.1 From b6f11098c9a619f480582b26edd26c5b195c69f4 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 4 Dec 2020 03:33:41 +0100 Subject: efi_loader: move EFI_LOAD_FILE2_PROTOCOL_GUID The EFI_LOAD_FILE_PROTOCOL_GUID and EFI_LOAD_FILE2_PROTOCOL_GUID are needed to complement the implementation of the LoadFile() boot service. Remove a duplicate declaration of a variable for the EFI_LOAD_FILE2_PROTOCOL_GUID. Move the remaining declaration to efi_boottime.c. Add a variable for the EFI_LOAD_FILE_PROTOCOL_GUID. Signed-off-by: Heinrich Schuchardt --- include/efi_loader.h | 3 +++ lib/efi_loader/efi_boottime.c | 3 +++ lib/efi_loader/efi_load_initrd.c | 3 --- lib/efi_selftest/efi_selftest_load_initrd.c | 7 ++++--- 4 files changed, 10 insertions(+), 6 deletions(-) (limited to 'lib/efi_loader') diff --git a/include/efi_loader.h b/include/efi_loader.h index 76cd2b36f2b..4c6eb8616d5 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -195,6 +195,9 @@ extern const efi_guid_t efi_file_system_info_guid; extern const efi_guid_t efi_guid_device_path_utilities_protocol; /* GUID of the deprecated Unicode collation protocol */ extern const efi_guid_t efi_guid_unicode_collation_protocol; +/* GUIDs of the Load File and Load File2 protocol */ +extern const efi_guid_t efi_guid_load_file_protocol; +extern const efi_guid_t efi_guid_load_file2_protocol; /* GUID of the Unicode collation protocol */ extern const efi_guid_t efi_guid_unicode_collation_protocol2; extern const efi_guid_t efi_guid_hii_config_routing_protocol; diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 4f7479d4dfd..afe8adb91e5 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -81,6 +81,9 @@ const efi_guid_t efi_guid_event_group_ready_to_boot = /* event group ResetSystem() invoked (before ExitBootServices) */ const efi_guid_t efi_guid_event_group_reset_system = EFI_EVENT_GROUP_RESET_SYSTEM; +/* GUIDs of the Load File and Load File2 protocols */ +const efi_guid_t efi_guid_load_file_protocol = EFI_LOAD_FILE_PROTOCOL_GUID; +const efi_guid_t efi_guid_load_file2_protocol = EFI_LOAD_FILE2_PROTOCOL_GUID; static efi_status_t EFIAPI efi_disconnect_controller( efi_handle_t controller_handle, diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c index d517d686c33..4bf3b5ef684 100644 --- a/lib/efi_loader/efi_load_initrd.c +++ b/lib/efi_loader/efi_load_initrd.c @@ -12,9 +12,6 @@ #include #include -static const efi_guid_t efi_guid_load_file2_protocol = - EFI_LOAD_FILE2_PROTOCOL_GUID; - static efi_status_t EFIAPI efi_load_file2_initrd(struct efi_load_file_protocol *this, struct efi_device_path *file_path, bool boot_policy, diff --git a/lib/efi_selftest/efi_selftest_load_initrd.c b/lib/efi_selftest/efi_selftest_load_initrd.c index fe060a66440..f591dcd2115 100644 --- a/lib/efi_selftest/efi_selftest_load_initrd.c +++ b/lib/efi_selftest/efi_selftest_load_initrd.c @@ -86,7 +86,6 @@ static int setup(const efi_handle_t handle, static int execute(void) { - efi_guid_t lf2_proto_guid = EFI_LOAD_FILE2_PROTOCOL_GUID; struct efi_load_file_protocol *lf2; struct efi_device_path *dp2, *dp2_invalid; efi_status_t status; @@ -99,13 +98,15 @@ static int execute(void) memset(buffer, 0, sizeof(buffer)); dp2 = (struct efi_device_path *)&dp; - status = boottime->locate_device_path(&lf2_proto_guid, &dp2, &handle); + status = boottime->locate_device_path(&efi_guid_load_file2_protocol, + &dp2, &handle); if (status != EFI_SUCCESS) { efi_st_error("Unable to locate device path\n"); return EFI_ST_FAILURE; } - status = boottime->handle_protocol(handle, &lf2_proto_guid, + status = boottime->handle_protocol(handle, + &efi_guid_load_file2_protocol, (void **)&lf2); if (status != EFI_SUCCESS) { efi_st_error("Unable to locate protocol\n"); -- cgit v1.3.1 From c06c55b1f5deb994ef7544f99419b4ab68f82e4f Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 4 Dec 2020 09:27:41 +0100 Subject: efi_loader: pass boot_policy to efi_load_image_from_path Implementing support for loading images via the EFI_LOAD_FILE_PROTOCOL requires the boot policy as input for efi_load_image_from_path(). Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'lib/efi_loader') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index afe8adb91e5..f18e384c39b 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1860,13 +1860,15 @@ out: * Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the * callers obligation to update the memory type as needed. * - * @file_path: the path of the image to load - * @buffer: buffer containing the loaded image - * @size: size of the loaded image - * Return: status code + * @boot_policy: true for request originating from the boot manager + * @file_path: the path of the image to load + * @buffer: buffer containing the loaded image + * @size: size of the loaded image + * Return: status code */ static -efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, +efi_status_t efi_load_image_from_path(bool boot_policy, + struct efi_device_path *file_path, void **buffer, efi_uintn_t *size) { struct efi_file_info *info = NULL; @@ -1968,8 +1970,8 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy, } if (!source_buffer) { - ret = efi_load_image_from_path(file_path, &dest_buffer, - &source_size); + ret = efi_load_image_from_path(boot_policy, file_path, + &dest_buffer, &source_size); if (ret != EFI_SUCCESS) goto error; } else { -- cgit v1.3.1 From 0e074d12393ba14536f8a103b28c75f74b7c5896 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 6 Dec 2020 10:47:57 +0100 Subject: efi_loader: carve out efi_load_image_from_file() efi_load_image_from_file() should read via either of: * EFI_SIMPLE_FILE_SYSTEM_PROTOCOL * EFI_LOAD_FILE_PROTOCOL * EFI_LOAD_FILE2_PROTOCOL To make the code readable carve out a function to load the image via the file system protocol. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 45 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) (limited to 'lib/efi_loader') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index f18e384c39b..1983ca3f6b9 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1855,32 +1855,26 @@ out: } /** - * efi_load_image_from_path() - load an image using a file path + * efi_load_image_from_file() - load an image from file system * * Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the * callers obligation to update the memory type as needed. * - * @boot_policy: true for request originating from the boot manager * @file_path: the path of the image to load * @buffer: buffer containing the loaded image * @size: size of the loaded image * Return: status code */ static -efi_status_t efi_load_image_from_path(bool boot_policy, - struct efi_device_path *file_path, +efi_status_t efi_load_image_from_file(struct efi_device_path *file_path, void **buffer, efi_uintn_t *size) { struct efi_file_info *info = NULL; struct efi_file_handle *f; - static efi_status_t ret; + efi_status_t ret; u64 addr; efi_uintn_t bs; - /* In case of failure nothing is returned */ - *buffer = NULL; - *size = 0; - /* Open file */ f = efi_file_from_path(file_path); if (!f) @@ -1928,6 +1922,39 @@ error: return ret; } +/** + * efi_load_image_from_path() - load an image using a file path + * + * Read a file into a buffer allocated as EFI_BOOT_SERVICES_DATA. It is the + * callers obligation to update the memory type as needed. + * + * @boot_policy: true for request originating from the boot manager + * @file_path: the path of the image to load + * @buffer: buffer containing the loaded image + * @size: size of the loaded image + * Return: status code + */ +static +efi_status_t efi_load_image_from_path(bool boot_policy, + struct efi_device_path *file_path, + void **buffer, efi_uintn_t *size) +{ + efi_handle_t device; + efi_status_t ret; + struct efi_device_path *dp; + + /* In case of failure nothing is returned */ + *buffer = NULL; + *size = 0; + + dp = file_path; + ret = EFI_CALL(efi_locate_device_path( + &efi_simple_file_system_protocol_guid, &dp, &device)); + if (ret == EFI_SUCCESS) + return efi_load_image_from_file(file_path, buffer, size); + return EFI_NOT_FOUND; +} + /** * efi_load_image() - load an EFI image into memory * @boot_policy: true for request originating from the boot manager -- cgit v1.3.1 From 3da0b28582004981d6ca6866130d2835c3cbf0d0 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 6 Dec 2020 13:00:15 +0100 Subject: efi_loader: support EFI_LOAD_FILE_PROTOCOL Support loading images via the EFI_LOAD_FILE_PROTOCOL and EFI_LOAD_FILE2_PROTOCOL. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 49 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'lib/efi_loader') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 1983ca3f6b9..9bd63b6e524 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1942,6 +1942,10 @@ efi_status_t efi_load_image_from_path(bool boot_policy, efi_handle_t device; efi_status_t ret; struct efi_device_path *dp; + struct efi_load_file_protocol *load_file_protocol = NULL; + efi_uintn_t buffer_size; + uint64_t addr, pages; + const efi_guid_t *guid; /* In case of failure nothing is returned */ *buffer = NULL; @@ -1952,7 +1956,50 @@ efi_status_t efi_load_image_from_path(bool boot_policy, &efi_simple_file_system_protocol_guid, &dp, &device)); if (ret == EFI_SUCCESS) return efi_load_image_from_file(file_path, buffer, size); - return EFI_NOT_FOUND; + + ret = EFI_CALL(efi_locate_device_path( + &efi_guid_load_file_protocol, &dp, &device)); + if (ret == EFI_SUCCESS) { + guid = &efi_guid_load_file_protocol; + } else if (!boot_policy) { + guid = &efi_guid_load_file2_protocol; + ret = EFI_CALL(efi_locate_device_path(guid, &dp, &device)); + } + if (ret != EFI_SUCCESS) + return EFI_NOT_FOUND; + ret = EFI_CALL(efi_handle_protocol(device, guid, + (void **)&load_file_protocol)); + if (ret != EFI_SUCCESS) + return EFI_NOT_FOUND; + buffer_size = 0; + ret = load_file_protocol->load_file(load_file_protocol, dp, + boot_policy, &buffer_size, + NULL); + if (ret != EFI_BUFFER_TOO_SMALL) + goto out; + pages = efi_size_in_pages(buffer_size); + ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, EFI_BOOT_SERVICES_DATA, + pages, &addr); + if (ret != EFI_SUCCESS) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + ret = EFI_CALL(load_file_protocol->load_file( + load_file_protocol, dp, boot_policy, + &buffer_size, (void *)(uintptr_t)addr)); + if (ret != EFI_SUCCESS) + efi_free_pages(addr, pages); +out: + if (load_file_protocol) + EFI_CALL(efi_close_protocol(device, + &efi_guid_load_file2_protocol, + efi_root, NULL)); + if (ret == EFI_SUCCESS) { + *buffer = (void *)(uintptr_t)addr; + *size = buffer_size; + } + + return ret; } /** -- cgit v1.3.1 From f9ad240e65ac2f45d7b0acd770b5d79e50c3d92f Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 10 Jan 2020 12:33:59 +0100 Subject: efi_loader: make efi_protocol_open() non-static Provide efi_protocol_open() as library function. Signed-off-by: Heinrich Schuchardt --- include/efi_loader.h | 5 +++++ lib/efi_loader/efi_boottime.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'lib/efi_loader') diff --git a/include/efi_loader.h b/include/efi_loader.h index 4c6eb8616d5..365f3d01dc7 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -500,6 +500,11 @@ efi_status_t efi_search_protocol(const efi_handle_t handle, efi_status_t efi_add_protocol(const efi_handle_t handle, const efi_guid_t *protocol, void *protocol_interface); +/* Open protocol */ +efi_status_t efi_protocol_open(struct efi_handler *handler, + void **protocol_interface, void *agent_handle, + void *controller_handle, uint32_t attributes); + /* Delete protocol from a handle */ efi_status_t efi_remove_protocol(const efi_handle_t handle, const efi_guid_t *protocol, diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 9bd63b6e524..03053e8660d 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2779,7 +2779,7 @@ static void EFIAPI efi_set_mem(void *buffer, size_t size, uint8_t value) * * Return: status code */ -static efi_status_t efi_protocol_open( +efi_status_t efi_protocol_open( struct efi_handler *handler, void **protocol_interface, void *agent_handle, void *controller_handle, uint32_t attributes) -- cgit v1.3.1 From 264485131c59c1c8fa17fe742bbca65cef868d94 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 10 Jan 2020 12:36:01 +0100 Subject: efi_loader: link partition to block device We provide a UEFI driver for block devices. When ConnectController() is called for a handle with the EFI_BLOCK_IO_PROTOCOL this driver creates the partitions. When DisconnectController() is called the handles for the partitions have to be deleted. This requires that the child controllers (partitions) open the EFI_BLOCK_IO_PROTOCOL of the controller (block IO device) with attribute EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_disk.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'lib/efi_loader') diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 7bd1ccec450..496ef29dd84 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -376,6 +376,23 @@ static efi_status_t efi_disk_add_dev( /* Fill in object data */ if (part) { struct efi_device_path *node = efi_dp_part_node(desc, part); + struct efi_handler *handler; + void *protocol_interface; + + /* Parent must expose EFI_BLOCK_IO_PROTOCOL */ + ret = efi_search_protocol(parent, &efi_block_io_guid, &handler); + if (ret != EFI_SUCCESS) + goto error; + + /* + * Link the partition (child controller) to the block device + * (controller). + */ + ret = efi_protocol_open(handler, &protocol_interface, NULL, + &diskobj->header, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER); + if (ret != EFI_SUCCESS) + goto error; diskobj->dp = efi_dp_append_node(dp_parent, node); efi_free_pool(node); @@ -453,6 +470,9 @@ static efi_status_t efi_disk_add_dev( } } return EFI_SUCCESS; +error: + efi_delete_handle(&diskobj->header); + return ret; } /** -- cgit v1.3.1