|
@@ -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,
|
|
|
+};
|