From c0ebfc8664d9b533ce956547abb4377188bf7f07 Mon Sep 17 00:00:00 2001 From: "xypron.glpk@gmx.de" Date: Thu, 13 Jul 2017 23:24:32 +0200 Subject: [PATCH] efi_loader: implement ProtocolsPerHandle Boot service ProtocolsPerHandle is implemented in efi_protocols_per_handle. Signed-off-by: Heinrich Schuchardt Signed-off-by: Alexander Graf --- lib/efi_loader/efi_boottime.c | 45 ++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index e0aead47c9..97be7b82e4 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -865,10 +865,53 @@ static efi_status_t EFIAPI efi_protocols_per_handle(void *handle, efi_guid_t ***protocol_buffer, unsigned long *protocol_buffer_count) { + unsigned long buffer_size; + struct efi_object *efiobj; + unsigned long i, j; + struct list_head *lhandle; + efi_status_t r; + EFI_ENTRY("%p, %p, %p", handle, protocol_buffer, protocol_buffer_count); + + if (!handle || !protocol_buffer || !protocol_buffer_count) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + *protocol_buffer = NULL; *protocol_buffer_count = 0; - return EFI_EXIT(EFI_OUT_OF_RESOURCES); + list_for_each(lhandle, &efi_obj_list) { + efiobj = list_entry(lhandle, struct efi_object, link); + + if (efiobj->handle != handle) + continue; + + /* Count protocols */ + for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { + if (efiobj->protocols[i].guid) + ++*protocol_buffer_count; + } + /* Copy guids */ + if (*protocol_buffer_count) { + buffer_size = sizeof(efi_guid_t *) * + *protocol_buffer_count; + r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, + buffer_size, + (void **)protocol_buffer); + if (r != EFI_SUCCESS) + return EFI_EXIT(r); + j = 0; + for (i = 0; i < ARRAY_SIZE(efiobj->protocols); ++i) { + if (efiobj->protocols[i].guid) { + (*protocol_buffer)[j] = (void *) + efiobj->protocols[i].guid; + ++j; + } + } + } + break; + } + + return EFI_EXIT(EFI_SUCCESS); } static efi_status_t EFIAPI efi_locate_handle_buffer( -- 2.39.5