blob: 1cc8246b4be3e0b49fc3acf5b58458f688e570da [file] [log] [blame]
Jakub Czapigadd85c822020-12-10 11:16:47 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <stdlib.h>
4#include <string.h>
5
6#include <tests/test.h>
7
8#include <fmap.h>
9#include <commonlib/region.h>
10
11#include <tests/lib/fmap/fmap_data.h>
12#include <tests/lib/fmap/fmap_config.h>
13
Julius Wernerc8931972021-04-16 16:48:32 -070014static struct region_device flash_rdev_rw;
15static struct region_device flash_rdev_ro;
Jakub Czapigadd85c822020-12-10 11:16:47 +010016static char *flash_buffer = NULL;
17static size_t flash_buffer_size = 0;
18
19static void prepare_flash_buffer(void)
20{
21 /* Prepare flash buffer with dummy data and FMAP */
22 flash_buffer = malloc(FMAP_SECTION_FLASH_SIZE);
23 flash_buffer_size = FMAP_SECTION_FLASH_SIZE;
24
25 /* Fill first part of buffer with dummy data */
26 for (int i = 0; i < FMAP_SECTION_FMAP_START; ++i)
27 flash_buffer[i] = 'a' + i % ('z' - 'a');
28
29 /* Copy FMAP section into buffer */
30 memcpy(flash_buffer + FMAP_SECTION_FMAP_START, tests_fmap_bin, FMAP_SIZE);
31
32 /* Fill rest of buffer with dummy data */
33 for (int i = FMAP_SECTION_FMAP_START + FMAP_SECTION_FMAP_SIZE;
Jakub Czapigac08b6a72022-01-10 13:36:47 +000034 i < FMAP_SECTION_FLASH_SIZE; ++i)
Jakub Czapigadd85c822020-12-10 11:16:47 +010035 flash_buffer[i] = 'a' + i % ('z' - 'a');
36}
37
38static int setup_fmap(void **state)
39{
40 prepare_flash_buffer();
Julius Wernerc8931972021-04-16 16:48:32 -070041 rdev_chain_mem_rw(&flash_rdev_rw, flash_buffer, FMAP_SECTION_FLASH_SIZE);
42 rdev_chain_mem(&flash_rdev_ro, flash_buffer, FMAP_SECTION_FLASH_SIZE);
Jakub Czapigadd85c822020-12-10 11:16:47 +010043 return 0;
44}
45
46static int teardown_fmap(void **state)
47{
Julius Wernerc8931972021-04-16 16:48:32 -070048 rdev_chain_mem_rw(&flash_rdev_rw, NULL, 0);
49 rdev_chain_mem(&flash_rdev_ro, NULL, 0);
Jakub Czapigadd85c822020-12-10 11:16:47 +010050
51 free(flash_buffer);
52 flash_buffer = NULL;
53 flash_buffer_size = 0;
54
55 return 0;
56}
57
58void boot_device_init(void)
59{
60 /* Setup in unit test setup function */
61}
62
63const struct region_device *boot_device_ro(void)
64{
Julius Wernerc8931972021-04-16 16:48:32 -070065 return &flash_rdev_ro;
Jakub Czapigadd85c822020-12-10 11:16:47 +010066}
67
68const struct region_device *boot_device_rw(void)
69{
Julius Wernerc8931972021-04-16 16:48:32 -070070 return &flash_rdev_rw;
Jakub Czapigadd85c822020-12-10 11:16:47 +010071}
72
73static void test_fmap_locate_area_as_rdev(void **state)
74{
75 const char buffer[] = "abcdefghijk0123456789";
76 struct region_device rdev;
77
78 assert_int_not_equal(-1, fmap_locate_area_as_rdev("RO_VPD", &rdev));
Julius Wernerc8931972021-04-16 16:48:32 -070079 assert_ptr_equal(flash_buffer + FMAP_SECTION_RO_VPD_START, rdev_mmap_full(&rdev));
Jakub Czapigadd85c822020-12-10 11:16:47 +010080 assert_int_equal(FMAP_SECTION_RO_VPD_SIZE, region_device_sz(&rdev));
81
82 /* Check if locating area second time works */
83 assert_int_not_equal(-1, fmap_locate_area_as_rdev("RO_VPD", &rdev));
Julius Wernerc8931972021-04-16 16:48:32 -070084 assert_ptr_equal(flash_buffer + FMAP_SECTION_RO_VPD_START, rdev_mmap_full(&rdev));
Jakub Czapigadd85c822020-12-10 11:16:47 +010085 assert_int_equal(FMAP_SECTION_RO_VPD_SIZE, region_device_sz(&rdev));
86
87 assert_int_not_equal(-1, fmap_locate_area_as_rdev("RECOVERY_MRC_CACHE", &rdev));
Julius Wernerc8931972021-04-16 16:48:32 -070088 assert_ptr_equal(flash_buffer + FMAP_SECTION_RECOVERY_MRC_CACHE_START,
89 rdev_mmap_full(&rdev));
Jakub Czapigadd85c822020-12-10 11:16:47 +010090 assert_int_equal(FMAP_SECTION_RECOVERY_MRC_CACHE_SIZE, region_device_sz(&rdev));
91
92 /* Expect error when writing to read-only area */
Julius Wernerc8931972021-04-16 16:48:32 -070093 assert_int_equal(-1, rdev_writeat(&rdev, buffer, 0, sizeof(buffer)));
Jakub Czapigadd85c822020-12-10 11:16:47 +010094
95 /* Expect error when looking for incorrect area */
96 assert_int_equal(-1, fmap_locate_area_as_rdev("NONEXISTENT_AREA", &rdev));
97 assert_int_equal(-1, fmap_locate_area_as_rdev("", &rdev));
98 assert_int_equal(-1, fmap_locate_area_as_rdev(NULL, &rdev));
99
100 /* Function fmap_locate_area_as_rdev is not tested with NULL
101 as region_device pointer as it is not allowed. */
102}
103
104static void test_fmap_locate_area_as_rdev_rw(void **state)
105{
106 struct region_device rdev;
107 size_t ro_rw_section_size = FMAP_SECTION_MISC_RW_SIZE;
108 char *buffer1 = malloc(ro_rw_section_size);
109 char *buffer2 = malloc(ro_rw_section_size);
110 char *dummy_data = malloc(ro_rw_section_size);
111
112 /* Fill buffer with dummy data */
113 for (int i = 0; i < ro_rw_section_size; ++i)
114 dummy_data[i] = '0' + i % ('9' - '0');
115
116 assert_int_not_equal(-1, fmap_locate_area_as_rdev_rw("RW_SECTION_A", &rdev));
Julius Wernerc8931972021-04-16 16:48:32 -0700117 assert_ptr_equal(flash_buffer + FMAP_SECTION_RW_SECTION_A_START, rdev_mmap_full(&rdev));
Jakub Czapigadd85c822020-12-10 11:16:47 +0100118 assert_int_equal(FMAP_SECTION_RW_SECTION_A_SIZE, region_device_sz(&rdev));
119
120 /* Check if locating area second time works */
121 assert_int_not_equal(-1, fmap_locate_area_as_rdev_rw("RW_SECTION_A", &rdev));
Julius Wernerc8931972021-04-16 16:48:32 -0700122 assert_ptr_equal(flash_buffer + FMAP_SECTION_RW_SECTION_A_START, rdev_mmap_full(&rdev));
Jakub Czapigadd85c822020-12-10 11:16:47 +0100123 assert_int_equal(FMAP_SECTION_RW_SECTION_A_SIZE, region_device_sz(&rdev));
124
125 assert_int_not_equal(-1, fmap_locate_area_as_rdev_rw("MISC_RW", &rdev));
Julius Wernerc8931972021-04-16 16:48:32 -0700126 assert_ptr_equal(flash_buffer + FMAP_SECTION_MISC_RW_START, rdev_mmap_full(&rdev));
Jakub Czapigadd85c822020-12-10 11:16:47 +0100127 assert_int_equal(FMAP_SECTION_MISC_RW_SIZE, region_device_sz(&rdev));
128
129
130 /* Expect error when looking for incorrect area */
131 assert_int_equal(-1, fmap_locate_area_as_rdev_rw("NONEXISTENT_AREA", &rdev));
132 assert_int_equal(-1, fmap_locate_area_as_rdev_rw("", &rdev));
133
134 /* Expect error when passing invalid references */
135 assert_int_equal(-1, fmap_locate_area_as_rdev_rw(NULL, &rdev));
136
137 /* Function fmap_locate_area_as_rdev_rw is not tested with NULL
138 as region_device pointer as it is not allowed. */
139
140 /* Test if returned section region device is writable */
141 assert_int_not_equal(-1, fmap_locate_area_as_rdev_rw("MISC_RW", &rdev));
142 assert_int_equal(ro_rw_section_size,
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000143 rdev_readat(&rdev, buffer1, 0, ro_rw_section_size));
Jakub Czapigadd85c822020-12-10 11:16:47 +0100144 assert_int_equal(ro_rw_section_size,
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000145 rdev_writeat(&rdev, dummy_data, 0, ro_rw_section_size));
Jakub Czapigadd85c822020-12-10 11:16:47 +0100146 /* Check if written data is visible and correct after locating area as RO */
147 assert_int_not_equal(-1, fmap_locate_area_as_rdev("MISC_RW", &rdev));
148 assert_int_equal(ro_rw_section_size,
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000149 rdev_readat(&rdev, buffer2, 0, ro_rw_section_size));
Jakub Czapigadd85c822020-12-10 11:16:47 +0100150 assert_memory_not_equal(buffer1, buffer2, ro_rw_section_size);
151 assert_memory_equal(dummy_data, buffer2, ro_rw_section_size);
152
153 free(buffer1);
154 free(buffer2);
155 free(dummy_data);
156}
157
158static void test_fmap_locate_area(void **state)
159{
160 struct region ar;
161
162 /* Try to locate named area */
163 assert_int_not_equal(-1, fmap_locate_area("COREBOOT", &ar));
164 assert_int_equal(FMAP_SECTION_COREBOOT_START, region_offset(&ar));
165 assert_int_equal(FMAP_SECTION_COREBOOT_SIZE, region_sz(&ar));
166
167 /* Check if locating area second time works */
168 assert_int_not_equal(-1, fmap_locate_area("COREBOOT", &ar));
169 assert_int_equal(FMAP_SECTION_COREBOOT_START, region_offset(&ar));
170 assert_int_equal(FMAP_SECTION_COREBOOT_SIZE, region_sz(&ar));
171
172 /* Look for another area */
173 assert_int_not_equal(-1, fmap_locate_area("GBB", &ar));
174 assert_int_equal(FMAP_SECTION_GBB_START, region_offset(&ar));
175 assert_int_equal(FMAP_SECTION_GBB_SIZE, region_sz(&ar));
176
177 /* Expect error when looking for incorrect area */
178 assert_int_equal(-1, fmap_locate_area("NONEXISTENT_AREA", &ar));
179 assert_int_equal(-1, fmap_locate_area("", &ar));
180 assert_int_equal(-1, fmap_locate_area(NULL, &ar));
181
182 /* Expect error when passing invalid region pointer */
183 assert_int_equal(-1, fmap_locate_area("SHARED_DATA", NULL));
184}
185
186static void test_fmap_find_region_name(void **state)
187{
188 (void)state;
189 struct region ar;
190 char found_area_name[FMAP_STRLEN] = "";
191 const char *area_name = "RW_PRESERVE";
192
193 /* Find area by name */
194 assert_int_not_equal(-1, fmap_locate_area(area_name, &ar));
195
196 /* Find name of previously located region */
197 assert_int_not_equal(-1, fmap_find_region_name(&ar, found_area_name));
198 assert_string_equal(area_name, found_area_name);
199
200 /* Expect error when passing invalid buffer */
201 assert_int_equal(-1, fmap_find_region_name(&ar, NULL));
202
203 /* Expect error when passing invalid region pointer */
204 assert_int_equal(-1, fmap_find_region_name(NULL, found_area_name));
205
206 /* Try to find area outside of flash region */
207 ar.offset = FMAP_SECTION_FLASH_START + FMAP_SECTION_FLASH_SIZE + 0x100;
208 ar.size = 0x1000;
209 assert_int_equal(-1, fmap_find_region_name(&ar, found_area_name));
210
211 /* Try to find area with correct offset and incorrect size */
212 ar.offset = FMAP_SECTION_COREBOOT_START;
213 ar.size = FMAP_SECTION_COREBOOT_SIZE / 4;
214 assert_int_equal(-1, fmap_find_region_name(&ar, found_area_name));
215
216 /* Try to find area with correct size and incorrect offset */
217 ar.offset = FMAP_SECTION_GBB_START - 0x100;
218 ar.size = FMAP_SECTION_GBB_START;
219 assert_int_equal(-1, fmap_find_region_name(&ar, found_area_name));
220
221 /* Try to find area with correct offset overlapping with another area */
222 ar.offset = FMAP_SECTION_MISC_RW_START;
223 ar.size = FMAP_SECTION_MISC_RW_START + 0x1000;
224 assert_int_equal(-1, fmap_find_region_name(&ar, found_area_name));
225}
226
227static void test_fmap_read_area(void **state)
228{
229 const unsigned int section_size = FMAP_SECTION_RW_SECTION_A_SIZE;
230 const unsigned int section_start = FMAP_SECTION_RW_SECTION_A_START;
231 char *buffer = malloc(section_size);
232
233 /* Find and read area data. Compare with memory device simulating flash. */
234 assert_int_equal(section_size, fmap_read_area("RW_SECTION_A", buffer, section_size));
235 assert_memory_equal(flash_buffer + section_start, buffer, section_size);
236
237 /* Expect error when reading incorrect area */
238 assert_int_equal(-1, fmap_read_area("NONEXISTENT_SECTION", buffer, section_size));
239 assert_int_equal(-1, fmap_read_area("", buffer, section_size));
240 assert_int_equal(-1, fmap_read_area(NULL, buffer, section_size));
241
242 /* Function fmap_read_area is not tested with NULL
243 as output buffer pointer as it is not allowed. */
244
245 free(buffer);
246}
247
248static void test_fmap_overwrite_area(void **state)
249{
250 const char *section_name = "FW_MAIN_A";
251 const unsigned int section_size = FMAP_SECTION_FW_MAIN_A_SIZE;
252 char *buffer1 = malloc(section_size);
253 char *buffer2 = malloc(section_size);
254 char *new_data = malloc(section_size / 2);
255 char *zero_buffer = malloc(section_size / 2);
256 memset(zero_buffer, 0, section_size / 2);
257 memset(new_data, 0x42, section_size / 2);
258
259 /* Save buffer for future comparisons */
260 assert_int_equal(section_size, fmap_read_area(section_name, buffer1, section_size));
261
262 /* Overwrite part of section. */
263 assert_int_equal(section_size / 2,
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000264 fmap_overwrite_area(section_name, new_data, section_size / 2));
Jakub Czapigadd85c822020-12-10 11:16:47 +0100265
266 /* Read and check if memory has changed as expected */
267 assert_int_equal(section_size, fmap_read_area(section_name, buffer2, section_size));
268 assert_memory_not_equal(buffer1, buffer2, section_size);
269 /* Check if requested section area was overwritten properly */
270 assert_memory_equal(buffer2, new_data, section_size / 2);
271 /* Check if rest of section was zero-filled */
272 assert_memory_equal(buffer2 + (section_size / 2), zero_buffer, section_size / 2);
273
274 /* Expect error when overwriting incorrect section */
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000275 assert_int_equal(
276 -1, fmap_overwrite_area("NONEXISTENT_SECTION", new_data, section_size / 2));
Jakub Czapigadd85c822020-12-10 11:16:47 +0100277 assert_int_equal(-1, fmap_overwrite_area(NULL, new_data, section_size / 2));
278
279 /* Function fmap_overwrite_area is not tested with NULL
280 as input buffer pointer as it is not allowed. */
281
282 free(buffer1);
283 free(buffer2);
284 free(new_data);
285 free(zero_buffer);
286}
287
288int main(void)
289{
290 const struct CMUnitTest tests[] = {
Jakub Czapigac08b6a72022-01-10 13:36:47 +0000291 cmocka_unit_test_setup_teardown(test_fmap_locate_area_as_rdev, setup_fmap,
292 teardown_fmap),
293 cmocka_unit_test_setup_teardown(test_fmap_locate_area_as_rdev_rw, setup_fmap,
294 teardown_fmap),
295 cmocka_unit_test_setup_teardown(test_fmap_locate_area, setup_fmap,
296 teardown_fmap),
297 cmocka_unit_test_setup_teardown(test_fmap_find_region_name, setup_fmap,
298 teardown_fmap),
299 cmocka_unit_test_setup_teardown(test_fmap_read_area, setup_fmap, teardown_fmap),
300 cmocka_unit_test_setup_teardown(test_fmap_overwrite_area, setup_fmap,
301 teardown_fmap),
Jakub Czapigadd85c822020-12-10 11:16:47 +0100302 };
303
Jakub Czapiga7c6081e2021-08-25 16:27:35 +0200304 return cb_run_group_tests(tests, NULL, NULL);
Jakub Czapigadd85c822020-12-10 11:16:47 +0100305}