]> git.sur5r.net Git - u-boot/blobdiff - lib/efi_loader/efi_boottime.c
efi_loader: helper functions for protocol management
[u-boot] / lib / efi_loader / efi_boottime.c
index 98477dfed676f26003d149982b578a8ee48ae61c..e372c8bb94f05e2df55b1a540abe0ef687e8ca0d 100644 (file)
@@ -702,6 +702,125 @@ struct efi_object *efi_search_obj(const void *handle)
        return NULL;
 }
 
+/*
+ * 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.
  *