Skip to content

Commit 3c6edd9

Browse files
committed
efi: zboot: create MemoryMapped() device path for the parent if needed
LoadImage() is supposed to install an instance of the protocol EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL onto the loaded image's handle so that the program can figure out where it was loaded from. The reference implementation even does this (with a NULL protocol pointer) if the call to LoadImage() used the source buffer and size arguments, and passed NULL for the image device path. Hand rolled implementations of LoadImage may behave differently, though, and so it is better to tolerate situations where the protocol is missing. And actually, concatenating an Offset() node to a NULL device path (as we do currently) is not great either. So in cases where the protocol is absent, or when it points to NULL, construct a MemoryMapped() device node as the base node that describes the parent image's footprint in memory. Cc: Daan De Meyer <[email protected]> Cc: Jeremy Linton <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent 04419e8 commit 3c6edd9

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

drivers/firmware/efi/libstub/zboot.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ static void append_end_node(efi_device_path_protocol_t **dp)
162162
asmlinkage efi_status_t __efiapi
163163
efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
164164
{
165+
struct efi_mem_mapped_dev_path mmdp = {
166+
.header.type = EFI_DEV_HW,
167+
.header.sub_type = EFI_DEV_MEM_MAPPED,
168+
.header.length = sizeof(struct efi_mem_mapped_dev_path)
169+
};
165170
efi_device_path_protocol_t *parent_dp, *dpp, *lf2_dp, *li_dp;
166171
efi_load_file2_protocol_t zboot_load_file2;
167172
efi_loaded_image_t *parent, *child;
@@ -191,13 +196,20 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
191196
status = efi_bs_call(handle_protocol, handle,
192197
&LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID,
193198
(void **)&parent_dp);
194-
if (status != EFI_SUCCESS) {
195-
log(L"Failed to locate parent's loaded image device path protocol");
196-
return status;
199+
if (status != EFI_SUCCESS || parent_dp == NULL) {
200+
// Create a MemoryMapped() device path node to describe
201+
// the parent image if no device path was provided.
202+
mmdp.memory_type = parent->image_code_type;
203+
mmdp.starting_addr = (unsigned long)parent->image_base;
204+
mmdp.ending_addr = (unsigned long)parent->image_base +
205+
parent->image_size - 1;
206+
parent_dp = &mmdp.header;
207+
dp_len = sizeof(mmdp);
208+
} else {
209+
dp_len = device_path_length(parent_dp);
197210
}
198211

199212
// Allocate some pool memory for device path protocol data
200-
dp_len = parent_dp ? device_path_length(parent_dp) : 0;
201213
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
202214
2 * (dp_len + sizeof(struct efi_rel_offset_dev_path) +
203215
sizeof(struct efi_generic_dev_path)) +

include/linux/efi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,13 @@ struct efi_rel_offset_dev_path {
10041004
u64 ending_offset;
10051005
} __packed;
10061006

1007+
struct efi_mem_mapped_dev_path {
1008+
struct efi_generic_dev_path header;
1009+
u32 memory_type;
1010+
u64 starting_addr;
1011+
u64 ending_addr;
1012+
} __packed;
1013+
10071014
struct efi_dev_path {
10081015
union {
10091016
struct efi_generic_dev_path header;

0 commit comments

Comments
 (0)