From 8f7e2b2980a2d964db60a19a5d2ef8532caddf7d Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 26 Dec 2018 12:49:09 +0100 Subject: [PATCH] efi_loader: set entry point in efi_load_pe() Up to now efi_load_pe() returns the entry point or NULL in case of an error. This does not allow to return correct error codes from LoadImage(). Let efi_load_pe() return a status code and fill in the entry point in the corresponding field of the image object. Signed-off-by: Heinrich Schuchardt --- cmd/bootefi.c | 13 ++++------- include/efi_loader.h | 4 ++-- lib/efi_loader/efi_boottime.c | 6 ++--- lib/efi_loader/efi_image_loader.c | 37 ++++++++++++++++++------------- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index ee685d8644..7f9913c0ee 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -266,9 +266,6 @@ static efi_status_t do_bootefi_exec(void *efi, struct efi_loaded_image_obj *image_obj = NULL; struct efi_loaded_image *loaded_image_info = NULL; - EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, - struct efi_system_table *st); - /* * Special case for efi payload not loaded from disk, such as * 'bootefi hello' or for example payload loaded directly into @@ -300,11 +297,9 @@ static efi_status_t do_bootefi_exec(void *efi, goto err_prepare; /* Load the EFI payload */ - entry = efi_load_pe(image_obj, efi, loaded_image_info); - if (!entry) { - ret = EFI_LOAD_ERROR; + ret = efi_load_pe(image_obj, efi, loaded_image_info); + if (ret != EFI_SUCCESS) goto err_prepare; - } if (memdp) { struct efi_device_path_memory *mdp = (void *)memdp; @@ -319,14 +314,14 @@ static efi_status_t do_bootefi_exec(void *efi, "{ro,boot}(blob)0000000000000000"); /* Call our payload! */ - debug("%s: Jumping to 0x%p\n", __func__, entry); + debug("%s: Jumping to 0x%p\n", __func__, image_obj->entry); if (setjmp(&image_obj->exit_jmp)) { ret = image_obj->exit_status; goto err_prepare; } - ret = efi_do_enter(&image_obj->header, &systab, entry); + ret = efi_do_enter(&image_obj->header, &systab, image_obj->entry); err_prepare: /* image has returned, loaded-image obj goes *poof*: */ diff --git a/include/efi_loader.h b/include/efi_loader.h index 6a98981ebb..3ce43f7a6f 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -301,8 +301,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(struct efi_loaded_image_obj *handle, void *efi, - struct efi_loaded_image *loaded_image_info); +efi_status_t 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 diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index b1c0007e5a..155cdc5a23 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1738,11 +1738,9 @@ static efi_status_t EFIAPI efi_load_image(bool boot_policy, ret = efi_setup_loaded_image(dp, fp, image_obj, &info); if (ret != EFI_SUCCESS) goto error_invalid_image; - (*image_obj)->entry = efi_load_pe(*image_obj, source_buffer, info); - if (!(*image_obj)->entry) { - ret = EFI_UNSUPPORTED; + ret = efi_load_pe(*image_obj, source_buffer, info); + if (ret != EFI_SUCCESS) goto error_invalid_image; - } /* Update the type of the allocated memory */ efi_add_memory_map((uintptr_t)source_buffer, efi_size_in_pages(source_size), diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index a18ce0a570..b55c2840e8 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -193,13 +193,19 @@ static void efi_set_code_and_data_type( } } -/* +/** + * efi_load_pe() - relocate EFI binary + * * This function loads all sections from a PE binary into a newly reserved - * piece of memory. On successful load it then returns the entry point for - * the binary. Otherwise NULL. + * piece of memory. On success the entry point is returned as handle->entry. + * + * @handle: loaded image handle + * @efi: pointer to the EFI binary + * @loaded_image_info: loaded image protocol + * Return: status code */ -void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, - struct efi_loaded_image *loaded_image_info) +efi_status_t 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; @@ -210,7 +216,6 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, const IMAGE_BASE_RELOCATION *rel; unsigned long rel_size; int rel_idx = IMAGE_DIRECTORY_ENTRY_BASERELOC; - void *entry; uint64_t image_base; uint64_t image_size; unsigned long virt_size = 0; @@ -219,13 +224,13 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, dos = efi; if (dos->e_magic != IMAGE_DOS_SIGNATURE) { printf("%s: Invalid DOS Signature\n", __func__); - return NULL; + return EFI_LOAD_ERROR; } nt = (void *) ((char *)efi + dos->e_lfanew); if (nt->Signature != IMAGE_NT_SIGNATURE) { printf("%s: Invalid NT Signature\n", __func__); - return NULL; + return EFI_LOAD_ERROR; } for (i = 0; machines[i]; i++) @@ -237,7 +242,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, if (!supported) { printf("%s: Machine type 0x%04x is not supported\n", __func__, nt->FileHeader.Machine); - return NULL; + return EFI_LOAD_ERROR; } /* Calculate upper virtual address boundary */ @@ -263,9 +268,9 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, if (!efi_reloc) { printf("%s: Could not allocate %lu bytes\n", __func__, virt_size); - return NULL; + return EFI_OUT_OF_RESOURCES; } - entry = efi_reloc + opt->AddressOfEntryPoint; + handle->entry = efi_reloc + opt->AddressOfEntryPoint; rel_size = opt->DataDirectory[rel_idx].Size; rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress; virt_size = ALIGN(virt_size, opt->SectionAlignment); @@ -279,16 +284,16 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, if (!efi_reloc) { printf("%s: Could not allocate %lu bytes\n", __func__, virt_size); - return NULL; + return EFI_OUT_OF_RESOURCES; } - entry = efi_reloc + opt->AddressOfEntryPoint; + handle->entry = efi_reloc + opt->AddressOfEntryPoint; rel_size = opt->DataDirectory[rel_idx].Size; rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress; virt_size = ALIGN(virt_size, opt->SectionAlignment); } else { printf("%s: Invalid optional header magic %x\n", __func__, nt->OptionalHeader.Magic); - return NULL; + return EFI_LOAD_ERROR; } /* Load sections into RAM */ @@ -306,7 +311,7 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, (unsigned long)image_base) != EFI_SUCCESS) { efi_free_pages((uintptr_t) efi_reloc, (virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT); - return NULL; + return EFI_LOAD_ERROR; } /* Flush cache */ @@ -320,5 +325,5 @@ void *efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, handle->reloc_base = efi_reloc; handle->reloc_size = virt_size; - return entry; + return EFI_SUCCESS; } -- 2.30.2