summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2017-10-26 19:25:53 +0200
committerAlexander Graf <agraf@suse.de>2017-12-01 13:22:56 +0100
commit3f79a2b532d8deafd5293f9f7e492d30fc6e339d (patch)
tree11f0ece91f565b1b75c19211b710c16c1d6cc73c
parent49d62cb0937bfdb1774a2c5c244595d9a09815b3 (diff)
downloadu-boot-3f79a2b532d8deafd5293f9f7e492d30fc6e339d.tar.gz
u-boot-3f79a2b532d8deafd5293f9f7e492d30fc6e339d.tar.xz
u-boot-3f79a2b532d8deafd5293f9f7e492d30fc6e339d.zip
efi_loader: helper functions for protocol management
This patch provides helper functions to manage protocols. efi_search_protocol - find a protocol on a handle efi_add_protocol - install a protocol on a handle efi_remove_protocol - remove a protocol from a handle efi_remove_all_protocols - remove all protocols from a handle Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r--include/efi_loader.h12
-rw-r--r--lib/efi_loader/efi_boottime.c119
2 files changed, 131 insertions, 0 deletions
diff --git a/include/efi_loader.h b/include/efi_loader.h
index a5aae1b87e..934f64dccb 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -196,6 +196,18 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path);
efi_status_t efi_create_handle(void **handle);
/* Call this to validate a handle and find the EFI object for it */
struct efi_object *efi_search_obj(const void *handle);
+/* Find a protocol on a handle */
+efi_status_t efi_search_protocol(const void *handle,
+ const efi_guid_t *protocol_guid,
+ struct efi_handler **handler);
+/* Install new protocol on a handle */
+efi_status_t efi_add_protocol(const void *handle, const efi_guid_t *protocol,
+ void *protocol_interface);
+/* Delete protocol from a handle */
+efi_status_t efi_remove_protocol(const void *handle, const efi_guid_t *protocol,
+ void *protocol_interface);
+/* Delete all protocols from a handle */
+efi_status_t efi_remove_all_protocols(const void *handle);
/* Call this to create an event */
efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
void (EFIAPI *notify_function) (
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 98477dfed6..e372c8bb94 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -703,6 +703,125 @@ struct efi_object *efi_search_obj(const void *handle)
}
/*
+ * Find a protocol on a handle.
+ *
+ * @handle handle
+ * @protocol_guid GUID of the protocol
+ * @handler reference to the protocol
+ * @return status code
+ */
+efi_status_t efi_search_protocol(const void *handle,
+ const efi_guid_t *protocol_guid,
+ struct efi_handler **handler)
+{
+ struct efi_object *efiobj;
+ size_t i;
+ struct efi_handler *protocol;
+
+ if (!handle || !protocol_guid)
+ return EFI_INVALID_PARAMETER;
+ efiobj = efi_search_obj(handle);
+ if (!efiobj)
+ return EFI_INVALID_PARAMETER;
+ for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
+ protocol = &efiobj->protocols[i];
+ if (!protocol->guid)
+ continue;
+ if (!guidcmp(protocol->guid, protocol_guid)) {
+ if (handler)
+ *handler = protocol;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+/*
+ * Install new protocol on a handle.
+ *
+ * @handle handle on which the protocol shall be installed
+ * @protocol GUID of the protocol to be installed
+ * @protocol_interface interface of the protocol implementation
+ * @return status code
+ */
+efi_status_t efi_add_protocol(const void *handle, const efi_guid_t *protocol,
+ void *protocol_interface)
+{
+ struct efi_object *efiobj;
+ struct efi_handler *handler;
+ efi_status_t ret;
+ size_t i;
+
+ efiobj = efi_search_obj(handle);
+ if (!efiobj)
+ return EFI_INVALID_PARAMETER;
+ ret = efi_search_protocol(handle, protocol, NULL);
+ if (ret != EFI_NOT_FOUND)
+ return EFI_INVALID_PARAMETER;
+ handler = calloc(1, sizeof(struct efi_handler));
+ if (!handler)
+ return EFI_OUT_OF_RESOURCES;
+ /* Install protocol in first empty slot. */
+ for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
+ handler = &efiobj->protocols[i];
+ if (handler->guid)
+ continue;
+ handler->guid = protocol;
+ handler->protocol_interface = protocol_interface;
+ return EFI_SUCCESS;
+ }
+ return EFI_OUT_OF_RESOURCES;
+}
+
+/*
+ * Delete protocol from a handle.
+ *
+ * @handle handle from which the protocol shall be deleted
+ * @protocol GUID of the protocol to be deleted
+ * @protocol_interface interface of the protocol implementation
+ * @return status code
+ */
+efi_status_t efi_remove_protocol(const void *handle, const efi_guid_t *protocol,
+ void *protocol_interface)
+{
+ struct efi_handler *handler;
+ efi_status_t ret;
+
+ ret = efi_search_protocol(handle, protocol, &handler);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ if (handler->protocol_interface != protocol_interface)
+ return EFI_NOT_FOUND;
+ handler->guid = NULL;
+ handler->protocol_interface = NULL;
+ return EFI_SUCCESS;
+}
+
+/*
+ * Delete all protocols from a handle.
+ *
+ * @handle handle from which the protocols shall be deleted
+ * @return status code
+ */
+efi_status_t efi_remove_all_protocols(const void *handle)
+{
+ struct efi_object *efiobj;
+ struct efi_handler *handler;
+ size_t i;
+
+ efiobj = efi_search_obj(handle);
+ if (!efiobj)
+ return EFI_INVALID_PARAMETER;
+
+ for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
+ handler = &efiobj->protocols[i];
+ handler->guid = NULL;
+ handler->protocol_interface = NULL;
+ }
+ return EFI_SUCCESS;
+}
+
+/*
* Install protocol interface.
*
* This function implements the InstallProtocolInterface service.