1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <tests/test.h>
4 #include <cbmem.h>
5 #include <commonlib/bsd/cbmem_id.h>
6 #include <stage_cache.h>
7
8 #define CBMEM_SIZE (32 * KiB)
9
10 /* CBMEM top pointer used by implementation. */
11 extern uintptr_t _cbmem_top_ptr;
12
cbmem_run_init_hooks(int is_recovery)13 void cbmem_run_init_hooks(int is_recovery)
14 {
15 }
16
get_cbmem_ptr(void)17 static void *get_cbmem_ptr(void)
18 {
19 void *cbmem_top_ptr = (void *)_cbmem_top_ptr;
20 if (cbmem_top_ptr)
21 return cbmem_top_ptr - CBMEM_SIZE;
22 else
23 return NULL;
24 }
25
clear_cbmem(void)26 static void clear_cbmem(void)
27 {
28 void *ptr = get_cbmem_ptr();
29 if (ptr)
30 memset(ptr, 0, CBMEM_SIZE);
31 }
32
setup_test(void ** state)33 int setup_test(void **state)
34 {
35 void *cbmem_top_ptr = malloc(CBMEM_SIZE);
36
37 if (!cbmem_top_ptr)
38 return -1;
39
40 _cbmem_top_ptr = (uintptr_t)cbmem_top_ptr + CBMEM_SIZE;
41 clear_cbmem();
42 cbmem_initialize_empty();
43 return 0;
44 }
45
teardown_test(void ** state)46 int teardown_test(void **state)
47 {
48 if (_cbmem_top_ptr && (_cbmem_top_ptr - CBMEM_SIZE))
49 free((void *)(_cbmem_top_ptr - CBMEM_SIZE));
50
51 _cbmem_top_ptr = 0;
52 return 0;
53 }
54
55 /* This function is used as prog_entry of struct prog to prevent potential calls to unaccessible
56 or incorrect addresses. */
prog_entry_mock(void * arg)57 void prog_entry_mock(void *arg)
58 {
59 }
60
61 /* This test checks if stage_cache_add() correctly adds CBMEM_ID_STAGE_x_META
62 and CBMEM_ID_STAGEx_CACHE entries to cbmem. stage_cache_add() must create meta
63 entry containing load address, entry address and argument for it. It also must
64 copy buffer pointer pointed by start pointer of prog struct to cache entry. */
test_stage_cache_add(void ** state)65 void test_stage_cache_add(void **state)
66 {
67 const int id = 12;
68 int arg = 0xC14;
69 struct stage_cache *meta = NULL;
70 uint8_t *prog_data_buf = NULL;
71 const size_t data_sz = 4 * KiB;
72 uint8_t *data = malloc(data_sz);
73 struct prog prog_data = {0};
74
75 assert_non_null(data);
76 memset(data, 0xDB, data_sz);
77 prog_data = (struct prog)PROG_INIT(PROG_ROMSTAGE, "test_prog");
78 prog_set_area(&prog_data, data, data_sz);
79 prog_set_entry(&prog_data, prog_entry_mock, &arg);
80
81 stage_cache_add(id, &prog_data);
82
83 meta = cbmem_find(CBMEM_ID_STAGEx_META + id);
84 assert_non_null(meta);
85 assert_int_equal(meta->load_addr, (uintptr_t)prog_start(&prog_data));
86 assert_int_equal(meta->entry_addr, (uintptr_t)prog_entry(&prog_data));
87 assert_int_equal(meta->arg, (uintptr_t)prog_entry_arg(&prog_data));
88
89 prog_data_buf = cbmem_find(CBMEM_ID_STAGEx_CACHE + id);
90 assert_non_null(prog_data_buf);
91 assert_memory_equal(data, prog_data_buf, data_sz);
92
93 free(data);
94 }
95
96 /* This test checks if stage_cache_add_raw() correctly creates entry with data from
97 provided buffer. Data should be accessible using cbmem_find() with
98 (CBMEM_ID_STAGEx_RAW + id) parameter. */
test_stage_cache_add_raw(void ** state)99 void test_stage_cache_add_raw(void **state)
100 {
101 const int id = 55;
102 const size_t data_sz = 8 * KiB;
103 uint8_t *data = malloc(data_sz);
104 uint8_t *data_raw = NULL;
105
106 assert_non_null(data);
107 memset(data, 0x91, data_sz);
108
109 stage_cache_add_raw(id, data, data_sz);
110
111 data_raw = cbmem_find(CBMEM_ID_STAGEx_RAW + id);
112 assert_non_null(data_raw);
113 assert_memory_equal(data_raw, data, data_sz);
114
115 free(data);
116 }
117
118
119 /* This test checks if stage_cache_get_raw() correctly extracts base and size of previously
120 added entry. */
test_stage_cache_get_raw(void ** state)121 void test_stage_cache_get_raw(void **state)
122 {
123 const int id = 23;
124 const size_t data_sz = 3 * KiB;
125 uint8_t *data = malloc(data_sz);
126 size_t data_out_sz = 0;
127 uint8_t *data_out = NULL;
128
129 assert_non_null(data);
130 memset(data, 0x3c, data_sz);
131 stage_cache_add_raw(id, data, data_sz);
132
133 stage_cache_get_raw(id, (void **)&data_out, &data_out_sz);
134
135 assert_int_equal(data_sz, data_out_sz);
136 assert_memory_equal(data, data_out, data_sz);
137
138 free(data);
139 }
140
141 /* This test checks if stage_cache_load_stage() correctly loads previously added stage data
142 and its metadata. */
test_stage_cache_load_stage(void ** state)143 void test_stage_cache_load_stage(void **state)
144 {
145 int id = 0xCC;
146 struct prog prog_out = {0};
147 const size_t data_sz = 7 * KiB;
148 uint8_t *data = malloc(data_sz);
149 uint8_t *data_bak = malloc(data_sz);
150 struct prog prog_data = {0};
151 int arg = 0x33224455;
152
153 assert_non_null(data);
154 assert_non_null(data_bak);
155 memset(data, 0x45, data_sz);
156
157 prog_data = (struct prog)PROG_INIT(PROG_RAMSTAGE, "test_prog");
158 prog_set_area(&prog_data, data, data_sz);
159 prog_set_entry(&prog_data, prog_entry_mock, &arg);
160 stage_cache_add(id, &prog_data);
161
162 /* Copy current data to backup buffer and clear current buffer */
163 memcpy(data_bak, data, data_sz);
164 memset(data, 0, data_sz);
165
166 /* Load stage data. Data should be returned to the same buffer. */
167 stage_cache_load_stage(id, &prog_out);
168
169 /* Data should be same as it was before */
170 assert_memory_equal(data, data_bak, data_sz);
171 assert_int_equal(prog_start(&prog_data), prog_start(&prog_out));
172 assert_int_equal(prog_size(&prog_data), prog_size(&prog_out));
173 assert_ptr_equal(prog_entry(&prog_data), prog_entry(&prog_out));
174 assert_ptr_equal(prog_entry_arg(&prog_data), prog_entry_arg(&prog_out));
175
176 free(data_bak);
177 free(data);
178 }
179
main(void)180 int main(void)
181 {
182 const struct CMUnitTest tests[] = {
183 cmocka_unit_test_setup_teardown(test_stage_cache_add, setup_test,
184 teardown_test),
185 cmocka_unit_test_setup_teardown(test_stage_cache_add_raw, setup_test,
186 teardown_test),
187 cmocka_unit_test_setup_teardown(test_stage_cache_get_raw, setup_test,
188 teardown_test),
189 cmocka_unit_test_setup_teardown(test_stage_cache_load_stage, setup_test,
190 teardown_test),
191 };
192
193 return cb_run_group_tests(tests, NULL, NULL);
194 }
195