summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2019-07-14 19:26:47 +0200
committerIgor Opaniuk <igor.opaniuk@toradex.com>2019-08-30 14:56:03 +0300
commit39f6f546f4ec9f3b15b6bd970da552d828311963 (patch)
treebbafb03f7e5f7fc2db556836721fe56e827aa75c
parente1cbe8c74e87036e649b0e34656aebabb3aa00c7 (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>
-rw-r--r--lib/efi_loader/efi_device_path.c40
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));