efi_selftest: test unaligned memory access

According to the UEFI spec unaligned memory access should be enabled on
CPUs supporting it.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 2b943bc..4fe404d 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -31,6 +31,10 @@
 efi_selftest_variables.o \
 efi_selftest_watchdog.o
 
+ifeq ($(CONFIG_CMD_BOOTEFI_SELFTEST),y)
+obj-$(CONFIG_CPU_V7) += efi_selftest_unaligned.o
+endif
+
 ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy)
 obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest_block_device.o
 endif
diff --git a/lib/efi_selftest/efi_selftest_unaligned.c b/lib/efi_selftest/efi_selftest_unaligned.c
new file mode 100644
index 0000000..f799c6d
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_unaligned.c
@@ -0,0 +1,67 @@
+/*
+ * efi_selftest_unaligned
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * Test unaligned memory access on ARMv7.
+ */
+
+#include <efi_selftest.h>
+
+struct aligned_buffer {
+	char a[8] __aligned(8);
+};
+
+/*
+ * Return an u32 at a give address.
+ * If the address is not four byte aligned, an unaligned memory access
+ * occurs.
+ *
+ * @addr:	address to read
+ * @return:	value at the address
+ */
+static inline u32 deref(u32 *addr)
+{
+	int ret;
+
+	asm(
+		"ldr %[out], [%[in]]\n\t"
+		: [out] "=r" (ret)
+		: [in] "r" (addr)
+	);
+	return ret;
+}
+
+/*
+ * Execute unit test.
+ * An unaligned memory access is executed. The result is checked.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+	struct aligned_buffer buf = {
+		{0, 1, 2, 3, 4, 5, 6, 7},
+		};
+	void *v = &buf;
+	u32 r = 0;
+
+	/* Read an unaligned address */
+	r = deref(v + 1);
+
+	/* UEFI only supports low endian systems */
+	if (r != 0x04030201) {
+		efi_st_error("Unaligned access failed");
+		return EFI_ST_FAILURE;
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(unaligned) = {
+	.name = "unaligned memory access",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.execute = execute,
+};