Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e0d64e6a authored by Peter Jones's avatar Peter Jones Committed by Matt Fleming
Browse files

efi: Use ucs2_as_utf8 in efivarfs instead of open coding a bad version



Translate EFI's UCS-2 variable names to UTF-8 instead of just assuming
all variable names fit in ASCII.

Signed-off-by: default avatarPeter Jones <pjones@redhat.com>
Acked-by: default avatarMatthew Garrett <mjg59@coreos.com>
Tested-by: default avatarLee, Chun-Yi <jlee@suse.com>
Signed-off-by: default avatarMatt Fleming <matt@codeblueprint.co.uk>
parent 73500267
Loading
Loading
Loading
Loading
+11 −19
Original line number Original line Diff line number Diff line
@@ -540,38 +540,30 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
static int
static int
efivar_create_sysfs_entry(struct efivar_entry *new_var)
efivar_create_sysfs_entry(struct efivar_entry *new_var)
{
{
	int i, short_name_size;
	int short_name_size;
	char *short_name;
	char *short_name;
	unsigned long variable_name_size;
	unsigned long utf8_name_size;
	efi_char16_t *variable_name;
	efi_char16_t *variable_name = new_var->var.VariableName;
	int ret;
	int ret;


	variable_name = new_var->var.VariableName;
	variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t);

	/*
	/*
	 * Length of the variable bytes in ASCII, plus the '-' separator,
	 * Length of the variable bytes in UTF8, plus the '-' separator,
	 * plus the GUID, plus trailing NUL
	 * plus the GUID, plus trailing NUL
	 */
	 */
	short_name_size = variable_name_size / sizeof(efi_char16_t)
	utf8_name_size = ucs2_utf8size(variable_name);
				+ 1 + EFI_VARIABLE_GUID_LEN + 1;
	short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1;

	short_name = kzalloc(short_name_size, GFP_KERNEL);


	short_name = kmalloc(short_name_size, GFP_KERNEL);
	if (!short_name)
	if (!short_name)
		return -ENOMEM;
		return -ENOMEM;


	/* Convert Unicode to normal chars (assume top bits are 0),
	ucs2_as_utf8(short_name, variable_name, short_name_size);
	   ala UTF-8 */

	for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
		short_name[i] = variable_name[i] & 0xFF;
	}
	/* This is ugly, but necessary to separate one vendor's
	/* This is ugly, but necessary to separate one vendor's
	   private variables from another's.         */
	   private variables from another's.         */

	short_name[utf8_name_size] = '-';
	*(short_name + strlen(short_name)) = '-';
	efi_guid_to_str(&new_var->var.VendorGuid,
	efi_guid_to_str(&new_var->var.VendorGuid,
			 short_name + strlen(short_name));
			 short_name + utf8_name_size + 1);


	new_var->kobj.kset = efivars_kset;
	new_var->kobj.kset = efivars_kset;


+3 −4
Original line number Original line Diff line number Diff line
@@ -118,7 +118,7 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
	struct dentry *dentry, *root = sb->s_root;
	struct dentry *dentry, *root = sb->s_root;
	unsigned long size = 0;
	unsigned long size = 0;
	char *name;
	char *name;
	int len, i;
	int len;
	int err = -ENOMEM;
	int err = -ENOMEM;


	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
@@ -128,15 +128,14 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
	memcpy(entry->var.VariableName, name16, name_size);
	memcpy(entry->var.VariableName, name16, name_size);
	memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
	memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));


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


	/* name, plus '-', plus GUID, plus NUL*/
	/* name, plus '-', plus GUID, plus NUL*/
	name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL);
	name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL);
	if (!name)
	if (!name)
		goto fail;
		goto fail;


	for (i = 0; i < len; i++)
	ucs2_as_utf8(name, entry->var.VariableName, len);
		name[i] = entry->var.VariableName[i] & 0xFF;


	name[len] = '-';
	name[len] = '-';