Signed-off-by: Heinrich Schuchardt <xypron.g...@gmx.de> --- lib/efi_loader/efi_boottime.c | 77 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-)
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 1069da7d79..c5a17b6252 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1052,9 +1052,84 @@ static efi_status_t EFIAPI efi_disconnect_controller(void *controller_handle, void *driver_image_handle, void *child_handle) { + struct efi_driver_binding_protocol *binding_protocol; + efi_handle_t child_handle_buffer; + unsigned long driver_count; + efi_handle_t *driver_handle_buffer; + size_t i; + UINTN number_of_children; + efi_status_t r; + size_t stop_count = 0; + EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle, child_handle); - return EFI_EXIT(EFI_INVALID_PARAMETER); + + if (!efi_search_obj(controller_handle)) { + r = EFI_INVALID_PARAMETER; + goto out; + } + + /* Create list of driver handles */ + if (driver_image_handle) { + driver_handle_buffer = &driver_image_handle, + driver_count = 1; + /* Check that the handle supports driver binding protocol */ + r = efi_search_protocol(driver_image_handle, + &efi_guid_driver_binding_protocol, + NULL); + } else { + /* Get buffer with all handles with driver binding protocol */ + r = EFI_CALL(efi_locate_handle_buffer( + by_protocol, &efi_guid_driver_binding_protocol, + NULL, &driver_count, &driver_handle_buffer)); + } + if (r != EFI_SUCCESS) + goto out; + + /* Create list of child handles */ + if (child_handle) { + number_of_children = 1; + child_handle_buffer = &child_handle; + } else { + /* + * We do not fully support child handles. + * + * It is unclear from which handle and which protocols the + * list of child controllers should be collected. + */ + number_of_children = 0; + child_handle_buffer = NULL; + } + + for (i = 0; i < driver_count; ++i) { + r = EFI_CALL(efi_open_protocol( + driver_handle_buffer[i], + &efi_guid_driver_binding_protocol, + (void **)&binding_protocol, + driver_handle_buffer[i], NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL)); + if (r != EFI_SUCCESS) + continue; + + r = EFI_CALL(binding_protocol->stop(binding_protocol, + controller_handle, + number_of_children, + child_handle_buffer)); + if (r == EFI_SUCCESS) + ++stop_count; + EFI_CALL(efi_close_protocol(driver_handle_buffer[i], + &efi_guid_driver_binding_protocol, + driver_handle_buffer[i], NULL)); + } + + if (driver_image_handle) + efi_free_pool(driver_handle_buffer); + if (stop_count) + r = EFI_SUCCESS; + else + r = EFI_NOT_FOUND; +out: + return EFI_EXIT(r); } efi_status_t EFIAPI efi_close_protocol(void *handle, const efi_guid_t *protocol, -- 2.14.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot