blob: 525e94b7217622862a19dba26ddc3f90d9343d92 [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
Simon Glass723ef9d2021-08-18 21:40:28 -060017/* Declare a new bloblist test */
Simon Glass78b0ef52018-11-15 18:43:53 -070018#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));
Simon Glass9341a3f2022-01-12 19:26:16 -070074 ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
Simon Glass78b0ef52018-11-15 18:43:53 -070075 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
Simon Glass9341a3f2022-01-12 19:26:16 -070076 ut_asserteq_ptr(hdr, bloblist_check_magic(TEST_ADDR));
Simon Glass78b0ef52018-11-15 18:43:53 -070077 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));
Simon Glass9341a3f2022-01-12 19:26:16 -070088
89 hdr->magic++;
90 ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
91 hdr->magic--;
92
Simon Glass78b0ef52018-11-15 18:43:53 -070093 hdr->flags++;
94 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
95
96 return 1;
97}
98BLOBLIST_TEST(bloblist_test_init, 0);
99
100static int bloblist_test_blob(struct unit_test_state *uts)
101{
102 struct bloblist_hdr *hdr;
103 struct bloblist_rec *rec, *rec2;
104 char *data;
105
106 /* At the start there should be no records */
107 hdr = clear_bloblist();
108 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
109 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
Simon Glass7c58b082020-09-19 18:49:27 -0600110 ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
Simon Glass78b0ef52018-11-15 18:43:53 -0700111
112 /* Add a record and check that we can find it */
Simon Glass06373972020-09-19 18:49:29 -0600113 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700114 rec = (void *)(hdr + 1);
Simon Glass7c58b082020-09-19 18:49:27 -0600115 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700116 data = bloblist_find(TEST_TAG, TEST_SIZE);
Simon Glass7c58b082020-09-19 18:49:27 -0600117 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700118
Simon Glass3e85ea02020-01-27 08:49:52 -0700119 /* Check the data is zeroed */
120 ut_assertok(check_zero(data, TEST_SIZE));
121
Simon Glass78b0ef52018-11-15 18:43:53 -0700122 /* Check the 'ensure' method */
Simon Glass7c58b082020-09-19 18:49:27 -0600123 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700124 ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
125 rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
Simon Glass3e85ea02020-01-27 08:49:52 -0700126 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700127
128 /* Check for a non-existent record */
Simon Glass7c58b082020-09-19 18:49:27 -0600129 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
130 ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
Simon Glass78b0ef52018-11-15 18:43:53 -0700131 ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
132
133 return 0;
134}
135BLOBLIST_TEST(bloblist_test_blob, 0);
136
Simon Glass1e0304e2020-01-27 08:49:50 -0700137/* Check bloblist_ensure_size_ret() */
138static int bloblist_test_blob_ensure(struct unit_test_state *uts)
139{
140 void *data, *data2;
141 int size;
142
143 /* At the start there should be no records */
144 clear_bloblist();
145 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
146
147 /* Test with an empty bloblist */
148 size = TEST_SIZE;
149 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
150 ut_asserteq(TEST_SIZE, size);
Simon Glass3e85ea02020-01-27 08:49:52 -0700151 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass1e0304e2020-01-27 08:49:50 -0700152
153 /* Check that we get the same thing again */
154 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
155 ut_asserteq(TEST_SIZE, size);
Simon Glass7c58b082020-09-19 18:49:27 -0600156 ut_asserteq_addr(data, data2);
Simon Glass1e0304e2020-01-27 08:49:50 -0700157
158 /* Check that the size remains the same */
159 size = TEST_SIZE2;
160 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
161 ut_asserteq(TEST_SIZE, size);
162
163 /* Check running out of space */
164 size = TEST_SIZE_LARGE;
165 ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
166
167 return 0;
168}
169BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
170
Simon Glass78b0ef52018-11-15 18:43:53 -0700171static int bloblist_test_bad_blob(struct unit_test_state *uts)
172{
173 struct bloblist_hdr *hdr;
174 void *data;
175
176 hdr = clear_bloblist();
177 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
178 data = hdr + 1;
179 data += sizeof(struct bloblist_rec);
Simon Glass7c58b082020-09-19 18:49:27 -0600180 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
181 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700182
183 return 0;
184}
185BLOBLIST_TEST(bloblist_test_bad_blob, 0);
186
187static int bloblist_test_checksum(struct unit_test_state *uts)
188{
189 struct bloblist_hdr *hdr;
190 char *data, *data2;
191
192 hdr = clear_bloblist();
193 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
194 ut_assertok(bloblist_finish());
195 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
196
197 /*
198 * Now change things amd make sure that the checksum notices. We cannot
199 * change the size or alloced fields, since that will crash the code.
200 * It has to rely on these being correct.
201 */
202 hdr->flags--;
203 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
204 hdr->flags++;
205
206 hdr->size--;
207 ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
208 hdr->size++;
209
210 hdr->spare++;
211 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
212 hdr->spare--;
213
214 hdr->chksum++;
215 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
216 hdr->chksum--;
217
218 /* Make sure the checksum changes when we add blobs */
Simon Glass06373972020-09-19 18:49:29 -0600219 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700220 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
221
Simon Glass06373972020-09-19 18:49:29 -0600222 data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700223 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
224 ut_assertok(bloblist_finish());
225
226 /* It should also change if we change the data */
227 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
228 *data += 1;
229 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
230 *data -= 1;
231
232 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
233 *data2 += 1;
234 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
235 *data2 -= 1;
236
237 /*
238 * Changing data outside the range of valid data should not affect
239 * the checksum.
240 */
241 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
242 data[TEST_SIZE]++;
243 data2[TEST_SIZE2]++;
244 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
245
246 return 0;
247}
Simon Glass78b0ef52018-11-15 18:43:53 -0700248BLOBLIST_TEST(bloblist_test_checksum, 0);
249
Simon Glassb936a972020-09-19 18:49:26 -0600250/* Test the 'bloblist info' command */
251static int bloblist_test_cmd_info(struct unit_test_state *uts)
252{
Simon Glassb936a972020-09-19 18:49:26 -0600253 struct bloblist_hdr *hdr;
254 char *data, *data2;
255
256 hdr = clear_bloblist();
257 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
258 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
259 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
260
261 console_record_reset_enable();
Simon Glassb8f00822020-11-08 21:08:43 -0700262 ut_silence_console(uts);
Simon Glassb936a972020-09-19 18:49:26 -0600263 console_record_reset();
264 run_command("bloblist info", 0);
Simon Glass7c58b082020-09-19 18:49:27 -0600265 ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
Simon Glass06373972020-09-19 18:49:29 -0600266 ut_assert_nextline("size: 400 1 KiB");
Simon Glassb936a972020-09-19 18:49:26 -0600267 ut_assert_nextline("alloced: 70 112 Bytes");
Simon Glass06373972020-09-19 18:49:29 -0600268 ut_assert_nextline("free: 390 912 Bytes");
Simon Glassb936a972020-09-19 18:49:26 -0600269 ut_assert_console_end();
Simon Glassb8f00822020-11-08 21:08:43 -0700270 ut_unsilence_console(uts);
Simon Glassb936a972020-09-19 18:49:26 -0600271
272 return 0;
273}
274BLOBLIST_TEST(bloblist_test_cmd_info, 0);
275
276/* Test the 'bloblist list' command */
277static int bloblist_test_cmd_list(struct unit_test_state *uts)
278{
Simon Glassb936a972020-09-19 18:49:26 -0600279 struct bloblist_hdr *hdr;
280 char *data, *data2;
281
282 hdr = clear_bloblist();
283 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
284 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
285 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
286
287 console_record_reset_enable();
Simon Glassb8f00822020-11-08 21:08:43 -0700288 ut_silence_console(uts);
Simon Glassb936a972020-09-19 18:49:26 -0600289 console_record_reset();
290 run_command("bloblist list", 0);
291 ut_assert_nextline("Address Size Tag Name");
Simon Glass7c58b082020-09-19 18:49:27 -0600292 ut_assert_nextline("%08lx %8x 1 EC host event",
293 (ulong)map_to_sysmem(data), TEST_SIZE);
294 ut_assert_nextline("%08lx %8x 2 SPL hand-off",
295 (ulong)map_to_sysmem(data2), TEST_SIZE2);
Simon Glassb936a972020-09-19 18:49:26 -0600296 ut_assert_console_end();
Simon Glassb8f00822020-11-08 21:08:43 -0700297 ut_unsilence_console(uts);
Simon Glassb936a972020-09-19 18:49:26 -0600298
299 return 0;
300}
301BLOBLIST_TEST(bloblist_test_cmd_list, 0);
302
Simon Glassd7985e62020-09-19 18:49:28 -0600303/* Test alignment of bloblist blobs */
304static int bloblist_test_align(struct unit_test_state *uts)
305{
306 struct bloblist_hdr *hdr;
Simon Glass06373972020-09-19 18:49:29 -0600307 ulong addr;
308 char *data;
Simon Glassd7985e62020-09-19 18:49:28 -0600309 int i;
310
311 /* At the start there should be no records */
312 hdr = clear_bloblist();
313 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
314 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
315
Simon Glass06373972020-09-19 18:49:29 -0600316 /* Check the default alignment */
Simon Glassd7985e62020-09-19 18:49:28 -0600317 for (i = 0; i < 3; i++) {
318 int size = i * 3;
319 ulong addr;
320 char *data;
321 int j;
322
Simon Glass06373972020-09-19 18:49:29 -0600323 data = bloblist_add(i, size, 0);
Simon Glassd7985e62020-09-19 18:49:28 -0600324 ut_assertnonnull(data);
325 addr = map_to_sysmem(data);
326 ut_asserteq(0, addr & (BLOBLIST_ALIGN - 1));
327
328 /* Only the bytes in the blob data should be zeroed */
329 for (j = 0; j < size; j++)
330 ut_asserteq(0, data[j]);
331 for (; j < BLOBLIST_ALIGN; j++)
332 ut_asserteq(ERASE_BYTE, data[j]);
333 }
334
Simon Glass06373972020-09-19 18:49:29 -0600335 /* Check larger alignment */
336 for (i = 0; i < 3; i++) {
337 int align = 32 << i;
338
339 data = bloblist_add(3 + i, i * 4, align);
340 ut_assertnonnull(data);
341 addr = map_to_sysmem(data);
342 ut_asserteq(0, addr & (align - 1));
343 }
344
345 /* Check alignment with an bloblist starting on a smaller alignment */
346 hdr = map_sysmem(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE);
347 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
348 memset(hdr, '\0', sizeof(*hdr));
349 ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
350 0));
351
352 data = bloblist_add(1, 5, BLOBLIST_ALIGN * 2);
353 ut_assertnonnull(data);
354 addr = map_to_sysmem(data);
355 ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1));
356
Simon Glassd7985e62020-09-19 18:49:28 -0600357 return 0;
358}
359BLOBLIST_TEST(bloblist_test_align, 0);
360
Simon Glassab7e7462021-01-13 20:29:43 -0700361/* Test relocation of a bloblist */
362static int bloblist_test_reloc(struct unit_test_state *uts)
363{
364 const uint large_size = TEST_BLOBLIST_SIZE;
365 const uint small_size = 0x20;
366 void *old_ptr, *new_ptr;
367 void *blob1, *blob2;
368 ulong new_addr;
369 ulong new_size;
370
371 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
372 old_ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
373
374 /* Add one blob and then one that won't fit */
375 blob1 = bloblist_add(TEST_TAG, small_size, 0);
376 ut_assertnonnull(blob1);
377 blob2 = bloblist_add(TEST_TAG2, large_size, 0);
378 ut_assertnull(blob2);
379
380 /* Relocate the bloblist somewhere else, a bit larger */
381 new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE;
382 new_size = TEST_BLOBLIST_SIZE + 0x100;
383 new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE);
384 bloblist_reloc(new_ptr, new_size, old_ptr, TEST_BLOBLIST_SIZE);
385 gd->bloblist = new_ptr;
386
387 /* Check the old blob is there and that we can now add the bigger one */
388 ut_assertnonnull(bloblist_find(TEST_TAG, small_size));
389 ut_assertnull(bloblist_find(TEST_TAG2, small_size));
390 blob2 = bloblist_add(TEST_TAG2, large_size, 0);
391 ut_assertnonnull(blob2);
392
393 return 0;
394}
395BLOBLIST_TEST(bloblist_test_reloc, 0);
396
Simon Glassf20a1132021-07-05 16:32:53 -0600397/* Test expansion of a blob */
398static int bloblist_test_grow(struct unit_test_state *uts)
399{
400 const uint small_size = 0x20;
401 void *blob1, *blob2, *blob1_new;
402 struct bloblist_hdr *hdr;
403 void *ptr;
404
405 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
406 hdr = ptr;
407 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
408
409 /* Create two blobs */
410 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
411 blob1 = bloblist_add(TEST_TAG, small_size, 0);
412 ut_assertnonnull(blob1);
413 ut_assertok(check_zero(blob1, small_size));
414 strcpy(blob1, test1_str);
415
416 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
417 ut_assertnonnull(blob2);
418 strcpy(blob2, test2_str);
419
420 ut_asserteq(sizeof(struct bloblist_hdr) +
421 sizeof(struct bloblist_rec) * 2 + small_size * 2,
422 hdr->alloced);
423
424 /* Resize the first one */
425 ut_assertok(bloblist_resize(TEST_TAG, small_size + 4));
426
427 /* The first one should not have moved, just got larger */
428 blob1_new = bloblist_find(TEST_TAG, small_size + 4);
429 ut_asserteq_ptr(blob1, blob1_new);
430
431 /* The new space should be zeroed */
432 ut_assertok(check_zero(blob1 + small_size, 4));
433
434 /* The second one should have moved */
435 blob2 = bloblist_find(TEST_TAG2, small_size);
436 ut_assertnonnull(blob2);
437 ut_asserteq_str(test2_str, blob2);
438
439 /* The header should have more bytes in use */
440 hdr = ptr;
441 ut_asserteq(sizeof(struct bloblist_hdr) +
442 sizeof(struct bloblist_rec) * 2 + small_size * 2 +
443 BLOBLIST_ALIGN,
444 hdr->alloced);
445
446 return 0;
447}
448BLOBLIST_TEST(bloblist_test_grow, 0);
449
450/* Test shrinking of a blob */
451static int bloblist_test_shrink(struct unit_test_state *uts)
452{
453 const uint small_size = 0x20;
454 void *blob1, *blob2, *blob1_new;
455 struct bloblist_hdr *hdr;
456 int new_size;
457 void *ptr;
458
459 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
460
461 /* Create two blobs */
462 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
463 blob1 = bloblist_add(TEST_TAG, small_size, 0);
464 ut_assertnonnull(blob1);
465 strcpy(blob1, test1_str);
466
467 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
468 ut_assertnonnull(blob2);
469 strcpy(blob2, test2_str);
470
471 hdr = ptr;
472 ut_asserteq(sizeof(struct bloblist_hdr) +
473 sizeof(struct bloblist_rec) * 2 + small_size * 2,
474 hdr->alloced);
475
476 /* Resize the first one */
477 new_size = small_size - BLOBLIST_ALIGN - 4;
478 ut_assertok(bloblist_resize(TEST_TAG, new_size));
479
480 /* The first one should not have moved, just got smaller */
481 blob1_new = bloblist_find(TEST_TAG, new_size);
482 ut_asserteq_ptr(blob1, blob1_new);
483
484 /* The second one should have moved */
485 blob2 = bloblist_find(TEST_TAG2, small_size);
486 ut_assertnonnull(blob2);
487 ut_asserteq_str(test2_str, blob2);
488
489 /* The header should have fewer bytes in use */
490 hdr = ptr;
491 ut_asserteq(sizeof(struct bloblist_hdr) +
492 sizeof(struct bloblist_rec) * 2 + small_size * 2 -
493 BLOBLIST_ALIGN,
494 hdr->alloced);
495
496 return 0;
497}
498BLOBLIST_TEST(bloblist_test_shrink, 0);
499
500/* Test failing to adjust a blob size */
501static int bloblist_test_resize_fail(struct unit_test_state *uts)
502{
503 const uint small_size = 0x20;
504 struct bloblist_hdr *hdr;
505 void *blob1, *blob2;
506 int new_size;
507 void *ptr;
508
509 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
510
511 /* Create two blobs */
512 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
513 blob1 = bloblist_add(TEST_TAG, small_size, 0);
514 ut_assertnonnull(blob1);
515
516 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
517 ut_assertnonnull(blob2);
518
519 hdr = ptr;
520 ut_asserteq(sizeof(struct bloblist_hdr) +
521 sizeof(struct bloblist_rec) * 2 + small_size * 2,
522 hdr->alloced);
523
524 /* Resize the first one, to check the boundary conditions */
525 ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1));
526
527 new_size = small_size + (hdr->size - hdr->alloced);
528 ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1));
529 ut_assertok(bloblist_resize(TEST_TAG, new_size));
530
531 return 0;
532}
533BLOBLIST_TEST(bloblist_test_resize_fail, 0);
534
535/* Test expanding the last blob in a bloblist */
536static int bloblist_test_resize_last(struct unit_test_state *uts)
537{
538 const uint small_size = 0x20;
539 struct bloblist_hdr *hdr;
540 void *blob1, *blob2, *blob2_new;
541 int alloced_val;
542 void *ptr;
543
544 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
545 memset(ptr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
546 hdr = ptr;
547
548 /* Create two blobs */
549 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
550 blob1 = bloblist_add(TEST_TAG, small_size, 0);
551 ut_assertnonnull(blob1);
552
553 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
554 ut_assertnonnull(blob2);
555
556 /* Check the byte after the last blob */
557 alloced_val = sizeof(struct bloblist_hdr) +
558 sizeof(struct bloblist_rec) * 2 + small_size * 2;
559 ut_asserteq(alloced_val, hdr->alloced);
560 ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size);
561 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced));
562
563 /* Resize the second one, checking nothing changes */
564 ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4));
565
566 blob2_new = bloblist_find(TEST_TAG2, small_size + 4);
567 ut_asserteq_ptr(blob2, blob2_new);
568
569 /*
570 * the new blob should encompass the byte we checked now, so it should
571 * be zeroed. This zeroing should affect only the four new bytes added
572 * to the blob.
573 */
574 ut_asserteq(0, *((u8 *)hdr + alloced_val));
575 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4));
576
577 /* Check that the new top of the allocated blobs has not been touched */
578 alloced_val += BLOBLIST_ALIGN;
579 ut_asserteq(alloced_val, hdr->alloced);
580 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced));
581
582 return 0;
583}
584BLOBLIST_TEST(bloblist_test_resize_last, 0);
585
Simon Glass3e26de52021-07-05 16:32:55 -0600586/* Check a completely full bloblist */
587static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
588{
589 void *ptr;
590 int size;
591
592 /* At the start there should be no records */
593 clear_bloblist();
594 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
595
596 /* Add a blob that takes up all space */
597 size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) -
598 sizeof(struct bloblist_rec);
599 ptr = bloblist_add(TEST_TAG, size, 0);
600 ut_assertnonnull(ptr);
601
602 ptr = bloblist_add(TEST_TAG, size + 1, 0);
603 ut_assertnull(ptr);
604
605 return 0;
606}
607BLOBLIST_TEST(bloblist_test_blob_maxsize, 0);
608
Simon Glassed38aef2020-05-10 11:40:03 -0600609int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
610 char *const argv[])
Simon Glass78b0ef52018-11-15 18:43:53 -0700611{
Simon Glassb50211f2021-03-07 17:35:10 -0700612 struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test);
613 const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test);
Simon Glass78b0ef52018-11-15 18:43:53 -0700614
Philippe Reynes1f99f842019-12-17 19:07:04 +0100615 return cmd_ut_category("bloblist", "bloblist_test_",
616 tests, n_ents, argc, argv);
Simon Glass78b0ef52018-11-15 18:43:53 -0700617}