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