+
+ if (!handle || !protocol_guid)
+ return EFI_INVALID_PARAMETER;
+ efiobj = efi_search_obj(handle);
+ if (!efiobj)
+ return EFI_INVALID_PARAMETER;
+ list_for_each(lhandle, &efiobj->protocols) {
+ struct efi_handler *protocol;
+
+ protocol = list_entry(lhandle, struct efi_handler, link);
+ 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;
+
+ 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;
+ handler->guid = protocol;
+ handler->protocol_interface = protocol_interface;
+ list_add_tail(&handler->link, &efiobj->protocols);
+ return EFI_SUCCESS;
+}
+
+/*
+ * 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 (guidcmp(handler->guid, protocol))
+ return EFI_INVALID_PARAMETER;
+ list_del(&handler->link);
+ free(handler);
+ 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 list_head *lhandle;
+ struct list_head *pos;
+
+ efiobj = efi_search_obj(handle);
+ if (!efiobj)
+ return EFI_INVALID_PARAMETER;
+ list_for_each_safe(lhandle, pos, &efiobj->protocols) {
+ struct efi_handler *protocol;
+ efi_status_t ret;
+
+ protocol = list_entry(lhandle, struct efi_handler, link);
+
+ ret = efi_remove_protocol(handle, protocol->guid,
+ protocol->protocol_interface);
+ if (ret != EFI_SUCCESS)
+ return ret;
+ }
+ return EFI_SUCCESS;
+}
+
+/*
+ * Install protocol interface.
+ *
+ * This function implements the InstallProtocolInterface service.
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @handle handle on which the protocol shall be installed
+ * @protocol GUID of the protocol to be installed
+ * @protocol_interface_type type of the interface to be installed,
+ * always EFI_NATIVE_INTERFACE
+ * @protocol_interface interface of the protocol implementation
+ * @return status code
+ */
+static efi_status_t EFIAPI efi_install_protocol_interface(
+ void **handle, const efi_guid_t *protocol,
+ int protocol_interface_type, void *protocol_interface)
+{