xref: /aosp_15_r20/external/coreboot/tests/lib/cbfs-lookup-test.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <cbfs.h>
5 #include <commonlib/bsd/cbfs_mdata.h>
6 #include <commonlib/bsd/cbfs_private.h>
7 #include <commonlib/region.h>
8 #include <string.h>
9 #include <tests/lib/cbfs_util.h>
10 #include <tests/test.h>
11 
12 
13 static struct cbfs_boot_device cbd;
14 
15 static u8 aligned_cbfs_buffer[(sizeof(struct cbfs_test_file) + CBFS_ALIGNMENT) * 10] __aligned(
16 	CBFS_ALIGNMENT);
17 
18 static u8 *unaligned_cbfs_buffer = &aligned_cbfs_buffer[3];
19 static uintptr_t unaligned_cbfs_buffer_size = sizeof(aligned_cbfs_buffer) - 3;
20 
21 static u8 cbfs_mcache[TEST_MCACHE_SIZE] __aligned(CBFS_MCACHE_ALIGNMENT);
22 
23 /* Add files to CBFS buffer. NULL in files list equals to one CBFS_ALIGNMENT of spacing. */
create_cbfs(const struct cbfs_test_file * files[],const size_t nfiles,u8 * buffer,const size_t buffer_size)24 static int create_cbfs(const struct cbfs_test_file *files[], const size_t nfiles, u8 *buffer,
25 		       const size_t buffer_size)
26 {
27 	u8 *data_ptr = buffer;
28 	size_t file_size = 0;
29 	memset(buffer, 0, buffer_size);
30 
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]);
35 		} else {
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);
40 		}
41 
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)];
45 	}
46 
47 	return 0;
48 }
49 
50 /* Mocks */
51 
cbfs_get_boot_device(bool force_ro)52 const struct cbfs_boot_device *cbfs_get_boot_device(bool force_ro)
53 {
54 	return &cbd;
55 }
56 
ulzman(const void * src,size_t srcn,void * dst,size_t dstn)57 size_t ulzman(const void *src, size_t srcn, void *dst, size_t dstn)
58 {
59 	check_expected(srcn);
60 	check_expected(dstn);
61 	memcpy(dst, src, dstn);
62 	return dstn;
63 }
64 
ulz4fn(const void * src,size_t srcn,void * dst,size_t dstn)65 size_t ulz4fn(const void *src, size_t srcn, void *dst, size_t dstn)
66 {
67 	check_expected(srcn);
68 	check_expected(dstn);
69 	memcpy(dst, src, dstn);
70 	return dstn;
71 }
72 
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);
76 
cbfs_lookup(cbfs_dev_t dev,const char * name,union cbfs_mdata * mdata_out,size_t * data_offset_out,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)
79 {
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));
83 	return err;
84 }
85 
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);
89 
cbfs_mcache_lookup(const void * mcache,size_t mcache_size,const char * name,union cbfs_mdata * mdata_out,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)
92 {
93 	const enum cb_err err = __real_cbfs_mcache_lookup(mcache, mcache_size, name, mdata_out,
94 						       data_offset_out);
95 	assert_int_equal(err, mock_type(enum cb_err));
96 	return err;
97 }
98 
99 extern void *__real_mem_pool_alloc(struct mem_pool *mp, size_t sz);
100 
mem_pool_alloc(struct mem_pool * mp,size_t sz)101 void *mem_pool_alloc(struct mem_pool *mp, size_t sz)
102 {
103 	check_expected(sz);
104 	assert_ptr_equal(mp, &cbfs_cache);
105 	return __real_mem_pool_alloc(mp, sz);
106 }
107 
108 extern void __real_mem_pool_free(struct mem_pool *mp, void *p);
109 
mem_pool_free(struct mem_pool * mp,void * p)110 void mem_pool_free(struct mem_pool *mp, void *p)
111 {
112 	check_expected(p);
113 	assert_ptr_equal(mp, &cbfs_cache);
114 	return __real_mem_pool_free(mp, p);
115 }
116 
117 static u8 cbmem_test_buf[2 * MiB];
118 
cbmem_add(u32 id,u64 size)119 void *cbmem_add(u32 id, u64 size)
120 {
121 	check_expected(id);
122 	check_expected(size);
123 	return cbmem_test_buf;
124 }
125 
126 /* Setup, teardown and utils */
127 
128 struct cbfs_test_state_ex {
129 	u32 file_type;
130 	u32 file_length;
131 	enum cb_err lookup_result;
132 };
133 
134 struct cbfs_test_state {
135 	u8 *cbfs_buf;
136 	size_t cbfs_size;
137 
138 	/* Optionals */
139 	struct cbfs_test_state_ex ex;
140 };
141 
setup_test_cbfs_aligned(void ** state)142 static int setup_test_cbfs_aligned(void **state)
143 {
144 	struct cbfs_test_state *s = malloc(sizeof(struct cbfs_test_state));
145 
146 	if (!s)
147 		return 1;
148 	s->cbfs_buf = aligned_cbfs_buffer;
149 	s->cbfs_size = sizeof(aligned_cbfs_buffer);
150 	memset(&s->ex, 0, sizeof(s->ex));
151 
152 	/* Prestate */
153 	if (*state != NULL)
154 		s->ex = *((struct cbfs_test_state_ex *)*state);
155 
156 	*state = s;
157 
158 	rdev_chain_mem(&cbd.rdev, aligned_cbfs_buffer, sizeof(aligned_cbfs_buffer));
159 	memset(aligned_cbfs_buffer, 0, sizeof(aligned_cbfs_buffer));
160 
161 	cbd.mcache = cbfs_mcache;
162 	cbd.mcache_size = TEST_MCACHE_SIZE;
163 
164 	return 0;
165 }
166 
setup_test_cbfs_unaligned(void ** state)167 static int setup_test_cbfs_unaligned(void **state)
168 {
169 	struct cbfs_test_state *s = malloc(sizeof(struct cbfs_test_state));
170 
171 	if (!s)
172 		return 1;
173 	s->cbfs_buf = unaligned_cbfs_buffer;
174 	s->cbfs_size = unaligned_cbfs_buffer_size;
175 	memset(&s->ex, 0, sizeof(s->ex));
176 
177 	/* Prestate */
178 	if (*state != NULL)
179 		s->ex = *((struct cbfs_test_state_ex *)*state);
180 
181 	*state = s;
182 
183 	rdev_chain_mem(&cbd.rdev, unaligned_cbfs_buffer, unaligned_cbfs_buffer_size);
184 	memset(unaligned_cbfs_buffer, 0, unaligned_cbfs_buffer_size);
185 
186 	cbd.mcache = cbfs_mcache;
187 	cbd.mcache_size = TEST_MCACHE_SIZE;
188 
189 	return 0;
190 }
191 
teardown_test_cbfs(void ** state)192 static int teardown_test_cbfs(void **state)
193 {
194 	free(*state);
195 	memset(&cbd, 0, sizeof(cbd));
196 	return 0;
197 }
198 
199 /* Utils */
200 
expect_lookup_result(enum cb_err res)201 static void expect_lookup_result(enum cb_err res)
202 {
203 	if (CONFIG(NO_CBFS_MCACHE))
204 		will_return(cbfs_lookup, (res));
205 	else
206 		will_return(cbfs_mcache_lookup, (res));
207 }
208 
209 /* Tests */
210 
211 /* Test case for cbfs_map() function. Validate file searching in the correct CBFS */
test_cbfs_map(void ** state)212 static void test_cbfs_map(void **state)
213 {
214 	void *mapping;
215 	size_t size_out;
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,
220 	};
221 	assert_int_equal(
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));
224 
225 	/* Existing files */
226 	size_out = 0;
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);
232 
233 	expect_value(mem_pool_free, p, mapping);
234 	cbfs_unmap(mapping);
235 
236 	size_out = 0;
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);
245 
246 	expect_value(mem_pool_free, p, mapping);
247 	cbfs_unmap(mapping);
248 
249 	size_out = 0;
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);
255 
256 	expect_value(mem_pool_free, p, mapping);
257 	cbfs_unmap(mapping);
258 
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);
264 
265 	expect_value(mem_pool_free, p, mapping);
266 	cbfs_unmap(mapping);
267 
268 	size_out = 0;
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);
277 
278 	expect_value(mem_pool_free, p, mapping);
279 	cbfs_unmap(mapping);
280 
281 	/* Nonexistent files */
282 	size_out = 0;
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);
287 
288 	size_out = 0;
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);
293 }
294 
test_cbfs_cbmem_alloc(void ** state)295 static void test_cbfs_cbmem_alloc(void **state)
296 {
297 	void *mapping;
298 	size_t size_out;
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,
303 	};
304 	assert_int_equal(
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));
307 
308 	/* Existing files */
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);
316 
317 	expect_value(mem_pool_free, p, mapping);
318 	cbfs_unmap(mapping);
319 
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);
329 
330 	expect_value(mem_pool_free, p, mapping);
331 	cbfs_unmap(mapping);
332 
333 	size_out = 0;
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);
341 
342 	expect_value(mem_pool_free, p, mapping);
343 	cbfs_unmap(mapping);
344 
345 	size_out = 0;
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);
353 
354 	expect_value(mem_pool_free, p, mapping);
355 	cbfs_unmap(mapping);
356 
357 	size_out = 0;
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);
367 
368 	expect_value(mem_pool_free, p, mapping);
369 	cbfs_unmap(mapping);
370 
371 	/* Nonexistent files */
372 	size_out = 0;
373 	expect_lookup_result(CB_CBFS_NOT_FOUND);
374 	mapping = cbfs_cbmem_alloc("nothing-file", 0x0301, &size_out);
375 	assert_null(mapping);
376 
377 	size_out = 0;
378 	expect_lookup_result(CB_CBFS_NOT_FOUND);
379 	mapping = cbfs_cbmem_alloc("", 0x0302, &size_out);
380 	assert_null(mapping);
381 }
382 
test_cbfs_image_not_aligned(void ** state)383 static void test_cbfs_image_not_aligned(void **state)
384 {
385 	void *mapping;
386 	size_t size_out;
387 	struct cbfs_test_state *s = *state;
388 	const struct cbfs_test_file *cbfs_files[] = {
389 		&test_file_int_1,
390 		&test_file_2,
391 	};
392 	assert_int_equal(0, create_cbfs(cbfs_files, ARRAY_SIZE(cbfs_files), &s->cbfs_buf[5],
393 					s->cbfs_size - 5));
394 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
395 
396 	size_out = 0;
397 	expect_lookup_result(CB_CBFS_NOT_FOUND);
398 	mapping = cbfs_map(TEST_DATA_INT_1_FILENAME, &size_out);
399 	assert_null(mapping);
400 
401 	size_out = 0;
402 	expect_lookup_result(CB_CBFS_NOT_FOUND);
403 	mapping = cbfs_map(TEST_DATA_2_FILENAME, &size_out);
404 	assert_null(mapping);
405 }
406 
test_cbfs_file_not_aligned(void ** state)407 static void test_cbfs_file_not_aligned(void **state)
408 {
409 	void *mapping;
410 	size_t size_out;
411 	struct cbfs_test_state *s = *state;
412 
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));
417 
418 	size_out = 0;
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)]);
423 
424 	size_out = 0;
425 	expect_lookup_result(CB_CBFS_NOT_FOUND);
426 	mapping = cbfs_map(TEST_DATA_1_FILENAME, &size_out);
427 	assert_null(mapping);
428 }
429 
test_cbfs_garbage_data_before_aligned_file(void ** state)430 static void test_cbfs_garbage_data_before_aligned_file(void **state)
431 {
432 	void *mapping;
433 	size_t size_out;
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;
438 
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));
443 
444 	size_out = 0;
445 	expect_lookup_result(CB_SUCCESS);
446 	mapping = cbfs_map(TEST_DATA_INT_2_FILENAME, &size_out);
447 	assert_ptr_equal(
448 		mapping,
449 		&s->cbfs_buf[garbage_sz + offsetof(struct cbfs_test_file, attrs_and_data)]);
450 }
451 
test_cbfs_garbage_data_before_unaligned_file(void ** state)452 static void test_cbfs_garbage_data_before_unaligned_file(void **state)
453 {
454 	void *mapping;
455 	size_t size_out;
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;
460 
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));
465 
466 	size_out = 0;
467 	expect_lookup_result(CB_CBFS_NOT_FOUND);
468 	mapping = cbfs_map(TEST_DATA_INT_2_FILENAME, &size_out);
469 	assert_null(mapping);
470 }
471 
test_cbfs_file_bigger_than_rdev(void ** state)472 static void test_cbfs_file_bigger_than_rdev(void **state)
473 {
474 	void *mapping;
475 	size_t size_out;
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);
482 
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));
486 
487 	size_out = 0;
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);
493 }
494 
test_cbfs_fail_beyond_rdev(void ** state)495 static void test_cbfs_fail_beyond_rdev(void **state)
496 {
497 	void *mapping;
498 	size_t size_out;
499 	struct cbfs_test_state *s = *state;
500 	size_t second_file_start = ALIGN_UP(sizeof(test_file_1), CBFS_ALIGNMENT);
501 
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;
507 
508 	/* CBFS initialization should not fail if last file is not valid */
509 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
510 
511 	size_out = 0;
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);
516 
517 	size_out = 0;
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);
522 	}
523 	expect_lookup_result(s->ex.lookup_result);
524 	cbfs_map(TEST_DATA_2_FILENAME, &size_out);
525 }
526 
test_cbfs_unaligned_file_in_the_middle(void ** state)527 static void test_cbfs_unaligned_file_in_the_middle(void **state)
528 {
529 	void *mapping;
530 	size_t size_out;
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);
535 
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));
539 
540 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
541 
542 	size_out = 0;
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));
547 
548 	size_out = 0;
549 	expect_lookup_result(CB_CBFS_NOT_FOUND);
550 	mapping = cbfs_map(TEST_DATA_INT_1_FILENAME, &size_out);
551 	assert_null(mapping);
552 
553 	size_out = 0;
554 	expect_lookup_result(CB_SUCCESS);
555 	mapping = cbfs_map(TEST_DATA_INT_2_FILENAME, &size_out);
556 	assert_ptr_equal(
557 		mapping,
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));
560 }
561 
test_cbfs_overlapping_files(void ** state)562 static void test_cbfs_overlapping_files(void **state)
563 {
564 	void *mapping;
565 	size_t size_out;
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;
573 
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);
580 
581 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
582 
583 	size_out = 0;
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));
588 
589 	size_out = 0;
590 	expect_lookup_result(CB_SUCCESS);
591 	mapping = cbfs_map(TEST_DATA_INT_1_FILENAME, &size_out);
592 	assert_ptr_equal(
593 		mapping,
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);
596 
597 	size_out = 0;
598 	expect_lookup_result(CB_CBFS_NOT_FOUND);
599 	mapping = cbfs_map(TEST_DATA_INT_2_FILENAME, &size_out);
600 	assert_null(mapping);
601 }
602 
test_cbfs_incorrect_file_in_the_middle(void ** state)603 static void test_cbfs_incorrect_file_in_the_middle(void **state)
604 {
605 	void *mapping;
606 	size_t size_out;
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;
612 
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);
619 
620 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
621 
622 	size_out = 0;
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));
627 
628 	size_out = 0;
629 	expect_lookup_result(CB_CBFS_NOT_FOUND);
630 	mapping = cbfs_map(TEST_DATA_INT_1_FILENAME, &size_out);
631 	assert_null(mapping);
632 
633 	size_out = 0;
634 	expect_lookup_result(CB_SUCCESS);
635 	mapping = cbfs_map(TEST_DATA_INT_2_FILENAME, &size_out);
636 	assert_ptr_equal(
637 		mapping,
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));
640 }
641 
test_cbfs_two_files_with_same_name(void ** state)642 static void test_cbfs_two_files_with_same_name(void **state)
643 {
644 	void *mapping;
645 	size_t size_out;
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);
650 
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));
655 
656 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
657 
658 	size_out = 0;
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));
663 
664 	size_out = 0;
665 	expect_lookup_result(CB_SUCCESS);
666 	mapping = cbfs_map(TEST_DATA_INT_1_FILENAME, &size_out);
667 	assert_ptr_equal(
668 		mapping,
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));
671 }
672 
test_cbfs_filename_not_terminated(void ** state)673 static void test_cbfs_filename_not_terminated(void **state)
674 {
675 	void *mapping;
676 	size_t size_out;
677 	struct cbfs_test_state *s = *state;
678 	struct cbfs_test_file *f;
679 	const char fname[] = "abcdefghijklmnop";
680 
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));
685 
686 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
687 
688 	size_out = 0;
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);
693 }
694 
test_cbfs_filename_terminated_but_too_long(void ** state)695 static void test_cbfs_filename_terminated_but_too_long(void **state)
696 {
697 	void *mapping;
698 	size_t size_out;
699 	struct cbfs_test_state *s = *state;
700 	struct cbfs_test_file *f;
701 
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));
708 
709 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
710 
711 	size_out = 0;
712 	expect_lookup_result(CB_CBFS_NOT_FOUND);
713 	mapping = cbfs_map(TEST_DATA_1_FILENAME, &size_out);
714 	assert_null(mapping);
715 }
716 
test_cbfs_attributes_offset_larger_than_offset(void ** state)717 static void test_cbfs_attributes_offset_larger_than_offset(void **state)
718 {
719 	void *mapping;
720 	size_t size_out;
721 	struct cbfs_test_state *s = *state;
722 	struct cbfs_test_file *f;
723 
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);
731 
732 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
733 
734 	size_out = 0;
735 	expect_lookup_result(CB_CBFS_NOT_FOUND);
736 	mapping = cbfs_map(TEST_DATA_2_FILENAME, &size_out);
737 	assert_null(mapping);
738 }
739 
test_cbfs_attributes_offset_cut_off_at_len(void ** state)740 static void test_cbfs_attributes_offset_cut_off_at_len(void **state)
741 {
742 	void *mapping;
743 	size_t size_out;
744 	struct cbfs_test_state *s = *state;
745 	struct cbfs_test_file *f;
746 
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));
754 
755 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
756 
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. */
761 	size_out = 0;
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);
766 }
767 
test_cbfs_attributes_offset_cut_off_at_data(void ** state)768 static void test_cbfs_attributes_offset_cut_off_at_data(void **state)
769 {
770 	void *mapping;
771 	size_t size_out;
772 	struct cbfs_test_state *s = *state;
773 	struct cbfs_test_file *f;
774 
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));
781 
782 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
783 
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. */
788 	size_out = 0;
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);
793 }
794 
test_cbfs_attributes_offset_smaller_than_file_struct(void ** state)795 static void test_cbfs_attributes_offset_smaller_than_file_struct(void **state)
796 {
797 	void *mapping;
798 	size_t size_out;
799 	struct cbfs_test_state *s = *state;
800 	struct cbfs_test_file *f;
801 
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);
806 
807 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
808 
809 	size_out = 0;
810 	expect_lookup_result(CB_CBFS_NOT_FOUND);
811 	mapping = cbfs_map(TEST_DATA_2_FILENAME, &size_out);
812 	assert_null(mapping);
813 }
814 
test_cbfs_offset_smaller_than_header_size(void ** state)815 static void test_cbfs_offset_smaller_than_header_size(void **state)
816 {
817 	void *mapping;
818 	size_t size_out;
819 	struct cbfs_test_state *s = *state;
820 	struct cbfs_test_file *f;
821 
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);
826 
827 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
828 
829 	size_out = 0;
830 	expect_lookup_result(CB_CBFS_NOT_FOUND);
831 	mapping = cbfs_map(TEST_DATA_INT_1_FILENAME, &size_out);
832 	assert_null(mapping);
833 }
834 
test_cbfs_attributes_offset_is_zero(void ** state)835 static void test_cbfs_attributes_offset_is_zero(void **state)
836 {
837 	void *mapping;
838 	size_t size_out;
839 	struct cbfs_test_state *s = *state;
840 
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));
843 
844 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
845 
846 	size_out = 0;
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)]);
851 }
852 
test_cbfs_offset_is_zero(void ** state)853 static void test_cbfs_offset_is_zero(void **state)
854 {
855 	void *mapping;
856 	size_t size_out;
857 	struct cbfs_test_state *s = *state;
858 	struct cbfs_test_file *f;
859 
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);
864 
865 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
866 
867 	size_out = 0;
868 	expect_lookup_result(CB_CBFS_NOT_FOUND);
869 	mapping = cbfs_map(TEST_DATA_INT_1_FILENAME, &size_out);
870 	assert_null(mapping);
871 }
872 
test_cbfs_attributes_too_large(void ** state)873 static void test_cbfs_attributes_too_large(void **state)
874 {
875 	void *mapping;
876 	size_t size_out;
877 	struct cbfs_test_state *s = *state;
878 	struct cbfs_test_file *f;
879 
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
885 	   lookup code. */
886 	f->header.offset =
887 		cpu_to_be32(be32_to_cpu(f->header.offset) + sizeof(union cbfs_mdata));
888 
889 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
890 
891 	size_out = 0;
892 	expect_lookup_result(CB_CBFS_NOT_FOUND);
893 	mapping = cbfs_map(TEST_DATA_2_FILENAME, &size_out);
894 	assert_null(mapping);
895 }
896 
897 /* Requires cbfs_test_state.ex.file_length to be set */
test_cbfs_file_length(void ** state)898 static void test_cbfs_file_length(void **state)
899 {
900 	void *mapping;
901 	size_t size_out;
902 	struct cbfs_test_state *s = *state;
903 	struct cbfs_test_file *f;
904 
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);
909 
910 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
911 
912 	size_out = 0;
913 	expect_lookup_result(CB_CBFS_NOT_FOUND);
914 	mapping = cbfs_map(TEST_DATA_1_FILENAME, &size_out);
915 	assert_null(mapping);
916 }
917 
test_cbfs_attributes_offset_uint32_max(void ** state)918 static void test_cbfs_attributes_offset_uint32_max(void **state)
919 {
920 	void *mapping;
921 	size_t size_out;
922 	struct cbfs_test_state *s = *state;
923 	struct cbfs_test_file *f;
924 
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);
929 
930 	assert_int_equal(CB_SUCCESS, cbfs_init_boot_device(&cbd, NULL));
931 
932 	size_out = 0;
933 	expect_lookup_result(CB_CBFS_NOT_FOUND);
934 	mapping = cbfs_map(TEST_DATA_1_FILENAME, &size_out);
935 	assert_null(mapping);
936 }
937 
938 #define CBFS_LOOKUP_NAME_SETUP_PRESTATE_COMMON_TEST(name, test_fn, setup_fn, prestate)         \
939 	{                                                                                      \
940 		(name), (test_fn), (setup_fn), teardown_test_cbfs, (prestate),                 \
941 	}
942 
943 #define CBFS_LOOKUP_NAME_PRESTATE_TEST(name, test_fn, prestate)                                \
944 	EMPTY_WRAP(                                                                            \
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,         \
949 							    (prestate)))
950 
951 #define CBFS_LOOKUP_TEST(test_fn) CBFS_LOOKUP_NAME_PRESTATE_TEST(#test_fn, test_fn, NULL)
952 
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),       \
960 						  })),                                         \
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),       \
967 						  })))
968 
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),                      \
974 				       }))
975 
main(void)976 int main(void)
977 {
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),
981 
982 		CBFS_LOOKUP_TEST(test_cbfs_image_not_aligned),
983 		CBFS_LOOKUP_TEST(test_cbfs_file_not_aligned),
984 
985 		CBFS_LOOKUP_TEST(test_cbfs_garbage_data_before_aligned_file),
986 		CBFS_LOOKUP_TEST(test_cbfs_garbage_data_before_unaligned_file),
987 
988 		CBFS_LOOKUP_TEST(test_cbfs_file_bigger_than_rdev),
989 
990 		/* Correct file */
991 		CBFS_LOOKUP_TEST_FAIL_BEYOND_RDEV("File fitting in rdev",
992 						  sizeof(struct cbfs_test_file), CB_SUCCESS),
993 
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),
998 
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),
1004 			CB_CBFS_NOT_FOUND),
1005 
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),
1011 			CB_CBFS_NOT_FOUND),
1012 
1013 		/* Filename beyond rdev */
1014 		CBFS_LOOKUP_TEST_FAIL_BEYOND_RDEV("Filename beyond rdev",
1015 						  offsetof(struct cbfs_test_file, filename),
1016 						  CB_CBFS_NOT_FOUND),
1017 
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,
1022 						  CB_CBFS_NOT_FOUND),
1023 
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,
1027 						  CB_CBFS_NOT_FOUND),
1028 
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),
1032 
1033 		CBFS_LOOKUP_TEST(test_cbfs_two_files_with_same_name),
1034 
1035 		CBFS_LOOKUP_TEST(test_cbfs_filename_not_terminated),
1036 		CBFS_LOOKUP_TEST(test_cbfs_filename_terminated_but_too_long),
1037 
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),
1041 
1042 		CBFS_LOOKUP_TEST(test_cbfs_attributes_offset_smaller_than_file_struct),
1043 
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),
1048 
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),
1060 
1061 		CBFS_LOOKUP_TEST(test_cbfs_attributes_offset_uint32_max),
1062 	};
1063 
1064 	return cb_run_group_tests(cbfs_lookup_aligned_and_unaligned_tests, NULL, NULL);
1065 }
1066