[U-Boot,v2,6/8] efi_loader: correcty determine total device path length

Message ID 20180416055910.12611-7-xypron.glpk@gmx.de
State Accepted
Delegated to: Alexander Graf
Headers show
Series
  • efi_loader: fixes for EFI_DEVICE_PATH_UTILITIES_PROTOCOL
Related show

Commit Message

Heinrich Schuchardt April 16, 2018, 5:59 a.m.
Device paths may consist of multiple instances. Up to now we have only
considered the size of the first instance. For the services of the
EFI_DEVICE_PATH_UTILITIES_PROTOCOL in most cases the total length of the
device path is relevant.

So let's rename efi_dp_size() to efi_dp_instance_size() and create a new
function efi_dp_size() that calculates the total device path length.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
v2
	no change
---
 include/efi_loader.h             |  5 ++++-
 lib/efi_loader/efi_boottime.c    |  4 ++--
 lib/efi_loader/efi_device_path.c | 34 +++++++++++++++++++++++---------
 3 files changed, 31 insertions(+), 12 deletions(-)

Patch

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 0358bcb1d7..1298b5e160 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -324,7 +324,10 @@  int efi_dp_match(const struct efi_device_path *a,
 		 const struct efi_device_path *b);
 struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
 				   struct efi_device_path **rem);
-unsigned efi_dp_size(const struct efi_device_path *dp);
+/* get size of the first device path instance excluding end node */
+efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp);
+/* size of multi-instance device path excluding end node */
+efi_uintn_t efi_dp_size(const struct efi_device_path *dp);
 struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp);
 struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
 				      const struct efi_device_path *dp2);
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 7a9449f59c..1cfdabf6eb 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -2219,7 +2219,7 @@  static efi_status_t EFIAPI efi_locate_device_path(
 	}
 
 	/* Find end of device path */
-	len = efi_dp_size(*device_path);
+	len = efi_dp_instance_size(*device_path);
 
 	/* Get all handles implementing the protocol */
 	ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL,
@@ -2234,7 +2234,7 @@  static efi_status_t EFIAPI efi_locate_device_path(
 		if (ret != EFI_SUCCESS)
 			continue;
 		dp = (struct efi_device_path *)handler->protocol_interface;
-		len_dp = efi_dp_size(dp);
+		len_dp = efi_dp_instance_size(dp);
 		/*
 		 * This handle can only be a better fit
 		 * if its device path length is longer than the best fit and
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index 46d3fea732..09c3ec4273 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -149,7 +149,7 @@  static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
 				   struct efi_device_path **rem)
 {
 	struct efi_object *efiobj;
-	unsigned int dp_size = efi_dp_size(dp);
+	efi_uintn_t dp_size = efi_dp_instance_size(dp);
 
 	list_for_each_entry(efiobj, &efi_obj_list, link) {
 		struct efi_handler *handler;
@@ -170,11 +170,12 @@  static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
 					 * the caller.
 					 */
 					*rem = ((void *)dp) +
-						efi_dp_size(obj_dp);
+						efi_dp_instance_size(obj_dp);
 					return efiobj;
 				} else {
 					/* Only return on exact matches */
-					if (efi_dp_size(obj_dp) == dp_size)
+					if (efi_dp_instance_size(obj_dp) ==
+					    dp_size)
 						return efiobj;
 				}
 			}
@@ -229,10 +230,10 @@  const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp)
 	return ret;
 }
 
-/* return size not including End node: */
-unsigned efi_dp_size(const struct efi_device_path *dp)
+/* get size of the first device path instance excluding end node */
+efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp)
 {
-	unsigned sz = 0;
+	efi_uintn_t sz = 0;
 
 	if (!dp || dp->type == DEVICE_PATH_TYPE_END)
 		return 0;
@@ -244,10 +245,25 @@  unsigned efi_dp_size(const struct efi_device_path *dp)
 	return sz;
 }
 
+/* get size of multi-instance device path excluding end node */
+efi_uintn_t efi_dp_size(const struct efi_device_path *dp)
+{
+	const struct efi_device_path *p = dp;
+
+	if (!p)
+		return 0;
+	while (p->type != DEVICE_PATH_TYPE_END ||
+	       p->sub_type != DEVICE_PATH_SUB_TYPE_END)
+		p = (void *)p + p->length;
+
+	return (void *)p - (void *)dp;
+}
+
+/* copy multi-instance device path */
 struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
 {
 	struct efi_device_path *ndp;
-	unsigned sz = efi_dp_size(dp) + sizeof(END);
+	size_t sz = efi_dp_size(dp) + sizeof(END);
 
 	if (!dp)
 		return NULL;
@@ -298,7 +314,7 @@  struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
 	} else if (!node) {
 		ret = efi_dp_dup(dp);
 	} else if (!dp) {
-		unsigned sz = node->length;
+		size_t sz = node->length;
 		void *p = dp_alloc(sz + sizeof(END));
 		if (!p)
 			return NULL;
@@ -307,7 +323,7 @@  struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
 		ret = p;
 	} else {
 		/* both dp and node are non-null */
-		unsigned sz = efi_dp_size(dp);
+		size_t sz = efi_dp_size(dp);
 		void *p = dp_alloc(sz + node->length + sizeof(END));
 		if (!p)
 			return NULL;