x86: zimage: Support booting Linux kernel from an EFI payload
authorBin Meng <bmeng.cn@gmail.com>
Thu, 23 Aug 2018 15:24:10 +0000 (08:24 -0700)
committerBin Meng <bmeng.cn@gmail.com>
Thu, 30 Aug 2018 03:23:14 +0000 (11:23 +0800)
At present Linux kernel loaded from U-Boot as an EFI payload does
not boot. This fills in kernel's boot params structure with the
required critical EFI information like system table address and
memory map stuff so that kernel can obtain essential data like
runtime services and ACPI table to boot.

With this patch, now U-Boot as an EFI payload becomes much more
practical: it is another option of kernel bootloader, ie, can be
a replacement for grub.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
arch/x86/cpu/efi/payload.c
arch/x86/include/asm/zimage.h
arch/x86/lib/zimage.c
include/efi.h

index 0e7c7c1ba49dc4389ac0e75f867130c25bfdbff5..c323c7b19a592d50e6c891f567cfd25d5f2e205f 100644 (file)
@@ -8,6 +8,7 @@
 #include <efi.h>
 #include <errno.h>
 #include <usb.h>
+#include <asm/bootparam.h>
 #include <asm/e820.h>
 #include <asm/post.h>
 
@@ -250,3 +251,39 @@ unsigned int install_e820_map(unsigned int max_entries,
 
        return num_entries;
 }
+
+void setup_efi_info(struct efi_info *efi_info)
+{
+       struct efi_entry_systable *table;
+       struct efi_entry_memmap *map;
+       char *signature;
+       int size, ret;
+
+       memset(efi_info, 0, sizeof(struct efi_info));
+
+       ret = efi_info_get(EFIET_SYS_TABLE, (void **)&table, &size);
+       if (ret) {
+               printf("Cannot find EFI system table, ret=%d\n", ret);
+               return;
+       }
+       efi_info->efi_systab = (u32)(table->sys_table);
+
+       ret = efi_info_get(EFIET_MEMORY_MAP, (void **)&map, &size);
+       if (ret) {
+               printf("Cannot find EFI memory map tables, ret=%d\n", ret);
+               return;
+       }
+       efi_info->efi_memdesc_size = map->desc_size;
+       efi_info->efi_memdesc_version = map->version;
+       efi_info->efi_memmap = (u32)(map->desc);
+       efi_info->efi_memmap_size = size - sizeof(struct efi_entry_memmap);
+
+#ifdef CONFIG_EFI_STUB_64BIT
+       efi_info->efi_systab_hi = table->sys_table >> 32;
+       efi_info->efi_memmap_hi = (u64)(u32)(map->desc) >> 32;
+       signature = EFI64_LOADER_SIGNATURE;
+#else
+       signature = EFI32_LOADER_SIGNATURE;
+#endif
+       memcpy(&efi_info->efi_loader_signature, signature, 4);
+}
index 03bed54d0bdf09d47ce1c79e06093424c7a8f396..80e128ccf36f980b2e512fd513bd3bd92cb1f432 100644 (file)
@@ -35,5 +35,6 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size,
 int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
                 unsigned long initrd_addr, unsigned long initrd_size);
 void setup_video(struct screen_info *screen_info);
+void setup_efi_info(struct efi_info *efi_info);
 
 #endif
index 04ed972482d085bb432af91edbb00ea88e08704b..0442fda760652a2e57ff1aea027a979d319442ec 100644 (file)
@@ -295,6 +295,10 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
        setup_device_tree(hdr, (const void *)env_get_hex("fdtaddr", 0));
        setup_video(&setup_base->screen_info);
 
+#ifdef CONFIG_EFI_STUB
+       setup_efi_info(&setup_base->efi_info);
+#endif
+
        return 0;
 }
 
index 63017c86f252f42ae6e709832935efe10250975d..e1854ecd23bb8845ee1ed812ef19607a95ec2a68 100644 (file)
@@ -41,6 +41,9 @@
 #define efi_va_end va_end
 #endif /* __x86_64__ */
 
+#define EFI32_LOADER_SIGNATURE "EL32"
+#define EFI64_LOADER_SIGNATURE "EL64"
+
 struct efi_device_path;
 
 typedef struct {