aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorMatthew Garrett <matthew.garrett@nebula.com>2013-04-15 16:09:45 -0400
committerMatt Fleming <matt.fleming@intel.com>2013-04-15 16:23:03 -0400
commit0635eb8a54cf0fea64b174bb68bc36b9c3d622db (patch)
tree9430096d286e5da9044ab7e6cb85bdaca07c9717 /drivers/firmware
parent7791c8423f1f7f4dad94e753bae67461d5b80be8 (diff)
Move utf16 functions to kernel core and rename
We want to be able to use the utf16 functions that are currently present in the EFI variables code in platform-specific code as well. Move them to the kernel core, and in the process rename them to accurately describe what they do - they don't handle UTF16, only UCS2. Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> Signed-off-by: Matt Fleming <matt.fleming@intel.com>
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) &&