1 /*
2  * efi_selftest_unaligned
3  *
4  * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  *
8  * Test unaligned memory access on ARMv7.
9  */
10 
11 #include <efi_selftest.h>
12 
13 struct aligned_buffer {
14 	char a[8] __aligned(8);
15 };
16 
17 /*
18  * Return an u32 at a give address.
19  * If the address is not four byte aligned, an unaligned memory access
20  * occurs.
21  *
22  * @addr:	address to read
23  * @return:	value at the address
24  */
25 static inline u32 deref(u32 *addr)
26 {
27 	int ret;
28 
29 	asm(
30 		"ldr %[out], [%[in]]\n\t"
31 		: [out] "=r" (ret)
32 		: [in] "r" (addr)
33 	);
34 	return ret;
35 }
36 
37 /*
38  * Execute unit test.
39  * An unaligned memory access is executed. The result is checked.
40  *
41  * @return:	EFI_ST_SUCCESS for success
42  */
43 static int execute(void)
44 {
45 	struct aligned_buffer buf = {
46 		{0, 1, 2, 3, 4, 5, 6, 7},
47 		};
48 	void *v = &buf;
49 	u32 r = 0;
50 
51 	/* Read an unaligned address */
52 	r = deref(v + 1);
53 
54 	/* UEFI only supports low endian systems */
55 	if (r != 0x04030201) {
56 		efi_st_error("Unaligned access failed");
57 		return EFI_ST_FAILURE;
58 	}
59 
60 	return EFI_ST_SUCCESS;
61 }
62 
63 EFI_UNIT_TEST(unaligned) = {
64 	.name = "unaligned memory access",
65 	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
66 	.execute = execute,
67 };
68