]>
Commit | Line | Data |
---|---|---|
207c5a55 GKH |
1 | From 5189c2a7c7769ee9d037d76c1a7b8550ccf3481c Mon Sep 17 00:00:00 2001 |
2 | From: Olof Johansson <olof@lixom.net> | |
3 | Date: Wed, 24 Oct 2012 10:00:44 -0700 | |
4 | Subject: x86: efi: Turn off efi_enabled after setup on mixed fw/kernel | |
5 | ||
6 | From: Olof Johansson <olof@lixom.net> | |
7 | ||
8 | commit 5189c2a7c7769ee9d037d76c1a7b8550ccf3481c upstream. | |
9 | ||
10 | When 32-bit EFI is used with 64-bit kernel (or vice versa), turn off | |
11 | efi_enabled once setup is done. Beyond setup, it is normally used to | |
12 | determine if runtime services are available and we will have none. | |
13 | ||
14 | This will resolve issues stemming from efivars modprobe panicking on a | |
15 | 32/64-bit setup, as well as some reboot issues on similar setups. | |
16 | ||
17 | Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45991 | |
18 | ||
19 | Reported-by: Marko Kohtala <marko.kohtala@gmail.com> | |
20 | Reported-by: Maxim Kammerer <mk@dee.su> | |
21 | Signed-off-by: Olof Johansson <olof@lixom.net> | |
22 | Acked-by: Maarten Lankhorst <maarten.lankhorst@canonical.com> | |
23 | Cc: Matthew Garrett <mjg@redhat.com> | |
24 | Signed-off-by: Matt Fleming <matt.fleming@intel.com> | |
25 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
26 | ||
27 | --- | |
28 | arch/x86/include/asm/efi.h | 1 + | |
29 | arch/x86/kernel/setup.c | 12 ++++++++++++ | |
30 | arch/x86/platform/efi/efi.c | 18 ++++++++++-------- | |
31 | 3 files changed, 23 insertions(+), 8 deletions(-) | |
32 | ||
33 | --- a/arch/x86/include/asm/efi.h | |
34 | +++ b/arch/x86/include/asm/efi.h | |
35 | @@ -98,6 +98,7 @@ extern void efi_set_executable(efi_memor | |
36 | extern int efi_memblock_x86_reserve_range(void); | |
37 | extern void efi_call_phys_prelog(void); | |
38 | extern void efi_call_phys_epilog(void); | |
39 | +extern void efi_unmap_memmap(void); | |
40 | ||
41 | #ifndef CONFIG_EFI | |
42 | /* | |
43 | --- a/arch/x86/kernel/setup.c | |
44 | +++ b/arch/x86/kernel/setup.c | |
45 | @@ -1053,6 +1053,18 @@ void __init setup_arch(char **cmdline_p) | |
46 | mcheck_init(); | |
47 | ||
48 | arch_init_ideal_nops(); | |
49 | + | |
50 | +#ifdef CONFIG_EFI | |
51 | + /* Once setup is done above, disable efi_enabled on mismatched | |
52 | + * firmware/kernel archtectures since there is no support for | |
53 | + * runtime services. | |
54 | + */ | |
55 | + if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) { | |
56 | + pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); | |
57 | + efi_unmap_memmap(); | |
58 | + efi_enabled = 0; | |
59 | + } | |
60 | +#endif | |
61 | } | |
62 | ||
63 | #ifdef CONFIG_X86_32 | |
64 | --- a/arch/x86/platform/efi/efi.c | |
65 | +++ b/arch/x86/platform/efi/efi.c | |
66 | @@ -69,11 +69,15 @@ EXPORT_SYMBOL(efi); | |
67 | struct efi_memory_map memmap; | |
68 | ||
69 | bool efi_64bit; | |
70 | -static bool efi_native; | |
71 | ||
72 | static struct efi efi_phys __initdata; | |
73 | static efi_system_table_t efi_systab __initdata; | |
74 | ||
75 | +static inline bool efi_is_native(void) | |
76 | +{ | |
77 | + return IS_ENABLED(CONFIG_X86_64) == efi_64bit; | |
78 | +} | |
79 | + | |
80 | static int __init setup_noefi(char *arg) | |
81 | { | |
82 | efi_enabled = 0; | |
83 | @@ -419,7 +423,7 @@ void __init efi_reserve_boot_services(vo | |
84 | } | |
85 | } | |
86 | ||
87 | -static void __init efi_unmap_memmap(void) | |
88 | +void __init efi_unmap_memmap(void) | |
89 | { | |
90 | if (memmap.map) { | |
91 | early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); | |
92 | @@ -431,7 +435,7 @@ void __init efi_free_boot_services(void) | |
93 | { | |
94 | void *p; | |
95 | ||
96 | - if (!efi_native) | |
97 | + if (!efi_is_native()) | |
98 | return; | |
99 | ||
100 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | |
101 | @@ -683,12 +687,10 @@ void __init efi_init(void) | |
102 | return; | |
103 | } | |
104 | efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; | |
105 | - efi_native = !efi_64bit; | |
106 | #else | |
107 | efi_phys.systab = (efi_system_table_t *) | |
108 | (boot_params.efi_info.efi_systab | | |
109 | ((__u64)boot_params.efi_info.efi_systab_hi<<32)); | |
110 | - efi_native = efi_64bit; | |
111 | #endif | |
112 | ||
113 | if (efi_systab_init(efi_phys.systab)) { | |
114 | @@ -722,7 +724,7 @@ void __init efi_init(void) | |
115 | * that doesn't match the kernel 32/64-bit mode. | |
116 | */ | |
117 | ||
118 | - if (!efi_native) | |
119 | + if (!efi_is_native()) | |
120 | pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); | |
121 | else if (efi_runtime_init()) { | |
122 | efi_enabled = 0; | |
123 | @@ -734,7 +736,7 @@ void __init efi_init(void) | |
124 | return; | |
125 | } | |
126 | #ifdef CONFIG_X86_32 | |
127 | - if (efi_native) { | |
128 | + if (efi_is_native()) { | |
129 | x86_platform.get_wallclock = efi_get_time; | |
130 | x86_platform.set_wallclock = efi_set_rtc_mmss; | |
131 | } | |
132 | @@ -800,7 +802,7 @@ void __init efi_enter_virtual_mode(void) | |
133 | * non-native EFI | |
134 | */ | |
135 | ||
136 | - if (!efi_native) { | |
137 | + if (!efi_is_native()) { | |
138 | efi_unmap_memmap(); | |
139 | return; | |
140 | } |