All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/9] EFI protocol services
@ 2017-07-05 16:18 Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 1/9] efi_loader: refactor efi_open_protocol Heinrich Schuchardt
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2017-07-05 16:18 UTC (permalink / raw)
  To: u-boot

Currently only a small fraction of the UEFI specification is
implemented in U-Boot. It is sufficient to load grub but it
fails on iPXE.

With this patch series all EFI protocol services are implemented
that are needed to reach the console prompt of the
bin-<ARCH>-efi/snponly.efi target of iPXE.

Futher patches for event services are needed to use the iPXE
console. These will be provided in a separate patch series.

The 1st patch refactors efi_open_protocol to enable the implementation
of InstallProtocolInterface. This patch eliminates the open protocol
functions in efi_disk, efi_gop, and efi_net.

The 2nd patch adds missing parameter checks to efi_open_protocol.

The 3rd patch implements InstallProtocolInteface.

The 4th patch partially implements UninstallProtocolInterface.

The 5th patch refactors efi_install_protocol_interface to make it
callable internally.

The 6th patch refactors efi_uninstall_protocol_interface to make
it callable internally.

The 7th patch implements InstallMultipleProtocolInterfaces by
calling efi_install_protocol_interface.

The 8th patch refactors efi_locate_handle to make it
callable internally.

The 9th patch implements LocateHandleBuffer.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

Heinrich Schuchardt (9):
  efi_loader: refactor efi_open_protocol
  efi_loader: efi_open_protocol: parameter checks
  efi_loader: implement InstallProtocolInterface
  efi_loader: implement UninstallProtocolInterface
  efi_loader: refactor efi_install_protocol_interface
  efi_loader: refactor efi_uninstall_protocol_interface
  efi_loader: implement InstallMultipleProtocolInterfaces
  efi_loader: refactor efi_locate_handle
  efi_loader: implement LocateHandleBuffer

 cmd/bootefi.c                 |  14 +--
 include/efi_api.h             |   2 +-
 include/efi_loader.h          |  17 +--
 lib/efi_loader/efi_boottime.c | 237 ++++++++++++++++++++++++++++++++++++++----
 lib/efi_loader/efi_disk.c     |  29 +-----
 lib/efi_loader/efi_gop.c      |   2 +-
 lib/efi_loader/efi_net.c      |  30 +-----
 7 files changed, 232 insertions(+), 99 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/9] efi_loader: refactor efi_open_protocol
  2017-07-05 16:18 [U-Boot] [PATCH 0/9] EFI protocol services Heinrich Schuchardt
@ 2017-07-05 16:18 ` Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 2/9] efi_loader: efi_open_protocol: parameter checks Heinrich Schuchardt
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2017-07-05 16:18 UTC (permalink / raw)
  To: u-boot

efi_open_protocol was implemented to call a protocol specific 'open'
function to retrieve the protocol interface.

The UEFI specification does not know of such a function.

It is not possible to implement InstallProtocolInterface with the
current design.

With the patch the protocol interface itself is stored in the list
of installed protocols of an efi_object instead of an open function.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 cmd/bootefi.c                 | 14 +++-----------
 include/efi_loader.h          | 17 ++---------------
 lib/efi_loader/efi_boottime.c | 18 ++++++++++++++----
 lib/efi_loader/efi_disk.c     | 29 +++--------------------------
 lib/efi_loader/efi_gop.c      |  2 +-
 lib/efi_loader/efi_net.c      | 30 +++---------------------------
 6 files changed, 26 insertions(+), 84 deletions(-)

diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 90ecde65d1..d80cb0723f 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -54,14 +54,6 @@ static struct efi_device_path_file_path bootefi_device_path[] = {
 	}
 };
 
-static efi_status_t EFIAPI bootefi_open_dp(void *handle, efi_guid_t *protocol,
-			void **protocol_interface, void *agent_handle,
-			void *controller_handle, uint32_t attributes)
-{
-	*protocol_interface = bootefi_device_path;
-	return EFI_SUCCESS;
-}
-
 /* The EFI loaded_image interface for the image executed via "bootefi" */
 static struct efi_loaded_image loaded_image_info = {
 	.device_handle = bootefi_device_path,
@@ -78,7 +70,7 @@ static struct efi_object loaded_image_info_obj = {
 			 * return handle which points to loaded_image_info
 			 */
 			.guid = &efi_guid_loaded_image,
-			.open = &efi_return_handle,
+			.protocol_interface = &loaded_image_info,
 		},
 		{
 			/*
@@ -86,7 +78,7 @@ static struct efi_object loaded_image_info_obj = {
 			 * bootefi_device_path
 			 */
 			.guid = &efi_guid_device_path,
-			.open = &bootefi_open_dp,
+			.protocol_interface = bootefi_device_path,
 		},
 	},
 };
@@ -99,7 +91,7 @@ static struct efi_object bootefi_device_obj = {
 			/* When asking for the device path interface, return
 			 * bootefi_device_path */
 			.guid = &efi_guid_device_path,
-			.open = &bootefi_open_dp,
+			.protocol_interface = bootefi_device_path
 		}
 	},
 };
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 99619f53a9..c620652307 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -49,15 +49,10 @@ struct efi_class_map {
 /*
  * 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 handler open function for that
- * object protocol combination.
- */
+ * protocol GUID to the respective protocol interface */
 struct efi_handler {
 	const efi_guid_t *guid;
-	efi_status_t (EFIAPI *open)(void *handle,
-			efi_guid_t *protocol, void **protocol_interface,
-			void *agent_handle, void *controller_handle,
-			uint32_t attributes);
+	void *protocol_interface;
 };
 
 /*
@@ -91,14 +86,6 @@ void efi_smbios_register(void);
 /* Called by networking code to memorize the dhcp ack package */
 void efi_net_set_dhcp_ack(void *pkt, int len);
 
-/*
- * Stub implementation for a protocol opener that just returns the handle as
- * interface
- */
-efi_status_t EFIAPI efi_return_handle(void *handle,
-		efi_guid_t *protocol, void **protocol_interface,
-		void *agent_handle, void *controller_handle,
-		uint32_t attributes);
 /* Called from places to check whether a timer expired */
 void efi_timer_check(void);
 /* PE loader implementation */
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 27e51a253f..5c72f92474 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -442,7 +442,6 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
 		.protocols = {
 			{
 				.guid = &efi_guid_loaded_image,
-				.open = &efi_return_handle,
 			},
 		},
 	};
@@ -452,6 +451,7 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy,
 	EFI_ENTRY("%d, %p, %p, %p, %ld, %p", boot_policy, parent_image,
 		  file_path, source_buffer, source_size, image_handle);
 	info = malloc(sizeof(*info));
+	loaded_image_info_obj.protocols[0].protocol_interface = info;
 	obj = malloc(sizeof(loaded_image_info_obj));
 	memset(info, 0, sizeof(*info));
 	memcpy(obj, &loaded_image_info_obj, sizeof(loaded_image_info_obj));
@@ -723,6 +723,13 @@ static efi_status_t EFIAPI efi_open_protocol(
 	EFI_ENTRY("%p, %p, %p, %p, %p, 0x%x", handle, protocol,
 		  protocol_interface, agent_handle, controller_handle,
 		  attributes);
+
+	if (!protocol_interface && attributes !=
+	    EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
+		r = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
 	list_for_each(lhandle, &efi_obj_list) {
 		struct efi_object *efiobj;
 		efiobj = list_entry(lhandle, struct efi_object, link);
@@ -736,9 +743,12 @@ static efi_status_t EFIAPI efi_open_protocol(
 			if (!hprotocol)
 				break;
 			if (!guidcmp(hprotocol, protocol)) {
-				r = handler->open(handle, protocol,
-				    protocol_interface, agent_handle,
-				    controller_handle, attributes);
+				if (attributes !=
+				    EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
+					*protocol_interface =
+						handler->protocol_interface;
+				}
+				r = EFI_SUCCESS;
 				goto out;
 			}
 		}
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 39e602a868..3ad7706472 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -35,29 +35,6 @@ struct efi_disk_obj {
 	const struct blk_desc *desc;
 };
 
-static efi_status_t EFIAPI efi_disk_open_block(void *handle,
-			efi_guid_t *protocol, void **protocol_interface,
-			void *agent_handle, void *controller_handle,
-			uint32_t attributes)
-{
-	struct efi_disk_obj *diskobj = handle;
-
-	*protocol_interface = &diskobj->ops;
-
-	return EFI_SUCCESS;
-}
-
-static efi_status_t EFIAPI efi_disk_open_dp(void *handle, efi_guid_t *protocol,
-			void **protocol_interface, void *agent_handle,
-			void *controller_handle, uint32_t attributes)
-{
-	struct efi_disk_obj *diskobj = handle;
-
-	*protocol_interface = diskobj->dp;
-
-	return EFI_SUCCESS;
-}
-
 static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this,
 			char extended_verification)
 {
@@ -210,10 +187,11 @@ static void efi_disk_add_dev(const char *name,
 	diskobj = calloc(1, objlen);
 
 	/* Fill in object data */
+	dp = (void *)&diskobj[1];
 	diskobj->parent.protocols[0].guid = &efi_block_io_guid;
-	diskobj->parent.protocols[0].open = efi_disk_open_block;
+	diskobj->parent.protocols[0].protocol_interface = &diskobj->ops;
 	diskobj->parent.protocols[1].guid = &efi_guid_device_path;
-	diskobj->parent.protocols[1].open = efi_disk_open_dp;
+	diskobj->parent.protocols[1].protocol_interface = dp;
 	diskobj->parent.handle = diskobj;
 	diskobj->ops = block_io_disk_template;
 	diskobj->ifname = if_typename;
@@ -230,7 +208,6 @@ static void efi_disk_add_dev(const char *name,
 	diskobj->ops.media = &diskobj->media;
 
 	/* Fill in device path */
-	dp = (void*)&diskobj[1];
 	diskobj->dp = dp;
 	dp[0].dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE;
 	dp[0].dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH;
diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c
index 286ad83097..c491ca0815 100644
--- a/lib/efi_loader/efi_gop.c
+++ b/lib/efi_loader/efi_gop.c
@@ -172,7 +172,7 @@ int efi_gop_register(void)
 
 	/* Fill in object data */
 	gopobj->parent.protocols[0].guid = &efi_gop_guid;
-	gopobj->parent.protocols[0].open = efi_return_handle;
+	gopobj->parent.protocols[0].open = &gopobj->ops;
 	gopobj->parent.handle = &gopobj->ops;
 	gopobj->ops.query_mode = gop_query_mode;
 	gopobj->ops.set_mode = gop_set_mode;
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
index 604ac6e040..0b949d86e8 100644
--- a/lib/efi_loader/efi_net.c
+++ b/lib/efi_loader/efi_net.c
@@ -199,30 +199,6 @@ static efi_status_t EFIAPI efi_net_receive(struct efi_simple_network *this,
 	return EFI_EXIT(EFI_SUCCESS);
 }
 
-static efi_status_t EFIAPI efi_net_open_dp(void *handle, efi_guid_t *protocol,
-			void **protocol_interface, void *agent_handle,
-			void *controller_handle, uint32_t attributes)
-{
-	struct efi_simple_network *net = handle;
-	struct efi_net_obj *netobj = container_of(net, struct efi_net_obj, net);
-
-	*protocol_interface = &netobj->dp_mac;
-
-	return EFI_SUCCESS;
-}
-
-static efi_status_t EFIAPI efi_net_open_pxe(void *handle, efi_guid_t *protocol,
-			void **protocol_interface, void *agent_handle,
-			void *controller_handle, uint32_t attributes)
-{
-	struct efi_simple_network *net = handle;
-	struct efi_net_obj *netobj = container_of(net, struct efi_net_obj, net);
-
-	*protocol_interface = &netobj->pxe;
-
-	return EFI_SUCCESS;
-}
-
 void efi_net_set_dhcp_ack(void *pkt, int len)
 {
 	int maxsize = sizeof(*dhcp_ack);
@@ -258,11 +234,11 @@ int efi_net_register(void **handle)
 
 	/* Fill in object data */
 	netobj->parent.protocols[0].guid = &efi_net_guid;
-	netobj->parent.protocols[0].open = efi_return_handle;
+	netobj->parent.protocols[0].protocol_interface = &netobj->net;
 	netobj->parent.protocols[1].guid = &efi_guid_device_path;
-	netobj->parent.protocols[1].open = efi_net_open_dp;
+	netobj->parent.protocols[1].protocol_interface = &netobj->dp_mac;
 	netobj->parent.protocols[2].guid = &efi_pxe_guid;
-	netobj->parent.protocols[2].open = efi_net_open_pxe;
+	netobj->parent.protocols[2].protocol_interface = &netobj->pxe;
 	netobj->parent.handle = &netobj->net;
 	netobj->net.start = efi_net_start;
 	netobj->net.stop = efi_net_stop;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 2/9] efi_loader: efi_open_protocol: parameter checks
  2017-07-05 16:18 [U-Boot] [PATCH 0/9] EFI protocol services Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 1/9] efi_loader: refactor efi_open_protocol Heinrich Schuchardt
@ 2017-07-05 16:18 ` Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 3/9] efi_loader: implement InstallProtocolInterface Heinrich Schuchardt
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2017-07-05 16:18 UTC (permalink / raw)
  To: u-boot

Add all parameter checks for function efi_open_protocol that do not
depend on a locking table.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 lib/efi_loader/efi_boottime.c | 31 +++++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 5c72f92474..22e9e6001d 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -718,15 +718,35 @@ static efi_status_t EFIAPI efi_open_protocol(
 {
 	struct list_head *lhandle;
 	int i;
-	efi_status_t r = EFI_UNSUPPORTED;
+	efi_status_t r = EFI_INVALID_PARAMETER;
 
 	EFI_ENTRY("%p, %p, %p, %p, %p, 0x%x", handle, protocol,
 		  protocol_interface, agent_handle, controller_handle,
 		  attributes);
 
-	if (!protocol_interface && attributes !=
-	    EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
-		r = EFI_INVALID_PARAMETER;
+	if (!handle || !protocol ||
+	    (!protocol_interface && attributes !=
+	     EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) {
+		goto out;
+	}
+
+	switch (attributes) {
+	case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
+	case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
+	case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:
+		break;
+	case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
+		if (controller_handle == handle)
+			goto out;
+	case EFI_OPEN_PROTOCOL_BY_DRIVER:
+	case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
+		if (controller_handle == NULL)
+			goto out;
+	case EFI_OPEN_PROTOCOL_EXCLUSIVE:
+		if (agent_handle == NULL)
+			goto out;
+		break;
+	default:
 		goto out;
 	}
 
@@ -752,8 +772,11 @@ static efi_status_t EFIAPI efi_open_protocol(
 				goto out;
 			}
 		}
+		goto unsupported;
 	}
 
+unsupported:
+	r = EFI_UNSUPPORTED;
 out:
 	return EFI_EXIT(r);
 }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 3/9] efi_loader: implement InstallProtocolInterface
  2017-07-05 16:18 [U-Boot] [PATCH 0/9] EFI protocol services Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 1/9] efi_loader: refactor efi_open_protocol Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 2/9] efi_loader: efi_open_protocol: parameter checks Heinrich Schuchardt
@ 2017-07-05 16:18 ` Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 4/9] efi_loader: implement UninstallProtocolInterface Heinrich Schuchardt
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2017-07-05 16:18 UTC (permalink / raw)
  To: u-boot

efi_install_protocol_interface up to now only returned an error code.

The patch implements the UEFI specification for InstallProtocolInterface
with the exception that it will not create new handles.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 include/efi_api.h             |  2 +-
 lib/efi_loader/efi_boottime.c | 52 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/include/efi_api.h b/include/efi_api.h
index f071b36b53..42cd47ff08 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -58,7 +58,7 @@ struct efi_boot_services {
 	efi_status_t (EFIAPI *signal_event)(void *event);
 	efi_status_t (EFIAPI *close_event)(void *event);
 	efi_status_t (EFIAPI *check_event)(void *event);
-
+#define EFI_NATIVE_INTERFACE	0x00000000
 	efi_status_t (EFIAPI *install_protocol_interface)(
 			void **handle, efi_guid_t *protocol,
 			int protocol_interface_type, void *protocol_interface);
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 22e9e6001d..7596f16b84 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -303,10 +303,60 @@ static efi_status_t EFIAPI efi_install_protocol_interface(void **handle,
 			efi_guid_t *protocol, int protocol_interface_type,
 			void *protocol_interface)
 {
+	struct list_head *lhandle;
+	int i;
+	efi_status_t r;
+
 	EFI_ENTRY("%p, %p, %d, %p", handle, protocol, protocol_interface_type,
 		  protocol_interface);
-	return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+	if (!handle || !protocol ||
+	    protocol_interface_type != EFI_NATIVE_INTERFACE) {
+		r = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	/* Create new handle if requested. */
+	if (!*handle) {
+		r = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+	/* Find object. */
+	list_for_each(lhandle, &efi_obj_list) {
+		struct efi_object *efiobj;
+		efiobj = list_entry(lhandle, struct efi_object, link);
+
+		if (efiobj->handle != *handle)
+			continue;
+		/* Check if protocol is already installed on the handle. */
+		for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
+			struct efi_handler *handler = &efiobj->protocols[i];
+
+			if (handler->guid == protocol) {
+				r = EFI_INVALID_PARAMETER;
+				goto out;
+			}
+		/* Install protocol in first empty slot. */
+		for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
+			struct efi_handler *handler = &efiobj->protocols[i];
+
+			if (handler->guid)
+				continue;
+
+			handler->guid = protocol;
+			handler->protocol_interface = protocol_interface;
+			r = EFI_SUCCESS;
+			goto out;
+			}
+		}
+		r = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+	r = EFI_INVALID_PARAMETER;
+out:
+	return EFI_EXIT(r);
 }
+
 static efi_status_t EFIAPI efi_reinstall_protocol_interface(void *handle,
 			efi_guid_t *protocol, void *old_interface,
 			void *new_interface)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 4/9] efi_loader: implement UninstallProtocolInterface
  2017-07-05 16:18 [U-Boot] [PATCH 0/9] EFI protocol services Heinrich Schuchardt
                   ` (2 preceding siblings ...)
  2017-07-05 16:18 ` [U-Boot] [PATCH 3/9] efi_loader: implement InstallProtocolInterface Heinrich Schuchardt
@ 2017-07-05 16:18 ` Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 5/9] efi_loader: refactor efi_install_protocol_interface Heinrich Schuchardt
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2017-07-05 16:18 UTC (permalink / raw)
  To: u-boot

Without the patch efi_uninstall_protocol_interface always returns an
error.

With the patch protocols without interface can be uninstalled.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 lib/efi_loader/efi_boottime.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 7596f16b84..b3a59b4219 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -369,8 +369,41 @@ static efi_status_t EFIAPI efi_reinstall_protocol_interface(void *handle,
 static efi_status_t EFIAPI efi_uninstall_protocol_interface(void *handle,
 			efi_guid_t *protocol, void *protocol_interface)
 {
+	struct list_head *lhandle;
+	int i;
+	efi_status_t r = EFI_NOT_FOUND;
+
 	EFI_ENTRY("%p, %p, %p", handle, protocol, protocol_interface);
-	return EFI_EXIT(EFI_NOT_FOUND);
+
+	if (!handle || !protocol) {
+		r = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	list_for_each(lhandle, &efi_obj_list) {
+		struct efi_object *efiobj;
+		efiobj = list_entry(lhandle, struct efi_object, link);
+
+		if (efiobj->handle != handle)
+			continue;
+
+		for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) {
+			struct efi_handler *handler = &efiobj->protocols[i];
+			const efi_guid_t *hprotocol = handler->guid;
+			if (!guidcmp(hprotocol, protocol)) {
+				if (handler->protocol_interface) {
+					r = EFI_ACCESS_DENIED;
+				} else {
+					handler->guid = 0;
+					r = EFI_SUCCESS;
+				}
+				goto out;
+			}
+		}
+	}
+
+out:
+	return EFI_EXIT(r);
 }
 
 static efi_status_t EFIAPI efi_register_protocol_notify(efi_guid_t *protocol,
@@ -811,7 +844,7 @@ static efi_status_t EFIAPI efi_open_protocol(
 			struct efi_handler *handler = &efiobj->protocols[i];
 			const efi_guid_t *hprotocol = handler->guid;
 			if (!hprotocol)
-				break;
+				continue;
 			if (!guidcmp(hprotocol, protocol)) {
 				if (attributes !=
 				    EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 5/9] efi_loader: refactor efi_install_protocol_interface
  2017-07-05 16:18 [U-Boot] [PATCH 0/9] EFI protocol services Heinrich Schuchardt
                   ` (3 preceding siblings ...)
  2017-07-05 16:18 ` [U-Boot] [PATCH 4/9] efi_loader: implement UninstallProtocolInterface Heinrich Schuchardt
@ 2017-07-05 16:18 ` Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 6/9] efi_loader: refactor efi_uninstall_protocol_interface Heinrich Schuchardt
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2017-07-05 16:18 UTC (permalink / raw)
  To: u-boot

For the implementation of InstallMultipleProtocolInterfaces we
need to call efi_install_protocol_interface. In internal calls
we should not pass through EFI_EXIT.

The patch introduces a wrapper function
efi_install_protocol_interface_ext.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 lib/efi_loader/efi_boottime.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index b3a59b4219..0075ccaaa2 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -307,9 +307,6 @@ static efi_status_t EFIAPI efi_install_protocol_interface(void **handle,
 	int i;
 	efi_status_t r;
 
-	EFI_ENTRY("%p, %p, %d, %p", handle, protocol, protocol_interface_type,
-		  protocol_interface);
-
 	if (!handle || !protocol ||
 	    protocol_interface_type != EFI_NATIVE_INTERFACE) {
 		r = EFI_INVALID_PARAMETER;
@@ -354,7 +351,19 @@ static efi_status_t EFIAPI efi_install_protocol_interface(void **handle,
 	}
 	r = EFI_INVALID_PARAMETER;
 out:
-	return EFI_EXIT(r);
+	return r;
+}
+
+static efi_status_t EFIAPI efi_install_protocol_interface_ext(void **handle,
+			efi_guid_t *protocol, int protocol_interface_type,
+			void *protocol_interface)
+{
+	EFI_ENTRY("%p, %p, %d, %p", handle, protocol, protocol_interface_type,
+		  protocol_interface);
+
+	return EFI_EXIT(efi_install_protocol_interface(handle, protocol,
+						       protocol_interface_type,
+						       protocol_interface));
 }
 
 static efi_status_t EFIAPI efi_reinstall_protocol_interface(void *handle,
@@ -889,7 +898,7 @@ static const struct efi_boot_services efi_boot_services = {
 	.signal_event = efi_signal_event,
 	.close_event = efi_close_event,
 	.check_event = efi_check_event,
-	.install_protocol_interface = efi_install_protocol_interface,
+	.install_protocol_interface = efi_install_protocol_interface_ext,
 	.reinstall_protocol_interface = efi_reinstall_protocol_interface,
 	.uninstall_protocol_interface = efi_uninstall_protocol_interface,
 	.handle_protocol = efi_handle_protocol,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 6/9] efi_loader: refactor efi_uninstall_protocol_interface
  2017-07-05 16:18 [U-Boot] [PATCH 0/9] EFI protocol services Heinrich Schuchardt
                   ` (4 preceding siblings ...)
  2017-07-05 16:18 ` [U-Boot] [PATCH 5/9] efi_loader: refactor efi_install_protocol_interface Heinrich Schuchardt
@ 2017-07-05 16:18 ` Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 7/9] efi_loader: implement InstallMultipleProtocolInterfaces Heinrich Schuchardt
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2017-07-05 16:18 UTC (permalink / raw)
  To: u-boot

For the implementation of UninstallMultipleProtocolInterfaces we
need to call efi_uninstall_protocol_interface. In internal calls
we should not pass through EFI_EXIT.

The patch introduces a wrapper function
efi_uninstall_protocol_interface_ext.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 lib/efi_loader/efi_boottime.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 0075ccaaa2..607287d01f 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -382,8 +382,6 @@ static efi_status_t EFIAPI efi_uninstall_protocol_interface(void *handle,
 	int i;
 	efi_status_t r = EFI_NOT_FOUND;
 
-	EFI_ENTRY("%p, %p, %p", handle, protocol, protocol_interface);
-
 	if (!handle || !protocol) {
 		r = EFI_INVALID_PARAMETER;
 		goto out;
@@ -412,7 +410,16 @@ static efi_status_t EFIAPI efi_uninstall_protocol_interface(void *handle,
 	}
 
 out:
-	return EFI_EXIT(r);
+	return r;
+}
+
+static efi_status_t EFIAPI efi_uninstall_protocol_interface_ext(void *handle,
+			efi_guid_t *protocol, void *protocol_interface)
+{
+	EFI_ENTRY("%p, %p, %p", handle, protocol, protocol_interface);
+
+	return EFI_EXIT(efi_uninstall_protocol_interface(handle, protocol,
+							 protocol_interface));
 }
 
 static efi_status_t EFIAPI efi_register_protocol_notify(efi_guid_t *protocol,
@@ -900,7 +907,7 @@ static const struct efi_boot_services efi_boot_services = {
 	.check_event = efi_check_event,
 	.install_protocol_interface = efi_install_protocol_interface_ext,
 	.reinstall_protocol_interface = efi_reinstall_protocol_interface,
-	.uninstall_protocol_interface = efi_uninstall_protocol_interface,
+	.uninstall_protocol_interface = efi_uninstall_protocol_interface_ext,
 	.handle_protocol = efi_handle_protocol,
 	.reserved = NULL,
 	.register_protocol_notify = efi_register_protocol_notify,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 7/9] efi_loader: implement InstallMultipleProtocolInterfaces
  2017-07-05 16:18 [U-Boot] [PATCH 0/9] EFI protocol services Heinrich Schuchardt
                   ` (5 preceding siblings ...)
  2017-07-05 16:18 ` [U-Boot] [PATCH 6/9] efi_loader: refactor efi_uninstall_protocol_interface Heinrich Schuchardt
@ 2017-07-05 16:18 ` Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 8/9] efi_loader: refactor efi_locate_handle Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 9/9] efi_loader: implement LocateHandleBuffer Heinrich Schuchardt
  8 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2017-07-05 16:18 UTC (permalink / raw)
  To: u-boot

Implement InstallMultipleProtocolInterfaces in function
efi_install_multiple_protocol_interfaces by repeatedly
calling efi_install_protocol_interface.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 lib/efi_loader/efi_boottime.c | 39 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 607287d01f..74b9620ad8 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -778,7 +778,44 @@ static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(
 			void **handle, ...)
 {
 	EFI_ENTRY("%p", handle);
-	return EFI_EXIT(EFI_OUT_OF_RESOURCES);
+
+	va_list argptr;
+	efi_guid_t *protocol;
+	void *protocol_interface;
+	efi_status_t r = EFI_SUCCESS;
+	int i = 0;
+
+	if (!handle)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	va_start(argptr, handle);
+	for (;;) {
+		protocol = va_arg(argptr, efi_guid_t*);
+		if (!protocol)
+			break;
+		protocol_interface = va_arg(argptr, void*);
+		r = efi_install_protocol_interface(handle, protocol,
+						   EFI_NATIVE_INTERFACE,
+						   protocol_interface);
+		if (r != EFI_SUCCESS)
+			break;
+		i++;
+	}
+	va_end(argptr);
+	if (r == EFI_SUCCESS)
+		return EFI_EXIT(r);
+
+	/* If an error occured undo all changes. */
+	va_start(argptr, handle);
+	for (; i; --i) {
+		protocol = va_arg(argptr, efi_guid_t*);
+		protocol_interface = va_arg(argptr, void*);
+		efi_uninstall_protocol_interface(handle, protocol,
+						 protocol_interface);
+	}
+	va_end(argptr);
+
+	return EFI_EXIT(r);
 }
 
 static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 8/9] efi_loader: refactor efi_locate_handle
  2017-07-05 16:18 [U-Boot] [PATCH 0/9] EFI protocol services Heinrich Schuchardt
                   ` (6 preceding siblings ...)
  2017-07-05 16:18 ` [U-Boot] [PATCH 7/9] efi_loader: implement InstallMultipleProtocolInterfaces Heinrich Schuchardt
@ 2017-07-05 16:18 ` Heinrich Schuchardt
  2017-07-05 16:18 ` [U-Boot] [PATCH 9/9] efi_loader: implement LocateHandleBuffer Heinrich Schuchardt
  8 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2017-07-05 16:18 UTC (permalink / raw)
  To: u-boot

To implement LocateHandleBuffer we need to call efi_locate_handle
internally without running through EFI_EXIT.

So put EFI_ENTRY and EFI_EXIT into a new wrapper function
efi_locate_handle_ext.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 lib/efi_loader/efi_boottime.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 74b9620ad8..888207681c 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -461,9 +461,6 @@ static efi_status_t EFIAPI efi_locate_handle(
 	struct list_head *lhandle;
 	unsigned long size = 0;
 
-	EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
-		  buffer_size, buffer);
-
 	/* Count how much space we need */
 	list_for_each(lhandle, &efi_obj_list) {
 		struct efi_object *efiobj;
@@ -475,7 +472,7 @@ static efi_status_t EFIAPI efi_locate_handle(
 
 	if (*buffer_size < size) {
 		*buffer_size = size;
-		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+		return EFI_BUFFER_TOO_SMALL;
 	}
 
 	/* Then fill the array */
@@ -488,7 +485,19 @@ static efi_status_t EFIAPI efi_locate_handle(
 	}
 
 	*buffer_size = size;
-	return EFI_EXIT(EFI_SUCCESS);
+	return EFI_SUCCESS;
+}
+
+static efi_status_t EFIAPI efi_locate_handle_ext(
+			enum efi_locate_search_type search_type,
+			efi_guid_t *protocol, void *search_key,
+			unsigned long *buffer_size, efi_handle_t *buffer)
+{
+	EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
+		  buffer_size, buffer);
+
+	return EFI_EXIT(efi_locate_handle(search_type, protocol, search_key,
+			buffer_size, buffer));
 }
 
 static efi_status_t EFIAPI efi_locate_device_path(efi_guid_t *protocol,
@@ -948,7 +957,7 @@ static const struct efi_boot_services efi_boot_services = {
 	.handle_protocol = efi_handle_protocol,
 	.reserved = NULL,
 	.register_protocol_notify = efi_register_protocol_notify,
-	.locate_handle = efi_locate_handle,
+	.locate_handle = efi_locate_handle_ext,
 	.locate_device_path = efi_locate_device_path,
 	.install_configuration_table = efi_install_configuration_table_ext,
 	.load_image = efi_load_image,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 9/9] efi_loader: implement LocateHandleBuffer
  2017-07-05 16:18 [U-Boot] [PATCH 0/9] EFI protocol services Heinrich Schuchardt
                   ` (7 preceding siblings ...)
  2017-07-05 16:18 ` [U-Boot] [PATCH 8/9] efi_loader: refactor efi_locate_handle Heinrich Schuchardt
@ 2017-07-05 16:18 ` Heinrich Schuchardt
  8 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2017-07-05 16:18 UTC (permalink / raw)
  To: u-boot

UEFI boot service LocateHandleBuffer is implemented by calling
efi_allocate_handle and efi_locate_handle.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 lib/efi_loader/efi_boottime.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 888207681c..3060c25a2a 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -753,9 +753,32 @@ static efi_status_t EFIAPI efi_locate_handle_buffer(
 			efi_guid_t *protocol, void *search_key,
 			unsigned long *no_handles, efi_handle_t **buffer)
 {
+	efi_status_t r;
+	unsigned long buffer_size = 0;
+
 	EFI_ENTRY("%d, %p, %p, %p, %p", search_type, protocol, search_key,
 		  no_handles, buffer);
-	return EFI_EXIT(EFI_NOT_FOUND);
+
+	if (!no_handles || !buffer) {
+		r = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+	*no_handles = 0;
+	*buffer = NULL;
+	r = efi_locate_handle(search_type, protocol, search_key, &buffer_size,
+			      *buffer);
+	if (r != EFI_BUFFER_TOO_SMALL)
+		goto out;
+	r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, buffer_size,
+			      (void **)buffer);
+	if (r != EFI_SUCCESS)
+		goto out;
+	r = efi_locate_handle(search_type, protocol, search_key, &buffer_size,
+			      *buffer);
+	if (r == EFI_SUCCESS)
+		*no_handles = buffer_size / sizeof(void *);
+out:
+	return EFI_EXIT(r);
 }
 
 static struct efi_class_map efi_class_maps[] = {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-07-05 16:18 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-05 16:18 [U-Boot] [PATCH 0/9] EFI protocol services Heinrich Schuchardt
2017-07-05 16:18 ` [U-Boot] [PATCH 1/9] efi_loader: refactor efi_open_protocol Heinrich Schuchardt
2017-07-05 16:18 ` [U-Boot] [PATCH 2/9] efi_loader: efi_open_protocol: parameter checks Heinrich Schuchardt
2017-07-05 16:18 ` [U-Boot] [PATCH 3/9] efi_loader: implement InstallProtocolInterface Heinrich Schuchardt
2017-07-05 16:18 ` [U-Boot] [PATCH 4/9] efi_loader: implement UninstallProtocolInterface Heinrich Schuchardt
2017-07-05 16:18 ` [U-Boot] [PATCH 5/9] efi_loader: refactor efi_install_protocol_interface Heinrich Schuchardt
2017-07-05 16:18 ` [U-Boot] [PATCH 6/9] efi_loader: refactor efi_uninstall_protocol_interface Heinrich Schuchardt
2017-07-05 16:18 ` [U-Boot] [PATCH 7/9] efi_loader: implement InstallMultipleProtocolInterfaces Heinrich Schuchardt
2017-07-05 16:18 ` [U-Boot] [PATCH 8/9] efi_loader: refactor efi_locate_handle Heinrich Schuchardt
2017-07-05 16:18 ` [U-Boot] [PATCH 9/9] efi_loader: implement LocateHandleBuffer Heinrich Schuchardt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.