blob: 900299dd68e8d97caaaaac28ec7ff4d8c59f41d9 [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
6#include <common.h>
7#include <bloblist.h>
8#include <log.h>
9#include <mapmem.h>
10#include <test/suites.h>
11#include <test/test.h>
12#include <test/ut.h>
13
14DECLARE_GLOBAL_DATA_PTR;
15
16/* Declare a new compression test */
17#define BLOBLIST_TEST(_name, _flags) \
18 UNIT_TEST(_name, _flags, bloblist_test)
19
20enum {
21 TEST_TAG = 1,
22 TEST_TAG2 = 2,
23 TEST_TAG_MISSING = 3,
24
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
35static struct bloblist_hdr *clear_bloblist(void)
36{
37 struct bloblist_hdr *hdr;
38
Simon Glassb83994d2020-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 Glass919e7a82018-11-15 18:43:53 -070044 hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
Simon Glass751b7c72020-09-19 18:49:28 -060045 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
Simon Glassb83994d2020-01-27 08:49:52 -070046 memset(hdr, '\0', sizeof(*hdr));
Simon Glass919e7a82018-11-15 18:43:53 -070047
48 return hdr;
49}
50
Simon Glassb83994d2020-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 Glass919e7a82018-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));
70 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
71 hdr->version++;
72 ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
73 TEST_BLOBLIST_SIZE));
74
75 ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0x10, 0));
76 ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0));
77 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
78
79 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
80 ut_assertok(bloblist_finish());
81 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
82 hdr->flags++;
83 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
84
85 return 1;
86}
87BLOBLIST_TEST(bloblist_test_init, 0);
88
89static int bloblist_test_blob(struct unit_test_state *uts)
90{
91 struct bloblist_hdr *hdr;
92 struct bloblist_rec *rec, *rec2;
93 char *data;
94
95 /* At the start there should be no records */
96 hdr = clear_bloblist();
97 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
98 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
Simon Glasscdd4e302020-09-19 18:49:27 -060099 ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
Simon Glass919e7a82018-11-15 18:43:53 -0700100
101 /* Add a record and check that we can find it */
Simon Glass4c1497e2020-09-19 18:49:29 -0600102 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass919e7a82018-11-15 18:43:53 -0700103 rec = (void *)(hdr + 1);
Simon Glasscdd4e302020-09-19 18:49:27 -0600104 ut_asserteq_addr(rec + 1, data);
Simon Glass919e7a82018-11-15 18:43:53 -0700105 data = bloblist_find(TEST_TAG, TEST_SIZE);
Simon Glasscdd4e302020-09-19 18:49:27 -0600106 ut_asserteq_addr(rec + 1, data);
Simon Glass919e7a82018-11-15 18:43:53 -0700107
Simon Glassb83994d2020-01-27 08:49:52 -0700108 /* Check the data is zeroed */
109 ut_assertok(check_zero(data, TEST_SIZE));
110
Simon Glass919e7a82018-11-15 18:43:53 -0700111 /* Check the 'ensure' method */
Simon Glasscdd4e302020-09-19 18:49:27 -0600112 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass919e7a82018-11-15 18:43:53 -0700113 ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
114 rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
Simon Glassb83994d2020-01-27 08:49:52 -0700115 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass919e7a82018-11-15 18:43:53 -0700116
117 /* Check for a non-existent record */
Simon Glasscdd4e302020-09-19 18:49:27 -0600118 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
119 ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
Simon Glass919e7a82018-11-15 18:43:53 -0700120 ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
121
122 return 0;
123}
124BLOBLIST_TEST(bloblist_test_blob, 0);
125
Simon Glass5b044542020-01-27 08:49:50 -0700126/* Check bloblist_ensure_size_ret() */
127static int bloblist_test_blob_ensure(struct unit_test_state *uts)
128{
129 void *data, *data2;
130 int size;
131
132 /* At the start there should be no records */
133 clear_bloblist();
134 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
135
136 /* Test with an empty bloblist */
137 size = TEST_SIZE;
138 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
139 ut_asserteq(TEST_SIZE, size);
Simon Glassb83994d2020-01-27 08:49:52 -0700140 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass5b044542020-01-27 08:49:50 -0700141
142 /* Check that we get the same thing again */
143 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
144 ut_asserteq(TEST_SIZE, size);
Simon Glasscdd4e302020-09-19 18:49:27 -0600145 ut_asserteq_addr(data, data2);
Simon Glass5b044542020-01-27 08:49:50 -0700146
147 /* Check that the size remains the same */
148 size = TEST_SIZE2;
149 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
150 ut_asserteq(TEST_SIZE, size);
151
152 /* Check running out of space */
153 size = TEST_SIZE_LARGE;
154 ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
155
156 return 0;
157}
158BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
159
Simon Glass919e7a82018-11-15 18:43:53 -0700160static int bloblist_test_bad_blob(struct unit_test_state *uts)
161{
162 struct bloblist_hdr *hdr;
163 void *data;
164
165 hdr = clear_bloblist();
166 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
167 data = hdr + 1;
168 data += sizeof(struct bloblist_rec);
Simon Glasscdd4e302020-09-19 18:49:27 -0600169 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
170 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass919e7a82018-11-15 18:43:53 -0700171
172 return 0;
173}
174BLOBLIST_TEST(bloblist_test_bad_blob, 0);
175
176static int bloblist_test_checksum(struct unit_test_state *uts)
177{
178 struct bloblist_hdr *hdr;
179 char *data, *data2;
180
181 hdr = clear_bloblist();
182 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
183 ut_assertok(bloblist_finish());
184 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
185
186 /*
187 * Now change things amd make sure that the checksum notices. We cannot
188 * change the size or alloced fields, since that will crash the code.
189 * It has to rely on these being correct.
190 */
191 hdr->flags--;
192 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
193 hdr->flags++;
194
195 hdr->size--;
196 ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
197 hdr->size++;
198
199 hdr->spare++;
200 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
201 hdr->spare--;
202
203 hdr->chksum++;
204 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
205 hdr->chksum--;
206
207 /* Make sure the checksum changes when we add blobs */
Simon Glass4c1497e2020-09-19 18:49:29 -0600208 data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
Simon Glass919e7a82018-11-15 18:43:53 -0700209 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
210
Simon Glass4c1497e2020-09-19 18:49:29 -0600211 data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0);
Simon Glass919e7a82018-11-15 18:43:53 -0700212 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
213 ut_assertok(bloblist_finish());
214
215 /* It should also change if we change the data */
216 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
217 *data += 1;
218 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
219 *data -= 1;
220
221 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
222 *data2 += 1;
223 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
224 *data2 -= 1;
225
226 /*
227 * Changing data outside the range of valid data should not affect
228 * the checksum.
229 */
230 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
231 data[TEST_SIZE]++;
232 data2[TEST_SIZE2]++;
233 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
234
235 return 0;
236}
Simon Glass919e7a82018-11-15 18:43:53 -0700237BLOBLIST_TEST(bloblist_test_checksum, 0);
238
Simon Glass4aed2272020-09-19 18:49:26 -0600239/* Test the 'bloblist info' command */
240static int bloblist_test_cmd_info(struct unit_test_state *uts)
241{
Simon Glass4aed2272020-09-19 18:49:26 -0600242 struct bloblist_hdr *hdr;
243 char *data, *data2;
244
245 hdr = clear_bloblist();
246 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
247 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
248 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
249
250 console_record_reset_enable();
Simon Glassef7e2642020-11-08 21:08:43 -0700251 ut_silence_console(uts);
Simon Glass4aed2272020-09-19 18:49:26 -0600252 console_record_reset();
253 run_command("bloblist info", 0);
Simon Glasscdd4e302020-09-19 18:49:27 -0600254 ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
Simon Glass4c1497e2020-09-19 18:49:29 -0600255 ut_assert_nextline("size: 400 1 KiB");
Simon Glass4aed2272020-09-19 18:49:26 -0600256 ut_assert_nextline("alloced: 70 112 Bytes");
Simon Glass4c1497e2020-09-19 18:49:29 -0600257 ut_assert_nextline("free: 390 912 Bytes");
Simon Glass4aed2272020-09-19 18:49:26 -0600258 ut_assert_console_end();
Simon Glassef7e2642020-11-08 21:08:43 -0700259 ut_unsilence_console(uts);
Simon Glass4aed2272020-09-19 18:49:26 -0600260
261 return 0;
262}
263BLOBLIST_TEST(bloblist_test_cmd_info, 0);
264
265/* Test the 'bloblist list' command */
266static int bloblist_test_cmd_list(struct unit_test_state *uts)
267{
Simon Glass4aed2272020-09-19 18:49:26 -0600268 struct bloblist_hdr *hdr;
269 char *data, *data2;
270
271 hdr = clear_bloblist();
272 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
273 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
274 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
275
276 console_record_reset_enable();
Simon Glassef7e2642020-11-08 21:08:43 -0700277 ut_silence_console(uts);
Simon Glass4aed2272020-09-19 18:49:26 -0600278 console_record_reset();
279 run_command("bloblist list", 0);
280 ut_assert_nextline("Address Size Tag Name");
Simon Glasscdd4e302020-09-19 18:49:27 -0600281 ut_assert_nextline("%08lx %8x 1 EC host event",
282 (ulong)map_to_sysmem(data), TEST_SIZE);
283 ut_assert_nextline("%08lx %8x 2 SPL hand-off",
284 (ulong)map_to_sysmem(data2), TEST_SIZE2);
Simon Glass4aed2272020-09-19 18:49:26 -0600285 ut_assert_console_end();
Simon Glassef7e2642020-11-08 21:08:43 -0700286 ut_unsilence_console(uts);
Simon Glass4aed2272020-09-19 18:49:26 -0600287
288 return 0;
289}
290BLOBLIST_TEST(bloblist_test_cmd_list, 0);
291
Simon Glass751b7c72020-09-19 18:49:28 -0600292/* Test alignment of bloblist blobs */
293static int bloblist_test_align(struct unit_test_state *uts)
294{
295 struct bloblist_hdr *hdr;
Simon Glass4c1497e2020-09-19 18:49:29 -0600296 ulong addr;
297 char *data;
Simon Glass751b7c72020-09-19 18:49:28 -0600298 int i;
299
300 /* At the start there should be no records */
301 hdr = clear_bloblist();
302 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
303 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
304
Simon Glass4c1497e2020-09-19 18:49:29 -0600305 /* Check the default alignment */
Simon Glass751b7c72020-09-19 18:49:28 -0600306 for (i = 0; i < 3; i++) {
307 int size = i * 3;
308 ulong addr;
309 char *data;
310 int j;
311
Simon Glass4c1497e2020-09-19 18:49:29 -0600312 data = bloblist_add(i, size, 0);
Simon Glass751b7c72020-09-19 18:49:28 -0600313 ut_assertnonnull(data);
314 addr = map_to_sysmem(data);
315 ut_asserteq(0, addr & (BLOBLIST_ALIGN - 1));
316
317 /* Only the bytes in the blob data should be zeroed */
318 for (j = 0; j < size; j++)
319 ut_asserteq(0, data[j]);
320 for (; j < BLOBLIST_ALIGN; j++)
321 ut_asserteq(ERASE_BYTE, data[j]);
322 }
323
Simon Glass4c1497e2020-09-19 18:49:29 -0600324 /* Check larger alignment */
325 for (i = 0; i < 3; i++) {
326 int align = 32 << i;
327
328 data = bloblist_add(3 + i, i * 4, align);
329 ut_assertnonnull(data);
330 addr = map_to_sysmem(data);
331 ut_asserteq(0, addr & (align - 1));
332 }
333
334 /* Check alignment with an bloblist starting on a smaller alignment */
335 hdr = map_sysmem(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE);
336 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
337 memset(hdr, '\0', sizeof(*hdr));
338 ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
339 0));
340
341 data = bloblist_add(1, 5, BLOBLIST_ALIGN * 2);
342 ut_assertnonnull(data);
343 addr = map_to_sysmem(data);
344 ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1));
345
Simon Glass751b7c72020-09-19 18:49:28 -0600346 return 0;
347}
348BLOBLIST_TEST(bloblist_test_align, 0);
349
Simon Glass09140112020-05-10 11:40:03 -0600350int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
351 char *const argv[])
Simon Glass919e7a82018-11-15 18:43:53 -0700352{
353 struct unit_test *tests = ll_entry_start(struct unit_test,
354 bloblist_test);
355 const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
356
Philippe Reynes4ad4edf2019-12-17 19:07:04 +0100357 return cmd_ut_category("bloblist", "bloblist_test_",
358 tests, n_ents, argc, argv);
Simon Glass919e7a82018-11-15 18:43:53 -0700359}