blob: 7c63682908a579c6427ecdfd9ccd4241f2afc71f [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
Simon Glass919e7a82018-11-15 18:43:53 -07006#include <bloblist.h>
7#include <log.h>
8#include <mapmem.h>
Simon Glass401d1c42020-10-30 21:38:53 -06009#include <asm/global_data.h>
Simon Glass919e7a82018-11-15 18:43:53 -070010#include <test/suites.h>
11#include <test/test.h>
12#include <test/ut.h>
13
14DECLARE_GLOBAL_DATA_PTR;
15
Simon Glass127ca102021-08-18 21:40:28 -060016/* Declare a new bloblist test */
Simon Glass919e7a82018-11-15 18:43:53 -070017#define BLOBLIST_TEST(_name, _flags) \
18 UNIT_TEST(_name, _flags, bloblist_test)
19
20enum {
Simon Glassf16ec772022-01-12 19:26:19 -070021 TEST_TAG = BLOBLISTT_U_BOOT_SPL_HANDOFF,
22 TEST_TAG2 = BLOBLISTT_VBOOT_CTX,
23 TEST_TAG_MISSING = 0x10000,
Simon Glass919e7a82018-11-15 18:43:53 -070024
25 TEST_SIZE = 10,
26 TEST_SIZE2 = 20,
Simon Glass4c1497e2020-09-19 18:49:29 -060027 TEST_SIZE_LARGE = 0x3e0,
Simon Glass919e7a82018-11-15 18:43:53 -070028
29 TEST_ADDR = CONFIG_BLOBLIST_ADDR,
Simon Glass4c1497e2020-09-19 18:49:29 -060030 TEST_BLOBLIST_SIZE = 0x400,
Simon Glass751b7c72020-09-19 18:49:28 -060031
32 ERASE_BYTE = '\xff',
Simon Glass919e7a82018-11-15 18:43:53 -070033};
34
Simon Glass1fe59372021-07-05 16:32:53 -060035static const char test1_str[] = "the eyes are open";
36static const char test2_str[] = "the mouth moves";
37
Simon Glass919e7a82018-11-15 18:43:53 -070038static struct bloblist_hdr *clear_bloblist(void)
39{
40 struct bloblist_hdr *hdr;
41
Simon Glassb83994d2020-01-27 08:49:52 -070042 /*
43 * Clear out any existing bloblist so we have a clean slate. Zero the
44 * header so that existing records are removed, but set everything else
45 * to 0xff for testing purposes.
46 */
Simon Glass919e7a82018-11-15 18:43:53 -070047 hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
Simon Glass751b7c72020-09-19 18:49:28 -060048 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
Simon Glassb83994d2020-01-27 08:49:52 -070049 memset(hdr, '\0', sizeof(*hdr));
Simon Glass919e7a82018-11-15 18:43:53 -070050
51 return hdr;
52}
53
Simon Glassb83994d2020-01-27 08:49:52 -070054static int check_zero(void *data, int size)
55{
56 u8 *ptr;
57 int i;
58
59 for (ptr = data, i = 0; i < size; i++, ptr++) {
60 if (*ptr)
61 return -EINVAL;
62 }
63
64 return 0;
65}
66
Simon Glass919e7a82018-11-15 18:43:53 -070067static int bloblist_test_init(struct unit_test_state *uts)
68{
69 struct bloblist_hdr *hdr;
70
71 hdr = clear_bloblist();
72 ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
Simon Glassff3bd492022-01-12 19:26:16 -070073 ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
Simon Glass7d790a82023-12-27 13:07:09 -080074 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassff3bd492022-01-12 19:26:16 -070075 ut_asserteq_ptr(hdr, bloblist_check_magic(TEST_ADDR));
Simon Glass919e7a82018-11-15 18:43:53 -070076 hdr->version++;
77 ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
78 TEST_BLOBLIST_SIZE));
79
Simon Glass7d790a82023-12-27 13:07:09 -080080 ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0xc, 0, 0));
81 ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0, 0));
82 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass919e7a82018-11-15 18:43:53 -070083
84 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
85 ut_assertok(bloblist_finish());
86 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
Simon Glassff3bd492022-01-12 19:26:16 -070087
88 hdr->magic++;
89 ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
90 hdr->magic--;
91
Simon Glass919e7a82018-11-15 18:43:53 -070092 hdr->flags++;
93 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
94
95 return 1;
96}
97BLOBLIST_TEST(bloblist_test_init, 0);
98
99static int bloblist_test_blob(struct unit_test_state *uts)
100{
101 struct bloblist_hdr *hdr;
102 struct bloblist_rec *rec, *rec2;
103 char *data;
104
105 /* At the start there should be no records */
106 hdr = clear_bloblist();
107 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
Simon Glass7d790a82023-12-27 13:07:09 -0800108 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glassb86b2d92023-12-27 13:07:08 -0800109 ut_asserteq(sizeof(struct bloblist_hdr), bloblist_get_size());
110 ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_total_size());
Simon Glasse50a24a2022-01-12 19:26:23 -0700111 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();
Simon Glass7d790a82023-12-27 13:07:09 -0800147 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass5b044542020-01-27 08:49:50 -0700148
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();
Simon Glass7d790a82023-12-27 13:07:09 -0800179 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass919e7a82018-11-15 18:43:53 -0700180 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();
Simon Glass7d790a82023-12-27 13:07:09 -0800195 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass919e7a82018-11-15 18:43:53 -0700196 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
Simon Glassb86b2d92023-12-27 13:07:08 -0800208 hdr->total_size--;
Raymond Mao67254212024-02-03 08:36:21 -0800209 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
Simon Glassb86b2d92023-12-27 13:07:08 -0800210 hdr->total_size++;
Simon Glass919e7a82018-11-15 18:43:53 -0700211
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
Simon Glass7d790a82023-12-27 13:07:09 -0800220 hdr->align_log2++;
221 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
222 hdr->align_log2--;
223
Simon Glass919e7a82018-11-15 18:43:53 -0700224 /* Make sure the checksum changes when we add blobs */
Simon Glass4c1497e2020-09-19 18:49:29 -0600225 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass919e7a82018-11-15 18:43:53 -0700226 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
227
Simon Glass4c1497e2020-09-19 18:49:29 -0600228 data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
Simon Glass919e7a82018-11-15 18:43:53 -0700229 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
230 ut_assertok(bloblist_finish());
231
232 /* It should also change if we change the data */
233 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
234 *data += 1;
235 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
236 *data -= 1;
237
238 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
239 *data2 += 1;
240 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
241 *data2 -= 1;
242
243 /*
Simon Glass997dac62023-12-27 13:07:05 -0800244 * Changing data outside the range of valid data should affect the
245 * checksum.
Simon Glass919e7a82018-11-15 18:43:53 -0700246 */
247 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
248 data[TEST_SIZE]++;
Simon Glass997dac62023-12-27 13:07:05 -0800249 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
250 data[TEST_SIZE]--;
251 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
252
Simon Glass919e7a82018-11-15 18:43:53 -0700253 data2[TEST_SIZE2]++;
Simon Glass997dac62023-12-27 13:07:05 -0800254 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
255 data[TEST_SIZE]--;
Simon Glass919e7a82018-11-15 18:43:53 -0700256 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
257
258 return 0;
259}
Simon Glass919e7a82018-11-15 18:43:53 -0700260BLOBLIST_TEST(bloblist_test_checksum, 0);
261
Simon Glass4aed2272020-09-19 18:49:26 -0600262/* Test the 'bloblist info' command */
263static int bloblist_test_cmd_info(struct unit_test_state *uts)
264{
Simon Glass4aed2272020-09-19 18:49:26 -0600265 struct bloblist_hdr *hdr;
266 char *data, *data2;
267
268 hdr = clear_bloblist();
Simon Glass7d790a82023-12-27 13:07:09 -0800269 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass4aed2272020-09-19 18:49:26 -0600270 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
271 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
272
273 console_record_reset_enable();
Simon Glassef7e2642020-11-08 21:08:43 -0700274 ut_silence_console(uts);
Simon Glass4aed2272020-09-19 18:49:26 -0600275 console_record_reset();
276 run_command("bloblist info", 0);
Simon Glassb86b2d92023-12-27 13:07:08 -0800277 ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
278 ut_assert_nextline("total size: 400 1 KiB");
279 ut_assert_nextline("used size: 50 80 Bytes");
280 ut_assert_nextline("free: 3b0 944 Bytes");
Simon Glass4aed2272020-09-19 18:49:26 -0600281 ut_assert_console_end();
Simon Glassef7e2642020-11-08 21:08:43 -0700282 ut_unsilence_console(uts);
Simon Glass4aed2272020-09-19 18:49:26 -0600283
284 return 0;
285}
286BLOBLIST_TEST(bloblist_test_cmd_info, 0);
287
288/* Test the 'bloblist list' command */
289static int bloblist_test_cmd_list(struct unit_test_state *uts)
290{
Simon Glass4aed2272020-09-19 18:49:26 -0600291 struct bloblist_hdr *hdr;
292 char *data, *data2;
293
294 hdr = clear_bloblist();
Simon Glass7d790a82023-12-27 13:07:09 -0800295 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass4aed2272020-09-19 18:49:26 -0600296 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
297 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
298
299 console_record_reset_enable();
Simon Glassef7e2642020-11-08 21:08:43 -0700300 ut_silence_console(uts);
Simon Glass4aed2272020-09-19 18:49:26 -0600301 console_record_reset();
302 run_command("bloblist list", 0);
Simon Glassf16ec772022-01-12 19:26:19 -0700303 ut_assert_nextline("Address Size Tag Name");
Simon Glasse748e4b2023-12-27 13:06:59 -0800304 ut_assert_nextline("%08lx %8x fff000 SPL hand-off",
Simon Glasscdd4e302020-09-19 18:49:27 -0600305 (ulong)map_to_sysmem(data), TEST_SIZE);
Simon Glasse748e4b2023-12-27 13:06:59 -0800306 ut_assert_nextline("%08lx %8x 202 Chrome OS vboot context",
Simon Glasscdd4e302020-09-19 18:49:27 -0600307 (ulong)map_to_sysmem(data2), TEST_SIZE2);
Simon Glass4aed2272020-09-19 18:49:26 -0600308 ut_assert_console_end();
Simon Glassef7e2642020-11-08 21:08:43 -0700309 ut_unsilence_console(uts);
Simon Glass4aed2272020-09-19 18:49:26 -0600310
311 return 0;
312}
313BLOBLIST_TEST(bloblist_test_cmd_list, 0);
314
Simon Glass751b7c72020-09-19 18:49:28 -0600315/* Test alignment of bloblist blobs */
316static int bloblist_test_align(struct unit_test_state *uts)
317{
318 struct bloblist_hdr *hdr;
Simon Glass4c1497e2020-09-19 18:49:29 -0600319 ulong addr;
320 char *data;
Simon Glass751b7c72020-09-19 18:49:28 -0600321 int i;
322
323 /* At the start there should be no records */
324 hdr = clear_bloblist();
Simon Glass7d790a82023-12-27 13:07:09 -0800325 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass751b7c72020-09-19 18:49:28 -0600326 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
327
Simon Glass4c1497e2020-09-19 18:49:29 -0600328 /* Check the default alignment */
Simon Glass751b7c72020-09-19 18:49:28 -0600329 for (i = 0; i < 3; i++) {
330 int size = i * 3;
331 ulong addr;
332 char *data;
333 int j;
334
Simon Glass4c1497e2020-09-19 18:49:29 -0600335 data = bloblist_add(i, size, 0);
Simon Glass751b7c72020-09-19 18:49:28 -0600336 ut_assertnonnull(data);
337 addr = map_to_sysmem(data);
Simon Glassb6e83822023-12-27 13:07:07 -0800338 ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN - 1));
Simon Glass751b7c72020-09-19 18:49:28 -0600339
340 /* Only the bytes in the blob data should be zeroed */
341 for (j = 0; j < size; j++)
342 ut_asserteq(0, data[j]);
Simon Glassb6e83822023-12-27 13:07:07 -0800343 for (; j < BLOBLIST_BLOB_ALIGN; j++)
Simon Glass751b7c72020-09-19 18:49:28 -0600344 ut_asserteq(ERASE_BYTE, data[j]);
345 }
346
Simon Glass4c1497e2020-09-19 18:49:29 -0600347 /* Check larger alignment */
348 for (i = 0; i < 3; i++) {
Simon Glass1a2e02f2023-12-27 13:07:00 -0800349 int align = 5 - i;
Simon Glass4c1497e2020-09-19 18:49:29 -0600350
351 data = bloblist_add(3 + i, i * 4, align);
352 ut_assertnonnull(data);
353 addr = map_to_sysmem(data);
354 ut_asserteq(0, addr & (align - 1));
355 }
356
357 /* Check alignment with an bloblist starting on a smaller alignment */
Simon Glassb6e83822023-12-27 13:07:07 -0800358 hdr = map_sysmem(TEST_ADDR + BLOBLIST_BLOB_ALIGN, TEST_BLOBLIST_SIZE);
Simon Glass4c1497e2020-09-19 18:49:29 -0600359 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
360 memset(hdr, '\0', sizeof(*hdr));
361 ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
Simon Glass7d790a82023-12-27 13:07:09 -0800362 0, 0));
Simon Glass4c1497e2020-09-19 18:49:29 -0600363
Simon Glass1a2e02f2023-12-27 13:07:00 -0800364 data = bloblist_add(1, 5, BLOBLIST_ALIGN_LOG2 + 1);
Simon Glass4c1497e2020-09-19 18:49:29 -0600365 ut_assertnonnull(data);
366 addr = map_to_sysmem(data);
Simon Glassb6e83822023-12-27 13:07:07 -0800367 ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN * 2 - 1));
Simon Glass4c1497e2020-09-19 18:49:29 -0600368
Simon Glass751b7c72020-09-19 18:49:28 -0600369 return 0;
370}
371BLOBLIST_TEST(bloblist_test_align, 0);
372
Simon Glass9fe06462021-01-13 20:29:43 -0700373/* Test relocation of a bloblist */
374static int bloblist_test_reloc(struct unit_test_state *uts)
375{
376 const uint large_size = TEST_BLOBLIST_SIZE;
377 const uint small_size = 0x20;
Raymond Mao1ef43f32024-02-03 08:36:22 -0800378 void *new_ptr;
Simon Glass9fe06462021-01-13 20:29:43 -0700379 void *blob1, *blob2;
380 ulong new_addr;
381 ulong new_size;
382
Simon Glass7d790a82023-12-27 13:07:09 -0800383 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass9fe06462021-01-13 20:29:43 -0700384
385 /* Add one blob and then one that won't fit */
386 blob1 = bloblist_add(TEST_TAG, small_size, 0);
387 ut_assertnonnull(blob1);
388 blob2 = bloblist_add(TEST_TAG2, large_size, 0);
389 ut_assertnull(blob2);
390
391 /* Relocate the bloblist somewhere else, a bit larger */
392 new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE;
393 new_size = TEST_BLOBLIST_SIZE + 0x100;
394 new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE);
Raymond Mao1ef43f32024-02-03 08:36:22 -0800395 ut_assertok(bloblist_reloc(new_ptr, new_size));
Simon Glass9fe06462021-01-13 20:29:43 -0700396
397 /* Check the old blob is there and that we can now add the bigger one */
398 ut_assertnonnull(bloblist_find(TEST_TAG, small_size));
399 ut_assertnull(bloblist_find(TEST_TAG2, small_size));
400 blob2 = bloblist_add(TEST_TAG2, large_size, 0);
401 ut_assertnonnull(blob2);
402
403 return 0;
404}
405BLOBLIST_TEST(bloblist_test_reloc, 0);
406
Simon Glass1fe59372021-07-05 16:32:53 -0600407/* Test expansion of a blob */
408static int bloblist_test_grow(struct unit_test_state *uts)
409{
410 const uint small_size = 0x20;
411 void *blob1, *blob2, *blob1_new;
412 struct bloblist_hdr *hdr;
413 void *ptr;
414
415 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
416 hdr = ptr;
417 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
418
419 /* Create two blobs */
Simon Glass7d790a82023-12-27 13:07:09 -0800420 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass1fe59372021-07-05 16:32:53 -0600421 blob1 = bloblist_add(TEST_TAG, small_size, 0);
422 ut_assertnonnull(blob1);
423 ut_assertok(check_zero(blob1, small_size));
424 strcpy(blob1, test1_str);
425
426 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
427 ut_assertnonnull(blob2);
428 strcpy(blob2, test2_str);
429
430 ut_asserteq(sizeof(struct bloblist_hdr) +
431 sizeof(struct bloblist_rec) * 2 + small_size * 2,
Simon Glassb86b2d92023-12-27 13:07:08 -0800432 hdr->used_size);
Simon Glass1fe59372021-07-05 16:32:53 -0600433
434 /* Resize the first one */
435 ut_assertok(bloblist_resize(TEST_TAG, small_size + 4));
436
437 /* The first one should not have moved, just got larger */
438 blob1_new = bloblist_find(TEST_TAG, small_size + 4);
439 ut_asserteq_ptr(blob1, blob1_new);
440
441 /* The new space should be zeroed */
442 ut_assertok(check_zero(blob1 + small_size, 4));
443
444 /* The second one should have moved */
445 blob2 = bloblist_find(TEST_TAG2, small_size);
446 ut_assertnonnull(blob2);
447 ut_asserteq_str(test2_str, blob2);
448
449 /* The header should have more bytes in use */
450 hdr = ptr;
451 ut_asserteq(sizeof(struct bloblist_hdr) +
452 sizeof(struct bloblist_rec) * 2 + small_size * 2 +
Simon Glassb6e83822023-12-27 13:07:07 -0800453 BLOBLIST_BLOB_ALIGN,
Simon Glassb86b2d92023-12-27 13:07:08 -0800454 hdr->used_size);
Simon Glass1fe59372021-07-05 16:32:53 -0600455
456 return 0;
457}
458BLOBLIST_TEST(bloblist_test_grow, 0);
459
460/* Test shrinking of a blob */
461static int bloblist_test_shrink(struct unit_test_state *uts)
462{
463 const uint small_size = 0x20;
464 void *blob1, *blob2, *blob1_new;
465 struct bloblist_hdr *hdr;
466 int new_size;
467 void *ptr;
468
469 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
470
471 /* Create two blobs */
Simon Glass7d790a82023-12-27 13:07:09 -0800472 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass1fe59372021-07-05 16:32:53 -0600473 blob1 = bloblist_add(TEST_TAG, small_size, 0);
474 ut_assertnonnull(blob1);
475 strcpy(blob1, test1_str);
476
477 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
478 ut_assertnonnull(blob2);
479 strcpy(blob2, test2_str);
480
481 hdr = ptr;
482 ut_asserteq(sizeof(struct bloblist_hdr) +
483 sizeof(struct bloblist_rec) * 2 + small_size * 2,
Simon Glassb86b2d92023-12-27 13:07:08 -0800484 hdr->used_size);
Simon Glass1fe59372021-07-05 16:32:53 -0600485
486 /* Resize the first one */
487 new_size = small_size - BLOBLIST_ALIGN - 4;
488 ut_assertok(bloblist_resize(TEST_TAG, new_size));
489
490 /* The first one should not have moved, just got smaller */
491 blob1_new = bloblist_find(TEST_TAG, new_size);
492 ut_asserteq_ptr(blob1, blob1_new);
493
494 /* The second one should have moved */
495 blob2 = bloblist_find(TEST_TAG2, small_size);
496 ut_assertnonnull(blob2);
497 ut_asserteq_str(test2_str, blob2);
498
499 /* The header should have fewer bytes in use */
500 hdr = ptr;
501 ut_asserteq(sizeof(struct bloblist_hdr) +
502 sizeof(struct bloblist_rec) * 2 + small_size * 2 -
503 BLOBLIST_ALIGN,
Simon Glassb86b2d92023-12-27 13:07:08 -0800504 hdr->used_size);
Simon Glass1fe59372021-07-05 16:32:53 -0600505
506 return 0;
507}
508BLOBLIST_TEST(bloblist_test_shrink, 0);
509
510/* Test failing to adjust a blob size */
511static int bloblist_test_resize_fail(struct unit_test_state *uts)
512{
513 const uint small_size = 0x20;
514 struct bloblist_hdr *hdr;
515 void *blob1, *blob2;
516 int new_size;
517 void *ptr;
518
519 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
520
521 /* Create two blobs */
Simon Glass7d790a82023-12-27 13:07:09 -0800522 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass1fe59372021-07-05 16:32:53 -0600523 blob1 = bloblist_add(TEST_TAG, small_size, 0);
524 ut_assertnonnull(blob1);
525
526 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
527 ut_assertnonnull(blob2);
528
529 hdr = ptr;
530 ut_asserteq(sizeof(struct bloblist_hdr) +
531 sizeof(struct bloblist_rec) * 2 + small_size * 2,
Simon Glassb86b2d92023-12-27 13:07:08 -0800532 hdr->used_size);
Simon Glass1fe59372021-07-05 16:32:53 -0600533
534 /* Resize the first one, to check the boundary conditions */
535 ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1));
536
Simon Glassb86b2d92023-12-27 13:07:08 -0800537 new_size = small_size + (hdr->total_size - hdr->used_size);
Simon Glass1fe59372021-07-05 16:32:53 -0600538 ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1));
539 ut_assertok(bloblist_resize(TEST_TAG, new_size));
540
541 return 0;
542}
543BLOBLIST_TEST(bloblist_test_resize_fail, 0);
544
545/* Test expanding the last blob in a bloblist */
546static int bloblist_test_resize_last(struct unit_test_state *uts)
547{
548 const uint small_size = 0x20;
549 struct bloblist_hdr *hdr;
550 void *blob1, *blob2, *blob2_new;
551 int alloced_val;
552 void *ptr;
553
554 ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
555 memset(ptr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
556 hdr = ptr;
557
558 /* Create two blobs */
Simon Glass7d790a82023-12-27 13:07:09 -0800559 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass1fe59372021-07-05 16:32:53 -0600560 blob1 = bloblist_add(TEST_TAG, small_size, 0);
561 ut_assertnonnull(blob1);
562
563 blob2 = bloblist_add(TEST_TAG2, small_size, 0);
564 ut_assertnonnull(blob2);
565
566 /* Check the byte after the last blob */
567 alloced_val = sizeof(struct bloblist_hdr) +
568 sizeof(struct bloblist_rec) * 2 + small_size * 2;
Simon Glassb86b2d92023-12-27 13:07:08 -0800569 ut_asserteq(alloced_val, hdr->used_size);
Simon Glass1fe59372021-07-05 16:32:53 -0600570 ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size);
Simon Glassb86b2d92023-12-27 13:07:08 -0800571 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
Simon Glass1fe59372021-07-05 16:32:53 -0600572
573 /* Resize the second one, checking nothing changes */
574 ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4));
575
576 blob2_new = bloblist_find(TEST_TAG2, small_size + 4);
577 ut_asserteq_ptr(blob2, blob2_new);
578
579 /*
580 * the new blob should encompass the byte we checked now, so it should
581 * be zeroed. This zeroing should affect only the four new bytes added
582 * to the blob.
583 */
584 ut_asserteq(0, *((u8 *)hdr + alloced_val));
585 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4));
586
587 /* Check that the new top of the allocated blobs has not been touched */
Simon Glassb6e83822023-12-27 13:07:07 -0800588 alloced_val += BLOBLIST_BLOB_ALIGN;
Simon Glassb86b2d92023-12-27 13:07:08 -0800589 ut_asserteq(alloced_val, hdr->used_size);
590 ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
Simon Glass1fe59372021-07-05 16:32:53 -0600591
592 return 0;
593}
594BLOBLIST_TEST(bloblist_test_resize_last, 0);
595
Simon Glass1f618d52021-07-05 16:32:55 -0600596/* Check a completely full bloblist */
597static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
598{
599 void *ptr;
600 int size;
601
602 /* At the start there should be no records */
603 clear_bloblist();
Simon Glass7d790a82023-12-27 13:07:09 -0800604 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
Simon Glass1f618d52021-07-05 16:32:55 -0600605
606 /* Add a blob that takes up all space */
607 size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) -
608 sizeof(struct bloblist_rec);
609 ptr = bloblist_add(TEST_TAG, size, 0);
610 ut_assertnonnull(ptr);
611
612 ptr = bloblist_add(TEST_TAG, size + 1, 0);
613 ut_assertnull(ptr);
614
615 return 0;
616}
617BLOBLIST_TEST(bloblist_test_blob_maxsize, 0);
618
Simon Glass09140112020-05-10 11:40:03 -0600619int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
620 char *const argv[])
Simon Glass919e7a82018-11-15 18:43:53 -0700621{
Simon Glassa7a98752021-03-07 17:35:10 -0700622 struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test);
623 const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test);
Simon Glass919e7a82018-11-15 18:43:53 -0700624
Philippe Reynes4ad4edf2019-12-17 19:07:04 +0100625 return cmd_ut_category("bloblist", "bloblist_test_",
626 tests, n_ents, argc, argv);
Simon Glass919e7a82018-11-15 18:43:53 -0700627}