Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Matthew Garrett and committed by
Matt Fleming
0635eb8a 7791c842

+89 -62
+1
drivers/firmware/Kconfig
··· 39 39 config EFI_VARS 40 40 tristate "EFI Variable Support via sysfs" 41 41 depends on EFI 42 + select UCS2_STRING 42 43 default n 43 44 help 44 45 If you say Y here, you are able to get EFI (Extensible Firmware
+18 -62
drivers/firmware/efivars.c
··· 80 80 #include <linux/slab.h> 81 81 #include <linux/pstore.h> 82 82 #include <linux/ctype.h> 83 + #include <linux/ucs2_string.h> 83 84 84 85 #include <linux/fs.h> 85 86 #include <linux/ramfs.h> ··· 173 172 static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries); 174 173 static bool efivar_wq_enabled = true; 175 174 176 - /* Return the number of unicode characters in data */ 177 - static unsigned long 178 - utf16_strnlen(efi_char16_t *s, size_t maxlength) 179 - { 180 - unsigned long length = 0; 181 - 182 - while (*s++ != 0 && length < maxlength) 183 - length++; 184 - return length; 185 - } 186 - 187 - static inline unsigned long 188 - utf16_strlen(efi_char16_t *s) 189 - { 190 - return utf16_strnlen(s, ~0UL); 191 - } 192 - 193 - /* 194 - * Return the number of bytes is the length of this string 195 - * Note: this is NOT the same as the number of unicode characters 196 - */ 197 - static inline unsigned long 198 - utf16_strsize(efi_char16_t *data, unsigned long maxlength) 199 - { 200 - return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t); 201 - } 202 - 203 - static inline int 204 - utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len) 205 - { 206 - while (1) { 207 - if (len == 0) 208 - return 0; 209 - if (*a < *b) 210 - return -1; 211 - if (*a > *b) 212 - return 1; 213 - if (*a == 0) /* implies *b == 0 */ 214 - return 0; 215 - a++; 216 - b++; 217 - len--; 218 - } 219 - } 220 - 221 175 static bool 222 176 validate_device_path(struct efi_variable *var, int match, u8 *buffer, 223 177 unsigned long len) ··· 224 268 u16 filepathlength; 225 269 int i, desclength = 0, namelen; 226 270 227 - namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName)); 271 + namelen = ucs2_strnlen(var->VariableName, sizeof(var->VariableName)); 228 272 229 273 /* Either "Boot" or "Driver" followed by four digits of hex */ 230 274 for (i = match; i < match+4; i++) { ··· 247 291 * There's no stored length for the description, so it has to be 248 292 * found by hand 249 293 */ 250 - desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2; 294 + desclength = ucs2_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2; 251 295 252 296 /* Each boot entry must have a descriptor */ 253 297 if (!desclength) ··· 537 581 spin_lock_irq(&efivars->lock); 538 582 539 583 status = check_var_size_locked(efivars, new_var->Attributes, 540 - new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); 584 + new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024)); 541 585 542 586 if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED) 543 587 status = efivars->ops->set_variable(new_var->VariableName, ··· 715 759 * QueryVariableInfo() isn't supported by the firmware. 716 760 */ 717 761 718 - varsize = datasize + utf16_strsize(var->var.VariableName, 1024); 762 + varsize = datasize + ucs2_strsize(var->var.VariableName, 1024); 719 763 status = check_var_size(efivars, attributes, varsize); 720 764 721 765 if (status != EFI_SUCCESS) { ··· 1167 1211 1168 1212 inode = NULL; 1169 1213 1170 - len = utf16_strlen(entry->var.VariableName); 1214 + len = ucs2_strlen(entry->var.VariableName); 1171 1215 1172 1216 /* name, plus '-', plus GUID, plus NUL*/ 1173 1217 name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC); ··· 1425 1469 1426 1470 if (efi_guidcmp(entry->var.VendorGuid, vendor)) 1427 1471 continue; 1428 - if (utf16_strncmp(entry->var.VariableName, efi_name, 1429 - utf16_strlen(efi_name))) { 1472 + if (ucs2_strncmp(entry->var.VariableName, efi_name, 1473 + ucs2_strlen(efi_name))) { 1430 1474 /* 1431 1475 * Check if an old format, 1432 1476 * which doesn't support holding ··· 1438 1482 for (i = 0; i < DUMP_NAME_LEN; i++) 1439 1483 efi_name_old[i] = name_old[i]; 1440 1484 1441 - if (utf16_strncmp(entry->var.VariableName, efi_name_old, 1442 - utf16_strlen(efi_name_old))) 1485 + if (ucs2_strncmp(entry->var.VariableName, efi_name_old, 1486 + ucs2_strlen(efi_name_old))) 1443 1487 continue; 1444 1488 } 1445 1489 ··· 1517 1561 * Does this variable already exist? 1518 1562 */ 1519 1563 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 1520 - strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 1521 - strsize2 = utf16_strsize(new_var->VariableName, 1024); 1564 + strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024); 1565 + strsize2 = ucs2_strsize(new_var->VariableName, 1024); 1522 1566 if (strsize1 == strsize2 && 1523 1567 !memcmp(&(search_efivar->var.VariableName), 1524 1568 new_var->VariableName, strsize1) && ··· 1534 1578 } 1535 1579 1536 1580 status = check_var_size_locked(efivars, new_var->Attributes, 1537 - new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); 1581 + new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024)); 1538 1582 1539 1583 if (status && status != EFI_UNSUPPORTED) { 1540 1584 spin_unlock_irq(&efivars->lock); ··· 1558 1602 1559 1603 /* Create the entry in sysfs. Locking is not required here */ 1560 1604 status = efivar_create_sysfs_entry(efivars, 1561 - utf16_strsize(new_var->VariableName, 1605 + ucs2_strsize(new_var->VariableName, 1562 1606 1024), 1563 1607 new_var->VariableName, 1564 1608 &new_var->VendorGuid); ··· 1588 1632 * Does this variable already exist? 1589 1633 */ 1590 1634 list_for_each_entry_safe(search_efivar, n, &efivars->list, list) { 1591 - strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024); 1592 - strsize2 = utf16_strsize(del_var->VariableName, 1024); 1635 + strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024); 1636 + strsize2 = ucs2_strsize(del_var->VariableName, 1024); 1593 1637 if (strsize1 == strsize2 && 1594 1638 !memcmp(&(search_efivar->var.VariableName), 1595 1639 del_var->VariableName, strsize1) && ··· 1635 1679 unsigned long strsize1, strsize2; 1636 1680 bool found = false; 1637 1681 1638 - strsize1 = utf16_strsize(variable_name, 1024); 1682 + strsize1 = ucs2_strsize(variable_name, 1024); 1639 1683 list_for_each_entry_safe(entry, n, &efivars->list, list) { 1640 - strsize2 = utf16_strsize(entry->var.VariableName, 1024); 1684 + strsize2 = ucs2_strsize(entry->var.VariableName, 1024); 1641 1685 if (strsize1 == strsize2 && 1642 1686 !memcmp(variable_name, &(entry->var.VariableName), 1643 1687 strsize2) &&
+14
include/linux/ucs2_string.h
··· 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 + 7 + typedef u16 ucs2_char_t; 8 + 9 + unsigned long ucs2_strnlen(const ucs2_char_t *s, size_t maxlength); 10 + unsigned long ucs2_strlen(const ucs2_char_t *s); 11 + unsigned long ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength); 12 + int ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len); 13 + 14 + #endif /* _LINUX_UCS2_STRING_H_ */
+3
lib/Kconfig
··· 404 404 help 405 405 Enable fast lookup object identifier registry. 406 406 407 + config UCS2_STRING 408 + tristate 409 + 407 410 endmenu
+2
lib/Makefile
··· 174 174 cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@ 175 175 176 176 clean-files += oid_registry_data.c 177 + 178 + obj-$(CONFIG_UCS2_STRING) += ucs2_string.o
+51
lib/ucs2_string.c
··· 1 + #include <linux/ucs2_string.h> 2 + #include <linux/module.h> 3 + 4 + /* Return the number of unicode characters in data */ 5 + unsigned long 6 + ucs2_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 + } 14 + EXPORT_SYMBOL(ucs2_strnlen); 15 + 16 + unsigned long 17 + ucs2_strlen(const ucs2_char_t *s) 18 + { 19 + return ucs2_strnlen(s, ~0UL); 20 + } 21 + EXPORT_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 + */ 27 + unsigned long 28 + ucs2_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 + } 32 + EXPORT_SYMBOL(ucs2_strsize); 33 + 34 + int 35 + ucs2_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 + } 51 + EXPORT_SYMBOL(ucs2_strncmp);