[U-Boot] [PATCH 0/4] implement ReinstallProtocolInterface

This patch series implements the ReinstallProtocolInterface interface and provides a unit test.
UninstallProtocolInterface now checks the interface being uninstalled.
Heinrich Schuchardt (4): efi_selftest: correct efi_selftest_manageprotocols efi_loader: check interface when uninstalling protocol efi_loader: implement ReinstallProtocolInterface efi_selftest: test ReinstallProtocolInterface
lib/efi_loader/efi_boottime.c | 68 ++++++++++++------- lib/efi_selftest/efi_selftest_controllers.c | 35 +++++++++- .../efi_selftest_manageprotocols.c | 2 +- 3 files changed, 78 insertions(+), 27 deletions(-)

Pass the correct interface when uninstalling a protocol.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- lib/efi_selftest/efi_selftest_manageprotocols.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/efi_selftest/efi_selftest_manageprotocols.c b/lib/efi_selftest/efi_selftest_manageprotocols.c index 3e4755c25e9..44b8da3ba5d 100644 --- a/lib/efi_selftest/efi_selftest_manageprotocols.c +++ b/lib/efi_selftest/efi_selftest_manageprotocols.c @@ -335,7 +335,7 @@ static int execute(void) return EFI_ST_FAILURE; } ret = boottime->uninstall_protocol_interface(handle1, &guid3, - &interface1); + &interface3); if (ret != EFI_SUCCESS) { efi_st_error("UninstallProtocolInterface failed\n"); return EFI_ST_FAILURE;

The interface has to be checked in UninstallProtocolInterface.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- lib/efi_loader/efi_boottime.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 5e4089df621..bfaef29d3e6 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -494,6 +494,8 @@ efi_status_t efi_remove_protocol(const efi_handle_t handle, return ret; if (guidcmp(handler->guid, protocol)) return EFI_INVALID_PARAMETER; + if (handler->protocol_interface != protocol_interface) + return EFI_INVALID_PARAMETER; list_del(&handler->link); free(handler); return EFI_SUCCESS;

The ReinstallProtocolInterface boot time service is implemented.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- lib/efi_loader/efi_boottime.c | 66 +++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 23 deletions(-)
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index bfaef29d3e6..8abbdfcec4c 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1022,29 +1022,6 @@ out: return EFI_EXIT(r); }
-/* - * Reinstall protocol interface. - * - * This function implements the ReinstallProtocolInterface service. - * See the Unified Extensible Firmware Interface (UEFI) specification - * for details. - * - * @handle handle on which the protocol shall be - * reinstalled - * @protocol GUID of the protocol to be installed - * @old_interface interface to be removed - * @new_interface interface to be installed - * @return status code - */ -static efi_status_t EFIAPI efi_reinstall_protocol_interface( - efi_handle_t handle, const efi_guid_t *protocol, - void *old_interface, void *new_interface) -{ - EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface, - new_interface); - return EFI_EXIT(EFI_ACCESS_DENIED); -} - /* * Get all drivers associated to a controller. * The allocated buffer has to be freed with free(). @@ -2775,6 +2752,49 @@ out: return EFI_EXIT(ret); }
+/* + * Reinstall protocol interface. + * + * This function implements the ReinstallProtocolInterface service. + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * The old interface is uninstalled. The new interface is installed. + * Drivers are connected. + * + * @handle handle on which the protocol shall be + * reinstalled + * @protocol GUID of the protocol to be installed + * @old_interface interface to be removed + * @new_interface interface to be installed + * @return status code + */ +static efi_status_t EFIAPI efi_reinstall_protocol_interface( + efi_handle_t handle, const efi_guid_t *protocol, + void *old_interface, void *new_interface) +{ + efi_status_t ret; + + EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface, + new_interface); + ret = EFI_CALL(efi_uninstall_protocol_interface(handle, protocol, + old_interface)); + if (ret != EFI_SUCCESS) + goto out; + ret = EFI_CALL(efi_install_protocol_interface(&handle, protocol, + EFI_NATIVE_INTERFACE, + new_interface)); + if (ret != EFI_SUCCESS) + goto out; + /* + * The returned status code has to be ignored. + * Do not create an error if no suitable driver for the handle exists. + */ + EFI_CALL(efi_connect_controller(handle, NULL, NULL, true)); +out: + return EFI_EXIT(ret); +} + /* * Get all child controllers associated to a driver. * The allocated buffer has to be freed with free().

Add a test for ReinstallProtocolInterface to the controller selftest.
As ReinstallProtocolInterface has to connect controllers to the new interface is does not fit to the manage protocols selftest.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- lib/efi_selftest/efi_selftest_controllers.c | 35 +++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-)
diff --git a/lib/efi_selftest/efi_selftest_controllers.c b/lib/efi_selftest/efi_selftest_controllers.c index e30c11b1e45..ceefa03444f 100644 --- a/lib/efi_selftest/efi_selftest_controllers.c +++ b/lib/efi_selftest/efi_selftest_controllers.c @@ -6,7 +6,7 @@ * * This unit test checks the following protocol services: * ConnectController, DisconnectController, - * InstallProtocol, UninstallProtocol, + * InstallProtocol, ReinstallProtocol, UninstallProtocol, * OpenProtocol, CloseProtcol, OpenProtocolInformation */
@@ -14,6 +14,8 @@
#define NUMBER_OF_CHILD_CONTROLLERS 4
+static int interface1 = 1; +static int interface2 = 2; static struct efi_boot_services *boottime; const efi_guid_t guid_driver_binding_protocol = EFI_DRIVER_BINDING_PROTOCOL_GUID; @@ -271,7 +273,7 @@ static int setup(const efi_handle_t img_handle, /* Create controller handle */ ret = boottime->install_protocol_interface( &handle_controller, &guid_controller, - EFI_NATIVE_INTERFACE, NULL); + EFI_NATIVE_INTERFACE, &interface1); if (ret != EFI_SUCCESS) { efi_st_error("InstallProtocolInterface failed\n"); return EFI_ST_FAILURE; @@ -299,6 +301,7 @@ static int setup(const efi_handle_t img_handle, * Disconnect and destroy the remaining child controllers. * * Connect a controller to a driver. + * Reinstall the driver protocol on the controller. * Uninstall the driver protocol from the controller. */ static int execute(void) @@ -361,9 +364,35 @@ static int execute(void) efi_st_error("Number of children %u != %u\n", (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS); } + /* Try to uninstall controller protocol using the wrong interface */ + ret = boottime->uninstall_protocol_interface(handle_controller, + &guid_controller, + &interface2); + if (ret == EFI_SUCCESS) { + efi_st_error( + "Interface not checked when uninstalling protocol\n"); + return EFI_ST_FAILURE; + } + /* Reinstall controller protocol */ + ret = boottime->reinstall_protocol_interface(handle_controller, + &guid_controller, + &interface1, + &interface2); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to reinstall protocols\n"); + return EFI_ST_FAILURE; + } + /* Check number of child controllers */ + ret = count_child_controllers(handle_controller, &guid_controller, + &count); + if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) { + efi_st_error("Number of children %u != %u\n", + (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS); + } /* Uninstall controller protocol */ ret = boottime->uninstall_protocol_interface(handle_controller, - &guid_controller, NULL); + &guid_controller, + &interface2); if (ret != EFI_SUCCESS) { efi_st_error("Failed to uninstall protocols\n"); return EFI_ST_FAILURE;
participants (1)
-
Heinrich Schuchardt