1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <libpayload-config.h>
6 #include <commonlib/bsd/cb_err.h>
7 #include <commonlib/bsd/cbfs_mdata.h>
9 #include <mocks/cbfs_util.h>
13 #include <tests/test.h>
15 #include "../libcbfs/cbfs.c"
19 unsigned long virtual_offset
= 0;
20 struct sysinfo_t lib_sysinfo
;
22 unsigned long ulzman(const unsigned char *src
, unsigned long srcn
, unsigned char *dst
,
25 assert_true(dstn
!= 0);
28 memcpy(dst
, src
, dstn
);
32 size_t ulz4fn(const void *src
, size_t srcn
, void *dst
, size_t dstn
)
34 assert_non_null(dstn
);
37 memcpy(dst
, src
, dstn
);
41 static size_t test_fmap_offset
= 0;
42 static size_t test_fmap_size
= 0;
43 static enum cb_err test_fmap_result
= CB_SUCCESS
;
45 static void set_fmap_locate_area_results(size_t offset
, size_t size
, size_t result
)
47 test_fmap_offset
= offset
;
48 test_fmap_size
= size
;
49 test_fmap_result
= result
;
52 enum cb_err
fmap_locate_area(const char *name
, size_t *offset
, size_t *size
)
54 *offset
= test_fmap_offset
;
55 *size
= test_fmap_size
;
56 return test_fmap_result
;
59 enum cb_err
cbfs_mcache_lookup(const void *mcache
, size_t mcache_size
, const char *name
,
60 union cbfs_mdata
*mdata_out
, size_t *data_offset_out
)
62 assert_non_null(mcache
);
63 assert_true(mcache_size
> 0 && mcache_size
% CBFS_MCACHE_ALIGNMENT
== 0);
64 assert_non_null(mdata_out
);
65 assert_non_null(data_offset_out
);
69 enum cb_err ret
= mock_type(enum cb_err
);
70 if (ret
!= CB_SUCCESS
)
73 memcpy(mdata_out
, mock_ptr_type(const union cbfs_mdata
*), sizeof(union cbfs_mdata
));
74 *data_offset_out
= mock_type(size_t);
78 static void expect_cbfs_mcache_lookup(const char *name
, enum cb_err err
,
79 const union cbfs_mdata
*mdata
, size_t data_offset_out
)
81 expect_string(cbfs_mcache_lookup
, name
, name
);
82 will_return(cbfs_mcache_lookup
, err
);
84 if (err
== CB_SUCCESS
) {
85 will_return(cbfs_mcache_lookup
, mdata
);
86 will_return(cbfs_mcache_lookup
, data_offset_out
);
90 enum cb_err
cbfs_lookup(cbfs_dev_t dev
, const char *name
, union cbfs_mdata
*mdata_out
,
91 size_t *data_offset_out
, struct vb2_hash
*metadata_hash
)
96 enum cb_err ret
= mock_type(enum cb_err
);
97 if (ret
!= CB_SUCCESS
)
100 memcpy(mdata_out
, mock_ptr_type(const union cbfS_mdata
*), sizeof(union cbfs_mdata
));
101 *data_offset_out
= mock_type(size_t);
105 static void expect_cbfs_lookup(const char *name
, enum cb_err err
, const union cbfs_mdata
*mdata
,
106 size_t data_offset_out
)
108 expect_string(cbfs_lookup
, name
, name
);
109 will_return(cbfs_lookup
, err
);
111 if (err
== CB_SUCCESS
) {
112 will_return(cbfs_lookup
, mdata
);
113 will_return(cbfs_lookup
, data_offset_out
);
117 const void *cbfs_find_attr(const union cbfs_mdata
*mdata
, uint32_t attr_tag
, size_t size_check
)
119 return mock_ptr_type(void *);
122 static bool force_single_boot_device_size_failure
= false;
124 ssize_t
boot_device_read(void *buf
, size_t offset
, size_t size
)
126 memcpy(buf
, (void *)offset
, size
);
127 if (force_single_boot_device_size_failure
) {
128 force_single_boot_device_size_failure
= false;
136 static size_t get_cbfs_file_size(const void *file_ptr
)
138 const struct cbfs_file
*f
= file_ptr
;
139 return be32toh(f
->offset
) + be32toh(f
->len
);
142 static void create_cbfs(const struct cbfs_test_file
*files
[], const size_t nfiles
,
143 uint8_t *buffer
, const size_t buffer_size
)
145 uint8_t *data_ptr
= buffer
;
146 size_t file_size
= 0;
147 memset(buffer
, 0, buffer_size
);
148 for (size_t i
= 0; i
< nfiles
; ++i
) {
149 if (files
[i
] == NULL
) {
150 file_size
= CBFS_ALIGNMENT
;
151 assert_true(&data_ptr
[file_size
] < &buffer
[buffer_size
]);
153 file_size
= get_cbfs_file_size(files
[i
]);
154 assert_true(&data_ptr
[file_size
] < &buffer
[buffer_size
]);
155 memcpy(data_ptr
, files
[i
], file_size
);
157 data_ptr
= &data_ptr
[file_size
];
158 data_ptr
= &buffer
[ALIGN_UP((uintptr_t)data_ptr
- (uintptr_t)buffer
,
163 static size_t get_created_cbfs_file_start_offset(const struct cbfs_test_file
*files
[],
166 size_t offset_out
= 0;
168 for (size_t i
= 0; i
< nfile
; ++i
) {
169 offset
= files
[i
] ? get_cbfs_file_size(files
[i
]) : CBFS_ALIGNMENT
;
170 offset_out
= ALIGN_UP(offset_out
+ offset
, CBFS_ALIGNMENT
);
178 aligned_cbfs_ro_buffer
[(sizeof(struct cbfs_test_file
) + CBFS_ALIGNMENT
* 50)] __aligned(
180 static const size_t aligned_cbfs_ro_buffer_size
= sizeof(aligned_cbfs_ro_buffer
);
182 aligned_cbfs_rw_buffer
[(sizeof(struct cbfs_test_file
) + CBFS_ALIGNMENT
* 50)] __aligned(
184 static const size_t aligned_cbfs_rw_buffer_size
= sizeof(aligned_cbfs_rw_buffer
);
186 static uint8_t *unaligned_cbfs_ro_buffer
= &aligned_cbfs_ro_buffer
[5];
187 static const size_t unaligned_cbfs_ro_buffer_size
= aligned_cbfs_ro_buffer_size
- 5;
188 static uint8_t *unaligned_cbfs_rw_buffer
= &aligned_cbfs_rw_buffer
[5];
189 static const size_t unaligned_cbfs_rw_buffer_size
= aligned_cbfs_rw_buffer_size
- 5;
191 struct cbfs_test_state
{
192 uint8_t *cbfs_ro_buf
;
193 uint64_t cbfs_ro_size
;
194 uint8_t *cbfs_rw_buf
;
195 uint64_t cbfs_rw_size
;
197 size_t mcache_ro_offset
;
198 size_t mcache_ro_size
;
199 size_t mcache_rw_offset
;
200 size_t mcache_rw_size
;
202 struct cbfs_test_setup
{
210 /* Because of how CMocka works, it should be called in the test function, or in the setup
211 function only if CBFS API capable of initializing RO CBFS boot device is called. */
212 static void setup_cbfs_boot_device(struct cbfs_test_state
*s
)
214 set_fmap_locate_area_results(0, 0, CB_SUCCESS
);
215 lib_sysinfo
.cbfs_ro_mcache_offset
= 0;
216 lib_sysinfo
.cbfs_ro_mcache_size
= 0;
217 memset((void *)cbfs_get_boot_device(true), 0, sizeof(struct cbfs_boot_device
));
219 set_fmap_locate_area_results((size_t)s
->cbfs_ro_buf
, s
->cbfs_ro_size
,
221 lib_sysinfo
.cbfs_ro_mcache_offset
= s
->mcache_ro_offset
;
222 lib_sysinfo
.cbfs_ro_mcache_size
= s
->mcache_ro_size
;
225 lib_sysinfo
.cbfs_offset
= 0;
226 lib_sysinfo
.cbfs_size
= 0;
227 lib_sysinfo
.cbfs_rw_mcache_offset
= 0;
228 lib_sysinfo
.cbfs_rw_mcache_size
= 0;
229 memset((void *)cbfs_get_boot_device(false), 0, sizeof(struct cbfs_boot_device
));
231 lib_sysinfo
.cbfs_offset
= (uint64_t)s
->cbfs_rw_buf
;
232 lib_sysinfo
.cbfs_size
= s
->cbfs_rw_size
;
233 lib_sysinfo
.cbfs_rw_mcache_offset
= s
->mcache_rw_offset
;
234 lib_sysinfo
.cbfs_rw_mcache_size
= s
->mcache_rw_size
;
238 static int setup_cbfs_test(void **state
)
240 struct cbfs_test_state
*s
= calloc(1, sizeof(*s
));
246 memcpy(&s
->ex
, *state
, sizeof(s
->ex
));
249 if (s
->ex
.unaligned
) {
250 s
->cbfs_ro_buf
= unaligned_cbfs_ro_buffer
;
251 s
->cbfs_ro_size
= unaligned_cbfs_ro_buffer_size
;
253 s
->cbfs_ro_buf
= aligned_cbfs_ro_buffer
;
254 s
->cbfs_ro_size
= aligned_cbfs_ro_buffer_size
;
259 if (s
->ex
.unaligned
) {
260 s
->cbfs_rw_buf
= unaligned_cbfs_rw_buffer
;
261 s
->cbfs_rw_size
= unaligned_cbfs_rw_buffer_size
;
263 s
->cbfs_rw_buf
= aligned_cbfs_rw_buffer
;
264 s
->cbfs_rw_size
= aligned_cbfs_rw_buffer_size
;
273 static int teardown_cbfs_test(void **state
)
283 static void test_cbfs_boot_device_init(void **state
)
285 const struct cbfs_boot_device
*cbd
= NULL
;
287 /* No valid RO, should fail */
288 set_fmap_locate_area_results(0, 0, CB_ERR
);
289 lib_sysinfo
.cbfs_offset
= 0;
290 lib_sysinfo
.cbfs_size
= 0;
291 lib_sysinfo
.cbfs_rw_mcache_size
= 0;
292 lib_sysinfo
.cbfs_rw_mcache_offset
= 0;
293 lib_sysinfo
.cbfs_ro_mcache_offset
= 0;
294 lib_sysinfo
.cbfs_ro_mcache_size
= 0;
295 assert_int_equal(NULL
, cbfs_get_boot_device(true));
296 assert_null(cbfs_ro_map("file", NULL
));
299 set_fmap_locate_area_results(0x12345678, 0x90ABCDEF, CB_SUCCESS
);
300 lib_sysinfo
.cbfs_ro_mcache_offset
= 0x600D41C3;
301 lib_sysinfo
.cbfs_ro_mcache_size
= 0xBADBEEFF;
302 cbd
= cbfs_get_boot_device(true);
303 assert_non_null(cbd
);
304 assert_int_equal(0x12345678, cbd
->dev
.offset
);
305 assert_int_equal(0x90ABCDEF, cbd
->dev
.size
);
306 assert_int_equal(0xBADBEEFF, cbd
->mcache_size
);
307 assert_int_equal(0x600D41C3, cbd
->mcache
);
309 lib_sysinfo
.cbfs_offset
= 0xAABBCCDD;
310 lib_sysinfo
.cbfs_size
= 0x1000;
311 lib_sysinfo
.cbfs_rw_mcache_offset
= 0x8F8F8F8F;
312 lib_sysinfo
.cbfs_rw_mcache_size
= 0x500;
313 cbd
= cbfs_get_boot_device(false);
314 assert_non_null(cbd
);
315 assert_int_equal(0xAABBCCDD, cbd
->dev
.offset
);
316 assert_int_equal(0x1000, cbd
->dev
.size
);
317 assert_int_equal(0x8F8F8F8F, cbd
->mcache
);
318 assert_int_equal(0x500, cbd
->mcache_size
);
321 /* This test checks cbfs_map() basic cases and covers only RW CBFS. */
322 void test_cbfs_map(void **state
)
324 struct cbfs_test_state
*s
= *state
;
325 void *mapping
= NULL
;
327 const struct cbfs_test_file
*cbfs_files
[] = {
328 &test_file_int_1
, &test_file_2
, NULL
, &test_file_int_3
,
329 &test_file_int_2
, NULL
, NULL
, &test_file_1
,
331 uint8_t *cbfs_buf
= NULL
;
334 setup_cbfs_boot_device(s
);
335 cbfs_buf
= s
->cbfs_rw_buf
;
336 create_cbfs(cbfs_files
, ARRAY_SIZE(cbfs_files
), s
->cbfs_rw_buf
, s
->cbfs_rw_size
);
339 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 0);
340 expect_cbfs_lookup(TEST_DATA_INT_1_FILENAME
, CB_SUCCESS
,
341 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
342 foffset
+ be32toh(test_file_int_1
.header
.offset
));
343 will_return(cbfs_find_attr
, NULL
);
344 mapping
= cbfs_map(TEST_DATA_INT_1_FILENAME
, &size_out
);
345 assert_non_null(mapping
);
346 assert_int_equal(TEST_DATA_INT_1_SIZE
, size_out
);
347 assert_memory_equal(test_data_int_1
, mapping
, TEST_DATA_INT_1_SIZE
);
351 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 1);
352 expect_cbfs_lookup(TEST_DATA_2_FILENAME
, CB_SUCCESS
,
353 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
354 foffset
+ be32toh(test_file_2
.header
.offset
));
355 will_return(cbfs_find_attr
, &test_file_2
.attrs_and_data
);
356 expect_value(ulzman
, srcn
, TEST_DATA_2_SIZE
);
357 expect_value(ulzman
, dstn
, TEST_DATA_2_SIZE
);
358 mapping
= cbfs_map(TEST_DATA_2_FILENAME
, &size_out
);
359 assert_non_null(mapping
);
360 assert_int_equal(TEST_DATA_2_SIZE
, size_out
);
361 assert_memory_equal(test_data_2
, mapping
, TEST_DATA_2_SIZE
);
365 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 3);
366 expect_cbfs_lookup(TEST_DATA_INT_3_FILENAME
, CB_SUCCESS
,
367 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
368 foffset
+ be32toh(test_file_int_3
.header
.offset
));
369 will_return(cbfs_find_attr
, &test_file_int_3
.attrs_and_data
);
370 expect_value(ulz4fn
, srcn
, TEST_DATA_INT_3_SIZE
);
371 expect_value(ulz4fn
, dstn
, TEST_DATA_INT_3_SIZE
);
372 mapping
= cbfs_map(TEST_DATA_INT_3_FILENAME
, &size_out
);
373 assert_non_null(mapping
);
374 assert_int_equal(TEST_DATA_INT_3_SIZE
, size_out
);
375 assert_memory_equal(test_data_int_3
, mapping
, TEST_DATA_INT_3_SIZE
);
379 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 4);
380 expect_cbfs_lookup(TEST_DATA_INT_2_FILENAME
, CB_SUCCESS
,
381 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
382 foffset
+ be32toh(test_file_int_2
.header
.offset
));
383 will_return(cbfs_find_attr
, NULL
);
384 mapping
= cbfs_map(TEST_DATA_INT_2_FILENAME
, &size_out
);
385 assert_non_null(mapping
);
386 assert_int_equal(TEST_DATA_INT_2_SIZE
, size_out
);
387 assert_memory_equal(test_data_int_2
, mapping
, TEST_DATA_INT_2_SIZE
);
391 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 7);
392 expect_cbfs_lookup(TEST_DATA_1_FILENAME
, CB_SUCCESS
,
393 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
394 foffset
+ be32toh(test_file_1
.header
.offset
));
395 will_return(cbfs_find_attr
, NULL
);
396 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
397 assert_non_null(mapping
);
398 assert_int_equal(TEST_DATA_1_SIZE
, size_out
);
399 assert_memory_equal(test_data_1
, mapping
, TEST_DATA_1_SIZE
);
403 expect_cbfs_lookup("invalid_file", CB_CBFS_NOT_FOUND
, 0, 0);
404 if (s
->ex
.init_rw
&& CONFIG(LP_ENABLE_CBFS_FALLBACK
))
405 expect_cbfs_lookup("invalid_file", CB_CBFS_NOT_FOUND
, 0, 0);
406 mapping
= cbfs_map("invalid_file", &size_out
);
407 assert_null(mapping
);
410 static void test_cbfs_invalid_compression_algo(void **state
)
412 struct cbfs_test_state
*s
= *state
;
413 void *mapping
= NULL
;
415 uint8_t *cbfs_buf
= NULL
;
416 struct cbfs_test_file
*f
;
417 struct cbfs_file_attr_compression
*comp
;
418 const struct cbfs_test_file
*cbfs_files
[] = {
422 setup_cbfs_boot_device(s
);
423 cbfs_buf
= s
->cbfs_rw_buf
;
424 create_cbfs(cbfs_files
, ARRAY_SIZE(cbfs_files
), s
->cbfs_rw_buf
, s
->cbfs_rw_size
);
426 f
= (struct cbfs_test_file
*)cbfs_buf
;
427 comp
= (struct cbfs_file_attr_compression
*)&f
->attrs_and_data
[0];
428 comp
->compression
= 0xFFFFFFF0;
431 expect_cbfs_lookup(TEST_DATA_2_FILENAME
, CB_SUCCESS
, (const union cbfs_mdata
*)cbfs_buf
,
432 be32toh(test_file_1
.header
.offset
));
433 will_return(cbfs_find_attr
, comp
);
434 mapping
= cbfs_map(TEST_DATA_2_FILENAME
, &size_out
);
435 assert_null(mapping
);
438 static void test_cbfs_io_error(void **state
)
440 struct cbfs_test_state
*s
= *state
;
441 setup_cbfs_boot_device(s
);
443 expect_cbfs_lookup(TEST_DATA_1_FILENAME
, CB_CBFS_IO
, 0, 0);
444 assert_null(cbfs_map(TEST_DATA_1_FILENAME
, NULL
));
447 static void test_cbfs_successful_fallback_to_ro(void **state
)
449 struct cbfs_test_state
*s
= *state
;
450 void *mapping
= NULL
;
452 const struct cbfs_test_file
*cbfs_files
[] = {
453 &test_file_1
, &test_file_2
, &test_file_int_1
,
454 &test_file_int_1
, &test_file_int_2
, &test_file_int_3
,
456 uint8_t *cbfs_buf
= NULL
;
459 if (!CONFIG(LP_ENABLE_CBFS_FALLBACK
)) {
460 print_message("Skipping test, because LP_ENABLE_CBFS_FALLBACK == 0\n");
464 setup_cbfs_boot_device(s
);
465 cbfs_buf
= s
->cbfs_ro_buf
;
466 create_cbfs(cbfs_files
, ARRAY_SIZE(cbfs_files
), s
->cbfs_ro_buf
, s
->cbfs_ro_size
);
468 create_cbfs(cbfs_files
, ARRAY_SIZE(cbfs_files
) - 2, s
->cbfs_rw_buf
,
472 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 1);
473 expect_cbfs_lookup(TEST_DATA_2_FILENAME
, CB_CBFS_NOT_FOUND
, 0, 0);
474 expect_cbfs_lookup(TEST_DATA_2_FILENAME
, CB_SUCCESS
,
475 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
476 foffset
+ be32toh(test_file_2
.header
.offset
));
477 will_return(cbfs_find_attr
, &test_file_2
.attrs_and_data
);
478 expect_value(ulzman
, srcn
, TEST_DATA_2_SIZE
);
479 expect_value(ulzman
, dstn
, TEST_DATA_2_SIZE
);
480 mapping
= cbfs_map(TEST_DATA_2_FILENAME
, &size_out
);
481 assert_non_null(mapping
);
482 assert_int_equal(TEST_DATA_2_SIZE
, size_out
);
483 assert_memory_equal(test_data_2
, mapping
, TEST_DATA_2_SIZE
);
487 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 5);
488 expect_cbfs_lookup(TEST_DATA_INT_3_FILENAME
, CB_CBFS_NOT_FOUND
, 0, 0);
489 expect_cbfs_lookup(TEST_DATA_INT_3_FILENAME
, CB_SUCCESS
,
490 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
491 foffset
+ be32toh(test_file_int_3
.header
.offset
));
492 will_return(cbfs_find_attr
, &test_file_int_3
.attrs_and_data
);
493 expect_value(ulz4fn
, srcn
, TEST_DATA_INT_3_SIZE
);
494 expect_value(ulz4fn
, dstn
, TEST_DATA_INT_3_SIZE
);
495 mapping
= cbfs_map(TEST_DATA_INT_3_FILENAME
, &size_out
);
496 assert_non_null(mapping
);
497 assert_int_equal(TEST_DATA_INT_3_SIZE
, size_out
);
498 assert_memory_equal(test_data_int_3
, mapping
, TEST_DATA_INT_3_SIZE
);
502 static void test_cbfs_load(void **state
)
504 struct cbfs_test_state
*s
= *state
;
506 const struct cbfs_test_file
*cbfs_files
[] = {
507 &test_file_int_1
, &test_file_2
, NULL
, &test_file_int_3
,
508 &test_file_int_2
, NULL
, NULL
, &test_file_1
,
510 uint8_t *cbfs_buf
= NULL
;
511 uint8_t load_buf
[1 * KiB
];
514 setup_cbfs_boot_device(s
);
515 cbfs_buf
= s
->cbfs_rw_buf
;
516 create_cbfs(cbfs_files
, ARRAY_SIZE(cbfs_files
), s
->cbfs_rw_buf
, s
->cbfs_rw_size
);
518 /* Successful load */
520 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 0);
521 expect_cbfs_lookup(TEST_DATA_INT_1_FILENAME
, CB_SUCCESS
,
522 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
523 foffset
+ be32toh(test_file_int_1
.header
.offset
));
524 will_return(cbfs_find_attr
, NULL
);
525 size_out
= cbfs_load(TEST_DATA_INT_1_FILENAME
, load_buf
, sizeof(load_buf
));
526 assert_int_equal(TEST_DATA_INT_1_SIZE
, size_out
);
527 assert_memory_equal(test_data_int_1
, load_buf
, TEST_DATA_INT_1_SIZE
);
529 /* Buffer too small */
531 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 7);
532 expect_cbfs_lookup(TEST_DATA_1_FILENAME
, CB_SUCCESS
,
533 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
534 foffset
+ be32toh(test_file_1
.header
.offset
));
535 will_return(cbfs_find_attr
, NULL
);
536 size_out
= cbfs_load(TEST_DATA_1_FILENAME
, load_buf
, TEST_DATA_1_SIZE
/ 2);
537 assert_int_equal(0, size_out
);
540 static void test_cbfs_map_with_mcache(void **state
)
542 struct cbfs_test_state
*s
= *state
;
543 void *mapping
= NULL
;
545 const struct cbfs_test_file
*cbfs_files
[] = {
546 &test_file_int_2
, &test_file_1
, NULL
,
547 &test_file_int_3
, &test_file_int_1
, &test_file_2
,
549 uint8_t *cbfs_buf
= NULL
;
552 /* Will not be accessed, just needs to be valid. */
553 s
->mcache_ro_offset
= ALIGN_UP(0x1000, CBFS_MCACHE_ALIGNMENT
);
554 s
->mcache_ro_size
= ALIGN_UP(0x500, CBFS_MCACHE_ALIGNMENT
);
555 s
->mcache_rw_offset
= ALIGN_UP(0x3000, CBFS_MCACHE_ALIGNMENT
);
556 s
->mcache_rw_size
= ALIGN_UP(0x600, CBFS_MCACHE_ALIGNMENT
);
557 setup_cbfs_boot_device(s
);
558 cbfs_buf
= s
->cbfs_rw_buf
;
559 create_cbfs(cbfs_files
, ARRAY_SIZE(cbfs_files
), s
->cbfs_rw_buf
, s
->cbfs_rw_size
);
562 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 4);
563 expect_cbfs_mcache_lookup(TEST_DATA_INT_1_FILENAME
, CB_SUCCESS
,
564 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
565 foffset
+ be32toh(test_file_int_1
.header
.offset
));
566 will_return(cbfs_find_attr
, NULL
);
567 mapping
= cbfs_map(TEST_DATA_INT_1_FILENAME
, &size_out
);
568 assert_non_null(mapping
);
569 assert_int_equal(TEST_DATA_INT_1_SIZE
, size_out
);
570 assert_memory_equal(test_data_int_1
, mapping
, TEST_DATA_INT_1_SIZE
);
574 static void test_cbfs_boot_device_read_failure(void **state
)
576 struct cbfs_test_state
*s
= *state
;
577 void *mapping
= NULL
;
579 const struct cbfs_test_file
*cbfs_files
[] = {
580 &test_file_int_3
, &test_file_1
, NULL
,
581 &test_file_int_3
, &test_file_int_1
, &test_file_2
,
583 uint8_t *cbfs_buf
= NULL
;
586 setup_cbfs_boot_device(s
);
587 cbfs_buf
= s
->cbfs_rw_buf
;
588 create_cbfs(cbfs_files
, ARRAY_SIZE(cbfs_files
), s
->cbfs_rw_buf
, s
->cbfs_rw_size
);
591 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 1);
592 expect_cbfs_lookup(TEST_DATA_1_FILENAME
, CB_SUCCESS
,
593 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
594 foffset
+ be32toh(test_file_1
.header
.offset
));
595 will_return(cbfs_find_attr
, NULL
);
596 force_single_boot_device_size_failure
= true;
597 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
598 assert_null(mapping
);
601 /* This test uses RW CBFS only */
602 static void test_cbfs_unverified_area_map(void **state
)
604 struct cbfs_test_state
*s
= *state
;
605 void *mapping
= NULL
;
607 const struct cbfs_test_file
*cbfs_files
[] = {
608 &test_file_int_1
, &test_file_2
, NULL
, &test_file_int_3
,
609 &test_file_int_2
, NULL
, NULL
, &test_file_1
,
611 uint8_t *cbfs_buf
= NULL
;
614 cbfs_buf
= s
->cbfs_rw_buf
;
615 set_fmap_locate_area_results((size_t)cbfs_buf
, s
->cbfs_rw_size
, CB_SUCCESS
);
616 create_cbfs(cbfs_files
, ARRAY_SIZE(cbfs_files
), s
->cbfs_rw_buf
, s
->cbfs_rw_size
);
619 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 0);
620 expect_cbfs_lookup(TEST_DATA_INT_1_FILENAME
, CB_SUCCESS
,
621 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
622 foffset
+ be32toh(test_file_int_1
.header
.offset
));
623 will_return(cbfs_find_attr
, NULL
);
624 mapping
= cbfs_unverified_area_map("TEST_AREA", TEST_DATA_INT_1_FILENAME
, &size_out
);
625 assert_non_null(mapping
);
626 assert_int_equal(TEST_DATA_INT_1_SIZE
, size_out
);
627 assert_memory_equal(test_data_int_1
, mapping
, TEST_DATA_INT_1_SIZE
);
631 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 1);
632 expect_cbfs_lookup(TEST_DATA_2_FILENAME
, CB_SUCCESS
,
633 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
634 foffset
+ be32toh(test_file_2
.header
.offset
));
635 will_return(cbfs_find_attr
, &test_file_2
.attrs_and_data
);
636 expect_value(ulzman
, srcn
, TEST_DATA_2_SIZE
);
637 expect_value(ulzman
, dstn
, TEST_DATA_2_SIZE
);
638 mapping
= cbfs_unverified_area_map("TEST_AREA", TEST_DATA_2_FILENAME
, &size_out
);
639 assert_non_null(mapping
);
640 assert_int_equal(TEST_DATA_2_SIZE
, size_out
);
641 assert_memory_equal(test_data_2
, mapping
, TEST_DATA_2_SIZE
);
645 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 3);
646 expect_cbfs_lookup(TEST_DATA_INT_3_FILENAME
, CB_SUCCESS
,
647 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
648 foffset
+ be32toh(test_file_int_3
.header
.offset
));
649 will_return(cbfs_find_attr
, &test_file_int_3
.attrs_and_data
);
650 expect_value(ulz4fn
, srcn
, TEST_DATA_INT_3_SIZE
);
651 expect_value(ulz4fn
, dstn
, TEST_DATA_INT_3_SIZE
);
652 mapping
= cbfs_unverified_area_map("TEST_AREA", TEST_DATA_INT_3_FILENAME
, &size_out
);
653 assert_non_null(mapping
);
654 assert_int_equal(TEST_DATA_INT_3_SIZE
, size_out
);
655 assert_memory_equal(test_data_int_3
, mapping
, TEST_DATA_INT_3_SIZE
);
659 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 4);
660 expect_cbfs_lookup(TEST_DATA_INT_2_FILENAME
, CB_SUCCESS
,
661 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
662 foffset
+ be32toh(test_file_int_2
.header
.offset
));
663 will_return(cbfs_find_attr
, NULL
);
664 mapping
= cbfs_unverified_area_map("TEST_AREA", TEST_DATA_INT_2_FILENAME
, &size_out
);
665 assert_non_null(mapping
);
666 assert_int_equal(TEST_DATA_INT_2_SIZE
, size_out
);
667 assert_memory_equal(test_data_int_2
, mapping
, TEST_DATA_INT_2_SIZE
);
671 foffset
= get_created_cbfs_file_start_offset(cbfs_files
, 7);
672 expect_cbfs_lookup(TEST_DATA_1_FILENAME
, CB_SUCCESS
,
673 (const union cbfs_mdata
*)&cbfs_buf
[foffset
],
674 foffset
+ be32toh(test_file_1
.header
.offset
));
675 will_return(cbfs_find_attr
, NULL
);
676 mapping
= cbfs_unverified_area_map("TEST_AREA", TEST_DATA_1_FILENAME
, &size_out
);
677 assert_non_null(mapping
);
678 assert_int_equal(TEST_DATA_1_SIZE
, size_out
);
679 assert_memory_equal(test_data_1
, mapping
, TEST_DATA_1_SIZE
);
683 expect_cbfs_lookup("invalid_file", CB_CBFS_NOT_FOUND
, 0, 0);
684 mapping
= cbfs_unverified_area_map("TEST_AREA", "invalid_file", &size_out
);
685 assert_null(mapping
);
688 #define TEST_CBFS_NAME_ALIGN_RO_RW(fn, test_name, enable_unaligned, enable_init_ro, \
690 ((struct CMUnitTest){ \
691 .name = (test_name), \
693 .setup_func = setup_cbfs_test, \
694 .teardown_func = teardown_cbfs_test, \
696 &(struct cbfs_test_setup){ \
697 .unaligned = enable_unaligned, \
698 .init_ro = enable_init_ro, \
699 .init_rw = enable_init_rw, \
703 #define TEST_CBFS_LOOKUP(fn) \
704 EMPTY_WRAP(TEST_CBFS_NAME_ALIGN_RO_RW(fn, #fn ", RW, aligned", false, false, true), \
705 TEST_CBFS_NAME_ALIGN_RO_RW(fn, #fn ", RW, unaligned", true, false, true))
707 #define TEST_CBFS_RO_FALLBACK(fn) \
708 EMPTY_WRAP(TEST_CBFS_NAME_ALIGN_RO_RW(fn, #fn ", RW+RO, aligned", false, true, true), \
709 TEST_CBFS_NAME_ALIGN_RO_RW(fn, #fn ", RW+RO, unaligned", true, true, true), \
710 TEST_CBFS_NAME_ALIGN_RO_RW(fn, #fn ", RO, aligned", false, true, false), \
711 TEST_CBFS_NAME_ALIGN_RO_RW(fn, #fn ", RO, unaligned", true, true, false))
716 const struct CMUnitTest tests
[] = {
717 cmocka_unit_test(test_cbfs_boot_device_init
),
718 TEST_CBFS_LOOKUP(test_cbfs_map
),
719 TEST_CBFS_LOOKUP(test_cbfs_invalid_compression_algo
),
720 TEST_CBFS_LOOKUP(test_cbfs_io_error
),
721 TEST_CBFS_RO_FALLBACK(test_cbfs_successful_fallback_to_ro
),
722 TEST_CBFS_LOOKUP(test_cbfs_load
),
723 TEST_CBFS_LOOKUP(test_cbfs_map_with_mcache
),
724 TEST_CBFS_LOOKUP(test_cbfs_boot_device_read_failure
),
725 TEST_CBFS_LOOKUP(test_cbfs_unverified_area_map
),
728 return lp_run_group_tests(tests
, NULL
, NULL
);