blob: ab8f41c6808351af06819b075428bd770eb073e0 [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
Simon Glass78b0ef52018-11-15 18:43:53 -07006#include <bloblist.h>
7#include <log.h>
8#include <mapmem.h>
9#include <test/suites.h>
10#include <test/test.h>
11#include <test/ut.h>
12
Simon Glass723ef9d2021-08-18 21:40:28 -060013/* Declare a new bloblist test */
Simon Glass78b0ef52018-11-15 18:43:53 -070014#define BLOBLIST_TEST(_name, _flags) \
Simon Glassb15512c2025-01-20 14:25:32 -070015 UNIT_TEST(_name, _flags, bloblist)
Simon Glass78b0ef52018-11-15 18:43:53 -070016
17enum {
Simon Glassfd20df42022-01-12 19:26:19 -070018 TEST_TAG = BLOBLISTT_U_BOOT_SPL_HANDOFF,
19 TEST_TAG2 = BLOBLISTT_VBOOT_CTX,
20 TEST_TAG_MISSING = 0x10000,
Simon Glass78b0ef52018-11-15 18:43:53 -070021
22 TEST_SIZE = 10,
23 TEST_SIZE2 = 20,
Simon Glass06373972020-09-19 18:49:29 -060024 TEST_SIZE_LARGE = 0x3e0,
Simon Glass78b0ef52018-11-15 18:43:53 -070025
26 TEST_ADDR = CONFIG_BLOBLIST_ADDR,
Simon Glass06373972020-09-19 18:49:29 -060027 TEST_BLOBLIST_SIZE = 0x400,
Simon Glassd7985e62020-09-19 18:49:28 -060028
29 ERASE_BYTE = '\xff',
Simon Glass78b0ef52018-11-15 18:43:53 -070030};
31
Simon Glassf20a1132021-07-05 16:32:53 -060032static const char test1_str[] = "the eyes are open";
33static const char test2_str[] = "the mouth moves";
34
Simon Glass78b0ef52018-11-15 18:43:53 -070035static struct bloblist_hdr *clear_bloblist(void)
36{
37 struct bloblist_hdr *hdr;
38
Simon Glass3e85ea02020-01-27 08:49:52 -070039 /*
40 * Clear out any existing bloblist so we have a clean slate. Zero the
41 * header so that existing records are removed, but set everything else
42 * to 0xff for testing purposes.
43 */
Simon Glass78b0ef52018-11-15 18:43:53 -070044 hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
Simon Glassd7985e62020-09-19 18:49:28 -060045 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
Simon Glass3e85ea02020-01-27 08:49:52 -070046 memset(hdr, '\0', sizeof(*hdr));
Simon Glass78b0ef52018-11-15 18:43:53 -070047
48 return hdr;
49}
50
Simon Glass3e85ea02020-01-27 08:49:52 -070051static int check_zero(void *data, int size)
52{
53 u8 *ptr;
54 int i;
55
56 for (ptr = data, i = 0; i < size; i++, ptr++) {
57 if (*ptr)
58 return -EINVAL;
59 }
60
61 return 0;
62}
63
Simon Glass78b0ef52018-11-15 18:43:53 -070064static int bloblist_test_init(struct unit_test_state *uts)
65{
66 struct bloblist_hdr *hdr;
67
68 hdr = clear_bloblist();
69 ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
Simon Glass9341a3f2022-01-12 19:26:16 -070070 ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
Simon Glassaee5a9c2023-12-27 13:07:09 -080071 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass9341a3f2022-01-12 19:26:16 -070072 ut_asserteq_ptr(hdr, bloblist_check_magic(TEST_ADDR));
Simon Glass78b0ef52018-11-15 18:43:53 -070073 hdr->version++;
74 ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
75 TEST_BLOBLIST_SIZE));
76
Simon Glassaee5a9c2023-12-27 13:07:09 -080077 ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0xc, 0, 0));
78 ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0, 0));
79 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass78b0ef52018-11-15 18:43:53 -070080
81 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
82 ut_assertok(bloblist_finish());
83 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
Simon Glass9341a3f2022-01-12 19:26:16 -070084
85 hdr->magic++;
86 ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
87 hdr->magic--;
88
Simon Glass78b0ef52018-11-15 18:43:53 -070089 hdr->flags++;
90 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
91
92 return 1;
93}
Simon Glassd7ae4862024-10-28 13:47:54 +010094BLOBLIST_TEST(bloblist_test_init, UFT_BLOBLIST);
Simon Glass78b0ef52018-11-15 18:43:53 -070095
96static int bloblist_test_blob(struct unit_test_state *uts)
97{
98 struct bloblist_hdr *hdr;
99 struct bloblist_rec *rec, *rec2;
100 char *data;
Raymond Maoc6881f12025-01-27 06:49:34 -0800101 int size = 0;
Simon Glass78b0ef52018-11-15 18:43:53 -0700102
103 /* At the start there should be no records */
104 hdr = clear_bloblist();
105 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
Raymond Maoc6881f12025-01-27 06:49:34 -0800106 ut_assertnull(bloblist_get_blob(TEST_TAG, &size));
Simon Glassaee5a9c2023-12-27 13:07:09 -0800107 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass39d5ad32023-12-27 13:07:08 -0800108 ut_asserteq(sizeof(struct bloblist_hdr), bloblist_get_size());
109 ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_total_size());
Simon Glass01fd56a2022-01-12 19:26:23 -0700110 ut_asserteq(TEST_ADDR, bloblist_get_base());
Simon Glass7c58b082020-09-19 18:49:27 -0600111 ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
Simon Glass78b0ef52018-11-15 18:43:53 -0700112
113 /* Add a record and check that we can find it */
Simon Glass06373972020-09-19 18:49:29 -0600114 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700115 rec = (void *)(hdr + 1);
Simon Glass7c58b082020-09-19 18:49:27 -0600116 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700117 data = bloblist_find(TEST_TAG, TEST_SIZE);
Simon Glass7c58b082020-09-19 18:49:27 -0600118 ut_asserteq_addr(rec + 1, data);
Raymond Maoc6881f12025-01-27 06:49:34 -0800119 ut_asserteq_addr(bloblist_get_blob(TEST_TAG, &size), data);
120 ut_asserteq(size, TEST_SIZE);
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}
Simon Glassd7ae4862024-10-28 13:47:54 +0100138BLOBLIST_TEST(bloblist_test_blob, UFT_BLOBLIST);
Simon Glass78b0ef52018-11-15 18:43:53 -0700139
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}
Simon Glassd7ae4862024-10-28 13:47:54 +0100172BLOBLIST_TEST(bloblist_test_blob_ensure, UFT_BLOBLIST);
Simon Glass1e0304e2020-01-27 08:49:50 -0700173
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}
Simon Glassd7ae4862024-10-28 13:47:54 +0100188BLOBLIST_TEST(bloblist_test_bad_blob, UFT_BLOBLIST);
Simon Glass78b0ef52018-11-15 18:43:53 -0700189
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--;
Raymond Maobc7f0ab2024-02-03 08:36:21 -0800210 ut_asserteq(-EIO, 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 Glassd7ae4862024-10-28 13:47:54 +0100261BLOBLIST_TEST(bloblist_test_checksum, UFT_BLOBLIST);
Simon Glass78b0ef52018-11-15 18:43:53 -0700262
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
Simon Glassb936a972020-09-19 18:49:26 -0600274 run_command("bloblist info", 0);
Simon Glass39d5ad32023-12-27 13:07:08 -0800275 ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
276 ut_assert_nextline("total size: 400 1 KiB");
277 ut_assert_nextline("used size: 50 80 Bytes");
278 ut_assert_nextline("free: 3b0 944 Bytes");
Simon Glassb936a972020-09-19 18:49:26 -0600279
280 return 0;
281}
Simon Glassd7ae4862024-10-28 13:47:54 +0100282BLOBLIST_TEST(bloblist_test_cmd_info, UFT_BLOBLIST | UTF_CONSOLE);
Simon Glassb936a972020-09-19 18:49:26 -0600283
284/* Test the 'bloblist list' command */
285static int bloblist_test_cmd_list(struct unit_test_state *uts)
286{
Simon Glassb936a972020-09-19 18:49:26 -0600287 struct bloblist_hdr *hdr;
288 char *data, *data2;
289
290 hdr = clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800291 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassb936a972020-09-19 18:49:26 -0600292 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
293 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
294
Simon Glassb936a972020-09-19 18:49:26 -0600295 run_command("bloblist list", 0);
Simon Glassfd20df42022-01-12 19:26:19 -0700296 ut_assert_nextline("Address Size Tag Name");
Simon Glass871e5d02023-12-27 13:06:59 -0800297 ut_assert_nextline("%08lx %8x fff000 SPL hand-off",
Simon Glass7c58b082020-09-19 18:49:27 -0600298 (ulong)map_to_sysmem(data), TEST_SIZE);
Simon Glass871e5d02023-12-27 13:06:59 -0800299 ut_assert_nextline("%08lx %8x 202 Chrome OS vboot context",
Simon Glass7c58b082020-09-19 18:49:27 -0600300 (ulong)map_to_sysmem(data2), TEST_SIZE2);
Simon Glassb936a972020-09-19 18:49:26 -0600301
302 return 0;
303}
Simon Glassd7ae4862024-10-28 13:47:54 +0100304BLOBLIST_TEST(bloblist_test_cmd_list, UFT_BLOBLIST | UTF_CONSOLE);
Simon Glassb936a972020-09-19 18:49:26 -0600305
Simon Glassd7985e62020-09-19 18:49:28 -0600306/* Test alignment of bloblist blobs */
307static int bloblist_test_align(struct unit_test_state *uts)
308{
309 struct bloblist_hdr *hdr;
Simon Glass06373972020-09-19 18:49:29 -0600310 ulong addr;
311 char *data;
Simon Glassd7985e62020-09-19 18:49:28 -0600312 int i;
313
314 /* At the start there should be no records */
315 hdr = clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800316 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassd7985e62020-09-19 18:49:28 -0600317 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
318
Simon Glass06373972020-09-19 18:49:29 -0600319 /* Check the default alignment */
Simon Glassd7985e62020-09-19 18:49:28 -0600320 for (i = 0; i < 3; i++) {
321 int size = i * 3;
322 ulong addr;
323 char *data;
324 int j;
325
Simon Glass06373972020-09-19 18:49:29 -0600326 data = bloblist_add(i, size, 0);
Simon Glassd7985e62020-09-19 18:49:28 -0600327 ut_assertnonnull(data);
328 addr = map_to_sysmem(data);
Simon Glass703a5da2023-12-27 13:07:07 -0800329 ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN - 1));
Simon Glassd7985e62020-09-19 18:49:28 -0600330
331 /* Only the bytes in the blob data should be zeroed */
332 for (j = 0; j < size; j++)
333 ut_asserteq(0, data[j]);
Simon Glass703a5da2023-12-27 13:07:07 -0800334 for (; j < BLOBLIST_BLOB_ALIGN; j++)
Simon Glassd7985e62020-09-19 18:49:28 -0600335 ut_asserteq(ERASE_BYTE, data[j]);
336 }
337
Simon Glass06373972020-09-19 18:49:29 -0600338 /* Check larger alignment */
339 for (i = 0; i < 3; i++) {
Simon Glassc2aa4ef2023-12-27 13:07:00 -0800340 int align = 5 - i;
Simon Glass06373972020-09-19 18:49:29 -0600341
342 data = bloblist_add(3 + i, i * 4, align);
343 ut_assertnonnull(data);
344 addr = map_to_sysmem(data);
345 ut_asserteq(0, addr & (align - 1));
346 }
347
348 /* Check alignment with an bloblist starting on a smaller alignment */
Simon Glass703a5da2023-12-27 13:07:07 -0800349 hdr = map_sysmem(TEST_ADDR + BLOBLIST_BLOB_ALIGN, TEST_BLOBLIST_SIZE);
Simon Glass06373972020-09-19 18:49:29 -0600350 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
351 memset(hdr, '\0', sizeof(*hdr));
352 ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
Simon Glassaee5a9c2023-12-27 13:07:09 -0800353 0, 0));
Simon Glass06373972020-09-19 18:49:29 -0600354
Simon Glassc2aa4ef2023-12-27 13:07:00 -0800355 data = bloblist_add(1, 5, BLOBLIST_ALIGN_LOG2 + 1);
Simon Glass06373972020-09-19 18:49:29 -0600356 ut_assertnonnull(data);
357 addr = map_to_sysmem(data);
Simon Glass703a5da2023-12-27 13:07:07 -0800358 ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN * 2 - 1));
Simon Glass06373972020-09-19 18:49:29 -0600359
Simon Glassd7985e62020-09-19 18:49:28 -0600360 return 0;
361}
Simon Glassd7ae4862024-10-28 13:47:54 +0100362BLOBLIST_TEST(bloblist_test_align, UFT_BLOBLIST);
Simon Glassd7985e62020-09-19 18:49:28 -0600363
Simon Glassab7e7462021-01-13 20:29:43 -0700364/* Test relocation of a bloblist */
365static int bloblist_test_reloc(struct unit_test_state *uts)
366{
367 const uint large_size = TEST_BLOBLIST_SIZE;
368 const uint small_size = 0x20;
Raymond Mao1a99d2c2024-02-03 08:36:22 -0800369 void *new_ptr;
Simon Glassab7e7462021-01-13 20:29:43 -0700370 void *blob1, *blob2;
371 ulong new_addr;
372 ulong new_size;
373
Simon Glassaee5a9c2023-12-27 13:07:09 -0800374 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassab7e7462021-01-13 20:29:43 -0700375
376 /* Add one blob and then one that won't fit */
377 blob1 = bloblist_add(TEST_TAG, small_size, 0);
378 ut_assertnonnull(blob1);
379 blob2 = bloblist_add(TEST_TAG2, large_size, 0);
380 ut_assertnull(blob2);
381
382 /* Relocate the bloblist somewhere else, a bit larger */
383 new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE;
384 new_size = TEST_BLOBLIST_SIZE + 0x100;
385 new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE);
Raymond Mao1a99d2c2024-02-03 08:36:22 -0800386 ut_assertok(bloblist_reloc(new_ptr, new_size));
Simon Glassab7e7462021-01-13 20:29:43 -0700387
388 /* Check the old blob is there and that we can now add the bigger one */
389 ut_assertnonnull(bloblist_find(TEST_TAG, small_size));
390 ut_assertnull(bloblist_find(TEST_TAG2, small_size));
391 blob2 = bloblist_add(TEST_TAG2, large_size, 0);
392 ut_assertnonnull(blob2);
393
394 return 0;
395}
Simon Glassd7ae4862024-10-28 13:47:54 +0100396BLOBLIST_TEST(bloblist_test_reloc, UFT_BLOBLIST);
Simon Glassab7e7462021-01-13 20:29:43 -0700397
Simon Glassf20a1132021-07-05 16:32:53 -0600398/* Test expansion of a blob */
399static int bloblist_test_grow(struct unit_test_state *uts)
400{
401 const uint small_size = 0x20;
402 void *blob1, *blob2, *blob1_new;
403 struct bloblist_hdr *hdr;
404 void *ptr;
405
406 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
407 hdr = ptr;
408 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
409
410 /* Create two blobs */
Simon Glassaee5a9c2023-12-27 13:07:09 -0800411 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassf20a1132021-07-05 16:32:53 -0600412 blob1 = bloblist_add(TEST_TAG, small_size, 0);
413 ut_assertnonnull(blob1);
414 ut_assertok(check_zero(blob1, small_size));
415 strcpy(blob1, test1_str);
416
417 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
418 ut_assertnonnull(blob2);
419 strcpy(blob2, test2_str);
420
421 ut_asserteq(sizeof(struct bloblist_hdr) +
422 sizeof(struct bloblist_rec) * 2 + small_size * 2,
Simon Glass39d5ad32023-12-27 13:07:08 -0800423 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600424
425 /* Resize the first one */
426 ut_assertok(bloblist_resize(TEST_TAG, small_size + 4));
427
428 /* The first one should not have moved, just got larger */
429 blob1_new = bloblist_find(TEST_TAG, small_size + 4);
430 ut_asserteq_ptr(blob1, blob1_new);
431
432 /* The new space should be zeroed */
433 ut_assertok(check_zero(blob1 + small_size, 4));
434
435 /* The second one should have moved */
436 blob2 = bloblist_find(TEST_TAG2, small_size);
437 ut_assertnonnull(blob2);
438 ut_asserteq_str(test2_str, blob2);
439
440 /* The header should have more bytes in use */
441 hdr = ptr;
442 ut_asserteq(sizeof(struct bloblist_hdr) +
443 sizeof(struct bloblist_rec) * 2 + small_size * 2 +
Simon Glass703a5da2023-12-27 13:07:07 -0800444 BLOBLIST_BLOB_ALIGN,
Simon Glass39d5ad32023-12-27 13:07:08 -0800445 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600446
447 return 0;
448}
Simon Glassd7ae4862024-10-28 13:47:54 +0100449BLOBLIST_TEST(bloblist_test_grow, UFT_BLOBLIST);
Simon Glassf20a1132021-07-05 16:32:53 -0600450
451/* Test shrinking of a blob */
452static int bloblist_test_shrink(struct unit_test_state *uts)
453{
454 const uint small_size = 0x20;
455 void *blob1, *blob2, *blob1_new;
456 struct bloblist_hdr *hdr;
457 int new_size;
458 void *ptr;
459
460 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
461
462 /* Create two blobs */
Simon Glassaee5a9c2023-12-27 13:07:09 -0800463 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassf20a1132021-07-05 16:32:53 -0600464 blob1 = bloblist_add(TEST_TAG, small_size, 0);
465 ut_assertnonnull(blob1);
466 strcpy(blob1, test1_str);
467
468 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
469 ut_assertnonnull(blob2);
470 strcpy(blob2, test2_str);
471
472 hdr = ptr;
473 ut_asserteq(sizeof(struct bloblist_hdr) +
474 sizeof(struct bloblist_rec) * 2 + small_size * 2,
Simon Glass39d5ad32023-12-27 13:07:08 -0800475 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600476
477 /* Resize the first one */
478 new_size = small_size - BLOBLIST_ALIGN - 4;
479 ut_assertok(bloblist_resize(TEST_TAG, new_size));
480
481 /* The first one should not have moved, just got smaller */
482 blob1_new = bloblist_find(TEST_TAG, new_size);
483 ut_asserteq_ptr(blob1, blob1_new);
484
485 /* The second one should have moved */
486 blob2 = bloblist_find(TEST_TAG2, small_size);
487 ut_assertnonnull(blob2);
488 ut_asserteq_str(test2_str, blob2);
489
490 /* The header should have fewer bytes in use */
491 hdr = ptr;
492 ut_asserteq(sizeof(struct bloblist_hdr) +
493 sizeof(struct bloblist_rec) * 2 + small_size * 2 -
494 BLOBLIST_ALIGN,
Simon Glass39d5ad32023-12-27 13:07:08 -0800495 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600496
497 return 0;
498}
Simon Glassd7ae4862024-10-28 13:47:54 +0100499BLOBLIST_TEST(bloblist_test_shrink, UFT_BLOBLIST);
Simon Glassf20a1132021-07-05 16:32:53 -0600500
501/* Test failing to adjust a blob size */
502static int bloblist_test_resize_fail(struct unit_test_state *uts)
503{
504 const uint small_size = 0x20;
505 struct bloblist_hdr *hdr;
506 void *blob1, *blob2;
507 int new_size;
508 void *ptr;
509
510 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
511
512 /* Create two blobs */
Simon Glassaee5a9c2023-12-27 13:07:09 -0800513 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassf20a1132021-07-05 16:32:53 -0600514 blob1 = bloblist_add(TEST_TAG, small_size, 0);
515 ut_assertnonnull(blob1);
516
517 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
518 ut_assertnonnull(blob2);
519
520 hdr = ptr;
521 ut_asserteq(sizeof(struct bloblist_hdr) +
522 sizeof(struct bloblist_rec) * 2 + small_size * 2,
Simon Glass39d5ad32023-12-27 13:07:08 -0800523 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600524
525 /* Resize the first one, to check the boundary conditions */
526 ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1));
527
Simon Glass39d5ad32023-12-27 13:07:08 -0800528 new_size = small_size + (hdr->total_size - hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600529 ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1));
530 ut_assertok(bloblist_resize(TEST_TAG, new_size));
531
532 return 0;
533}
Simon Glassd7ae4862024-10-28 13:47:54 +0100534BLOBLIST_TEST(bloblist_test_resize_fail, UFT_BLOBLIST);
Simon Glassf20a1132021-07-05 16:32:53 -0600535
536/* Test expanding the last blob in a bloblist */
537static int bloblist_test_resize_last(struct unit_test_state *uts)
538{
539 const uint small_size = 0x20;
540 struct bloblist_hdr *hdr;
541 void *blob1, *blob2, *blob2_new;
542 int alloced_val;
543 void *ptr;
544
545 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
546 memset(ptr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
547 hdr = ptr;
548
549 /* Create two blobs */
Simon Glassaee5a9c2023-12-27 13:07:09 -0800550 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassf20a1132021-07-05 16:32:53 -0600551 blob1 = bloblist_add(TEST_TAG, small_size, 0);
552 ut_assertnonnull(blob1);
553
554 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
555 ut_assertnonnull(blob2);
556
557 /* Check the byte after the last blob */
558 alloced_val = sizeof(struct bloblist_hdr) +
559 sizeof(struct bloblist_rec) * 2 + small_size * 2;
Simon Glass39d5ad32023-12-27 13:07:08 -0800560 ut_asserteq(alloced_val, hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600561 ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size);
Simon Glass39d5ad32023-12-27 13:07:08 -0800562 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
Simon Glassf20a1132021-07-05 16:32:53 -0600563
564 /* Resize the second one, checking nothing changes */
565 ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4));
566
567 blob2_new = bloblist_find(TEST_TAG2, small_size + 4);
568 ut_asserteq_ptr(blob2, blob2_new);
569
570 /*
571 * the new blob should encompass the byte we checked now, so it should
572 * be zeroed. This zeroing should affect only the four new bytes added
573 * to the blob.
574 */
575 ut_asserteq(0, *((u8 *)hdr + alloced_val));
576 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4));
577
578 /* Check that the new top of the allocated blobs has not been touched */
Simon Glass703a5da2023-12-27 13:07:07 -0800579 alloced_val += BLOBLIST_BLOB_ALIGN;
Simon Glass39d5ad32023-12-27 13:07:08 -0800580 ut_asserteq(alloced_val, hdr->used_size);
581 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
Simon Glassf20a1132021-07-05 16:32:53 -0600582
583 return 0;
584}
Simon Glassd7ae4862024-10-28 13:47:54 +0100585BLOBLIST_TEST(bloblist_test_resize_last, UFT_BLOBLIST);
Simon Glassf20a1132021-07-05 16:32:53 -0600586
Simon Glass3e26de52021-07-05 16:32:55 -0600587/* Check a completely full bloblist */
588static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
589{
590 void *ptr;
591 int size;
592
593 /* At the start there should be no records */
594 clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800595 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass3e26de52021-07-05 16:32:55 -0600596
597 /* Add a blob that takes up all space */
598 size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) -
599 sizeof(struct bloblist_rec);
600 ptr = bloblist_add(TEST_TAG, size, 0);
601 ut_assertnonnull(ptr);
602
603 ptr = bloblist_add(TEST_TAG, size + 1, 0);
604 ut_assertnull(ptr);
605
606 return 0;
607}
Simon Glassd7ae4862024-10-28 13:47:54 +0100608BLOBLIST_TEST(bloblist_test_blob_maxsize, UFT_BLOBLIST);