efi_loader: set entry point in efi_load_pe()
authorHeinrich Schuchardt <xypron.glpk@gmx.de>
Wed, 26 Dec 2018 11:49:09 +0000 (12:49 +0100)
committerHeinrich Schuchardt <xypron.glpk@gmx.de>
Sat, 16 Feb 2019 14:42:20 +0000 (15:42 +0100)
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 <xypron.glpk@gmx.de>
cmd/bootefi.c
include/efi_loader.h
lib/efi_loader/efi_boottime.c
lib/efi_loader/efi_image_loader.c

index ee685d8..7f9913c 100644 (file)
@@ -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*: */
index 6a98981..3ce43f7 100644 (file)
@@ -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
index b1c0007..155cdc5 100644 (file)
@@ -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),
index a18ce0a..b55c284 100644 (file)
@@ -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;
 }