efi_loader: eliminate inline function ascii2unicode()
[oweals/u-boot.git] / lib / efi_loader / efi_device_path.c
index d8c052d6ec50f743642ac375513ca821a499fa30..ea39f13b735cc52828c06fd2bfaf8300c3714a0d 100644 (file)
@@ -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 = {
@@ -335,6 +336,9 @@ struct efi_device_path *efi_dp_create_device_node(const u8 type,
 {
        struct efi_device_path *ret;
 
+       if (length < sizeof(struct efi_device_path))
+               return NULL;
+
        ret = dp_alloc(length);
        if (!ret)
                return ret;
@@ -661,7 +665,7 @@ static void *dp_part_node(void *buf, struct blk_desc *desc, int part)
                cddp->dp.sub_type = DEVICE_PATH_SUB_TYPE_CDROM_PATH;
                cddp->dp.length = sizeof(*cddp);
                cddp->partition_start = info.start;
-               cddp->partition_end = info.size;
+               cddp->partition_size = info.size;
 
                buf = &cddp[1];
        } else {
@@ -790,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;
 }
 
 /*
@@ -816,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));
@@ -917,14 +942,14 @@ struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
  *
  * @full_path:         device path including device and file path
  * @device_path:       path of the device
- * @file_path:         relative path of the file
+ * @file_path:         relative path of the file or NULL if there is none
  * Return:             status code
  */
 efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
                                    struct efi_device_path **device_path,
                                    struct efi_device_path **file_path)
 {
-       struct efi_device_path *p, *dp, *fp;
+       struct efi_device_path *p, *dp, *fp = NULL;
 
        *device_path = NULL;
        *file_path = NULL;
@@ -935,7 +960,7 @@ efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
        while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
                p = efi_dp_next(p);
                if (!p)
-                       return EFI_INVALID_PARAMETER;
+                       goto out;
        }
        fp = efi_dp_dup(p);
        if (!fp)
@@ -944,6 +969,7 @@ efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
        p->sub_type = DEVICE_PATH_SUB_TYPE_END;
        p->length = sizeof(*p);
 
+out:
        *device_path = dp;
        *file_path = fp;
        return EFI_SUCCESS;