xref: /aosp_15_r20/external/coreboot/tests/lib/cbmem_stage_cache-test.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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