1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Tests for ACPI code generation via a device-property table
4  *
5  * Copyright 2019 Google LLC
6  * Written by Simon Glass <sjg@chromium.org>
7  */
8 
9 #include <dm.h>
10 #include <u-boot/uuid.h>
11 #include <acpi/acpigen.h>
12 #include <acpi/acpi_dp.h>
13 #include <asm/unaligned.h>
14 #include <dm/acpi.h>
15 #include <dm/test.h>
16 #include <test/ut.h>
17 #include "acpi.h"
18 
19 /* Maximum size of the ACPI context needed for most tests */
20 #define ACPI_CONTEXT_SIZE	500
21 
22 #define TEST_INT8	0x7d
23 #define TEST_INT16	0x2345
24 #define TEST_INT32	0x12345678
25 #define TEST_INT64	0x4567890123456
26 #define TEST_STR	"testing acpi strings"
27 #define TEST_REF	"\\SB.I2C0.TPM2"
28 #define EXPECT_REF	"SB__I2C0TPM2"
29 
alloc_context(struct acpi_ctx ** ctxp)30 static int alloc_context(struct acpi_ctx **ctxp)
31 {
32 	return acpi_test_alloc_context_size(ctxp, ACPI_CONTEXT_SIZE);
33 
34 	return 0;
35 }
36 
free_context(struct acpi_ctx ** ctxp)37 static void free_context(struct acpi_ctx **ctxp)
38 {
39 	free(*ctxp);
40 	*ctxp = NULL;
41 }
42 
43 /* Test emitting an empty table */
dm_test_acpi_dp_new_table(struct unit_test_state * uts)44 static int dm_test_acpi_dp_new_table(struct unit_test_state *uts)
45 {
46 	struct acpi_ctx *ctx;
47 	struct acpi_dp *dp;
48 	u8 *ptr;
49 
50 	ut_assertok(alloc_context(&ctx));
51 
52 	dp = acpi_dp_new_table("FRED");
53 	ut_assertnonnull(dp);
54 
55 	ptr = acpigen_get_current(ctx);
56 	ut_assertok(acpi_dp_write(ctx, dp));
57 	ut_asserteq(10, acpigen_get_current(ctx) - ptr);
58 	ut_asserteq(NAME_OP, *(u8 *)ptr);
59 	ut_asserteq_strn("FRED", (char *)ptr + 1);
60 	ut_asserteq(PACKAGE_OP, ptr[5]);
61 	ut_asserteq(4, acpi_test_get_length(ptr + 6));
62 	ut_asserteq(0, ptr[9]);
63 
64 	free_context(&ctx);
65 
66 	return 0;
67 }
68 DM_TEST(dm_test_acpi_dp_new_table, 0);
69 
70 /* Test emitting an integer */
dm_test_acpi_dp_int(struct unit_test_state * uts)71 static int dm_test_acpi_dp_int(struct unit_test_state *uts)
72 {
73 	struct acpi_ctx *ctx;
74 	char uuid[UUID_STR_LEN + 1];
75 	struct acpi_dp *dp;
76 	u8 *ptr;
77 
78 	ut_assertok(alloc_context(&ctx));
79 
80 	dp = acpi_dp_new_table("FRED");
81 	ut_assertnonnull(dp);
82 	ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT32));
83 
84 	ptr = acpigen_get_current(ctx);
85 	ut_assertok(acpi_dp_write(ctx, dp));
86 	ut_asserteq(54, acpigen_get_current(ctx) - ptr);
87 	ut_asserteq(NAME_OP, *(u8 *)ptr);
88 	ut_asserteq_strn("FRED", (char *)ptr + 1);
89 	ut_asserteq(PACKAGE_OP, ptr[5]);
90 	ut_asserteq(48, acpi_test_get_length(ptr + 6));
91 	ut_asserteq(2, ptr[9]);
92 
93 	/* UUID */
94 	ut_asserteq(BUFFER_OP, ptr[10]);
95 	ut_asserteq(22, acpi_test_get_length(ptr + 11));
96 	ut_asserteq(WORD_PREFIX, ptr[14]);
97 	ut_asserteq(16, get_unaligned((u16 *)(ptr + 15)));
98 	uuid_bin_to_str(ptr + 17, uuid, 1);
99 	ut_asserteq_str(ACPI_DP_UUID, uuid);
100 
101 	/* Container package */
102 	ut_asserteq(PACKAGE_OP, ptr[33]);
103 	ut_asserteq(20, acpi_test_get_length(ptr + 34));
104 	ut_asserteq(1, ptr[37]);
105 
106 	/* Package with name and (integer) value */
107 	ut_asserteq(PACKAGE_OP, ptr[38]);
108 	ut_asserteq(15, acpi_test_get_length(ptr + 39));
109 	ut_asserteq(2, ptr[42]);
110 	ut_asserteq(STRING_PREFIX, ptr[43]);
111 	ut_asserteq_str("MARY", (char *)ptr + 44);
112 
113 	ut_asserteq(DWORD_PREFIX, ptr[49]);
114 	ut_asserteq(TEST_INT32, get_unaligned((u32 *)(ptr + 50)));
115 
116 	free_context(&ctx);
117 
118 	return 0;
119 }
120 DM_TEST(dm_test_acpi_dp_int, 0);
121 
122 /* Test emitting a 64-bit integer */
dm_test_acpi_dp_int64(struct unit_test_state * uts)123 static int dm_test_acpi_dp_int64(struct unit_test_state *uts)
124 {
125 	struct acpi_ctx *ctx;
126 	struct acpi_dp *dp;
127 	u8 *ptr;
128 
129 	ut_assertok(alloc_context(&ctx));
130 
131 	dp = acpi_dp_new_table("FRED");
132 	ut_assertnonnull(dp);
133 	ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT64));
134 
135 	ptr = acpigen_get_current(ctx);
136 	ut_assertok(acpi_dp_write(ctx, dp));
137 	ut_asserteq(58, acpigen_get_current(ctx) - ptr);
138 
139 	ut_asserteq(QWORD_PREFIX, ptr[49]);
140 	ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 50)));
141 
142 	free_context(&ctx);
143 
144 	return 0;
145 }
146 DM_TEST(dm_test_acpi_dp_int64, 0);
147 
148 /* Test emitting a 16-bit integer */
dm_test_acpi_dp_int16(struct unit_test_state * uts)149 static int dm_test_acpi_dp_int16(struct unit_test_state *uts)
150 {
151 	struct acpi_ctx *ctx;
152 	struct acpi_dp *dp;
153 	u8 *ptr;
154 
155 	ut_assertok(alloc_context(&ctx));
156 
157 	dp = acpi_dp_new_table("FRED");
158 	ut_assertnonnull(dp);
159 	ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT16));
160 
161 	ptr = acpigen_get_current(ctx);
162 	ut_assertok(acpi_dp_write(ctx, dp));
163 	ut_asserteq(52, acpigen_get_current(ctx) - ptr);
164 
165 	ut_asserteq(WORD_PREFIX, ptr[49]);
166 	ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 50)));
167 
168 	free_context(&ctx);
169 
170 	return 0;
171 }
172 DM_TEST(dm_test_acpi_dp_int16, 0);
173 
174 /* Test emitting a 8-bit integer */
dm_test_acpi_dp_int8(struct unit_test_state * uts)175 static int dm_test_acpi_dp_int8(struct unit_test_state *uts)
176 {
177 	struct acpi_ctx *ctx;
178 	struct acpi_dp *dp;
179 	u8 *ptr;
180 
181 	ut_assertok(alloc_context(&ctx));
182 
183 	dp = acpi_dp_new_table("FRED");
184 	ut_assertnonnull(dp);
185 	ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT8));
186 
187 	ptr = acpigen_get_current(ctx);
188 	ut_assertok(acpi_dp_write(ctx, dp));
189 	ut_asserteq(51, acpigen_get_current(ctx) - ptr);
190 
191 	ut_asserteq(BYTE_PREFIX, ptr[49]);
192 	ut_asserteq(TEST_INT8, ptr[50]);
193 
194 	free_context(&ctx);
195 
196 	return 0;
197 }
198 DM_TEST(dm_test_acpi_dp_int8, 0);
199 
200 /* Test emitting multiple values */
dm_test_acpi_dp_multiple(struct unit_test_state * uts)201 static int dm_test_acpi_dp_multiple(struct unit_test_state *uts)
202 {
203 	struct acpi_ctx *ctx;
204 	struct acpi_dp *dp;
205 	u8 *ptr;
206 
207 	ut_assertok(alloc_context(&ctx));
208 
209 	dp = acpi_dp_new_table("FRED");
210 	ut_assertnonnull(dp);
211 	ut_assertnonnull(acpi_dp_add_integer(dp, "int16", TEST_INT16));
212 	ut_assertnonnull(acpi_dp_add_string(dp, "str", TEST_STR));
213 	ut_assertnonnull(acpi_dp_add_reference(dp, "ref", TEST_REF));
214 
215 	ptr = acpigen_get_current(ctx);
216 	ut_assertok(acpi_dp_write(ctx, dp));
217 	ut_asserteq(110, acpigen_get_current(ctx) - ptr);
218 
219 	ut_asserteq(WORD_PREFIX, ptr[0x32]);
220 	ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 0x33)));
221 	ut_asserteq(STRING_PREFIX, ptr[0x3f]);
222 	ut_asserteq_str(TEST_STR, (char *)ptr + 0x40);
223 	ut_asserteq(ROOT_PREFIX, ptr[0x5f]);
224 	ut_asserteq(MULTI_NAME_PREFIX, ptr[0x60]);
225 	ut_asserteq(3, ptr[0x61]);
226 	ut_asserteq_strn(EXPECT_REF, (char *)ptr + 0x62);
227 
228 	free_context(&ctx);
229 
230 	return 0;
231 }
232 DM_TEST(dm_test_acpi_dp_multiple, 0);
233 
234 /* Test emitting an array */
dm_test_acpi_dp_array(struct unit_test_state * uts)235 static int dm_test_acpi_dp_array(struct unit_test_state *uts)
236 {
237 	struct acpi_ctx *ctx;
238 	struct acpi_dp *dp;
239 	u64 speed[4];
240 	u8 *ptr;
241 
242 	ut_assertok(alloc_context(&ctx));
243 
244 	dp = acpi_dp_new_table("FRED");
245 	ut_assertnonnull(dp);
246 	speed[0] = TEST_INT8;
247 	speed[1] = TEST_INT16;
248 	speed[2] = TEST_INT32;
249 	speed[3] = TEST_INT64;
250 	ut_assertnonnull(acpi_dp_add_integer_array(dp, "speeds", speed,
251 						   ARRAY_SIZE(speed)));
252 
253 	ptr = acpigen_get_current(ctx);
254 	ut_assertok(acpi_dp_write(ctx, dp));
255 	ut_asserteq(75, acpigen_get_current(ctx) - ptr);
256 
257 	ut_asserteq(BYTE_PREFIX, ptr[0x38]);
258 	ut_asserteq(TEST_INT8, ptr[0x39]);
259 
260 	ut_asserteq(WORD_PREFIX, ptr[0x3a]);
261 	ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 0x3b)));
262 
263 	ut_asserteq(DWORD_PREFIX, ptr[0x3d]);
264 	ut_asserteq(TEST_INT32, get_unaligned((u32 *)(ptr + 0x3e)));
265 
266 	ut_asserteq(QWORD_PREFIX, ptr[0x42]);
267 	ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 0x43)));
268 
269 	free_context(&ctx);
270 
271 	return 0;
272 }
273 DM_TEST(dm_test_acpi_dp_array, 0);
274 
275 /* Test emitting a child */
dm_test_acpi_dp_child(struct unit_test_state * uts)276 static int dm_test_acpi_dp_child(struct unit_test_state *uts)
277 {
278 	struct acpi_ctx *ctx;
279 	struct acpi_dp *dp, *child1, *child2;
280 	char uuid[UUID_STR_LEN + 1];
281 	u8 *ptr, *pptr;
282 	int i;
283 
284 	ut_assertok(alloc_context(&ctx));
285 
286 	child1 = acpi_dp_new_table("child");
287 	ut_assertnonnull(child1);
288 	ut_assertnonnull(acpi_dp_add_integer(child1, "height", TEST_INT16));
289 
290 	child2 = acpi_dp_new_table("child");
291 	ut_assertnonnull(child2);
292 	ut_assertnonnull(acpi_dp_add_integer(child2, "age", TEST_INT8));
293 
294 	dp = acpi_dp_new_table("FRED");
295 	ut_assertnonnull(dp);
296 
297 	ut_assertnonnull(acpi_dp_add_child(dp, "anna", child1));
298 	ut_assertnonnull(acpi_dp_add_child(dp, "john", child2));
299 
300 	ptr = acpigen_get_current(ctx);
301 	ut_assertok(acpi_dp_write(ctx, dp));
302 	ut_asserteq(178, acpigen_get_current(ctx) - ptr);
303 
304 	/* UUID for child extension using Hierarchical Data Extension UUID */
305 	ut_asserteq(BUFFER_OP, ptr[10]);
306 	ut_asserteq(22, acpi_test_get_length(ptr + 11));
307 	ut_asserteq(WORD_PREFIX, ptr[14]);
308 	ut_asserteq(16, get_unaligned((u16 *)(ptr + 15)));
309 	uuid_bin_to_str(ptr + 17, uuid, 1);
310 	ut_asserteq_str(ACPI_DP_CHILD_UUID, uuid);
311 
312 	/* Package with two children */
313 	ut_asserteq(PACKAGE_OP, ptr[0x21]);
314 	ut_asserteq(0x28, acpi_test_get_length(ptr + 0x22));
315 	ut_asserteq(2, ptr[0x25]);
316 
317 	/* First we expect the two children as string/value */
318 	pptr = ptr + 0x26;
319 	for (i = 0; i < 2; i++) {
320 		ut_asserteq(PACKAGE_OP, pptr[0]);
321 		ut_asserteq(0x11, acpi_test_get_length(pptr + 1));
322 		ut_asserteq(2, pptr[4]);
323 		ut_asserteq(STRING_PREFIX, pptr[5]);
324 		ut_asserteq_str(i ? "john" : "anna", (char *)pptr + 6);
325 		ut_asserteq(STRING_PREFIX, pptr[11]);
326 		ut_asserteq_str("child", (char *)pptr + 12);
327 		pptr += 0x12;
328 	}
329 
330 	/* Write the two children */
331 	ut_asserteq(0x4a, pptr - ptr);
332 	for (i = 0; i < 2; i++) {
333 		const char *prop = i ? "age" : "height";
334 		const int datalen = i ? 1 : 2;
335 		int len = strlen(prop) + 1;
336 
337 		ut_asserteq(NAME_OP, pptr[0]);
338 		ut_asserteq_strn("chil", (char *)pptr + 1);
339 		ut_asserteq(PACKAGE_OP, pptr[5]);
340 		ut_asserteq(0x27 + len + datalen, acpi_test_get_length(pptr + 6));
341 		ut_asserteq(2, pptr[9]);
342 
343 		/* UUID */
344 		ut_asserteq(BUFFER_OP, pptr[10]);
345 		ut_asserteq(22, acpi_test_get_length(pptr + 11));
346 		ut_asserteq(WORD_PREFIX, pptr[14]);
347 		ut_asserteq(16, get_unaligned((u16 *)(pptr + 15)));
348 		uuid_bin_to_str(pptr + 17, uuid, 1);
349 		ut_asserteq_str(ACPI_DP_UUID, uuid);
350 		pptr += 33;
351 
352 		/* Containing package */
353 		ut_asserteq(i ? 0xa1 : 0x6b, pptr - ptr);
354 		ut_asserteq(PACKAGE_OP, pptr[0]);
355 		ut_asserteq(0xb + len + datalen, acpi_test_get_length(pptr + 1));
356 		ut_asserteq(1, pptr[4]);
357 
358 		/* Package containing the property-name string and the value */
359 		pptr += 5;
360 		ut_asserteq(i ? 0xa6 : 0x70, pptr - ptr);
361 		ut_asserteq(PACKAGE_OP, pptr[0]);
362 		ut_asserteq(6 + len + datalen, acpi_test_get_length(pptr + 1));
363 		ut_asserteq(2, pptr[4]);
364 
365 		ut_asserteq(STRING_PREFIX, pptr[5]);
366 		ut_asserteq_str(i ? "age" : "height", (char *)pptr + 6);
367 		pptr += 6 + len;
368 		if (i) {
369 			ut_asserteq(BYTE_PREFIX, pptr[0]);
370 			ut_asserteq(TEST_INT8, pptr[1]);
371 		} else {
372 			ut_asserteq(WORD_PREFIX, pptr[0]);
373 			ut_asserteq(TEST_INT16,
374 				    get_unaligned((u16 *)(pptr + 1)));
375 		}
376 		pptr += 1 + datalen;
377 	}
378 	ut_asserteq(178, pptr - ptr);
379 
380 	free_context(&ctx);
381 
382 	return 0;
383 }
384 DM_TEST(dm_test_acpi_dp_child, 0);
385 
386 /* Test emitting a GPIO */
dm_test_acpi_dp_gpio(struct unit_test_state * uts)387 static int dm_test_acpi_dp_gpio(struct unit_test_state *uts)
388 {
389 	struct acpi_ctx *ctx;
390 	struct acpi_dp *dp;
391 	u8 *ptr, *pptr;
392 
393 	ut_assertok(alloc_context(&ctx));
394 
395 	dp = acpi_dp_new_table("FRED");
396 	ut_assertnonnull(dp);
397 
398 	/* Try a few different parameters */
399 	ut_assertnonnull(acpi_dp_add_gpio(dp, "reset", TEST_REF, 0x23, 0x24,
400 					  ACPI_GPIO_ACTIVE_HIGH));
401 	ut_assertnonnull(acpi_dp_add_gpio(dp, "allow", TEST_REF, 0, 0,
402 					  ACPI_GPIO_ACTIVE_LOW));
403 
404 	ptr = acpigen_get_current(ctx);
405 	ut_assertok(acpi_dp_write(ctx, dp));
406 	ut_asserteq(0x6e, acpigen_get_current(ctx) - ptr);
407 
408 	pptr = ptr + 0x2c; //0x3a;
409 	ut_asserteq_str("reset", (char *)pptr);
410 	ut_asserteq_strn(EXPECT_REF, (char *)pptr + 0xe);
411 	ut_asserteq(0x23, pptr[0x1b]);
412 	ut_asserteq(0x24, pptr[0x1d]);
413 	ut_asserteq(ZERO_OP, pptr[0x1e]);
414 
415 	pptr = ptr + 0x51;
416 	ut_asserteq_str("allow", (char *)pptr);
417 	ut_asserteq_strn(EXPECT_REF, (char *)pptr + 0xe);
418 	ut_asserteq(ZERO_OP, pptr[0x1a]);
419 	ut_asserteq(ZERO_OP, pptr[0x1b]);
420 	ut_asserteq(ONE_OP, pptr[0x1c]);
421 
422 	return 0;
423 }
424 DM_TEST(dm_test_acpi_dp_gpio, 0);
425 
426 /* Test copying info from the device tree to ACPI tables */
dm_test_acpi_dp_copy(struct unit_test_state * uts)427 static int dm_test_acpi_dp_copy(struct unit_test_state *uts)
428 {
429 	struct acpi_ctx *ctx;
430 	struct udevice *dev;
431 	struct acpi_dp *dp;
432 	ofnode node;
433 	u8 *ptr;
434 
435 	ut_assertok(alloc_context(&ctx));
436 
437 	dp = acpi_dp_new_table("FRED");
438 	ut_assertnonnull(dp);
439 
440 	ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
441 	ut_asserteq_str("a-test", dev->name);
442 
443 	ut_assertok(acpi_dp_dev_copy_int(dev, dp, "int-value"));
444 	ut_asserteq(-EINVAL, acpi_dp_dev_copy_int(dev, dp, "missing-value"));
445 	ut_assertok(acpi_dp_dev_copy_int(dev, dp, "uint-value"));
446 
447 	ut_assertok(acpi_dp_dev_copy_str(dev, dp, "str-value"));
448 	ut_asserteq(-EINVAL, acpi_dp_dev_copy_str(dev, dp, "missing-value"));
449 
450 	node = ofnode_path("/chosen");
451 	ut_assert(ofnode_valid(node));
452 	ut_assertok(acpi_dp_ofnode_copy_int(node, dp, "int-values"));
453 	ut_asserteq(-EINVAL,
454 		    acpi_dp_ofnode_copy_int(node, dp, "missing-value"));
455 
456 	ut_assertok(acpi_dp_ofnode_copy_str(node, dp, "setting"));
457 	ut_asserteq(-EINVAL,
458 		    acpi_dp_ofnode_copy_str(node, dp, "missing-value"));
459 
460 	ptr = acpigen_get_current(ctx);
461 	ut_assertok(acpi_dp_write(ctx, dp));
462 	ut_asserteq(0x9d, acpigen_get_current(ctx) - ptr);
463 
464 	ut_asserteq(STRING_PREFIX, ptr[0x2b]);
465 	ut_asserteq_str("int-value", (char *)ptr + 0x2c);
466 	ut_asserteq(WORD_PREFIX, ptr[0x36]);
467 	ut_asserteq(1234, get_unaligned((u16 *)(ptr + 0x37)));
468 
469 	ut_asserteq(STRING_PREFIX, ptr[0x3e]);
470 	ut_asserteq_str("uint-value", (char *)ptr + 0x3f);
471 	ut_asserteq(DWORD_PREFIX, ptr[0x4a]);
472 	ut_asserteq(-1234, get_unaligned((u32 *)(ptr + 0x4b)));
473 
474 	ut_asserteq(STRING_PREFIX, ptr[0x54]);
475 	ut_asserteq_str("str-value", (char *)ptr + 0x55);
476 	ut_asserteq(STRING_PREFIX, ptr[0x5f]);
477 	ut_asserteq_str("test string", (char *)ptr + 0x60);
478 
479 	ut_asserteq(STRING_PREFIX, ptr[0x71]);
480 	ut_asserteq_str("int-values", (char *)ptr + 0x72);
481 	ut_asserteq(WORD_PREFIX, ptr[0x7d]);
482 	ut_asserteq(0x1937, get_unaligned((u16 *)(ptr + 0x7e)));
483 
484 	ut_asserteq(STRING_PREFIX, ptr[0x85]);
485 	ut_asserteq_str("setting", (char *)ptr + 0x86);
486 	ut_asserteq(STRING_PREFIX, ptr[0x8e]);
487 	ut_asserteq_str("sunrise ohoka", (char *)(ptr + 0x8f));
488 
489 	return 0;
490 }
491 DM_TEST(dm_test_acpi_dp_copy, UTF_SCAN_PDATA | UTF_SCAN_FDT);
492