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