bloblist: Checksum the entire bloblist
[pandora-u-boot.git] / test / bloblist.c
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
15 DECLARE_GLOBAL_DATA_PTR;
16
17 /* Declare a new bloblist test */
18 #define BLOBLIST_TEST(_name, _flags) \
19                 UNIT_TEST(_name, _flags, bloblist_test)
20
21 enum {
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
36 static const char test1_str[] = "the eyes are open";
37 static const char test2_str[] = "the mouth moves";
38
39 static 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
55 static 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
68 static 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));
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, 0x10, 0));
82         ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0));
83         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 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 }
98 BLOBLIST_TEST(bloblist_test_init, 0);
99
100 static 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));
110         ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_size());
111         ut_asserteq(TEST_ADDR, bloblist_get_base());
112         ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
113
114         /* Add a record and check that we can find it */
115         data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
116         rec = (void *)(hdr + 1);
117         ut_asserteq_addr(rec + 1, data);
118         data = bloblist_find(TEST_TAG, TEST_SIZE);
119         ut_asserteq_addr(rec + 1, data);
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, 0);
138
139 /* Check bloblist_ensure_size_ret() */
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));
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, 0);
172
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));
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, 0);
188
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));
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->size--;
209         ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
210         hdr->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         /* Make sure the checksum changes when we add blobs */
221         data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
222         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
223
224         data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
225         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
226         ut_assertok(bloblist_finish());
227
228         /* It should also change if we change the data */
229         ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
230         *data += 1;
231         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
232         *data -= 1;
233
234         ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
235         *data2 += 1;
236         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
237         *data2 -= 1;
238
239         /*
240          * Changing data outside the range of valid data should affect the
241          * checksum.
242          */
243         ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
244         data[TEST_SIZE]++;
245         ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
246         data[TEST_SIZE]--;
247         ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
248
249         data2[TEST_SIZE2]++;
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         return 0;
255 }
256 BLOBLIST_TEST(bloblist_test_checksum, 0);
257
258 /* Test the 'bloblist info' command */
259 static int bloblist_test_cmd_info(struct unit_test_state *uts)
260 {
261         struct bloblist_hdr *hdr;
262         char *data, *data2;
263
264         hdr = clear_bloblist();
265         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
266         data = bloblist_ensure(TEST_TAG, TEST_SIZE);
267         data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
268
269         console_record_reset_enable();
270         ut_silence_console(uts);
271         console_record_reset();
272         run_command("bloblist info", 0);
273         ut_assert_nextline("base:     %lx", (ulong)map_to_sysmem(hdr));
274         ut_assert_nextline("size:     400    1 KiB");
275         ut_assert_nextline("alloced:  70     112 Bytes");
276         ut_assert_nextline("free:     390    912 Bytes");
277         ut_assert_console_end();
278         ut_unsilence_console(uts);
279
280         return 0;
281 }
282 BLOBLIST_TEST(bloblist_test_cmd_info, 0);
283
284 /* Test the 'bloblist list' command */
285 static int bloblist_test_cmd_list(struct unit_test_state *uts)
286 {
287         struct bloblist_hdr *hdr;
288         char *data, *data2;
289
290         hdr = clear_bloblist();
291         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
292         data = bloblist_ensure(TEST_TAG, TEST_SIZE);
293         data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
294
295         console_record_reset_enable();
296         ut_silence_console(uts);
297         console_record_reset();
298         run_command("bloblist list", 0);
299         ut_assert_nextline("Address       Size   Tag Name");
300         ut_assert_nextline("%08lx  %8x  fff000 SPL hand-off",
301                            (ulong)map_to_sysmem(data), TEST_SIZE);
302         ut_assert_nextline("%08lx  %8x   202 Chrome OS vboot context",
303                            (ulong)map_to_sysmem(data2), TEST_SIZE2);
304         ut_assert_console_end();
305         ut_unsilence_console(uts);
306
307         return 0;
308 }
309 BLOBLIST_TEST(bloblist_test_cmd_list, 0);
310
311 /* Test alignment of bloblist blobs */
312 static int bloblist_test_align(struct unit_test_state *uts)
313 {
314         struct bloblist_hdr *hdr;
315         ulong addr;
316         char *data;
317         int i;
318
319         /* At the start there should be no records */
320         hdr = clear_bloblist();
321         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
322         ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
323
324         /* Check the default alignment */
325         for (i = 0; i < 3; i++) {
326                 int size = i * 3;
327                 ulong addr;
328                 char *data;
329                 int j;
330
331                 data = bloblist_add(i, size, 0);
332                 ut_assertnonnull(data);
333                 addr = map_to_sysmem(data);
334                 ut_asserteq(0, addr & (BLOBLIST_ALIGN - 1));
335
336                 /* Only the bytes in the blob data should be zeroed */
337                 for (j = 0; j < size; j++)
338                         ut_asserteq(0, data[j]);
339                 for (; j < BLOBLIST_ALIGN; j++)
340                         ut_asserteq(ERASE_BYTE, data[j]);
341         }
342
343         /* Check larger alignment */
344         for (i = 0; i < 3; i++) {
345                 int align = 5 - i;
346
347                 data = bloblist_add(3 + i, i * 4, align);
348                 ut_assertnonnull(data);
349                 addr = map_to_sysmem(data);
350                 ut_asserteq(0, addr & (align - 1));
351         }
352
353         /* Check alignment with an bloblist starting on a smaller alignment */
354         hdr = map_sysmem(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE);
355         memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
356         memset(hdr, '\0', sizeof(*hdr));
357         ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
358                                  0));
359
360         data = bloblist_add(1, 5, BLOBLIST_ALIGN_LOG2 + 1);
361         ut_assertnonnull(data);
362         addr = map_to_sysmem(data);
363         ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1));
364
365         return 0;
366 }
367 BLOBLIST_TEST(bloblist_test_align, 0);
368
369 /* Test relocation of a bloblist */
370 static int bloblist_test_reloc(struct unit_test_state *uts)
371 {
372         const uint large_size = TEST_BLOBLIST_SIZE;
373         const uint small_size = 0x20;
374         void *old_ptr, *new_ptr;
375         void *blob1, *blob2;
376         ulong new_addr;
377         ulong new_size;
378
379         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
380         old_ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
381
382         /* Add one blob and then one that won't fit */
383         blob1 = bloblist_add(TEST_TAG, small_size, 0);
384         ut_assertnonnull(blob1);
385         blob2 = bloblist_add(TEST_TAG2, large_size, 0);
386         ut_assertnull(blob2);
387
388         /* Relocate the bloblist somewhere else, a bit larger */
389         new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE;
390         new_size = TEST_BLOBLIST_SIZE + 0x100;
391         new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE);
392         bloblist_reloc(new_ptr, new_size, old_ptr, TEST_BLOBLIST_SIZE);
393         gd->bloblist = new_ptr;
394
395         /* Check the old blob is there and that we can now add the bigger one */
396         ut_assertnonnull(bloblist_find(TEST_TAG, small_size));
397         ut_assertnull(bloblist_find(TEST_TAG2, small_size));
398         blob2 = bloblist_add(TEST_TAG2, large_size, 0);
399         ut_assertnonnull(blob2);
400
401         return 0;
402 }
403 BLOBLIST_TEST(bloblist_test_reloc, 0);
404
405 /* Test expansion of a blob */
406 static int bloblist_test_grow(struct unit_test_state *uts)
407 {
408         const uint small_size = 0x20;
409         void *blob1, *blob2, *blob1_new;
410         struct bloblist_hdr *hdr;
411         void *ptr;
412
413         ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
414         hdr = ptr;
415         memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
416
417         /* Create two blobs */
418         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
419         blob1 = bloblist_add(TEST_TAG, small_size, 0);
420         ut_assertnonnull(blob1);
421         ut_assertok(check_zero(blob1, small_size));
422         strcpy(blob1, test1_str);
423
424         blob2 = bloblist_add(TEST_TAG2, small_size, 0);
425         ut_assertnonnull(blob2);
426         strcpy(blob2, test2_str);
427
428         ut_asserteq(sizeof(struct bloblist_hdr) +
429                     sizeof(struct bloblist_rec) * 2 + small_size * 2,
430                     hdr->alloced);
431
432         /* Resize the first one */
433         ut_assertok(bloblist_resize(TEST_TAG, small_size + 4));
434
435         /* The first one should not have moved, just got larger */
436         blob1_new = bloblist_find(TEST_TAG, small_size + 4);
437         ut_asserteq_ptr(blob1, blob1_new);
438
439         /* The new space should be zeroed */
440         ut_assertok(check_zero(blob1 + small_size, 4));
441
442         /* The second one should have moved */
443         blob2 = bloblist_find(TEST_TAG2, small_size);
444         ut_assertnonnull(blob2);
445         ut_asserteq_str(test2_str, blob2);
446
447         /* The header should have more bytes in use */
448         hdr = ptr;
449         ut_asserteq(sizeof(struct bloblist_hdr) +
450                     sizeof(struct bloblist_rec) * 2 + small_size * 2 +
451                     BLOBLIST_ALIGN,
452                     hdr->alloced);
453
454         return 0;
455 }
456 BLOBLIST_TEST(bloblist_test_grow, 0);
457
458 /* Test shrinking of a blob */
459 static int bloblist_test_shrink(struct unit_test_state *uts)
460 {
461         const uint small_size = 0x20;
462         void *blob1, *blob2, *blob1_new;
463         struct bloblist_hdr *hdr;
464         int new_size;
465         void *ptr;
466
467         ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
468
469         /* Create two blobs */
470         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
471         blob1 = bloblist_add(TEST_TAG, small_size, 0);
472         ut_assertnonnull(blob1);
473         strcpy(blob1, test1_str);
474
475         blob2 = bloblist_add(TEST_TAG2, small_size, 0);
476         ut_assertnonnull(blob2);
477         strcpy(blob2, test2_str);
478
479         hdr = ptr;
480         ut_asserteq(sizeof(struct bloblist_hdr) +
481                     sizeof(struct bloblist_rec) * 2 + small_size * 2,
482                     hdr->alloced);
483
484         /* Resize the first one */
485         new_size = small_size - BLOBLIST_ALIGN - 4;
486         ut_assertok(bloblist_resize(TEST_TAG, new_size));
487
488         /* The first one should not have moved, just got smaller */
489         blob1_new = bloblist_find(TEST_TAG, new_size);
490         ut_asserteq_ptr(blob1, blob1_new);
491
492         /* The second one should have moved */
493         blob2 = bloblist_find(TEST_TAG2, small_size);
494         ut_assertnonnull(blob2);
495         ut_asserteq_str(test2_str, blob2);
496
497         /* The header should have fewer bytes in use */
498         hdr = ptr;
499         ut_asserteq(sizeof(struct bloblist_hdr) +
500                     sizeof(struct bloblist_rec) * 2 + small_size * 2 -
501                     BLOBLIST_ALIGN,
502                     hdr->alloced);
503
504         return 0;
505 }
506 BLOBLIST_TEST(bloblist_test_shrink, 0);
507
508 /* Test failing to adjust a blob size */
509 static int bloblist_test_resize_fail(struct unit_test_state *uts)
510 {
511         const uint small_size = 0x20;
512         struct bloblist_hdr *hdr;
513         void *blob1, *blob2;
514         int new_size;
515         void *ptr;
516
517         ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
518
519         /* Create two blobs */
520         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
521         blob1 = bloblist_add(TEST_TAG, small_size, 0);
522         ut_assertnonnull(blob1);
523
524         blob2 = bloblist_add(TEST_TAG2, small_size, 0);
525         ut_assertnonnull(blob2);
526
527         hdr = ptr;
528         ut_asserteq(sizeof(struct bloblist_hdr) +
529                     sizeof(struct bloblist_rec) * 2 + small_size * 2,
530                     hdr->alloced);
531
532         /* Resize the first one, to check the boundary conditions */
533         ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1));
534
535         new_size = small_size + (hdr->size - hdr->alloced);
536         ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1));
537         ut_assertok(bloblist_resize(TEST_TAG, new_size));
538
539         return 0;
540 }
541 BLOBLIST_TEST(bloblist_test_resize_fail, 0);
542
543 /* Test expanding the last blob in a bloblist */
544 static int bloblist_test_resize_last(struct unit_test_state *uts)
545 {
546         const uint small_size = 0x20;
547         struct bloblist_hdr *hdr;
548         void *blob1, *blob2, *blob2_new;
549         int alloced_val;
550         void *ptr;
551
552         ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
553         memset(ptr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
554         hdr = ptr;
555
556         /* Create two blobs */
557         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
558         blob1 = bloblist_add(TEST_TAG, small_size, 0);
559         ut_assertnonnull(blob1);
560
561         blob2 = bloblist_add(TEST_TAG2, small_size, 0);
562         ut_assertnonnull(blob2);
563
564         /* Check the byte after the last blob */
565         alloced_val = sizeof(struct bloblist_hdr) +
566                     sizeof(struct bloblist_rec) * 2 + small_size * 2;
567         ut_asserteq(alloced_val, hdr->alloced);
568         ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size);
569         ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced));
570
571         /* Resize the second one, checking nothing changes */
572         ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4));
573
574         blob2_new = bloblist_find(TEST_TAG2, small_size + 4);
575         ut_asserteq_ptr(blob2, blob2_new);
576
577         /*
578          * the new blob should encompass the byte we checked now, so it should
579          * be zeroed. This zeroing should affect only the four new bytes added
580          * to the blob.
581          */
582         ut_asserteq(0, *((u8 *)hdr + alloced_val));
583         ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4));
584
585         /* Check that the new top of the allocated blobs has not been touched */
586         alloced_val += BLOBLIST_ALIGN;
587         ut_asserteq(alloced_val, hdr->alloced);
588         ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced));
589
590         return 0;
591 }
592 BLOBLIST_TEST(bloblist_test_resize_last, 0);
593
594 /* Check a completely full bloblist */
595 static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
596 {
597         void *ptr;
598         int size;
599
600         /* At the start there should be no records */
601         clear_bloblist();
602         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
603
604         /* Add a blob that takes up all space */
605         size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) -
606                 sizeof(struct bloblist_rec);
607         ptr = bloblist_add(TEST_TAG, size, 0);
608         ut_assertnonnull(ptr);
609
610         ptr = bloblist_add(TEST_TAG, size + 1, 0);
611         ut_assertnull(ptr);
612
613         return 0;
614 }
615 BLOBLIST_TEST(bloblist_test_blob_maxsize, 0);
616
617 int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
618                    char *const argv[])
619 {
620         struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test);
621         const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test);
622
623         return cmd_ut_category("bloblist", "bloblist_test_",
624                                tests, n_ents, argc, argv);
625 }