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