diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/Kconfig | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/bootm.h | 12 | ||||
-rw-r--r-- | arch/x86/include/asm/bootparam.h | 70 | ||||
-rw-r--r-- | arch/x86/include/asm/cpu.h | 1 | ||||
-rw-r--r-- | arch/x86/lib/bootm.c | 43 | ||||
-rw-r--r-- | arch/x86/lib/zimage.c | 17 |
6 files changed, 104 insertions, 43 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 07be5cd..99e59d9 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -32,8 +32,8 @@ config X86_RUN_32BIT config X86_RUN_64BIT bool "64-bit" select X86_64 - select SPL - select SPL_SEPARATE_BSS + select SPL if !EFI_APP + select SPL_SEPARATE_BSS if !EFI_APP help Build U-Boot as a 64-bit binary with a 32-bit SPL. This is experimental and many features are missing. U-Boot SPL starts up, diff --git a/arch/x86/include/asm/bootm.h b/arch/x86/include/asm/bootm.h index 109f686..3b64178 100644 --- a/arch/x86/include/asm/bootm.h +++ b/arch/x86/include/asm/bootm.h @@ -14,14 +14,14 @@ void bootm_announce_and_cleanup(void); * This boots a kernel image, either 32-bit or 64-bit. It will also work with * a self-extracting kernel, if you set @image_64bit to false. * - * @setup_base: Pointer to the setup.bin information for the kernel - * @load_address: Pointer to the start of the kernel image - * @image_64bit: true if the image is a raw 64-bit kernel, false if it - * is raw 32-bit or any type of self-extracting kernel - * such as a bzImage. + * @setup_base: Address of the setup.bin information for the kernel + * @entry: Address of the kernel entry point + * @image_64bit: true if the image is a raw 64-bit kernel, or a kernel + * which supports booting in 64-bit mode; false if it is raw 32-bit or any type + * of self-extracting kernel such as a bzImage. * Return: -ve error code. This function does not return if the kernel was * booted successfully. */ -int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit); +int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit); #endif diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h index 7a3c1f5..ea816ca 100644 --- a/arch/x86/include/asm/bootparam.h +++ b/arch/x86/include/asm/bootparam.h @@ -9,19 +9,54 @@ #include <asm/ist.h> #include <asm/video/edid.h> -/* setup data types */ -enum { - SETUP_NONE = 0, - SETUP_E820_EXT, - SETUP_DTB, -}; +/* setup_data/setup_indirect types */ +#define SETUP_NONE 0 +#define SETUP_E820_EXT 1 +#define SETUP_DTB 2 +#define SETUP_PCI 3 +#define SETUP_EFI 4 +#define SETUP_APPLE_PROPERTIES 5 +#define SETUP_JAILHOUSE 6 +#define SETUP_CC_BLOB 7 +#define SETUP_IMA 8 +#define SETUP_RNG_SEED 9 +#define SETUP_ENUM_MAX SETUP_RNG_SEED + +#define SETUP_INDIRECT BIT(31) +#define SETUP_TYPE_MAX (SETUP_ENUM_MAX | SETUP_INDIRECT) + +/* ram_size flags */ +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 + +/* loadflags */ +#define LOADED_HIGH BIT(0) +#define KASLR_FLAG BIT(1) +#define QUIET_FLAG BIT(5) +#define KEEP_SEGMENTS BIT(6) +#define CAN_USE_HEAP BIT(7) + +#define XLF_KERNEL_64 BIT(0) +#define XLF_CAN_BE_LOADED_ABOVE_4G BIT(1) +#define XLF_EFI_HANDOVER_32 BIT(2) +#define XLF_EFI_HANDOVER_64 BIT(3) +#define XLF_EFI_KEXEC BIT(4) /* extensible setup data list node */ struct setup_data { __u64 next; __u32 type; __u32 len; - __u8 data[0]; + __u8 data[]; +}; + +/* extensible setup indirect data node */ +struct setup_indirect { + __u32 type; + __u32 reserved; /* Reserved, must be set to zero. */ + __u64 len; + __u64 addr; }; /** @@ -34,9 +69,6 @@ struct setup_header { __u16 root_flags; __u32 syssize; __u16 ram_size; -#define RAMDISK_IMAGE_START_MASK 0x07FF -#define RAMDISK_PROMPT_FLAG 0x8000 -#define RAMDISK_LOAD_FLAG 0x4000 __u16 vid_mode; __u16 root_dev; __u16 boot_flag; @@ -44,15 +76,10 @@ struct setup_header { __u32 header; __u16 version; __u32 realmode_swtch; - __u16 start_sys; + __u16 start_sys_seg; __u16 kernel_version; __u8 type_of_loader; __u8 loadflags; -#define LOADED_HIGH BIT(0) -#define KASLR_FLAG BIT(1) -#define QUIET_FLAG BIT(5) -#define KEEP_SEGMENTS BIT(6) /* Obsolete */ -#define CAN_USE_HEAP BIT(7) __u16 setup_move_size; __u32 code32_start; __u32 ramdisk_image; @@ -65,13 +92,8 @@ struct setup_header { __u32 initrd_addr_max; __u32 kernel_alignment; __u8 relocatable_kernel; - u8 min_alignment; -#define XLF_KERNEL_64 BIT(0) -#define XLF_CAN_BE_LOADED_ABOVE_4G BIT(1) -#define XLF_EFI_HANDOVER_32 BIT(2) -#define XLF_EFI_HANDOVER_64 BIT(3) -#define XLF_EFI_KEXEC BIT(4) - u16 xloadflags; + __u8 min_alignment; + __u16 xloadflags; __u32 cmdline_size; __u32 hardware_subarch; __u64 hardware_subarch_data; @@ -81,7 +103,7 @@ struct setup_header { __u64 pref_address; __u32 init_size; __u32 handover_offset; - u32 kernel_info_offset; + __u32 kernel_info_offset; } __attribute__((packed)); struct sys_desc_table { diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 3346012..073f80b 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -262,6 +262,7 @@ void cpu_call32(ulong code_seg32, ulong target, ulong table); * * @setup_base: Pointer to the setup.bin information for the kernel * @target: Pointer to the start of the kernel image + * Return: -EFAULT if the kernel returned; otherwise does not return */ int cpu_jump_to_64bit(ulong setup_base, ulong target); diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index 873e2bc..61cb7bc 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -10,6 +10,7 @@ #include <common.h> #include <bootstage.h> #include <command.h> +#include <efi.h> #include <hang.h> #include <log.h> #include <asm/global_data.h> @@ -149,26 +150,52 @@ error: return 1; } -int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit) +int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit) { bootm_announce_and_cleanup(); #ifdef CONFIG_SYS_COREBOOT timestamp_add_now(TS_U_BOOT_START_KERNEL); #endif + + /* + * Exit EFI boot services just before jumping, after all console + * output, since the console won't be available afterwards. + */ + if (IS_ENABLED(CONFIG_EFI_APP)) { + int ret; + + ret = efi_store_memory_map(efi_get_priv()); + if (ret) + return ret; + printf("Exiting EFI boot services\n"); + ret = efi_call_exit_boot_services(); + if (ret) + return ret; + } + if (image_64bit) { if (!cpu_has_64bit()) { puts("Cannot boot 64-bit kernel on 32-bit machine\n"); return -EFAULT; } - /* At present 64-bit U-Boot does not support booting a + /* + * At present 64-bit U-Boot only supports booting a 64-bit * kernel. - * TODO(sjg@chromium.org): Support booting both 32-bit and - * 64-bit kernels from 64-bit U-Boot. + * + * TODO(sjg@chromium.org): Support booting 32-bit kernels from + * 64-bit U-Boot */ -#if !CONFIG_IS_ENABLED(X86_64) - return cpu_jump_to_64bit(setup_base, load_address); -#endif + if (CONFIG_IS_ENABLED(X86_64)) { + typedef void (*h_func)(ulong zero, ulong setup); + h_func func; + + /* jump to Linux with rdi=0, rsi=setup_base */ + func = (h_func)entry; + func(0, setup_base); + } else { + return cpu_jump_to_64bit(setup_base, entry); + } } else { /* * Set %ebx, %ebp, and %edi to 0, %esi to point to the @@ -190,7 +217,7 @@ int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit) "movl $0, %%ebp\n" "cli\n" "jmp *%[kernel_entry]\n" - :: [kernel_entry]"a"(load_address), + :: [kernel_entry]"a"(entry), [boot_params] "S"(setup_base), "b"(0), "D"(0) ); diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index 9cc0449..e5ea512 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -504,13 +504,24 @@ static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc, static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + struct boot_params *params = state.base_ptr; + struct setup_header *hdr = ¶ms->hdr; + bool image_64bit; + ulong entry; int ret; disable_interrupts(); + entry = state.load_address; + image_64bit = false; + if (IS_ENABLED(CONFIG_X86_RUN_64BIT) && + (hdr->xloadflags & XLF_KERNEL_64)) { + entry += 0x200; + image_64bit = true; + } + /* we assume that the kernel is in place */ - ret = boot_linux_kernel((ulong)state.base_ptr, state.load_address, - false); + ret = boot_linux_kernel((ulong)state.base_ptr, entry, image_64bit); printf("Kernel returned! (err=%d)\n", ret); return CMD_RET_FAILURE; @@ -655,7 +666,7 @@ void zimage_dump(struct boot_params *base_ptr) printf("%-20s %s\n", "", "Ancient kernel, using version 100"); print_num("Version", hdr->version); print_num("Real mode switch", hdr->realmode_swtch); - print_num("Start sys", hdr->start_sys); + print_num("Start sys seg", hdr->start_sys_seg); print_num("Kernel version", hdr->kernel_version); version = get_kernel_version(base_ptr, (void *)state.bzimage_addr); if (version) |