1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2018, Google Inc. All rights reserved.
4  */
5 
6 #include <bloblist.h>
7 #include <log.h>
8 #include <mapmem.h>
9 #include <test/test.h>
10 #include <test/ut.h>
11 
12 /* Declare a new bloblist test */
13 #define BLOBLIST_TEST(_name, _flags) \
14 		UNIT_TEST(_name, _flags, bloblist)
15 
16 enum {
17 	TEST_TAG		= BLOBLISTT_U_BOOT_SPL_HANDOFF,
18 	TEST_TAG2		= BLOBLISTT_VBOOT_CTX,
19 	TEST_TAG_MISSING	= 0x10000,
20 
21 	TEST_SIZE		= 10,
22 	TEST_SIZE2		= 20,
23 	TEST_SIZE_LARGE		= 0x3e0,
24 
25 	TEST_ADDR		= CONFIG_BLOBLIST_ADDR,
26 	TEST_BLOBLIST_SIZE	= 0x400,
27 
28 	ERASE_BYTE		= '\xff',
29 };
30 
31 static const char test1_str[] = "the eyes are open";
32 static const char test2_str[] = "the mouth moves";
33 
clear_bloblist(void)34 static struct bloblist_hdr *clear_bloblist(void)
35 {
36 	struct bloblist_hdr *hdr;
37 
38 	/*
39 	 * Clear out any existing bloblist so we have a clean slate. Zero the
40 	 * header so that existing records are removed, but set everything else
41 	 * to 0xff for testing purposes.
42 	 */
43 	hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
44 	memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
45 	memset(hdr, '\0', sizeof(*hdr));
46 
47 	return hdr;
48 }
49 
check_zero(void * data,int size)50 static int check_zero(void *data, int size)
51 {
52 	u8 *ptr;
53 	int i;
54 
55 	for (ptr = data, i = 0; i < size; i++, ptr++) {
56 		if (*ptr)
57 			return -EINVAL;
58 	}
59 
60 	return 0;
61 }
62 
bloblist_test_init(struct unit_test_state * uts)63 static int bloblist_test_init(struct unit_test_state *uts)
64 {
65 	struct bloblist_hdr *hdr;
66 
67 	hdr = clear_bloblist();
68 	ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
69 	ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
70 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
71 	ut_asserteq_ptr(hdr, bloblist_check_magic(TEST_ADDR));
72 	hdr->version++;
73 	ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
74 						     TEST_BLOBLIST_SIZE));
75 
76 	ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0xc, 0, 0));
77 	ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0, 0));
78 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
79 
80 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
81 	ut_assertok(bloblist_finish());
82 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
83 
84 	hdr->magic++;
85 	ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
86 	hdr->magic--;
87 
88 	hdr->flags++;
89 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
90 
91 	return 1;
92 }
93 BLOBLIST_TEST(bloblist_test_init, UFT_BLOBLIST);
94 
bloblist_test_blob(struct unit_test_state * uts)95 static int bloblist_test_blob(struct unit_test_state *uts)
96 {
97 	struct bloblist_hdr *hdr;
98 	struct bloblist_rec *rec, *rec2;
99 	char *data;
100 	int size = 0;
101 
102 	/* At the start there should be no records */
103 	hdr = clear_bloblist();
104 	ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
105 	ut_assertnull(bloblist_get_blob(TEST_TAG, &size));
106 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
107 	ut_asserteq(sizeof(struct bloblist_hdr), bloblist_get_size());
108 	ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_total_size());
109 	ut_asserteq(TEST_ADDR, bloblist_get_base());
110 	ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
111 
112 	/* Add a record and check that we can find it */
113 	data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
114 	rec = (void *)(hdr + 1);
115 	ut_asserteq_addr(rec + 1, data);
116 	data = bloblist_find(TEST_TAG, TEST_SIZE);
117 	ut_asserteq_addr(rec + 1, data);
118 	ut_asserteq_addr(bloblist_get_blob(TEST_TAG, &size), data);
119 	ut_asserteq(size, TEST_SIZE);
120 
121 	/* Check the data is zeroed */
122 	ut_assertok(check_zero(data, TEST_SIZE));
123 
124 	/* Check the 'ensure' method */
125 	ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
126 	ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
127 	rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
128 	ut_assertok(check_zero(data, TEST_SIZE));
129 
130 	/* Check for a non-existent record */
131 	ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
132 	ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
133 	ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
134 
135 	return 0;
136 }
137 BLOBLIST_TEST(bloblist_test_blob, UFT_BLOBLIST);
138 
139 /* Check bloblist_ensure_size_ret() */
bloblist_test_blob_ensure(struct unit_test_state * uts)140 static int bloblist_test_blob_ensure(struct unit_test_state *uts)
141 {
142 	void *data, *data2;
143 	int size;
144 
145 	/* At the start there should be no records */
146 	clear_bloblist();
147 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
148 
149 	/* Test with an empty bloblist */
150 	size = TEST_SIZE;
151 	ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
152 	ut_asserteq(TEST_SIZE, size);
153 	ut_assertok(check_zero(data, TEST_SIZE));
154 
155 	/* Check that we get the same thing again */
156 	ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
157 	ut_asserteq(TEST_SIZE, size);
158 	ut_asserteq_addr(data, data2);
159 
160 	/* Check that the size remains the same */
161 	size = TEST_SIZE2;
162 	ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
163 	ut_asserteq(TEST_SIZE, size);
164 
165 	/* Check running out of space */
166 	size = TEST_SIZE_LARGE;
167 	ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
168 
169 	return 0;
170 }
171 BLOBLIST_TEST(bloblist_test_blob_ensure, UFT_BLOBLIST);
172 
bloblist_test_bad_blob(struct unit_test_state * uts)173 static int bloblist_test_bad_blob(struct unit_test_state *uts)
174 {
175 	struct bloblist_hdr *hdr;
176 	void *data;
177 
178 	hdr = clear_bloblist();
179 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
180 	data = hdr + 1;
181 	data += sizeof(struct bloblist_rec);
182 	ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
183 	ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
184 
185 	return 0;
186 }
187 BLOBLIST_TEST(bloblist_test_bad_blob, UFT_BLOBLIST);
188 
bloblist_test_checksum(struct unit_test_state * uts)189 static int bloblist_test_checksum(struct unit_test_state *uts)
190 {
191 	struct bloblist_hdr *hdr;
192 	char *data, *data2;
193 
194 	hdr = clear_bloblist();
195 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
196 	ut_assertok(bloblist_finish());
197 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
198 
199 	/*
200 	 * Now change things amd make sure that the checksum notices. We cannot
201 	 * change the size or alloced fields, since that will crash the code.
202 	 * It has to rely on these being correct.
203 	 */
204 	hdr->flags--;
205 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
206 	hdr->flags++;
207 
208 	hdr->total_size--;
209 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
210 	hdr->total_size++;
211 
212 	hdr->spare++;
213 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
214 	hdr->spare--;
215 
216 	hdr->chksum++;
217 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
218 	hdr->chksum--;
219 
220 	hdr->align_log2++;
221 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
222 	hdr->align_log2--;
223 
224 	/* Make sure the checksum changes when we add blobs */
225 	data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
226 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
227 
228 	data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
229 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
230 	ut_assertok(bloblist_finish());
231 
232 	/* It should also change if we change the data */
233 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
234 	*data += 1;
235 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
236 	*data -= 1;
237 
238 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
239 	*data2 += 1;
240 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
241 	*data2 -= 1;
242 
243 	/*
244 	 * Changing data outside the range of valid data should affect the
245 	 * checksum.
246 	 */
247 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
248 	data[TEST_SIZE]++;
249 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
250 	data[TEST_SIZE]--;
251 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
252 
253 	data2[TEST_SIZE2]++;
254 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
255 	data[TEST_SIZE]--;
256 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
257 
258 	return 0;
259 }
260 BLOBLIST_TEST(bloblist_test_checksum, UFT_BLOBLIST);
261 
262 /* Test the 'bloblist info' command */
bloblist_test_cmd_info(struct unit_test_state * uts)263 static int bloblist_test_cmd_info(struct unit_test_state *uts)
264 {
265 	struct bloblist_hdr *hdr;
266 	char *data, *data2;
267 
268 	hdr = clear_bloblist();
269 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
270 	data = bloblist_ensure(TEST_TAG, TEST_SIZE);
271 	data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
272 
273 	run_command("bloblist info", 0);
274 	ut_assert_nextline("base:       %lx", (ulong)map_to_sysmem(hdr));
275 	ut_assert_nextline("total size: 400    1 KiB");
276 	ut_assert_nextline("used size:  50     80 Bytes");
277 	ut_assert_nextline("free:       3b0    944 Bytes");
278 
279 	return 0;
280 }
281 BLOBLIST_TEST(bloblist_test_cmd_info, UFT_BLOBLIST | UTF_CONSOLE);
282 
283 /* Test the 'bloblist list' command */
bloblist_test_cmd_list(struct unit_test_state * uts)284 static int bloblist_test_cmd_list(struct unit_test_state *uts)
285 {
286 	struct bloblist_hdr *hdr;
287 	char *data, *data2;
288 
289 	hdr = clear_bloblist();
290 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
291 	data = bloblist_ensure(TEST_TAG, TEST_SIZE);
292 	data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
293 
294 	run_command("bloblist list", 0);
295 	ut_assert_nextline("Address       Size   Tag Name");
296 	ut_assert_nextline("%08lx  %8x  fff000 SPL hand-off",
297 			   (ulong)map_to_sysmem(data), TEST_SIZE);
298 	ut_assert_nextline("%08lx  %8x   202 Chrome OS vboot context",
299 			   (ulong)map_to_sysmem(data2), TEST_SIZE2);
300 
301 	return 0;
302 }
303 BLOBLIST_TEST(bloblist_test_cmd_list, UFT_BLOBLIST | UTF_CONSOLE);
304 
305 /* Test alignment of bloblist blobs */
bloblist_test_align(struct unit_test_state * uts)306 static int bloblist_test_align(struct unit_test_state *uts)
307 {
308 	struct bloblist_hdr *hdr;
309 	ulong addr;
310 	char *data;
311 	int i;
312 
313 	/* At the start there should be no records */
314 	hdr = clear_bloblist();
315 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
316 	ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
317 
318 	/* Check the default alignment */
319 	for (i = 0; i < 3; i++) {
320 		int size = i * 3;
321 		ulong addr;
322 		char *data;
323 		int j;
324 
325 		data = bloblist_add(i, size, 0);
326 		ut_assertnonnull(data);
327 		addr = map_to_sysmem(data);
328 		ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN - 1));
329 
330 		/* Only the bytes in the blob data should be zeroed */
331 		for (j = 0; j < size; j++)
332 			ut_asserteq(0, data[j]);
333 		for (; j < BLOBLIST_BLOB_ALIGN; j++)
334 			ut_asserteq(ERASE_BYTE, data[j]);
335 	}
336 
337 	/* Check larger alignment */
338 	for (i = 0; i < 3; i++) {
339 		int align = 5 - i;
340 
341 		data = bloblist_add(3 + i, i * 4, align);
342 		ut_assertnonnull(data);
343 		addr = map_to_sysmem(data);
344 		ut_asserteq(0, addr & (align - 1));
345 	}
346 
347 	/* Check alignment with an bloblist starting on a smaller alignment */
348 	hdr = map_sysmem(TEST_ADDR + BLOBLIST_BLOB_ALIGN, TEST_BLOBLIST_SIZE);
349 	memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
350 	memset(hdr, '\0', sizeof(*hdr));
351 	ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
352 				 0, 0));
353 
354 	data = bloblist_add(1, 5, BLOBLIST_ALIGN_LOG2 + 1);
355 	ut_assertnonnull(data);
356 	addr = map_to_sysmem(data);
357 	ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN * 2 - 1));
358 
359 	return 0;
360 }
361 BLOBLIST_TEST(bloblist_test_align, UFT_BLOBLIST);
362 
363 /* Test relocation of a bloblist */
bloblist_test_reloc(struct unit_test_state * uts)364 static int bloblist_test_reloc(struct unit_test_state *uts)
365 {
366 	const uint large_size = TEST_BLOBLIST_SIZE;
367 	const uint small_size = 0x20;
368 	void *new_ptr;
369 	void *blob1, *blob2;
370 	ulong new_addr;
371 	ulong new_size;
372 
373 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
374 
375 	/* Add one blob and then one that won't fit */
376 	blob1 = bloblist_add(TEST_TAG, small_size, 0);
377 	ut_assertnonnull(blob1);
378 	blob2 = bloblist_add(TEST_TAG2, large_size, 0);
379 	ut_assertnull(blob2);
380 
381 	/* Relocate the bloblist somewhere else, a bit larger */
382 	new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE;
383 	new_size = TEST_BLOBLIST_SIZE + 0x100;
384 	new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE);
385 	ut_assertok(bloblist_reloc(new_ptr, new_size));
386 
387 	/* Check the old blob is there and that we can now add the bigger one */
388 	ut_assertnonnull(bloblist_find(TEST_TAG, small_size));
389 	ut_assertnull(bloblist_find(TEST_TAG2, small_size));
390 	blob2 = bloblist_add(TEST_TAG2, large_size, 0);
391 	ut_assertnonnull(blob2);
392 
393 	return 0;
394 }
395 BLOBLIST_TEST(bloblist_test_reloc, UFT_BLOBLIST);
396 
397 /* Test expansion of a blob */
bloblist_test_grow(struct unit_test_state * uts)398 static int bloblist_test_grow(struct unit_test_state *uts)
399 {
400 	const uint small_size = 0x20;
401 	void *blob1, *blob2, *blob1_new;
402 	struct bloblist_hdr *hdr;
403 	void *ptr;
404 
405 	ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
406 	hdr = ptr;
407 	memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
408 
409 	/* Create two blobs */
410 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
411 	blob1 = bloblist_add(TEST_TAG, small_size, 0);
412 	ut_assertnonnull(blob1);
413 	ut_assertok(check_zero(blob1, small_size));
414 	strcpy(blob1, test1_str);
415 
416 	blob2 = bloblist_add(TEST_TAG2, small_size, 0);
417 	ut_assertnonnull(blob2);
418 	strcpy(blob2, test2_str);
419 
420 	ut_asserteq(sizeof(struct bloblist_hdr) +
421 		    sizeof(struct bloblist_rec) * 2 + small_size * 2,
422 		    hdr->used_size);
423 
424 	/* Resize the first one */
425 	ut_assertok(bloblist_resize(TEST_TAG, small_size + 4));
426 
427 	/* The first one should not have moved, just got larger */
428 	blob1_new = bloblist_find(TEST_TAG, small_size + 4);
429 	ut_asserteq_ptr(blob1, blob1_new);
430 
431 	/* The new space should be zeroed */
432 	ut_assertok(check_zero(blob1 + small_size, 4));
433 
434 	/* The second one should have moved */
435 	blob2 = bloblist_find(TEST_TAG2, small_size);
436 	ut_assertnonnull(blob2);
437 	ut_asserteq_str(test2_str, blob2);
438 
439 	/* The header should have more bytes in use */
440 	hdr = ptr;
441 	ut_asserteq(sizeof(struct bloblist_hdr) +
442 		    sizeof(struct bloblist_rec) * 2 + small_size * 2 +
443 		    BLOBLIST_BLOB_ALIGN,
444 		    hdr->used_size);
445 
446 	return 0;
447 }
448 BLOBLIST_TEST(bloblist_test_grow, UFT_BLOBLIST);
449 
450 /* Test shrinking of a blob */
bloblist_test_shrink(struct unit_test_state * uts)451 static int bloblist_test_shrink(struct unit_test_state *uts)
452 {
453 	const uint small_size = 0x20;
454 	void *blob1, *blob2, *blob1_new;
455 	struct bloblist_hdr *hdr;
456 	int new_size;
457 	void *ptr;
458 
459 	ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
460 
461 	/* Create two blobs */
462 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
463 	blob1 = bloblist_add(TEST_TAG, small_size, 0);
464 	ut_assertnonnull(blob1);
465 	strcpy(blob1, test1_str);
466 
467 	blob2 = bloblist_add(TEST_TAG2, small_size, 0);
468 	ut_assertnonnull(blob2);
469 	strcpy(blob2, test2_str);
470 
471 	hdr = ptr;
472 	ut_asserteq(sizeof(struct bloblist_hdr) +
473 		    sizeof(struct bloblist_rec) * 2 + small_size * 2,
474 		    hdr->used_size);
475 
476 	/* Resize the first one */
477 	new_size = small_size - BLOBLIST_ALIGN - 4;
478 	ut_assertok(bloblist_resize(TEST_TAG, new_size));
479 
480 	/* The first one should not have moved, just got smaller */
481 	blob1_new = bloblist_find(TEST_TAG, new_size);
482 	ut_asserteq_ptr(blob1, blob1_new);
483 
484 	/* The second one should have moved */
485 	blob2 = bloblist_find(TEST_TAG2, small_size);
486 	ut_assertnonnull(blob2);
487 	ut_asserteq_str(test2_str, blob2);
488 
489 	/* The header should have fewer bytes in use */
490 	hdr = ptr;
491 	ut_asserteq(sizeof(struct bloblist_hdr) +
492 		    sizeof(struct bloblist_rec) * 2 + small_size * 2 -
493 		    BLOBLIST_ALIGN,
494 		    hdr->used_size);
495 
496 	return 0;
497 }
498 BLOBLIST_TEST(bloblist_test_shrink, UFT_BLOBLIST);
499 
500 /* Test failing to adjust a blob size */
bloblist_test_resize_fail(struct unit_test_state * uts)501 static int bloblist_test_resize_fail(struct unit_test_state *uts)
502 {
503 	const uint small_size = 0x20;
504 	struct bloblist_hdr *hdr;
505 	void *blob1, *blob2;
506 	int new_size;
507 	void *ptr;
508 
509 	ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
510 
511 	/* Create two blobs */
512 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
513 	blob1 = bloblist_add(TEST_TAG, small_size, 0);
514 	ut_assertnonnull(blob1);
515 
516 	blob2 = bloblist_add(TEST_TAG2, small_size, 0);
517 	ut_assertnonnull(blob2);
518 
519 	hdr = ptr;
520 	ut_asserteq(sizeof(struct bloblist_hdr) +
521 		    sizeof(struct bloblist_rec) * 2 + small_size * 2,
522 		    hdr->used_size);
523 
524 	/* Resize the first one, to check the boundary conditions */
525 	ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1));
526 
527 	new_size = small_size + (hdr->total_size - hdr->used_size);
528 	ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1));
529 	ut_assertok(bloblist_resize(TEST_TAG, new_size));
530 
531 	return 0;
532 }
533 BLOBLIST_TEST(bloblist_test_resize_fail, UFT_BLOBLIST);
534 
535 /* Test expanding the last blob in a bloblist */
bloblist_test_resize_last(struct unit_test_state * uts)536 static int bloblist_test_resize_last(struct unit_test_state *uts)
537 {
538 	const uint small_size = 0x20;
539 	struct bloblist_hdr *hdr;
540 	void *blob1, *blob2, *blob2_new;
541 	int alloced_val;
542 	void *ptr;
543 
544 	ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
545 	memset(ptr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
546 	hdr = ptr;
547 
548 	/* Create two blobs */
549 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
550 	blob1 = bloblist_add(TEST_TAG, small_size, 0);
551 	ut_assertnonnull(blob1);
552 
553 	blob2 = bloblist_add(TEST_TAG2, small_size, 0);
554 	ut_assertnonnull(blob2);
555 
556 	/* Check the byte after the last blob */
557 	alloced_val = sizeof(struct bloblist_hdr) +
558 		    sizeof(struct bloblist_rec) * 2 + small_size * 2;
559 	ut_asserteq(alloced_val, hdr->used_size);
560 	ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size);
561 	ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
562 
563 	/* Resize the second one, checking nothing changes */
564 	ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4));
565 
566 	blob2_new = bloblist_find(TEST_TAG2, small_size + 4);
567 	ut_asserteq_ptr(blob2, blob2_new);
568 
569 	/*
570 	 * the new blob should encompass the byte we checked now, so it should
571 	 * be zeroed. This zeroing should affect only the four new bytes added
572 	 * to the blob.
573 	 */
574 	ut_asserteq(0, *((u8 *)hdr + alloced_val));
575 	ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4));
576 
577 	/* Check that the new top of the allocated blobs has not been touched */
578 	alloced_val += BLOBLIST_BLOB_ALIGN;
579 	ut_asserteq(alloced_val, hdr->used_size);
580 	ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
581 
582 	return 0;
583 }
584 BLOBLIST_TEST(bloblist_test_resize_last, UFT_BLOBLIST);
585 
586 /* Check a completely full bloblist */
bloblist_test_blob_maxsize(struct unit_test_state * uts)587 static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
588 {
589 	void *ptr;
590 	int size;
591 
592 	/* At the start there should be no records */
593 	clear_bloblist();
594 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
595 
596 	/* Add a blob that takes up all space */
597 	size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) -
598 		sizeof(struct bloblist_rec);
599 	ptr = bloblist_add(TEST_TAG, size, 0);
600 	ut_assertnonnull(ptr);
601 
602 	ptr = bloblist_add(TEST_TAG, size + 1, 0);
603 	ut_assertnull(ptr);
604 
605 	return 0;
606 }
607 BLOBLIST_TEST(bloblist_test_blob_maxsize, UFT_BLOBLIST);
608