aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/Kconfig1
-rw-r--r--drivers/firmware/efivars.c80
2 files changed, 19 insertions, 62 deletions
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 bf15d81d74e1..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)
@@ -581,7 +537,7 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
581 spin_lock_irq(&efivars->lock); 537 spin_lock_irq(&efivars->lock);
582 538
583 status = check_var_size_locked(efivars, new_var->Attributes, 539 status = check_var_size_locked(efivars, new_var->Attributes,
584 new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); 540 new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024));
585 541
586 if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED) 542 if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
587 status = efivars->ops->set_variable(new_var->VariableName, 543 status = efivars->ops->set_variable(new_var->VariableName,
@@ -759,7 +715,7 @@ static ssize_t efivarfs_file_write(struct file *file,
759 * QueryVariableInfo() isn't supported by the firmware. 715 * QueryVariableInfo() isn't supported by the firmware.
760 */ 716 */
761 717
762 varsize = datasize + utf16_strsize(var->var.VariableName, 1024); 718 varsize = datasize + ucs2_strsize(var->var.VariableName, 1024);
763 status = check_var_size(efivars, attributes, varsize); 719 status = check_var_size(efivars, attributes, varsize);
764 720
765 if (status != EFI_SUCCESS) { 721 if (status != EFI_SUCCESS) {
@@ -1211,7 +1167,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
1211 1167
1212 inode = NULL; 1168 inode = NULL;
1213 1169
1214 len = utf16_strlen(entry->var.VariableName); 1170 len = ucs2_strlen(entry->var.VariableName);
1215 1171
1216 /* name, plus '-', plus GUID, plus NUL*/ 1172 /* name, plus '-', plus GUID, plus NUL*/
1217 name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC); 1173 name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC);
@@ -1469,8 +1425,8 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
1469 1425
1470 if (efi_guidcmp(entry->var.VendorGuid, vendor)) 1426 if (efi_guidcmp(entry->var.VendorGuid, vendor))
1471 continue; 1427 continue;
1472 if (utf16_strncmp(entry->var.VariableName, efi_name, 1428 if (ucs2_strncmp(entry->var.VariableName, efi_name,
1473 utf16_strlen(efi_name))) { 1429 ucs2_strlen(efi_name))) {
1474 /* 1430 /*
1475 * Check if an old format, 1431 * Check if an old format,
1476 * which doesn't support holding 1432 * which doesn't support holding
@@ -1482,8 +1438,8 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
1482 for (i = 0; i < DUMP_NAME_LEN; i++) 1438 for (i = 0; i < DUMP_NAME_LEN; i++)
1483 efi_name_old[i] = name_old[i]; 1439 efi_name_old[i] = name_old[i];
1484 1440
1485 if (utf16_strncmp(entry->var.VariableName, efi_name_old, 1441 if (ucs2_strncmp(entry->var.VariableName, efi_name_old,
1486 utf16_strlen(efi_name_old))) 1442 ucs2_strlen(efi_name_old)))
1487 continue; 1443 continue;
1488 } 1444 }
1489 1445
@@ -1561,8 +1517,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
1561 * Does this variable already exist? 1517 * Does this variable already exist?
1562 */ 1518 */
1563 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 1519 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
1564 strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 1520 strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024);
1565 strsize2 = utf16_strsize(new_var->VariableName, 1024); 1521 strsize2 = ucs2_strsize(new_var->VariableName, 1024);
1566 if (strsize1 == strsize2 && 1522 if (strsize1 == strsize2 &&
1567 !memcmp(&(search_efivar->var.VariableName), 1523 !memcmp(&(search_efivar->var.VariableName),
1568 new_var->VariableName, strsize1) && 1524 new_var->VariableName, strsize1) &&
@@ -1578,7 +1534,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
1578 } 1534 }
1579 1535
1580 status = check_var_size_locked(efivars, new_var->Attributes, 1536 status = check_var_size_locked(efivars, new_var->Attributes,
1581 new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); 1537 new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024));
1582 1538
1583 if (status && status != EFI_UNSUPPORTED) { 1539 if (status && status != EFI_UNSUPPORTED) {
1584 spin_unlock_irq(&efivars->lock); 1540 spin_unlock_irq(&efivars->lock);
@@ -1602,7 +1558,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
1602 1558
1603 /* Create the entry in sysfs. Locking is not required here */ 1559 /* Create the entry in sysfs. Locking is not required here */
1604 status = efivar_create_sysfs_entry(efivars, 1560 status = efivar_create_sysfs_entry(efivars,
1605 utf16_strsize(new_var->VariableName, 1561 ucs2_strsize(new_var->VariableName,
1606 1024), 1562 1024),
1607 new_var->VariableName, 1563 new_var->VariableName,
1608 &new_var->VendorGuid); 1564 &new_var->VendorGuid);
@@ -1632,8 +1588,8 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
1632 * Does this variable already exist? 1588 * Does this variable already exist?
1633 */ 1589 */
1634 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 1590 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
1635 strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 1591 strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024);
1636 strsize2 = utf16_strsize(del_var->VariableName, 1024); 1592 strsize2 = ucs2_strsize(del_var->VariableName, 1024);
1637 if (strsize1 == strsize2 && 1593 if (strsize1 == strsize2 &&
1638 !memcmp(&(search_efivar->var.VariableName), 1594 !memcmp(&(search_efivar->var.VariableName),
1639 del_var->VariableName, strsize1) && 1595 del_var->VariableName, strsize1) &&
@@ -1679,9 +1635,9 @@ static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor)
1679 unsigned long strsize1, strsize2; 1635 unsigned long strsize1, strsize2;
1680 bool found = false; 1636 bool found = false;
1681 1637
1682 strsize1 = utf16_strsize(variable_name, 1024); 1638 strsize1 = ucs2_strsize(variable_name, 1024);
1683 list_for_each_entry_safe(entry, n, &efivars->list, list) { 1639 list_for_each_entry_safe(entry, n, &efivars->list, list) {
1684 strsize2 = utf16_strsize(entry->var.VariableName, 1024); 1640 strsize2 = ucs2_strsize(entry->var.VariableName, 1024);
1685 if (strsize1 == strsize2 && 1641 if (strsize1 == strsize2 &&
1686 !memcmp(variable_name, &(entry->var.VariableName), 1642 !memcmp(variable_name, &(entry->var.VariableName),
1687 strsize2) && 1643 strsize2) &&