| From e0d64e6a880e64545ad7d55786aa84ab76bac475 Mon Sep 17 00:00:00 2001 |
| From: Peter Jones <pjones@redhat.com> |
| Date: Mon, 8 Feb 2016 14:48:12 -0500 |
| Subject: efi: Use ucs2_as_utf8 in efivarfs instead of open coding a bad version |
| |
| From: Peter Jones <pjones@redhat.com> |
| |
| commit e0d64e6a880e64545ad7d55786aa84ab76bac475 upstream. |
| |
| Translate EFI's UCS-2 variable names to UTF-8 instead of just assuming |
| all variable names fit in ASCII. |
| |
| Signed-off-by: Peter Jones <pjones@redhat.com> |
| Acked-by: Matthew Garrett <mjg59@coreos.com> |
| Tested-by: Lee, Chun-Yi <jlee@suse.com> |
| Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/firmware/efi/efivars.c | 28 ++++++++++------------------ |
| fs/efivarfs/super.c | 7 +++---- |
| 2 files changed, 13 insertions(+), 22 deletions(-) |
| |
| --- a/drivers/firmware/efi/efivars.c |
| +++ b/drivers/firmware/efi/efivars.c |
| @@ -405,35 +405,27 @@ efivar_create_sysfs_entry(struct efivar_ |
| { |
| int i, short_name_size; |
| char *short_name; |
| - unsigned long variable_name_size; |
| - efi_char16_t *variable_name; |
| - |
| - variable_name = new_var->var.VariableName; |
| - variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t); |
| + unsigned long utf8_name_size; |
| + efi_char16_t *variable_name = new_var->var.VariableName; |
| |
| /* |
| - * 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 |
| */ |
| - short_name_size = variable_name_size / sizeof(efi_char16_t) |
| - + 1 + EFI_VARIABLE_GUID_LEN + 1; |
| - |
| - short_name = kzalloc(short_name_size, GFP_KERNEL); |
| + utf8_name_size = ucs2_utf8size(variable_name); |
| + short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1; |
| |
| + short_name = kmalloc(short_name_size, GFP_KERNEL); |
| if (!short_name) |
| return 1; |
| |
| - /* Convert Unicode to normal chars (assume top bits are 0), |
| - ala UTF-8 */ |
| - for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) { |
| - short_name[i] = variable_name[i] & 0xFF; |
| - } |
| + ucs2_as_utf8(short_name, variable_name, short_name_size); |
| + |
| /* This is ugly, but necessary to separate one vendor's |
| private variables from another's. */ |
| - |
| - *(short_name + strlen(short_name)) = '-'; |
| + short_name[utf8_name_size] = '-'; |
| efi_guid_unparse(&new_var->var.VendorGuid, |
| - short_name + strlen(short_name)); |
| + short_name + utf8_name_size + 1); |
| |
| new_var->kobj.kset = efivars_kset; |
| |
| --- a/fs/efivarfs/super.c |
| +++ b/fs/efivarfs/super.c |
| @@ -128,7 +128,7 @@ static int efivarfs_callback(efi_char16_ |
| struct dentry *dentry, *root = sb->s_root; |
| unsigned long size = 0; |
| char *name; |
| - int len, i; |
| + int len; |
| int err = -ENOMEM; |
| |
| entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
| @@ -138,15 +138,14 @@ static int efivarfs_callback(efi_char16_ |
| memcpy(entry->var.VariableName, name16, name_size); |
| 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 = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL); |
| if (!name) |
| goto fail; |
| |
| - for (i = 0; i < len; i++) |
| - name[i] = entry->var.VariableName[i] & 0xFF; |
| + ucs2_as_utf8(name, entry->var.VariableName, len); |
| |
| name[len] = '-'; |
| |