bloblist: Add functions to obtain base address and size
[platform/kernel/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 not affect
241          * the checksum.
242          */
243         ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
244         data[TEST_SIZE]++;
245         data2[TEST_SIZE2]++;
246         ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
247
248         return 0;
249 }
250 BLOBLIST_TEST(bloblist_test_checksum, 0);
251
252 /* Test the 'bloblist info' command */
253 static int bloblist_test_cmd_info(struct unit_test_state *uts)
254 {
255         struct bloblist_hdr *hdr;
256         char *data, *data2;
257
258         hdr = clear_bloblist();
259         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
260         data = bloblist_ensure(TEST_TAG, TEST_SIZE);
261         data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
262
263         console_record_reset_enable();
264         ut_silence_console(uts);
265         console_record_reset();
266         run_command("bloblist info", 0);
267         ut_assert_nextline("base:     %lx", (ulong)map_to_sysmem(hdr));
268         ut_assert_nextline("size:     400    1 KiB");
269         ut_assert_nextline("alloced:  70     112 Bytes");
270         ut_assert_nextline("free:     390    912 Bytes");
271         ut_assert_console_end();
272         ut_unsilence_console(uts);
273
274         return 0;
275 }
276 BLOBLIST_TEST(bloblist_test_cmd_info, 0);
277
278 /* Test the 'bloblist list' command */
279 static int bloblist_test_cmd_list(struct unit_test_state *uts)
280 {
281         struct bloblist_hdr *hdr;
282         char *data, *data2;
283
284         hdr = clear_bloblist();
285         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
286         data = bloblist_ensure(TEST_TAG, TEST_SIZE);
287         data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
288
289         console_record_reset_enable();
290         ut_silence_console(uts);
291         console_record_reset();
292         run_command("bloblist list", 0);
293         ut_assert_nextline("Address       Size   Tag Name");
294         ut_assert_nextline("%08lx  %8x  8000 SPL hand-off",
295                            (ulong)map_to_sysmem(data), TEST_SIZE);
296         ut_assert_nextline("%08lx  %8x   106 Chrome OS vboot context",
297                            (ulong)map_to_sysmem(data2), TEST_SIZE2);
298         ut_assert_console_end();
299         ut_unsilence_console(uts);
300
301         return 0;
302 }
303 BLOBLIST_TEST(bloblist_test_cmd_list, 0);
304
305 /* Test alignment of bloblist blobs */
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));
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_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_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 = 32 << 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_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));
353
354         data = bloblist_add(1, 5, BLOBLIST_ALIGN * 2);
355         ut_assertnonnull(data);
356         addr = map_to_sysmem(data);
357         ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1));
358
359         return 0;
360 }
361 BLOBLIST_TEST(bloblist_test_align, 0);
362
363 /* Test relocation of a bloblist */
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 *old_ptr, *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));
374         old_ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
375
376         /* Add one blob and then one that won't fit */
377         blob1 = bloblist_add(TEST_TAG, small_size, 0);
378         ut_assertnonnull(blob1);
379         blob2 = bloblist_add(TEST_TAG2, large_size, 0);
380         ut_assertnull(blob2);
381
382         /* Relocate the bloblist somewhere else, a bit larger */
383         new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE;
384         new_size = TEST_BLOBLIST_SIZE + 0x100;
385         new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE);
386         bloblist_reloc(new_ptr, new_size, old_ptr, TEST_BLOBLIST_SIZE);
387         gd->bloblist = new_ptr;
388
389         /* Check the old blob is there and that we can now add the bigger one */
390         ut_assertnonnull(bloblist_find(TEST_TAG, small_size));
391         ut_assertnull(bloblist_find(TEST_TAG2, small_size));
392         blob2 = bloblist_add(TEST_TAG2, large_size, 0);
393         ut_assertnonnull(blob2);
394
395         return 0;
396 }
397 BLOBLIST_TEST(bloblist_test_reloc, 0);
398
399 /* Test expansion of a blob */
400 static int bloblist_test_grow(struct unit_test_state *uts)
401 {
402         const uint small_size = 0x20;
403         void *blob1, *blob2, *blob1_new;
404         struct bloblist_hdr *hdr;
405         void *ptr;
406
407         ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
408         hdr = ptr;
409         memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
410
411         /* Create two blobs */
412         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
413         blob1 = bloblist_add(TEST_TAG, small_size, 0);
414         ut_assertnonnull(blob1);
415         ut_assertok(check_zero(blob1, small_size));
416         strcpy(blob1, test1_str);
417
418         blob2 = bloblist_add(TEST_TAG2, small_size, 0);
419         ut_assertnonnull(blob2);
420         strcpy(blob2, test2_str);
421
422         ut_asserteq(sizeof(struct bloblist_hdr) +
423                     sizeof(struct bloblist_rec) * 2 + small_size * 2,
424                     hdr->alloced);
425
426         /* Resize the first one */
427         ut_assertok(bloblist_resize(TEST_TAG, small_size + 4));
428
429         /* The first one should not have moved, just got larger */
430         blob1_new = bloblist_find(TEST_TAG, small_size + 4);
431         ut_asserteq_ptr(blob1, blob1_new);
432
433         /* The new space should be zeroed */
434         ut_assertok(check_zero(blob1 + small_size, 4));
435
436         /* The second one should have moved */
437         blob2 = bloblist_find(TEST_TAG2, small_size);
438         ut_assertnonnull(blob2);
439         ut_asserteq_str(test2_str, blob2);
440
441         /* The header should have more bytes in use */
442         hdr = ptr;
443         ut_asserteq(sizeof(struct bloblist_hdr) +
444                     sizeof(struct bloblist_rec) * 2 + small_size * 2 +
445                     BLOBLIST_ALIGN,
446                     hdr->alloced);
447
448         return 0;
449 }
450 BLOBLIST_TEST(bloblist_test_grow, 0);
451
452 /* Test shrinking of a blob */
453 static int bloblist_test_shrink(struct unit_test_state *uts)
454 {
455         const uint small_size = 0x20;
456         void *blob1, *blob2, *blob1_new;
457         struct bloblist_hdr *hdr;
458         int new_size;
459         void *ptr;
460
461         ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
462
463         /* Create two blobs */
464         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
465         blob1 = bloblist_add(TEST_TAG, small_size, 0);
466         ut_assertnonnull(blob1);
467         strcpy(blob1, test1_str);
468
469         blob2 = bloblist_add(TEST_TAG2, small_size, 0);
470         ut_assertnonnull(blob2);
471         strcpy(blob2, test2_str);
472
473         hdr = ptr;
474         ut_asserteq(sizeof(struct bloblist_hdr) +
475                     sizeof(struct bloblist_rec) * 2 + small_size * 2,
476                     hdr->alloced);
477
478         /* Resize the first one */
479         new_size = small_size - BLOBLIST_ALIGN - 4;
480         ut_assertok(bloblist_resize(TEST_TAG, new_size));
481
482         /* The first one should not have moved, just got smaller */
483         blob1_new = bloblist_find(TEST_TAG, new_size);
484         ut_asserteq_ptr(blob1, blob1_new);
485
486         /* The second one should have moved */
487         blob2 = bloblist_find(TEST_TAG2, small_size);
488         ut_assertnonnull(blob2);
489         ut_asserteq_str(test2_str, blob2);
490
491         /* The header should have fewer bytes in use */
492         hdr = ptr;
493         ut_asserteq(sizeof(struct bloblist_hdr) +
494                     sizeof(struct bloblist_rec) * 2 + small_size * 2 -
495                     BLOBLIST_ALIGN,
496                     hdr->alloced);
497
498         return 0;
499 }
500 BLOBLIST_TEST(bloblist_test_shrink, 0);
501
502 /* Test failing to adjust a blob size */
503 static int bloblist_test_resize_fail(struct unit_test_state *uts)
504 {
505         const uint small_size = 0x20;
506         struct bloblist_hdr *hdr;
507         void *blob1, *blob2;
508         int new_size;
509         void *ptr;
510
511         ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
512
513         /* Create two blobs */
514         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
515         blob1 = bloblist_add(TEST_TAG, small_size, 0);
516         ut_assertnonnull(blob1);
517
518         blob2 = bloblist_add(TEST_TAG2, small_size, 0);
519         ut_assertnonnull(blob2);
520
521         hdr = ptr;
522         ut_asserteq(sizeof(struct bloblist_hdr) +
523                     sizeof(struct bloblist_rec) * 2 + small_size * 2,
524                     hdr->alloced);
525
526         /* Resize the first one, to check the boundary conditions */
527         ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1));
528
529         new_size = small_size + (hdr->size - hdr->alloced);
530         ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1));
531         ut_assertok(bloblist_resize(TEST_TAG, new_size));
532
533         return 0;
534 }
535 BLOBLIST_TEST(bloblist_test_resize_fail, 0);
536
537 /* Test expanding the last blob in a bloblist */
538 static int bloblist_test_resize_last(struct unit_test_state *uts)
539 {
540         const uint small_size = 0x20;
541         struct bloblist_hdr *hdr;
542         void *blob1, *blob2, *blob2_new;
543         int alloced_val;
544         void *ptr;
545
546         ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
547         memset(ptr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
548         hdr = ptr;
549
550         /* Create two blobs */
551         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
552         blob1 = bloblist_add(TEST_TAG, small_size, 0);
553         ut_assertnonnull(blob1);
554
555         blob2 = bloblist_add(TEST_TAG2, small_size, 0);
556         ut_assertnonnull(blob2);
557
558         /* Check the byte after the last blob */
559         alloced_val = sizeof(struct bloblist_hdr) +
560                     sizeof(struct bloblist_rec) * 2 + small_size * 2;
561         ut_asserteq(alloced_val, hdr->alloced);
562         ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size);
563         ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced));
564
565         /* Resize the second one, checking nothing changes */
566         ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4));
567
568         blob2_new = bloblist_find(TEST_TAG2, small_size + 4);
569         ut_asserteq_ptr(blob2, blob2_new);
570
571         /*
572          * the new blob should encompass the byte we checked now, so it should
573          * be zeroed. This zeroing should affect only the four new bytes added
574          * to the blob.
575          */
576         ut_asserteq(0, *((u8 *)hdr + alloced_val));
577         ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4));
578
579         /* Check that the new top of the allocated blobs has not been touched */
580         alloced_val += BLOBLIST_ALIGN;
581         ut_asserteq(alloced_val, hdr->alloced);
582         ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced));
583
584         return 0;
585 }
586 BLOBLIST_TEST(bloblist_test_resize_last, 0);
587
588 /* Check a completely full bloblist */
589 static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
590 {
591         void *ptr;
592         int size;
593
594         /* At the start there should be no records */
595         clear_bloblist();
596         ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
597
598         /* Add a blob that takes up all space */
599         size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) -
600                 sizeof(struct bloblist_rec);
601         ptr = bloblist_add(TEST_TAG, size, 0);
602         ut_assertnonnull(ptr);
603
604         ptr = bloblist_add(TEST_TAG, size + 1, 0);
605         ut_assertnull(ptr);
606
607         return 0;
608 }
609 BLOBLIST_TEST(bloblist_test_blob_maxsize, 0);
610
611 int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
612                    char *const argv[])
613 {
614         struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test);
615         const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test);
616
617         return cmd_ut_category("bloblist", "bloblist_test_",
618                                tests, n_ents, argc, argv);
619 }