Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 362695
b: refs/heads/master
c: 0635eb8
h: refs/heads/master
i:
  362693: e833469
  362691: ec6f3d9
  362687: 86f0cae
v: v3
  • Loading branch information
Matthew Garrett authored and Matt Fleming committed Apr 15, 2013
1 parent 8ec390e commit 61d1bd6
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 63 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7791c8423f1f7f4dad94e753bae67461d5b80be8
refs/heads/master: 0635eb8a54cf0fea64b174bb68bc36b9c3d622db
1 change: 1 addition & 0 deletions trunk/drivers/firmware/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ config FIRMWARE_MEMMAP
config EFI_VARS
tristate "EFI Variable Support via sysfs"
depends on EFI
select UCS2_STRING
default n
help
If you say Y here, you are able to get EFI (Extensible Firmware
Expand Down
80 changes: 18 additions & 62 deletions trunk/drivers/firmware/efivars.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
#include <linux/slab.h>
#include <linux/pstore.h>
#include <linux/ctype.h>
#include <linux/ucs2_string.h>

#include <linux/fs.h>
#include <linux/ramfs.h>
Expand Down Expand Up @@ -172,51 +173,6 @@ static void efivar_update_sysfs_entries(struct work_struct *);
static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries);
static bool efivar_wq_enabled = true;

/* Return the number of unicode characters in data */
static unsigned long
utf16_strnlen(efi_char16_t *s, size_t maxlength)
{
unsigned long length = 0;

while (*s++ != 0 && length < maxlength)
length++;
return length;
}

static inline unsigned long
utf16_strlen(efi_char16_t *s)
{
return utf16_strnlen(s, ~0UL);
}

/*
* Return the number of bytes is the length of this string
* Note: this is NOT the same as the number of unicode characters
*/
static inline unsigned long
utf16_strsize(efi_char16_t *data, unsigned long maxlength)
{
return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
}

static inline int
utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len)
{
while (1) {
if (len == 0)
return 0;
if (*a < *b)
return -1;
if (*a > *b)
return 1;
if (*a == 0) /* implies *b == 0 */
return 0;
a++;
b++;
len--;
}
}

static bool
validate_device_path(struct efi_variable *var, int match, u8 *buffer,
unsigned long len)
Expand Down Expand Up @@ -268,7 +224,7 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer,
u16 filepathlength;
int i, desclength = 0, namelen;

namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName));
namelen = ucs2_strnlen(var->VariableName, sizeof(var->VariableName));

/* Either "Boot" or "Driver" followed by four digits of hex */
for (i = match; i < match+4; i++) {
Expand All @@ -291,7 +247,7 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer,
* There's no stored length for the description, so it has to be
* found by hand
*/
desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
desclength = ucs2_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;

/* Each boot entry must have a descriptor */
if (!desclength)
Expand Down Expand Up @@ -581,7 +537,7 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
spin_lock_irq(&efivars->lock);

status = check_var_size_locked(efivars, new_var->Attributes,
new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024));

if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
status = efivars->ops->set_variable(new_var->VariableName,
Expand Down Expand Up @@ -759,7 +715,7 @@ static ssize_t efivarfs_file_write(struct file *file,
* QueryVariableInfo() isn't supported by the firmware.
*/

varsize = datasize + utf16_strsize(var->var.VariableName, 1024);
varsize = datasize + ucs2_strsize(var->var.VariableName, 1024);
status = check_var_size(efivars, attributes, varsize);

if (status != EFI_SUCCESS) {
Expand Down Expand Up @@ -1211,7 +1167,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)

inode = NULL;

len = utf16_strlen(entry->var.VariableName);
len = ucs2_strlen(entry->var.VariableName);

/* name, plus '-', plus GUID, plus NUL*/
name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC);
Expand Down Expand Up @@ -1469,8 +1425,8 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,

if (efi_guidcmp(entry->var.VendorGuid, vendor))
continue;
if (utf16_strncmp(entry->var.VariableName, efi_name,
utf16_strlen(efi_name))) {
if (ucs2_strncmp(entry->var.VariableName, efi_name,
ucs2_strlen(efi_name))) {
/*
* Check if an old format,
* which doesn't support holding
Expand All @@ -1482,8 +1438,8 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
for (i = 0; i < DUMP_NAME_LEN; i++)
efi_name_old[i] = name_old[i];

if (utf16_strncmp(entry->var.VariableName, efi_name_old,
utf16_strlen(efi_name_old)))
if (ucs2_strncmp(entry->var.VariableName, efi_name_old,
ucs2_strlen(efi_name_old)))
continue;
}

Expand Down Expand Up @@ -1561,8 +1517,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
* Does this variable already exist?
*/
list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
strsize2 = utf16_strsize(new_var->VariableName, 1024);
strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024);
strsize2 = ucs2_strsize(new_var->VariableName, 1024);
if (strsize1 == strsize2 &&
!memcmp(&(search_efivar->var.VariableName),
new_var->VariableName, strsize1) &&
Expand All @@ -1578,7 +1534,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
}

status = check_var_size_locked(efivars, new_var->Attributes,
new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024));

if (status && status != EFI_UNSUPPORTED) {
spin_unlock_irq(&efivars->lock);
Expand All @@ -1602,7 +1558,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,

/* Create the entry in sysfs. Locking is not required here */
status = efivar_create_sysfs_entry(efivars,
utf16_strsize(new_var->VariableName,
ucs2_strsize(new_var->VariableName,
1024),
new_var->VariableName,
&new_var->VendorGuid);
Expand Down Expand Up @@ -1632,8 +1588,8 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
* Does this variable already exist?
*/
list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
strsize2 = utf16_strsize(del_var->VariableName, 1024);
strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024);
strsize2 = ucs2_strsize(del_var->VariableName, 1024);
if (strsize1 == strsize2 &&
!memcmp(&(search_efivar->var.VariableName),
del_var->VariableName, strsize1) &&
Expand Down Expand Up @@ -1679,9 +1635,9 @@ static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor)
unsigned long strsize1, strsize2;
bool found = false;

strsize1 = utf16_strsize(variable_name, 1024);
strsize1 = ucs2_strsize(variable_name, 1024);
list_for_each_entry_safe(entry, n, &efivars->list, list) {
strsize2 = utf16_strsize(entry->var.VariableName, 1024);
strsize2 = ucs2_strsize(entry->var.VariableName, 1024);
if (strsize1 == strsize2 &&
!memcmp(variable_name, &(entry->var.VariableName),
strsize2) &&
Expand Down
14 changes: 14 additions & 0 deletions trunk/include/linux/ucs2_string.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef _LINUX_UCS2_STRING_H_
#define _LINUX_UCS2_STRING_H_

#include <linux/types.h> /* for size_t */
#include <linux/stddef.h> /* for NULL */

typedef u16 ucs2_char_t;

unsigned long ucs2_strnlen(const ucs2_char_t *s, size_t maxlength);
unsigned long ucs2_strlen(const ucs2_char_t *s);
unsigned long ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength);
int ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len);

#endif /* _LINUX_UCS2_STRING_H_ */
3 changes: 3 additions & 0 deletions trunk/lib/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -404,4 +404,7 @@ config OID_REGISTRY
help
Enable fast lookup object identifier registry.

config UCS2_STRING
tristate

endmenu
2 changes: 2 additions & 0 deletions trunk/lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,5 @@ quiet_cmd_build_OID_registry = GEN $@
cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@

clean-files += oid_registry_data.c

obj-$(CONFIG_UCS2_STRING) += ucs2_string.o
51 changes: 51 additions & 0 deletions trunk/lib/ucs2_string.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <linux/ucs2_string.h>
#include <linux/module.h>

/* Return the number of unicode characters in data */
unsigned long
ucs2_strnlen(const ucs2_char_t *s, size_t maxlength)
{
unsigned long length = 0;

while (*s++ != 0 && length < maxlength)
length++;
return length;
}
EXPORT_SYMBOL(ucs2_strnlen);

unsigned long
ucs2_strlen(const ucs2_char_t *s)
{
return ucs2_strnlen(s, ~0UL);
}
EXPORT_SYMBOL(ucs2_strlen);

/*
* Return the number of bytes is the length of this string
* Note: this is NOT the same as the number of unicode characters
*/
unsigned long
ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength)
{
return ucs2_strnlen(data, maxlength/sizeof(ucs2_char_t)) * sizeof(ucs2_char_t);
}
EXPORT_SYMBOL(ucs2_strsize);

int
ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len)
{
while (1) {
if (len == 0)
return 0;
if (*a < *b)
return -1;
if (*a > *b)
return 1;
if (*a == 0) /* implies *b == 0 */
return 0;
a++;
b++;
len--;
}
}
EXPORT_SYMBOL(ucs2_strncmp);

0 comments on commit 61d1bd6

Please sign in to comment.