blob: 68535237641a5affdd589c228aeacd006cf5acae [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
6#include <common.h>
7#include <bloblist.h>
8#include <log.h>
9#include <mapmem.h>
Simon Glassb936a972020-09-19 18:49:26 -060010#include <asm/state.h>
Simon Glass78b0ef52018-11-15 18:43:53 -070011#include <test/suites.h>
12#include <test/test.h>
13#include <test/ut.h>
14
15DECLARE_GLOBAL_DATA_PTR;
16
17/* Declare a new compression test */
18#define BLOBLIST_TEST(_name, _flags) \
19 UNIT_TEST(_name, _flags, bloblist_test)
20
21enum {
22 TEST_TAG = 1,
23 TEST_TAG2 = 2,
24 TEST_TAG_MISSING = 3,
25
26 TEST_SIZE = 10,
27 TEST_SIZE2 = 20,
Simon Glass1e0304e2020-01-27 08:49:50 -070028 TEST_SIZE_LARGE = 0xe0,
Simon Glass78b0ef52018-11-15 18:43:53 -070029
30 TEST_ADDR = CONFIG_BLOBLIST_ADDR,
31 TEST_BLOBLIST_SIZE = 0x100,
Simon Glassd7985e62020-09-19 18:49:28 -060032
33 ERASE_BYTE = '\xff',
Simon Glass78b0ef52018-11-15 18:43:53 -070034};
35
36static struct bloblist_hdr *clear_bloblist(void)
37{
38 struct bloblist_hdr *hdr;
39
Simon Glass3e85ea02020-01-27 08:49:52 -070040 /*
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.
44 */
Simon Glass78b0ef52018-11-15 18:43:53 -070045 hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
Simon Glassd7985e62020-09-19 18:49:28 -060046 memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
Simon Glass3e85ea02020-01-27 08:49:52 -070047 memset(hdr, '\0', sizeof(*hdr));
Simon Glass78b0ef52018-11-15 18:43:53 -070048
49 return hdr;
50}
51
Simon Glass3e85ea02020-01-27 08:49:52 -070052static int check_zero(void *data, int size)
53{
54 u8 *ptr;
55 int i;
56
57 for (ptr = data, i = 0; i < size; i++, ptr++) {
58 if (*ptr)
59 return -EINVAL;
60 }
61
62 return 0;
63}
64
Simon Glass78b0ef52018-11-15 18:43:53 -070065static int bloblist_test_init(struct unit_test_state *uts)
66{
67 struct bloblist_hdr *hdr;
68
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));
72 hdr->version++;
73 ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
74 TEST_BLOBLIST_SIZE));
75
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));
79
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));
83 hdr->flags++;
84 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
85
86 return 1;
87}
88BLOBLIST_TEST(bloblist_test_init, 0);
89
90static int bloblist_test_blob(struct unit_test_state *uts)
91{
92 struct bloblist_hdr *hdr;
93 struct bloblist_rec *rec, *rec2;
94 char *data;
95
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));
Simon Glass7c58b082020-09-19 18:49:27 -0600100 ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
Simon Glass78b0ef52018-11-15 18:43:53 -0700101
102 /* Add a record and check that we can find it */
103 data = bloblist_add(TEST_TAG, TEST_SIZE);
104 rec = (void *)(hdr + 1);
Simon Glass7c58b082020-09-19 18:49:27 -0600105 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700106 data = bloblist_find(TEST_TAG, TEST_SIZE);
Simon Glass7c58b082020-09-19 18:49:27 -0600107 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700108
Simon Glass3e85ea02020-01-27 08:49:52 -0700109 /* Check the data is zeroed */
110 ut_assertok(check_zero(data, TEST_SIZE));
111
Simon Glass78b0ef52018-11-15 18:43:53 -0700112 /* Check the 'ensure' method */
Simon Glass7c58b082020-09-19 18:49:27 -0600113 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700114 ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
115 rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
Simon Glass3e85ea02020-01-27 08:49:52 -0700116 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700117
118 /* Check for a non-existent record */
Simon Glass7c58b082020-09-19 18:49:27 -0600119 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
120 ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
Simon Glass78b0ef52018-11-15 18:43:53 -0700121 ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
122
123 return 0;
124}
125BLOBLIST_TEST(bloblist_test_blob, 0);
126
Simon Glass1e0304e2020-01-27 08:49:50 -0700127/* Check bloblist_ensure_size_ret() */
128static int bloblist_test_blob_ensure(struct unit_test_state *uts)
129{
130 void *data, *data2;
131 int size;
132
133 /* At the start there should be no records */
134 clear_bloblist();
135 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
136
137 /* Test with an empty bloblist */
138 size = TEST_SIZE;
139 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
140 ut_asserteq(TEST_SIZE, size);
Simon Glass3e85ea02020-01-27 08:49:52 -0700141 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass1e0304e2020-01-27 08:49:50 -0700142
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);
Simon Glass7c58b082020-09-19 18:49:27 -0600146 ut_asserteq_addr(data, data2);
Simon Glass1e0304e2020-01-27 08:49:50 -0700147
148 /* Check that the size remains the same */
149 size = TEST_SIZE2;
150 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
151 ut_asserteq(TEST_SIZE, size);
152
153 /* Check running out of space */
154 size = TEST_SIZE_LARGE;
155 ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
156
157 return 0;
158}
159BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
160
Simon Glass78b0ef52018-11-15 18:43:53 -0700161static int bloblist_test_bad_blob(struct unit_test_state *uts)
162{
163 struct bloblist_hdr *hdr;
164 void *data;
165
166 hdr = clear_bloblist();
167 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
168 data = hdr + 1;
169 data += sizeof(struct bloblist_rec);
Simon Glass7c58b082020-09-19 18:49:27 -0600170 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
171 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700172
173 return 0;
174}
175BLOBLIST_TEST(bloblist_test_bad_blob, 0);
176
177static int bloblist_test_checksum(struct unit_test_state *uts)
178{
179 struct bloblist_hdr *hdr;
180 char *data, *data2;
181
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));
186
187 /*
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.
191 */
192 hdr->flags--;
193 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
194 hdr->flags++;
195
196 hdr->size--;
197 ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
198 hdr->size++;
199
200 hdr->spare++;
201 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
202 hdr->spare--;
203
204 hdr->chksum++;
205 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
206 hdr->chksum--;
207
208 /* Make sure the checksum changes when we add blobs */
209 data = bloblist_add(TEST_TAG, TEST_SIZE);
210 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
211
212 data2 = bloblist_add(TEST_TAG2, TEST_SIZE2);
213 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
214 ut_assertok(bloblist_finish());
215
216 /* It should also change if we change the data */
217 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
218 *data += 1;
219 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
220 *data -= 1;
221
222 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
223 *data2 += 1;
224 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
225 *data2 -= 1;
226
227 /*
228 * Changing data outside the range of valid data should not affect
229 * the checksum.
230 */
231 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
232 data[TEST_SIZE]++;
233 data2[TEST_SIZE2]++;
234 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
235
236 return 0;
237}
Simon Glass78b0ef52018-11-15 18:43:53 -0700238BLOBLIST_TEST(bloblist_test_checksum, 0);
239
Simon Glassb936a972020-09-19 18:49:26 -0600240/* Test the 'bloblist info' command */
241static int bloblist_test_cmd_info(struct unit_test_state *uts)
242{
243 struct sandbox_state *state = state_get_current();
244 struct bloblist_hdr *hdr;
245 char *data, *data2;
246
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);
251
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);
Simon Glass7c58b082020-09-19 18:49:27 -0600257 ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
Simon Glassb936a972020-09-19 18:49:26 -0600258 ut_assert_nextline("size: 100 256 Bytes");
259 ut_assert_nextline("alloced: 70 112 Bytes");
260 ut_assert_nextline("free: 90 144 Bytes");
261 ut_assert_console_end();
262 gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
263
264 return 0;
265}
266BLOBLIST_TEST(bloblist_test_cmd_info, 0);
267
268/* Test the 'bloblist list' command */
269static int bloblist_test_cmd_list(struct unit_test_state *uts)
270{
271 struct sandbox_state *state = state_get_current();
272 struct bloblist_hdr *hdr;
273 char *data, *data2;
274
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);
279
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");
Simon Glass7c58b082020-09-19 18:49:27 -0600286 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);
Simon Glassb936a972020-09-19 18:49:26 -0600290 ut_assert_console_end();
291 gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
292
293 return 0;
294}
295BLOBLIST_TEST(bloblist_test_cmd_list, 0);
296
Simon Glassd7985e62020-09-19 18:49:28 -0600297/* Test alignment of bloblist blobs */
298static int bloblist_test_align(struct unit_test_state *uts)
299{
300 struct bloblist_hdr *hdr;
301 int i;
302
303 /* At the start there should be no records */
304 hdr = clear_bloblist();
305 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
306 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
307
308 /* Check the alignment */
309 for (i = 0; i < 3; i++) {
310 int size = i * 3;
311 ulong addr;
312 char *data;
313 int j;
314
315 data = bloblist_add(i, size);
316 ut_assertnonnull(data);
317 addr = map_to_sysmem(data);
318 ut_asserteq(0, addr & (BLOBLIST_ALIGN - 1));
319
320 /* Only the bytes in the blob data should be zeroed */
321 for (j = 0; j < size; j++)
322 ut_asserteq(0, data[j]);
323 for (; j < BLOBLIST_ALIGN; j++)
324 ut_asserteq(ERASE_BYTE, data[j]);
325 }
326
327 return 0;
328}
329BLOBLIST_TEST(bloblist_test_align, 0);
330
Simon Glassed38aef2020-05-10 11:40:03 -0600331int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
332 char *const argv[])
Simon Glass78b0ef52018-11-15 18:43:53 -0700333{
334 struct unit_test *tests = ll_entry_start(struct unit_test,
335 bloblist_test);
336 const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
337
Philippe Reynes1f99f842019-12-17 19:07:04 +0100338 return cmd_ut_category("bloblist", "bloblist_test_",
339 tests, n_ents, argc, argv);
Simon Glass78b0ef52018-11-15 18:43:53 -0700340}