summaryrefslogtreecommitdiff
path: root/lib/efi_loader/efi_boottime.c
diff options
context:
space:
mode:
authorxypron.glpk@gmx.de <xypron.glpk@gmx.de>2017-07-13 23:24:32 +0200
committerAlexander Graf <agraf@suse.de>2017-07-25 10:03:50 +0200
commitc0ebfc8664d9b533ce956547abb4377188bf7f07 (patch)
treea182d9f3ac8ec117e6f1d4ea88c490bbe662abf0 /lib/efi_loader/efi_boottime.c
parentb521d29eb1b0dd7be8ee306729f93d964c4c0288 (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.c45
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(