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