ac3a84
From 57474bf255aafb683f4bb38e5bcb88cf48f07882 Mon Sep 17 00:00:00 2001
ac3a84
From: Jan Janssen <medhefgo@web.de>
ac3a84
Date: Tue, 22 Nov 2022 16:30:44 +0100
ac3a84
Subject: [PATCH] boot: Use xstr8_to_16 for path conversion
ac3a84
ac3a84
(cherry picked from commit 7444e10611671abac35be3ab9fe9697cd4c90d62)
ac3a84
ac3a84
Related: #2138081
ac3a84
---
ac3a84
 src/boot/efi/boot.c |   8 ++--
ac3a84
 src/boot/efi/cpio.c |  19 +--------
ac3a84
 src/boot/efi/util.c | 102 ++++++++------------------------------------
ac3a84
 src/boot/efi/util.h |   3 +-
ac3a84
 4 files changed, 24 insertions(+), 108 deletions(-)
ac3a84
ac3a84
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
ac3a84
index 013df67e49..581043df01 100644
ac3a84
--- a/src/boot/efi/boot.c
ac3a84
+++ b/src/boot/efi/boot.c
ac3a84
@@ -1465,7 +1465,7 @@ static void config_entry_add_type1(
ac3a84
                 if (streq8(key, "linux")) {
ac3a84
                         free(entry->loader);
ac3a84
                         entry->type = LOADER_LINUX;
ac3a84
-                        entry->loader = xstra_to_path(value);
ac3a84
+                        entry->loader = xstr8_to_path(value);
ac3a84
                         entry->key = 'l';
ac3a84
                         continue;
ac3a84
                 }
ac3a84
@@ -1473,7 +1473,7 @@ static void config_entry_add_type1(
ac3a84
                 if (streq8(key, "efi")) {
ac3a84
                         entry->type = LOADER_EFI;
ac3a84
                         free(entry->loader);
ac3a84
-                        entry->loader = xstra_to_path(value);
ac3a84
+                        entry->loader = xstr8_to_path(value);
ac3a84
 
ac3a84
                         /* do not add an entry for ourselves */
ac3a84
                         if (strcaseeq16(entry->loader, loaded_image_path)) {
ac3a84
@@ -1494,7 +1494,7 @@ static void config_entry_add_type1(
ac3a84
 
ac3a84
                 if (streq8(key, "devicetree")) {
ac3a84
                         free(entry->devicetree);
ac3a84
-                        entry->devicetree = xstra_to_path(value);
ac3a84
+                        entry->devicetree = xstr8_to_path(value);
ac3a84
                         continue;
ac3a84
                 }
ac3a84
 
ac3a84
@@ -1503,7 +1503,7 @@ static void config_entry_add_type1(
ac3a84
                                 entry->initrd,
ac3a84
                                 n_initrd == 0 ? 0 : (n_initrd + 1) * sizeof(uint16_t *),
ac3a84
                                 (n_initrd + 2) * sizeof(uint16_t *));
ac3a84
-                        entry->initrd[n_initrd++] = xstra_to_path(value);
ac3a84
+                        entry->initrd[n_initrd++] = xstr8_to_path(value);
ac3a84
                         entry->initrd[n_initrd] = NULL;
ac3a84
                         continue;
ac3a84
                 }
ac3a84
diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c
ac3a84
index 1dbfe5f380..79b5d4327b 100644
ac3a84
--- a/src/boot/efi/cpio.c
ac3a84
+++ b/src/boot/efi/cpio.c
ac3a84
@@ -359,24 +359,7 @@ static char16_t *get_dropin_dir(const EFI_DEVICE_PATH *file_path) {
ac3a84
         if (device_path_to_str(file_path, &file_path_str) != EFI_SUCCESS)
ac3a84
                 return NULL;
ac3a84
 
ac3a84
-        for (char16_t *i = file_path_str, *fixed = i;; i++) {
ac3a84
-                if (*i == '\0') {
ac3a84
-                        *fixed = '\0';
ac3a84
-                        break;
ac3a84
-                }
ac3a84
-
ac3a84
-                /* Fix device path node separator. */
ac3a84
-                if (*i == '/')
ac3a84
-                        *i = '\\';
ac3a84
-
ac3a84
-                /* Double '\' is not allowed in EFI file paths. */
ac3a84
-                if (fixed != file_path_str && fixed[-1] == '\\' && *i == '\\')
ac3a84
-                        continue;
ac3a84
-
ac3a84
-                *fixed = *i;
ac3a84
-                fixed++;
ac3a84
-        }
ac3a84
-
ac3a84
+        convert_efi_path(file_path_str);
ac3a84
         return xpool_print(u"%s.extra.d", file_path_str);
ac3a84
 }
ac3a84
 
ac3a84
diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c
ac3a84
index b727d6de7e..3268c511d0 100644
ac3a84
--- a/src/boot/efi/util.c
ac3a84
+++ b/src/boot/efi/util.c
ac3a84
@@ -249,97 +249,29 @@ void efivar_set_time_usec(const EFI_GUID *vendor, const char16_t *name, uint64_t
ac3a84
         efivar_set(vendor, name, str, 0);
ac3a84
 }
ac3a84
 
ac3a84
-static int utf8_to_16(const char *stra, char16_t *c) {
ac3a84
-        char16_t unichar;
ac3a84
-        UINTN len;
ac3a84
-
ac3a84
-        assert(stra);
ac3a84
-        assert(c);
ac3a84
-
ac3a84
-        if (!(stra[0] & 0x80))
ac3a84
-                len = 1;
ac3a84
-        else if ((stra[0] & 0xe0) == 0xc0)
ac3a84
-                len = 2;
ac3a84
-        else if ((stra[0] & 0xf0) == 0xe0)
ac3a84
-                len = 3;
ac3a84
-        else if ((stra[0] & 0xf8) == 0xf0)
ac3a84
-                len = 4;
ac3a84
-        else if ((stra[0] & 0xfc) == 0xf8)
ac3a84
-                len = 5;
ac3a84
-        else if ((stra[0] & 0xfe) == 0xfc)
ac3a84
-                len = 6;
ac3a84
-        else
ac3a84
-                return -1;
ac3a84
-
ac3a84
-        switch (len) {
ac3a84
-        case 1:
ac3a84
-                unichar = stra[0];
ac3a84
-                break;
ac3a84
-        case 2:
ac3a84
-                unichar = stra[0] & 0x1f;
ac3a84
-                break;
ac3a84
-        case 3:
ac3a84
-                unichar = stra[0] & 0x0f;
ac3a84
-                break;
ac3a84
-        case 4:
ac3a84
-                unichar = stra[0] & 0x07;
ac3a84
-                break;
ac3a84
-        case 5:
ac3a84
-                unichar = stra[0] & 0x03;
ac3a84
-                break;
ac3a84
-        case 6:
ac3a84
-                unichar = stra[0] & 0x01;
ac3a84
-                break;
ac3a84
-        }
ac3a84
-
ac3a84
-        for (UINTN i = 1; i < len; i++) {
ac3a84
-                if ((stra[i] & 0xc0) != 0x80)
ac3a84
-                        return -1;
ac3a84
-                unichar <<= 6;
ac3a84
-                unichar |= stra[i] & 0x3f;
ac3a84
-        }
ac3a84
-
ac3a84
-        *c = unichar;
ac3a84
-        return len;
ac3a84
-}
ac3a84
-
ac3a84
-char16_t *xstra_to_path(const char *stra) {
ac3a84
-        char16_t *str;
ac3a84
-        UINTN strlen;
ac3a84
-        UINTN len;
ac3a84
-        UINTN i;
ac3a84
-
ac3a84
-        assert(stra);
ac3a84
+void convert_efi_path(char16_t *path) {
ac3a84
+        assert(path);
ac3a84
 
ac3a84
-        len = strlen8(stra);
ac3a84
-        str = xnew(char16_t, len + 2);
ac3a84
+        for (size_t i = 0, fixed = 0;; i++) {
ac3a84
+                /* Fix device path node separator. */
ac3a84
+                path[fixed] = (path[i] == '/') ? '\\' : path[i];
ac3a84
 
ac3a84
-        str[0] = '\\';
ac3a84
-        strlen = 1;
ac3a84
-        i = 0;
ac3a84
-        while (i < len) {
ac3a84
-                int utf8len;
ac3a84
-
ac3a84
-                utf8len = utf8_to_16(stra + i, str + strlen);
ac3a84
-                if (utf8len <= 0) {
ac3a84
-                        /* invalid utf8 sequence, skip the garbage */
ac3a84
-                        i++;
ac3a84
+                /* Double '\' is not allowed in EFI file paths. */
ac3a84
+                if (fixed > 0 && path[fixed - 1] == '\\' && path[fixed] == '\\')
ac3a84
                         continue;
ac3a84
-                }
ac3a84
 
ac3a84
-                if (str[strlen] == '/')
ac3a84
-                        str[strlen] = '\\';
ac3a84
-                if (str[strlen] == '\\' && str[strlen-1] == '\\') {
ac3a84
-                        /* skip double slashes */
ac3a84
-                        i += utf8len;
ac3a84
-                        continue;
ac3a84
-                }
ac3a84
+                if (path[i] == '\0')
ac3a84
+                        break;
ac3a84
 
ac3a84
-                strlen++;
ac3a84
-                i += utf8len;
ac3a84
+                fixed++;
ac3a84
         }
ac3a84
-        str[strlen] = '\0';
ac3a84
-        return str;
ac3a84
+}
ac3a84
+
ac3a84
+char16_t *xstr8_to_path(const char *str8) {
ac3a84
+        assert(str8);
ac3a84
+        char16_t *path = xstr8_to_16(str8);
ac3a84
+        convert_efi_path(path);
ac3a84
+        return path;
ac3a84
 }
ac3a84
 
ac3a84
 EFI_STATUS file_read(EFI_FILE *dir, const char16_t *name, UINTN off, UINTN size, char **ret, UINTN *ret_size) {
ac3a84
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
ac3a84
index d78feac39c..e4ab8138c4 100644
ac3a84
--- a/src/boot/efi/util.h
ac3a84
+++ b/src/boot/efi/util.h
ac3a84
@@ -112,7 +112,8 @@ EFI_STATUS efivar_get_uint32_le(const EFI_GUID *vendor, const char16_t *name, ui
ac3a84
 EFI_STATUS efivar_get_uint64_le(const EFI_GUID *vendor, const char16_t *name, uint64_t *ret);
ac3a84
 EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const char16_t *name, bool *ret);
ac3a84
 
ac3a84
-char16_t *xstra_to_path(const char *stra);
ac3a84
+void convert_efi_path(char16_t *path);
ac3a84
+char16_t *xstr8_to_path(const char *stra);
ac3a84
 
ac3a84
 EFI_STATUS file_read(EFI_FILE *dir, const char16_t *name, UINTN off, UINTN size, char **content, UINTN *content_size);
ac3a84