blob: cbdc9db4ecfa4cadbb80e46a499a8b89bc2276b7 [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>
Simon Glass4aed2272020-09-19 18:49:26 -060010#include <asm/state.h>
Simon Glass919e7a82018-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 Glass5b044542020-01-27 08:49:50 -070028 TEST_SIZE_LARGE = 0xe0,
Simon Glass919e7a82018-11-15 18:43:53 -070029
30 TEST_ADDR = CONFIG_BLOBLIST_ADDR,
31 TEST_BLOBLIST_SIZE = 0x100,
32};
33
34static struct bloblist_hdr *clear_bloblist(void)
35{
36 struct bloblist_hdr *hdr;
37
Simon Glassb83994d2020-01-27 08:49:52 -070038 /*
39 * Clear out any existing bloblist so we have a clean slate. Zero the
40 * header so that existing records are removed, but set everything else
41 * to 0xff for testing purposes.
42 */
Simon Glass919e7a82018-11-15 18:43:53 -070043 hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
Simon Glassb83994d2020-01-27 08:49:52 -070044 memset(hdr, '\xff', TEST_BLOBLIST_SIZE);
45 memset(hdr, '\0', sizeof(*hdr));
Simon Glass919e7a82018-11-15 18:43:53 -070046
47 return hdr;
48}
49
Simon Glassb83994d2020-01-27 08:49:52 -070050static int check_zero(void *data, int size)
51{
52 u8 *ptr;
53 int i;
54
55 for (ptr = data, i = 0; i < size; i++, ptr++) {
56 if (*ptr)
57 return -EINVAL;
58 }
59
60 return 0;
61}
62
Simon Glass919e7a82018-11-15 18:43:53 -070063static int bloblist_test_init(struct unit_test_state *uts)
64{
65 struct bloblist_hdr *hdr;
66
67 hdr = clear_bloblist();
68 ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
69 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
70 hdr->version++;
71 ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
72 TEST_BLOBLIST_SIZE));
73
74 ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0x10, 0));
75 ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0));
76 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
77
78 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
79 ut_assertok(bloblist_finish());
80 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
81 hdr->flags++;
82 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
83
84 return 1;
85}
86BLOBLIST_TEST(bloblist_test_init, 0);
87
88static int bloblist_test_blob(struct unit_test_state *uts)
89{
90 struct bloblist_hdr *hdr;
91 struct bloblist_rec *rec, *rec2;
92 char *data;
93
94 /* At the start there should be no records */
95 hdr = clear_bloblist();
96 ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
97 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
98
99 /* Add a record and check that we can find it */
100 data = bloblist_add(TEST_TAG, TEST_SIZE);
101 rec = (void *)(hdr + 1);
102 ut_asserteq_ptr(rec + 1, data);
103 data = bloblist_find(TEST_TAG, TEST_SIZE);
104 ut_asserteq_ptr(rec + 1, data);
105
Simon Glassb83994d2020-01-27 08:49:52 -0700106 /* Check the data is zeroed */
107 ut_assertok(check_zero(data, TEST_SIZE));
108
Simon Glass919e7a82018-11-15 18:43:53 -0700109 /* Check the 'ensure' method */
110 ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
111 ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
112 rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
Simon Glassb83994d2020-01-27 08:49:52 -0700113 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass919e7a82018-11-15 18:43:53 -0700114
115 /* Check for a non-existent record */
116 ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
117 ut_asserteq_ptr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
118 ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
119
120 return 0;
121}
122BLOBLIST_TEST(bloblist_test_blob, 0);
123
Simon Glass5b044542020-01-27 08:49:50 -0700124/* Check bloblist_ensure_size_ret() */
125static int bloblist_test_blob_ensure(struct unit_test_state *uts)
126{
127 void *data, *data2;
128 int size;
129
130 /* At the start there should be no records */
131 clear_bloblist();
132 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
133
134 /* Test with an empty bloblist */
135 size = TEST_SIZE;
136 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
137 ut_asserteq(TEST_SIZE, size);
Simon Glassb83994d2020-01-27 08:49:52 -0700138 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass5b044542020-01-27 08:49:50 -0700139
140 /* Check that we get the same thing again */
141 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
142 ut_asserteq(TEST_SIZE, size);
143 ut_asserteq_ptr(data, data2);
144
145 /* Check that the size remains the same */
146 size = TEST_SIZE2;
147 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
148 ut_asserteq(TEST_SIZE, size);
149
150 /* Check running out of space */
151 size = TEST_SIZE_LARGE;
152 ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
153
154 return 0;
155}
156BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
157
Simon Glass919e7a82018-11-15 18:43:53 -0700158static int bloblist_test_bad_blob(struct unit_test_state *uts)
159{
160 struct bloblist_hdr *hdr;
161 void *data;
162
163 hdr = clear_bloblist();
164 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
165 data = hdr + 1;
166 data += sizeof(struct bloblist_rec);
167 ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
168 ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
169
170 return 0;
171}
172BLOBLIST_TEST(bloblist_test_bad_blob, 0);
173
174static int bloblist_test_checksum(struct unit_test_state *uts)
175{
176 struct bloblist_hdr *hdr;
177 char *data, *data2;
178
179 hdr = clear_bloblist();
180 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
181 ut_assertok(bloblist_finish());
182 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
183
184 /*
185 * Now change things amd make sure that the checksum notices. We cannot
186 * change the size or alloced fields, since that will crash the code.
187 * It has to rely on these being correct.
188 */
189 hdr->flags--;
190 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
191 hdr->flags++;
192
193 hdr->size--;
194 ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
195 hdr->size++;
196
197 hdr->spare++;
198 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
199 hdr->spare--;
200
201 hdr->chksum++;
202 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
203 hdr->chksum--;
204
205 /* Make sure the checksum changes when we add blobs */
206 data = bloblist_add(TEST_TAG, TEST_SIZE);
207 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
208
209 data2 = bloblist_add(TEST_TAG2, TEST_SIZE2);
210 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
211 ut_assertok(bloblist_finish());
212
213 /* It should also change if we change the data */
214 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
215 *data += 1;
216 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
217 *data -= 1;
218
219 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
220 *data2 += 1;
221 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
222 *data2 -= 1;
223
224 /*
225 * Changing data outside the range of valid data should not affect
226 * the checksum.
227 */
228 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
229 data[TEST_SIZE]++;
230 data2[TEST_SIZE2]++;
231 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
232
233 return 0;
234}
Simon Glass919e7a82018-11-15 18:43:53 -0700235BLOBLIST_TEST(bloblist_test_checksum, 0);
236
Simon Glass4aed2272020-09-19 18:49:26 -0600237/* Test the 'bloblist info' command */
238static int bloblist_test_cmd_info(struct unit_test_state *uts)
239{
240 struct sandbox_state *state = state_get_current();
241 struct bloblist_hdr *hdr;
242 char *data, *data2;
243
244 hdr = clear_bloblist();
245 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
246 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
247 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
248
249 console_record_reset_enable();
250 if (!state->show_test_output)
251 gd->flags |= GD_FLG_SILENT;
252 console_record_reset();
253 run_command("bloblist info", 0);
254 ut_assert_nextline("base: %x", map_to_sysmem(hdr));
255 ut_assert_nextline("size: 100 256 Bytes");
256 ut_assert_nextline("alloced: 70 112 Bytes");
257 ut_assert_nextline("free: 90 144 Bytes");
258 ut_assert_console_end();
259 gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
260
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{
268 struct sandbox_state *state = state_get_current();
269 struct bloblist_hdr *hdr;
270 char *data, *data2;
271
272 hdr = clear_bloblist();
273 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
274 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
275 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
276
277 console_record_reset_enable();
278 if (!state->show_test_output)
279 gd->flags |= GD_FLG_SILENT;
280 console_record_reset();
281 run_command("bloblist list", 0);
282 ut_assert_nextline("Address Size Tag Name");
283 ut_assert_nextline("%08x %8x 1 EC host event", map_to_sysmem(data),
284 TEST_SIZE);
285 ut_assert_nextline("%08x %8x 2 SPL hand-off", map_to_sysmem(data2),
286 TEST_SIZE2);
287 ut_assert_console_end();
288 gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
289
290 return 0;
291}
292BLOBLIST_TEST(bloblist_test_cmd_list, 0);
293
Simon Glass09140112020-05-10 11:40:03 -0600294int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
295 char *const argv[])
Simon Glass919e7a82018-11-15 18:43:53 -0700296{
297 struct unit_test *tests = ll_entry_start(struct unit_test,
298 bloblist_test);
299 const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
300
Philippe Reynes4ad4edf2019-12-17 19:07:04 +0100301 return cmd_ut_category("bloblist", "bloblist_test_",
302 tests, n_ents, argc, argv);
Simon Glass919e7a82018-11-15 18:43:53 -0700303}