diff mbox series

[U-Boot,RFC,v2,06/15] efi_loader: device path: convert efi_device_path to DM

Message ID 20190208081542.2813-7-takahiro.akashi@linaro.org
State RFC
Delegated to: Alexander Graf
Headers show
Series dm, efi: integrate efi objects into DM | expand

Commit Message

AKASHI Takahiro Feb. 8, 2019, 8:15 a.m. UTC
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 include/efi_loader.h                       |   4 +-
 lib/efi_loader/efi_device_path.c           | 136 ++++++++++++++-------
 lib/efi_loader/efi_device_path_to_text.c   |  55 +++++++++
 lib/efi_loader/efi_device_path_utilities.c |  14 +++
 4 files changed, 164 insertions(+), 45 deletions(-)
diff mbox series

Patch

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 4df965455c21..2773df4a26e9 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -386,8 +386,8 @@  extern void *efi_bounce_buffer;
 struct efi_device_path *efi_dp_next(const struct efi_device_path *dp);
 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);
+efi_handle_t efi_dp_find_obj(struct efi_device_path *dp,
+			     struct efi_device_path **rem);
 /* 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 */
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index d94982314a3e..a85a2d0ff6ba 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -140,69 +140,92 @@  static struct efi_device_path *shorten_path(struct efi_device_path *dp)
 	return dp;
 }
 
-static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
-				   struct efi_device_path **rem)
+struct dp_param {
+	struct efi_device_path *dp;
+	bool short_path;
+	struct efi_device_path **rem;
+	struct udevice *dev;
+};
+
+static int find_obj_cb(struct udevice *dev, void *arg)
 {
-	struct efi_object *efiobj;
+	struct dp_param *param = arg;
+	struct efi_device_path *dp = param->dp;
+	bool short_path = param->short_path;
+	struct efi_device_path **rem = param->rem;
 	efi_uintn_t dp_size = efi_dp_instance_size(dp);
 
-	list_for_each_entry(efiobj, &efi_obj_list, link) {
-		struct efi_handler *handler;
-		struct efi_device_path *obj_dp;
-		efi_status_t ret;
-
-		ret = efi_search_protocol(efiobj,
-					  &efi_guid_device_path, &handler);
-		if (ret != EFI_SUCCESS)
-			continue;
-		obj_dp = handler->protocol_interface;
-
-		do {
-			if (efi_dp_match(dp, obj_dp) == 0) {
-				if (rem) {
-					/*
-					 * Allow partial matches, but inform
-					 * the caller.
-					 */
-					*rem = ((void *)dp) +
-						efi_dp_instance_size(obj_dp);
-					return efiobj;
-				} else {
-					/* Only return on exact matches */
-					if (efi_dp_instance_size(obj_dp) ==
-					    dp_size)
-						return efiobj;
-				}
+	struct udevice *protocol;
+	struct efi_handler *handler;
+	struct efi_device_path *obj_dp;
+	efi_status_t ret;
+
+	ret = efi_search_protocol(dev, &efi_guid_device_path, &protocol);
+	if (ret != EFI_SUCCESS)
+		return 0;
+
+	handler = protocol->uclass_platdata;
+	obj_dp = handler->protocol_interface;
+	do {
+		if (efi_dp_match(dp, obj_dp) == 0) {
+			if (rem) {
+				/*
+				 * Allow partial matches, but inform
+				 * the caller.
+				 */
+				*rem = ((void *)dp) +
+					efi_dp_instance_size(obj_dp);
+				param->dev = dev;
+				return 1;
 			}
 
-			obj_dp = shorten_path(efi_dp_next(obj_dp));
-		} while (short_path && obj_dp);
-	}
+			/* Only return on exact matches */
+			if (efi_dp_instance_size(obj_dp) == dp_size) {
+				param->dev = dev;
+				return 1;
+			}
+		}
+
+		obj_dp = shorten_path(efi_dp_next(obj_dp));
+	} while (short_path && obj_dp);
+
+	return 0;
+}
+
+static struct udevice *find_obj(struct efi_device_path *dp, bool short_path,
+				struct efi_device_path **rem)
+{
+	struct dp_param dp_param;
+	efi_status_t ret;
+
+	ret = efi_foreach_dev(find_obj_cb, &dp_param);
+	if (ret)
+		return NULL;
 
-	return NULL;
+	return dp_param.dev;
 }
 
 /*
  * Find an efiobj from device-path, if 'rem' is not NULL, returns the
  * remaining part of the device path after the matched object.
  */
-struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
-				   struct efi_device_path **rem)
+efi_handle_t efi_dp_find_obj(struct efi_device_path *dp,
+			     struct efi_device_path **rem)
 {
-	struct efi_object *efiobj;
+	struct udevice *dev;
 
 	/* Search for an exact match first */
-	efiobj = find_obj(dp, false, NULL);
+	dev = find_obj(dp, false, NULL);
 
 	/* Then for a fuzzy match */
-	if (!efiobj)
-		efiobj = find_obj(dp, false, rem);
+	if (!dev)
+		dev = find_obj(dp, false, rem);
 
 	/* And now for a fuzzy short match */
-	if (!efiobj)
-		efiobj = find_obj(dp, true, rem);
+	if (!dev)
+		dev = find_obj(dp, true, rem);
 
-	return efiobj;
+	return dev;
 }
 
 /*
@@ -992,3 +1015,30 @@  efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
 
 	return EFI_SUCCESS;
 }
+
+extern
+char *efi_convert_device_path_to_str(struct efi_device_path *device_path,
+				     bool display_only,
+				     bool allow_shortcuts);
+
+static int efi_device_path_probe(struct udevice *dev)
+{
+	struct efi_handler *handler;
+	struct efi_device_path *dp;
+	char *name;
+
+	handler = dev->uclass_platdata;
+	dp = handler->protocol_interface;
+	name = efi_convert_device_path_to_str(dp, true, true);
+	device_set_name(dev, name);
+
+	/* TODO: free at unprobe */
+
+	return 0;
+}
+
+U_BOOT_DRIVER(efi_device_path) = {
+	.name = "efi_device_path",
+	.id = UCLASS_EFI_PROTOCOL,
+	.probe = efi_device_path_probe,
+};
diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c
index e219f84b28d2..3d518000eb59 100644
--- a/lib/efi_loader/efi_device_path_to_text.c
+++ b/lib/efi_loader/efi_device_path_to_text.c
@@ -6,6 +6,7 @@ 
  */
 
 #include <common.h>
+#include <dm.h>
 #include <efi_loader.h>
 
 #define MAC_OUTPUT_LEN 22
@@ -295,6 +296,47 @@  out:
 	return text;
 }
 
+/* Temprarily used in probe() for device path protocol driver */
+char *efi_convert_device_path_to_str(struct efi_device_path *device_path,
+				     bool display_only,
+				     bool allow_shortcuts)
+{
+	char *text = NULL;
+	char buffer[MAX_PATH_LEN];
+	char *str = buffer;
+
+	if (!device_path)
+		goto out;
+
+	while (device_path &&
+	       str + MAX_NODE_LEN < buffer + MAX_PATH_LEN) {
+		if (display_only) {
+			/* Only first 8 characters */
+			struct efi_device_path *next;
+
+			next = efi_dp_next(device_path);
+			if (next) {
+				device_path = next;
+				continue;
+			}
+
+			str = efi_convert_single_device_node_to_text(str,
+								device_path);
+			str[9] = '\0';
+			break;
+		}
+
+		*str++ = '/';
+		str = efi_convert_single_device_node_to_text(str, device_path);
+		device_path = efi_dp_next(device_path);
+	}
+
+	text = strdup(buffer);
+
+out:
+	return text;
+}
+
 /*
  * This function implements the ConvertDevicePathToText service of the
  * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
@@ -344,3 +386,16 @@  const struct efi_device_path_to_text_protocol efi_device_path_to_text = {
 	.convert_device_node_to_text = efi_convert_device_node_to_text,
 	.convert_device_path_to_text = efi_convert_device_path_to_text,
 };
+
+static int efi_device_path_to_text_probe(struct udevice *dev)
+{
+	device_set_name(dev, "DEVICE_PATH_TO_TEXT");
+
+	return 0;
+}
+
+U_BOOT_DRIVER(efi_device_path_to_text) = {
+	.name = "efi_device_path_to_text",
+	.id = UCLASS_EFI_PROTOCOL,
+	.probe = efi_device_path_to_text_probe,
+};
diff --git a/lib/efi_loader/efi_device_path_utilities.c b/lib/efi_loader/efi_device_path_utilities.c
index 94015329c8cb..7d7f0c46b18f 100644
--- a/lib/efi_loader/efi_device_path_utilities.c
+++ b/lib/efi_loader/efi_device_path_utilities.c
@@ -6,6 +6,7 @@ 
  */
 
 #include <common.h>
+#include <dm.h>
 #include <efi_loader.h>
 
 const efi_guid_t efi_guid_device_path_utilities_protocol =
@@ -197,3 +198,16 @@  const struct efi_device_path_utilities_protocol efi_device_path_utilities = {
 	.is_device_path_multi_instance = is_device_path_multi_instance,
 	.create_device_node = create_device_node,
 };
+
+static int efi_device_path_utils_probe(struct udevice *dev)
+{
+	device_set_name(dev, "DEVICE_PATH_UTILITIES");
+
+	return 0;
+}
+
+U_BOOT_DRIVER(efi_device_path_utils) = {
+	.name = "efi_device_path_utils",
+	.id = UCLASS_EFI_PROTOCOL,
+	.probe = efi_device_path_utils_probe,
+};