[U-Boot] [RFC 01/10] efi_loader: add back optional efi_handler::open()

Rob Clark robdclark at gmail.com
Thu Jul 27 21:37:58 UTC 2017


In some cases it is useful to defer creation of the protocol interface
object.  So add back an optional ->open() hook that is used if
protcol_interface is NULL.

I've slightly simplified the fxn ptr signature to remove unneeded args,
and so compiler will complain if patches that used the "old way" are,
and which do not need this extra complexity, are rebased.

Signed-off-by: Rob Clark <robdclark at gmail.com>
---
 include/efi_loader.h          | 12 +++++++++++-
 lib/efi_loader/efi_boottime.c | 30 ++++++++++++++++++++++++------
 2 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 037cc7c543..03c4ed5e1c 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -70,10 +70,17 @@ extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
 /*
  * When the UEFI payload wants to open a protocol on an object to get its
  * interface (usually a struct with callback functions), this struct maps the
- * protocol GUID to the respective protocol interface */
+ * protocol GUID to the respective protocol interface.
+ *
+ * The optional ->open() fxn can be used for cases where the protocol
+ * interface is constructed on-demand, and is called if protocol_interface
+ * is NULL.
+ */
 struct efi_handler {
 	const efi_guid_t *guid;
 	void *protocol_interface;
+	efi_status_t (EFIAPI *open)(void *handle, const efi_guid_t *protocol,
+			void **protocol_interface);
 };
 
 /*
@@ -191,6 +198,9 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
 int efi_memory_init(void);
 /* Adds new or overrides configuration table entry to the system table */
 efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table);
+efi_status_t efi_get_protocol(struct efi_object *efiobj,
+			      struct efi_handler *handler,
+			      void **protocol_interface);
 
 #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
 extern void *efi_bounce_buffer;
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index de338f009c..9ce550f5d2 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1004,6 +1004,23 @@ out:
 	return EFI_EXIT(r);
 }
 
+efi_status_t efi_get_protocol(struct efi_object *efiobj,
+			      struct efi_handler *handler,
+			      void **protocol_interface)
+{
+	efi_status_t ret = EFI_SUCCESS;
+
+	if (!handler->protocol_interface) {
+		ret = handler->open(efiobj->handle,
+				handler->guid,
+				&handler->protocol_interface);
+	}
+	*protocol_interface =
+		handler->protocol_interface;
+
+	return ret;
+}
+
 static efi_status_t EFIAPI efi_locate_protocol(efi_guid_t *protocol,
 					       void *registration,
 					       void **protocol_interface)
@@ -1026,9 +1043,10 @@ static efi_status_t EFIAPI efi_locate_protocol(efi_guid_t *protocol,
 			if (!handler->guid)
 				continue;
 			if (!guidcmp(handler->guid, protocol)) {
-				*protocol_interface =
-					handler->protocol_interface;
-				return EFI_EXIT(EFI_SUCCESS);
+				efi_status_t ret;
+				ret = efi_get_protocol(efiobj, handler,
+						       protocol_interface);
+				return EFI_EXIT(ret);
 			}
 		}
 	}
@@ -1162,12 +1180,12 @@ static efi_status_t EFIAPI efi_open_protocol(
 			if (!hprotocol)
 				continue;
 			if (!guidcmp(hprotocol, protocol)) {
+				r = EFI_SUCCESS;
 				if (attributes !=
 				    EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
-					*protocol_interface =
-						handler->protocol_interface;
+					r = efi_get_protocol(efiobj, handler,
+							     protocol_interface);
 				}
-				r = EFI_SUCCESS;
 				goto out;
 			}
 		}
-- 
2.13.0



More information about the U-Boot mailing list