[U-Boot] [PATCH 10/11] efi_loader: Add mem-mapped for fallback

Rob Clark robdclark at gmail.com
Tue Oct 10 12:23:06 UTC 2017


When we don't have a real device/image path, such as 'bootefi hello',
construct a mem-mapped device-path.

This fixes 'bootefi hello' after devicepath refactoring.

Fixes: 95c5553ea2 ("efi_loader: refactor boot device and loaded_image handling")
Signed-off-by: Rob Clark <robdclark at gmail.com>
---
 cmd/bootefi.c                            | 23 +++++++++++++++++++++++
 include/efi_api.h                        |  8 ++++++++
 include/efi_loader.h                     |  3 +++
 lib/efi_loader/efi_device_path.c         | 24 ++++++++++++++++++++++++
 lib/efi_loader/efi_device_path_to_text.c |  9 +++++++++
 5 files changed, 67 insertions(+)

diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 24958ada46..18176a1266 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -128,6 +128,7 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt,
 {
 	struct efi_loaded_image loaded_image_info = {};
 	struct efi_object loaded_image_info_obj = {};
+	struct efi_device_path *memdp = NULL;
 	ulong ret;
 
 	ulong (*entry)(void *image_handle, struct efi_system_table *st)
@@ -136,6 +137,20 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt,
 	const efi_guid_t fdt_guid = EFI_FDT_GUID;
 	bootm_headers_t img = { 0 };
 
+	/*
+	 * Special case for efi payload not loaded from disk, such as
+	 * 'bootefi hello' or for example payload loaded directly into
+	 * memory via jtag/etc:
+	 */
+	if (!device_path && !image_path) {
+		printf("WARNING: using memory device/image path, this may confuse some payloads!\n");
+		/* actual addresses filled in after efi_load_pe() */
+		memdp = efi_dp_from_mem(0, 0, 0);
+		device_path = image_path = memdp;
+	} else {
+		assert(device_path && image_path);
+	}
+
 	/* Initialize and populate EFI object list */
 	if (!efi_obj_list_initalized)
 		efi_init_obj_list();
@@ -182,6 +197,14 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt,
 		goto exit;
 	}
 
+	if (memdp) {
+		struct efi_device_path_memory *mdp = (void *)memdp;
+		mdp->memory_type = loaded_image_info.image_code_type;
+		mdp->start_address = (uintptr_t)loaded_image_info.image_base;
+		mdp->end_address = mdp->start_address +
+				loaded_image_info.image_size;
+	}
+
 	/* we don't support much: */
 	env_set("efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported",
 		"{ro,boot}(blob)0000000000000000");
diff --git a/include/efi_api.h b/include/efi_api.h
index 9610d03d47..07b2af7020 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -299,8 +299,16 @@ struct efi_mac_addr {
 } __packed;
 
 #define DEVICE_PATH_TYPE_HARDWARE_DEVICE	0x01
+#  define DEVICE_PATH_SUB_TYPE_MEMORY		0x03
 #  define DEVICE_PATH_SUB_TYPE_VENDOR		0x04
 
+struct efi_device_path_memory {
+	struct efi_device_path dp;
+	u32 memory_type;
+	u64 start_address;
+	u64 end_address;
+} __packed;
+
 struct efi_device_path_vendor {
 	struct efi_device_path dp;
 	efi_guid_t guid;
diff --git a/include/efi_loader.h b/include/efi_loader.h
index fa4e1cdb1c..db805e898f 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -269,6 +269,9 @@ struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part);
 struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
 					 const char *path);
 struct efi_device_path *efi_dp_from_eth(void);
+struct efi_device_path *efi_dp_from_mem(uint32_t mem_type,
+					uint64_t start_address,
+					uint64_t end_address);
 void efi_dp_split_file_path(struct efi_device_path *full_path,
 			    struct efi_device_path **device_path,
 			    struct efi_device_path **file_path);
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index 5d5c3b3464..f6e368e029 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -538,6 +538,30 @@ struct efi_device_path *efi_dp_from_eth(void)
 }
 #endif
 
+/* Construct a device-path for memory-mapped image */
+struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
+					uint64_t start_address,
+					uint64_t end_address)
+{
+	struct efi_device_path_memory *mdp;
+	void *buf, *start;
+
+	start = buf = dp_alloc(sizeof(*mdp) + sizeof(END));
+
+	mdp = buf;
+	mdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
+	mdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MEMORY;
+	mdp->dp.length = sizeof(*mdp);
+	mdp->memory_type = memory_type;
+	mdp->start_address = start_address;
+	mdp->end_address = end_address;
+	buf = &mdp[1];
+
+	*((struct efi_device_path *)buf) = END;
+
+	return start;
+}
+
 /*
  * Helper to split a full device path (containing both device and file
  * parts) into it's constituent parts.
diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c
index 1a5ef3919b..62771338f0 100644
--- a/lib/efi_loader/efi_device_path_to_text.c
+++ b/lib/efi_loader/efi_device_path_to_text.c
@@ -24,6 +24,15 @@ static char *dp_unknown(char *s, struct efi_device_path *dp)
 static char *dp_hardware(char *s, struct efi_device_path *dp)
 {
 	switch (dp->sub_type) {
+	case DEVICE_PATH_SUB_TYPE_MEMORY: {
+		struct efi_device_path_memory *mdp =
+			(struct efi_device_path_memory *)dp;
+		s += sprintf(s, "/MemoryMapped(0x%x,0x%llx,0x%llx)",
+			     mdp->memory_type,
+			     mdp->start_address,
+			     mdp->end_address);
+		break;
+	}
 	case DEVICE_PATH_SUB_TYPE_VENDOR: {
 		struct efi_device_path_vendor *vdp =
 			(struct efi_device_path_vendor *)dp;
-- 
2.13.6



More information about the U-Boot mailing list