]>
Commit | Line | Data |
---|---|---|
919e7a8f SG |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (c) 2018, Google Inc. All rights reserved. | |
4 | */ | |
5 | ||
919e7a8f SG |
6 | #include <bloblist.h> |
7 | #include <log.h> | |
8 | #include <mapmem.h> | |
401d1c4f | 9 | #include <asm/global_data.h> |
919e7a8f SG |
10 | #include <test/suites.h> |
11 | #include <test/test.h> | |
12 | #include <test/ut.h> | |
13 | ||
14 | DECLARE_GLOBAL_DATA_PTR; | |
15 | ||
127ca104 | 16 | /* Declare a new bloblist test */ |
919e7a8f SG |
17 | #define BLOBLIST_TEST(_name, _flags) \ |
18 | UNIT_TEST(_name, _flags, bloblist_test) | |
19 | ||
20 | enum { | |
f16ec777 SG |
21 | TEST_TAG = BLOBLISTT_U_BOOT_SPL_HANDOFF, |
22 | TEST_TAG2 = BLOBLISTT_VBOOT_CTX, | |
23 | TEST_TAG_MISSING = 0x10000, | |
919e7a8f SG |
24 | |
25 | TEST_SIZE = 10, | |
26 | TEST_SIZE2 = 20, | |
4c1497e7 | 27 | TEST_SIZE_LARGE = 0x3e0, |
919e7a8f SG |
28 | |
29 | TEST_ADDR = CONFIG_BLOBLIST_ADDR, | |
4c1497e7 | 30 | TEST_BLOBLIST_SIZE = 0x400, |
751b7c79 SG |
31 | |
32 | ERASE_BYTE = '\xff', | |
919e7a8f SG |
33 | }; |
34 | ||
1fe59375 SG |
35 | static const char test1_str[] = "the eyes are open"; |
36 | static const char test2_str[] = "the mouth moves"; | |
37 | ||
919e7a8f SG |
38 | static struct bloblist_hdr *clear_bloblist(void) |
39 | { | |
40 | struct bloblist_hdr *hdr; | |
41 | ||
b83994de SG |
42 | /* |
43 | * Clear out any existing bloblist so we have a clean slate. Zero the | |
44 | * header so that existing records are removed, but set everything else | |
45 | * to 0xff for testing purposes. | |
46 | */ | |
919e7a8f | 47 | hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE); |
751b7c79 | 48 | memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE); |
b83994de | 49 | memset(hdr, '\0', sizeof(*hdr)); |
919e7a8f SG |
50 | |
51 | return hdr; | |
52 | } | |
53 | ||
b83994de SG |
54 | static int check_zero(void *data, int size) |
55 | { | |
56 | u8 *ptr; | |
57 | int i; | |
58 | ||
59 | for (ptr = data, i = 0; i < size; i++, ptr++) { | |
60 | if (*ptr) | |
61 | return -EINVAL; | |
62 | } | |
63 | ||
64 | return 0; | |
65 | } | |
66 | ||
919e7a8f SG |
67 | static int bloblist_test_init(struct unit_test_state *uts) |
68 | { | |
69 | struct bloblist_hdr *hdr; | |
70 | ||
71 | hdr = clear_bloblist(); | |
72 | ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
ff3bd498 | 73 | ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR)); |
7d790a80 | 74 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
ff3bd498 | 75 | ut_asserteq_ptr(hdr, bloblist_check_magic(TEST_ADDR)); |
919e7a8f SG |
76 | hdr->version++; |
77 | ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR, | |
78 | TEST_BLOBLIST_SIZE)); | |
79 | ||
7d790a80 SG |
80 | ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0xc, 0, 0)); |
81 | ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0, 0)); | |
82 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); | |
919e7a8f SG |
83 | |
84 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
85 | ut_assertok(bloblist_finish()); | |
86 | ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
ff3bd498 SG |
87 | |
88 | hdr->magic++; | |
89 | ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR)); | |
90 | hdr->magic--; | |
91 | ||
919e7a8f SG |
92 | hdr->flags++; |
93 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
94 | ||
95 | return 1; | |
96 | } | |
6cdb1497 | 97 | BLOBLIST_TEST(bloblist_test_init, UFT_BLOBLIST); |
919e7a8f SG |
98 | |
99 | static int bloblist_test_blob(struct unit_test_state *uts) | |
100 | { | |
101 | struct bloblist_hdr *hdr; | |
102 | struct bloblist_rec *rec, *rec2; | |
103 | char *data; | |
104 | ||
105 | /* At the start there should be no records */ | |
106 | hdr = clear_bloblist(); | |
107 | ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE)); | |
7d790a80 | 108 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
b86b2d94 SG |
109 | ut_asserteq(sizeof(struct bloblist_hdr), bloblist_get_size()); |
110 | ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_total_size()); | |
e50a24a0 | 111 | ut_asserteq(TEST_ADDR, bloblist_get_base()); |
cdd4e30d | 112 | ut_asserteq(map_to_sysmem(hdr), TEST_ADDR); |
919e7a8f SG |
113 | |
114 | /* Add a record and check that we can find it */ | |
4c1497e7 | 115 | data = bloblist_add(TEST_TAG, TEST_SIZE, 0); |
919e7a8f | 116 | rec = (void *)(hdr + 1); |
cdd4e30d | 117 | ut_asserteq_addr(rec + 1, data); |
919e7a8f | 118 | data = bloblist_find(TEST_TAG, TEST_SIZE); |
cdd4e30d | 119 | ut_asserteq_addr(rec + 1, data); |
919e7a8f | 120 | |
b83994de SG |
121 | /* Check the data is zeroed */ |
122 | ut_assertok(check_zero(data, TEST_SIZE)); | |
123 | ||
919e7a8f | 124 | /* Check the 'ensure' method */ |
cdd4e30d | 125 | ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); |
919e7a8f SG |
126 | ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2)); |
127 | rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN)); | |
b83994de | 128 | ut_assertok(check_zero(data, TEST_SIZE)); |
919e7a8f SG |
129 | |
130 | /* Check for a non-existent record */ | |
cdd4e30d SG |
131 | ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); |
132 | ut_asserteq_addr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2)); | |
919e7a8f SG |
133 | ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0)); |
134 | ||
135 | return 0; | |
136 | } | |
6cdb1497 | 137 | BLOBLIST_TEST(bloblist_test_blob, UFT_BLOBLIST); |
919e7a8f | 138 | |
5b044548 SG |
139 | /* Check bloblist_ensure_size_ret() */ |
140 | static int bloblist_test_blob_ensure(struct unit_test_state *uts) | |
141 | { | |
142 | void *data, *data2; | |
143 | int size; | |
144 | ||
145 | /* At the start there should be no records */ | |
146 | clear_bloblist(); | |
7d790a80 | 147 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
5b044548 SG |
148 | |
149 | /* Test with an empty bloblist */ | |
150 | size = TEST_SIZE; | |
151 | ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data)); | |
152 | ut_asserteq(TEST_SIZE, size); | |
b83994de | 153 | ut_assertok(check_zero(data, TEST_SIZE)); |
5b044548 SG |
154 | |
155 | /* Check that we get the same thing again */ | |
156 | ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data2)); | |
157 | ut_asserteq(TEST_SIZE, size); | |
cdd4e30d | 158 | ut_asserteq_addr(data, data2); |
5b044548 SG |
159 | |
160 | /* Check that the size remains the same */ | |
161 | size = TEST_SIZE2; | |
162 | ut_assertok(bloblist_ensure_size_ret(TEST_TAG, &size, &data)); | |
163 | ut_asserteq(TEST_SIZE, size); | |
164 | ||
165 | /* Check running out of space */ | |
166 | size = TEST_SIZE_LARGE; | |
167 | ut_asserteq(-ENOSPC, bloblist_ensure_size_ret(TEST_TAG2, &size, &data)); | |
168 | ||
169 | return 0; | |
170 | } | |
6cdb1497 | 171 | BLOBLIST_TEST(bloblist_test_blob_ensure, UFT_BLOBLIST); |
5b044548 | 172 | |
919e7a8f SG |
173 | static int bloblist_test_bad_blob(struct unit_test_state *uts) |
174 | { | |
175 | struct bloblist_hdr *hdr; | |
176 | void *data; | |
177 | ||
178 | hdr = clear_bloblist(); | |
7d790a80 | 179 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
919e7a8f SG |
180 | data = hdr + 1; |
181 | data += sizeof(struct bloblist_rec); | |
cdd4e30d SG |
182 | ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); |
183 | ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); | |
919e7a8f SG |
184 | |
185 | return 0; | |
186 | } | |
6cdb1497 | 187 | BLOBLIST_TEST(bloblist_test_bad_blob, UFT_BLOBLIST); |
919e7a8f SG |
188 | |
189 | static int bloblist_test_checksum(struct unit_test_state *uts) | |
190 | { | |
191 | struct bloblist_hdr *hdr; | |
192 | char *data, *data2; | |
193 | ||
194 | hdr = clear_bloblist(); | |
7d790a80 | 195 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
919e7a8f SG |
196 | ut_assertok(bloblist_finish()); |
197 | ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
198 | ||
199 | /* | |
200 | * Now change things amd make sure that the checksum notices. We cannot | |
201 | * change the size or alloced fields, since that will crash the code. | |
202 | * It has to rely on these being correct. | |
203 | */ | |
204 | hdr->flags--; | |
205 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
206 | hdr->flags++; | |
207 | ||
b86b2d94 | 208 | hdr->total_size--; |
67254214 | 209 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); |
b86b2d94 | 210 | hdr->total_size++; |
919e7a8f SG |
211 | |
212 | hdr->spare++; | |
213 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
214 | hdr->spare--; | |
215 | ||
216 | hdr->chksum++; | |
217 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
218 | hdr->chksum--; | |
219 | ||
7d790a80 SG |
220 | hdr->align_log2++; |
221 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
222 | hdr->align_log2--; | |
223 | ||
919e7a8f | 224 | /* Make sure the checksum changes when we add blobs */ |
4c1497e7 | 225 | data = bloblist_add(TEST_TAG, TEST_SIZE, 0); |
919e7a8f SG |
226 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); |
227 | ||
4c1497e7 | 228 | data2 = bloblist_add(TEST_TAG2, TEST_SIZE2, 0); |
919e7a8f SG |
229 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); |
230 | ut_assertok(bloblist_finish()); | |
231 | ||
232 | /* It should also change if we change the data */ | |
233 | ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
234 | *data += 1; | |
235 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
236 | *data -= 1; | |
237 | ||
238 | ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
239 | *data2 += 1; | |
240 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
241 | *data2 -= 1; | |
242 | ||
243 | /* | |
997dac6e SG |
244 | * Changing data outside the range of valid data should affect the |
245 | * checksum. | |
919e7a8f SG |
246 | */ |
247 | ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
248 | data[TEST_SIZE]++; | |
997dac6e SG |
249 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); |
250 | data[TEST_SIZE]--; | |
251 | ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); | |
252 | ||
919e7a8f | 253 | data2[TEST_SIZE2]++; |
997dac6e SG |
254 | ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); |
255 | data[TEST_SIZE]--; | |
919e7a8f SG |
256 | ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); |
257 | ||
258 | return 0; | |
259 | } | |
6cdb1497 | 260 | BLOBLIST_TEST(bloblist_test_checksum, UFT_BLOBLIST); |
919e7a8f | 261 | |
4aed2276 SG |
262 | /* Test the 'bloblist info' command */ |
263 | static int bloblist_test_cmd_info(struct unit_test_state *uts) | |
264 | { | |
4aed2276 SG |
265 | struct bloblist_hdr *hdr; |
266 | char *data, *data2; | |
267 | ||
268 | hdr = clear_bloblist(); | |
7d790a80 | 269 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
4aed2276 SG |
270 | data = bloblist_ensure(TEST_TAG, TEST_SIZE); |
271 | data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2); | |
272 | ||
4aed2276 | 273 | run_command("bloblist info", 0); |
b86b2d94 SG |
274 | ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr)); |
275 | ut_assert_nextline("total size: 400 1 KiB"); | |
276 | ut_assert_nextline("used size: 50 80 Bytes"); | |
277 | ut_assert_nextline("free: 3b0 944 Bytes"); | |
4aed2276 SG |
278 | |
279 | return 0; | |
280 | } | |
6cdb1497 | 281 | BLOBLIST_TEST(bloblist_test_cmd_info, UFT_BLOBLIST | UTF_CONSOLE); |
4aed2276 SG |
282 | |
283 | /* Test the 'bloblist list' command */ | |
284 | static int bloblist_test_cmd_list(struct unit_test_state *uts) | |
285 | { | |
4aed2276 SG |
286 | struct bloblist_hdr *hdr; |
287 | char *data, *data2; | |
288 | ||
289 | hdr = clear_bloblist(); | |
7d790a80 | 290 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
4aed2276 SG |
291 | data = bloblist_ensure(TEST_TAG, TEST_SIZE); |
292 | data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2); | |
293 | ||
4aed2276 | 294 | run_command("bloblist list", 0); |
f16ec777 | 295 | ut_assert_nextline("Address Size Tag Name"); |
e748e4b7 | 296 | ut_assert_nextline("%08lx %8x fff000 SPL hand-off", |
cdd4e30d | 297 | (ulong)map_to_sysmem(data), TEST_SIZE); |
e748e4b7 | 298 | ut_assert_nextline("%08lx %8x 202 Chrome OS vboot context", |
cdd4e30d | 299 | (ulong)map_to_sysmem(data2), TEST_SIZE2); |
4aed2276 SG |
300 | |
301 | return 0; | |
302 | } | |
6cdb1497 | 303 | BLOBLIST_TEST(bloblist_test_cmd_list, UFT_BLOBLIST | UTF_CONSOLE); |
4aed2276 | 304 | |
751b7c79 SG |
305 | /* Test alignment of bloblist blobs */ |
306 | static int bloblist_test_align(struct unit_test_state *uts) | |
307 | { | |
308 | struct bloblist_hdr *hdr; | |
4c1497e7 SG |
309 | ulong addr; |
310 | char *data; | |
751b7c79 SG |
311 | int i; |
312 | ||
313 | /* At the start there should be no records */ | |
314 | hdr = clear_bloblist(); | |
7d790a80 | 315 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
751b7c79 SG |
316 | ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE)); |
317 | ||
4c1497e7 | 318 | /* Check the default alignment */ |
751b7c79 SG |
319 | for (i = 0; i < 3; i++) { |
320 | int size = i * 3; | |
321 | ulong addr; | |
322 | char *data; | |
323 | int j; | |
324 | ||
4c1497e7 | 325 | data = bloblist_add(i, size, 0); |
751b7c79 SG |
326 | ut_assertnonnull(data); |
327 | addr = map_to_sysmem(data); | |
b6e83826 | 328 | ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN - 1)); |
751b7c79 SG |
329 | |
330 | /* Only the bytes in the blob data should be zeroed */ | |
331 | for (j = 0; j < size; j++) | |
332 | ut_asserteq(0, data[j]); | |
b6e83826 | 333 | for (; j < BLOBLIST_BLOB_ALIGN; j++) |
751b7c79 SG |
334 | ut_asserteq(ERASE_BYTE, data[j]); |
335 | } | |
336 | ||
4c1497e7 SG |
337 | /* Check larger alignment */ |
338 | for (i = 0; i < 3; i++) { | |
1a2e02f9 | 339 | int align = 5 - i; |
4c1497e7 SG |
340 | |
341 | data = bloblist_add(3 + i, i * 4, align); | |
342 | ut_assertnonnull(data); | |
343 | addr = map_to_sysmem(data); | |
344 | ut_asserteq(0, addr & (align - 1)); | |
345 | } | |
346 | ||
347 | /* Check alignment with an bloblist starting on a smaller alignment */ | |
b6e83826 | 348 | hdr = map_sysmem(TEST_ADDR + BLOBLIST_BLOB_ALIGN, TEST_BLOBLIST_SIZE); |
4c1497e7 SG |
349 | memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE); |
350 | memset(hdr, '\0', sizeof(*hdr)); | |
351 | ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE, | |
7d790a80 | 352 | 0, 0)); |
4c1497e7 | 353 | |
1a2e02f9 | 354 | data = bloblist_add(1, 5, BLOBLIST_ALIGN_LOG2 + 1); |
4c1497e7 SG |
355 | ut_assertnonnull(data); |
356 | addr = map_to_sysmem(data); | |
b6e83826 | 357 | ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN * 2 - 1)); |
4c1497e7 | 358 | |
751b7c79 SG |
359 | return 0; |
360 | } | |
6cdb1497 | 361 | BLOBLIST_TEST(bloblist_test_align, UFT_BLOBLIST); |
751b7c79 | 362 | |
9fe06464 SG |
363 | /* Test relocation of a bloblist */ |
364 | static int bloblist_test_reloc(struct unit_test_state *uts) | |
365 | { | |
366 | const uint large_size = TEST_BLOBLIST_SIZE; | |
367 | const uint small_size = 0x20; | |
1ef43f3b | 368 | void *new_ptr; |
9fe06464 SG |
369 | void *blob1, *blob2; |
370 | ulong new_addr; | |
371 | ulong new_size; | |
372 | ||
7d790a80 | 373 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
9fe06464 SG |
374 | |
375 | /* Add one blob and then one that won't fit */ | |
376 | blob1 = bloblist_add(TEST_TAG, small_size, 0); | |
377 | ut_assertnonnull(blob1); | |
378 | blob2 = bloblist_add(TEST_TAG2, large_size, 0); | |
379 | ut_assertnull(blob2); | |
380 | ||
381 | /* Relocate the bloblist somewhere else, a bit larger */ | |
382 | new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE; | |
383 | new_size = TEST_BLOBLIST_SIZE + 0x100; | |
384 | new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE); | |
1ef43f3b | 385 | ut_assertok(bloblist_reloc(new_ptr, new_size)); |
9fe06464 SG |
386 | |
387 | /* Check the old blob is there and that we can now add the bigger one */ | |
388 | ut_assertnonnull(bloblist_find(TEST_TAG, small_size)); | |
389 | ut_assertnull(bloblist_find(TEST_TAG2, small_size)); | |
390 | blob2 = bloblist_add(TEST_TAG2, large_size, 0); | |
391 | ut_assertnonnull(blob2); | |
392 | ||
393 | return 0; | |
394 | } | |
6cdb1497 | 395 | BLOBLIST_TEST(bloblist_test_reloc, UFT_BLOBLIST); |
9fe06464 | 396 | |
1fe59375 SG |
397 | /* Test expansion of a blob */ |
398 | static int bloblist_test_grow(struct unit_test_state *uts) | |
399 | { | |
400 | const uint small_size = 0x20; | |
401 | void *blob1, *blob2, *blob1_new; | |
402 | struct bloblist_hdr *hdr; | |
403 | void *ptr; | |
404 | ||
405 | ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); | |
406 | hdr = ptr; | |
407 | memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE); | |
408 | ||
409 | /* Create two blobs */ | |
7d790a80 | 410 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
1fe59375 SG |
411 | blob1 = bloblist_add(TEST_TAG, small_size, 0); |
412 | ut_assertnonnull(blob1); | |
413 | ut_assertok(check_zero(blob1, small_size)); | |
414 | strcpy(blob1, test1_str); | |
415 | ||
416 | blob2 = bloblist_add(TEST_TAG2, small_size, 0); | |
417 | ut_assertnonnull(blob2); | |
418 | strcpy(blob2, test2_str); | |
419 | ||
420 | ut_asserteq(sizeof(struct bloblist_hdr) + | |
421 | sizeof(struct bloblist_rec) * 2 + small_size * 2, | |
b86b2d94 | 422 | hdr->used_size); |
1fe59375 SG |
423 | |
424 | /* Resize the first one */ | |
425 | ut_assertok(bloblist_resize(TEST_TAG, small_size + 4)); | |
426 | ||
427 | /* The first one should not have moved, just got larger */ | |
428 | blob1_new = bloblist_find(TEST_TAG, small_size + 4); | |
429 | ut_asserteq_ptr(blob1, blob1_new); | |
430 | ||
431 | /* The new space should be zeroed */ | |
432 | ut_assertok(check_zero(blob1 + small_size, 4)); | |
433 | ||
434 | /* The second one should have moved */ | |
435 | blob2 = bloblist_find(TEST_TAG2, small_size); | |
436 | ut_assertnonnull(blob2); | |
437 | ut_asserteq_str(test2_str, blob2); | |
438 | ||
439 | /* The header should have more bytes in use */ | |
440 | hdr = ptr; | |
441 | ut_asserteq(sizeof(struct bloblist_hdr) + | |
442 | sizeof(struct bloblist_rec) * 2 + small_size * 2 + | |
b6e83826 | 443 | BLOBLIST_BLOB_ALIGN, |
b86b2d94 | 444 | hdr->used_size); |
1fe59375 SG |
445 | |
446 | return 0; | |
447 | } | |
6cdb1497 | 448 | BLOBLIST_TEST(bloblist_test_grow, UFT_BLOBLIST); |
1fe59375 SG |
449 | |
450 | /* Test shrinking of a blob */ | |
451 | static int bloblist_test_shrink(struct unit_test_state *uts) | |
452 | { | |
453 | const uint small_size = 0x20; | |
454 | void *blob1, *blob2, *blob1_new; | |
455 | struct bloblist_hdr *hdr; | |
456 | int new_size; | |
457 | void *ptr; | |
458 | ||
459 | ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); | |
460 | ||
461 | /* Create two blobs */ | |
7d790a80 | 462 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
1fe59375 SG |
463 | blob1 = bloblist_add(TEST_TAG, small_size, 0); |
464 | ut_assertnonnull(blob1); | |
465 | strcpy(blob1, test1_str); | |
466 | ||
467 | blob2 = bloblist_add(TEST_TAG2, small_size, 0); | |
468 | ut_assertnonnull(blob2); | |
469 | strcpy(blob2, test2_str); | |
470 | ||
471 | hdr = ptr; | |
472 | ut_asserteq(sizeof(struct bloblist_hdr) + | |
473 | sizeof(struct bloblist_rec) * 2 + small_size * 2, | |
b86b2d94 | 474 | hdr->used_size); |
1fe59375 SG |
475 | |
476 | /* Resize the first one */ | |
477 | new_size = small_size - BLOBLIST_ALIGN - 4; | |
478 | ut_assertok(bloblist_resize(TEST_TAG, new_size)); | |
479 | ||
480 | /* The first one should not have moved, just got smaller */ | |
481 | blob1_new = bloblist_find(TEST_TAG, new_size); | |
482 | ut_asserteq_ptr(blob1, blob1_new); | |
483 | ||
484 | /* The second one should have moved */ | |
485 | blob2 = bloblist_find(TEST_TAG2, small_size); | |
486 | ut_assertnonnull(blob2); | |
487 | ut_asserteq_str(test2_str, blob2); | |
488 | ||
489 | /* The header should have fewer bytes in use */ | |
490 | hdr = ptr; | |
491 | ut_asserteq(sizeof(struct bloblist_hdr) + | |
492 | sizeof(struct bloblist_rec) * 2 + small_size * 2 - | |
493 | BLOBLIST_ALIGN, | |
b86b2d94 | 494 | hdr->used_size); |
1fe59375 SG |
495 | |
496 | return 0; | |
497 | } | |
6cdb1497 | 498 | BLOBLIST_TEST(bloblist_test_shrink, UFT_BLOBLIST); |
1fe59375 SG |
499 | |
500 | /* Test failing to adjust a blob size */ | |
501 | static int bloblist_test_resize_fail(struct unit_test_state *uts) | |
502 | { | |
503 | const uint small_size = 0x20; | |
504 | struct bloblist_hdr *hdr; | |
505 | void *blob1, *blob2; | |
506 | int new_size; | |
507 | void *ptr; | |
508 | ||
509 | ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); | |
510 | ||
511 | /* Create two blobs */ | |
7d790a80 | 512 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
1fe59375 SG |
513 | blob1 = bloblist_add(TEST_TAG, small_size, 0); |
514 | ut_assertnonnull(blob1); | |
515 | ||
516 | blob2 = bloblist_add(TEST_TAG2, small_size, 0); | |
517 | ut_assertnonnull(blob2); | |
518 | ||
519 | hdr = ptr; | |
520 | ut_asserteq(sizeof(struct bloblist_hdr) + | |
521 | sizeof(struct bloblist_rec) * 2 + small_size * 2, | |
b86b2d94 | 522 | hdr->used_size); |
1fe59375 SG |
523 | |
524 | /* Resize the first one, to check the boundary conditions */ | |
525 | ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1)); | |
526 | ||
b86b2d94 | 527 | new_size = small_size + (hdr->total_size - hdr->used_size); |
1fe59375 SG |
528 | ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1)); |
529 | ut_assertok(bloblist_resize(TEST_TAG, new_size)); | |
530 | ||
531 | return 0; | |
532 | } | |
6cdb1497 | 533 | BLOBLIST_TEST(bloblist_test_resize_fail, UFT_BLOBLIST); |
1fe59375 SG |
534 | |
535 | /* Test expanding the last blob in a bloblist */ | |
536 | static int bloblist_test_resize_last(struct unit_test_state *uts) | |
537 | { | |
538 | const uint small_size = 0x20; | |
539 | struct bloblist_hdr *hdr; | |
540 | void *blob1, *blob2, *blob2_new; | |
541 | int alloced_val; | |
542 | void *ptr; | |
543 | ||
544 | ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); | |
545 | memset(ptr, ERASE_BYTE, TEST_BLOBLIST_SIZE); | |
546 | hdr = ptr; | |
547 | ||
548 | /* Create two blobs */ | |
7d790a80 | 549 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
1fe59375 SG |
550 | blob1 = bloblist_add(TEST_TAG, small_size, 0); |
551 | ut_assertnonnull(blob1); | |
552 | ||
553 | blob2 = bloblist_add(TEST_TAG2, small_size, 0); | |
554 | ut_assertnonnull(blob2); | |
555 | ||
556 | /* Check the byte after the last blob */ | |
557 | alloced_val = sizeof(struct bloblist_hdr) + | |
558 | sizeof(struct bloblist_rec) * 2 + small_size * 2; | |
b86b2d94 | 559 | ut_asserteq(alloced_val, hdr->used_size); |
1fe59375 | 560 | ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size); |
b86b2d94 | 561 | ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size)); |
1fe59375 SG |
562 | |
563 | /* Resize the second one, checking nothing changes */ | |
564 | ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4)); | |
565 | ||
566 | blob2_new = bloblist_find(TEST_TAG2, small_size + 4); | |
567 | ut_asserteq_ptr(blob2, blob2_new); | |
568 | ||
569 | /* | |
570 | * the new blob should encompass the byte we checked now, so it should | |
571 | * be zeroed. This zeroing should affect only the four new bytes added | |
572 | * to the blob. | |
573 | */ | |
574 | ut_asserteq(0, *((u8 *)hdr + alloced_val)); | |
575 | ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4)); | |
576 | ||
577 | /* Check that the new top of the allocated blobs has not been touched */ | |
b6e83826 | 578 | alloced_val += BLOBLIST_BLOB_ALIGN; |
b86b2d94 SG |
579 | ut_asserteq(alloced_val, hdr->used_size); |
580 | ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size)); | |
1fe59375 SG |
581 | |
582 | return 0; | |
583 | } | |
6cdb1497 | 584 | BLOBLIST_TEST(bloblist_test_resize_last, UFT_BLOBLIST); |
1fe59375 | 585 | |
1f618d52 SG |
586 | /* Check a completely full bloblist */ |
587 | static int bloblist_test_blob_maxsize(struct unit_test_state *uts) | |
588 | { | |
589 | void *ptr; | |
590 | int size; | |
591 | ||
592 | /* At the start there should be no records */ | |
593 | clear_bloblist(); | |
7d790a80 | 594 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
1f618d52 SG |
595 | |
596 | /* Add a blob that takes up all space */ | |
597 | size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) - | |
598 | sizeof(struct bloblist_rec); | |
599 | ptr = bloblist_add(TEST_TAG, size, 0); | |
600 | ut_assertnonnull(ptr); | |
601 | ||
602 | ptr = bloblist_add(TEST_TAG, size + 1, 0); | |
603 | ut_assertnull(ptr); | |
604 | ||
605 | return 0; | |
606 | } | |
6cdb1497 | 607 | BLOBLIST_TEST(bloblist_test_blob_maxsize, UFT_BLOBLIST); |
1f618d52 | 608 | |
09140113 SG |
609 | int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc, |
610 | char *const argv[]) | |
919e7a8f | 611 | { |
a7a98755 SG |
612 | struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test); |
613 | const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test); | |
919e7a8f | 614 | |
4ad4edfe PR |
615 | return cmd_ut_category("bloblist", "bloblist_test_", |
616 | tests, n_ents, argc, argv); | |
919e7a8f | 617 | } |