#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 = {
{
struct efi_device_path *ret;
+ if (length < sizeof(struct efi_device_path))
+ return NULL;
+
ret = dp_alloc(length);
if (!ret)
return ret;
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 {
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;
}
/*
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));
*
* @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;
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)
p->sub_type = DEVICE_PATH_SUB_TYPE_END;
p->length = sizeof(*p);
+out:
*device_path = dp;
*file_path = fp;
return EFI_SUCCESS;