diff options
author | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2019-07-14 19:26:47 +0200 |
---|---|---|
committer | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2019-07-16 22:17:23 +0000 |
commit | 046fe7b50741363bd2df47cd01b35c0228b165bf (patch) | |
tree | 938d37679eea2e17062a9befdfe5dcb9c0400bdb /lib/efi_loader/efi_device_path.c | |
parent | 02b31dce934d64edf26c3757fb5749f83eae621e (diff) |
efi_loader: efi_dp_from_file() expect UTF-8 path
Properly convert UTF-8 file names to UTF-16.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Diffstat (limited to 'lib/efi_loader/efi_device_path.c')
-rw-r--r-- | lib/efi_loader/efi_device_path.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 10f890f44f..eeeb806836 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -12,6 +12,7 @@ #include <mmc.h> #include <efi_loader.h> #include <part.h> +#include <asm-generic/unaligned.h> /* template END node: */ static const struct efi_device_path END = { @@ -793,16 +794,36 @@ struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part) return buf; } -/* convert path to an UEFI style path (i.e. DOS style backslashes and UTF-16) */ -static void path_to_uefi(u16 *uefi, const char *path) +/** + * path_to_uefi() - convert UTF-8 path to an UEFI style path + * + * Convert UTF-8 path to a UEFI style path (i.e. with backslashes as path + * separators and UTF-16). + * + * @src: source buffer + * @uefi: target buffer, possibly unaligned + */ +static void path_to_uefi(void *uefi, const char *src) { - while (*path) { - char c = *(path++); - if (c == '/') - c = '\\'; - *(uefi++) = c; + u16 *pos = uefi; + + /* + * efi_set_bootdev() calls this routine indirectly before the UEFI + * subsystem is initialized. So we cannot assume unaligned access to be + * enabled. + */ + allow_unaligned(); + + while (*src) { + s32 code = utf8_get(&src); + + if (code < 0) + code = '?'; + else if (code == '/') + code = '\\'; + utf16_put(code, &pos); } - *uefi = '\0'; + *pos = 0; } /* @@ -819,7 +840,8 @@ struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part, if (desc) dpsize = dp_part_size(desc, part); - fpsize = sizeof(struct efi_device_path) + 2 * (strlen(path) + 1); + fpsize = sizeof(struct efi_device_path) + + 2 * (utf8_utf16_strlen(path) + 1); dpsize += fpsize; start = buf = dp_alloc(dpsize + sizeof(END)); |