
Currently we expect the loaded image handle to point to the loaded image protocol. Additionally we have appended private fields to the protocol.
With the patch the handle points to a loaded image object and the private fields are added here. This matches how we handle the net and the gop object.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- cmd/bootefi.c | 14 ++++---- include/efi_api.h | 8 ----- include/efi_loader.h | 21 ++++++++--- lib/efi_loader/efi_boottime.c | 58 +++++++++++++------------------ lib/efi_loader/efi_image_loader.c | 23 ++++++------ 5 files changed, 62 insertions(+), 62 deletions(-)
diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 3ca0d588dd..f76f29a7b1 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -343,7 +343,7 @@ static efi_status_t do_bootefi_exec(void *efi, efi_handle_t mem_handle = NULL; struct efi_device_path *memdp = NULL; efi_status_t ret; - efi_handle_t image_handle; + struct efi_loaded_image_obj *image_handle; struct efi_loaded_image *loaded_image_info;
EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, @@ -386,7 +386,7 @@ static efi_status_t do_bootefi_exec(void *efi, /* Transfer environment variable bootargs as load options */ set_load_options(loaded_image_info, "bootargs"); /* Load the EFI payload */ - entry = efi_load_pe(efi, loaded_image_info); + entry = efi_load_pe(image_handle, efi, loaded_image_info); if (!entry) { ret = EFI_LOAD_ERROR; goto exit; @@ -407,8 +407,8 @@ static efi_status_t do_bootefi_exec(void *efi, /* Call our payload! */ debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
- if (setjmp(&loaded_image_info->exit_jmp)) { - ret = loaded_image_info->exit_status; + if (setjmp(&image_handle->exit_jmp)) { + ret = image_handle->exit_status; goto exit; }
@@ -450,7 +450,7 @@ static efi_status_t do_bootefi_exec(void *efi, exit: /* image has returned, loaded-image obj goes *poof*: */ if (image_handle) - efi_delete_handle(image_handle); + efi_delete_handle(&image_handle->parent); if (mem_handle) efi_delete_handle(mem_handle);
@@ -535,7 +535,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #endif #ifdef CONFIG_CMD_BOOTEFI_SELFTEST if (!strcmp(argv[1], "selftest")) { - efi_handle_t image_handle; + struct efi_loaded_image_obj *image_handle; struct efi_loaded_image *loaded_image_info;
/* Construct a dummy device path. */ @@ -558,7 +558,7 @@ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) r = efi_selftest(image_handle, &systab); efi_restore_gd(); free(loaded_image_info->load_options); - efi_delete_handle(image_handle); + efi_delete_handle(&image_handle->parent); return r != EFI_SUCCESS; } else #endif diff --git a/include/efi_api.h b/include/efi_api.h index 5004f520ff..c42df6900a 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -340,14 +340,6 @@ struct efi_loaded_image { unsigned int image_code_type; unsigned int image_data_type; unsigned long unload; - - /* Below are efi loader private fields */ -#ifdef CONFIG_EFI_LOADER - void *reloc_base; - aligned_u64 reloc_size; - efi_status_t exit_status; - struct jmp_buf_data exit_jmp; -#endif };
#define DEVICE_PATH_GUID \ diff --git a/include/efi_loader.h b/include/efi_loader.h index d665627e91..74df070316 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -189,6 +189,20 @@ struct efi_object { void *handle; };
+/** + * struct efi_loaded_image_obj - handle of a loaded image + */ +struct efi_loaded_image_obj { + /* Generic EFI object parent class data */ + struct efi_object parent; + void *reloc_base; + aligned_u64 reloc_size; + efi_status_t exit_status; + struct jmp_buf_data exit_jmp; + EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, + struct efi_system_table *st); +}; + /** * struct efi_event * @@ -270,7 +284,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout); /* Called from places to check whether a timer expired */ void efi_timer_check(void); /* PE loader implementation */ -void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info); +void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, + struct efi_loaded_image *loaded_image_info); /* Called once to store the pristine gd pointer */ void efi_save_gd(void); /* Special case handler for error/abort that just tries to dtrt to get @@ -353,12 +368,10 @@ efi_status_t efi_install_configuration_table(const efi_guid_t *guid, void *table /* Sets up a loaded image */ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path, - efi_handle_t *handle_ptr, + struct efi_loaded_image_obj **handle_ptr, struct efi_loaded_image **info_ptr); efi_status_t efi_load_image_from_path(struct efi_device_path *file_path, void **buffer); -/* Print information about a loaded image */ -efi_status_t efi_print_image_info(struct efi_loaded_image *image, void *pc); /* Print information about all loaded images */ void efi_print_image_infos(void *pc);
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index bc230f6824..2496608981 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1480,12 +1480,12 @@ static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid, */ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, struct efi_device_path *file_path, - efi_handle_t *handle_ptr, + struct efi_loaded_image_obj **handle_ptr, struct efi_loaded_image **info_ptr) { efi_status_t ret; struct efi_loaded_image *info; - struct efi_object *obj; + struct efi_loaded_image_obj *obj;
info = calloc(1, sizeof(*info)); if (!info) @@ -1497,14 +1497,12 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, }
/* Add internal object to object list */ - efi_add_handle(obj); - /* efi_exit() assumes that the handle points to the info */ - obj->handle = info; + efi_add_handle(&obj->parent);
- if (handle_ptr) - *handle_ptr = obj->handle; if (info_ptr) *info_ptr = info; + if (handle_ptr) + *handle_ptr = obj;
info->revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION; info->file_path = file_path; @@ -1516,8 +1514,8 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the device path interface, return * bootefi_device_path */ - ret = efi_add_protocol(obj->handle, &efi_guid_device_path, - device_path); + ret = efi_add_protocol(obj->parent.handle, + &efi_guid_device_path, device_path); if (ret != EFI_SUCCESS) goto failure; } @@ -1526,7 +1524,8 @@ efi_status_t efi_setup_loaded_image(struct efi_device_path *device_path, * When asking for the loaded_image interface, just * return handle which points to loaded_image_info */ - ret = efi_add_protocol(obj->handle, &efi_guid_loaded_image, info); + ret = efi_add_protocol(obj->parent.handle, + &efi_guid_loaded_image, info); if (ret != EFI_SUCCESS) goto failure;
@@ -1609,6 +1608,8 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_handle_t *image_handle) { struct efi_loaded_image *info; + struct efi_loaded_image_obj **image_obj = + (struct efi_loaded_image_obj **)image_handle; efi_status_t ret;
EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image, @@ -1635,20 +1636,19 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, * file parts: */ efi_dp_split_file_path(file_path, &dp, &fp); - ret = efi_setup_loaded_image(dp, fp, image_handle, &info); + ret = efi_setup_loaded_image(dp, fp, image_obj, &info); if (ret != EFI_SUCCESS) goto failure; } else { /* In this case, file_path is the "device" path, i.e. * something like a HARDWARE_DEVICE:MEMORY_MAPPED */ - ret = efi_setup_loaded_image(file_path, NULL, image_handle, - &info); + ret = efi_setup_loaded_image(file_path, NULL, image_obj, &info); if (ret != EFI_SUCCESS) goto error; } - info->reserved = efi_load_pe(source_buffer, info); - if (!info->reserved) { + (*image_obj)->entry = efi_load_pe(*image_obj, source_buffer, info); + if (!(*image_obj)->entry) { ret = EFI_UNSUPPORTED; goto failure; } @@ -1680,18 +1680,16 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, unsigned long *exit_data_size, s16 **exit_data) { - EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, - struct efi_system_table *st); - struct efi_loaded_image *info = image_handle; + struct efi_loaded_image_obj *image_obj = + (struct efi_loaded_image_obj *)image_handle; efi_status_t ret;
EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data); - entry = info->reserved;
efi_is_direct_boot = false;
/* call the image! */ - if (setjmp(&info->exit_jmp)) { + if (setjmp(&image_obj->exit_jmp)) { /* * We called the entry point of the child image with EFI_CALL * in the lines below. The child image called the Exit() boot @@ -1714,12 +1712,12 @@ static efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, assert(__efi_entry_check()); debug("%sEFI: %lu returned by started image\n", __efi_nesting_dec(), - (unsigned long)((uintptr_t)info->exit_status & + (unsigned long)((uintptr_t)image_obj->exit_status & ~EFI_ERROR_MASK)); - return EFI_EXIT(info->exit_status); + return EFI_EXIT(image_obj->exit_status); }
- ret = EFI_CALL(entry(image_handle, &systab)); + ret = EFI_CALL(image_obj->entry(image_handle, &systab));
/* * Usually UEFI applications call Exit() instead of returning. @@ -1750,17 +1748,11 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, int16_t *exit_data) { /* - * We require that the handle points to the original loaded - * image protocol interface. - * - * For getting the longjmp address this is safer than locating - * the protocol because the protocol may have been reinstalled - * pointing to another memory location. - * * TODO: We should call the unload procedure of the loaded * image protocol. */ - struct efi_loaded_image *loaded_image_info = (void *)image_handle; + struct efi_loaded_image_obj *image_obj = + (struct efi_loaded_image_obj *)image_handle;
EFI_ENTRY("%p, %ld, %ld, %p", image_handle, exit_status, exit_data_size, exit_data); @@ -1774,8 +1766,8 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, */ efi_restore_gd();
- loaded_image_info->exit_status = exit_status; - longjmp(&loaded_image_info->exit_jmp, 1); + image_obj->exit_status = exit_status; + longjmp(&image_obj->exit_jmp, 1);
panic("EFI application exited"); } diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index fdf40a62c8..a18ce0a570 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -48,20 +48,21 @@ static int machines[] = { * If the program counter is located within the image the offset to the base * address is shown. * + * @obj: EFI object * @image: loaded image * @pc: program counter (use NULL to suppress offset output) * @return: status code */ -efi_status_t efi_print_image_info(struct efi_loaded_image *image, void *pc) +static efi_status_t efi_print_image_info(struct efi_loaded_image_obj *obj, + struct efi_loaded_image *image, + void *pc) { - if (!image) - return EFI_INVALID_PARAMETER; printf("UEFI image"); printf(" [0x%p:0x%p]", - image->reloc_base, image->reloc_base + image->reloc_size - 1); - if (pc && pc >= image->reloc_base && - pc < image->reloc_base + image->reloc_size) - printf(" pc=0x%zx", pc - image->reloc_base); + obj->reloc_base, obj->reloc_base + obj->reloc_size - 1); + if (pc && pc >= obj->reloc_base && + pc < obj->reloc_base + obj->reloc_size) + printf(" pc=0x%zx", pc - obj->reloc_base); if (image->file_path) printf(" '%pD'", image->file_path); printf("\n"); @@ -82,6 +83,7 @@ void efi_print_image_infos(void *pc) list_for_each_entry(handler, &efiobj->protocols, link) { if (!guidcmp(handler->guid, &efi_guid_loaded_image)) { efi_print_image_info( + (struct efi_loaded_image_obj *)efiobj, handler->protocol_interface, pc); } } @@ -196,7 +198,8 @@ static void efi_set_code_and_data_type( * piece of memory. On successful load it then returns the entry point for * the binary. Otherwise NULL. */ -void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) +void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, + struct efi_loaded_image *loaded_image_info) { IMAGE_NT_HEADERS32 *nt; IMAGE_DOS_HEADER *dos; @@ -314,8 +317,8 @@ void *efi_load_pe(void *efi, struct efi_loaded_image *loaded_image_info) /* Populate the loaded image interface bits */ loaded_image_info->image_base = efi; loaded_image_info->image_size = image_size; - loaded_image_info->reloc_base = efi_reloc; - loaded_image_info->reloc_size = virt_size; + handle->reloc_base = efi_reloc; + handle->reloc_size = virt_size;
return entry; }