blob: 17d9dd03d07acfaee339b7f58a6f6251886e0103 [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 {
Simon Glassfd20df42022-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 Glass78b0ef52018-11-15 18:43:53 -070025
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 Glassaee5a9c2023-12-27 13:07:09 -080075 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 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
Simon Glassaee5a9c2023-12-27 13:07:09 -080081 ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0xc, 0, 0));
82 ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0, 0));
83 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass78b0ef52018-11-15 18:43:53 -070084
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));
Simon Glassaee5a9c2023-12-27 13:07:09 -0800109 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass39d5ad32023-12-27 13:07:08 -0800110 ut_asserteq(sizeof(struct bloblist_hdr), bloblist_get_size());
111 ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_total_size());
Simon Glass01fd56a2022-01-12 19:26:23 -0700112 ut_asserteq(TEST_ADDR, bloblist_get_base());
Simon Glass7c58b082020-09-19 18:49:27 -0600113 ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
Simon Glass78b0ef52018-11-15 18:43:53 -0700114
115 /* Add a record and check that we can find it */
Simon Glass06373972020-09-19 18:49:29 -0600116 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700117 rec = (void *)(hdr + 1);
Simon Glass7c58b082020-09-19 18:49:27 -0600118 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700119 data = bloblist_find(TEST_TAG, TEST_SIZE);
Simon Glass7c58b082020-09-19 18:49:27 -0600120 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700121
Simon Glass3e85ea02020-01-27 08:49:52 -0700122 /* Check the data is zeroed */
123 ut_assertok(check_zero(data, TEST_SIZE));
124
Simon Glass78b0ef52018-11-15 18:43:53 -0700125 /* Check the 'ensure' method */
Simon Glass7c58b082020-09-19 18:49:27 -0600126 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700127 ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
128 rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
Simon Glass3e85ea02020-01-27 08:49:52 -0700129 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700130
131 /* Check for a non-existent record */
Simon Glass7c58b082020-09-19 18:49:27 -0600132 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
133 ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
Simon Glass78b0ef52018-11-15 18:43:53 -0700134 ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
135
136 return 0;
137}
138BLOBLIST_TEST(bloblist_test_blob, 0);
139
Simon Glass1e0304e2020-01-27 08:49:50 -0700140/* Check bloblist_ensure_size_ret() */
141static int bloblist_test_blob_ensure(struct unit_test_state *uts)
142{
143 void *data, *data2;
144 int size;
145
146 /* At the start there should be no records */
147 clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800148 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass1e0304e2020-01-27 08:49:50 -0700149
150 /* Test with an empty bloblist */
151 size = TEST_SIZE;
152 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
153 ut_asserteq(TEST_SIZE, size);
Simon Glass3e85ea02020-01-27 08:49:52 -0700154 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass1e0304e2020-01-27 08:49:50 -0700155
156 /* Check that we get the same thing again */
157 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
158 ut_asserteq(TEST_SIZE, size);
Simon Glass7c58b082020-09-19 18:49:27 -0600159 ut_asserteq_addr(data, data2);
Simon Glass1e0304e2020-01-27 08:49:50 -0700160
161 /* Check that the size remains the same */
162 size = TEST_SIZE2;
163 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
164 ut_asserteq(TEST_SIZE, size);
165
166 /* Check running out of space */
167 size = TEST_SIZE_LARGE;
168 ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
169
170 return 0;
171}
172BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
173
Simon Glass78b0ef52018-11-15 18:43:53 -0700174static int bloblist_test_bad_blob(struct unit_test_state *uts)
175{
176 struct bloblist_hdr *hdr;
177 void *data;
178
179 hdr = clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800180 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass78b0ef52018-11-15 18:43:53 -0700181 data = hdr + 1;
182 data += sizeof(struct bloblist_rec);
Simon Glass7c58b082020-09-19 18:49:27 -0600183 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
184 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700185
186 return 0;
187}
188BLOBLIST_TEST(bloblist_test_bad_blob, 0);
189
190static int bloblist_test_checksum(struct unit_test_state *uts)
191{
192 struct bloblist_hdr *hdr;
193 char *data, *data2;
194
195 hdr = clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800196 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass78b0ef52018-11-15 18:43:53 -0700197 ut_assertok(bloblist_finish());
198 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
199
200 /*
201 * Now change things amd make sure that the checksum notices. We cannot
202 * change the size or alloced fields, since that will crash the code.
203 * It has to rely on these being correct.
204 */
205 hdr->flags--;
206 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
207 hdr->flags++;
208
Simon Glass39d5ad32023-12-27 13:07:08 -0800209 hdr->total_size--;
Simon Glass78b0ef52018-11-15 18:43:53 -0700210 ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
Simon Glass39d5ad32023-12-27 13:07:08 -0800211 hdr->total_size++;
Simon Glass78b0ef52018-11-15 18:43:53 -0700212
213 hdr->spare++;
214 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
215 hdr->spare--;
216
217 hdr->chksum++;
218 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
219 hdr->chksum--;
220
Simon Glassaee5a9c2023-12-27 13:07:09 -0800221 hdr->align_log2++;
222 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
223 hdr->align_log2--;
224
Simon Glass78b0ef52018-11-15 18:43:53 -0700225 /* Make sure the checksum changes when we add blobs */
Simon Glass06373972020-09-19 18:49:29 -0600226 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700227 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
228
Simon Glass06373972020-09-19 18:49:29 -0600229 data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700230 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
231 ut_assertok(bloblist_finish());
232
233 /* It should also change if we change the data */
234 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
235 *data += 1;
236 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
237 *data -= 1;
238
239 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
240 *data2 += 1;
241 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
242 *data2 -= 1;
243
244 /*
Simon Glass8968c052023-12-27 13:07:05 -0800245 * Changing data outside the range of valid data should affect the
246 * checksum.
Simon Glass78b0ef52018-11-15 18:43:53 -0700247 */
248 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
249 data[TEST_SIZE]++;
Simon Glass8968c052023-12-27 13:07:05 -0800250 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
251 data[TEST_SIZE]--;
252 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
253
Simon Glass78b0ef52018-11-15 18:43:53 -0700254 data2[TEST_SIZE2]++;
Simon Glass8968c052023-12-27 13:07:05 -0800255 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
256 data[TEST_SIZE]--;
Simon Glass78b0ef52018-11-15 18:43:53 -0700257 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
258
259 return 0;
260}
Simon Glass78b0ef52018-11-15 18:43:53 -0700261BLOBLIST_TEST(bloblist_test_checksum, 0);
262
Simon Glassb936a972020-09-19 18:49:26 -0600263/* Test the 'bloblist info' command */
264static int bloblist_test_cmd_info(struct unit_test_state *uts)
265{
Simon Glassb936a972020-09-19 18:49:26 -0600266 struct bloblist_hdr *hdr;
267 char *data, *data2;
268
269 hdr = clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800270 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassb936a972020-09-19 18:49:26 -0600271 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
272 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
273
274 console_record_reset_enable();
Simon Glassb8f00822020-11-08 21:08:43 -0700275 ut_silence_console(uts);
Simon Glassb936a972020-09-19 18:49:26 -0600276 console_record_reset();
277 run_command("bloblist info", 0);
Simon Glass39d5ad32023-12-27 13:07:08 -0800278 ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
279 ut_assert_nextline("total size: 400 1 KiB");
280 ut_assert_nextline("used size: 50 80 Bytes");
281 ut_assert_nextline("free: 3b0 944 Bytes");
Simon Glassb936a972020-09-19 18:49:26 -0600282 ut_assert_console_end();
Simon Glassb8f00822020-11-08 21:08:43 -0700283 ut_unsilence_console(uts);
Simon Glassb936a972020-09-19 18:49:26 -0600284
285 return 0;
286}
287BLOBLIST_TEST(bloblist_test_cmd_info, 0);
288
289/* Test the 'bloblist list' command */
290static int bloblist_test_cmd_list(struct unit_test_state *uts)
291{
Simon Glassb936a972020-09-19 18:49:26 -0600292 struct bloblist_hdr *hdr;
293 char *data, *data2;
294
295 hdr = clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800296 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassb936a972020-09-19 18:49:26 -0600297 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
298 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
299
300 console_record_reset_enable();
Simon Glassb8f00822020-11-08 21:08:43 -0700301 ut_silence_console(uts);
Simon Glassb936a972020-09-19 18:49:26 -0600302 console_record_reset();
303 run_command("bloblist list", 0);
Simon Glassfd20df42022-01-12 19:26:19 -0700304 ut_assert_nextline("Address Size Tag Name");
Simon Glass871e5d02023-12-27 13:06:59 -0800305 ut_assert_nextline("%08lx %8x fff000 SPL hand-off",
Simon Glass7c58b082020-09-19 18:49:27 -0600306 (ulong)map_to_sysmem(data), TEST_SIZE);
Simon Glass871e5d02023-12-27 13:06:59 -0800307 ut_assert_nextline("%08lx %8x 202 Chrome OS vboot context",
Simon Glass7c58b082020-09-19 18:49:27 -0600308 (ulong)map_to_sysmem(data2), TEST_SIZE2);
Simon Glassb936a972020-09-19 18:49:26 -0600309 ut_assert_console_end();
Simon Glassb8f00822020-11-08 21:08:43 -0700310 ut_unsilence_console(uts);
Simon Glassb936a972020-09-19 18:49:26 -0600311
312 return 0;
313}
314BLOBLIST_TEST(bloblist_test_cmd_list, 0);
315
Simon Glassd7985e62020-09-19 18:49:28 -0600316/* Test alignment of bloblist blobs */
317static int bloblist_test_align(struct unit_test_state *uts)
318{
319 struct bloblist_hdr *hdr;
Simon Glass06373972020-09-19 18:49:29 -0600320 ulong addr;
321 char *data;
Simon Glassd7985e62020-09-19 18:49:28 -0600322 int i;
323
324 /* At the start there should be no records */
325 hdr = clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800326 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassd7985e62020-09-19 18:49:28 -0600327 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
328
Simon Glass06373972020-09-19 18:49:29 -0600329 /* Check the default alignment */
Simon Glassd7985e62020-09-19 18:49:28 -0600330 for (i = 0; i < 3; i++) {
331 int size = i * 3;
332 ulong addr;
333 char *data;
334 int j;
335
Simon Glass06373972020-09-19 18:49:29 -0600336 data = bloblist_add(i, size, 0);
Simon Glassd7985e62020-09-19 18:49:28 -0600337 ut_assertnonnull(data);
338 addr = map_to_sysmem(data);
Simon Glass703a5da2023-12-27 13:07:07 -0800339 ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN - 1));
Simon Glassd7985e62020-09-19 18:49:28 -0600340
341 /* Only the bytes in the blob data should be zeroed */
342 for (j = 0; j < size; j++)
343 ut_asserteq(0, data[j]);
Simon Glass703a5da2023-12-27 13:07:07 -0800344 for (; j < BLOBLIST_BLOB_ALIGN; j++)
Simon Glassd7985e62020-09-19 18:49:28 -0600345 ut_asserteq(ERASE_BYTE, data[j]);
346 }
347
Simon Glass06373972020-09-19 18:49:29 -0600348 /* Check larger alignment */
349 for (i = 0; i < 3; i++) {
Simon Glassc2aa4ef2023-12-27 13:07:00 -0800350 int align = 5 - i;
Simon Glass06373972020-09-19 18:49:29 -0600351
352 data = bloblist_add(3 + i, i * 4, align);
353 ut_assertnonnull(data);
354 addr = map_to_sysmem(data);
355 ut_asserteq(0, addr & (align - 1));
356 }
357
358 /* Check alignment with an bloblist starting on a smaller alignment */
Simon Glass703a5da2023-12-27 13:07:07 -0800359 hdr = map_sysmem(TEST_ADDR + BLOBLIST_BLOB_ALIGN, TEST_BLOBLIST_SIZE);
Simon Glass06373972020-09-19 18:49:29 -0600360 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
361 memset(hdr, '\0', sizeof(*hdr));
362 ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
Simon Glassaee5a9c2023-12-27 13:07:09 -0800363 0, 0));
Simon Glass06373972020-09-19 18:49:29 -0600364
Simon Glassc2aa4ef2023-12-27 13:07:00 -0800365 data = bloblist_add(1, 5, BLOBLIST_ALIGN_LOG2 + 1);
Simon Glass06373972020-09-19 18:49:29 -0600366 ut_assertnonnull(data);
367 addr = map_to_sysmem(data);
Simon Glass703a5da2023-12-27 13:07:07 -0800368 ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN * 2 - 1));
Simon Glass06373972020-09-19 18:49:29 -0600369
Simon Glassd7985e62020-09-19 18:49:28 -0600370 return 0;
371}
372BLOBLIST_TEST(bloblist_test_align, 0);
373
Simon Glassab7e7462021-01-13 20:29:43 -0700374/* Test relocation of a bloblist */
375static int bloblist_test_reloc(struct unit_test_state *uts)
376{
377 const uint large_size = TEST_BLOBLIST_SIZE;
378 const uint small_size = 0x20;
379 void *old_ptr, *new_ptr;
380 void *blob1, *blob2;
381 ulong new_addr;
382 ulong new_size;
383
Simon Glassaee5a9c2023-12-27 13:07:09 -0800384 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassab7e7462021-01-13 20:29:43 -0700385 old_ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
386
387 /* Add one blob and then one that won't fit */
388 blob1 = bloblist_add(TEST_TAG, small_size, 0);
389 ut_assertnonnull(blob1);
390 blob2 = bloblist_add(TEST_TAG2, large_size, 0);
391 ut_assertnull(blob2);
392
393 /* Relocate the bloblist somewhere else, a bit larger */
394 new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE;
395 new_size = TEST_BLOBLIST_SIZE + 0x100;
396 new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE);
397 bloblist_reloc(new_ptr, new_size, old_ptr, TEST_BLOBLIST_SIZE);
398 gd->bloblist = new_ptr;
399
400 /* Check the old blob is there and that we can now add the bigger one */
401 ut_assertnonnull(bloblist_find(TEST_TAG, small_size));
402 ut_assertnull(bloblist_find(TEST_TAG2, small_size));
403 blob2 = bloblist_add(TEST_TAG2, large_size, 0);
404 ut_assertnonnull(blob2);
405
406 return 0;
407}
408BLOBLIST_TEST(bloblist_test_reloc, 0);
409
Simon Glassf20a1132021-07-05 16:32:53 -0600410/* Test expansion of a blob */
411static int bloblist_test_grow(struct unit_test_state *uts)
412{
413 const uint small_size = 0x20;
414 void *blob1, *blob2, *blob1_new;
415 struct bloblist_hdr *hdr;
416 void *ptr;
417
418 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
419 hdr = ptr;
420 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
421
422 /* Create two blobs */
Simon Glassaee5a9c2023-12-27 13:07:09 -0800423 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassf20a1132021-07-05 16:32:53 -0600424 blob1 = bloblist_add(TEST_TAG, small_size, 0);
425 ut_assertnonnull(blob1);
426 ut_assertok(check_zero(blob1, small_size));
427 strcpy(blob1, test1_str);
428
429 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
430 ut_assertnonnull(blob2);
431 strcpy(blob2, test2_str);
432
433 ut_asserteq(sizeof(struct bloblist_hdr) +
434 sizeof(struct bloblist_rec) * 2 + small_size * 2,
Simon Glass39d5ad32023-12-27 13:07:08 -0800435 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600436
437 /* Resize the first one */
438 ut_assertok(bloblist_resize(TEST_TAG, small_size + 4));
439
440 /* The first one should not have moved, just got larger */
441 blob1_new = bloblist_find(TEST_TAG, small_size + 4);
442 ut_asserteq_ptr(blob1, blob1_new);
443
444 /* The new space should be zeroed */
445 ut_assertok(check_zero(blob1 + small_size, 4));
446
447 /* The second one should have moved */
448 blob2 = bloblist_find(TEST_TAG2, small_size);
449 ut_assertnonnull(blob2);
450 ut_asserteq_str(test2_str, blob2);
451
452 /* The header should have more bytes in use */
453 hdr = ptr;
454 ut_asserteq(sizeof(struct bloblist_hdr) +
455 sizeof(struct bloblist_rec) * 2 + small_size * 2 +
Simon Glass703a5da2023-12-27 13:07:07 -0800456 BLOBLIST_BLOB_ALIGN,
Simon Glass39d5ad32023-12-27 13:07:08 -0800457 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600458
459 return 0;
460}
461BLOBLIST_TEST(bloblist_test_grow, 0);
462
463/* Test shrinking of a blob */
464static int bloblist_test_shrink(struct unit_test_state *uts)
465{
466 const uint small_size = 0x20;
467 void *blob1, *blob2, *blob1_new;
468 struct bloblist_hdr *hdr;
469 int new_size;
470 void *ptr;
471
472 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
473
474 /* Create two blobs */
Simon Glassaee5a9c2023-12-27 13:07:09 -0800475 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassf20a1132021-07-05 16:32:53 -0600476 blob1 = bloblist_add(TEST_TAG, small_size, 0);
477 ut_assertnonnull(blob1);
478 strcpy(blob1, test1_str);
479
480 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
481 ut_assertnonnull(blob2);
482 strcpy(blob2, test2_str);
483
484 hdr = ptr;
485 ut_asserteq(sizeof(struct bloblist_hdr) +
486 sizeof(struct bloblist_rec) * 2 + small_size * 2,
Simon Glass39d5ad32023-12-27 13:07:08 -0800487 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600488
489 /* Resize the first one */
490 new_size = small_size - BLOBLIST_ALIGN - 4;
491 ut_assertok(bloblist_resize(TEST_TAG, new_size));
492
493 /* The first one should not have moved, just got smaller */
494 blob1_new = bloblist_find(TEST_TAG, new_size);
495 ut_asserteq_ptr(blob1, blob1_new);
496
497 /* The second one should have moved */
498 blob2 = bloblist_find(TEST_TAG2, small_size);
499 ut_assertnonnull(blob2);
500 ut_asserteq_str(test2_str, blob2);
501
502 /* The header should have fewer bytes in use */
503 hdr = ptr;
504 ut_asserteq(sizeof(struct bloblist_hdr) +
505 sizeof(struct bloblist_rec) * 2 + small_size * 2 -
506 BLOBLIST_ALIGN,
Simon Glass39d5ad32023-12-27 13:07:08 -0800507 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600508
509 return 0;
510}
511BLOBLIST_TEST(bloblist_test_shrink, 0);
512
513/* Test failing to adjust a blob size */
514static int bloblist_test_resize_fail(struct unit_test_state *uts)
515{
516 const uint small_size = 0x20;
517 struct bloblist_hdr *hdr;
518 void *blob1, *blob2;
519 int new_size;
520 void *ptr;
521
522 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
523
524 /* Create two blobs */
Simon Glassaee5a9c2023-12-27 13:07:09 -0800525 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassf20a1132021-07-05 16:32:53 -0600526 blob1 = bloblist_add(TEST_TAG, small_size, 0);
527 ut_assertnonnull(blob1);
528
529 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
530 ut_assertnonnull(blob2);
531
532 hdr = ptr;
533 ut_asserteq(sizeof(struct bloblist_hdr) +
534 sizeof(struct bloblist_rec) * 2 + small_size * 2,
Simon Glass39d5ad32023-12-27 13:07:08 -0800535 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600536
537 /* Resize the first one, to check the boundary conditions */
538 ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1));
539
Simon Glass39d5ad32023-12-27 13:07:08 -0800540 new_size = small_size + (hdr->total_size - hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600541 ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1));
542 ut_assertok(bloblist_resize(TEST_TAG, new_size));
543
544 return 0;
545}
546BLOBLIST_TEST(bloblist_test_resize_fail, 0);
547
548/* Test expanding the last blob in a bloblist */
549static int bloblist_test_resize_last(struct unit_test_state *uts)
550{
551 const uint small_size = 0x20;
552 struct bloblist_hdr *hdr;
553 void *blob1, *blob2, *blob2_new;
554 int alloced_val;
555 void *ptr;
556
557 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
558 memset(ptr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
559 hdr = ptr;
560
561 /* Create two blobs */
Simon Glassaee5a9c2023-12-27 13:07:09 -0800562 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassf20a1132021-07-05 16:32:53 -0600563 blob1 = bloblist_add(TEST_TAG, small_size, 0);
564 ut_assertnonnull(blob1);
565
566 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
567 ut_assertnonnull(blob2);
568
569 /* Check the byte after the last blob */
570 alloced_val = sizeof(struct bloblist_hdr) +
571 sizeof(struct bloblist_rec) * 2 + small_size * 2;
Simon Glass39d5ad32023-12-27 13:07:08 -0800572 ut_asserteq(alloced_val, hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600573 ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size);
Simon Glass39d5ad32023-12-27 13:07:08 -0800574 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
Simon Glassf20a1132021-07-05 16:32:53 -0600575
576 /* Resize the second one, checking nothing changes */
577 ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4));
578
579 blob2_new = bloblist_find(TEST_TAG2, small_size + 4);
580 ut_asserteq_ptr(blob2, blob2_new);
581
582 /*
583 * the new blob should encompass the byte we checked now, so it should
584 * be zeroed. This zeroing should affect only the four new bytes added
585 * to the blob.
586 */
587 ut_asserteq(0, *((u8 *)hdr + alloced_val));
588 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4));
589
590 /* Check that the new top of the allocated blobs has not been touched */
Simon Glass703a5da2023-12-27 13:07:07 -0800591 alloced_val += BLOBLIST_BLOB_ALIGN;
Simon Glass39d5ad32023-12-27 13:07:08 -0800592 ut_asserteq(alloced_val, hdr->used_size);
593 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
Simon Glassf20a1132021-07-05 16:32:53 -0600594
595 return 0;
596}
597BLOBLIST_TEST(bloblist_test_resize_last, 0);
598
Simon Glass3e26de52021-07-05 16:32:55 -0600599/* Check a completely full bloblist */
600static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
601{
602 void *ptr;
603 int size;
604
605 /* At the start there should be no records */
606 clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800607 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass3e26de52021-07-05 16:32:55 -0600608
609 /* Add a blob that takes up all space */
610 size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) -
611 sizeof(struct bloblist_rec);
612 ptr = bloblist_add(TEST_TAG, size, 0);
613 ut_assertnonnull(ptr);
614
615 ptr = bloblist_add(TEST_TAG, size + 1, 0);
616 ut_assertnull(ptr);
617
618 return 0;
619}
620BLOBLIST_TEST(bloblist_test_blob_maxsize, 0);
621
Simon Glassed38aef2020-05-10 11:40:03 -0600622int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
623 char *const argv[])
Simon Glass78b0ef52018-11-15 18:43:53 -0700624{
Simon Glassb50211f2021-03-07 17:35:10 -0700625 struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test);
626 const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test);
Simon Glass78b0ef52018-11-15 18:43:53 -0700627
Philippe Reynes1f99f842019-12-17 19:07:04 +0100628 return cmd_ut_category("bloblist", "bloblist_test_",
629 tests, n_ents, argc, argv);
Simon Glass78b0ef52018-11-15 18:43:53 -0700630}