diff options
-rw-r--r-- | lib/efi_selftest/efi_selftest_controllers.c | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/lib/efi_selftest/efi_selftest_controllers.c b/lib/efi_selftest/efi_selftest_controllers.c index 63e674b..02f1957 100644 --- a/lib/efi_selftest/efi_selftest_controllers.c +++ b/lib/efi_selftest/efi_selftest_controllers.c @@ -28,6 +28,7 @@ static efi_guid_t guid_child_controller = static efi_handle_t handle_controller; static efi_handle_t handle_child_controller[NUMBER_OF_CHILD_CONTROLLERS]; static efi_handle_t handle_driver; +static bool allow_removal; /* * Count child controllers @@ -85,8 +86,8 @@ static efi_status_t EFIAPI supported( controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER); switch (ret) { case EFI_ACCESS_DENIED: - case EFI_ALREADY_STARTED: return ret; + case EFI_ALREADY_STARTED: case EFI_SUCCESS: break; default: @@ -124,8 +125,8 @@ static efi_status_t EFIAPI start( controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER); switch (ret) { case EFI_ACCESS_DENIED: - case EFI_ALREADY_STARTED: return ret; + case EFI_ALREADY_STARTED: case EFI_SUCCESS: break; default: @@ -238,6 +239,9 @@ static efi_status_t EFIAPI stop( if (ret != EFI_SUCCESS) efi_st_error("Cannot free buffer\n"); + if (!allow_removal) + return EFI_DEVICE_ERROR; + /* Detach driver from controller */ ret = boottime->close_protocol( controller_handle, &guid_controller, @@ -342,6 +346,7 @@ static int execute(void) return EFI_ST_FAILURE; } /* Destroy remaining child controllers and disconnect controller */ + allow_removal = true; ret = boottime->disconnect_controller(handle_controller, NULL, NULL); if (ret != EFI_SUCCESS) { efi_st_error("Failed to disconnect controller\n"); @@ -393,7 +398,40 @@ static int execute(void) efi_st_error("Number of children %u != %u\n", (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS); } - /* Uninstall controller protocol */ + + allow_removal = false; + /* Try to uninstall controller protocol using the wrong interface */ + ret = boottime->uninstall_protocol_interface(handle_controller, + &guid_controller, + &interface1); + if (ret != EFI_NOT_FOUND) { + efi_st_error("Interface not checked when uninstalling protocol\n"); + return EFI_ST_FAILURE; + } + + /* + * Uninstall a protocol while Disconnect controller won't + * allow it. + */ + ret = boottime->uninstall_protocol_interface(handle_controller, + &guid_controller, + &interface2); + if (ret != EFI_ACCESS_DENIED) { + efi_st_error("Uninstall protocol interface failed\n"); + return EFI_ST_FAILURE; + } + /* + * Check number of child controllers and make sure children have + * been reconnected + */ + 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); + } + + allow_removal = true; ret = boottime->uninstall_protocol_interface(handle_controller, &guid_controller, &interface2); |