1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2018, Google Inc. All rights reserved.
10 #include <asm/state.h>
11 #include <test/suites.h>
12 #include <test/test.h>
15 DECLARE_GLOBAL_DATA_PTR;
17 /* Declare a new compression test */
18 #define BLOBLIST_TEST(_name, _flags) \
19 UNIT_TEST(_name, _flags, bloblist_test)
28 TEST_SIZE_LARGE = 0x3e0,
30 TEST_ADDR = CONFIG_BLOBLIST_ADDR,
31 TEST_BLOBLIST_SIZE = 0x400,
36 static struct bloblist_hdr *clear_bloblist(void)
38 struct bloblist_hdr *hdr;
41 * Clear out any existing bloblist so we have a clean slate. Zero the
42 * header so that existing records are removed, but set everything else
43 * to 0xff for testing purposes.
45 hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
46 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
47 memset(hdr, '\0', sizeof(*hdr));
52 static int check_zero(void *data, int size)
57 for (ptr = data, i = 0; i < size; i++, ptr++) {
65 static int bloblist_test_init(struct unit_test_state *uts)
67 struct bloblist_hdr *hdr;
69 hdr = clear_bloblist();
70 ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
71 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
73 ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
76 ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0x10, 0));
77 ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0));
78 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
80 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
81 ut_assertok(bloblist_finish());
82 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
84 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
88 BLOBLIST_TEST(bloblist_test_init, 0);
90 static int bloblist_test_blob(struct unit_test_state *uts)
92 struct bloblist_hdr *hdr;
93 struct bloblist_rec *rec, *rec2;
96 /* At the start there should be no records */
97 hdr = clear_bloblist();
98 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
99 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
100 ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
102 /* Add a record and check that we can find it */
103 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
104 rec = (void *)(hdr + 1);
105 ut_asserteq_addr(rec + 1, data);
106 data = bloblist_find(TEST_TAG, TEST_SIZE);
107 ut_asserteq_addr(rec + 1, data);
109 /* Check the data is zeroed */
110 ut_assertok(check_zero(data, TEST_SIZE));
112 /* Check the 'ensure' method */
113 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
114 ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
115 rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
116 ut_assertok(check_zero(data, TEST_SIZE));
118 /* Check for a non-existent record */
119 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
120 ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
121 ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
125 BLOBLIST_TEST(bloblist_test_blob, 0);
127 /* Check bloblist_ensure_size_ret() */
128 static int bloblist_test_blob_ensure(struct unit_test_state *uts)
133 /* At the start there should be no records */
135 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
137 /* Test with an empty bloblist */
139 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
140 ut_asserteq(TEST_SIZE, size);
141 ut_assertok(check_zero(data, TEST_SIZE));
143 /* Check that we get the same thing again */
144 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
145 ut_asserteq(TEST_SIZE, size);
146 ut_asserteq_addr(data, data2);
148 /* Check that the size remains the same */
150 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
151 ut_asserteq(TEST_SIZE, size);
153 /* Check running out of space */
154 size = TEST_SIZE_LARGE;
155 ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
159 BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
161 static int bloblist_test_bad_blob(struct unit_test_state *uts)
163 struct bloblist_hdr *hdr;
166 hdr = clear_bloblist();
167 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
169 data += sizeof(struct bloblist_rec);
170 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
171 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
175 BLOBLIST_TEST(bloblist_test_bad_blob, 0);
177 static int bloblist_test_checksum(struct unit_test_state *uts)
179 struct bloblist_hdr *hdr;
182 hdr = clear_bloblist();
183 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
184 ut_assertok(bloblist_finish());
185 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
188 * Now change things amd make sure that the checksum notices. We cannot
189 * change the size or alloced fields, since that will crash the code.
190 * It has to rely on these being correct.
193 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
197 ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
201 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
205 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
208 /* Make sure the checksum changes when we add blobs */
209 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
210 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
212 data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
213 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
214 ut_assertok(bloblist_finish());
216 /* It should also change if we change the data */
217 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
219 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
222 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
224 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
228 * Changing data outside the range of valid data should not affect
231 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
234 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
238 BLOBLIST_TEST(bloblist_test_checksum, 0);
240 /* Test the 'bloblist info' command */
241 static int bloblist_test_cmd_info(struct unit_test_state *uts)
243 struct sandbox_state *state = state_get_current();
244 struct bloblist_hdr *hdr;
247 hdr = clear_bloblist();
248 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
249 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
250 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
252 console_record_reset_enable();
253 if (!state->show_test_output)
254 gd->flags |= GD_FLG_SILENT;
255 console_record_reset();
256 run_command("bloblist info", 0);
257 ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
258 ut_assert_nextline("size: 400 1 KiB");
259 ut_assert_nextline("alloced: 70 112 Bytes");
260 ut_assert_nextline("free: 390 912 Bytes");
261 ut_assert_console_end();
262 gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
266 BLOBLIST_TEST(bloblist_test_cmd_info, 0);
268 /* Test the 'bloblist list' command */
269 static int bloblist_test_cmd_list(struct unit_test_state *uts)
271 struct sandbox_state *state = state_get_current();
272 struct bloblist_hdr *hdr;
275 hdr = clear_bloblist();
276 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
277 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
278 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
280 console_record_reset_enable();
281 if (!state->show_test_output)
282 gd->flags |= GD_FLG_SILENT;
283 console_record_reset();
284 run_command("bloblist list", 0);
285 ut_assert_nextline("Address Size Tag Name");
286 ut_assert_nextline("%08lx %8x 1 EC host event",
287 (ulong)map_to_sysmem(data), TEST_SIZE);
288 ut_assert_nextline("%08lx %8x 2 SPL hand-off",
289 (ulong)map_to_sysmem(data2), TEST_SIZE2);
290 ut_assert_console_end();
291 gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
295 BLOBLIST_TEST(bloblist_test_cmd_list, 0);
297 /* Test alignment of bloblist blobs */
298 static int bloblist_test_align(struct unit_test_state *uts)
300 struct bloblist_hdr *hdr;
305 /* At the start there should be no records */
306 hdr = clear_bloblist();
307 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
308 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
310 /* Check the default alignment */
311 for (i = 0; i < 3; i++) {
317 data = bloblist_add(i, size, 0);
318 ut_assertnonnull(data);
319 addr = map_to_sysmem(data);
320 ut_asserteq(0, addr & (BLOBLIST_ALIGN - 1));
322 /* Only the bytes in the blob data should be zeroed */
323 for (j = 0; j < size; j++)
324 ut_asserteq(0, data[j]);
325 for (; j < BLOBLIST_ALIGN; j++)
326 ut_asserteq(ERASE_BYTE, data[j]);
329 /* Check larger alignment */
330 for (i = 0; i < 3; i++) {
333 data = bloblist_add(3 + i, i * 4, align);
334 ut_assertnonnull(data);
335 addr = map_to_sysmem(data);
336 ut_asserteq(0, addr & (align - 1));
339 /* Check alignment with an bloblist starting on a smaller alignment */
340 hdr = map_sysmem(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE);
341 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
342 memset(hdr, '\0', sizeof(*hdr));
343 ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
346 data = bloblist_add(1, 5, BLOBLIST_ALIGN * 2);
347 ut_assertnonnull(data);
348 addr = map_to_sysmem(data);
349 ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1));
353 BLOBLIST_TEST(bloblist_test_align, 0);
355 int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
358 struct unit_test *tests = ll_entry_start(struct unit_test,
360 const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
362 return cmd_ut_category("bloblist", "bloblist_test_",
363 tests, n_ents, argc, argv);