aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2014-01-10 13:52:06 -0500
committerMatt Fleming <matt.fleming@intel.com>2014-03-04 16:43:57 -0500
commit7d453eee36ae4cf30fc2f2faae54f634c4f863b7 (patch)
treeccfb0d45555281eba81bab3548e541570da99ee2
parent4f9dbcfc40299ddaa780fe8c1cd74998c1be3af5 (diff)
x86/efi: Wire up CONFIG_EFI_MIXED
Add the Kconfig option and bump the kernel header version so that boot loaders can check whether the handover code is available if they want. The xloadflags field in the bzImage header is also updated to reflect that the kernel supports both entry points by setting both of XLF_EFI_HANDOVER_32 and XLF_EFI_HANDOVER_64 when CONFIG_EFI_MIXED=y. XLF_CAN_BE_LOADED_ABOVE_4G is disabled so that the kernel text is guaranteed to be addressable with 32-bits. Note that no boot loaders should be using the bits set in xloadflags to decide which entry point to jump to. The entire scheme is based on the concept that 32-bit bootloaders always jump to ->handover_offset and 64-bit loaders always jump to ->handover_offset + 512. We set both bits merely to inform the boot loader that it's safe to use the native handover offset even if the machine type in the PE/COFF header claims otherwise. Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r--arch/x86/Kconfig14
-rw-r--r--arch/x86/boot/header.S15
-rw-r--r--arch/x86/include/asm/efi.h11
-rw-r--r--arch/x86/kernel/setup.c2
-rw-r--r--arch/x86/platform/efi/efi.c2
5 files changed, 37 insertions, 7 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0af5250d914f..8453fe1342ea 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1585,6 +1585,20 @@ config EFI_STUB
1585 1585
1586 See Documentation/efi-stub.txt for more information. 1586 See Documentation/efi-stub.txt for more information.
1587 1587
1588config EFI_MIXED
1589 bool "EFI mixed-mode support"
1590 depends on EFI_STUB && X86_64
1591 ---help---
1592 Enabling this feature allows a 64-bit kernel to be booted
1593 on a 32-bit firmware, provided that your CPU supports 64-bit
1594 mode.
1595
1596 Note that it is not possible to boot a mixed-mode enabled
1597 kernel via the EFI boot stub - a bootloader that supports
1598 the EFI handover protocol must be used.
1599
1600 If unsure, say N.
1601
1588config SECCOMP 1602config SECCOMP
1589 def_bool y 1603 def_bool y
1590 prompt "Enable seccomp to safely compute untrusted bytecode" 1604 prompt "Enable seccomp to safely compute untrusted bytecode"
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index d69d96653325..256388260c88 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -283,7 +283,7 @@ _start:
283 # Part 2 of the header, from the old setup.S 283 # Part 2 of the header, from the old setup.S
284 284
285 .ascii "HdrS" # header signature 285 .ascii "HdrS" # header signature
286 .word 0x020c # header version number (>= 0x0105) 286 .word 0x020d # header version number (>= 0x0105)
287 # or else old loadlin-1.5 will fail) 287 # or else old loadlin-1.5 will fail)
288 .globl realmode_swtch 288 .globl realmode_swtch
289realmode_swtch: .word 0, 0 # default_switch, SETUPSEG 289realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
@@ -375,7 +375,8 @@ xloadflags:
375# define XLF0 0 375# define XLF0 0
376#endif 376#endif
377 377
378#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64) 378#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64) && \
379 !defined(CONFIG_EFI_MIXED)
379 /* kernel/boot_param/ramdisk could be loaded above 4g */ 380 /* kernel/boot_param/ramdisk could be loaded above 4g */
380# define XLF1 XLF_CAN_BE_LOADED_ABOVE_4G 381# define XLF1 XLF_CAN_BE_LOADED_ABOVE_4G
381#else 382#else
@@ -383,10 +384,14 @@ xloadflags:
383#endif 384#endif
384 385
385#ifdef CONFIG_EFI_STUB 386#ifdef CONFIG_EFI_STUB
386# ifdef CONFIG_X86_64 387# ifdef CONFIG_EFI_MIXED
387# define XLF23 XLF_EFI_HANDOVER_64 /* 64-bit EFI handover ok */ 388# define XLF23 (XLF_EFI_HANDOVER_32|XLF_EFI_HANDOVER_64)
388# else 389# else
389# define XLF23 XLF_EFI_HANDOVER_32 /* 32-bit EFI handover ok */ 390# ifdef CONFIG_X86_64
391# define XLF23 XLF_EFI_HANDOVER_64 /* 64-bit EFI handover ok */
392# else
393# define XLF23 XLF_EFI_HANDOVER_32 /* 32-bit EFI handover ok */
394# endif
390# endif 395# endif
391#else 396#else
392# define XLF23 0 397# define XLF23 0
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 85935e6f69f3..a3837254e320 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -152,6 +152,17 @@ static inline bool efi_is_native(void)
152 return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT); 152 return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT);
153} 153}
154 154
155static inline bool efi_runtime_supported(void)
156{
157 if (efi_is_native())
158 return true;
159
160 if (IS_ENABLED(CONFIG_EFI_MIXED) && !efi_enabled(EFI_OLD_MEMMAP))
161 return true;
162
163 return false;
164}
165
155extern struct console early_efi_console; 166extern struct console early_efi_console;
156extern void parse_efi_setup(u64 phys_addr, u32 data_len); 167extern void parse_efi_setup(u64 phys_addr, u32 data_len);
157 168
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 06853e670354..ff9b3a62a05c 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1243,7 +1243,7 @@ void __init setup_arch(char **cmdline_p)
1243 * mismatched firmware/kernel archtectures since there is no 1243 * mismatched firmware/kernel archtectures since there is no
1244 * support for runtime services. 1244 * support for runtime services.
1245 */ 1245 */
1246 if (efi_enabled(EFI_BOOT) && !efi_is_native()) { 1246 if (efi_enabled(EFI_BOOT) && !efi_runtime_supported()) {
1247 pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); 1247 pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
1248 efi_unmap_memmap(); 1248 efi_unmap_memmap();
1249 } 1249 }
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 39f5b7bba695..395decedfa2b 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -802,7 +802,7 @@ void __init efi_init(void)
802 * that doesn't match the kernel 32/64-bit mode. 802 * that doesn't match the kernel 32/64-bit mode.
803 */ 803 */
804 804
805 if (!efi_is_native()) 805 if (!efi_runtime_supported())
806 pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); 806 pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
807 else { 807 else {
808 if (disable_runtime || efi_runtime_init()) 808 if (disable_runtime || efi_runtime_init())