blob: 4bca62110a5cb7d59d7ca039c5d21bee8e937820 [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) \
15 UNIT_TEST(_name, _flags, bloblist_test)
16
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;
101
102 /* At the start there should be no records */
103 hdr = clear_bloblist();
104 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
Simon Glassaee5a9c2023-12-27 13:07:09 -0800105 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass39d5ad32023-12-27 13:07:08 -0800106 ut_asserteq(sizeof(struct bloblist_hdr), bloblist_get_size());
107 ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_total_size());
Simon Glass01fd56a2022-01-12 19:26:23 -0700108 ut_asserteq(TEST_ADDR, bloblist_get_base());
Simon Glass7c58b082020-09-19 18:49:27 -0600109 ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
Simon Glass78b0ef52018-11-15 18:43:53 -0700110
111 /* Add a record and check that we can find it */
Simon Glass06373972020-09-19 18:49:29 -0600112 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700113 rec = (void *)(hdr + 1);
Simon Glass7c58b082020-09-19 18:49:27 -0600114 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700115 data = bloblist_find(TEST_TAG, TEST_SIZE);
Simon Glass7c58b082020-09-19 18:49:27 -0600116 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700117
Simon Glass3e85ea02020-01-27 08:49:52 -0700118 /* Check the data is zeroed */
119 ut_assertok(check_zero(data, TEST_SIZE));
120
Simon Glass78b0ef52018-11-15 18:43:53 -0700121 /* Check the 'ensure' method */
Simon Glass7c58b082020-09-19 18:49:27 -0600122 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700123 ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
124 rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
Simon Glass3e85ea02020-01-27 08:49:52 -0700125 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700126
127 /* Check for a non-existent record */
Simon Glass7c58b082020-09-19 18:49:27 -0600128 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
129 ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
Simon Glass78b0ef52018-11-15 18:43:53 -0700130 ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
131
132 return 0;
133}
Simon Glassd7ae4862024-10-28 13:47:54 +0100134BLOBLIST_TEST(bloblist_test_blob, UFT_BLOBLIST);
Simon Glass78b0ef52018-11-15 18:43:53 -0700135
Simon Glass1e0304e2020-01-27 08:49:50 -0700136/* Check bloblist_ensure_size_ret() */
137static int bloblist_test_blob_ensure(struct unit_test_state *uts)
138{
139 void *data, *data2;
140 int size;
141
142 /* At the start there should be no records */
143 clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800144 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass1e0304e2020-01-27 08:49:50 -0700145
146 /* Test with an empty bloblist */
147 size = TEST_SIZE;
148 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
149 ut_asserteq(TEST_SIZE, size);
Simon Glass3e85ea02020-01-27 08:49:52 -0700150 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass1e0304e2020-01-27 08:49:50 -0700151
152 /* Check that we get the same thing again */
153 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
154 ut_asserteq(TEST_SIZE, size);
Simon Glass7c58b082020-09-19 18:49:27 -0600155 ut_asserteq_addr(data, data2);
Simon Glass1e0304e2020-01-27 08:49:50 -0700156
157 /* Check that the size remains the same */
158 size = TEST_SIZE2;
159 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
160 ut_asserteq(TEST_SIZE, size);
161
162 /* Check running out of space */
163 size = TEST_SIZE_LARGE;
164 ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
165
166 return 0;
167}
Simon Glassd7ae4862024-10-28 13:47:54 +0100168BLOBLIST_TEST(bloblist_test_blob_ensure, UFT_BLOBLIST);
Simon Glass1e0304e2020-01-27 08:49:50 -0700169
Simon Glass78b0ef52018-11-15 18:43:53 -0700170static int bloblist_test_bad_blob(struct unit_test_state *uts)
171{
172 struct bloblist_hdr *hdr;
173 void *data;
174
175 hdr = clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800176 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass78b0ef52018-11-15 18:43:53 -0700177 data = hdr + 1;
178 data += sizeof(struct bloblist_rec);
Simon Glass7c58b082020-09-19 18:49:27 -0600179 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
180 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700181
182 return 0;
183}
Simon Glassd7ae4862024-10-28 13:47:54 +0100184BLOBLIST_TEST(bloblist_test_bad_blob, UFT_BLOBLIST);
Simon Glass78b0ef52018-11-15 18:43:53 -0700185
186static int bloblist_test_checksum(struct unit_test_state *uts)
187{
188 struct bloblist_hdr *hdr;
189 char *data, *data2;
190
191 hdr = clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800192 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass78b0ef52018-11-15 18:43:53 -0700193 ut_assertok(bloblist_finish());
194 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
195
196 /*
197 * Now change things amd make sure that the checksum notices. We cannot
198 * change the size or alloced fields, since that will crash the code.
199 * It has to rely on these being correct.
200 */
201 hdr->flags--;
202 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
203 hdr->flags++;
204
Simon Glass39d5ad32023-12-27 13:07:08 -0800205 hdr->total_size--;
Raymond Maobc7f0ab2024-02-03 08:36:21 -0800206 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
Simon Glass39d5ad32023-12-27 13:07:08 -0800207 hdr->total_size++;
Simon Glass78b0ef52018-11-15 18:43:53 -0700208
209 hdr->spare++;
210 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
211 hdr->spare--;
212
213 hdr->chksum++;
214 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
215 hdr->chksum--;
216
Simon Glassaee5a9c2023-12-27 13:07:09 -0800217 hdr->align_log2++;
218 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
219 hdr->align_log2--;
220
Simon Glass78b0ef52018-11-15 18:43:53 -0700221 /* Make sure the checksum changes when we add blobs */
Simon Glass06373972020-09-19 18:49:29 -0600222 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700223 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
224
Simon Glass06373972020-09-19 18:49:29 -0600225 data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
Simon Glass78b0ef52018-11-15 18:43:53 -0700226 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
227 ut_assertok(bloblist_finish());
228
229 /* It should also change if we change the data */
230 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
231 *data += 1;
232 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
233 *data -= 1;
234
235 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
236 *data2 += 1;
237 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
238 *data2 -= 1;
239
240 /*
Simon Glass8968c052023-12-27 13:07:05 -0800241 * Changing data outside the range of valid data should affect the
242 * checksum.
Simon Glass78b0ef52018-11-15 18:43:53 -0700243 */
244 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
245 data[TEST_SIZE]++;
Simon Glass8968c052023-12-27 13:07:05 -0800246 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
247 data[TEST_SIZE]--;
248 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
249
Simon Glass78b0ef52018-11-15 18:43:53 -0700250 data2[TEST_SIZE2]++;
Simon Glass8968c052023-12-27 13:07:05 -0800251 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
252 data[TEST_SIZE]--;
Simon Glass78b0ef52018-11-15 18:43:53 -0700253 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
254
255 return 0;
256}
Simon Glassd7ae4862024-10-28 13:47:54 +0100257BLOBLIST_TEST(bloblist_test_checksum, UFT_BLOBLIST);
Simon Glass78b0ef52018-11-15 18:43:53 -0700258
Simon Glassb936a972020-09-19 18:49:26 -0600259/* Test the 'bloblist info' command */
260static int bloblist_test_cmd_info(struct unit_test_state *uts)
261{
Simon Glassb936a972020-09-19 18:49:26 -0600262 struct bloblist_hdr *hdr;
263 char *data, *data2;
264
265 hdr = clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800266 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassb936a972020-09-19 18:49:26 -0600267 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
268 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
269
Simon Glassb936a972020-09-19 18:49:26 -0600270 run_command("bloblist info", 0);
Simon Glass39d5ad32023-12-27 13:07:08 -0800271 ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
272 ut_assert_nextline("total size: 400 1 KiB");
273 ut_assert_nextline("used size: 50 80 Bytes");
274 ut_assert_nextline("free: 3b0 944 Bytes");
Simon Glassb936a972020-09-19 18:49:26 -0600275
276 return 0;
277}
Simon Glassd7ae4862024-10-28 13:47:54 +0100278BLOBLIST_TEST(bloblist_test_cmd_info, UFT_BLOBLIST | UTF_CONSOLE);
Simon Glassb936a972020-09-19 18:49:26 -0600279
280/* Test the 'bloblist list' command */
281static int bloblist_test_cmd_list(struct unit_test_state *uts)
282{
Simon Glassb936a972020-09-19 18:49:26 -0600283 struct bloblist_hdr *hdr;
284 char *data, *data2;
285
286 hdr = clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800287 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassb936a972020-09-19 18:49:26 -0600288 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
289 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
290
Simon Glassb936a972020-09-19 18:49:26 -0600291 run_command("bloblist list", 0);
Simon Glassfd20df42022-01-12 19:26:19 -0700292 ut_assert_nextline("Address Size Tag Name");
Simon Glass871e5d02023-12-27 13:06:59 -0800293 ut_assert_nextline("%08lx %8x fff000 SPL hand-off",
Simon Glass7c58b082020-09-19 18:49:27 -0600294 (ulong)map_to_sysmem(data), TEST_SIZE);
Simon Glass871e5d02023-12-27 13:06:59 -0800295 ut_assert_nextline("%08lx %8x 202 Chrome OS vboot context",
Simon Glass7c58b082020-09-19 18:49:27 -0600296 (ulong)map_to_sysmem(data2), TEST_SIZE2);
Simon Glassb936a972020-09-19 18:49:26 -0600297
298 return 0;
299}
Simon Glassd7ae4862024-10-28 13:47:54 +0100300BLOBLIST_TEST(bloblist_test_cmd_list, UFT_BLOBLIST | UTF_CONSOLE);
Simon Glassb936a972020-09-19 18:49:26 -0600301
Simon Glassd7985e62020-09-19 18:49:28 -0600302/* Test alignment of bloblist blobs */
303static int bloblist_test_align(struct unit_test_state *uts)
304{
305 struct bloblist_hdr *hdr;
Simon Glass06373972020-09-19 18:49:29 -0600306 ulong addr;
307 char *data;
Simon Glassd7985e62020-09-19 18:49:28 -0600308 int i;
309
310 /* At the start there should be no records */
311 hdr = clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800312 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassd7985e62020-09-19 18:49:28 -0600313 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
314
Simon Glass06373972020-09-19 18:49:29 -0600315 /* Check the default alignment */
Simon Glassd7985e62020-09-19 18:49:28 -0600316 for (i = 0; i < 3; i++) {
317 int size = i * 3;
318 ulong addr;
319 char *data;
320 int j;
321
Simon Glass06373972020-09-19 18:49:29 -0600322 data = bloblist_add(i, size, 0);
Simon Glassd7985e62020-09-19 18:49:28 -0600323 ut_assertnonnull(data);
324 addr = map_to_sysmem(data);
Simon Glass703a5da2023-12-27 13:07:07 -0800325 ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN - 1));
Simon Glassd7985e62020-09-19 18:49:28 -0600326
327 /* Only the bytes in the blob data should be zeroed */
328 for (j = 0; j < size; j++)
329 ut_asserteq(0, data[j]);
Simon Glass703a5da2023-12-27 13:07:07 -0800330 for (; j < BLOBLIST_BLOB_ALIGN; j++)
Simon Glassd7985e62020-09-19 18:49:28 -0600331 ut_asserteq(ERASE_BYTE, data[j]);
332 }
333
Simon Glass06373972020-09-19 18:49:29 -0600334 /* Check larger alignment */
335 for (i = 0; i < 3; i++) {
Simon Glassc2aa4ef2023-12-27 13:07:00 -0800336 int align = 5 - i;
Simon Glass06373972020-09-19 18:49:29 -0600337
338 data = bloblist_add(3 + i, i * 4, align);
339 ut_assertnonnull(data);
340 addr = map_to_sysmem(data);
341 ut_asserteq(0, addr & (align - 1));
342 }
343
344 /* Check alignment with an bloblist starting on a smaller alignment */
Simon Glass703a5da2023-12-27 13:07:07 -0800345 hdr = map_sysmem(TEST_ADDR + BLOBLIST_BLOB_ALIGN, TEST_BLOBLIST_SIZE);
Simon Glass06373972020-09-19 18:49:29 -0600346 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
347 memset(hdr, '\0', sizeof(*hdr));
348 ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
Simon Glassaee5a9c2023-12-27 13:07:09 -0800349 0, 0));
Simon Glass06373972020-09-19 18:49:29 -0600350
Simon Glassc2aa4ef2023-12-27 13:07:00 -0800351 data = bloblist_add(1, 5, BLOBLIST_ALIGN_LOG2 + 1);
Simon Glass06373972020-09-19 18:49:29 -0600352 ut_assertnonnull(data);
353 addr = map_to_sysmem(data);
Simon Glass703a5da2023-12-27 13:07:07 -0800354 ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN * 2 - 1));
Simon Glass06373972020-09-19 18:49:29 -0600355
Simon Glassd7985e62020-09-19 18:49:28 -0600356 return 0;
357}
Simon Glassd7ae4862024-10-28 13:47:54 +0100358BLOBLIST_TEST(bloblist_test_align, UFT_BLOBLIST);
Simon Glassd7985e62020-09-19 18:49:28 -0600359
Simon Glassab7e7462021-01-13 20:29:43 -0700360/* Test relocation of a bloblist */
361static int bloblist_test_reloc(struct unit_test_state *uts)
362{
363 const uint large_size = TEST_BLOBLIST_SIZE;
364 const uint small_size = 0x20;
Raymond Mao1a99d2c2024-02-03 08:36:22 -0800365 void *new_ptr;
Simon Glassab7e7462021-01-13 20:29:43 -0700366 void *blob1, *blob2;
367 ulong new_addr;
368 ulong new_size;
369
Simon Glassaee5a9c2023-12-27 13:07:09 -0800370 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassab7e7462021-01-13 20:29:43 -0700371
372 /* Add one blob and then one that won't fit */
373 blob1 = bloblist_add(TEST_TAG, small_size, 0);
374 ut_assertnonnull(blob1);
375 blob2 = bloblist_add(TEST_TAG2, large_size, 0);
376 ut_assertnull(blob2);
377
378 /* Relocate the bloblist somewhere else, a bit larger */
379 new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE;
380 new_size = TEST_BLOBLIST_SIZE + 0x100;
381 new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE);
Raymond Mao1a99d2c2024-02-03 08:36:22 -0800382 ut_assertok(bloblist_reloc(new_ptr, new_size));
Simon Glassab7e7462021-01-13 20:29:43 -0700383
384 /* Check the old blob is there and that we can now add the bigger one */
385 ut_assertnonnull(bloblist_find(TEST_TAG, small_size));
386 ut_assertnull(bloblist_find(TEST_TAG2, small_size));
387 blob2 = bloblist_add(TEST_TAG2, large_size, 0);
388 ut_assertnonnull(blob2);
389
390 return 0;
391}
Simon Glassd7ae4862024-10-28 13:47:54 +0100392BLOBLIST_TEST(bloblist_test_reloc, UFT_BLOBLIST);
Simon Glassab7e7462021-01-13 20:29:43 -0700393
Simon Glassf20a1132021-07-05 16:32:53 -0600394/* Test expansion of a blob */
395static int bloblist_test_grow(struct unit_test_state *uts)
396{
397 const uint small_size = 0x20;
398 void *blob1, *blob2, *blob1_new;
399 struct bloblist_hdr *hdr;
400 void *ptr;
401
402 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
403 hdr = ptr;
404 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
405
406 /* Create two blobs */
Simon Glassaee5a9c2023-12-27 13:07:09 -0800407 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassf20a1132021-07-05 16:32:53 -0600408 blob1 = bloblist_add(TEST_TAG, small_size, 0);
409 ut_assertnonnull(blob1);
410 ut_assertok(check_zero(blob1, small_size));
411 strcpy(blob1, test1_str);
412
413 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
414 ut_assertnonnull(blob2);
415 strcpy(blob2, test2_str);
416
417 ut_asserteq(sizeof(struct bloblist_hdr) +
418 sizeof(struct bloblist_rec) * 2 + small_size * 2,
Simon Glass39d5ad32023-12-27 13:07:08 -0800419 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600420
421 /* Resize the first one */
422 ut_assertok(bloblist_resize(TEST_TAG, small_size + 4));
423
424 /* The first one should not have moved, just got larger */
425 blob1_new = bloblist_find(TEST_TAG, small_size + 4);
426 ut_asserteq_ptr(blob1, blob1_new);
427
428 /* The new space should be zeroed */
429 ut_assertok(check_zero(blob1 + small_size, 4));
430
431 /* The second one should have moved */
432 blob2 = bloblist_find(TEST_TAG2, small_size);
433 ut_assertnonnull(blob2);
434 ut_asserteq_str(test2_str, blob2);
435
436 /* The header should have more bytes in use */
437 hdr = ptr;
438 ut_asserteq(sizeof(struct bloblist_hdr) +
439 sizeof(struct bloblist_rec) * 2 + small_size * 2 +
Simon Glass703a5da2023-12-27 13:07:07 -0800440 BLOBLIST_BLOB_ALIGN,
Simon Glass39d5ad32023-12-27 13:07:08 -0800441 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600442
443 return 0;
444}
Simon Glassd7ae4862024-10-28 13:47:54 +0100445BLOBLIST_TEST(bloblist_test_grow, UFT_BLOBLIST);
Simon Glassf20a1132021-07-05 16:32:53 -0600446
447/* Test shrinking of a blob */
448static int bloblist_test_shrink(struct unit_test_state *uts)
449{
450 const uint small_size = 0x20;
451 void *blob1, *blob2, *blob1_new;
452 struct bloblist_hdr *hdr;
453 int new_size;
454 void *ptr;
455
456 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
457
458 /* Create two blobs */
Simon Glassaee5a9c2023-12-27 13:07:09 -0800459 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassf20a1132021-07-05 16:32:53 -0600460 blob1 = bloblist_add(TEST_TAG, small_size, 0);
461 ut_assertnonnull(blob1);
462 strcpy(blob1, test1_str);
463
464 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
465 ut_assertnonnull(blob2);
466 strcpy(blob2, test2_str);
467
468 hdr = ptr;
469 ut_asserteq(sizeof(struct bloblist_hdr) +
470 sizeof(struct bloblist_rec) * 2 + small_size * 2,
Simon Glass39d5ad32023-12-27 13:07:08 -0800471 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600472
473 /* Resize the first one */
474 new_size = small_size - BLOBLIST_ALIGN - 4;
475 ut_assertok(bloblist_resize(TEST_TAG, new_size));
476
477 /* The first one should not have moved, just got smaller */
478 blob1_new = bloblist_find(TEST_TAG, new_size);
479 ut_asserteq_ptr(blob1, blob1_new);
480
481 /* The second one should have moved */
482 blob2 = bloblist_find(TEST_TAG2, small_size);
483 ut_assertnonnull(blob2);
484 ut_asserteq_str(test2_str, blob2);
485
486 /* The header should have fewer bytes in use */
487 hdr = ptr;
488 ut_asserteq(sizeof(struct bloblist_hdr) +
489 sizeof(struct bloblist_rec) * 2 + small_size * 2 -
490 BLOBLIST_ALIGN,
Simon Glass39d5ad32023-12-27 13:07:08 -0800491 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600492
493 return 0;
494}
Simon Glassd7ae4862024-10-28 13:47:54 +0100495BLOBLIST_TEST(bloblist_test_shrink, UFT_BLOBLIST);
Simon Glassf20a1132021-07-05 16:32:53 -0600496
497/* Test failing to adjust a blob size */
498static int bloblist_test_resize_fail(struct unit_test_state *uts)
499{
500 const uint small_size = 0x20;
501 struct bloblist_hdr *hdr;
502 void *blob1, *blob2;
503 int new_size;
504 void *ptr;
505
506 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
507
508 /* Create two blobs */
Simon Glassaee5a9c2023-12-27 13:07:09 -0800509 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassf20a1132021-07-05 16:32:53 -0600510 blob1 = bloblist_add(TEST_TAG, small_size, 0);
511 ut_assertnonnull(blob1);
512
513 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
514 ut_assertnonnull(blob2);
515
516 hdr = ptr;
517 ut_asserteq(sizeof(struct bloblist_hdr) +
518 sizeof(struct bloblist_rec) * 2 + small_size * 2,
Simon Glass39d5ad32023-12-27 13:07:08 -0800519 hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600520
521 /* Resize the first one, to check the boundary conditions */
522 ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1));
523
Simon Glass39d5ad32023-12-27 13:07:08 -0800524 new_size = small_size + (hdr->total_size - hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600525 ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1));
526 ut_assertok(bloblist_resize(TEST_TAG, new_size));
527
528 return 0;
529}
Simon Glassd7ae4862024-10-28 13:47:54 +0100530BLOBLIST_TEST(bloblist_test_resize_fail, UFT_BLOBLIST);
Simon Glassf20a1132021-07-05 16:32:53 -0600531
532/* Test expanding the last blob in a bloblist */
533static int bloblist_test_resize_last(struct unit_test_state *uts)
534{
535 const uint small_size = 0x20;
536 struct bloblist_hdr *hdr;
537 void *blob1, *blob2, *blob2_new;
538 int alloced_val;
539 void *ptr;
540
541 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
542 memset(ptr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
543 hdr = ptr;
544
545 /* Create two blobs */
Simon Glassaee5a9c2023-12-27 13:07:09 -0800546 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassf20a1132021-07-05 16:32:53 -0600547 blob1 = bloblist_add(TEST_TAG, small_size, 0);
548 ut_assertnonnull(blob1);
549
550 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
551 ut_assertnonnull(blob2);
552
553 /* Check the byte after the last blob */
554 alloced_val = sizeof(struct bloblist_hdr) +
555 sizeof(struct bloblist_rec) * 2 + small_size * 2;
Simon Glass39d5ad32023-12-27 13:07:08 -0800556 ut_asserteq(alloced_val, hdr->used_size);
Simon Glassf20a1132021-07-05 16:32:53 -0600557 ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size);
Simon Glass39d5ad32023-12-27 13:07:08 -0800558 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
Simon Glassf20a1132021-07-05 16:32:53 -0600559
560 /* Resize the second one, checking nothing changes */
561 ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4));
562
563 blob2_new = bloblist_find(TEST_TAG2, small_size + 4);
564 ut_asserteq_ptr(blob2, blob2_new);
565
566 /*
567 * the new blob should encompass the byte we checked now, so it should
568 * be zeroed. This zeroing should affect only the four new bytes added
569 * to the blob.
570 */
571 ut_asserteq(0, *((u8 *)hdr + alloced_val));
572 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4));
573
574 /* Check that the new top of the allocated blobs has not been touched */
Simon Glass703a5da2023-12-27 13:07:07 -0800575 alloced_val += BLOBLIST_BLOB_ALIGN;
Simon Glass39d5ad32023-12-27 13:07:08 -0800576 ut_asserteq(alloced_val, hdr->used_size);
577 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
Simon Glassf20a1132021-07-05 16:32:53 -0600578
579 return 0;
580}
Simon Glassd7ae4862024-10-28 13:47:54 +0100581BLOBLIST_TEST(bloblist_test_resize_last, UFT_BLOBLIST);
Simon Glassf20a1132021-07-05 16:32:53 -0600582
Simon Glass3e26de52021-07-05 16:32:55 -0600583/* Check a completely full bloblist */
584static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
585{
586 void *ptr;
587 int size;
588
589 /* At the start there should be no records */
590 clear_bloblist();
Simon Glassaee5a9c2023-12-27 13:07:09 -0800591 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass3e26de52021-07-05 16:32:55 -0600592
593 /* Add a blob that takes up all space */
594 size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) -
595 sizeof(struct bloblist_rec);
596 ptr = bloblist_add(TEST_TAG, size, 0);
597 ut_assertnonnull(ptr);
598
599 ptr = bloblist_add(TEST_TAG, size + 1, 0);
600 ut_assertnull(ptr);
601
602 return 0;
603}
Simon Glassd7ae4862024-10-28 13:47:54 +0100604BLOBLIST_TEST(bloblist_test_blob_maxsize, UFT_BLOBLIST);
Simon Glass3e26de52021-07-05 16:32:55 -0600605
Simon Glassed38aef2020-05-10 11:40:03 -0600606int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
607 char *const argv[])
Simon Glass78b0ef52018-11-15 18:43:53 -0700608{
Simon Glassb50211f2021-03-07 17:35:10 -0700609 struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test);
610 const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test);
Simon Glass78b0ef52018-11-15 18:43:53 -0700611
Philippe Reynes1f99f842019-12-17 19:07:04 +0100612 return cmd_ut_category("bloblist", "bloblist_test_",
613 tests, n_ents, argc, argv);
Simon Glass78b0ef52018-11-15 18:43:53 -0700614}