[U-Boot] [PATCH 2/2] efi_loader: delete handles

Heinrich Schuchardt xypron.glpk at gmx.de
Fri Sep 28 20:14:17 UTC 2018


When the last protocol interface has been uninstalled remove the handle.

Adjust ReinstallProtocol so that it does not remove the handle.

Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
 lib/efi_loader/efi_boottime.c | 81 ++++++++++++++++++++++++++---------
 1 file changed, 61 insertions(+), 20 deletions(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 5acd04b3842..b716498fbaa 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1155,21 +1155,19 @@ static efi_status_t efi_disconnect_all_drivers
 }
 
 /**
- * efi_uninstall_protocol_interface() - uninstall protocol interface
+ * efi_uninstall_protocol() - uninstall protocol interface
+ *
  * @handle:             handle from which the protocol shall be removed
  * @protocol:           GUID of the protocol to be removed
  * @protocol_interface: interface to be removed
  *
- * This function implements the UninstallProtocolInterface service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
+ * This function DOES NOT delete a handle without installed protocol.
  *
  * Return: status code
  */
-static efi_status_t EFIAPI efi_uninstall_protocol_interface(
-				efi_handle_t handle, const efi_guid_t *protocol,
-				void *protocol_interface)
+static efi_status_t efi_uninstall_protocol
+			(efi_handle_t handle, const efi_guid_t *protocol,
+			 void *protocol_interface)
 {
 	struct efi_object *efiobj;
 	struct efi_handler *handler;
@@ -1177,8 +1175,6 @@ static efi_status_t EFIAPI efi_uninstall_protocol_interface(
 	struct efi_open_protocol_info_item *pos;
 	efi_status_t r;
 
-	EFI_ENTRY("%p, %pUl, %p", handle, protocol, protocol_interface);
-
 	/* Check handle */
 	efiobj = efi_search_obj(handle);
 	if (!efiobj) {
@@ -1209,7 +1205,41 @@ static efi_status_t EFIAPI efi_uninstall_protocol_interface(
 	}
 	r = efi_remove_protocol(handle, protocol, protocol_interface);
 out:
-	return EFI_EXIT(r);
+	return r;
+}
+
+/**
+ * efi_uninstall_protocol_interface() - uninstall protocol interface
+ * @handle:             handle from which the protocol shall be removed
+ * @protocol:           GUID of the protocol to be removed
+ * @protocol_interface: interface to be removed
+ *
+ * This function implements the UninstallProtocolInterface service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_uninstall_protocol_interface
+			(efi_handle_t handle, const efi_guid_t *protocol,
+			 void *protocol_interface)
+{
+	efi_status_t ret;
+
+	EFI_ENTRY("%p, %pUl, %p", handle, protocol, protocol_interface);
+
+	ret = efi_uninstall_protocol(handle, protocol, protocol_interface);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	/* If the last protocol has been removed, delete the handle. */
+	if (list_empty(&handle->protocols)) {
+		list_del(&handle->link);
+		free(handle);
+	}
+out:
+	return EFI_EXIT(ret);
 }
 
 /**
@@ -2357,16 +2387,21 @@ static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
 		if (!protocol)
 			break;
 		protocol_interface = efi_va_arg(argptr, void*);
-		r = EFI_CALL(efi_uninstall_protocol_interface(
-						handle, protocol,
-						protocol_interface));
+		r = efi_uninstall_protocol(handle, protocol,
+					   protocol_interface);
 		if (r != EFI_SUCCESS)
 			break;
 		i++;
 	}
 	efi_va_end(argptr);
-	if (r == EFI_SUCCESS)
+	if (r == EFI_SUCCESS) {
+		/* If the last protocol has been removed, delete the handle. */
+		if (list_empty(&handle->protocols)) {
+			list_del(&handle->link);
+			free(handle);
+		}
 		return EFI_EXIT(r);
+	}
 
 	/* If an error occurred undo all changes. */
 	efi_va_start(argptr, handle);
@@ -2828,13 +2863,19 @@ static efi_status_t EFIAPI efi_reinstall_protocol_interface(
 
 	EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface,
 		  new_interface);
-	ret = EFI_CALL(efi_uninstall_protocol_interface(handle, protocol,
-							old_interface));
+
+	/* Uninstall protocol but do not delete handle */
+	ret = efi_uninstall_protocol(handle, protocol, old_interface);
 	if (ret != EFI_SUCCESS)
 		goto out;
-	ret = EFI_CALL(efi_install_protocol_interface(&handle, protocol,
-						      EFI_NATIVE_INTERFACE,
-						      new_interface));
+
+	/* Install the new protocol */
+	ret = efi_add_protocol(handle, protocol, new_interface);
+	/*
+	 * The UEFI spec does not specify what should happen to the handle
+	 * if in case of an error no protocol interface remains on the handle.
+	 * So let's do nothing here.
+	 */
 	if (ret != EFI_SUCCESS)
 		goto out;
 	/*
-- 
2.19.0



More information about the U-Boot mailing list