aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2013-06-13 11:59:23 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2013-06-13 11:59:23 -0400
commit45df901cc8ad10d03d77ddad8f37589b047144ef (patch)
treec2d07b2e487937cd4dd124d7ff5f709f52a9ccf8 /arch/x86
parentc8a22d19dd238ede87aa0ac4f7dbea8da039b9c1 (diff)
parentf8b8404337de4e2466e2e1139ea68b1f8295974f (diff)
Merge tag 'efi-urgent' into x86/urgent
* More tweaking to the EFI variable anti-bricking algorithm. Quite a few users were reporting boot regressions in v3.9. This has now been fixed with a more accurate "minimum storage requirement to avoid bricking" value from Samsung (5K instead of 50%) and code to trigger garbage collection when we near our limit - Matthew Garrett. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/boot/compressed/eboot.c47
-rw-r--r--arch/x86/include/asm/efi.h7
-rw-r--r--arch/x86/include/uapi/asm/bootparam.h1
-rw-r--r--arch/x86/platform/efi/efi.c188
4 files changed, 65 insertions, 178 deletions
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 35ee62fccf98..c205035a6b96 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -251,51 +251,6 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
251 *size = len; 251 *size = len;
252} 252}
253 253
254static efi_status_t setup_efi_vars(struct boot_params *params)
255{
256 struct setup_data *data;
257 struct efi_var_bootdata *efidata;
258 u64 store_size, remaining_size, var_size;
259 efi_status_t status;
260
261 if (sys_table->runtime->hdr.revision < EFI_2_00_SYSTEM_TABLE_REVISION)
262 return EFI_UNSUPPORTED;
263
264 data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
265
266 while (data && data->next)
267 data = (struct setup_data *)(unsigned long)data->next;
268
269 status = efi_call_phys4((void *)sys_table->runtime->query_variable_info,
270 EFI_VARIABLE_NON_VOLATILE |
271 EFI_VARIABLE_BOOTSERVICE_ACCESS |
272 EFI_VARIABLE_RUNTIME_ACCESS, &store_size,
273 &remaining_size, &var_size);
274
275 if (status != EFI_SUCCESS)
276 return status;
277
278 status = efi_call_phys3(sys_table->boottime->allocate_pool,
279 EFI_LOADER_DATA, sizeof(*efidata), &efidata);
280
281 if (status != EFI_SUCCESS)
282 return status;
283
284 efidata->data.type = SETUP_EFI_VARS;
285 efidata->data.len = sizeof(struct efi_var_bootdata) -
286 sizeof(struct setup_data);
287 efidata->data.next = 0;
288 efidata->store_size = store_size;
289 efidata->remaining_size = remaining_size;
290 efidata->max_var_size = var_size;
291
292 if (data)
293 data->next = (unsigned long)efidata;
294 else
295 params->hdr.setup_data = (unsigned long)efidata;
296
297}
298
299static efi_status_t setup_efi_pci(struct boot_params *params) 254static efi_status_t setup_efi_pci(struct boot_params *params)
300{ 255{
301 efi_pci_io_protocol *pci; 256 efi_pci_io_protocol *pci;
@@ -1202,8 +1157,6 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
1202 1157
1203 setup_graphics(boot_params); 1158 setup_graphics(boot_params);
1204 1159
1205 setup_efi_vars(boot_params);
1206
1207 setup_efi_pci(boot_params); 1160 setup_efi_pci(boot_params);
1208 1161
1209 status = efi_call_phys3(sys_table->boottime->allocate_pool, 1162 status = efi_call_phys3(sys_table->boottime->allocate_pool,
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 2fb5d5884e23..60c89f30c727 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -102,13 +102,6 @@ extern void efi_call_phys_epilog(void);
102extern void efi_unmap_memmap(void); 102extern void efi_unmap_memmap(void);
103extern void efi_memory_uc(u64 addr, unsigned long size); 103extern void efi_memory_uc(u64 addr, unsigned long size);
104 104
105struct efi_var_bootdata {
106 struct setup_data data;
107 u64 store_size;
108 u64 remaining_size;
109 u64 max_var_size;
110};
111
112#ifdef CONFIG_EFI 105#ifdef CONFIG_EFI
113 106
114static inline bool efi_is_native(void) 107static inline bool efi_is_native(void)
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index 08744242b8d2..c15ddaf90710 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -6,7 +6,6 @@
6#define SETUP_E820_EXT 1 6#define SETUP_E820_EXT 1
7#define SETUP_DTB 2 7#define SETUP_DTB 2
8#define SETUP_PCI 3 8#define SETUP_PCI 3
9#define SETUP_EFI_VARS 4
10 9
11/* ram_size flags */ 10/* ram_size flags */
12#define RAMDISK_IMAGE_START_MASK 0x07FF 11#define RAMDISK_IMAGE_START_MASK 0x07FF
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 82089d8b1954..5ae2eb09419e 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -42,7 +42,6 @@
42#include <linux/io.h> 42#include <linux/io.h>
43#include <linux/reboot.h> 43#include <linux/reboot.h>
44#include <linux/bcd.h> 44#include <linux/bcd.h>
45#include <linux/ucs2_string.h>
46 45
47#include <asm/setup.h> 46#include <asm/setup.h>
48#include <asm/efi.h> 47#include <asm/efi.h>
@@ -54,12 +53,12 @@
54 53
55#define EFI_DEBUG 1 54#define EFI_DEBUG 1
56 55
57/* 56#define EFI_MIN_RESERVE 5120
58 * There's some additional metadata associated with each 57
59 * variable. Intel's reference implementation is 60 bytes - bump that 58#define EFI_DUMMY_GUID \
60 * to account for potential alignment constraints 59 EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9)
61 */ 60
62#define VAR_METADATA_SIZE 64 61static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 };
63 62
64struct efi __read_mostly efi = { 63struct efi __read_mostly efi = {
65 .mps = EFI_INVALID_TABLE_ADDR, 64 .mps = EFI_INVALID_TABLE_ADDR,
@@ -79,13 +78,6 @@ struct efi_memory_map memmap;
79static struct efi efi_phys __initdata; 78static struct efi efi_phys __initdata;
80static efi_system_table_t efi_systab __initdata; 79static efi_system_table_t efi_systab __initdata;
81 80
82static u64 efi_var_store_size;
83static u64 efi_var_remaining_size;
84static u64 efi_var_max_var_size;
85static u64 boot_used_size;
86static u64 boot_var_size;
87static u64 active_size;
88
89unsigned long x86_efi_facility; 81unsigned long x86_efi_facility;
90 82
91/* 83/*
@@ -188,53 +180,8 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
188 efi_char16_t *name, 180 efi_char16_t *name,
189 efi_guid_t *vendor) 181 efi_guid_t *vendor)
190{ 182{
191 efi_status_t status; 183 return efi_call_virt3(get_next_variable,
192 static bool finished = false; 184 name_size, name, vendor);
193 static u64 var_size;
194
195 status = efi_call_virt3(get_next_variable,
196 name_size, name, vendor);
197
198 if (status == EFI_NOT_FOUND) {
199 finished = true;
200 if (var_size < boot_used_size) {
201 boot_var_size = boot_used_size - var_size;
202 active_size += boot_var_size;
203 } else {
204 printk(KERN_WARNING FW_BUG "efi: Inconsistent initial sizes\n");
205 }
206 }
207
208 if (boot_used_size && !finished) {
209 unsigned long size = 0;
210 u32 attr;
211 efi_status_t s;
212 void *tmp;
213
214 s = virt_efi_get_variable(name, vendor, &attr, &size, NULL);
215
216 if (s != EFI_BUFFER_TOO_SMALL || !size)
217 return status;
218
219 tmp = kmalloc(size, GFP_ATOMIC);
220
221 if (!tmp)
222 return status;
223
224 s = virt_efi_get_variable(name, vendor, &attr, &size, tmp);
225
226 if (s == EFI_SUCCESS && (attr & EFI_VARIABLE_NON_VOLATILE)) {
227 var_size += size;
228 var_size += ucs2_strsize(name, 1024);
229 active_size += size;
230 active_size += VAR_METADATA_SIZE;
231 active_size += ucs2_strsize(name, 1024);
232 }
233
234 kfree(tmp);
235 }
236
237 return status;
238} 185}
239 186
240static efi_status_t virt_efi_set_variable(efi_char16_t *name, 187static efi_status_t virt_efi_set_variable(efi_char16_t *name,
@@ -243,34 +190,9 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
243 unsigned long data_size, 190 unsigned long data_size,
244 void *data) 191 void *data)
245{ 192{
246 efi_status_t status; 193 return efi_call_virt5(set_variable,
247 u32 orig_attr = 0; 194 name, vendor, attr,
248 unsigned long orig_size = 0; 195 data_size, data);
249
250 status = virt_efi_get_variable(name, vendor, &orig_attr, &orig_size,
251 NULL);
252
253 if (status != EFI_BUFFER_TOO_SMALL)
254 orig_size = 0;
255
256 status = efi_call_virt5(set_variable,
257 name, vendor, attr,
258 data_size, data);
259
260 if (status == EFI_SUCCESS) {
261 if (orig_size) {
262 active_size -= orig_size;
263 active_size -= ucs2_strsize(name, 1024);
264 active_size -= VAR_METADATA_SIZE;
265 }
266 if (data_size) {
267 active_size += data_size;
268 active_size += ucs2_strsize(name, 1024);
269 active_size += VAR_METADATA_SIZE;
270 }
271 }
272
273 return status;
274} 196}
275 197
276static efi_status_t virt_efi_query_variable_info(u32 attr, 198static efi_status_t virt_efi_query_variable_info(u32 attr,
@@ -786,9 +708,6 @@ void __init efi_init(void)
786 char vendor[100] = "unknown"; 708 char vendor[100] = "unknown";
787 int i = 0; 709 int i = 0;
788 void *tmp; 710 void *tmp;
789 struct setup_data *data;
790 struct efi_var_bootdata *efi_var_data;
791 u64 pa_data;
792 711
793#ifdef CONFIG_X86_32 712#ifdef CONFIG_X86_32
794 if (boot_params.efi_info.efi_systab_hi || 713 if (boot_params.efi_info.efi_systab_hi ||
@@ -806,22 +725,6 @@ void __init efi_init(void)
806 if (efi_systab_init(efi_phys.systab)) 725 if (efi_systab_init(efi_phys.systab))
807 return; 726 return;
808 727
809 pa_data = boot_params.hdr.setup_data;
810 while (pa_data) {
811 data = early_ioremap(pa_data, sizeof(*efi_var_data));
812 if (data->type == SETUP_EFI_VARS) {
813 efi_var_data = (struct efi_var_bootdata *)data;
814
815 efi_var_store_size = efi_var_data->store_size;
816 efi_var_remaining_size = efi_var_data->remaining_size;
817 efi_var_max_var_size = efi_var_data->max_var_size;
818 }
819 pa_data = data->next;
820 early_iounmap(data, sizeof(*efi_var_data));
821 }
822
823 boot_used_size = efi_var_store_size - efi_var_remaining_size;
824
825 set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); 728 set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);
826 729
827 /* 730 /*
@@ -1085,6 +988,13 @@ void __init efi_enter_virtual_mode(void)
1085 runtime_code_page_mkexec(); 988 runtime_code_page_mkexec();
1086 989
1087 kfree(new_memmap); 990 kfree(new_memmap);
991
992 /* clean DUMMY object */
993 efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
994 EFI_VARIABLE_NON_VOLATILE |
995 EFI_VARIABLE_BOOTSERVICE_ACCESS |
996 EFI_VARIABLE_RUNTIME_ACCESS,
997 0, NULL);
1088} 998}
1089 999
1090/* 1000/*
@@ -1136,33 +1046,65 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
1136 efi_status_t status; 1046 efi_status_t status;
1137 u64 storage_size, remaining_size, max_size; 1047 u64 storage_size, remaining_size, max_size;
1138 1048
1049 if (!(attributes & EFI_VARIABLE_NON_VOLATILE))
1050 return 0;
1051
1139 status = efi.query_variable_info(attributes, &storage_size, 1052 status = efi.query_variable_info(attributes, &storage_size,
1140 &remaining_size, &max_size); 1053 &remaining_size, &max_size);
1141 if (status != EFI_SUCCESS) 1054 if (status != EFI_SUCCESS)
1142 return status; 1055 return status;
1143 1056
1144 if (!max_size && remaining_size > size)
1145 printk_once(KERN_ERR FW_BUG "Broken EFI implementation"
1146 " is returning MaxVariableSize=0\n");
1147 /* 1057 /*
1148 * Some firmware implementations refuse to boot if there's insufficient 1058 * Some firmware implementations refuse to boot if there's insufficient
1149 * space in the variable store. We account for that by refusing the 1059 * space in the variable store. We account for that by refusing the
1150 * write if permitting it would reduce the available space to under 1060 * write if permitting it would reduce the available space to under
1151 * 50%. However, some firmware won't reclaim variable space until 1061 * 5KB. This figure was provided by Samsung, so should be safe.
1152 * after the used (not merely the actively used) space drops below
1153 * a threshold. We can approximate that case with the value calculated
1154 * above. If both the firmware and our calculations indicate that the
1155 * available space would drop below 50%, refuse the write.
1156 */ 1062 */
1063 if ((remaining_size - size < EFI_MIN_RESERVE) &&
1064 !efi_no_storage_paranoia) {
1065
1066 /*
1067 * Triggering garbage collection may require that the firmware
1068 * generate a real EFI_OUT_OF_RESOURCES error. We can force
1069 * that by attempting to use more space than is available.
1070 */
1071 unsigned long dummy_size = remaining_size + 1024;
1072 void *dummy = kmalloc(dummy_size, GFP_ATOMIC);
1073
1074 status = efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
1075 EFI_VARIABLE_NON_VOLATILE |
1076 EFI_VARIABLE_BOOTSERVICE_ACCESS |
1077 EFI_VARIABLE_RUNTIME_ACCESS,
1078 dummy_size, dummy);
1079
1080 if (status == EFI_SUCCESS) {
1081 /*
1082 * This should have failed, so if it didn't make sure
1083 * that we delete it...
1084 */
1085 efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
1086 EFI_VARIABLE_NON_VOLATILE |
1087 EFI_VARIABLE_BOOTSERVICE_ACCESS |
1088 EFI_VARIABLE_RUNTIME_ACCESS,
1089 0, dummy);
1090 }
1157 1091
1158 if (!storage_size || size > remaining_size || 1092 /*
1159 (max_size && size > max_size)) 1093 * The runtime code may now have triggered a garbage collection
1160 return EFI_OUT_OF_RESOURCES; 1094 * run, so check the variable info again
1095 */
1096 status = efi.query_variable_info(attributes, &storage_size,
1097 &remaining_size, &max_size);
1161 1098
1162 if (!efi_no_storage_paranoia && 1099 if (status != EFI_SUCCESS)
1163 ((active_size + size + VAR_METADATA_SIZE > storage_size / 2) && 1100 return status;
1164 (remaining_size - size < storage_size / 2))) 1101
1165 return EFI_OUT_OF_RESOURCES; 1102 /*
1103 * There still isn't enough room, so return an error
1104 */
1105 if (remaining_size - size < EFI_MIN_RESERVE)
1106 return EFI_OUT_OF_RESOURCES;
1107 }
1166 1108
1167 return EFI_SUCCESS; 1109 return EFI_SUCCESS;
1168} 1110}