xref: /openbmc/u-boot/test/bloblist.c (revision f3275aa4)
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 <test/suites.h>
11 #include <test/test.h>
12 #include <test/ut.h>
13 
14 DECLARE_GLOBAL_DATA_PTR;
15 
16 /* Declare a new compression test */
17 #define BLOBLIST_TEST(_name, _flags) \
18 		UNIT_TEST(_name, _flags, bloblist_test)
19 
20 enum {
21 	TEST_TAG		= 1,
22 	TEST_TAG2		= 2,
23 	TEST_TAG_MISSING	= 3,
24 
25 	TEST_SIZE		= 10,
26 	TEST_SIZE2		= 20,
27 
28 	TEST_ADDR		= CONFIG_BLOBLIST_ADDR,
29 	TEST_BLOBLIST_SIZE	= 0x100,
30 };
31 
32 static struct bloblist_hdr *clear_bloblist(void)
33 {
34 	struct bloblist_hdr *hdr;
35 
36 	/* Clear out any existing bloblist so we have a clean slate */
37 	hdr = map_sysmem(CONFIG_BLOBLIST_ADDR, TEST_BLOBLIST_SIZE);
38 	memset(hdr, '\0', TEST_BLOBLIST_SIZE);
39 
40 	return hdr;
41 }
42 
43 static int bloblist_test_init(struct unit_test_state *uts)
44 {
45 	struct bloblist_hdr *hdr;
46 
47 	hdr = clear_bloblist();
48 	ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
49 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
50 	hdr->version++;
51 	ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
52 						     TEST_BLOBLIST_SIZE));
53 
54 	ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0x10, 0));
55 	ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0));
56 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
57 
58 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
59 	ut_assertok(bloblist_finish());
60 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
61 	hdr->flags++;
62 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
63 
64 	return 1;
65 }
66 BLOBLIST_TEST(bloblist_test_init, 0);
67 
68 static int bloblist_test_blob(struct unit_test_state *uts)
69 {
70 	struct bloblist_hdr *hdr;
71 	struct bloblist_rec *rec, *rec2;
72 	char *data;
73 
74 	/* At the start there should be no records */
75 	hdr = clear_bloblist();
76 	ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
77 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
78 
79 	/* Add a record and check that we can find it */
80 	data = bloblist_add(TEST_TAG, TEST_SIZE);
81 	rec = (void *)(hdr + 1);
82 	ut_asserteq_ptr(rec + 1, data);
83 	data = bloblist_find(TEST_TAG, TEST_SIZE);
84 	ut_asserteq_ptr(rec + 1, data);
85 
86 	/* Check the 'ensure' method */
87 	ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
88 	ut_assertnull(bloblist_ensure(TEST_TAG, TEST_SIZE2));
89 	rec2 = (struct bloblist_rec *)(data + ALIGN(TEST_SIZE, BLOBLIST_ALIGN));
90 
91 	/* Check for a non-existent record */
92 	ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
93 	ut_asserteq_ptr(rec2 + 1, bloblist_ensure(TEST_TAG2, TEST_SIZE2));
94 	ut_assertnull(bloblist_find(TEST_TAG_MISSING, 0));
95 
96 	return 0;
97 }
98 BLOBLIST_TEST(bloblist_test_blob, 0);
99 
100 static int bloblist_test_bad_blob(struct unit_test_state *uts)
101 {
102 	struct bloblist_hdr *hdr;
103 	void *data;
104 
105 	hdr = clear_bloblist();
106 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
107 	data = hdr + 1;
108 	data += sizeof(struct bloblist_rec);
109 	ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
110 	ut_asserteq_ptr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
111 
112 	return 0;
113 }
114 BLOBLIST_TEST(bloblist_test_bad_blob, 0);
115 
116 static int bloblist_test_checksum(struct unit_test_state *uts)
117 {
118 	struct bloblist_hdr *hdr;
119 	char *data, *data2;
120 
121 	hdr = clear_bloblist();
122 	ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
123 	ut_assertok(bloblist_finish());
124 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
125 
126 	/*
127 	 * Now change things amd make sure that the checksum notices. We cannot
128 	 * change the size or alloced fields, since that will crash the code.
129 	 * It has to rely on these being correct.
130 	 */
131 	hdr->flags--;
132 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
133 	hdr->flags++;
134 
135 	hdr->size--;
136 	ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
137 	hdr->size++;
138 
139 	hdr->spare++;
140 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
141 	hdr->spare--;
142 
143 	hdr->chksum++;
144 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
145 	hdr->chksum--;
146 
147 	/* Make sure the checksum changes when we add blobs */
148 	data = bloblist_add(TEST_TAG, TEST_SIZE);
149 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
150 
151 	data2 = bloblist_add(TEST_TAG2, TEST_SIZE2);
152 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
153 	ut_assertok(bloblist_finish());
154 
155 	/* It should also change if we change the data */
156 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
157 	*data += 1;
158 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
159 	*data -= 1;
160 
161 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
162 	*data2 += 1;
163 	ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
164 	*data2 -= 1;
165 
166 	/*
167 	 * Changing data outside the range of valid data should not affect
168 	 * the checksum.
169 	 */
170 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
171 	data[TEST_SIZE]++;
172 	data2[TEST_SIZE2]++;
173 	ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
174 
175 	return 0;
176 }
177 
178 BLOBLIST_TEST(bloblist_test_checksum, 0);
179 
180 int do_ut_bloblist(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
181 {
182 	struct unit_test *tests = ll_entry_start(struct unit_test,
183 						 bloblist_test);
184 	const int n_ents = ll_entry_count(struct unit_test, bloblist_test);
185 
186 	return cmd_ut_category("bloblist", tests, n_ents, argc, argv);
187 }
188