aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt6
-rw-r--r--arch/x86/Kconfig1
-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.c168
-rw-r--r--drivers/firmware/Kconfig1
-rw-r--r--drivers/firmware/efivars.c98
-rw-r--r--include/linux/efi.h9
-rw-r--r--include/linux/ucs2_string.h14
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/Makefile2
-rw-r--r--lib/ucs2_string.c51
13 files changed, 325 insertions, 83 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 4609e81dbc37..d1cc3a9fa14f 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -788,6 +788,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
788 edd= [EDD] 788 edd= [EDD]
789 Format: {"off" | "on" | "skip[mbr]"} 789 Format: {"off" | "on" | "skip[mbr]"}
790 790
791 efi_no_storage_paranoia [EFI; X86]
792 Using this parameter you can use more than 50% of
793 your efi variable storage. Use this parameter only if
794 you are really sure that your UEFI does sane gc and
795 fulfills the spec otherwise your board may brick.
796
791 eisa_irq_edge= [PARISC,HW] 797 eisa_irq_edge= [PARISC,HW]
792 See header of drivers/parisc/eisa.c. 798 See header of drivers/parisc/eisa.c.
793 799
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 70c0f3da0476..15b5cef4aa38 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1549,6 +1549,7 @@ config X86_SMAP
1549config EFI 1549config EFI
1550 bool "EFI runtime service support" 1550 bool "EFI runtime service support"
1551 depends on ACPI 1551 depends on ACPI
1552 select UCS2_STRING
1552 ---help--- 1553 ---help---
1553 This enables the kernel to use EFI runtime services that are 1554 This enables the kernel to use EFI runtime services that are
1554 available (such as the EFI variable services). 1555 available (such as the EFI variable services).
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index c205035a6b96..8615f7581820 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -251,6 +251,51 @@ 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->query_variable_info)
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(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
254static efi_status_t setup_efi_pci(struct boot_params *params) 299static efi_status_t setup_efi_pci(struct boot_params *params)
255{ 300{
256 efi_pci_io_protocol *pci; 301 efi_pci_io_protocol *pci;
@@ -1157,6 +1202,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
1157 1202
1158 setup_graphics(boot_params); 1203 setup_graphics(boot_params);
1159 1204
1205 setup_efi_vars(boot_params);
1206
1160 setup_efi_pci(boot_params); 1207 setup_efi_pci(boot_params);
1161 1208
1162 status = efi_call_phys3(sys_table->boottime->allocate_pool, 1209 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 60c89f30c727..2fb5d5884e23 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -102,6 +102,13 @@ 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
105#ifdef CONFIG_EFI 112#ifdef CONFIG_EFI
106 113
107static inline bool efi_is_native(void) 114static 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 c15ddaf90710..08744242b8d2 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -6,6 +6,7 @@
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
9 10
10/* ram_size flags */ 11/* ram_size flags */
11#define RAMDISK_IMAGE_START_MASK 0x07FF 12#define RAMDISK_IMAGE_START_MASK 0x07FF
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 5f2ecaf3f9d8..e4a86a677ce1 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -41,6 +41,7 @@
41#include <linux/io.h> 41#include <linux/io.h>
42#include <linux/reboot.h> 42#include <linux/reboot.h>
43#include <linux/bcd.h> 43#include <linux/bcd.h>
44#include <linux/ucs2_string.h>
44 45
45#include <asm/setup.h> 46#include <asm/setup.h>
46#include <asm/efi.h> 47#include <asm/efi.h>
@@ -51,6 +52,13 @@
51 52
52#define EFI_DEBUG 1 53#define EFI_DEBUG 1
53 54
55/*
56 * There's some additional metadata associated with each
57 * variable. Intel's reference implementation is 60 bytes - bump that
58 * to account for potential alignment constraints
59 */
60#define VAR_METADATA_SIZE 64
61
54struct efi __read_mostly efi = { 62struct efi __read_mostly efi = {
55 .mps = EFI_INVALID_TABLE_ADDR, 63 .mps = EFI_INVALID_TABLE_ADDR,
56 .acpi = EFI_INVALID_TABLE_ADDR, 64 .acpi = EFI_INVALID_TABLE_ADDR,
@@ -69,6 +77,13 @@ struct efi_memory_map memmap;
69static struct efi efi_phys __initdata; 77static struct efi efi_phys __initdata;
70static efi_system_table_t efi_systab __initdata; 78static efi_system_table_t efi_systab __initdata;
71 79
80static u64 efi_var_store_size;
81static u64 efi_var_remaining_size;
82static u64 efi_var_max_var_size;
83static u64 boot_used_size;
84static u64 boot_var_size;
85static u64 active_size;
86
72unsigned long x86_efi_facility; 87unsigned long x86_efi_facility;
73 88
74/* 89/*
@@ -98,6 +113,15 @@ static int __init setup_add_efi_memmap(char *arg)
98} 113}
99early_param("add_efi_memmap", setup_add_efi_memmap); 114early_param("add_efi_memmap", setup_add_efi_memmap);
100 115
116static bool efi_no_storage_paranoia;
117
118static int __init setup_storage_paranoia(char *arg)
119{
120 efi_no_storage_paranoia = true;
121 return 0;
122}
123early_param("efi_no_storage_paranoia", setup_storage_paranoia);
124
101 125
102static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) 126static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
103{ 127{
@@ -162,8 +186,53 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
162 efi_char16_t *name, 186 efi_char16_t *name,
163 efi_guid_t *vendor) 187 efi_guid_t *vendor)
164{ 188{
165 return efi_call_virt3(get_next_variable, 189 efi_status_t status;
166 name_size, name, vendor); 190 static bool finished = false;
191 static u64 var_size;
192
193 status = efi_call_virt3(get_next_variable,
194 name_size, name, vendor);
195
196 if (status == EFI_NOT_FOUND) {
197 finished = true;
198 if (var_size < boot_used_size) {
199 boot_var_size = boot_used_size - var_size;
200 active_size += boot_var_size;
201 } else {
202 printk(KERN_WARNING FW_BUG "efi: Inconsistent initial sizes\n");
203 }
204 }
205
206 if (boot_used_size && !finished) {
207 unsigned long size;
208 u32 attr;
209 efi_status_t s;
210 void *tmp;
211
212 s = virt_efi_get_variable(name, vendor, &attr, &size, NULL);
213
214 if (s != EFI_BUFFER_TOO_SMALL || !size)
215 return status;
216
217 tmp = kmalloc(size, GFP_ATOMIC);
218
219 if (!tmp)
220 return status;
221
222 s = virt_efi_get_variable(name, vendor, &attr, &size, tmp);
223
224 if (s == EFI_SUCCESS && (attr & EFI_VARIABLE_NON_VOLATILE)) {
225 var_size += size;
226 var_size += ucs2_strsize(name, 1024);
227 active_size += size;
228 active_size += VAR_METADATA_SIZE;
229 active_size += ucs2_strsize(name, 1024);
230 }
231
232 kfree(tmp);
233 }
234
235 return status;
167} 236}
168 237
169static efi_status_t virt_efi_set_variable(efi_char16_t *name, 238static efi_status_t virt_efi_set_variable(efi_char16_t *name,
@@ -172,9 +241,34 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
172 unsigned long data_size, 241 unsigned long data_size,
173 void *data) 242 void *data)
174{ 243{
175 return efi_call_virt5(set_variable, 244 efi_status_t status;
176 name, vendor, attr, 245 u32 orig_attr = 0;
177 data_size, data); 246 unsigned long orig_size = 0;
247
248 status = virt_efi_get_variable(name, vendor, &orig_attr, &orig_size,
249 NULL);
250
251 if (status != EFI_BUFFER_TOO_SMALL)
252 orig_size = 0;
253
254 status = efi_call_virt5(set_variable,
255 name, vendor, attr,
256 data_size, data);
257
258 if (status == EFI_SUCCESS) {
259 if (orig_size) {
260 active_size -= orig_size;
261 active_size -= ucs2_strsize(name, 1024);
262 active_size -= VAR_METADATA_SIZE;
263 }
264 if (data_size) {
265 active_size += data_size;
266 active_size += ucs2_strsize(name, 1024);
267 active_size += VAR_METADATA_SIZE;
268 }
269 }
270
271 return status;
178} 272}
179 273
180static efi_status_t virt_efi_query_variable_info(u32 attr, 274static efi_status_t virt_efi_query_variable_info(u32 attr,
@@ -682,6 +776,9 @@ void __init efi_init(void)
682 char vendor[100] = "unknown"; 776 char vendor[100] = "unknown";
683 int i = 0; 777 int i = 0;
684 void *tmp; 778 void *tmp;
779 struct setup_data *data;
780 struct efi_var_bootdata *efi_var_data;
781 u64 pa_data;
685 782
686#ifdef CONFIG_X86_32 783#ifdef CONFIG_X86_32
687 if (boot_params.efi_info.efi_systab_hi || 784 if (boot_params.efi_info.efi_systab_hi ||
@@ -699,6 +796,22 @@ void __init efi_init(void)
699 if (efi_systab_init(efi_phys.systab)) 796 if (efi_systab_init(efi_phys.systab))
700 return; 797 return;
701 798
799 pa_data = boot_params.hdr.setup_data;
800 while (pa_data) {
801 data = early_ioremap(pa_data, sizeof(*efi_var_data));
802 if (data->type == SETUP_EFI_VARS) {
803 efi_var_data = (struct efi_var_bootdata *)data;
804
805 efi_var_store_size = efi_var_data->store_size;
806 efi_var_remaining_size = efi_var_data->remaining_size;
807 efi_var_max_var_size = efi_var_data->max_var_size;
808 }
809 pa_data = data->next;
810 early_iounmap(data, sizeof(*efi_var_data));
811 }
812
813 boot_used_size = efi_var_store_size - efi_var_remaining_size;
814
702 set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); 815 set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);
703 816
704 /* 817 /*
@@ -999,3 +1112,48 @@ u64 efi_mem_attributes(unsigned long phys_addr)
999 } 1112 }
1000 return 0; 1113 return 0;
1001} 1114}
1115
1116/*
1117 * Some firmware has serious problems when using more than 50% of the EFI
1118 * variable store, i.e. it triggers bugs that can brick machines. Ensure that
1119 * we never use more than this safe limit.
1120 *
1121 * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
1122 * store.
1123 */
1124efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
1125{
1126 efi_status_t status;
1127 u64 storage_size, remaining_size, max_size;
1128
1129 status = efi.query_variable_info(attributes, &storage_size,
1130 &remaining_size, &max_size);
1131 if (status != EFI_SUCCESS)
1132 return status;
1133
1134 if (!max_size && remaining_size > size)
1135 printk_once(KERN_ERR FW_BUG "Broken EFI implementation"
1136 " is returning MaxVariableSize=0\n");
1137 /*
1138 * Some firmware implementations refuse to boot if there's insufficient
1139 * space in the variable store. We account for that by refusing the
1140 * write if permitting it would reduce the available space to under
1141 * 50%. However, some firmware won't reclaim variable space until
1142 * after the used (not merely the actively used) space drops below
1143 * a threshold. We can approximate that case with the value calculated
1144 * above. If both the firmware and our calculations indicate that the
1145 * available space would drop below 50%, refuse the write.
1146 */
1147
1148 if (!storage_size || size > remaining_size ||
1149 (max_size && size > max_size))
1150 return EFI_OUT_OF_RESOURCES;
1151
1152 if (!efi_no_storage_paranoia &&
1153 ((active_size + size + VAR_METADATA_SIZE > storage_size / 2) &&
1154 (remaining_size - size < storage_size / 2)))
1155 return EFI_OUT_OF_RESOURCES;
1156
1157 return EFI_SUCCESS;
1158}
1159EXPORT_SYMBOL_GPL(efi_query_variable_store);
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 42c759a4d047..3e532002e4d1 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -39,6 +39,7 @@ config FIRMWARE_MEMMAP
39config EFI_VARS 39config EFI_VARS
40 tristate "EFI Variable Support via sysfs" 40 tristate "EFI Variable Support via sysfs"
41 depends on EFI 41 depends on EFI
42 select UCS2_STRING
42 default n 43 default n
43 help 44 help
44 If you say Y here, you are able to get EFI (Extensible Firmware 45 If you say Y here, you are able to get EFI (Extensible Firmware
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 7acafb80fd4c..182ce9471175 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -80,6 +80,7 @@
80#include <linux/slab.h> 80#include <linux/slab.h>
81#include <linux/pstore.h> 81#include <linux/pstore.h>
82#include <linux/ctype.h> 82#include <linux/ctype.h>
83#include <linux/ucs2_string.h>
83 84
84#include <linux/fs.h> 85#include <linux/fs.h>
85#include <linux/ramfs.h> 86#include <linux/ramfs.h>
@@ -172,51 +173,6 @@ static void efivar_update_sysfs_entries(struct work_struct *);
172static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries); 173static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries);
173static bool efivar_wq_enabled = true; 174static bool efivar_wq_enabled = true;
174 175
175/* Return the number of unicode characters in data */
176static unsigned long
177utf16_strnlen(efi_char16_t *s, size_t maxlength)
178{
179 unsigned long length = 0;
180
181 while (*s++ != 0 && length < maxlength)
182 length++;
183 return length;
184}
185
186static inline unsigned long
187utf16_strlen(efi_char16_t *s)
188{
189 return utf16_strnlen(s, ~0UL);
190}
191
192/*
193 * Return the number of bytes is the length of this string
194 * Note: this is NOT the same as the number of unicode characters
195 */
196static inline unsigned long
197utf16_strsize(efi_char16_t *data, unsigned long maxlength)
198{
199 return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
200}
201
202static inline int
203utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len)
204{
205 while (1) {
206 if (len == 0)
207 return 0;
208 if (*a < *b)
209 return -1;
210 if (*a > *b)
211 return 1;
212 if (*a == 0) /* implies *b == 0 */
213 return 0;
214 a++;
215 b++;
216 len--;
217 }
218}
219
220static bool 176static bool
221validate_device_path(struct efi_variable *var, int match, u8 *buffer, 177validate_device_path(struct efi_variable *var, int match, u8 *buffer,
222 unsigned long len) 178 unsigned long len)
@@ -268,7 +224,7 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer,
268 u16 filepathlength; 224 u16 filepathlength;
269 int i, desclength = 0, namelen; 225 int i, desclength = 0, namelen;
270 226
271 namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName)); 227 namelen = ucs2_strnlen(var->VariableName, sizeof(var->VariableName));
272 228
273 /* Either "Boot" or "Driver" followed by four digits of hex */ 229 /* Either "Boot" or "Driver" followed by four digits of hex */
274 for (i = match; i < match+4; i++) { 230 for (i = match; i < match+4; i++) {
@@ -291,7 +247,7 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer,
291 * There's no stored length for the description, so it has to be 247 * There's no stored length for the description, so it has to be
292 * found by hand 248 * found by hand
293 */ 249 */
294 desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2; 250 desclength = ucs2_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
295 251
296 /* Each boot entry must have a descriptor */ 252 /* Each boot entry must have a descriptor */
297 if (!desclength) 253 if (!desclength)
@@ -436,24 +392,12 @@ static efi_status_t
436check_var_size_locked(struct efivars *efivars, u32 attributes, 392check_var_size_locked(struct efivars *efivars, u32 attributes,
437 unsigned long size) 393 unsigned long size)
438{ 394{
439 u64 storage_size, remaining_size, max_size;
440 efi_status_t status;
441 const struct efivar_operations *fops = efivars->ops; 395 const struct efivar_operations *fops = efivars->ops;
442 396
443 if (!efivars->ops->query_variable_info) 397 if (!efivars->ops->query_variable_store)
444 return EFI_UNSUPPORTED; 398 return EFI_UNSUPPORTED;
445 399
446 status = fops->query_variable_info(attributes, &storage_size, 400 return fops->query_variable_store(attributes, size);
447 &remaining_size, &max_size);
448
449 if (status != EFI_SUCCESS)
450 return status;
451
452 if (!storage_size || size > remaining_size || size > max_size ||
453 (remaining_size - size) < (storage_size / 2))
454 return EFI_OUT_OF_RESOURCES;
455
456 return status;
457} 401}
458 402
459 403
@@ -593,7 +537,7 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
593 spin_lock_irq(&efivars->lock); 537 spin_lock_irq(&efivars->lock);
594 538
595 status = check_var_size_locked(efivars, new_var->Attributes, 539 status = check_var_size_locked(efivars, new_var->Attributes,
596 new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); 540 new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024));
597 541
598 if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED) 542 if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
599 status = efivars->ops->set_variable(new_var->VariableName, 543 status = efivars->ops->set_variable(new_var->VariableName,
@@ -771,7 +715,7 @@ static ssize_t efivarfs_file_write(struct file *file,
771 * QueryVariableInfo() isn't supported by the firmware. 715 * QueryVariableInfo() isn't supported by the firmware.
772 */ 716 */
773 717
774 varsize = datasize + utf16_strsize(var->var.VariableName, 1024); 718 varsize = datasize + ucs2_strsize(var->var.VariableName, 1024);
775 status = check_var_size(efivars, attributes, varsize); 719 status = check_var_size(efivars, attributes, varsize);
776 720
777 if (status != EFI_SUCCESS) { 721 if (status != EFI_SUCCESS) {
@@ -1223,7 +1167,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
1223 1167
1224 inode = NULL; 1168 inode = NULL;
1225 1169
1226 len = utf16_strlen(entry->var.VariableName); 1170 len = ucs2_strlen(entry->var.VariableName);
1227 1171
1228 /* name, plus '-', plus GUID, plus NUL*/ 1172 /* name, plus '-', plus GUID, plus NUL*/
1229 name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC); 1173 name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC);
@@ -1481,8 +1425,8 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
1481 1425
1482 if (efi_guidcmp(entry->var.VendorGuid, vendor)) 1426 if (efi_guidcmp(entry->var.VendorGuid, vendor))
1483 continue; 1427 continue;
1484 if (utf16_strncmp(entry->var.VariableName, efi_name, 1428 if (ucs2_strncmp(entry->var.VariableName, efi_name,
1485 utf16_strlen(efi_name))) { 1429 ucs2_strlen(efi_name))) {
1486 /* 1430 /*
1487 * Check if an old format, 1431 * Check if an old format,
1488 * which doesn't support holding 1432 * which doesn't support holding
@@ -1494,8 +1438,8 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
1494 for (i = 0; i < DUMP_NAME_LEN; i++) 1438 for (i = 0; i < DUMP_NAME_LEN; i++)
1495 efi_name_old[i] = name_old[i]; 1439 efi_name_old[i] = name_old[i];
1496 1440
1497 if (utf16_strncmp(entry->var.VariableName, efi_name_old, 1441 if (ucs2_strncmp(entry->var.VariableName, efi_name_old,
1498 utf16_strlen(efi_name_old))) 1442 ucs2_strlen(efi_name_old)))
1499 continue; 1443 continue;
1500 } 1444 }
1501 1445
@@ -1573,8 +1517,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
1573 * Does this variable already exist? 1517 * Does this variable already exist?
1574 */ 1518 */
1575 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 1519 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
1576 strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 1520 strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024);
1577 strsize2 = utf16_strsize(new_var->VariableName, 1024); 1521 strsize2 = ucs2_strsize(new_var->VariableName, 1024);
1578 if (strsize1 == strsize2 && 1522 if (strsize1 == strsize2 &&
1579 !memcmp(&(search_efivar->var.VariableName), 1523 !memcmp(&(search_efivar->var.VariableName),
1580 new_var->VariableName, strsize1) && 1524 new_var->VariableName, strsize1) &&
@@ -1590,7 +1534,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
1590 } 1534 }
1591 1535
1592 status = check_var_size_locked(efivars, new_var->Attributes, 1536 status = check_var_size_locked(efivars, new_var->Attributes,
1593 new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); 1537 new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024));
1594 1538
1595 if (status && status != EFI_UNSUPPORTED) { 1539 if (status && status != EFI_UNSUPPORTED) {
1596 spin_unlock_irq(&efivars->lock); 1540 spin_unlock_irq(&efivars->lock);
@@ -1614,7 +1558,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
1614 1558
1615 /* Create the entry in sysfs. Locking is not required here */ 1559 /* Create the entry in sysfs. Locking is not required here */
1616 status = efivar_create_sysfs_entry(efivars, 1560 status = efivar_create_sysfs_entry(efivars,
1617 utf16_strsize(new_var->VariableName, 1561 ucs2_strsize(new_var->VariableName,
1618 1024), 1562 1024),
1619 new_var->VariableName, 1563 new_var->VariableName,
1620 &new_var->VendorGuid); 1564 &new_var->VendorGuid);
@@ -1644,8 +1588,8 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
1644 * Does this variable already exist? 1588 * Does this variable already exist?
1645 */ 1589 */
1646 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 1590 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
1647 strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 1591 strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024);
1648 strsize2 = utf16_strsize(del_var->VariableName, 1024); 1592 strsize2 = ucs2_strsize(del_var->VariableName, 1024);
1649 if (strsize1 == strsize2 && 1593 if (strsize1 == strsize2 &&
1650 !memcmp(&(search_efivar->var.VariableName), 1594 !memcmp(&(search_efivar->var.VariableName),
1651 del_var->VariableName, strsize1) && 1595 del_var->VariableName, strsize1) &&
@@ -1691,9 +1635,9 @@ static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor)
1691 unsigned long strsize1, strsize2; 1635 unsigned long strsize1, strsize2;
1692 bool found = false; 1636 bool found = false;
1693 1637
1694 strsize1 = utf16_strsize(variable_name, 1024); 1638 strsize1 = ucs2_strsize(variable_name, 1024);
1695 list_for_each_entry_safe(entry, n, &efivars->list, list) { 1639 list_for_each_entry_safe(entry, n, &efivars->list, list) {
1696 strsize2 = utf16_strsize(entry->var.VariableName, 1024); 1640 strsize2 = ucs2_strsize(entry->var.VariableName, 1024);
1697 if (strsize1 == strsize2 && 1641 if (strsize1 == strsize2 &&
1698 !memcmp(variable_name, &(entry->var.VariableName), 1642 !memcmp(variable_name, &(entry->var.VariableName),
1699 strsize2) && 1643 strsize2) &&
@@ -2131,7 +2075,7 @@ efivars_init(void)
2131 ops.get_variable = efi.get_variable; 2075 ops.get_variable = efi.get_variable;
2132 ops.set_variable = efi.set_variable; 2076 ops.set_variable = efi.set_variable;
2133 ops.get_next_variable = efi.get_next_variable; 2077 ops.get_next_variable = efi.get_next_variable;
2134 ops.query_variable_info = efi.query_variable_info; 2078 ops.query_variable_store = efi_query_variable_store;
2135 2079
2136 error = register_efivars(&__efivars, &ops, efi_kobj); 2080 error = register_efivars(&__efivars, &ops, efi_kobj);
2137 if (error) 2081 if (error)
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 9bf2f1fcae27..3d7df3d32c66 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -333,6 +333,7 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
333 unsigned long count, 333 unsigned long count,
334 u64 *max_size, 334 u64 *max_size,
335 int *reset_type); 335 int *reset_type);
336typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long size);
336 337
337/* 338/*
338 * EFI Configuration Table and GUID definitions 339 * EFI Configuration Table and GUID definitions
@@ -575,9 +576,15 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos
575#ifdef CONFIG_X86 576#ifdef CONFIG_X86
576extern void efi_late_init(void); 577extern void efi_late_init(void);
577extern void efi_free_boot_services(void); 578extern void efi_free_boot_services(void);
579extern efi_status_t efi_query_variable_store(u32 attributes, unsigned long size);
578#else 580#else
579static inline void efi_late_init(void) {} 581static inline void efi_late_init(void) {}
580static inline void efi_free_boot_services(void) {} 582static inline void efi_free_boot_services(void) {}
583
584static inline efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
585{
586 return EFI_SUCCESS;
587}
581#endif 588#endif
582extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr); 589extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
583extern u64 efi_get_iobase (void); 590extern u64 efi_get_iobase (void);
@@ -731,7 +738,7 @@ struct efivar_operations {
731 efi_get_variable_t *get_variable; 738 efi_get_variable_t *get_variable;
732 efi_get_next_variable_t *get_next_variable; 739 efi_get_next_variable_t *get_next_variable;
733 efi_set_variable_t *set_variable; 740 efi_set_variable_t *set_variable;
734 efi_query_variable_info_t *query_variable_info; 741 efi_query_variable_store_t *query_variable_store;
735}; 742};
736 743
737struct efivars { 744struct efivars {
diff --git a/include/linux/ucs2_string.h b/include/linux/ucs2_string.h
new file mode 100644
index 000000000000..cbb20afdbc01
--- /dev/null
+++ b/include/linux/ucs2_string.h
@@ -0,0 +1,14 @@
1#ifndef _LINUX_UCS2_STRING_H_
2#define _LINUX_UCS2_STRING_H_
3
4#include <linux/types.h> /* for size_t */
5#include <linux/stddef.h> /* for NULL */
6
7typedef u16 ucs2_char_t;
8
9unsigned long ucs2_strnlen(const ucs2_char_t *s, size_t maxlength);
10unsigned long ucs2_strlen(const ucs2_char_t *s);
11unsigned long ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength);
12int ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len);
13
14#endif /* _LINUX_UCS2_STRING_H_ */
diff --git a/lib/Kconfig b/lib/Kconfig
index 3958dc4389f9..fe01d418b09a 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -404,4 +404,7 @@ config OID_REGISTRY
404 help 404 help
405 Enable fast lookup object identifier registry. 405 Enable fast lookup object identifier registry.
406 406
407config UCS2_STRING
408 tristate
409
407endmenu 410endmenu
diff --git a/lib/Makefile b/lib/Makefile
index d7946ff75b2e..6e2cc561f761 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -174,3 +174,5 @@ quiet_cmd_build_OID_registry = GEN $@
174 cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@ 174 cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@
175 175
176clean-files += oid_registry_data.c 176clean-files += oid_registry_data.c
177
178obj-$(CONFIG_UCS2_STRING) += ucs2_string.o
diff --git a/lib/ucs2_string.c b/lib/ucs2_string.c
new file mode 100644
index 000000000000..6f500ef2301d
--- /dev/null
+++ b/lib/ucs2_string.c
@@ -0,0 +1,51 @@
1#include <linux/ucs2_string.h>
2#include <linux/module.h>
3
4/* Return the number of unicode characters in data */
5unsigned long
6ucs2_strnlen(const ucs2_char_t *s, size_t maxlength)
7{
8 unsigned long length = 0;
9
10 while (*s++ != 0 && length < maxlength)
11 length++;
12 return length;
13}
14EXPORT_SYMBOL(ucs2_strnlen);
15
16unsigned long
17ucs2_strlen(const ucs2_char_t *s)
18{
19 return ucs2_strnlen(s, ~0UL);
20}
21EXPORT_SYMBOL(ucs2_strlen);
22
23/*
24 * Return the number of bytes is the length of this string
25 * Note: this is NOT the same as the number of unicode characters
26 */
27unsigned long
28ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength)
29{
30 return ucs2_strnlen(data, maxlength/sizeof(ucs2_char_t)) * sizeof(ucs2_char_t);
31}
32EXPORT_SYMBOL(ucs2_strsize);
33
34int
35ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len)
36{
37 while (1) {
38 if (len == 0)
39 return 0;
40 if (*a < *b)
41 return -1;
42 if (*a > *b)
43 return 1;
44 if (*a == 0) /* implies *b == 0 */
45 return 0;
46 a++;
47 b++;
48 len--;
49 }
50}
51EXPORT_SYMBOL(ucs2_strncmp);