]>
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 | } | |
97 | BLOBLIST_TEST(bloblist_test_init, 0); | |
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 | } | |
137 | BLOBLIST_TEST(bloblist_test_blob, 0); | |
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 | } | |
171 | BLOBLIST_TEST(bloblist_test_blob_ensure, 0); | |
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 | } | |
187 | BLOBLIST_TEST(bloblist_test_bad_blob, 0); | |
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 | } | |
919e7a8f SG |
260 | BLOBLIST_TEST(bloblist_test_checksum, 0); |
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 | ||
273 | console_record_reset_enable(); | |
ef7e2649 | 274 | ut_silence_console(uts); |
4aed2276 SG |
275 | console_record_reset(); |
276 | run_command("bloblist info", 0); | |
b86b2d94 SG |
277 | ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr)); |
278 | ut_assert_nextline("total size: 400 1 KiB"); | |
279 | ut_assert_nextline("used size: 50 80 Bytes"); | |
280 | ut_assert_nextline("free: 3b0 944 Bytes"); | |
4aed2276 | 281 | ut_assert_console_end(); |
ef7e2649 | 282 | ut_unsilence_console(uts); |
4aed2276 SG |
283 | |
284 | return 0; | |
285 | } | |
286 | BLOBLIST_TEST(bloblist_test_cmd_info, 0); | |
287 | ||
288 | /* Test the 'bloblist list' command */ | |
289 | static int bloblist_test_cmd_list(struct unit_test_state *uts) | |
290 | { | |
4aed2276 SG |
291 | struct bloblist_hdr *hdr; |
292 | char *data, *data2; | |
293 | ||
294 | hdr = clear_bloblist(); | |
7d790a80 | 295 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
4aed2276 SG |
296 | data = bloblist_ensure(TEST_TAG, TEST_SIZE); |
297 | data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2); | |
298 | ||
299 | console_record_reset_enable(); | |
ef7e2649 | 300 | ut_silence_console(uts); |
4aed2276 SG |
301 | console_record_reset(); |
302 | run_command("bloblist list", 0); | |
f16ec777 | 303 | ut_assert_nextline("Address Size Tag Name"); |
e748e4b7 | 304 | ut_assert_nextline("%08lx %8x fff000 SPL hand-off", |
cdd4e30d | 305 | (ulong)map_to_sysmem(data), TEST_SIZE); |
e748e4b7 | 306 | ut_assert_nextline("%08lx %8x 202 Chrome OS vboot context", |
cdd4e30d | 307 | (ulong)map_to_sysmem(data2), TEST_SIZE2); |
4aed2276 | 308 | ut_assert_console_end(); |
ef7e2649 | 309 | ut_unsilence_console(uts); |
4aed2276 SG |
310 | |
311 | return 0; | |
312 | } | |
313 | BLOBLIST_TEST(bloblist_test_cmd_list, 0); | |
314 | ||
751b7c79 SG |
315 | /* Test alignment of bloblist blobs */ |
316 | static int bloblist_test_align(struct unit_test_state *uts) | |
317 | { | |
318 | struct bloblist_hdr *hdr; | |
4c1497e7 SG |
319 | ulong addr; |
320 | char *data; | |
751b7c79 SG |
321 | int i; |
322 | ||
323 | /* At the start there should be no records */ | |
324 | hdr = clear_bloblist(); | |
7d790a80 | 325 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
751b7c79 SG |
326 | ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE)); |
327 | ||
4c1497e7 | 328 | /* Check the default alignment */ |
751b7c79 SG |
329 | for (i = 0; i < 3; i++) { |
330 | int size = i * 3; | |
331 | ulong addr; | |
332 | char *data; | |
333 | int j; | |
334 | ||
4c1497e7 | 335 | data = bloblist_add(i, size, 0); |
751b7c79 SG |
336 | ut_assertnonnull(data); |
337 | addr = map_to_sysmem(data); | |
b6e83826 | 338 | ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN - 1)); |
751b7c79 SG |
339 | |
340 | /* Only the bytes in the blob data should be zeroed */ | |
341 | for (j = 0; j < size; j++) | |
342 | ut_asserteq(0, data[j]); | |
b6e83826 | 343 | for (; j < BLOBLIST_BLOB_ALIGN; j++) |
751b7c79 SG |
344 | ut_asserteq(ERASE_BYTE, data[j]); |
345 | } | |
346 | ||
4c1497e7 SG |
347 | /* Check larger alignment */ |
348 | for (i = 0; i < 3; i++) { | |
1a2e02f9 | 349 | int align = 5 - i; |
4c1497e7 SG |
350 | |
351 | data = bloblist_add(3 + i, i * 4, align); | |
352 | ut_assertnonnull(data); | |
353 | addr = map_to_sysmem(data); | |
354 | ut_asserteq(0, addr & (align - 1)); | |
355 | } | |
356 | ||
357 | /* Check alignment with an bloblist starting on a smaller alignment */ | |
b6e83826 | 358 | hdr = map_sysmem(TEST_ADDR + BLOBLIST_BLOB_ALIGN, TEST_BLOBLIST_SIZE); |
4c1497e7 SG |
359 | memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE); |
360 | memset(hdr, '\0', sizeof(*hdr)); | |
361 | ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE, | |
7d790a80 | 362 | 0, 0)); |
4c1497e7 | 363 | |
1a2e02f9 | 364 | data = bloblist_add(1, 5, BLOBLIST_ALIGN_LOG2 + 1); |
4c1497e7 SG |
365 | ut_assertnonnull(data); |
366 | addr = map_to_sysmem(data); | |
b6e83826 | 367 | ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN * 2 - 1)); |
4c1497e7 | 368 | |
751b7c79 SG |
369 | return 0; |
370 | } | |
371 | BLOBLIST_TEST(bloblist_test_align, 0); | |
372 | ||
9fe06464 SG |
373 | /* Test relocation of a bloblist */ |
374 | static int bloblist_test_reloc(struct unit_test_state *uts) | |
375 | { | |
376 | const uint large_size = TEST_BLOBLIST_SIZE; | |
377 | const uint small_size = 0x20; | |
1ef43f3b | 378 | void *new_ptr; |
9fe06464 SG |
379 | void *blob1, *blob2; |
380 | ulong new_addr; | |
381 | ulong new_size; | |
382 | ||
7d790a80 | 383 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
9fe06464 SG |
384 | |
385 | /* Add one blob and then one that won't fit */ | |
386 | blob1 = bloblist_add(TEST_TAG, small_size, 0); | |
387 | ut_assertnonnull(blob1); | |
388 | blob2 = bloblist_add(TEST_TAG2, large_size, 0); | |
389 | ut_assertnull(blob2); | |
390 | ||
391 | /* Relocate the bloblist somewhere else, a bit larger */ | |
392 | new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE; | |
393 | new_size = TEST_BLOBLIST_SIZE + 0x100; | |
394 | new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE); | |
1ef43f3b | 395 | ut_assertok(bloblist_reloc(new_ptr, new_size)); |
9fe06464 SG |
396 | |
397 | /* Check the old blob is there and that we can now add the bigger one */ | |
398 | ut_assertnonnull(bloblist_find(TEST_TAG, small_size)); | |
399 | ut_assertnull(bloblist_find(TEST_TAG2, small_size)); | |
400 | blob2 = bloblist_add(TEST_TAG2, large_size, 0); | |
401 | ut_assertnonnull(blob2); | |
402 | ||
403 | return 0; | |
404 | } | |
405 | BLOBLIST_TEST(bloblist_test_reloc, 0); | |
406 | ||
1fe59375 SG |
407 | /* Test expansion of a blob */ |
408 | static int bloblist_test_grow(struct unit_test_state *uts) | |
409 | { | |
410 | const uint small_size = 0x20; | |
411 | void *blob1, *blob2, *blob1_new; | |
412 | struct bloblist_hdr *hdr; | |
413 | void *ptr; | |
414 | ||
415 | ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); | |
416 | hdr = ptr; | |
417 | memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE); | |
418 | ||
419 | /* Create two blobs */ | |
7d790a80 | 420 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
1fe59375 SG |
421 | blob1 = bloblist_add(TEST_TAG, small_size, 0); |
422 | ut_assertnonnull(blob1); | |
423 | ut_assertok(check_zero(blob1, small_size)); | |
424 | strcpy(blob1, test1_str); | |
425 | ||
426 | blob2 = bloblist_add(TEST_TAG2, small_size, 0); | |
427 | ut_assertnonnull(blob2); | |
428 | strcpy(blob2, test2_str); | |
429 | ||
430 | ut_asserteq(sizeof(struct bloblist_hdr) + | |
431 | sizeof(struct bloblist_rec) * 2 + small_size * 2, | |
b86b2d94 | 432 | hdr->used_size); |
1fe59375 SG |
433 | |
434 | /* Resize the first one */ | |
435 | ut_assertok(bloblist_resize(TEST_TAG, small_size + 4)); | |
436 | ||
437 | /* The first one should not have moved, just got larger */ | |
438 | blob1_new = bloblist_find(TEST_TAG, small_size + 4); | |
439 | ut_asserteq_ptr(blob1, blob1_new); | |
440 | ||
441 | /* The new space should be zeroed */ | |
442 | ut_assertok(check_zero(blob1 + small_size, 4)); | |
443 | ||
444 | /* The second one should have moved */ | |
445 | blob2 = bloblist_find(TEST_TAG2, small_size); | |
446 | ut_assertnonnull(blob2); | |
447 | ut_asserteq_str(test2_str, blob2); | |
448 | ||
449 | /* The header should have more bytes in use */ | |
450 | hdr = ptr; | |
451 | ut_asserteq(sizeof(struct bloblist_hdr) + | |
452 | sizeof(struct bloblist_rec) * 2 + small_size * 2 + | |
b6e83826 | 453 | BLOBLIST_BLOB_ALIGN, |
b86b2d94 | 454 | hdr->used_size); |
1fe59375 SG |
455 | |
456 | return 0; | |
457 | } | |
458 | BLOBLIST_TEST(bloblist_test_grow, 0); | |
459 | ||
460 | /* Test shrinking of a blob */ | |
461 | static int bloblist_test_shrink(struct unit_test_state *uts) | |
462 | { | |
463 | const uint small_size = 0x20; | |
464 | void *blob1, *blob2, *blob1_new; | |
465 | struct bloblist_hdr *hdr; | |
466 | int new_size; | |
467 | void *ptr; | |
468 | ||
469 | ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); | |
470 | ||
471 | /* Create two blobs */ | |
7d790a80 | 472 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
1fe59375 SG |
473 | blob1 = bloblist_add(TEST_TAG, small_size, 0); |
474 | ut_assertnonnull(blob1); | |
475 | strcpy(blob1, test1_str); | |
476 | ||
477 | blob2 = bloblist_add(TEST_TAG2, small_size, 0); | |
478 | ut_assertnonnull(blob2); | |
479 | strcpy(blob2, test2_str); | |
480 | ||
481 | hdr = ptr; | |
482 | ut_asserteq(sizeof(struct bloblist_hdr) + | |
483 | sizeof(struct bloblist_rec) * 2 + small_size * 2, | |
b86b2d94 | 484 | hdr->used_size); |
1fe59375 SG |
485 | |
486 | /* Resize the first one */ | |
487 | new_size = small_size - BLOBLIST_ALIGN - 4; | |
488 | ut_assertok(bloblist_resize(TEST_TAG, new_size)); | |
489 | ||
490 | /* The first one should not have moved, just got smaller */ | |
491 | blob1_new = bloblist_find(TEST_TAG, new_size); | |
492 | ut_asserteq_ptr(blob1, blob1_new); | |
493 | ||
494 | /* The second one should have moved */ | |
495 | blob2 = bloblist_find(TEST_TAG2, small_size); | |
496 | ut_assertnonnull(blob2); | |
497 | ut_asserteq_str(test2_str, blob2); | |
498 | ||
499 | /* The header should have fewer bytes in use */ | |
500 | hdr = ptr; | |
501 | ut_asserteq(sizeof(struct bloblist_hdr) + | |
502 | sizeof(struct bloblist_rec) * 2 + small_size * 2 - | |
503 | BLOBLIST_ALIGN, | |
b86b2d94 | 504 | hdr->used_size); |
1fe59375 SG |
505 | |
506 | return 0; | |
507 | } | |
508 | BLOBLIST_TEST(bloblist_test_shrink, 0); | |
509 | ||
510 | /* Test failing to adjust a blob size */ | |
511 | static int bloblist_test_resize_fail(struct unit_test_state *uts) | |
512 | { | |
513 | const uint small_size = 0x20; | |
514 | struct bloblist_hdr *hdr; | |
515 | void *blob1, *blob2; | |
516 | int new_size; | |
517 | void *ptr; | |
518 | ||
519 | ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); | |
520 | ||
521 | /* Create two blobs */ | |
7d790a80 | 522 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
1fe59375 SG |
523 | blob1 = bloblist_add(TEST_TAG, small_size, 0); |
524 | ut_assertnonnull(blob1); | |
525 | ||
526 | blob2 = bloblist_add(TEST_TAG2, small_size, 0); | |
527 | ut_assertnonnull(blob2); | |
528 | ||
529 | hdr = ptr; | |
530 | ut_asserteq(sizeof(struct bloblist_hdr) + | |
531 | sizeof(struct bloblist_rec) * 2 + small_size * 2, | |
b86b2d94 | 532 | hdr->used_size); |
1fe59375 SG |
533 | |
534 | /* Resize the first one, to check the boundary conditions */ | |
535 | ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1)); | |
536 | ||
b86b2d94 | 537 | new_size = small_size + (hdr->total_size - hdr->used_size); |
1fe59375 SG |
538 | ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1)); |
539 | ut_assertok(bloblist_resize(TEST_TAG, new_size)); | |
540 | ||
541 | return 0; | |
542 | } | |
543 | BLOBLIST_TEST(bloblist_test_resize_fail, 0); | |
544 | ||
545 | /* Test expanding the last blob in a bloblist */ | |
546 | static int bloblist_test_resize_last(struct unit_test_state *uts) | |
547 | { | |
548 | const uint small_size = 0x20; | |
549 | struct bloblist_hdr *hdr; | |
550 | void *blob1, *blob2, *blob2_new; | |
551 | int alloced_val; | |
552 | void *ptr; | |
553 | ||
554 | ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); | |
555 | memset(ptr, ERASE_BYTE, TEST_BLOBLIST_SIZE); | |
556 | hdr = ptr; | |
557 | ||
558 | /* Create two blobs */ | |
7d790a80 | 559 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
1fe59375 SG |
560 | blob1 = bloblist_add(TEST_TAG, small_size, 0); |
561 | ut_assertnonnull(blob1); | |
562 | ||
563 | blob2 = bloblist_add(TEST_TAG2, small_size, 0); | |
564 | ut_assertnonnull(blob2); | |
565 | ||
566 | /* Check the byte after the last blob */ | |
567 | alloced_val = sizeof(struct bloblist_hdr) + | |
568 | sizeof(struct bloblist_rec) * 2 + small_size * 2; | |
b86b2d94 | 569 | ut_asserteq(alloced_val, hdr->used_size); |
1fe59375 | 570 | ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size); |
b86b2d94 | 571 | ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size)); |
1fe59375 SG |
572 | |
573 | /* Resize the second one, checking nothing changes */ | |
574 | ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4)); | |
575 | ||
576 | blob2_new = bloblist_find(TEST_TAG2, small_size + 4); | |
577 | ut_asserteq_ptr(blob2, blob2_new); | |
578 | ||
579 | /* | |
580 | * the new blob should encompass the byte we checked now, so it should | |
581 | * be zeroed. This zeroing should affect only the four new bytes added | |
582 | * to the blob. | |
583 | */ | |
584 | ut_asserteq(0, *((u8 *)hdr + alloced_val)); | |
585 | ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4)); | |
586 | ||
587 | /* Check that the new top of the allocated blobs has not been touched */ | |
b6e83826 | 588 | alloced_val += BLOBLIST_BLOB_ALIGN; |
b86b2d94 SG |
589 | ut_asserteq(alloced_val, hdr->used_size); |
590 | ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size)); | |
1fe59375 SG |
591 | |
592 | return 0; | |
593 | } | |
594 | BLOBLIST_TEST(bloblist_test_resize_last, 0); | |
595 | ||
1f618d52 SG |
596 | /* Check a completely full bloblist */ |
597 | static int bloblist_test_blob_maxsize(struct unit_test_state *uts) | |
598 | { | |
599 | void *ptr; | |
600 | int size; | |
601 | ||
602 | /* At the start there should be no records */ | |
603 | clear_bloblist(); | |
7d790a80 | 604 | ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0)); |
1f618d52 SG |
605 | |
606 | /* Add a blob that takes up all space */ | |
607 | size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) - | |
608 | sizeof(struct bloblist_rec); | |
609 | ptr = bloblist_add(TEST_TAG, size, 0); | |
610 | ut_assertnonnull(ptr); | |
611 | ||
612 | ptr = bloblist_add(TEST_TAG, size + 1, 0); | |
613 | ut_assertnull(ptr); | |
614 | ||
615 | return 0; | |
616 | } | |
617 | BLOBLIST_TEST(bloblist_test_blob_maxsize, 0); | |
618 | ||
09140113 SG |
619 | int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc, |
620 | char *const argv[]) | |
919e7a8f | 621 | { |
a7a98755 SG |
622 | struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test); |
623 | const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test); | |
919e7a8f | 624 | |
4ad4edfe PR |
625 | return cmd_ut_category("bloblist", "bloblist_test_", |
626 | tests, n_ents, argc, argv); | |
919e7a8f | 627 | } |