[U-Boot] [PATCH 0/2] efi_loader: registration key in LocateProtocol()

In LocateProtocol() implement searching by the registration key returned by RegisterNotifyProtocol().
With the patch series the UEFI SCT tests for LocateProtocol() are passed without error.
Factor our a common function module efi_check_register_notify_event() used by LocateHandle() and LocateProtocol().
Heinrich Schuchardt (2): efi_loader: factor our efi_check_register_notify_event() efi_loader: registration key in LocateProtocol()
lib/efi_loader/efi_boottime.c | 80 +++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 18 deletions(-)
-- 2.20.1

The code to check if a registration key is a valid key returned by RegisterProtocolNotify() can be reused. So let us factor it out into a new function efi_check_register_notify_event().
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- lib/efi_loader/efi_boottime.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-)
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 1ccf54c386..dd5f706af7 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1388,6 +1388,27 @@ static int efi_search(enum efi_locate_search_type search_type, } }
+/** + * efi_check_register_notify_event() - check if registration key is valid + * + * Check that a pointer is a valid registration key as returned by + * RegisterProtocolNotify(). + * + * @key: registration key + * Return: valid registration key or NULL + */ +static struct efi_register_notify_event *efi_check_register_notify_event + (void *key) +{ + struct efi_register_notify_event *event; + + list_for_each_entry(event, &efi_register_notify_events, link) { + if (event == (struct efi_register_notify_event *)key) + return event; + } + return NULL; +} + /** * efi_locate_handle() - locate handles implementing a protocol * @@ -1409,7 +1430,7 @@ static efi_status_t efi_locate_handle( { struct efi_object *efiobj; efi_uintn_t size = 0; - struct efi_register_notify_event *item, *event = NULL; + struct efi_register_notify_event *event; struct efi_protocol_notification *handle = NULL;
/* Check parameters */ @@ -1420,13 +1441,7 @@ static efi_status_t efi_locate_handle( if (!search_key) return EFI_INVALID_PARAMETER; /* Check that the registration key is valid */ - list_for_each_entry(item, &efi_register_notify_events, link) { - if (item == - (struct efi_register_notify_event *)search_key) { - event = item; - break; - } - } + event = efi_check_register_notify_event(search_key); if (!event) return EFI_INVALID_PARAMETER; break; -- 2.20.1

In LocateProtocol() implement searching by the registration key returned by RegisterNotifyProtocol().
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- lib/efi_loader/efi_boottime.c | 49 ++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 10 deletions(-)
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index dd5f706af7..ad38b816d3 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2259,29 +2259,58 @@ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol, void *registration, void **protocol_interface) { - struct list_head *lhandle; + struct efi_handler *handler; efi_status_t ret; + struct efi_object *efiobj;
EFI_ENTRY("%pUl, %p, %p", protocol, registration, protocol_interface);
+ /* + * The UEFI spec explicitly requires a protocol even if a registration + * key is provided. This differs from the logic in LocateHandle(). + */ if (!protocol || !protocol_interface) return EFI_EXIT(EFI_INVALID_PARAMETER);
- list_for_each(lhandle, &efi_obj_list) { - struct efi_object *efiobj; - struct efi_handler *handler; - - efiobj = list_entry(lhandle, struct efi_object, link); + if (registration) { + struct efi_register_notify_event *event; + struct efi_protocol_notification *handle;
+ event = efi_check_register_notify_event(registration); + if (!event) + return EFI_EXIT(EFI_INVALID_PARAMETER); + /* + * The UEFI spec requires to return EFI_NOT_FOUND if no + * protocol instance matches protocol and registration. + * So let's do the same for a mismatch between protocol and + * registration. + */ + if (guidcmp(&event->protocol, protocol)) + goto not_found; + if (list_empty(&event->handles)) + goto not_found; + handle = list_first_entry(&event->handles, + struct efi_protocol_notification, + link); + efiobj = handle->handle; + list_del(&handle->link); + free(handle); ret = efi_search_protocol(efiobj, protocol, &handler); - if (ret == EFI_SUCCESS) { - *protocol_interface = handler->protocol_interface; - return EFI_EXIT(EFI_SUCCESS); + if (ret == EFI_SUCCESS) + goto found; + } else { + list_for_each_entry(efiobj, &efi_obj_list, link) { + ret = efi_search_protocol(efiobj, protocol, &handler); + if (ret == EFI_SUCCESS) + goto found; } } +not_found: *protocol_interface = NULL; - return EFI_EXIT(EFI_NOT_FOUND); +found: + *protocol_interface = handler->protocol_interface; + return EFI_EXIT(EFI_SUCCESS); }
/** -- 2.20.1
participants (1)
-
Heinrich Schuchardt