efi_loader: Add mem-mapped for fallback
authorRob Clark <robdclark@gmail.com>
Tue, 10 Oct 2017 12:23:06 +0000 (08:23 -0400)
committerAlexander Graf <agraf@suse.de>
Thu, 12 Oct 2017 15:22:58 +0000 (17:22 +0200)
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@gmail.com>
Acked-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
cmd/bootefi.c
include/efi_api.h
include/efi_loader.h
lib/efi_loader/efi_device_path.c
lib/efi_loader/efi_device_path_to_text.c

index b7087e3da874e7f14745dc63dfbf62458bf80795..478bc116e242a167835d2033831d94034058931b 100644 (file)
@@ -127,6 +127,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)
@@ -135,6 +136,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();
@@ -181,6 +196,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");
index a9a6494afef44b0a664f207460e423bfdce2c8d4..94c15b279ac839332e5a4034674678707630f665 100644 (file)
@@ -297,8 +297,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;
index e1179b7dcd1149f9d78753b50540be848be8844b..1b92edbd77c2a888560f26a87cbe250aa475ec4a 100644 (file)
@@ -259,6 +259,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);
index 5d5c3b346467d3b2ddcfb3d38c09ee7ba91f7437..f6e368e029bdf37a768d54b9291c104fda8a30db 100644 (file)
@@ -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.
index 1a5ef3919bac92035c7a1a112b08a4313a8d6c71..62771338f0383a9850dc11de7f2d2d6a6247a04f 100644 (file)
@@ -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;