As per armv7 arch spec, for A-profile CPU if translation is disabled, then the default memory type is Device(-nGnRnE) instead of Normal, which requires that alignment be enforced.
This means in some cases we can't perform unaligned access even after allow_unaligned is called. We do have many platforms that didn't have translation enabled in U-Boot, and QEMU started to enforce this since 9.0. Fix by using unaligned access helper for UTF-16 memory read/write to ensure we don't do any unaligned access in U-Boot. Signed-off-by: Jiaxun Yang <jiaxun.y...@flygoat.com> --- lib/charset.c | 21 ++++++++++++--------- lib/efi_loader/efi_device_path.c | 11 ++--------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/lib/charset.c b/lib/charset.c index 182c92a50c48..af5f3ad16d9b 100644 --- a/lib/charset.c +++ b/lib/charset.c @@ -11,6 +11,7 @@ #include <efi_loader.h> #include <errno.h> #include <malloc.h> +#include <asm/unaligned.h> /** * codepage_437 - Unicode to codepage 437 translation table @@ -215,7 +216,7 @@ s32 utf16_get(const u16 **src) return -1; if (!**src) return 0; - code = **src; + code = get_unaligned_le16(*src); ++*src; if (code >= 0xDC00 && code <= 0xDFFF) return -1; @@ -242,12 +243,12 @@ int utf16_put(s32 code, u16 **dst) if ((code >= 0xD800 && code <= 0xDFFF) || code >= 0x110000) return -1; if (code < 0x10000) { - **dst = code; + put_unaligned_le16(code, *dst); } else { code -= 0x10000; - **dst = code >> 10 | 0xD800; + put_unaligned_le16(code >> 10 | 0xD800, *dst); ++*dst; - **dst = (code & 0x3ff) | 0xDC00; + put_unaligned_le16((code & 0x3ff) | 0xDC00, *dst); } ++*dst; return 0; @@ -392,7 +393,7 @@ int __efi_runtime u16_strncmp(const u16 *s1, const u16 *s2, size_t n) int ret = 0; for (; n; --n, ++s1, ++s2) { - ret = *s1 - *s2; + ret = get_unaligned_le16(s1) - get_unaligned_le16(s2); if (ret || !*s1) break; } @@ -403,7 +404,7 @@ int __efi_runtime u16_strncmp(const u16 *s1, const u16 *s2, size_t n) size_t __efi_runtime u16_strnlen(const u16 *in, size_t count) { size_t i; - for (i = 0; count-- && in[i]; i++); + for (i = 0; count-- && get_unaligned_le16(in + i); i++); return i; } @@ -417,8 +418,10 @@ u16 *u16_strcpy(u16 *dest, const u16 *src) u16 *tmp = dest; for (;; dest++, src++) { - *dest = *src; - if (!*src) + u16 code = get_unaligned_le16(src); + + put_unaligned_le16(code, dest); + if (!code) break; } @@ -463,7 +466,7 @@ uint8_t *utf16_to_utf8(uint8_t *dest, const uint16_t *src, size_t size) uint32_t code_high = 0; while (size--) { - uint32_t code = *src++; + uint32_t code = get_unaligned_le16(src++); if (code_high) { if (code >= 0xDC00 && code <= 0xDFFF) { diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 0f684590f22a..97a3200574a1 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -18,7 +18,7 @@ #include <efi_loader.h> #include <part.h> #include <uuid.h> -#include <asm-generic/unaligned.h> +#include <asm/unaligned.h> #include <linux/compat.h> /* U16_MAX */ /* template END node: */ @@ -873,13 +873,6 @@ static void path_to_uefi(void *uefi, const char *src) { 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); @@ -889,7 +882,7 @@ static void path_to_uefi(void *uefi, const char *src) code = '\\'; utf16_put(code, &pos); } - *pos = 0; + put_unaligned_le16(0, pos); } /** -- 2.45.2