aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2012-10-24 13:00:44 -0400
committerMatt Fleming <matt.fleming@intel.com>2012-10-25 14:09:40 -0400
commit5189c2a7c7769ee9d037d76c1a7b8550ccf3481c (patch)
tree29582d23f219fbefe00c216ec8a619ab8bf9996f
parent78bef24e8477653853eb028dfc18471f05e54955 (diff)
x86: efi: Turn off efi_enabled after setup on mixed fw/kernel
When 32-bit EFI is used with 64-bit kernel (or vice versa), turn off efi_enabled once setup is done. Beyond setup, it is normally used to determine if runtime services are available and we will have none. This will resolve issues stemming from efivars modprobe panicking on a 32/64-bit setup, as well as some reboot issues on similar setups. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45991 Reported-by: Marko Kohtala <marko.kohtala@gmail.com> Reported-by: Maxim Kammerer <mk@dee.su> Signed-off-by: Olof Johansson <olof@lixom.net> Acked-by: Maarten Lankhorst <maarten.lankhorst@canonical.com> Cc: stable@kernel.org # 3.4 - 3.6 Cc: Matthew Garrett <mjg@redhat.com> Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r--arch/x86/include/asm/efi.h1
-rw-r--r--arch/x86/kernel/setup.c12
-rw-r--r--arch/x86/platform/efi/efi.c18
3 files changed, 23 insertions, 8 deletions
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index c9dcc181d4d1..029189db84de 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -98,6 +98,7 @@ extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
98extern int efi_memblock_x86_reserve_range(void); 98extern int efi_memblock_x86_reserve_range(void);
99extern void efi_call_phys_prelog(void); 99extern void efi_call_phys_prelog(void);
100extern void efi_call_phys_epilog(void); 100extern void efi_call_phys_epilog(void);
101extern void efi_unmap_memmap(void);
101 102
102#ifndef CONFIG_EFI 103#ifndef CONFIG_EFI
103/* 104/*
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index a2bb18e02839..6fd7752cee96 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1035,6 +1035,18 @@ void __init setup_arch(char **cmdline_p)
1035 arch_init_ideal_nops(); 1035 arch_init_ideal_nops();
1036 1036
1037 register_refined_jiffies(CLOCK_TICK_RATE); 1037 register_refined_jiffies(CLOCK_TICK_RATE);
1038
1039#ifdef CONFIG_EFI
1040 /* Once setup is done above, disable efi_enabled on mismatched
1041 * firmware/kernel archtectures since there is no support for
1042 * runtime services.
1043 */
1044 if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) {
1045 pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
1046 efi_unmap_memmap();
1047 efi_enabled = 0;
1048 }
1049#endif
1038} 1050}
1039 1051
1040#ifdef CONFIG_X86_32 1052#ifdef CONFIG_X86_32
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index aded2a91162a..9bae3b73fccc 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -70,11 +70,15 @@ EXPORT_SYMBOL(efi);
70struct efi_memory_map memmap; 70struct efi_memory_map memmap;
71 71
72bool efi_64bit; 72bool efi_64bit;
73static bool efi_native;
74 73
75static struct efi efi_phys __initdata; 74static struct efi efi_phys __initdata;
76static efi_system_table_t efi_systab __initdata; 75static efi_system_table_t efi_systab __initdata;
77 76
77static inline bool efi_is_native(void)
78{
79 return IS_ENABLED(CONFIG_X86_64) == efi_64bit;
80}
81
78static int __init setup_noefi(char *arg) 82static int __init setup_noefi(char *arg)
79{ 83{
80 efi_enabled = 0; 84 efi_enabled = 0;
@@ -420,7 +424,7 @@ void __init efi_reserve_boot_services(void)
420 } 424 }
421} 425}
422 426
423static void __init efi_unmap_memmap(void) 427void __init efi_unmap_memmap(void)
424{ 428{
425 if (memmap.map) { 429 if (memmap.map) {
426 early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); 430 early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
@@ -432,7 +436,7 @@ void __init efi_free_boot_services(void)
432{ 436{
433 void *p; 437 void *p;
434 438
435 if (!efi_native) 439 if (!efi_is_native())
436 return; 440 return;
437 441
438 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { 442 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -684,12 +688,10 @@ void __init efi_init(void)
684 return; 688 return;
685 } 689 }
686 efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; 690 efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
687 efi_native = !efi_64bit;
688#else 691#else
689 efi_phys.systab = (efi_system_table_t *) 692 efi_phys.systab = (efi_system_table_t *)
690 (boot_params.efi_info.efi_systab | 693 (boot_params.efi_info.efi_systab |
691 ((__u64)boot_params.efi_info.efi_systab_hi<<32)); 694 ((__u64)boot_params.efi_info.efi_systab_hi<<32));
692 efi_native = efi_64bit;
693#endif 695#endif
694 696
695 if (efi_systab_init(efi_phys.systab)) { 697 if (efi_systab_init(efi_phys.systab)) {
@@ -723,7 +725,7 @@ void __init efi_init(void)
723 * that doesn't match the kernel 32/64-bit mode. 725 * that doesn't match the kernel 32/64-bit mode.
724 */ 726 */
725 727
726 if (!efi_native) 728 if (!efi_is_native())
727 pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); 729 pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
728 else if (efi_runtime_init()) { 730 else if (efi_runtime_init()) {
729 efi_enabled = 0; 731 efi_enabled = 0;
@@ -735,7 +737,7 @@ void __init efi_init(void)
735 return; 737 return;
736 } 738 }
737#ifdef CONFIG_X86_32 739#ifdef CONFIG_X86_32
738 if (efi_native) { 740 if (efi_is_native()) {
739 x86_platform.get_wallclock = efi_get_time; 741 x86_platform.get_wallclock = efi_get_time;
740 x86_platform.set_wallclock = efi_set_rtc_mmss; 742 x86_platform.set_wallclock = efi_set_rtc_mmss;
741 } 743 }
@@ -834,7 +836,7 @@ void __init efi_enter_virtual_mode(void)
834 * non-native EFI 836 * non-native EFI
835 */ 837 */
836 838
837 if (!efi_native) { 839 if (!efi_is_native()) {
838 efi_unmap_memmap(); 840 efi_unmap_memmap();
839 return; 841 return;
840 } 842 }