implement the efi stub boot on x86, this code is tested on qemu,
and dell latitude 7490. the EFI_ALLOCATE_MAX_PAGES cause an xfuncs
issue on real hardware so I transformed it to allocate any pages.

Signed-off-by: Chali Anis <chalian...@gmail.com>
---
 efi/payload/bootm.c | 139 ++++++++++++++--------------------------------------
 1 file changed, 38 insertions(+), 101 deletions(-)

diff --git a/efi/payload/bootm.c b/efi/payload/bootm.c
index 
ce225ab949c92cb0c52c1334c2395e30b309b781..401aefe28188bb4335f73a8e259a16c605096626
 100644
--- a/efi/payload/bootm.c
+++ b/efi/payload/bootm.c
@@ -133,101 +133,6 @@ static int efi_load_file_image(const char *file,
        return ret;
 }
 
-typedef void(*handover_fn)(void *image, struct efi_system_table *table,
-               struct x86_setup_header *header);
-
-static inline void linux_efi_handover(efi_handle_t handle,
-               struct x86_setup_header *header)
-{
-       handover_fn handover;
-       uintptr_t addr;
-
-       addr = header->code32_start + header->handover_offset;
-       if (IS_ENABLED(CONFIG_X86_64))
-               addr += 512;
-
-       handover = efi_phys_to_virt(addr);
-       handover(handle, efi_sys_table, header);
-}
-
-static int do_bootm_efi(struct image_data *data)
-{
-       void *tmp;
-       void *initrd = NULL;
-       size_t size;
-       efi_handle_t handle;
-       int ret;
-       const char *options;
-       struct efi_loaded_image *loaded_image;
-       struct x86_setup_header *image_header, *boot_header;
-
-       ret = efi_load_file_image(data->os_file, &loaded_image, &handle);
-       if (ret)
-               return ret;
-
-       image_header = (struct x86_setup_header *)loaded_image->image_base;
-
-       if (image_header->boot_flag != 0xAA55 ||
-           image_header->header != 0x53726448 ||
-           image_header->version < 0x20b ||
-           !image_header->relocatable_kernel) {
-               pr_err("Not a valid kernel image!\n");
-               BS->unload_image(handle);
-               return -EINVAL;
-       }
-
-       boot_header = xmalloc(0x4000);
-       memset(boot_header, 0, 0x4000);
-       memcpy(boot_header, image_header, sizeof(*image_header));
-
-       /* Refer to Linux kernel commit a27e292b8a54
-        * ("Documentation/x86/boot: Reserve type_of_loader=13 for barebox")
-        */
-       boot_header->type_of_loader = 0x13;
-
-       if (data->initrd_file) {
-               tmp = read_file(data->initrd_file, &size);
-               initrd = xmemalign(PAGE_SIZE, PAGE_ALIGN(size));
-               memcpy(initrd, tmp, size);
-               memset(initrd + size, 0, PAGE_ALIGN(size) - size);
-               free(tmp);
-               boot_header->ramdisk_image = efi_virt_to_phys(initrd);
-               boot_header->ramdisk_size = PAGE_ALIGN(size);
-       }
-
-       options = linux_bootargs_get();
-       if (options) {
-               boot_header->cmd_line_ptr = efi_virt_to_phys(options);
-               boot_header->cmdline_size = strlen(options);
-       }
-
-       boot_header->code32_start = efi_virt_to_phys(loaded_image->image_base +
-                       (image_header->setup_sects+1) * 512);
-
-       if (bootm_verbose(data)) {
-               printf("\nStarting kernel at 0x%p", loaded_image->image_base);
-               if (data->initrd_file)
-                       printf(", initrd at 0x%08x",
-                              boot_header->ramdisk_image);
-               printf("...\n");
-       }
-
-       if (data->dryrun) {
-               BS->unload_image(handle);
-               free(boot_header);
-               free(initrd);
-               return 0;
-       }
-
-       efi_set_variable_usec("LoaderTimeExecUSec", &efi_systemd_vendor_guid,
-                             ktime_to_us(ktime_get()));
-
-       shutdown_barebox();
-       linux_efi_handover(handle, boot_header);
-
-       return 0;
-}
-
 static bool ramdisk_is_fit(struct image_data *data)
 {
        struct stat st;
@@ -368,9 +273,9 @@ static int efi_load_ramdisk(struct efi_image_data *e)
        }
 
        vmem = efi_allocate_pages(&mem, initrd_size,
-                                EFI_ALLOCATE_MAX_ADDRESS, EFI_LOADER_DATA);
+                                EFI_ALLOCATE_ANY_PAGES, EFI_LOADER_DATA);
        if (!vmem) {
-               pr_err("Failed to allocate pages for initrd data\n");
+               pr_err("Failed to allocate pages for initrd data: %s\n", 
strerror(errno));
                ret = -ENOMEM;
                goto free_pool;
        }
@@ -498,6 +403,9 @@ static int efi_load_fdt(struct efi_image_data *e)
 
 static void efi_unload_fdt(struct efi_image_data *e)
 {
+       if (IS_ENABLED(CONFIG_EFI_FDT_FORCE))
+               return;
+
        BS->install_configuration_table(&efi_fdt_guid, NULL);
 
        efi_free_pages(efi_phys_to_virt(e->oftree_res.base),
@@ -539,12 +447,33 @@ static int do_bootm_efi_stub(struct image_data *data)
        return ret;
 }
 
-static struct image_handler efi_handle_tr = {
+static int efi_app_execute(struct image_data *data)
+{
+       int ret;
+       struct efi_image_data e = { .data = data };
+       enum filetype type;
+
+       ret = efi_load_file_image(data->os_file, &e.loaded_image, &e.handle);
+       if (ret)
+               return ret;
+
+       type = file_detect_type(e.loaded_image->image_base, PAGE_SIZE);
+
+       return efi_execute_image(e.handle, e.loaded_image, type);
+}
+
+static struct image_handler efi_app_handle_tr = {
        .name = "EFI Application",
-       .bootm = do_bootm_efi,
+       .bootm = efi_app_execute,
        .filetype = filetype_exe,
 };
 
+static struct image_handler efi_x86_linux_handle_tr = {
+       .name = "EFI X86 Linux kernel",
+       .bootm = do_bootm_efi_stub,
+       .filetype = filetype_x86_efi_linux_image,
+};
+
 static struct image_handler efi_arm64_handle_tr = {
        .name = "EFI ARM64 Linux kernel",
        .bootm = do_bootm_efi_stub,
@@ -594,13 +523,21 @@ static struct binfmt_hook binfmt_arm64_efi_hook = {
        .hook = efi_execute,
 };
 
+static struct binfmt_hook binfmt_x86_efi_hook = {
+       .type = filetype_x86_efi_linux_image,
+       .hook = efi_execute,
+};
+
 static int efi_register_image_handler(void)
 {
-       register_image_handler(&efi_handle_tr);
+       register_image_handler(&efi_app_handle_tr);
        binfmt_register(&binfmt_efi_hook);
 
-       if (IS_ENABLED(CONFIG_X86))
+       if (IS_ENABLED(CONFIG_X86)) {
                register_image_handler(&non_efi_handle_linux_x86);
+               register_image_handler(&efi_x86_linux_handle_tr);
+               binfmt_register(&binfmt_x86_efi_hook);
+       }
 
        if (IS_ENABLED(CONFIG_ARM64)) {
                register_image_handler(&efi_arm64_handle_tr);

-- 
2.34.1


Reply via email to