1 /* SPDX-License-Identifier: GPL-2.0-only */
5 #include <commonlib/bsd/cbfs_mdata.h>
6 #include <commonlib/bsd/cbfs_private.h>
7 #include <commonlib/region.h>
9 #include <tests/lib/cbfs_util.h>
10 #include <tests/test.h>
13 static struct cbfs_boot_device cbd
;
15 static u8 aligned_cbfs_buffer
[(sizeof(struct cbfs_test_file
) + CBFS_ALIGNMENT
) * 10] __aligned(
18 static u8
*unaligned_cbfs_buffer
= &aligned_cbfs_buffer
[3];
19 static uintptr_t unaligned_cbfs_buffer_size
= sizeof(aligned_cbfs_buffer
) - 3;
21 static u8 cbfs_mcache
[TEST_MCACHE_SIZE
] __aligned(CBFS_MCACHE_ALIGNMENT
);
23 /* Add files to CBFS buffer. NULL in files list equals to one CBFS_ALIGNMENT of spacing. */
24 static int create_cbfs(const struct cbfs_test_file
*files
[], const size_t nfiles
, u8
*buffer
,
25 const size_t buffer_size
)
27 u8
*data_ptr
= buffer
;
29 memset(buffer
, 0, buffer_size
);
31 for (size_t i
= 0; i
< nfiles
; ++i
) {
32 if (files
[i
] == NULL
) {
33 file_size
= CBFS_ALIGNMENT
;
34 assert_true(&data_ptr
[file_size
] < &buffer
[buffer_size
]);
36 file_size
= be32_to_cpu(files
[i
]->header
.len
)
37 + be32_to_cpu(files
[i
]->header
.offset
);
38 assert_true(&data_ptr
[file_size
] < &buffer
[buffer_size
]);
39 memcpy(data_ptr
, files
[i
], file_size
);
42 data_ptr
= &data_ptr
[file_size
];
43 const uintptr_t offset
= (uintptr_t)data_ptr
- (uintptr_t)buffer
;
44 data_ptr
= &buffer
[ALIGN_UP(offset
, CBFS_ALIGNMENT
)];
52 const struct cbfs_boot_device
*cbfs_get_boot_device(bool force_ro
)
57 size_t ulzman(const void *src
, size_t srcn
, void *dst
, size_t dstn
)
61 memcpy(dst
, src
, dstn
);
65 size_t ulz4fn(const void *src
, size_t srcn
, void *dst
, size_t dstn
)
69 memcpy(dst
, src
, dstn
);
73 extern enum cb_err
__real_cbfs_lookup(cbfs_dev_t dev
, const char *name
,
74 union cbfs_mdata
*mdata_out
, size_t *data_offset_out
,
75 struct vb2_hash
*metadata_hash
);
77 enum cb_err
cbfs_lookup(cbfs_dev_t dev
, const char *name
, union cbfs_mdata
*mdata_out
,
78 size_t *data_offset_out
, struct vb2_hash
*metadata_hash
)
80 const enum cb_err err
=
81 __real_cbfs_lookup(dev
, name
, mdata_out
, data_offset_out
, metadata_hash
);
82 assert_int_equal(err
, mock_type(enum cb_err
));
86 extern enum cb_err
__real_cbfs_mcache_lookup(const void *mcache
, size_t mcache_size
,
87 const char *name
, union cbfs_mdata
*mdata_out
,
88 size_t *data_offset_out
);
90 enum cb_err
cbfs_mcache_lookup(const void *mcache
, size_t mcache_size
, const char *name
,
91 union cbfs_mdata
*mdata_out
, size_t *data_offset_out
)
93 const enum cb_err err
= __real_cbfs_mcache_lookup(mcache
, mcache_size
, name
, mdata_out
,
95 assert_int_equal(err
, mock_type(enum cb_err
));
99 extern void *__real_mem_pool_alloc(struct mem_pool
*mp
, size_t sz
);
101 void *mem_pool_alloc(struct mem_pool
*mp
, size_t sz
)
104 assert_ptr_equal(mp
, &cbfs_cache
);
105 return __real_mem_pool_alloc(mp
, sz
);
108 extern void __real_mem_pool_free(struct mem_pool
*mp
, void *p
);
110 void mem_pool_free(struct mem_pool
*mp
, void *p
)
113 assert_ptr_equal(mp
, &cbfs_cache
);
114 return __real_mem_pool_free(mp
, p
);
117 static u8 cbmem_test_buf
[2 * MiB
];
119 void *cbmem_add(u32 id
, u64 size
)
122 check_expected(size
);
123 return cbmem_test_buf
;
126 /* Setup, teardown and utils */
128 struct cbfs_test_state_ex
{
131 enum cb_err lookup_result
;
134 struct cbfs_test_state
{
139 struct cbfs_test_state_ex ex
;
142 static int setup_test_cbfs_aligned(void **state
)
144 struct cbfs_test_state
*s
= malloc(sizeof(struct cbfs_test_state
));
148 s
->cbfs_buf
= aligned_cbfs_buffer
;
149 s
->cbfs_size
= sizeof(aligned_cbfs_buffer
);
150 memset(&s
->ex
, 0, sizeof(s
->ex
));
154 s
->ex
= *((struct cbfs_test_state_ex
*)*state
);
158 rdev_chain_mem(&cbd
.rdev
, aligned_cbfs_buffer
, sizeof(aligned_cbfs_buffer
));
159 memset(aligned_cbfs_buffer
, 0, sizeof(aligned_cbfs_buffer
));
161 cbd
.mcache
= cbfs_mcache
;
162 cbd
.mcache_size
= TEST_MCACHE_SIZE
;
167 static int setup_test_cbfs_unaligned(void **state
)
169 struct cbfs_test_state
*s
= malloc(sizeof(struct cbfs_test_state
));
173 s
->cbfs_buf
= unaligned_cbfs_buffer
;
174 s
->cbfs_size
= unaligned_cbfs_buffer_size
;
175 memset(&s
->ex
, 0, sizeof(s
->ex
));
179 s
->ex
= *((struct cbfs_test_state_ex
*)*state
);
183 rdev_chain_mem(&cbd
.rdev
, unaligned_cbfs_buffer
, unaligned_cbfs_buffer_size
);
184 memset(unaligned_cbfs_buffer
, 0, unaligned_cbfs_buffer_size
);
186 cbd
.mcache
= cbfs_mcache
;
187 cbd
.mcache_size
= TEST_MCACHE_SIZE
;
192 static int teardown_test_cbfs(void **state
)
195 memset(&cbd
, 0, sizeof(cbd
));
201 static void expect_lookup_result(enum cb_err res
)
203 if (CONFIG(NO_CBFS_MCACHE
))
204 will_return(cbfs_lookup
, (res
));
206 will_return(cbfs_mcache_lookup
, (res
));
211 /* Test case for cbfs_map() function. Validate file searching in the correct CBFS */
212 static void test_cbfs_map(void **state
)
216 struct cbfs_test_state
*s
= *state
;
217 const struct cbfs_test_file
*cbfs_files
[] = {
218 &test_file_int_1
, &test_file_2
, NULL
, &test_file_int_2
,
219 &test_file_1
, NULL
, NULL
, &test_file_int_3
,
222 0, create_cbfs(cbfs_files
, ARRAY_SIZE(cbfs_files
), s
->cbfs_buf
, s
->cbfs_size
));
223 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
227 expect_lookup_result(CB_SUCCESS
);
228 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
229 assert_non_null(mapping
);
230 assert_int_equal(TEST_DATA_1_SIZE
, size_out
);
231 assert_memory_equal(mapping
, test_data_1
, TEST_DATA_1_SIZE
);
233 expect_value(mem_pool_free
, p
, mapping
);
237 expect_value(ulzman
, srcn
, TEST_DATA_2_SIZE
);
238 expect_value(ulzman
, dstn
, TEST_DATA_2_SIZE
);
239 expect_value(mem_pool_alloc
, sz
, TEST_DATA_2_SIZE
);
240 expect_lookup_result(CB_SUCCESS
);
241 mapping
= cbfs_map(TEST_DATA_2_FILENAME
, &size_out
);
242 assert_non_null(mapping
);
243 assert_int_equal(TEST_DATA_2_SIZE
, size_out
);
244 assert_memory_equal(mapping
, test_data_2
, TEST_DATA_2_SIZE
);
246 expect_value(mem_pool_free
, p
, mapping
);
250 expect_lookup_result(CB_SUCCESS
);
251 mapping
= cbfs_map(TEST_DATA_INT_1_FILENAME
, &size_out
);
252 assert_non_null(mapping
);
253 assert_int_equal(TEST_DATA_INT_1_SIZE
, size_out
);
254 assert_memory_equal(mapping
, test_data_int_1
, TEST_DATA_INT_1_SIZE
);
256 expect_value(mem_pool_free
, p
, mapping
);
259 /* Do not pass output pointer to size. It should work correctly. */
260 expect_lookup_result(CB_SUCCESS
);
261 mapping
= cbfs_map(TEST_DATA_INT_2_FILENAME
, NULL
);
262 assert_non_null(mapping
);
263 assert_memory_equal(mapping
, test_data_int_2
, TEST_DATA_INT_2_SIZE
);
265 expect_value(mem_pool_free
, p
, mapping
);
269 expect_value(ulz4fn
, srcn
, TEST_DATA_INT_3_SIZE
);
270 expect_value(ulz4fn
, dstn
, TEST_DATA_INT_3_SIZE
);
271 expect_value(mem_pool_alloc
, sz
, TEST_DATA_INT_3_SIZE
);
272 expect_lookup_result(CB_SUCCESS
);
273 mapping
= cbfs_map(TEST_DATA_INT_3_FILENAME
, &size_out
);
274 assert_non_null(mapping
);
275 assert_int_equal(TEST_DATA_INT_3_SIZE
, size_out
);
276 assert_memory_equal(mapping
, test_data_int_3
, TEST_DATA_INT_3_SIZE
);
278 expect_value(mem_pool_free
, p
, mapping
);
281 /* Nonexistent files */
283 expect_lookup_result(CB_CBFS_NOT_FOUND
);
284 mapping
= cbfs_map("unknown_fname", &size_out
);
285 assert_ptr_equal(NULL
, mapping
);
286 assert_int_equal(0, size_out
);
289 expect_lookup_result(CB_CBFS_NOT_FOUND
);
290 mapping
= cbfs_map("", &size_out
);
291 assert_ptr_equal(NULL
, mapping
);
292 assert_int_equal(0, size_out
);
295 static void test_cbfs_cbmem_alloc(void **state
)
299 struct cbfs_test_state
*s
= *state
;
300 const struct cbfs_test_file
*cbfs_files
[] = {
301 NULL
, &test_file_1
, &test_file_2
, &test_file_int_1
,
302 NULL
, &test_file_int_2
, &test_file_int_3
, NULL
,
305 0, create_cbfs(cbfs_files
, ARRAY_SIZE(cbfs_files
), s
->cbfs_buf
, s
->cbfs_size
));
306 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
309 expect_lookup_result(CB_SUCCESS
);
310 expect_value(cbmem_add
, id
, 0x0101);
311 expect_value(cbmem_add
, size
, TEST_DATA_1_SIZE
);
312 mapping
= cbfs_cbmem_alloc(TEST_DATA_1_FILENAME
, 0x0101, &size_out
);
313 assert_non_null(mapping
);
314 assert_int_equal(TEST_DATA_1_SIZE
, size_out
);
315 assert_memory_equal(mapping
, test_data_1
, TEST_DATA_1_SIZE
);
317 expect_value(mem_pool_free
, p
, mapping
);
320 /* Do not pass output pointer to size. It should work correctly. */
321 expect_value(ulzman
, srcn
, TEST_DATA_2_SIZE
);
322 expect_value(ulzman
, dstn
, TEST_DATA_2_SIZE
);
323 expect_lookup_result(CB_SUCCESS
);
324 expect_value(cbmem_add
, id
, 0x0102);
325 expect_value(cbmem_add
, size
, TEST_DATA_2_SIZE
);
326 mapping
= cbfs_cbmem_alloc(TEST_DATA_2_FILENAME
, 0x0102, NULL
);
327 assert_non_null(mapping
);
328 assert_memory_equal(mapping
, test_data_2
, TEST_DATA_2_SIZE
);
330 expect_value(mem_pool_free
, p
, mapping
);
334 expect_lookup_result(CB_SUCCESS
);
335 expect_value(cbmem_add
, id
, 0x0201);
336 expect_value(cbmem_add
, size
, TEST_DATA_INT_1_SIZE
);
337 mapping
= cbfs_cbmem_alloc(TEST_DATA_INT_1_FILENAME
, 0x0201, &size_out
);
338 assert_non_null(mapping
);
339 assert_int_equal(TEST_DATA_INT_1_SIZE
, size_out
);
340 assert_memory_equal(mapping
, test_data_int_1
, TEST_DATA_INT_1_SIZE
);
342 expect_value(mem_pool_free
, p
, mapping
);
346 expect_lookup_result(CB_SUCCESS
);
347 expect_value(cbmem_add
, id
, 0x0202);
348 expect_value(cbmem_add
, size
, TEST_DATA_INT_2_SIZE
);
349 mapping
= cbfs_cbmem_alloc(TEST_DATA_INT_2_FILENAME
, 0x0202, &size_out
);
350 assert_non_null(mapping
);
351 assert_int_equal(TEST_DATA_INT_2_SIZE
, size_out
);
352 assert_memory_equal(mapping
, test_data_int_2
, TEST_DATA_INT_2_SIZE
);
354 expect_value(mem_pool_free
, p
, mapping
);
358 expect_value(ulz4fn
, srcn
, TEST_DATA_INT_3_SIZE
);
359 expect_value(ulz4fn
, dstn
, TEST_DATA_INT_3_SIZE
);
360 expect_lookup_result(CB_SUCCESS
);
361 expect_value(cbmem_add
, id
, 0x0203);
362 expect_value(cbmem_add
, size
, TEST_DATA_INT_2_SIZE
);
363 mapping
= cbfs_cbmem_alloc(TEST_DATA_INT_3_FILENAME
, 0x0203, &size_out
);
364 assert_non_null(mapping
);
365 assert_int_equal(TEST_DATA_INT_3_SIZE
, size_out
);
366 assert_memory_equal(mapping
, test_data_int_3
, TEST_DATA_INT_3_SIZE
);
368 expect_value(mem_pool_free
, p
, mapping
);
371 /* Nonexistent files */
373 expect_lookup_result(CB_CBFS_NOT_FOUND
);
374 mapping
= cbfs_cbmem_alloc("nothing-file", 0x0301, &size_out
);
375 assert_null(mapping
);
378 expect_lookup_result(CB_CBFS_NOT_FOUND
);
379 mapping
= cbfs_cbmem_alloc("", 0x0302, &size_out
);
380 assert_null(mapping
);
383 static void test_cbfs_image_not_aligned(void **state
)
387 struct cbfs_test_state
*s
= *state
;
388 const struct cbfs_test_file
*cbfs_files
[] = {
392 assert_int_equal(0, create_cbfs(cbfs_files
, ARRAY_SIZE(cbfs_files
), &s
->cbfs_buf
[5],
394 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
397 expect_lookup_result(CB_CBFS_NOT_FOUND
);
398 mapping
= cbfs_map(TEST_DATA_INT_1_FILENAME
, &size_out
);
399 assert_null(mapping
);
402 expect_lookup_result(CB_CBFS_NOT_FOUND
);
403 mapping
= cbfs_map(TEST_DATA_2_FILENAME
, &size_out
);
404 assert_null(mapping
);
407 static void test_cbfs_file_not_aligned(void **state
)
411 struct cbfs_test_state
*s
= *state
;
413 memcpy(s
->cbfs_buf
, &test_file_int_2
, sizeof(test_file_int_2
));
414 memcpy(&s
->cbfs_buf
[ALIGN_UP(sizeof(test_file_int_2
), CBFS_ALIGNMENT
) + 5],
415 &test_file_1
, sizeof(test_file_1
));
416 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
419 expect_lookup_result(CB_SUCCESS
);
420 mapping
= cbfs_map(TEST_DATA_INT_2_FILENAME
, &size_out
);
421 assert_ptr_equal(mapping
,
422 &s
->cbfs_buf
[offsetof(struct cbfs_test_file
, attrs_and_data
)]);
425 expect_lookup_result(CB_CBFS_NOT_FOUND
);
426 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
427 assert_null(mapping
);
430 static void test_cbfs_garbage_data_before_aligned_file(void **state
)
434 const char garbage
[] =
435 "NOT so USEFUL DaTa BYTES that should have at least CBFS_ALIGNMENT bytes";
436 const size_t garbage_sz
= CBFS_ALIGNMENT
;
437 struct cbfs_test_state
*s
= *state
;
439 /* Garbage data size has to be aligned to CBFS_ALIGNMENT */
440 memcpy(s
->cbfs_buf
, garbage
, garbage_sz
);
441 memcpy(&s
->cbfs_buf
[garbage_sz
], &test_file_int_2
, sizeof(test_file_int_2
));
442 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
445 expect_lookup_result(CB_SUCCESS
);
446 mapping
= cbfs_map(TEST_DATA_INT_2_FILENAME
, &size_out
);
449 &s
->cbfs_buf
[garbage_sz
+ offsetof(struct cbfs_test_file
, attrs_and_data
)]);
452 static void test_cbfs_garbage_data_before_unaligned_file(void **state
)
456 const char garbage
[] =
457 "NOT so USEFUL DaTa BYTES that should have at least CBFS_ALIGNMENT + 3 bytes";
458 const size_t garbage_sz
= CBFS_ALIGNMENT
+ 3;
459 struct cbfs_test_state
*s
= *state
;
461 assert_true(garbage_sz
== (CBFS_ALIGNMENT
+ 3));
462 memcpy(s
->cbfs_buf
, garbage
, garbage_sz
);
463 memcpy(&s
->cbfs_buf
[garbage_sz
], &test_file_int_2
, sizeof(test_file_int_2
));
464 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
467 expect_lookup_result(CB_CBFS_NOT_FOUND
);
468 mapping
= cbfs_map(TEST_DATA_INT_2_FILENAME
, &size_out
);
469 assert_null(mapping
);
472 static void test_cbfs_file_bigger_than_rdev(void **state
)
476 struct cbfs_test_state
*s
= *state
;
477 struct cbfs_test_file
*f
;
478 memcpy(s
->cbfs_buf
, &test_file_1
, sizeof(test_file_1
));
479 f
= (struct cbfs_test_file
*)s
->cbfs_buf
;
480 /* File with length equal to region_device size will go beyond it */
481 f
->header
.len
= cpu_to_be32(s
->cbfs_size
);
483 /* Initialization and mcache building will succeed, because it only does access file
484 headers, and not actual data */
485 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
488 /* Lookup should not succeed, because data is too long, so reading it later would cause
489 memory access issues */
490 expect_lookup_result(CB_CBFS_NOT_FOUND
);
491 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
492 assert_null(mapping
);
495 static void test_cbfs_fail_beyond_rdev(void **state
)
499 struct cbfs_test_state
*s
= *state
;
500 size_t second_file_start
= ALIGN_UP(sizeof(test_file_1
), CBFS_ALIGNMENT
);
502 memcpy(s
->cbfs_buf
, &test_file_1
, sizeof(test_file_1
));
503 memcpy(&s
->cbfs_buf
[second_file_start
], &test_file_2
, s
->ex
.file_length
);
504 assert_true((second_file_start
+ s
->ex
.file_length
) <= region_sz(&cbd
.rdev
.region
));
505 /* Adjust size of region device to cut everything after selected offset */
506 cbd
.rdev
.region
.size
= second_file_start
+ s
->ex
.file_length
;
508 /* CBFS initialization should not fail if last file is not valid */
509 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
512 expect_lookup_result(CB_SUCCESS
);
513 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
514 assert_ptr_equal(mapping
, &s
->cbfs_buf
[be32_to_cpu(test_file_1
.header
.offset
)]);
515 assert_int_equal(size_out
, TEST_DATA_1_SIZE
);
518 if (s
->ex
.lookup_result
== CB_SUCCESS
) {
519 expect_value(ulzman
, srcn
, TEST_DATA_2_SIZE
);
520 expect_value(ulzman
, dstn
, TEST_DATA_2_SIZE
);
521 expect_value(mem_pool_alloc
, sz
, TEST_DATA_2_SIZE
);
523 expect_lookup_result(s
->ex
.lookup_result
);
524 cbfs_map(TEST_DATA_2_FILENAME
, &size_out
);
527 static void test_cbfs_unaligned_file_in_the_middle(void **state
)
531 struct cbfs_test_state
*s
= *state
;
532 size_t second_file_start
= ALIGN_UP(sizeof(test_file_1
), CBFS_ALIGNMENT
) + 5;
533 size_t third_file_start
=
534 ALIGN_UP(sizeof(test_file_int_1
) + second_file_start
, CBFS_ALIGNMENT
);
536 memcpy(s
->cbfs_buf
, &test_file_1
, sizeof(test_file_1
));
537 memcpy(&s
->cbfs_buf
[second_file_start
], &test_file_int_1
, sizeof(test_file_int_1
));
538 memcpy(&s
->cbfs_buf
[third_file_start
], &test_file_int_2
, sizeof(test_file_int_2
));
540 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
543 expect_lookup_result(CB_SUCCESS
);
544 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
545 assert_ptr_equal(mapping
, &s
->cbfs_buf
[be32_to_cpu(test_file_1
.header
.offset
)]);
546 assert_int_equal(size_out
, be32_to_cpu(test_file_1
.header
.len
));
549 expect_lookup_result(CB_CBFS_NOT_FOUND
);
550 mapping
= cbfs_map(TEST_DATA_INT_1_FILENAME
, &size_out
);
551 assert_null(mapping
);
554 expect_lookup_result(CB_SUCCESS
);
555 mapping
= cbfs_map(TEST_DATA_INT_2_FILENAME
, &size_out
);
558 &s
->cbfs_buf
[third_file_start
+ be32_to_cpu(test_file_int_2
.header
.offset
)]);
559 assert_int_equal(size_out
, be32_to_cpu(test_file_int_2
.header
.len
));
562 static void test_cbfs_overlapping_files(void **state
)
566 struct cbfs_test_state
*s
= *state
;
567 size_t second_file_start
= ALIGN_UP(sizeof(test_file_1
), CBFS_ALIGNMENT
);
568 size_t third_file_start
=
569 ALIGN_UP(sizeof(test_file_int_1
) + second_file_start
, CBFS_ALIGNMENT
);
570 size_t second_file_size
=
571 third_file_start
+ sizeof(test_file_int_2
) - second_file_start
;
572 struct cbfs_test_file
*f
;
574 /* Third file is inside second file, thus it should not be found */
575 memcpy(s
->cbfs_buf
, &test_file_1
, sizeof(test_file_1
));
576 memcpy(&s
->cbfs_buf
[second_file_start
], &test_file_int_1
, sizeof(test_file_int_1
));
577 memcpy(&s
->cbfs_buf
[third_file_start
], &test_file_int_2
, sizeof(test_file_int_2
));
578 f
= (struct cbfs_test_file
*)&s
->cbfs_buf
[second_file_start
];
579 f
->header
.len
= cpu_to_be32(second_file_size
);
581 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
584 expect_lookup_result(CB_SUCCESS
);
585 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
586 assert_ptr_equal(mapping
, &s
->cbfs_buf
[be32_to_cpu(test_file_1
.header
.offset
)]);
587 assert_int_equal(size_out
, be32_to_cpu(test_file_1
.header
.len
));
590 expect_lookup_result(CB_SUCCESS
);
591 mapping
= cbfs_map(TEST_DATA_INT_1_FILENAME
, &size_out
);
594 &s
->cbfs_buf
[second_file_start
+ be32_to_cpu(test_file_int_1
.header
.offset
)]);
595 assert_int_equal(size_out
, second_file_size
);
598 expect_lookup_result(CB_CBFS_NOT_FOUND
);
599 mapping
= cbfs_map(TEST_DATA_INT_2_FILENAME
, &size_out
);
600 assert_null(mapping
);
603 static void test_cbfs_incorrect_file_in_the_middle(void **state
)
607 struct cbfs_test_state
*s
= *state
;
608 size_t second_file_start
= ALIGN_UP(sizeof(test_file_1
), CBFS_ALIGNMENT
);
609 size_t third_file_start
=
610 ALIGN_UP(sizeof(test_file_int_1
) + second_file_start
, CBFS_ALIGNMENT
);
611 struct cbfs_test_file
*f
;
613 /* Zero offset is illegal. File is not correct */
614 memcpy(s
->cbfs_buf
, &test_file_1
, sizeof(test_file_1
));
615 memcpy(&s
->cbfs_buf
[second_file_start
], &test_file_int_1
, sizeof(test_file_int_1
));
616 memcpy(&s
->cbfs_buf
[third_file_start
], &test_file_int_2
, sizeof(test_file_int_2
));
617 f
= (struct cbfs_test_file
*)&s
->cbfs_buf
[second_file_start
];
618 f
->header
.offset
= cpu_to_be32(0);
620 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
623 expect_lookup_result(CB_SUCCESS
);
624 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
625 assert_ptr_equal(mapping
, &s
->cbfs_buf
[be32_to_cpu(test_file_1
.header
.offset
)]);
626 assert_int_equal(size_out
, be32_to_cpu(test_file_1
.header
.len
));
629 expect_lookup_result(CB_CBFS_NOT_FOUND
);
630 mapping
= cbfs_map(TEST_DATA_INT_1_FILENAME
, &size_out
);
631 assert_null(mapping
);
634 expect_lookup_result(CB_SUCCESS
);
635 mapping
= cbfs_map(TEST_DATA_INT_2_FILENAME
, &size_out
);
638 &s
->cbfs_buf
[third_file_start
+ be32_to_cpu(test_file_int_2
.header
.offset
)]);
639 assert_int_equal(size_out
, be32_to_cpu(test_file_int_2
.header
.len
));
642 static void test_cbfs_two_files_with_same_name(void **state
)
646 struct cbfs_test_state
*s
= *state
;
647 size_t second_file_start
= ALIGN_UP(sizeof(test_file_1
), CBFS_ALIGNMENT
);
648 size_t third_file_start
=
649 ALIGN_UP(sizeof(test_file_1
) + second_file_start
, CBFS_ALIGNMENT
);
651 /* Only first occurrence of file will be found */
652 memcpy(s
->cbfs_buf
, &test_file_1
, sizeof(test_file_1
));
653 memcpy(&s
->cbfs_buf
[second_file_start
], &test_file_1
, sizeof(test_file_1
));
654 memcpy(&s
->cbfs_buf
[third_file_start
], &test_file_int_1
, sizeof(test_file_int_1
));
656 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
659 expect_lookup_result(CB_SUCCESS
);
660 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
661 assert_ptr_equal(mapping
, &s
->cbfs_buf
[be32_to_cpu(test_file_1
.header
.offset
)]);
662 assert_int_equal(size_out
, be32_to_cpu(test_file_1
.header
.len
));
665 expect_lookup_result(CB_SUCCESS
);
666 mapping
= cbfs_map(TEST_DATA_INT_1_FILENAME
, &size_out
);
669 &s
->cbfs_buf
[third_file_start
+ be32_to_cpu(test_file_int_1
.header
.offset
)]);
670 assert_int_equal(size_out
, be32_to_cpu(test_file_int_1
.header
.len
));
673 static void test_cbfs_filename_not_terminated(void **state
)
677 struct cbfs_test_state
*s
= *state
;
678 struct cbfs_test_file
*f
;
679 const char fname
[] = "abcdefghijklmnop";
681 assert_true(sizeof(test_file_1
.filename
) == strlen(fname
));
682 memcpy(s
->cbfs_buf
, &test_file_1
, sizeof(test_file_1
));
683 f
= (struct cbfs_test_file
*)s
->cbfs_buf
;
684 memcpy(f
->filename
, fname
, strlen(fname
));
686 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
689 /* Filename is too long and does not include NULL-terminator. */
690 expect_lookup_result(CB_CBFS_NOT_FOUND
);
691 mapping
= cbfs_map(fname
, &size_out
);
692 assert_null(mapping
);
695 static void test_cbfs_filename_terminated_but_too_long(void **state
)
699 struct cbfs_test_state
*s
= *state
;
700 struct cbfs_test_file
*f
;
702 /* Filename length in header offset field is too short by one to include
703 NULL-terminator of filename */
704 memcpy(s
->cbfs_buf
, &test_file_1
, sizeof(test_file_1
));
705 f
= (struct cbfs_test_file
*)s
->cbfs_buf
;
706 f
->header
.offset
= cpu_to_be32(offsetof(struct cbfs_test_file
, filename
)
707 + strlen(TEST_DATA_1_FILENAME
));
709 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
712 expect_lookup_result(CB_CBFS_NOT_FOUND
);
713 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
714 assert_null(mapping
);
717 static void test_cbfs_attributes_offset_larger_than_offset(void **state
)
721 struct cbfs_test_state
*s
= *state
;
722 struct cbfs_test_file
*f
;
724 /* Require attributes for this test */
725 assert_true(be32_to_cpu(test_file_2
.header
.attributes_offset
) != 0);
726 memcpy(s
->cbfs_buf
, &test_file_2
, sizeof(test_file_2
));
727 f
= (struct cbfs_test_file
*)s
->cbfs_buf
;
728 f
->header
.attributes_offset
= cpu_to_be32(sizeof(struct cbfs_file
) + FILENAME_SIZE
729 + sizeof(struct cbfs_file_attr_compression
));
730 f
->header
.offset
= cpu_to_be32(sizeof(struct cbfs_file
) + FILENAME_SIZE
);
732 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
735 expect_lookup_result(CB_CBFS_NOT_FOUND
);
736 mapping
= cbfs_map(TEST_DATA_2_FILENAME
, &size_out
);
737 assert_null(mapping
);
740 static void test_cbfs_attributes_offset_cut_off_at_len(void **state
)
744 struct cbfs_test_state
*s
= *state
;
745 struct cbfs_test_file
*f
;
747 /* Require attributes for this test */
748 assert_true(be32_to_cpu(test_file_2
.header
.attributes_offset
) != 0);
749 memcpy(s
->cbfs_buf
, &test_file_2
, sizeof(test_file_2
));
750 f
= (struct cbfs_test_file
*)s
->cbfs_buf
;
751 f
->header
.attributes_offset
=
752 cpu_to_be32(offsetof(struct cbfs_test_file
, attrs_and_data
)
753 + offsetof(struct cbfs_file_attribute
, len
));
755 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
757 /* No attributes will be found, because attributes_offset value is too big to cover
758 cbfs_file_attribute tag. Compression attribute of ths file will not be found, and
759 that is why there is no need to call expect_value(ulzma).
760 However, file will be found, because the offset is correct. */
762 expect_lookup_result(CB_SUCCESS
);
763 mapping
= cbfs_map(TEST_DATA_2_FILENAME
, &size_out
);
764 assert_ptr_equal(mapping
, &s
->cbfs_buf
[be32_to_cpu(f
->header
.offset
)]);
765 assert_int_equal(size_out
, TEST_DATA_2_SIZE
);
768 static void test_cbfs_attributes_offset_cut_off_at_data(void **state
)
772 struct cbfs_test_state
*s
= *state
;
773 struct cbfs_test_file
*f
;
775 /* Require attributes for this test */
776 assert_true(be32_to_cpu(test_file_2
.header
.attributes_offset
) != 0);
777 memcpy(s
->cbfs_buf
, &test_file_2
, sizeof(test_file_2
));
778 f
= (struct cbfs_test_file
*)s
->cbfs_buf
;
779 f
->header
.attributes_offset
= cpu_to_be32(sizeof(struct cbfs_file
) + FILENAME_SIZE
780 + offsetof(struct cbfs_file_attribute
, data
));
782 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
784 /* No attributes will be found, because attributes_offset value is too big to cover
785 cbfs_file_attribute tag and length. Compression attribute of ths file will not be
786 found, and that is why there is no need to call expect_value(ulzma).
787 However, file will be found, because the offset is correct. */
789 expect_lookup_result(CB_SUCCESS
);
790 mapping
= cbfs_map(TEST_DATA_2_FILENAME
, &size_out
);
791 assert_ptr_equal(mapping
, &s
->cbfs_buf
[be32_to_cpu(f
->header
.offset
)]);
792 assert_int_equal(size_out
, TEST_DATA_2_SIZE
);
795 static void test_cbfs_attributes_offset_smaller_than_file_struct(void **state
)
799 struct cbfs_test_state
*s
= *state
;
800 struct cbfs_test_file
*f
;
802 assert_true(be32_to_cpu(test_file_2
.header
.attributes_offset
) != 0);
803 memcpy(s
->cbfs_buf
, &test_file_2
, sizeof(test_file_2
));
804 f
= (struct cbfs_test_file
*)s
->cbfs_buf
;
805 f
->header
.attributes_offset
= cpu_to_be32(sizeof(struct cbfs_file
) / 2);
807 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
810 expect_lookup_result(CB_CBFS_NOT_FOUND
);
811 mapping
= cbfs_map(TEST_DATA_2_FILENAME
, &size_out
);
812 assert_null(mapping
);
815 static void test_cbfs_offset_smaller_than_header_size(void **state
)
819 struct cbfs_test_state
*s
= *state
;
820 struct cbfs_test_file
*f
;
822 assert_true(be32_to_cpu(test_file_int_1
.header
.attributes_offset
) == 0);
823 memcpy(s
->cbfs_buf
, &test_file_int_1
, sizeof(test_file_int_1
));
824 f
= (struct cbfs_test_file
*)s
->cbfs_buf
;
825 f
->header
.offset
= cpu_to_be32(sizeof(struct cbfs_file
) / 2);
827 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
830 expect_lookup_result(CB_CBFS_NOT_FOUND
);
831 mapping
= cbfs_map(TEST_DATA_INT_1_FILENAME
, &size_out
);
832 assert_null(mapping
);
835 static void test_cbfs_attributes_offset_is_zero(void **state
)
839 struct cbfs_test_state
*s
= *state
;
841 assert_true(be32_to_cpu(test_file_int_1
.header
.attributes_offset
) == 0);
842 memcpy(s
->cbfs_buf
, &test_file_int_1
, sizeof(test_file_int_1
));
844 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
847 expect_lookup_result(CB_SUCCESS
);
848 mapping
= cbfs_map(TEST_DATA_INT_1_FILENAME
, &size_out
);
849 assert_int_equal(TEST_DATA_INT_1_SIZE
, size_out
);
850 assert_ptr_equal(mapping
, &s
->cbfs_buf
[be32_to_cpu(test_file_int_1
.header
.offset
)]);
853 static void test_cbfs_offset_is_zero(void **state
)
857 struct cbfs_test_state
*s
= *state
;
858 struct cbfs_test_file
*f
;
860 assert_true(be32_to_cpu(test_file_int_1
.header
.attributes_offset
) == 0);
861 memcpy(s
->cbfs_buf
, &test_file_int_1
, sizeof(test_file_int_1
));
862 f
= (struct cbfs_test_file
*)s
->cbfs_buf
;
863 f
->header
.offset
= cpu_to_be32(0);
865 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
868 expect_lookup_result(CB_CBFS_NOT_FOUND
);
869 mapping
= cbfs_map(TEST_DATA_INT_1_FILENAME
, &size_out
);
870 assert_null(mapping
);
873 static void test_cbfs_attributes_too_large(void **state
)
877 struct cbfs_test_state
*s
= *state
;
878 struct cbfs_test_file
*f
;
880 assert_true(be32_to_cpu(test_file_2
.header
.attributes_offset
) != 0);
881 memcpy(s
->cbfs_buf
, &test_file_2
, sizeof(test_file_2
));
882 f
= (struct cbfs_test_file
*)s
->cbfs_buf
;
883 /* Offset determines size of header and attributes. CBFS module uses cbfs_mdata union to
884 store it, so offset (thus attributes) bigger than it should cause an error in the
887 cpu_to_be32(be32_to_cpu(f
->header
.offset
) + sizeof(union cbfs_mdata
));
889 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
892 expect_lookup_result(CB_CBFS_NOT_FOUND
);
893 mapping
= cbfs_map(TEST_DATA_2_FILENAME
, &size_out
);
894 assert_null(mapping
);
897 /* Requires cbfs_test_state.ex.file_length to be set */
898 static void test_cbfs_file_length(void **state
)
902 struct cbfs_test_state
*s
= *state
;
903 struct cbfs_test_file
*f
;
905 assert_true(be32_to_cpu(test_file_1
.header
.attributes_offset
) == 0);
906 memcpy(s
->cbfs_buf
, &test_file_1
, sizeof(test_file_1
));
907 f
= (struct cbfs_test_file
*)s
->cbfs_buf
;
908 f
->header
.len
= cpu_to_be32(s
->ex
.file_length
);
910 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
913 expect_lookup_result(CB_CBFS_NOT_FOUND
);
914 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
915 assert_null(mapping
);
918 static void test_cbfs_attributes_offset_uint32_max(void **state
)
922 struct cbfs_test_state
*s
= *state
;
923 struct cbfs_test_file
*f
;
925 assert_true(be32_to_cpu(test_file_1
.header
.attributes_offset
) == 0);
926 memcpy(s
->cbfs_buf
, &test_file_1
, sizeof(test_file_1
));
927 f
= (struct cbfs_test_file
*)s
->cbfs_buf
;
928 f
->header
.attributes_offset
= cpu_to_be32(UINT32_MAX
);
930 assert_int_equal(CB_SUCCESS
, cbfs_init_boot_device(&cbd
, NULL
));
933 expect_lookup_result(CB_CBFS_NOT_FOUND
);
934 mapping
= cbfs_map(TEST_DATA_1_FILENAME
, &size_out
);
935 assert_null(mapping
);
938 #define CBFS_LOOKUP_NAME_SETUP_PRESTATE_COMMON_TEST(name, test_fn, setup_fn, prestate) \
940 (name), (test_fn), (setup_fn), teardown_test_cbfs, (prestate), \
943 #define CBFS_LOOKUP_NAME_PRESTATE_TEST(name, test_fn, prestate) \
945 CBFS_LOOKUP_NAME_SETUP_PRESTATE_COMMON_TEST( \
946 ("aligned, " name), (test_fn), setup_test_cbfs_aligned, (prestate)), \
947 CBFS_LOOKUP_NAME_SETUP_PRESTATE_COMMON_TEST(("unaligned, " name), (test_fn), \
948 setup_test_cbfs_unaligned, \
951 #define CBFS_LOOKUP_TEST(test_fn) CBFS_LOOKUP_NAME_PRESTATE_TEST(#test_fn, test_fn, NULL)
953 #define CBFS_LOOKUP_TEST_FAIL_BEYOND_RDEV(name, file_len, lookup_res) \
954 EMPTY_WRAP(CBFS_LOOKUP_NAME_PRESTATE_TEST(name ", CBFS_TYPE_RAW", \
955 test_cbfs_fail_beyond_rdev, \
956 (&(struct cbfs_test_state_ex){ \
957 .file_type = CBFS_TYPE_RAW, \
958 .file_length = (file_len), \
959 .lookup_result = (lookup_res), \
961 CBFS_LOOKUP_NAME_PRESTATE_TEST(name ", CBFS_TYPE_NULL", \
962 test_cbfs_fail_beyond_rdev, \
963 (&(struct cbfs_test_state_ex){ \
964 .file_type = CBFS_TYPE_NULL, \
965 .file_length = (file_len), \
966 .lookup_result = (lookup_res), \
969 #define CBFS_LOOKUP_TEST_FILE_LENGTH(file_len) \
970 CBFS_LOOKUP_NAME_PRESTATE_TEST("test_cbfs_file_length, " #file_len, \
971 test_cbfs_file_length, \
972 (&(struct cbfs_test_state_ex){ \
973 .file_length = (file_len), \
978 const struct CMUnitTest cbfs_lookup_aligned_and_unaligned_tests
[] = {
979 CBFS_LOOKUP_TEST(test_cbfs_map
),
980 CBFS_LOOKUP_TEST(test_cbfs_cbmem_alloc
),
982 CBFS_LOOKUP_TEST(test_cbfs_image_not_aligned
),
983 CBFS_LOOKUP_TEST(test_cbfs_file_not_aligned
),
985 CBFS_LOOKUP_TEST(test_cbfs_garbage_data_before_aligned_file
),
986 CBFS_LOOKUP_TEST(test_cbfs_garbage_data_before_unaligned_file
),
988 CBFS_LOOKUP_TEST(test_cbfs_file_bigger_than_rdev
),
991 CBFS_LOOKUP_TEST_FAIL_BEYOND_RDEV("File fitting in rdev",
992 sizeof(struct cbfs_test_file
), CB_SUCCESS
),
994 /* Attributes beyond rdev */
995 CBFS_LOOKUP_TEST_FAIL_BEYOND_RDEV(
996 "Attributes and data beyond rdev",
997 offsetof(struct cbfs_test_file
, attrs_and_data
), CB_CBFS_NOT_FOUND
),
999 /* Attributes except tag beyond rdev */
1000 CBFS_LOOKUP_TEST_FAIL_BEYOND_RDEV(
1001 "Attributes except tag beyond rdev",
1002 offsetof(struct cbfs_test_file
, attrs_and_data
)
1003 - offsetof(struct cbfs_file_attribute
, len
),
1006 /* Attributes except tag and len beyond rdev */
1007 CBFS_LOOKUP_TEST_FAIL_BEYOND_RDEV(
1008 "Attributes except tag and len beyond rdev",
1009 offsetof(struct cbfs_test_file
, attrs_and_data
)
1010 - offsetof(struct cbfs_file_attribute
, data
),
1013 /* Filename beyond rdev */
1014 CBFS_LOOKUP_TEST_FAIL_BEYOND_RDEV("Filename beyond rdev",
1015 offsetof(struct cbfs_test_file
, filename
),
1018 /* Part of filename beyond rdev */
1019 CBFS_LOOKUP_TEST_FAIL_BEYOND_RDEV("Part of filename beyond rdev",
1020 offsetof(struct cbfs_test_file
, filename
)
1021 + FILENAME_SIZE
/ 2,
1024 /* Part of cbfs_file struct beyond rdev */
1025 CBFS_LOOKUP_TEST_FAIL_BEYOND_RDEV("Part of cbfs_file struct beyond rdev",
1026 offsetof(struct cbfs_test_file
, filename
) / 2,
1029 CBFS_LOOKUP_TEST(test_cbfs_unaligned_file_in_the_middle
),
1030 CBFS_LOOKUP_TEST(test_cbfs_overlapping_files
),
1031 CBFS_LOOKUP_TEST(test_cbfs_incorrect_file_in_the_middle
),
1033 CBFS_LOOKUP_TEST(test_cbfs_two_files_with_same_name
),
1035 CBFS_LOOKUP_TEST(test_cbfs_filename_not_terminated
),
1036 CBFS_LOOKUP_TEST(test_cbfs_filename_terminated_but_too_long
),
1038 CBFS_LOOKUP_TEST(test_cbfs_attributes_offset_larger_than_offset
),
1039 CBFS_LOOKUP_TEST(test_cbfs_attributes_offset_cut_off_at_len
),
1040 CBFS_LOOKUP_TEST(test_cbfs_attributes_offset_cut_off_at_data
),
1042 CBFS_LOOKUP_TEST(test_cbfs_attributes_offset_smaller_than_file_struct
),
1044 CBFS_LOOKUP_TEST(test_cbfs_offset_smaller_than_header_size
),
1045 CBFS_LOOKUP_TEST(test_cbfs_attributes_offset_is_zero
),
1046 CBFS_LOOKUP_TEST(test_cbfs_offset_is_zero
),
1047 CBFS_LOOKUP_TEST(test_cbfs_attributes_too_large
),
1049 CBFS_LOOKUP_TEST_FILE_LENGTH(UINT32_MAX
),
1050 CBFS_LOOKUP_TEST_FILE_LENGTH(UINT32_MAX
1051 - offsetof(struct cbfs_test_file
, attrs_and_data
)),
1052 CBFS_LOOKUP_TEST_FILE_LENGTH(
1053 UINT32_MAX
- offsetof(struct cbfs_test_file
, attrs_and_data
) / 2),
1054 CBFS_LOOKUP_TEST_FILE_LENGTH(
1055 UINT32_MAX
- offsetof(struct cbfs_test_file
, attrs_and_data
) * 2),
1056 CBFS_LOOKUP_TEST_FILE_LENGTH(
1057 UINT32_MAX
- offsetof(struct cbfs_test_file
, attrs_and_data
) - 1),
1058 CBFS_LOOKUP_TEST_FILE_LENGTH(
1059 UINT32_MAX
- offsetof(struct cbfs_test_file
, attrs_and_data
) + 1),
1061 CBFS_LOOKUP_TEST(test_cbfs_attributes_offset_uint32_max
),
1064 return cb_run_group_tests(cbfs_lookup_aligned_and_unaligned_tests
, NULL
, NULL
);