]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
efi_loader: check the status of disconnected drivers
authorIlias Apalodimas <ilias.apalodimas@linaro.org>
Tue, 20 Jun 2023 06:19:29 +0000 (09:19 +0300)
committerHeinrich Schuchardt <heinrich.schuchardt@canonical.com>
Sat, 15 Jul 2023 09:20:41 +0000 (11:20 +0200)
efi_uninstall_protocol() calls efi_disconnect_all_drivers() but never
checks the return value.  Instead it tries to identify protocols that
are still open after closing the ones that were opened with
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL, EFI_OPEN_PROTOCOL_GET_PROTOCOL
and EFI_OPEN_PROTOCOL_TEST_PROTOCOL.

Instead of doing that,  check the return value early and exit if
disconnecting the drivers failed.  Also reconnect all the drivers of
a handle if protocols are still found on the handle after disconnecting
controllers and closing the remaining protocols.

While at it fix a memory leak and properly free the opened protocol
information when closing a protocol.

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
lib/efi_loader/efi_boottime.c

index 5e932ee273be69038da783cea6d25912de4f6395..d294db9d8c121777df7817631081718fdbf7d251 100644 (file)
@@ -1374,17 +1374,23 @@ static efi_status_t efi_uninstall_protocol
        if (r != EFI_SUCCESS)
                goto out;
        /* Disconnect controllers */
-       efi_disconnect_all_drivers(efiobj, protocol, NULL);
+       r = efi_disconnect_all_drivers(efiobj, protocol, NULL);
+       if (r != EFI_SUCCESS) {
+               r = EFI_ACCESS_DENIED;
+               goto out;
+       }
        /* Close protocol */
        list_for_each_entry_safe(item, pos, &handler->open_infos, link) {
                if (item->info.attributes ==
                        EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL ||
                    item->info.attributes == EFI_OPEN_PROTOCOL_GET_PROTOCOL ||
                    item->info.attributes == EFI_OPEN_PROTOCOL_TEST_PROTOCOL)
-                       list_del(&item->link);
+                       efi_delete_open_info(item);
        }
+       /* if agents didn't close the protocols properly */
        if (!list_empty(&handler->open_infos)) {
                r =  EFI_ACCESS_DENIED;
+               EFI_CALL(efi_connect_controller(handle, NULL, NULL, true));
                goto out;
        }
        r = efi_remove_protocol(handle, protocol, protocol_interface);