From a61e6ad76914a30a562ac01339c5d21f3283def8 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 10 Jun 2023 21:25:18 +0200 Subject: efi_selftest: ReinstallProtocolInterface test Test ReinstallProtocolInterface() more rigorously. Replacing the sole installed protocol interface must not result in deleting the handle and creating a new one. Check which interface is actually installed before and after ReinstallProtocolInterface(). Signed-off-by: Heinrich Schuchardt --- lib/efi_selftest/efi_selftest_register_notify.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'lib') diff --git a/lib/efi_selftest/efi_selftest_register_notify.c b/lib/efi_selftest/efi_selftest_register_notify.c index ad4bcce1a10..adf5dd00a1e 100644 --- a/lib/efi_selftest/efi_selftest_register_notify.c +++ b/lib/efi_selftest/efi_selftest_register_notify.c @@ -124,6 +124,7 @@ static int execute(void) { efi_status_t ret; efi_handle_t handle1 = NULL, handle2 = NULL; + struct interface *interface; struct interface interface1, interface2; ret = boottime->install_protocol_interface(&handle1, &guid1, @@ -145,6 +146,18 @@ static int execute(void) efi_st_error("LocateHandle failed\n"); return EFI_ST_FAILURE; } + interface = NULL; + ret = boottime->open_protocol(handle1, &guid1, (void**)&interface, + NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) { + efi_st_error("Cannot find installed protocol on handle\n"); + return EFI_ST_FAILURE; + } + if (interface != &interface1) { + efi_st_error("Wrong interface after install\n"); + return EFI_ST_FAILURE; + } ret = boottime->free_pool(context.handles); if (ret != EFI_SUCCESS) { efi_st_error("FreePool failed\n"); @@ -186,6 +199,18 @@ static int execute(void) efi_st_error("FreePool failed\n"); return EFI_ST_FAILURE; } + interface = NULL; + ret = boottime->open_protocol(handle1, &guid1, (void**)&interface, + NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) { + efi_st_error("Cannot find reinstalled protocol on handle\n"); + return EFI_ST_FAILURE; + } + if (interface != &interface2) { + efi_st_error("Wrong interface after reinstall\n"); + return EFI_ST_FAILURE; + } context.notify_count = 0; ret = boottime->install_protocol_interface(&handle2, &guid1, EFI_NATIVE_INTERFACE, -- cgit v1.2.3 From 3ae95fe21cbd1e367e6169968ed2497a2ea8561a Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Wed, 14 Jun 2023 09:55:48 +0300 Subject: efi_selftests: fix controllers repeated selftesting Running the controller selftest more than one times fails with => setenv efi_selftest 'controllers' && bootefi selftest Testing EFI API implementation Selected test: 'controllers' Setting up 'controllers' Setting up 'controllers' succeeded Executing 'controllers' Executing 'controllers' succeeded Summary: 0 failures => bootefi selftest Testing EFI API implementation Selected test: 'controllers' Setting up 'controllers' lib/efi_selftest/efi_selftest_controllers.c(280): ERROR: InstallProtocolInterface failed lib/efi_selftest/efi_selftest.c(89): ERROR: Setting up 'controllers' failed Summary: 1 failures There are multiple reason for this. We don't uninstall the binding interface from the controller handle and we don't reset the handle pointers either. So let's uninstall all the protocols properly and reset the handles to NULL on setup(). While at it add a forgotten check when uninstalling protocols from the handle_controller and make sure the number of child controllers is 0 Signed-off-by: Ilias Apalodimas Reviewed-by: Heinrich Schuchardt Signed-off-by: Heinrich Schuchardt --- lib/efi_selftest/efi_selftest_controllers.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/efi_selftest/efi_selftest_controllers.c b/lib/efi_selftest/efi_selftest_controllers.c index d2bbd1c4f65..63e674bedc0 100644 --- a/lib/efi_selftest/efi_selftest_controllers.c +++ b/lib/efi_selftest/efi_selftest_controllers.c @@ -271,6 +271,8 @@ static int setup(const efi_handle_t img_handle, efi_status_t ret; boottime = systable->boottime; + handle_controller = NULL; + handle_driver = NULL; /* Create controller handle */ ret = boottime->install_protocol_interface( @@ -402,14 +404,36 @@ static int execute(void) /* Check number of child controllers */ ret = count_child_controllers(handle_controller, &guid_controller, &count); - if (ret == EFI_SUCCESS) + if (ret == EFI_SUCCESS || count) { efi_st_error("Uninstall failed\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; } + /* + * Tear down unit test. + * + */ +static int teardown(void) +{ + efi_status_t ret; + /* Uninstall binding protocol */ + ret = boottime->uninstall_protocol_interface(handle_driver, + &guid_driver_binding_protocol, + &binding_interface); + if (ret != EFI_SUCCESS) + efi_st_error("Failed to uninstall protocols\n"); + + return ret; +} + EFI_UNIT_TEST(controllers) = { .name = "controllers", .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, .setup = setup, .execute = execute, + .teardown = teardown, }; -- cgit v1.2.3 From 3cc2b9f5b982ff3a192202b6d422eeb1893fa667 Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Mon, 12 Jun 2023 18:35:58 +0300 Subject: efi_loader: simplify efi_disk_remove Instead of discovering the ID of the device and call two different functions for a block device or a partition, we can rewrite efi_disk_remove() and handle the minor differences between the two variants internally. As a results we can simplify efi_disk_remove() a lot and get rid of the extra efi_disk_delete_raw/blk calls. Signed-off-by: Ilias Apalodimas If a handle is not found, return 0 to let the device be removed. Reviewed-by: Heinrich Schuchardt --- lib/efi_loader/efi_disk.c | 91 ++++++++++++++--------------------------------- 1 file changed, 26 insertions(+), 65 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index d2256713a8e..28c8cdf7100 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -690,91 +690,52 @@ int efi_disk_probe(void *ctx, struct event *event) return 0; } -/* - * Delete an efi_disk object for a whole raw disk +/** + * efi_disk_remove - delete an efi_disk object for a block device or partition * - * @dev uclass device (UCLASS_BLK) + * @ctx: event context: driver binding protocol + * @event: EV_PM_PRE_REMOVE event * - * Delete an efi_disk object which is associated with @dev. - * The type of @dev must be UCLASS_BLK. + * Delete an efi_disk object which is associated with the UCLASS_BLK or + * UCLASS_PARTITION device for which the EV_PM_PRE_REMOVE event is raised. * - * @return 0 on success, -1 otherwise + * Return: 0 on success, -1 otherwise */ -static int efi_disk_delete_raw(struct udevice *dev) +int efi_disk_remove(void *ctx, struct event *event) { + enum uclass_id id; + struct udevice *dev = event->data.dm.dev; efi_handle_t handle; struct blk_desc *desc; - struct efi_disk_obj *diskobj; + struct efi_disk_obj *diskobj = NULL; if (dev_tag_get_ptr(dev, DM_TAG_EFI, (void **)&handle)) - return -1; + return 0; - desc = dev_get_uclass_plat(dev); - if (desc->uclass_id != UCLASS_EFI_LOADER) { + id = device_get_uclass_id(dev); + switch (id) { + case UCLASS_BLK: + desc = dev_get_uclass_plat(dev); + if (desc && desc->uclass_id != UCLASS_EFI_LOADER) + diskobj = container_of(handle, struct efi_disk_obj, + header); + break; + case UCLASS_PARTITION: diskobj = container_of(handle, struct efi_disk_obj, header); - efi_free_pool(diskobj->dp); + break; + default: + return 0; } - efi_delete_handle(handle); - dev_tag_del(dev, DM_TAG_EFI); - - return 0; -} - -/* - * Delete an efi_disk object for a disk partition - * - * @dev uclass device (UCLASS_PARTITION) - * - * Delete an efi_disk object which is associated with @dev. - * The type of @dev must be UCLASS_PARTITION. - * - * @return 0 on success, -1 otherwise - */ -static int efi_disk_delete_part(struct udevice *dev) -{ - efi_handle_t handle; - struct efi_disk_obj *diskobj; - - if (dev_tag_get_ptr(dev, DM_TAG_EFI, (void **)&handle)) - return -1; - - diskobj = container_of(handle, struct efi_disk_obj, header); + if (diskobj) + efi_free_pool(diskobj->dp); - efi_free_pool(diskobj->dp); efi_delete_handle(handle); dev_tag_del(dev, DM_TAG_EFI); return 0; } -/* - * Delete an efi_disk object for a block device - * - * @dev uclass device (UCLASS_BLK or UCLASS_PARTITION) - * - * Delete an efi_disk object which is associated with @dev. - * The type of @dev must be either UCLASS_BLK or UCLASS_PARTITION. - * This function is expected to be called at EV_PM_PRE_REMOVE. - * - * @return 0 on success, -1 otherwise - */ -int efi_disk_remove(void *ctx, struct event *event) -{ - enum uclass_id id; - struct udevice *dev; - - dev = event->data.dm.dev; - id = device_get_uclass_id(dev); - - if (id == UCLASS_BLK) - return efi_disk_delete_raw(dev); - else if (id == UCLASS_PARTITION) - return efi_disk_delete_part(dev); - else - return 0; -} - /** * efi_disk_get_device_name() - get U-Boot device name associated with EFI handle * -- cgit v1.2.3 From 5669591dd8d2b21bc79237b161107300eb7f2b12 Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Tue, 13 Jun 2023 16:23:06 +0300 Subject: efi_selftests: fix protocol repeated selftesting Running the protocols selftest more than one times fails with => setenv efi_selftest 'manage protocols' && bootefi selftest Testing EFI API implementation Selected test: 'manage protocols' Setting up 'manage protocols' Setting up 'manage protocols' succeeded Executing 'manage protocols' Executing 'manage protocols' succeeded Tearing down 'manage protocols' Tearing down 'manage protocols' succeeded Summary: 0 failures => bootefi selftest Testing EFI API implementation Selected test: 'manage protocols' Setting up 'manage protocols' lib/efi_selftest/efi_selftest_manageprotocols.c(88): ERROR: InstallProtocolInterface failed lib/efi_selftest/efi_selftest.c(89): ERROR: Setting up 'manage protocols' failed Tearing down 'manage protocols' Tearing down 'manage protocols' succeeded Summary: 1 failures The reason is that we don't set the handles to NULL after deleting and freeing them. As a result the subsequent protocol installation will try to use an existing handle which we just removed that from our object list. Signed-off-by: Ilias Apalodimas --- lib/efi_selftest/efi_selftest_manageprotocols.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/efi_selftest/efi_selftest_manageprotocols.c b/lib/efi_selftest/efi_selftest_manageprotocols.c index 8edb1e4d467..097b2ae3545 100644 --- a/lib/efi_selftest/efi_selftest_manageprotocols.c +++ b/lib/efi_selftest/efi_selftest_manageprotocols.c @@ -79,6 +79,8 @@ static int setup(const efi_handle_t img_handle, efi_status_t ret; efi_handle_t handle; + handle1 = NULL; + handle2 = NULL; boottime = systable->boottime; ret = boottime->install_protocol_interface(&handle1, &guid3, -- cgit v1.2.3