1 // © 2021 Qualcomm Innovation Center, Inc. All rights reserved.
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #if defined(UNIT_TESTS)
6 
7 #include <assert.h>
8 #include <hyptypes.h>
9 
10 #include <bitmap.h>
11 #include <compiler.h>
12 #include <cpulocal.h>
13 #include <gpt.h>
14 #include <log.h>
15 #include <partition_init.h>
16 #include <preempt.h>
17 #include <trace.h>
18 #include <util.h>
19 
20 #include "event_handlers.h"
21 
22 static gpt_t gpt;
23 
24 static gpt_entry_t
test_entry_init(gpt_type_t type,uint64_t value)25 test_entry_init(gpt_type_t type, uint64_t value)
26 {
27 	return (gpt_entry_t){
28 		.type  = type,
29 		.value = { .raw = value },
30 	};
31 }
32 
33 void
gpt_tests_add_offset(gpt_type_t type,gpt_value_t * value,size_t offset)34 gpt_tests_add_offset(gpt_type_t type, gpt_value_t *value, size_t offset)
35 {
36 	value->raw += (type != GPT_TYPE_TEST_C) ? offset : (offset * 2);
37 }
38 
39 bool
gpt_tests_values_equal(gpt_value_t x,gpt_value_t y)40 gpt_tests_values_equal(gpt_value_t x, gpt_value_t y)
41 {
42 	return x.raw == y.raw;
43 }
44 
45 error_t
gpt_tests_callback(gpt_entry_t entry,size_t base,size_t size,gpt_arg_t arg)46 gpt_tests_callback(gpt_entry_t entry, size_t base, size_t size, gpt_arg_t arg)
47 {
48 	LOG(DEBUG, INFO,
49 	    "GPT callback: t {:d}, v {:#x}, [{:#x}, {:#x}], arg {:#x}",
50 	    entry.type, entry.value.raw, base, size, arg.test);
51 
52 	return OK;
53 }
54 
55 void
gpt_handle_tests_init(void)56 gpt_handle_tests_init(void)
57 {
58 	partition_t *partition = partition_get_root();
59 	assert(partition != NULL);
60 
61 	gpt_config_t config = gpt_config_default();
62 	gpt_config_set_max_bits(&config, GPT_MAX_SIZE_BITS);
63 
64 	register_t types = 0U;
65 	bitmap_set(&types, GPT_TYPE_TEST_A);
66 	bitmap_set(&types, GPT_TYPE_TEST_B);
67 	bitmap_set(&types, GPT_TYPE_TEST_C);
68 
69 	error_t err = gpt_init(&gpt, partition, config, types);
70 	assert(err == OK);
71 }
72 
73 bool
gpt_handle_tests_start(void)74 gpt_handle_tests_start(void)
75 {
76 	error_t err;
77 
78 	preempt_disable();
79 
80 	if (cpulocal_get_index() != 0U) {
81 		goto out;
82 	}
83 
84 	assert(gpt_is_empty(&gpt));
85 
86 	size_t	    base, size;
87 	gpt_entry_t e1, e2;
88 
89 	base = 0x80000000U;
90 	size = 0x70000;
91 	e1   = test_entry_init(GPT_TYPE_TEST_A, base);
92 
93 	err = gpt_insert(&gpt, base, size, e1, true);
94 	assert(err == OK);
95 
96 	base = 0x80001000U;
97 	size = 0x4500;
98 	e1   = test_entry_init(GPT_TYPE_TEST_A, base);
99 	e2   = test_entry_init(GPT_TYPE_TEST_A, 0x900000);
100 
101 	err = gpt_update(&gpt, base, size, e1, e2);
102 	assert(err == OK);
103 
104 	base = 0x80020010U;
105 	size = 0x3;
106 	e2   = test_entry_init(GPT_TYPE_TEST_B, base);
107 
108 	err = gpt_insert(&gpt, base, size, e2, false);
109 	assert(err == OK);
110 
111 	base = 0x80040400U;
112 	size = 3;
113 	e1   = test_entry_init(GPT_TYPE_TEST_A, 0x80040400U);
114 	e2   = test_entry_init(GPT_TYPE_TEST_C, 0x400);
115 
116 	err = gpt_update(&gpt, base, size, e1, e2);
117 	assert(err == OK);
118 
119 	base = 0x80055555;
120 	size = 1234;
121 	e1   = test_entry_init(GPT_TYPE_TEST_A, 0x80055555);
122 
123 	err = gpt_remove(&gpt, base, size, e1);
124 	assert(err == OK);
125 
126 	gpt_dump_ranges(&gpt);
127 
128 	base = 0x80000050;
129 	size = 0x20;
130 	e1   = test_entry_init(GPT_TYPE_TEST_A, 0x80000050);
131 
132 	assert(!gpt_is_empty(&gpt));
133 
134 	bool ret = gpt_is_contiguous(&gpt, base, size, e1);
135 	assert(ret);
136 
137 	gpt_lookup_result_t lookup = gpt_lookup(&gpt, 0x8, 1U);
138 	LOG(DEBUG, INFO, "Lookup returned: {:d} {:#x} ({:#x})",
139 	    lookup.entry.type, lookup.entry.value.raw, lookup.size);
140 
141 	lookup = gpt_lookup(&gpt, 0x80040001, 2);
142 	LOG(DEBUG, INFO, "Lookup returned: {:d} {:#x} ({:#x})",
143 	    lookup.entry.type, lookup.entry.value.raw, lookup.size);
144 
145 	lookup = gpt_lookup(&gpt, 0x80050006, 0x20000);
146 	LOG(DEBUG, INFO, "Lookup returned: {:d} {:#x} ({:#x})",
147 	    lookup.entry.type, lookup.entry.value.raw, lookup.size);
148 
149 	gpt_arg_t arg;
150 
151 	base	 = 0x80000001;
152 	size	 = 0x6f000;
153 	arg.test = 0xfeed;
154 
155 	err = gpt_walk(&gpt, base, size, GPT_TYPE_TEST_A, GPT_CALLBACK_TEST,
156 		       arg);
157 	assert(err == OK);
158 
159 	base	 = 0x80040200U;
160 	size	 = 0x800;
161 	arg.test = 0xbeef;
162 
163 	err = gpt_walk(&gpt, base, size, GPT_TYPE_TEST_C, GPT_CALLBACK_TEST,
164 		       arg);
165 	assert(err == OK);
166 
167 	base = 0x100100U;
168 	size = 0x1;
169 	e1   = test_entry_init(GPT_TYPE_TEST_A, base);
170 
171 	err = gpt_insert(&gpt, base, size, e1, false);
172 	assert(err == OK);
173 
174 	base = 0x100300U;
175 	size = 0x1;
176 	e1   = test_entry_init(GPT_TYPE_TEST_A, base);
177 
178 	err = gpt_insert(&gpt, base, size, e1, false);
179 	assert(err == OK);
180 
181 	base = 0x100100U;
182 	size = 0x1;
183 	e1   = test_entry_init(GPT_TYPE_TEST_A, base);
184 
185 	err = gpt_remove(&gpt, base, size, e1);
186 	assert(err == OK);
187 
188 	gpt_dump_ranges(&gpt);
189 
190 	// Partially invalid update.
191 	base = 0x80030000U;
192 	size = 0x50000;
193 	e1   = test_entry_init(GPT_TYPE_TEST_A, base);
194 	e2   = test_entry_init(GPT_TYPE_TEST_B, base);
195 
196 	err = gpt_update(&gpt, base, size, e1, e2);
197 	assert(err != OK);
198 
199 	size = 0x10;
200 
201 	err = gpt_update(&gpt, base, size, e1, e2);
202 	assert(err == OK);
203 
204 	gpt_dump_ranges(&gpt);
205 
206 	// Attempt to insert invalid type.
207 	e1 = test_entry_init(GPT_TYPE_LEVEL, 0x213123123123);
208 
209 	err = gpt_insert(&gpt, 0x919100123f23, 0x1012301230, e1, false);
210 	assert(err != OK);
211 
212 	base = 0x70000000U;
213 	size = 0x20000000U;
214 	e1   = test_entry_init(GPT_TYPE_TEST_B, 0x50000000U);
215 
216 	err = gpt_insert(&gpt, base, size, e1, false);
217 	assert(err == OK);
218 
219 	gpt_dump_levels(&gpt);
220 
221 	err = gpt_clear(&gpt, 0U, 0x100000000U);
222 	assert(err == OK);
223 
224 	assert(gpt_is_empty(&gpt));
225 
226 	base = 0U;
227 	size = 1U;
228 	e1   = test_entry_init(GPT_TYPE_TEST_A, base);
229 
230 	err = gpt_insert(&gpt, base, size, e1, false);
231 	assert(err == OK);
232 
233 	for (index_t i = 0U; i < GPT_MAX_SIZE_BITS; i += GPT_LEVEL_BITS) {
234 		base = util_bit(i);
235 		size = 1U;
236 		e1   = test_entry_init(GPT_TYPE_TEST_A, base);
237 
238 		err = gpt_insert(&gpt, base, size, e1, false);
239 		assert(err == OK);
240 	}
241 
242 	gpt_dump_ranges(&gpt);
243 
244 	for (index_t i = 0U; i < GPT_MAX_SIZE_BITS; i += GPT_LEVEL_BITS) {
245 		base = util_bit(i);
246 		size = 1U;
247 		e1   = test_entry_init(GPT_TYPE_TEST_A, base);
248 
249 		err = gpt_remove(&gpt, base, size, e1);
250 		assert(err == OK);
251 	}
252 
253 	gpt_clear_all(&gpt);
254 
255 	for (index_t i = 0U; i < GPT_LEVEL_ENTRIES; i++) {
256 		base = 0xffff00000000 + (i << 8);
257 		size = 1U << 8;
258 		e1   = test_entry_init(GPT_TYPE_TEST_A, base);
259 
260 		err = gpt_insert(&gpt, base, size, e1, true);
261 		assert(err == OK);
262 	}
263 
264 	gpt_dump_levels(&gpt);
265 
266 	e1 = test_entry_init(GPT_TYPE_TEST_A, 1U);
267 
268 	err = gpt_insert(&gpt, 0x1000, 1U, e1, false);
269 	assert(err == OK);
270 
271 	err = gpt_insert(&gpt, 0x1002, 1U, e1, false);
272 	assert(err == OK);
273 
274 	err = gpt_insert(&gpt, 0x1002, 1U, e1, false);
275 	assert(err == OK);
276 
277 	e2 = test_entry_init(GPT_TYPE_TEST_B, 1U);
278 
279 	err = gpt_insert(&gpt, 0x1010, 1U, e2, false);
280 	assert(err == OK);
281 
282 	gpt_dump_levels(&gpt);
283 
284 	e1 = test_entry_init(GPT_TYPE_TEST_C, 2U);
285 
286 	err = gpt_insert(&gpt, 0U, 0x2000, e1, true);
287 	assert(err != OK);
288 
289 	gpt_clear(&gpt, 1U, 0x10000U);
290 
291 	gpt_dump_levels(&gpt);
292 
293 	gpt_clear_all(&gpt);
294 
295 	e1 = test_entry_init(GPT_TYPE_TEST_A, 0xdeadbeefbeadfeedU);
296 
297 	// Base and size cause overflow
298 	err = gpt_insert(&gpt, 0xffffffffffffff00, 0x0, e1, true);
299 	assert(err == ERROR_ARGUMENT_INVALID);
300 
301 	err = gpt_insert(&gpt, 0xffffffffffffff00, 0x100, e1, true);
302 	assert(err == ERROR_ARGUMENT_SIZE);
303 
304 	err = gpt_insert(&gpt, 0xffffffffffffffff, 0x33333333, e1, true);
305 	assert(err == ERROR_ARGUMENT_INVALID);
306 
307 	// Larger than max size supported
308 	err = gpt_insert(&gpt, util_bit(GPT_MAX_SIZE_BITS), 0x1, e1, true);
309 	assert(err == ERROR_ARGUMENT_SIZE);
310 
311 	err = gpt_insert(&gpt, util_bit(GPT_MAX_SIZE_BITS + 1), 0x33333333, e1,
312 			 true);
313 	assert(err == ERROR_ARGUMENT_SIZE);
314 
315 	err = gpt_insert(&gpt, util_bit(GPT_MAX_SIZE_BITS) - 1, 0x1, e1, true);
316 	assert(err == OK);
317 
318 	err = gpt_insert(&gpt, util_bit(GPT_MAX_SIZE_BITS) - 1, 0x1, e1, true);
319 	assert(err == ERROR_BUSY);
320 
321 	err = gpt_clear(&gpt, util_bit(GPT_MAX_SIZE_BITS) - 1, 0x1U);
322 	assert(err == OK);
323 
324 	err = gpt_insert(&gpt, util_bit(GPT_MAX_SIZE_BITS) - 2, 0x2, e1, true);
325 	assert(err == OK);
326 
327 	err = gpt_insert(&gpt, util_bit(GPT_MAX_SIZE_BITS) - 1, 0x1, e1, true);
328 	assert(err == ERROR_BUSY);
329 
330 	err = gpt_walk(&gpt, 0, util_bit(GPT_MAX_SIZE_BITS), GPT_TYPE_TEST_A,
331 		       GPT_CALLBACK_TEST, arg);
332 	assert(err == OK);
333 
334 	err = gpt_clear(&gpt, util_bit(GPT_MAX_SIZE_BITS) - 1, 0x1U);
335 	assert(err == OK);
336 
337 	err = gpt_walk(&gpt, 0, util_bit(GPT_MAX_SIZE_BITS), GPT_TYPE_TEST_A,
338 		       GPT_CALLBACK_TEST, arg);
339 	assert(err == OK);
340 
341 	err = gpt_insert(&gpt, util_bit(GPT_MAX_SIZE_BITS) - 2, 0x1, e1, true);
342 	assert(err == ERROR_BUSY);
343 
344 	e2 = e1;
345 	e2.value.raw += 1;
346 	err = gpt_insert(&gpt, util_bit(GPT_MAX_SIZE_BITS) - 1, 0x1, e2, true);
347 	assert(err == OK);
348 
349 	err = gpt_walk(&gpt, 0, util_bit(GPT_MAX_SIZE_BITS), GPT_TYPE_TEST_A,
350 		       GPT_CALLBACK_TEST, arg);
351 	assert(err == OK);
352 
353 	err = gpt_insert(&gpt, 0x4000000000000, 0x33333333, e1, true);
354 	assert(err == OK);
355 
356 	e1 = test_entry_init(GPT_TYPE_TEST_A, 0x3333444455550000U);
357 
358 	err = gpt_insert(&gpt, 0x234000000000, 0x679823213, e1, true);
359 	assert(err == OK);
360 
361 	// Attempt to insert range with overlap at end
362 	err = gpt_insert(&gpt, 0x233cdf123000, 0x82681e3f2, e1, true);
363 	assert(err != OK);
364 
365 	e1 = test_entry_init(GPT_TYPE_TEST_A, 0x3333444455556666U);
366 	e2 = test_entry_init(GPT_TYPE_TEST_B, 0x777788889999);
367 
368 	// Attempt to update range that doesn't match at the end
369 	err = gpt_update(&gpt, 0x234000006666, 0x73f8c532ab, e1, e2);
370 	assert(err != OK);
371 
372 	err = gpt_update(&gpt, 0x234000006666, 0x123e34, e1, e2);
373 	assert(err == OK);
374 
375 	gpt_dump_ranges(&gpt);
376 
377 	base = 0x7ab2348e293;
378 	size = 0x123809193;
379 
380 	e1 = test_entry_init(GPT_TYPE_TEST_A, 0x183741ea175);
381 
382 	err = gpt_insert(&gpt, 0U, base, e1, false);
383 	assert(err == OK);
384 
385 	e1.value.raw += base + size;
386 
387 	err = gpt_insert(&gpt, base + size, GPT_MAX_SIZE - base - size, e1,
388 			 false);
389 	assert(err == OK);
390 
391 	e1.value.raw -= size;
392 
393 	err = gpt_insert(&gpt, base, size, e1, false);
394 	assert(err == OK);
395 
396 	e1.value.raw -= base;
397 
398 	// GPT should now have a single contiguous entry
399 	assert(gpt_is_contiguous(&gpt, 0U, GPT_MAX_SIZE, e1));
400 
401 	gpt_dump_ranges(&gpt);
402 
403 	gpt_destroy(&gpt);
404 out:
405 	preempt_enable();
406 
407 	return false;
408 }
409 
410 #else
411 
412 extern char unused;
413 
414 #endif
415