All of lore.kernel.org
 help / color / mirror / Atom feed
From: Heinrich Schuchardt <xypron.glpk@gmx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3 05/18] efi_loader: reimplement LocateDevicePath
Date: Sun, 26 Nov 2017 14:05:10 +0100	[thread overview]
Message-ID: <20171126130523.4993-6-xypron.glpk@gmx.de> (raw)
In-Reply-To: <20171126130523.4993-1-xypron.glpk@gmx.de>

The current implementation of efi_locate_device_path does not match
the UEFI specification. It completely ignores the protocol
parameters.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
v3
	remove trailing dot in comment
v2
	no change
---
 lib/efi_loader/efi_boottime.c | 106 ++++++++++++++++++++++++++++++------------
 1 file changed, 76 insertions(+), 30 deletions(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 9b5512f086..565addfc3f 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1080,36 +1080,6 @@ static efi_status_t EFIAPI efi_locate_handle_ext(
 			buffer_size, buffer));
 }
 
-/*
- * Get the device path and handle of an device implementing a protocol.
- *
- * This function implements the LocateDevicePath service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
- *
- * @protocol		GUID of the protocol
- * @device_path		device path
- * @device		handle of the device
- * @return		status code
- */
-static efi_status_t EFIAPI efi_locate_device_path(
-			const efi_guid_t *protocol,
-			struct efi_device_path **device_path,
-			efi_handle_t *device)
-{
-	struct efi_object *efiobj;
-
-	EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device);
-
-	efiobj = efi_dp_find_obj(*device_path, device_path);
-	if (!efiobj)
-		return EFI_EXIT(EFI_NOT_FOUND);
-
-	*device = efiobj->handle;
-
-	return EFI_EXIT(EFI_SUCCESS);
-}
-
 /* Collapses configuration table entries, removing index i */
 static void efi_remove_configuration_table(int i)
 {
@@ -1813,6 +1783,82 @@ static efi_status_t EFIAPI efi_locate_protocol(const efi_guid_t *protocol,
 	return EFI_EXIT(EFI_NOT_FOUND);
 }
 
+/*
+ * Get the device path and handle of an device implementing a protocol.
+ *
+ * This function implements the LocateDevicePath service.
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @protocol		GUID of the protocol
+ * @device_path		device path
+ * @device		handle of the device
+ * @return		status code
+ */
+static efi_status_t EFIAPI efi_locate_device_path(
+			const efi_guid_t *protocol,
+			struct efi_device_path **device_path,
+			efi_handle_t *device)
+{
+	struct efi_device_path *dp;
+	size_t i;
+	struct efi_handler *handler;
+	efi_handle_t *handles;
+	size_t len, len_dp;
+	size_t len_best = 0;
+	efi_uintn_t no_handles;
+	u8 *remainder;
+	efi_status_t ret;
+
+	EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device);
+
+	if (!protocol || !device_path || !*device_path || !device) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	/* Find end of device path */
+	len = efi_dp_size(*device_path);
+
+	/* Get all handles implementing the protocol */
+	ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL,
+						&no_handles, &handles));
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	for (i = 0; i < no_handles; ++i) {
+		/* Find the device path protocol */
+		ret = efi_search_protocol(handles[i], &efi_guid_device_path,
+					  &handler);
+		if (ret != EFI_SUCCESS)
+			continue;
+		dp = (struct efi_device_path *)handler->protocol_interface;
+		len_dp = efi_dp_size(dp);
+		/*
+		 * This handle can only be a better fit
+		 * if its device path length is longer than the best fit and
+		 * if its device path length is shorter of equal the searched
+		 * device path.
+		 */
+		if (len_dp <= len_best || len_dp > len)
+			continue;
+		/* Check if dp is a subpath of device_path */
+		if (memcmp(*device_path, dp, len_dp))
+			continue;
+		*device = handles[i];
+		len_best = len_dp;
+	}
+	if (len_best) {
+		remainder = (u8 *)*device_path + len_best;
+		*device_path = (struct efi_device_path *)remainder;
+		ret = EFI_SUCCESS;
+	} else {
+		ret = EFI_NOT_FOUND;
+	}
+out:
+	return EFI_EXIT(ret);
+}
+
 /*
  * Install multiple protocol interfaces.
  *
-- 
2.14.2

  parent reply	other threads:[~2017-11-26 13:05 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-26 13:05 [U-Boot] [PATCH v3 00/18] efi_loader: manage protocols in a linked list (v3) Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 01/18] efi_loader: helloworld.c: remove superfluous include Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 02/18] efi_loader: size of media device path node represenation Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 03/18] efi_loader: efi_dp_str should print path not node Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 04/18] efi_loader: fix efi_convert_device_node_to_text Heinrich Schuchardt
2017-11-26 13:05 ` Heinrich Schuchardt [this message]
2017-11-26 13:05 ` [U-Boot] [PATCH v3 06/18] efi_selftest: test EFI_DEVICE_PATH_TO_TEXT_PROTOCOL Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 07/18] efi_loader: efi_disk: use efi_add_protocol Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 08/18] efi_loader: efi_net: " Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 09/18] efi_loader: efi_gop: " Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 10/18] efi_loader: simplify efi_open_protocol Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 11/18] efi_loader: simplify find_obj Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 12/18] efi_loader: manage protocols in a linked list Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 13/18] efi_selftest: compile without special compiler flags Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 14/18] efi_selftest: add missing line feed Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 15/18] efi_loader: output load options in helloworld Heinrich Schuchardt
2017-12-09 23:09   ` Florian Fainelli
2017-12-10  6:40     ` Heinrich Schuchardt
2017-12-10 22:20       ` Florian Fainelli
2017-12-11  8:15         ` Alexander Graf
2017-11-26 13:05 ` [U-Boot] [PATCH v3 16/18] test/py: check return code of helloworld Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 17/18] efi_loader: pass handle of loaded image Heinrich Schuchardt
2017-11-26 13:05 ` [U-Boot] [PATCH v3 18/18] efi_loader: helper function to add EFI object to list Heinrich Schuchardt
2017-11-27 17:09 ` [U-Boot] [PATCH v3 00/18] efi_loader: manage protocols in a linked list (v3) Simon Glass
2017-12-01 12:42   ` Alexander Graf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171126130523.4993-6-xypron.glpk@gmx.de \
    --to=xypron.glpk@gmx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.