xref: /aosp_15_r20/external/coreboot/tests/lib/stack-test.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <tests/test.h>
4 #include <lib.h>
5 #include <symbols.h>
6 
7 
8 #if CONFIG_STACK_SIZE == 0
9 #define STACK_SIZE 0x1000
10 #else
11 #define STACK_SIZE CONFIG_STACK_SIZE
12 #endif
13 
14 /* Value used for stack initialization. Change if implementation changes. */
15 #define STACK_GUARD_VALUE 0xDEADBEEF
16 
17 __weak extern u8 _stack[];
18 __weak extern u8 _estack[];
19 TEST_REGION(stack, STACK_SIZE);
20 
21 
fill_stack(u32 value)22 static void fill_stack(u32 value)
23 {
24 	u32 *stack = (u32 *)_stack;
25 	for (size_t i = 0; i < STACK_SIZE / sizeof(u32); ++i)
26 		stack[i] = value;
27 }
28 
29 /* Fill stack region with guard value.  */
clean_stack(void)30 static void clean_stack(void)
31 {
32 	fill_stack(STACK_GUARD_VALUE);
33 }
34 
setup_stack_test(void ** state)35 static int setup_stack_test(void **state)
36 {
37 	void *top_of_stack = _stack + sizeof(_stack);
38 
39 	clean_stack();
40 	*state = top_of_stack;
41 
42 	return 0;
43 }
44 
test_empty_stack(void ** state)45 static void test_empty_stack(void **state)
46 {
47 	void *top_of_stack = *state;
48 
49 	/* Expect success when checking empty stack. */
50 	assert_int_equal(0, checkstack(top_of_stack, 0));
51 }
52 
test_almost_full_stack(void ** state)53 static void test_almost_full_stack(void **state)
54 {
55 	void *top_of_stack = *state;
56 	u32 *stack = (u32 *)_stack;
57 
58 	/* Fill stack with random value except last word */
59 	for (size_t i = 1; i < STACK_SIZE / sizeof(u32); ++i)
60 		stack[i] = 0xAA11FF44;
61 
62 	/* Expect success when checking almost-full stack,
63 	   because last guard value is present */
64 	assert_int_equal(0, checkstack(top_of_stack, 0));
65 }
66 
test_full_stack(void ** state)67 static void test_full_stack(void **state)
68 {
69 	void *top_of_stack = *state;
70 
71 	/* Fill stack with value different than stack guard */
72 	fill_stack(0x600DB015);
73 
74 	/* Expect failure when checking full stack as absence of guard value at the end of
75 	   the stack indicates stack overrun. */
76 	expect_assert_failure(checkstack(top_of_stack, 0));
77 }
78 
test_partialy_filled_stack(void ** state)79 static void test_partialy_filled_stack(void **state)
80 {
81 	void *top_of_stack = *state;
82 	u32 *stack = (u32 *)_stack;
83 	size_t i = STACK_SIZE / sizeof(u32) / 2;
84 
85 	for (; i < STACK_SIZE / sizeof(u32); ++i)
86 		stack[i] = 0x4321ABDC + i;
87 
88 	/* Expect success when checking partially-filled stack,
89 	   because only part of stack is filled with non-guard value. */
90 	assert_int_equal(0, checkstack(top_of_stack, 0));
91 }
92 
test_alternately_filled_stack(void ** state)93 static void test_alternately_filled_stack(void **state)
94 {
95 	void *top_of_stack = *state;
96 	u32 *stack = (u32 *)_stack;
97 	size_t i;
98 
99 	for (i = 0; i < STACK_SIZE / sizeof(u32); i += 2)
100 		stack[i] = STACK_GUARD_VALUE;
101 
102 	for (i = 1; i < STACK_SIZE / sizeof(u32); i += 2)
103 		stack[i] = 0x42420707;
104 
105 	assert_int_equal(0, checkstack(top_of_stack, 0));
106 }
107 
test_incorrectly_initialized_stack(void ** state)108 static void test_incorrectly_initialized_stack(void **state)
109 {
110 	void *top_of_stack = *state;
111 	u32 *stack = (u32 *)_stack;
112 
113 	/* Remove last stack guard value */
114 	stack[0] = 0xFF00FF11;
115 
116 	/* Expect failure when there is no last stack guard value even if no other value was
117 	   changed. */
118 	expect_assert_failure(checkstack(top_of_stack, 0));
119 }
120 
main(void)121 int main(void)
122 {
123 	const struct CMUnitTest tests[] = {
124 		cmocka_unit_test_setup(test_empty_stack, setup_stack_test),
125 		cmocka_unit_test_setup(test_almost_full_stack, setup_stack_test),
126 		cmocka_unit_test_setup(test_full_stack, setup_stack_test),
127 		cmocka_unit_test_setup(test_partialy_filled_stack, setup_stack_test),
128 		cmocka_unit_test_setup(test_alternately_filled_stack, setup_stack_test),
129 		cmocka_unit_test_setup(test_incorrectly_initialized_stack, setup_stack_test),
130 	};
131 
132 	return cb_run_group_tests(tests, NULL, NULL);
133 }
134