1 /* SPDX-License-Identifier: GPL-2.0-only */
6 #include <tests/test.h>
9 #include <commonlib/region.h>
11 #include <tests/lib/fmap/fmap_data.h>
12 #include <tests/lib/fmap/fmap_config.h>
14 static struct mem_region_device mem_rdev_rw
;
15 static struct mem_region_device mem_rdev_ro
;
16 static char *flash_buffer
= NULL
;
17 static size_t flash_buffer_size
= 0;
19 static void prepare_flash_buffer(void)
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
;
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');
29 /* Copy FMAP section into buffer */
30 memcpy(flash_buffer
+ FMAP_SECTION_FMAP_START
, tests_fmap_bin
, FMAP_SIZE
);
32 /* Fill rest of buffer with dummy data */
33 for (int i
= FMAP_SECTION_FMAP_START
+ FMAP_SECTION_FMAP_SIZE
;
34 i
< FMAP_SECTION_FLASH_SIZE
; ++i
)
35 flash_buffer
[i
] = 'a' + i
% ('z' - 'a');
38 static int setup_fmap(void **state
)
40 prepare_flash_buffer();
42 mem_rdev_rw
= (struct mem_region_device
)
43 MEM_REGION_DEV_RW_INIT(flash_buffer
, FMAP_SECTION_FLASH_SIZE
);
45 mem_rdev_ro
= (struct mem_region_device
)
46 MEM_REGION_DEV_RO_INIT(flash_buffer
, FMAP_SECTION_FLASH_SIZE
);
51 static int teardown_fmap(void **state
)
53 struct mem_region_device empty
= {
70 flash_buffer_size
= 0;
75 void boot_device_init(void)
77 /* Setup in unit test setup function */
80 const struct region_device
*boot_device_ro(void)
82 return &mem_rdev_rw
.rdev
;
85 const struct region_device
*boot_device_rw(void)
87 return &mem_rdev_rw
.rdev
;
90 static void test_fmap_locate_area_as_rdev(void **state
)
92 const char buffer
[] = "abcdefghijk0123456789";
93 struct region_device rdev
;
95 assert_int_not_equal(-1, fmap_locate_area_as_rdev("RO_VPD", &rdev
));
96 assert_int_equal(FMAP_SECTION_RO_VPD_START
, region_device_offset(&rdev
));
97 assert_int_equal(FMAP_SECTION_RO_VPD_SIZE
, region_device_sz(&rdev
));
99 /* Check if locating area second time works */
100 assert_int_not_equal(-1, fmap_locate_area_as_rdev("RO_VPD", &rdev
));
101 assert_int_equal(FMAP_SECTION_RO_VPD_START
, region_device_offset(&rdev
));
102 assert_int_equal(FMAP_SECTION_RO_VPD_SIZE
, region_device_sz(&rdev
));
104 assert_int_not_equal(-1, fmap_locate_area_as_rdev("RECOVERY_MRC_CACHE", &rdev
));
105 assert_int_equal(FMAP_SECTION_RECOVERY_MRC_CACHE_START
, region_device_offset(&rdev
));
106 assert_int_equal(FMAP_SECTION_RECOVERY_MRC_CACHE_SIZE
, region_device_sz(&rdev
));
108 /* Expect error when writing to read-only area */
109 assert_int_equal(-1, rdev_writeat(&rdev
, buffer
,
110 region_device_offset(&rdev
), sizeof(buffer
)));
112 /* Expect error when looking for incorrect area */
113 assert_int_equal(-1, fmap_locate_area_as_rdev("NONEXISTENT_AREA", &rdev
));
114 assert_int_equal(-1, fmap_locate_area_as_rdev("", &rdev
));
115 assert_int_equal(-1, fmap_locate_area_as_rdev(NULL
, &rdev
));
117 /* Function fmap_locate_area_as_rdev is not tested with NULL
118 as region_device pointer as it is not allowed. */
121 static void test_fmap_locate_area_as_rdev_rw(void **state
)
123 struct region_device rdev
;
124 size_t ro_rw_section_size
= FMAP_SECTION_MISC_RW_SIZE
;
125 char *buffer1
= malloc(ro_rw_section_size
);
126 char *buffer2
= malloc(ro_rw_section_size
);
127 char *dummy_data
= malloc(ro_rw_section_size
);
129 /* Fill buffer with dummy data */
130 for (int i
= 0; i
< ro_rw_section_size
; ++i
)
131 dummy_data
[i
] = '0' + i
% ('9' - '0');
133 assert_int_not_equal(-1, fmap_locate_area_as_rdev_rw("RW_SECTION_A", &rdev
));
134 assert_int_equal(FMAP_SECTION_RW_SECTION_A_START
, region_device_offset(&rdev
));
135 assert_int_equal(FMAP_SECTION_RW_SECTION_A_SIZE
, region_device_sz(&rdev
));
137 /* Check if locating area second time works */
138 assert_int_not_equal(-1, fmap_locate_area_as_rdev_rw("RW_SECTION_A", &rdev
));
139 assert_int_equal(FMAP_SECTION_RW_SECTION_A_START
, region_device_offset(&rdev
));
140 assert_int_equal(FMAP_SECTION_RW_SECTION_A_SIZE
, region_device_sz(&rdev
));
142 assert_int_not_equal(-1, fmap_locate_area_as_rdev_rw("MISC_RW", &rdev
));
143 assert_int_equal(FMAP_SECTION_MISC_RW_START
, region_device_offset(&rdev
));
144 assert_int_equal(FMAP_SECTION_MISC_RW_SIZE
, region_device_sz(&rdev
));
147 /* Expect error when looking for incorrect area */
148 assert_int_equal(-1, fmap_locate_area_as_rdev_rw("NONEXISTENT_AREA", &rdev
));
149 assert_int_equal(-1, fmap_locate_area_as_rdev_rw("", &rdev
));
151 /* Expect error when passing invalid references */
152 assert_int_equal(-1, fmap_locate_area_as_rdev_rw(NULL
, &rdev
));
154 /* Function fmap_locate_area_as_rdev_rw is not tested with NULL
155 as region_device pointer as it is not allowed. */
157 /* Test if returned section region device is writable */
158 assert_int_not_equal(-1, fmap_locate_area_as_rdev_rw("MISC_RW", &rdev
));
159 assert_int_equal(ro_rw_section_size
,
160 rdev_readat(&rdev
, buffer1
, 0, ro_rw_section_size
));
161 assert_int_equal(ro_rw_section_size
,
162 rdev_writeat(&rdev
, dummy_data
, 0, ro_rw_section_size
));
163 /* Check if written data is visible and correct after locating area as RO */
164 assert_int_not_equal(-1, fmap_locate_area_as_rdev("MISC_RW", &rdev
));
165 assert_int_equal(ro_rw_section_size
,
166 rdev_readat(&rdev
, buffer2
, 0, ro_rw_section_size
));
167 assert_memory_not_equal(buffer1
, buffer2
, ro_rw_section_size
);
168 assert_memory_equal(dummy_data
, buffer2
, ro_rw_section_size
);
175 static void test_fmap_locate_area(void **state
)
179 /* Try to locate named area */
180 assert_int_not_equal(-1, fmap_locate_area("COREBOOT", &ar
));
181 assert_int_equal(FMAP_SECTION_COREBOOT_START
, region_offset(&ar
));
182 assert_int_equal(FMAP_SECTION_COREBOOT_SIZE
, region_sz(&ar
));
184 /* Check if locating area second time works */
185 assert_int_not_equal(-1, fmap_locate_area("COREBOOT", &ar
));
186 assert_int_equal(FMAP_SECTION_COREBOOT_START
, region_offset(&ar
));
187 assert_int_equal(FMAP_SECTION_COREBOOT_SIZE
, region_sz(&ar
));
189 /* Look for another area */
190 assert_int_not_equal(-1, fmap_locate_area("GBB", &ar
));
191 assert_int_equal(FMAP_SECTION_GBB_START
, region_offset(&ar
));
192 assert_int_equal(FMAP_SECTION_GBB_SIZE
, region_sz(&ar
));
194 /* Expect error when looking for incorrect area */
195 assert_int_equal(-1, fmap_locate_area("NONEXISTENT_AREA", &ar
));
196 assert_int_equal(-1, fmap_locate_area("", &ar
));
197 assert_int_equal(-1, fmap_locate_area(NULL
, &ar
));
199 /* Expect error when passing invalid region pointer */
200 assert_int_equal(-1, fmap_locate_area("SHARED_DATA", NULL
));
203 static void test_fmap_find_region_name(void **state
)
207 char found_area_name
[FMAP_STRLEN
] = "";
208 const char *area_name
= "RW_PRESERVE";
210 /* Find area by name */
211 assert_int_not_equal(-1, fmap_locate_area(area_name
, &ar
));
213 /* Find name of previously located region */
214 assert_int_not_equal(-1, fmap_find_region_name(&ar
, found_area_name
));
215 assert_string_equal(area_name
, found_area_name
);
217 /* Expect error when passing invalid buffer */
218 assert_int_equal(-1, fmap_find_region_name(&ar
, NULL
));
220 /* Expect error when passing invalid region pointer */
221 assert_int_equal(-1, fmap_find_region_name(NULL
, found_area_name
));
223 /* Try to find area outside of flash region */
224 ar
.offset
= FMAP_SECTION_FLASH_START
+ FMAP_SECTION_FLASH_SIZE
+ 0x100;
226 assert_int_equal(-1, fmap_find_region_name(&ar
, found_area_name
));
228 /* Try to find area with correct offset and incorrect size */
229 ar
.offset
= FMAP_SECTION_COREBOOT_START
;
230 ar
.size
= FMAP_SECTION_COREBOOT_SIZE
/ 4;
231 assert_int_equal(-1, fmap_find_region_name(&ar
, found_area_name
));
233 /* Try to find area with correct size and incorrect offset */
234 ar
.offset
= FMAP_SECTION_GBB_START
- 0x100;
235 ar
.size
= FMAP_SECTION_GBB_START
;
236 assert_int_equal(-1, fmap_find_region_name(&ar
, found_area_name
));
238 /* Try to find area with correct offset overlapping with another area */
239 ar
.offset
= FMAP_SECTION_MISC_RW_START
;
240 ar
.size
= FMAP_SECTION_MISC_RW_START
+ 0x1000;
241 assert_int_equal(-1, fmap_find_region_name(&ar
, found_area_name
));
244 static void test_fmap_read_area(void **state
)
246 const unsigned int section_size
= FMAP_SECTION_RW_SECTION_A_SIZE
;
247 const unsigned int section_start
= FMAP_SECTION_RW_SECTION_A_START
;
248 char *buffer
= malloc(section_size
);
250 /* Find and read area data. Compare with memory device simulating flash. */
251 assert_int_equal(section_size
, fmap_read_area("RW_SECTION_A", buffer
, section_size
));
252 assert_memory_equal(flash_buffer
+ section_start
, buffer
, section_size
);
254 /* Expect error when reading incorrect area */
255 assert_int_equal(-1, fmap_read_area("NONEXISTENT_SECTION", buffer
, section_size
));
256 assert_int_equal(-1, fmap_read_area("", buffer
, section_size
));
257 assert_int_equal(-1, fmap_read_area(NULL
, buffer
, section_size
));
259 /* Function fmap_read_area is not tested with NULL
260 as output buffer pointer as it is not allowed. */
265 static void test_fmap_overwrite_area(void **state
)
267 const char *section_name
= "FW_MAIN_A";
268 const unsigned int section_size
= FMAP_SECTION_FW_MAIN_A_SIZE
;
269 char *buffer1
= malloc(section_size
);
270 char *buffer2
= malloc(section_size
);
271 char *new_data
= malloc(section_size
/ 2);
272 char *zero_buffer
= malloc(section_size
/ 2);
273 memset(zero_buffer
, 0, section_size
/ 2);
274 memset(new_data
, 0x42, section_size
/ 2);
276 /* Save buffer for future comparisons */
277 assert_int_equal(section_size
, fmap_read_area(section_name
, buffer1
, section_size
));
279 /* Overwrite part of section. */
280 assert_int_equal(section_size
/ 2,
281 fmap_overwrite_area(section_name
, new_data
, section_size
/ 2));
283 /* Read and check if memory has changed as expected */
284 assert_int_equal(section_size
, fmap_read_area(section_name
, buffer2
, section_size
));
285 assert_memory_not_equal(buffer1
, buffer2
, section_size
);
286 /* Check if requested section area was overwritten properly */
287 assert_memory_equal(buffer2
, new_data
, section_size
/ 2);
288 /* Check if rest of section was zero-filled */
289 assert_memory_equal(buffer2
+ (section_size
/ 2), zero_buffer
, section_size
/ 2);
291 /* Expect error when overwriting incorrect section */
292 assert_int_equal(-1, fmap_overwrite_area("NONEXISTENT_SECTION",
293 new_data
, section_size
/ 2));
294 assert_int_equal(-1, fmap_overwrite_area(NULL
, new_data
, section_size
/ 2));
296 /* Function fmap_overwrite_area is not tested with NULL
297 as input buffer pointer as it is not allowed. */
307 const struct CMUnitTest tests
[] = {
308 cmocka_unit_test_setup_teardown(test_fmap_locate_area_as_rdev
,
309 setup_fmap
, teardown_fmap
),
310 cmocka_unit_test_setup_teardown(test_fmap_locate_area_as_rdev_rw
,
311 setup_fmap
, teardown_fmap
),
312 cmocka_unit_test_setup_teardown(test_fmap_locate_area
,
313 setup_fmap
, teardown_fmap
),
314 cmocka_unit_test_setup_teardown(test_fmap_find_region_name
,
315 setup_fmap
, teardown_fmap
),
316 cmocka_unit_test_setup_teardown(test_fmap_read_area
,
317 setup_fmap
, teardown_fmap
),
318 cmocka_unit_test_setup_teardown(test_fmap_overwrite_area
,
319 setup_fmap
, teardown_fmap
),
322 return cmocka_run_group_tests(tests
, NULL
, NULL
);