diff options
author | xypron.glpk@gmx.de <xypron.glpk@gmx.de> | 2017-07-13 23:24:32 +0200 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2017-07-25 10:03:50 +0200 |
commit | c0ebfc8664d9b533ce956547abb4377188bf7f07 (patch) | |
tree | a182d9f3ac8ec117e6f1d4ea88c490bbe662abf0 /lib/efi_loader/efi_boottime.c | |
parent | b521d29eb1b0dd7be8ee306729f93d964c4c0288 (diff) |
efi_loader: implement ProtocolsPerHandle
Boot service ProtocolsPerHandle is implemented in
efi_protocols_per_handle.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'lib/efi_loader/efi_boottime.c')
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 45 |
1 files changed, 44 insertions, 1 deletions
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( |