blob: 4104e6a92f6f7ff529be162373701a0198284fa3 [file] [log] [blame]
Simon Glass78b0ef52018-11-15 18:43:53 -07001// 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>
Simon Glass3ba929a2020-10-30 21:38:53 -060010#include <asm/global_data.h>
Simon Glass78b0ef52018-11-15 18:43:53 -070011#include <test/suites.h>
12#include <test/test.h>
13#include <test/ut.h>
14
15DECLARE_GLOBAL_DATA_PTR;
16
17/* Declare a new compression test */
18#define BLOBLIST_TEST(_name, _flags) \
19 UNIT_TEST(_name, _flags, bloblist_test)
20
21enum {
22 TEST_TAG = 1,
23 TEST_TAG2 = 2,
24 TEST_TAG_MISSING = 3,
25
26 TEST_SIZE = 10,
27 TEST_SIZE2 = 20,
Simon Glass06373972020-09-19 18:49:29 -060028 TEST_SIZE_LARGE = 0x3e0,
Simon Glass78b0ef52018-11-15 18:43:53 -070029
30 TEST_ADDR = CONFIG_BLOBLIST_ADDR,
Simon Glass06373972020-09-19 18:49:29 -060031 TEST_BLOBLIST_SIZE = 0x400,
Simon Glassd7985e62020-09-19 18:49:28 -060032
33 ERASE_BYTE = '\xff',
Simon Glass78b0ef52018-11-15 18:43:53 -070034};
35
Simon Glassf20a1132021-07-05 16:32:53 -060036static const char test1_str[] = "the eyes are open";
37static const char test2_str[] = "the mouth moves";
38
Simon Glass78b0ef52018-11-15 18:43:53 -070039static struct bloblist_hdr *clear_bloblist(void)
40{
41 struct bloblist_hdr *hdr;
42
Simon Glass3e85ea02020-01-27 08:49:52 -070043 /*
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 */
Simon Glass78b0ef52018-11-15 18:43:53 -070048 hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
Simon Glassd7985e62020-09-19 18:49:28 -060049 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
Simon Glass3e85ea02020-01-27 08:49:52 -070050 memset(hdr, '\0', sizeof(*hdr));
Simon Glass78b0ef52018-11-15 18:43:53 -070051
52 return hdr;
53}
54
Simon Glass3e85ea02020-01-27 08:49:52 -070055static 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
Simon Glass78b0ef52018-11-15 18:43:53 -070068static 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}
91BLOBLIST_TEST(bloblist_test_init, 0);
92
93static 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));
Simon Glass7c58b082020-09-19 18:49:27 -0600103 ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
Simon Glass78b0ef52018-11-15 18:43:53 -0700104
105 /* Add a record and check that we can find it */
Simon Glass06373972020-09-19 18:49:29 -0600106 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700107 rec = (void *)(hdr + 1);
Simon Glass7c58b082020-09-19 18:49:27 -0600108 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700109 data = bloblist_find(TEST_TAG, TEST_SIZE);
Simon Glass7c58b082020-09-19 18:49:27 -0600110 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700111
Simon Glass3e85ea02020-01-27 08:49:52 -0700112 /* Check the data is zeroed */
113 ut_assertok(check_zero(data, TEST_SIZE));
114
Simon Glass78b0ef52018-11-15 18:43:53 -0700115 /* Check the 'ensure' method */
Simon Glass7c58b082020-09-19 18:49:27 -0600116 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700117 ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
118 rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
Simon Glass3e85ea02020-01-27 08:49:52 -0700119 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700120
121 /* Check for a non-existent record */
Simon Glass7c58b082020-09-19 18:49:27 -0600122 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
123 ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
Simon Glass78b0ef52018-11-15 18:43:53 -0700124 ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
125
126 return 0;
127}
128BLOBLIST_TEST(bloblist_test_blob, 0);
129
Simon Glass1e0304e2020-01-27 08:49:50 -0700130/* Check bloblist_ensure_size_ret() */
131static 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);
Simon Glass3e85ea02020-01-27 08:49:52 -0700144 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass1e0304e2020-01-27 08:49:50 -0700145
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);
Simon Glass7c58b082020-09-19 18:49:27 -0600149 ut_asserteq_addr(data, data2);
Simon Glass1e0304e2020-01-27 08:49:50 -0700150
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}
162BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
163
Simon Glass78b0ef52018-11-15 18:43:53 -0700164static 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);
Simon Glass7c58b082020-09-19 18:49:27 -0600173 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
174 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700175
176 return 0;
177}
178BLOBLIST_TEST(bloblist_test_bad_blob, 0);
179
180static 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 */
Simon Glass06373972020-09-19 18:49:29 -0600212 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700213 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
214
Simon Glass06373972020-09-19 18:49:29 -0600215 data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700216 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}
Simon Glass78b0ef52018-11-15 18:43:53 -0700241BLOBLIST_TEST(bloblist_test_checksum, 0);
242
Simon Glassb936a972020-09-19 18:49:26 -0600243/* Test the 'bloblist info' command */
244static int bloblist_test_cmd_info(struct unit_test_state *uts)
245{
Simon Glassb936a972020-09-19 18:49:26 -0600246 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();
Simon Glassb8f00822020-11-08 21:08:43 -0700255 ut_silence_console(uts);
Simon Glassb936a972020-09-19 18:49:26 -0600256 console_record_reset();
257 run_command("bloblist info", 0);
Simon Glass7c58b082020-09-19 18:49:27 -0600258 ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
Simon Glass06373972020-09-19 18:49:29 -0600259 ut_assert_nextline("size: 400 1 KiB");
Simon Glassb936a972020-09-19 18:49:26 -0600260 ut_assert_nextline("alloced: 70 112 Bytes");
Simon Glass06373972020-09-19 18:49:29 -0600261 ut_assert_nextline("free: 390 912 Bytes");
Simon Glassb936a972020-09-19 18:49:26 -0600262 ut_assert_console_end();
Simon Glassb8f00822020-11-08 21:08:43 -0700263 ut_unsilence_console(uts);
Simon Glassb936a972020-09-19 18:49:26 -0600264
265 return 0;
266}
267BLOBLIST_TEST(bloblist_test_cmd_info, 0);
268
269/* Test the 'bloblist list' command */
270static int bloblist_test_cmd_list(struct unit_test_state *uts)
271{
Simon Glassb936a972020-09-19 18:49:26 -0600272 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();
Simon Glassb8f00822020-11-08 21:08:43 -0700281 ut_silence_console(uts);
Simon Glassb936a972020-09-19 18:49:26 -0600282 console_record_reset();
283 run_command("bloblist list", 0);
284 ut_assert_nextline("Address Size Tag Name");
Simon Glass7c58b082020-09-19 18:49:27 -0600285 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);
Simon Glassb936a972020-09-19 18:49:26 -0600289 ut_assert_console_end();
Simon Glassb8f00822020-11-08 21:08:43 -0700290 ut_unsilence_console(uts);
Simon Glassb936a972020-09-19 18:49:26 -0600291
292 return 0;
293}
294BLOBLIST_TEST(bloblist_test_cmd_list, 0);
295
Simon Glassd7985e62020-09-19 18:49:28 -0600296/* Test alignment of bloblist blobs */
297static int bloblist_test_align(struct unit_test_state *uts)
298{
299 struct bloblist_hdr *hdr;
Simon Glass06373972020-09-19 18:49:29 -0600300 ulong addr;
301 char *data;
Simon Glassd7985e62020-09-19 18:49:28 -0600302 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
Simon Glass06373972020-09-19 18:49:29 -0600309 /* Check the default alignment */
Simon Glassd7985e62020-09-19 18:49:28 -0600310 for (i = 0; i < 3; i++) {
311 int size = i * 3;
312 ulong addr;
313 char *data;
314 int j;
315
Simon Glass06373972020-09-19 18:49:29 -0600316 data = bloblist_add(i, size, 0);
Simon Glassd7985e62020-09-19 18:49:28 -0600317 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
Simon Glass06373972020-09-19 18:49:29 -0600328 /* 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
Simon Glassd7985e62020-09-19 18:49:28 -0600350 return 0;
351}
352BLOBLIST_TEST(bloblist_test_align, 0);
353
Simon Glassab7e7462021-01-13 20:29:43 -0700354/* Test relocation of a bloblist */
355static 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}
388BLOBLIST_TEST(bloblist_test_reloc, 0);
389
Simon Glassf20a1132021-07-05 16:32:53 -0600390/* Test expansion of a blob */
391static 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}
441BLOBLIST_TEST(bloblist_test_grow, 0);
442
443/* Test shrinking of a blob */
444static 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}
491BLOBLIST_TEST(bloblist_test_shrink, 0);
492
493/* Test failing to adjust a blob size */
494static 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}
526BLOBLIST_TEST(bloblist_test_resize_fail, 0);
527
528/* Test expanding the last blob in a bloblist */
529static 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}
577BLOBLIST_TEST(bloblist_test_resize_last, 0);
578
Simon Glass3e26de52021-07-05 16:32:55 -0600579/* Check a completely full bloblist */
580static 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}
600BLOBLIST_TEST(bloblist_test_blob_maxsize, 0);
601
Simon Glassed38aef2020-05-10 11:40:03 -0600602int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
603 char *const argv[])
Simon Glass78b0ef52018-11-15 18:43:53 -0700604{
Simon Glassb50211f2021-03-07 17:35:10 -0700605 struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test);
606 const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test);
Simon Glass78b0ef52018-11-15 18:43:53 -0700607
Philippe Reynes1f99f842019-12-17 19:07:04 +0100608 return cmd_ut_category("bloblist", "bloblist_test_",
609 tests, n_ents, argc, argv);
Simon Glass78b0ef52018-11-15 18:43:53 -0700610}