[Concept,10/20] boot: Show the device path for EFI bootflows

Message ID 20250828020732.981415-11-sjg@u-boot.org
State New
Headers
Series efi: App and devicetree improvements |

Commit Message

Simon Glass Aug. 28, 2025, 2:07 a.m. UTC
  From: Simon Glass <sjg@chromium.org>

If the bootflow relates to the EFI bootmeth, show the device path along
with the other info.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 cmd/bootflow.c            | 17 +++++++++++++++++
 include/efi.h             | 15 +++++++++++++++
 include/efi_device_path.h | 14 ++++++++++++++
 lib/efi/device_path.c     | 37 +++++++++++++++++++++++++++++++++++++
 lib/efi_client/app_run.c  | 18 ++++++++++++++++++
 5 files changed, 101 insertions(+)
  

Patch

diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index 464c3e40475..ae692cf521b 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -13,6 +13,7 @@ 
 #include <command.h>
 #include <console.h>
 #include <dm.h>
+#include <efi_device_path.h>
 #include <expo.h>
 #include <log.h>
 #include <mapmem.h>
@@ -453,6 +454,22 @@  static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
 		printf("FDT addr:  %lx\n", bflow->fdt_addr);
 	}
 	printf("Error:     %d\n", bflow->err);
+	if (IS_ENABLED(CONFIG_BOOTMETH_EFI) &&
+	    bflow->method->driver == DM_DRIVER_GET(bootmeth_4efi)) {
+		struct efi_device_path *dp;
+		bool alloced;
+
+		ret = efi_dp_from_bootflow(bflow, &dp, &alloced);
+		printf("EFI path   ");
+		if (!ret) {
+			printf("%pD\n", dp);
+			if (alloced)
+				efi_free_pool(dp);
+		} else {
+			printf("(err %dE)\n", ret);
+		}
+	}
+
 	if (dump && bflow->buf) {
 		/* Set some sort of maximum on the size */
 		int size = min(bflow->size, 10 << 10);
diff --git a/include/efi.h b/include/efi.h
index 3558c03db23..c07717811da 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -23,6 +23,8 @@ 
 #include <net.h>
 #endif
 
+struct udevice;
+
 /* Type INTN in UEFI specification */
 #define efi_intn_t ssize_t
 /* Type UINTN in UEFI specification*/
@@ -848,4 +850,17 @@  efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size,
 			   struct efi_device_path *dp_dev,
 			   struct efi_device_path *dp_img);
 
+/**
+ * efi_dp_from_bootdev() - Get the device path from a bootdev
+ *
+ * This is only available in the app. It looks up the bootdev and returns the
+ * assocated device path (attached to its sibling block device)
+ *
+ * @dev: UCLASS_BOOTDEV device to check
+ * @dpp: Returns device path on success
+ * Returns: 0 if OK, -ve on error
+ */
+int efi_dp_from_bootdev(const struct udevice *dev,
+			const struct efi_device_path **dpp);
+
 #endif /* _LINUX_EFI_H */
diff --git a/include/efi_device_path.h b/include/efi_device_path.h
index 2e425a6d82b..d030674d6bd 100644
--- a/include/efi_device_path.h
+++ b/include/efi_device_path.h
@@ -12,6 +12,7 @@ 
 
 enum uclass_id;
 struct blk_desc;
+struct bootflow;
 struct efi_load_option;
 struct udevice;
 
@@ -429,4 +430,17 @@  struct efi_device_path *efi_dp_from_http(const char *server,
 const char *efi_dp_guess_uclass(struct efi_device_path *device_path,
 				enum uclass_id *guessp);
 
+/**
+ * efi_dp_from_bootflow() - Get the device path for a bootflow
+ *
+ * @bflow: Bootflow to check
+ * @dpp: Returns the device path
+ * @allocedp: if NULL, no allocation is permitted, otherwise retrusn true if
+ * efi_free_pool() must be called to free the device path
+ * Return: 0 if OK, -EINVAL if @allocedp is NULL and allocation is needed,
+ * -ve on error
+ */
+int efi_dp_from_bootflow(const struct bootflow *bflow,
+			 struct efi_device_path **dpp, bool *allocedp);
+
 #endif /* EFI_DEVICE_PATH_H */
diff --git a/lib/efi/device_path.c b/lib/efi/device_path.c
index 191d58bbd2d..bae9e5c537a 100644
--- a/lib/efi/device_path.c
+++ b/lib/efi/device_path.c
@@ -8,6 +8,7 @@ 
 #define LOG_CATEGORY LOGC_EFI
 
 #include <blk.h>
+#include <bootflow.h>
 #include <dm.h>
 #include <dm/root.h>
 #include <efi_device_path.h>
@@ -1376,3 +1377,39 @@  const char *efi_dp_guess_uclass(struct efi_device_path *device_path,
 	return best_name;
 }
 
+int efi_dp_from_bootflow(const struct bootflow *bflow,
+			 struct efi_device_path **dpp, bool *allocedp)
+{
+	struct udevice *bdev = bflow->dev;
+	struct blk_desc *desc;
+	struct udevice *blk;
+	int ret;
+
+	if (IS_ENABLED(CONFIG_EFI_APP)) {
+		const struct efi_device_path *dpc;
+
+		ret = efi_dp_from_bootdev(bflow->dev, &dpc);
+		if (ret)
+			return log_msg_ret("dfa", ret);
+		*dpp = (struct efi_device_path *)dpc;
+		if (allocedp)
+			*allocedp = false;
+	} else {
+		struct efi_device_path *dp;
+
+		if (!allocedp)
+			return log_msg_ret("dfb", -EINVAL);
+		ret = bootdev_get_sibling_blk(bdev, &blk);
+		if (ret)
+			return log_msg_ret("dfc", ret);
+
+		desc = dev_get_uclass_plat(blk);
+		dp = efi_dp_from_part(desc, bflow->part);
+		if (!dp)
+			return log_msg_ret("dfd", -ENOMEM);
+		*allocedp = true;
+		*dpp = dp;
+	}
+
+	return 0;
+}
diff --git a/lib/efi_client/app_run.c b/lib/efi_client/app_run.c
index 03cc29778d8..9fc753ceed8 100644
--- a/lib/efi_client/app_run.c
+++ b/lib/efi_client/app_run.c
@@ -7,6 +7,7 @@ 
  */
 
 #include <bootm.h>
+#include <dm.h>
 #include <efi.h>
 #include <efi_api.h>
 #include <efi_device_path.h>
@@ -89,3 +90,20 @@  efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt,
 {
 	return efi_run_image(image, size, dp_dev, dp_img);
 }
+
+int efi_dp_from_bootdev(const struct udevice *dev,
+			const struct efi_device_path **dpp)
+{
+	const struct udevice *media = dev_get_parent(dev);
+	const struct efi_media_plat *plat;
+
+	log_debug("dev '%s': uclass ID %d\n", media->name,
+		  device_get_uclass_id(media));
+	if (device_get_uclass_id(media) != UCLASS_EFI_MEDIA)
+		return log_msg_ret("efb", -ENOTSUPP);
+
+	plat = dev_get_plat(media);
+	*dpp = plat->device_path;
+
+	return 0;
+}