blob: 49ac4b92aee980ae3a2473b1fb332c2419e97d57 [file] [log] [blame]
Simon Glass919e7a82018-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 Glass401d1c42020-10-30 21:38:53 -060010#include <asm/global_data.h>
Simon Glass919e7a82018-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 Glass127ca102021-08-18 21:40:28 -060017/* Declare a new bloblist test */
Simon Glass919e7a82018-11-15 18:43:53 -070018#define BLOBLIST_TEST(_name, _flags) \
19 UNIT_TEST(_name, _flags, bloblist_test)
20
21enum {
Simon Glassf16ec772022-01-12 19:26:19 -070022 TEST_TAG = BLOBLISTT_U_BOOT_SPL_HANDOFF,
23 TEST_TAG2 = BLOBLISTT_VBOOT_CTX,
24 TEST_TAG_MISSING = 0x10000,
Simon Glass919e7a82018-11-15 18:43:53 -070025
26 TEST_SIZE = 10,
27 TEST_SIZE2 = 20,
Simon Glass4c1497e2020-09-19 18:49:29 -060028 TEST_SIZE_LARGE = 0x3e0,
Simon Glass919e7a82018-11-15 18:43:53 -070029
30 TEST_ADDR = CONFIG_BLOBLIST_ADDR,
Simon Glass4c1497e2020-09-19 18:49:29 -060031 TEST_BLOBLIST_SIZE = 0x400,
Simon Glass751b7c72020-09-19 18:49:28 -060032
33 ERASE_BYTE = '\xff',
Simon Glass919e7a82018-11-15 18:43:53 -070034};
35
Simon Glass1fe59372021-07-05 16:32:53 -060036static const char test1_str[] = "the eyes are open";
37static const char test2_str[] = "the mouth moves";
38
Simon Glass919e7a82018-11-15 18:43:53 -070039static struct bloblist_hdr *clear_bloblist(void)
40{
41 struct bloblist_hdr *hdr;
42
Simon Glassb83994d2020-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 Glass919e7a82018-11-15 18:43:53 -070048 hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
Simon Glass751b7c72020-09-19 18:49:28 -060049 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
Simon Glassb83994d2020-01-27 08:49:52 -070050 memset(hdr, '\0', sizeof(*hdr));
Simon Glass919e7a82018-11-15 18:43:53 -070051
52 return hdr;
53}
54
Simon Glassb83994d2020-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 Glass919e7a82018-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 Glassff3bd492022-01-12 19:26:16 -070074 ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
Simon Glass919e7a82018-11-15 18:43:53 -070075 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
Simon Glassff3bd492022-01-12 19:26:16 -070076 ut_asserteq_ptr(hdr, bloblist_check_magic(TEST_ADDR));
Simon Glass919e7a82018-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 Glassff3bd492022-01-12 19:26:16 -070088
89 hdr->magic++;
90 ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
91 hdr->magic--;
92
Simon Glass919e7a82018-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 Glasse50a24a2022-01-12 19:26:23 -0700110 ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_size());
111 ut_asserteq(TEST_ADDR, bloblist_get_base());
Simon Glasscdd4e302020-09-19 18:49:27 -0600112 ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
Simon Glass919e7a82018-11-15 18:43:53 -0700113
114 /* Add a record and check that we can find it */
Simon Glass4c1497e2020-09-19 18:49:29 -0600115 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass919e7a82018-11-15 18:43:53 -0700116 rec = (void *)(hdr + 1);
Simon Glasscdd4e302020-09-19 18:49:27 -0600117 ut_asserteq_addr(rec + 1, data);
Simon Glass919e7a82018-11-15 18:43:53 -0700118 data = bloblist_find(TEST_TAG, TEST_SIZE);
Simon Glasscdd4e302020-09-19 18:49:27 -0600119 ut_asserteq_addr(rec + 1, data);
Simon Glass919e7a82018-11-15 18:43:53 -0700120
Simon Glassb83994d2020-01-27 08:49:52 -0700121 /* Check the data is zeroed */
122 ut_assertok(check_zero(data, TEST_SIZE));
123
Simon Glass919e7a82018-11-15 18:43:53 -0700124 /* Check the 'ensure' method */
Simon Glasscdd4e302020-09-19 18:49:27 -0600125 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass919e7a82018-11-15 18:43:53 -0700126 ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
127 rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
Simon Glassb83994d2020-01-27 08:49:52 -0700128 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass919e7a82018-11-15 18:43:53 -0700129
130 /* Check for a non-existent record */
Simon Glasscdd4e302020-09-19 18:49:27 -0600131 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
132 ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
Simon Glass919e7a82018-11-15 18:43:53 -0700133 ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
134
135 return 0;
136}
137BLOBLIST_TEST(bloblist_test_blob, 0);
138
Simon Glass5b044542020-01-27 08:49:50 -0700139/* Check bloblist_ensure_size_ret() */
140static 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);
Simon Glassb83994d2020-01-27 08:49:52 -0700153 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass5b044542020-01-27 08:49:50 -0700154
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);
Simon Glasscdd4e302020-09-19 18:49:27 -0600158 ut_asserteq_addr(data, data2);
Simon Glass5b044542020-01-27 08:49:50 -0700159
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}
171BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
172
Simon Glass919e7a82018-11-15 18:43:53 -0700173static 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);
Simon Glasscdd4e302020-09-19 18:49:27 -0600182 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
183 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass919e7a82018-11-15 18:43:53 -0700184
185 return 0;
186}
187BLOBLIST_TEST(bloblist_test_bad_blob, 0);
188
189static 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 */
Simon Glass4c1497e2020-09-19 18:49:29 -0600221 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass919e7a82018-11-15 18:43:53 -0700222 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
223
Simon Glass4c1497e2020-09-19 18:49:29 -0600224 data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
Simon Glass919e7a82018-11-15 18:43:53 -0700225 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 /*
Simon Glass997dac62023-12-27 13:07:05 -0800240 * Changing data outside the range of valid data should affect the
241 * checksum.
Simon Glass919e7a82018-11-15 18:43:53 -0700242 */
243 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
244 data[TEST_SIZE]++;
Simon Glass997dac62023-12-27 13:07:05 -0800245 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
Simon Glass919e7a82018-11-15 18:43:53 -0700249 data2[TEST_SIZE2]++;
Simon Glass997dac62023-12-27 13:07:05 -0800250 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
251 data[TEST_SIZE]--;
Simon Glass919e7a82018-11-15 18:43:53 -0700252 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
253
254 return 0;
255}
Simon Glass919e7a82018-11-15 18:43:53 -0700256BLOBLIST_TEST(bloblist_test_checksum, 0);
257
Simon Glass4aed2272020-09-19 18:49:26 -0600258/* Test the 'bloblist info' command */
259static int bloblist_test_cmd_info(struct unit_test_state *uts)
260{
Simon Glass4aed2272020-09-19 18:49:26 -0600261 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();
Simon Glassef7e2642020-11-08 21:08:43 -0700270 ut_silence_console(uts);
Simon Glass4aed2272020-09-19 18:49:26 -0600271 console_record_reset();
272 run_command("bloblist info", 0);
Simon Glasscdd4e302020-09-19 18:49:27 -0600273 ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
Simon Glass4c1497e2020-09-19 18:49:29 -0600274 ut_assert_nextline("size: 400 1 KiB");
Simon Glass4aed2272020-09-19 18:49:26 -0600275 ut_assert_nextline("alloced: 70 112 Bytes");
Simon Glass4c1497e2020-09-19 18:49:29 -0600276 ut_assert_nextline("free: 390 912 Bytes");
Simon Glass4aed2272020-09-19 18:49:26 -0600277 ut_assert_console_end();
Simon Glassef7e2642020-11-08 21:08:43 -0700278 ut_unsilence_console(uts);
Simon Glass4aed2272020-09-19 18:49:26 -0600279
280 return 0;
281}
282BLOBLIST_TEST(bloblist_test_cmd_info, 0);
283
284/* Test the 'bloblist list' command */
285static int bloblist_test_cmd_list(struct unit_test_state *uts)
286{
Simon Glass4aed2272020-09-19 18:49:26 -0600287 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();
Simon Glassef7e2642020-11-08 21:08:43 -0700296 ut_silence_console(uts);
Simon Glass4aed2272020-09-19 18:49:26 -0600297 console_record_reset();
298 run_command("bloblist list", 0);
Simon Glassf16ec772022-01-12 19:26:19 -0700299 ut_assert_nextline("Address Size Tag Name");
Simon Glasse748e4b2023-12-27 13:06:59 -0800300 ut_assert_nextline("%08lx %8x fff000 SPL hand-off",
Simon Glasscdd4e302020-09-19 18:49:27 -0600301 (ulong)map_to_sysmem(data), TEST_SIZE);
Simon Glasse748e4b2023-12-27 13:06:59 -0800302 ut_assert_nextline("%08lx %8x 202 Chrome OS vboot context",
Simon Glasscdd4e302020-09-19 18:49:27 -0600303 (ulong)map_to_sysmem(data2), TEST_SIZE2);
Simon Glass4aed2272020-09-19 18:49:26 -0600304 ut_assert_console_end();
Simon Glassef7e2642020-11-08 21:08:43 -0700305 ut_unsilence_console(uts);
Simon Glass4aed2272020-09-19 18:49:26 -0600306
307 return 0;
308}
309BLOBLIST_TEST(bloblist_test_cmd_list, 0);
310
Simon Glass751b7c72020-09-19 18:49:28 -0600311/* Test alignment of bloblist blobs */
312static int bloblist_test_align(struct unit_test_state *uts)
313{
314 struct bloblist_hdr *hdr;
Simon Glass4c1497e2020-09-19 18:49:29 -0600315 ulong addr;
316 char *data;
Simon Glass751b7c72020-09-19 18:49:28 -0600317 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
Simon Glass4c1497e2020-09-19 18:49:29 -0600324 /* Check the default alignment */
Simon Glass751b7c72020-09-19 18:49:28 -0600325 for (i = 0; i < 3; i++) {
326 int size = i * 3;
327 ulong addr;
328 char *data;
329 int j;
330
Simon Glass4c1497e2020-09-19 18:49:29 -0600331 data = bloblist_add(i, size, 0);
Simon Glass751b7c72020-09-19 18:49:28 -0600332 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
Simon Glass4c1497e2020-09-19 18:49:29 -0600343 /* Check larger alignment */
344 for (i = 0; i < 3; i++) {
Simon Glass1a2e02f2023-12-27 13:07:00 -0800345 int align = 5 - i;
Simon Glass4c1497e2020-09-19 18:49:29 -0600346
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
Simon Glass1a2e02f2023-12-27 13:07:00 -0800360 data = bloblist_add(1, 5, BLOBLIST_ALIGN_LOG2 + 1);
Simon Glass4c1497e2020-09-19 18:49:29 -0600361 ut_assertnonnull(data);
362 addr = map_to_sysmem(data);
363 ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1));
364
Simon Glass751b7c72020-09-19 18:49:28 -0600365 return 0;
366}
367BLOBLIST_TEST(bloblist_test_align, 0);
368
Simon Glass9fe06462021-01-13 20:29:43 -0700369/* Test relocation of a bloblist */
370static 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}
403BLOBLIST_TEST(bloblist_test_reloc, 0);
404
Simon Glass1fe59372021-07-05 16:32:53 -0600405/* Test expansion of a blob */
406static 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}
456BLOBLIST_TEST(bloblist_test_grow, 0);
457
458/* Test shrinking of a blob */
459static 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}
506BLOBLIST_TEST(bloblist_test_shrink, 0);
507
508/* Test failing to adjust a blob size */
509static 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}
541BLOBLIST_TEST(bloblist_test_resize_fail, 0);
542
543/* Test expanding the last blob in a bloblist */
544static 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}
592BLOBLIST_TEST(bloblist_test_resize_last, 0);
593
Simon Glass1f618d52021-07-05 16:32:55 -0600594/* Check a completely full bloblist */
595static 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}
615BLOBLIST_TEST(bloblist_test_blob_maxsize, 0);
616
Simon Glass09140112020-05-10 11:40:03 -0600617int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
618 char *const argv[])
Simon Glass919e7a82018-11-15 18:43:53 -0700619{
Simon Glassa7a98752021-03-07 17:35:10 -0700620 struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test);
621 const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test);
Simon Glass919e7a82018-11-15 18:43:53 -0700622
Philippe Reynes4ad4edf2019-12-17 19:07:04 +0100623 return cmd_ut_category("bloblist", "bloblist_test_",
624 tests, n_ents, argc, argv);
Simon Glass919e7a82018-11-15 18:43:53 -0700625}