blob: 028b0a9383c519d7b54a86be479d79500314c700 [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,
32};
33
34static struct bloblist_hdr *clear_bloblist(void)
35{
36 struct bloblist_hdr *hdr;
37
Simon Glass3e85ea02020-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 Glass78b0ef52018-11-15 18:43:53 -070043 hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
Simon Glass3e85ea02020-01-27 08:49:52 -070044 memset(hdr, '\xff', TEST_BLOBLIST_SIZE);
45 memset(hdr, '\0', sizeof(*hdr));
Simon Glass78b0ef52018-11-15 18:43:53 -070046
47 return hdr;
48}
49
Simon Glass3e85ea02020-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 Glass78b0ef52018-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));
Simon Glass7c58b082020-09-19 18:49:27 -060098 ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
Simon Glass78b0ef52018-11-15 18:43:53 -070099
100 /* Add a record and check that we can find it */
101 data = bloblist_add(TEST_TAG, TEST_SIZE);
102 rec = (void *)(hdr + 1);
Simon Glass7c58b082020-09-19 18:49:27 -0600103 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700104 data = bloblist_find(TEST_TAG, TEST_SIZE);
Simon Glass7c58b082020-09-19 18:49:27 -0600105 ut_asserteq_addr(rec + 1, data);
Simon Glass78b0ef52018-11-15 18:43:53 -0700106
Simon Glass3e85ea02020-01-27 08:49:52 -0700107 /* Check the data is zeroed */
108 ut_assertok(check_zero(data, TEST_SIZE));
109
Simon Glass78b0ef52018-11-15 18:43:53 -0700110 /* Check the 'ensure' method */
Simon Glass7c58b082020-09-19 18:49:27 -0600111 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700112 ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
113 rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
Simon Glass3e85ea02020-01-27 08:49:52 -0700114 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700115
116 /* Check for a non-existent record */
Simon Glass7c58b082020-09-19 18:49:27 -0600117 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
118 ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
Simon Glass78b0ef52018-11-15 18:43:53 -0700119 ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
120
121 return 0;
122}
123BLOBLIST_TEST(bloblist_test_blob, 0);
124
Simon Glass1e0304e2020-01-27 08:49:50 -0700125/* Check bloblist_ensure_size_ret() */
126static int bloblist_test_blob_ensure(struct unit_test_state *uts)
127{
128 void *data, *data2;
129 int size;
130
131 /* At the start there should be no records */
132 clear_bloblist();
133 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
134
135 /* Test with an empty bloblist */
136 size = TEST_SIZE;
137 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
138 ut_asserteq(TEST_SIZE, size);
Simon Glass3e85ea02020-01-27 08:49:52 -0700139 ut_assertok(check_zero(data, TEST_SIZE));
Simon Glass1e0304e2020-01-27 08:49:50 -0700140
141 /* Check that we get the same thing again */
142 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2));
143 ut_asserteq(TEST_SIZE, size);
Simon Glass7c58b082020-09-19 18:49:27 -0600144 ut_asserteq_addr(data, data2);
Simon Glass1e0304e2020-01-27 08:49:50 -0700145
146 /* Check that the size remains the same */
147 size = TEST_SIZE2;
148 ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data));
149 ut_asserteq(TEST_SIZE, size);
150
151 /* Check running out of space */
152 size = TEST_SIZE_LARGE;
153 ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data));
154
155 return 0;
156}
157BLOBLIST_TEST(bloblist_test_blob_ensure, 0);
158
Simon Glass78b0ef52018-11-15 18:43:53 -0700159static int bloblist_test_bad_blob(struct unit_test_state *uts)
160{
161 struct bloblist_hdr *hdr;
162 void *data;
163
164 hdr = clear_bloblist();
165 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
166 data = hdr + 1;
167 data += sizeof(struct bloblist_rec);
Simon Glass7c58b082020-09-19 18:49:27 -0600168 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
169 ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
Simon Glass78b0ef52018-11-15 18:43:53 -0700170
171 return 0;
172}
173BLOBLIST_TEST(bloblist_test_bad_blob, 0);
174
175static int bloblist_test_checksum(struct unit_test_state *uts)
176{
177 struct bloblist_hdr *hdr;
178 char *data, *data2;
179
180 hdr = clear_bloblist();
181 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
182 ut_assertok(bloblist_finish());
183 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
184
185 /*
186 * Now change things amd make sure that the checksum notices. We cannot
187 * change the size or alloced fields, since that will crash the code.
188 * It has to rely on these being correct.
189 */
190 hdr->flags--;
191 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
192 hdr->flags++;
193
194 hdr->size--;
195 ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
196 hdr->size++;
197
198 hdr->spare++;
199 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
200 hdr->spare--;
201
202 hdr->chksum++;
203 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
204 hdr->chksum--;
205
206 /* Make sure the checksum changes when we add blobs */
207 data = bloblist_add(TEST_TAG, TEST_SIZE);
208 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
209
210 data2 = bloblist_add(TEST_TAG2, TEST_SIZE2);
211 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
212 ut_assertok(bloblist_finish());
213
214 /* It should also change if we change the data */
215 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
216 *data += 1;
217 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
218 *data -= 1;
219
220 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
221 *data2 += 1;
222 ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
223 *data2 -= 1;
224
225 /*
226 * Changing data outside the range of valid data should not affect
227 * the checksum.
228 */
229 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
230 data[TEST_SIZE]++;
231 data2[TEST_SIZE2]++;
232 ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
233
234 return 0;
235}
Simon Glass78b0ef52018-11-15 18:43:53 -0700236BLOBLIST_TEST(bloblist_test_checksum, 0);
237
Simon Glassb936a972020-09-19 18:49:26 -0600238/* Test the 'bloblist info' command */
239static int bloblist_test_cmd_info(struct unit_test_state *uts)
240{
241 struct sandbox_state *state = state_get_current();
242 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();
251 if (!state->show_test_output)
252 gd->flags |= GD_FLG_SILENT;
253 console_record_reset();
254 run_command("bloblist info", 0);
Simon Glass7c58b082020-09-19 18:49:27 -0600255 ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
Simon Glassb936a972020-09-19 18:49:26 -0600256 ut_assert_nextline("size: 100 256 Bytes");
257 ut_assert_nextline("alloced: 70 112 Bytes");
258 ut_assert_nextline("free: 90 144 Bytes");
259 ut_assert_console_end();
260 gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
261
262 return 0;
263}
264BLOBLIST_TEST(bloblist_test_cmd_info, 0);
265
266/* Test the 'bloblist list' command */
267static int bloblist_test_cmd_list(struct unit_test_state *uts)
268{
269 struct sandbox_state *state = state_get_current();
270 struct bloblist_hdr *hdr;
271 char *data, *data2;
272
273 hdr = clear_bloblist();
274 ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
275 data = bloblist_ensure(TEST_TAG, TEST_SIZE);
276 data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
277
278 console_record_reset_enable();
279 if (!state->show_test_output)
280 gd->flags |= GD_FLG_SILENT;
281 console_record_reset();
282 run_command("bloblist list", 0);
283 ut_assert_nextline("Address Size Tag Name");
Simon Glass7c58b082020-09-19 18:49:27 -0600284 ut_assert_nextline("%08lx %8x 1 EC host event",
285 (ulong)map_to_sysmem(data), TEST_SIZE);
286 ut_assert_nextline("%08lx %8x 2 SPL hand-off",
287 (ulong)map_to_sysmem(data2), TEST_SIZE2);
Simon Glassb936a972020-09-19 18:49:26 -0600288 ut_assert_console_end();
289 gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD);
290
291 return 0;
292}
293BLOBLIST_TEST(bloblist_test_cmd_list, 0);
294
Simon Glassed38aef2020-05-10 11:40:03 -0600295int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
296 char *const argv[])
Simon Glass78b0ef52018-11-15 18:43:53 -0700297{
298 struct unit_test *tests = ll_entry_start(struct unit_test,
299 bloblist_test);
300 const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
301
Philippe Reynes1f99f842019-12-17 19:07:04 +0100302 return cmd_ut_category("bloblist", "bloblist_test_",
303 tests, n_ents, argc, argv);
Simon Glass78b0ef52018-11-15 18:43:53 -0700304}