1 // SPDX-License-Identifier: GPL-2.0+
3 * Tests for ACPI code generation via a device-property table
5 * Copyright 2019 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
12 #include <acpi/acpigen.h>
13 #include <acpi/acpi_dp.h>
14 #include <asm/unaligned.h>
20 /* Maximum size of the ACPI context needed for most tests */
21 #define ACPI_CONTEXT_SIZE 500
23 #define TEST_INT8 0x7d
24 #define TEST_INT16 0x2345
25 #define TEST_INT32 0x12345678
26 #define TEST_INT64 0x4567890123456
27 #define TEST_STR "testing acpi strings"
28 #define TEST_REF "\\SB.I2C0.TPM2"
29 #define EXPECT_REF "SB__I2C0TPM2"
31 static int alloc_context(struct acpi_ctx **ctxp)
33 return acpi_test_alloc_context_size(ctxp, ACPI_CONTEXT_SIZE);
38 static void free_context(struct acpi_ctx **ctxp)
44 /* Test emitting an empty table */
45 static int dm_test_acpi_dp_new_table(struct unit_test_state *uts)
51 ut_assertok(alloc_context(&ctx));
53 dp = acpi_dp_new_table("FRED");
56 ptr = acpigen_get_current(ctx);
57 ut_assertok(acpi_dp_write(ctx, dp));
58 ut_asserteq(10, acpigen_get_current(ctx) - ptr);
59 ut_asserteq(NAME_OP, *(u8 *)ptr);
60 ut_asserteq_strn("FRED", (char *)ptr + 1);
61 ut_asserteq(PACKAGE_OP, ptr[5]);
62 ut_asserteq(4, acpi_test_get_length(ptr + 6));
63 ut_asserteq(0, ptr[9]);
69 DM_TEST(dm_test_acpi_dp_new_table, 0);
71 /* Test emitting an integer */
72 static int dm_test_acpi_dp_int(struct unit_test_state *uts)
75 char uuid[UUID_STR_LEN + 1];
79 ut_assertok(alloc_context(&ctx));
81 dp = acpi_dp_new_table("FRED");
83 ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT32));
85 ptr = acpigen_get_current(ctx);
86 ut_assertok(acpi_dp_write(ctx, dp));
87 ut_asserteq(54, acpigen_get_current(ctx) - ptr);
88 ut_asserteq(NAME_OP, *(u8 *)ptr);
89 ut_asserteq_strn("FRED", (char *)ptr + 1);
90 ut_asserteq(PACKAGE_OP, ptr[5]);
91 ut_asserteq(48, acpi_test_get_length(ptr + 6));
92 ut_asserteq(2, ptr[9]);
95 ut_asserteq(BUFFER_OP, ptr[10]);
96 ut_asserteq(22, acpi_test_get_length(ptr + 11));
97 ut_asserteq(WORD_PREFIX, ptr[14]);
98 ut_asserteq(16, get_unaligned((u16 *)(ptr + 15)));
99 uuid_bin_to_str(ptr + 17, uuid, 1);
100 ut_asserteq_str(ACPI_DP_UUID, uuid);
102 /* Container package */
103 ut_asserteq(PACKAGE_OP, ptr[33]);
104 ut_asserteq(20, acpi_test_get_length(ptr + 34));
105 ut_asserteq(1, ptr[37]);
107 /* Package with name and (integer) value */
108 ut_asserteq(PACKAGE_OP, ptr[38]);
109 ut_asserteq(15, acpi_test_get_length(ptr + 39));
110 ut_asserteq(2, ptr[42]);
111 ut_asserteq(STRING_PREFIX, ptr[43]);
112 ut_asserteq_str("MARY", (char *)ptr + 44);
114 ut_asserteq(DWORD_PREFIX, ptr[49]);
115 ut_asserteq(TEST_INT32, get_unaligned((u32 *)(ptr + 50)));
121 DM_TEST(dm_test_acpi_dp_int, 0);
123 /* Test emitting a 64-bit integer */
124 static int dm_test_acpi_dp_int64(struct unit_test_state *uts)
126 struct acpi_ctx *ctx;
130 ut_assertok(alloc_context(&ctx));
132 dp = acpi_dp_new_table("FRED");
133 ut_assertnonnull(dp);
134 ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT64));
136 ptr = acpigen_get_current(ctx);
137 ut_assertok(acpi_dp_write(ctx, dp));
138 ut_asserteq(58, acpigen_get_current(ctx) - ptr);
140 ut_asserteq(QWORD_PREFIX, ptr[49]);
141 ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 50)));
147 DM_TEST(dm_test_acpi_dp_int64, 0);
149 /* Test emitting a 16-bit integer */
150 static int dm_test_acpi_dp_int16(struct unit_test_state *uts)
152 struct acpi_ctx *ctx;
156 ut_assertok(alloc_context(&ctx));
158 dp = acpi_dp_new_table("FRED");
159 ut_assertnonnull(dp);
160 ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT16));
162 ptr = acpigen_get_current(ctx);
163 ut_assertok(acpi_dp_write(ctx, dp));
164 ut_asserteq(52, acpigen_get_current(ctx) - ptr);
166 ut_asserteq(WORD_PREFIX, ptr[49]);
167 ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 50)));
173 DM_TEST(dm_test_acpi_dp_int16, 0);
175 /* Test emitting a 8-bit integer */
176 static int dm_test_acpi_dp_int8(struct unit_test_state *uts)
178 struct acpi_ctx *ctx;
182 ut_assertok(alloc_context(&ctx));
184 dp = acpi_dp_new_table("FRED");
185 ut_assertnonnull(dp);
186 ut_assertnonnull(acpi_dp_add_integer(dp, "MARY", TEST_INT8));
188 ptr = acpigen_get_current(ctx);
189 ut_assertok(acpi_dp_write(ctx, dp));
190 ut_asserteq(51, acpigen_get_current(ctx) - ptr);
192 ut_asserteq(BYTE_PREFIX, ptr[49]);
193 ut_asserteq(TEST_INT8, ptr[50]);
199 DM_TEST(dm_test_acpi_dp_int8, 0);
201 /* Test emitting multiple values */
202 static int dm_test_acpi_dp_multiple(struct unit_test_state *uts)
204 struct acpi_ctx *ctx;
208 ut_assertok(alloc_context(&ctx));
210 dp = acpi_dp_new_table("FRED");
211 ut_assertnonnull(dp);
212 ut_assertnonnull(acpi_dp_add_integer(dp, "int16", TEST_INT16));
213 ut_assertnonnull(acpi_dp_add_string(dp, "str", TEST_STR));
214 ut_assertnonnull(acpi_dp_add_reference(dp, "ref", TEST_REF));
216 ptr = acpigen_get_current(ctx);
217 ut_assertok(acpi_dp_write(ctx, dp));
218 ut_asserteq(110, acpigen_get_current(ctx) - ptr);
220 ut_asserteq(WORD_PREFIX, ptr[0x32]);
221 ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 0x33)));
222 ut_asserteq(STRING_PREFIX, ptr[0x3f]);
223 ut_asserteq_str(TEST_STR, (char *)ptr + 0x40);
224 ut_asserteq(ROOT_PREFIX, ptr[0x5f]);
225 ut_asserteq(MULTI_NAME_PREFIX, ptr[0x60]);
226 ut_asserteq(3, ptr[0x61]);
227 ut_asserteq_strn(EXPECT_REF, (char *)ptr + 0x62);
233 DM_TEST(dm_test_acpi_dp_multiple, 0);
235 /* Test emitting an array */
236 static int dm_test_acpi_dp_array(struct unit_test_state *uts)
238 struct acpi_ctx *ctx;
243 ut_assertok(alloc_context(&ctx));
245 dp = acpi_dp_new_table("FRED");
246 ut_assertnonnull(dp);
247 speed[0] = TEST_INT8;
248 speed[1] = TEST_INT16;
249 speed[2] = TEST_INT32;
250 speed[3] = TEST_INT64;
251 ut_assertnonnull(acpi_dp_add_integer_array(dp, "speeds", speed,
254 ptr = acpigen_get_current(ctx);
255 ut_assertok(acpi_dp_write(ctx, dp));
256 ut_asserteq(75, acpigen_get_current(ctx) - ptr);
258 ut_asserteq(BYTE_PREFIX, ptr[0x38]);
259 ut_asserteq(TEST_INT8, ptr[0x39]);
261 ut_asserteq(WORD_PREFIX, ptr[0x3a]);
262 ut_asserteq(TEST_INT16, get_unaligned((u16 *)(ptr + 0x3b)));
264 ut_asserteq(DWORD_PREFIX, ptr[0x3d]);
265 ut_asserteq(TEST_INT32, get_unaligned((u32 *)(ptr + 0x3e)));
267 ut_asserteq(QWORD_PREFIX, ptr[0x42]);
268 ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)(ptr + 0x43)));
274 DM_TEST(dm_test_acpi_dp_array, 0);
276 /* Test emitting a child */
277 static int dm_test_acpi_dp_child(struct unit_test_state *uts)
279 struct acpi_ctx *ctx;
280 struct acpi_dp *dp, *child1, *child2;
281 char uuid[UUID_STR_LEN + 1];
285 ut_assertok(alloc_context(&ctx));
287 child1 = acpi_dp_new_table("child");
288 ut_assertnonnull(child1);
289 ut_assertnonnull(acpi_dp_add_integer(child1, "height", TEST_INT16));
291 child2 = acpi_dp_new_table("child");
292 ut_assertnonnull(child2);
293 ut_assertnonnull(acpi_dp_add_integer(child2, "age", TEST_INT8));
295 dp = acpi_dp_new_table("FRED");
296 ut_assertnonnull(dp);
298 ut_assertnonnull(acpi_dp_add_child(dp, "anna", child1));
299 ut_assertnonnull(acpi_dp_add_child(dp, "john", child2));
301 ptr = acpigen_get_current(ctx);
302 ut_assertok(acpi_dp_write(ctx, dp));
303 ut_asserteq(178, acpigen_get_current(ctx) - ptr);
305 /* UUID for child extension using Hierarchical Data Extension UUID */
306 ut_asserteq(BUFFER_OP, ptr[10]);
307 ut_asserteq(22, acpi_test_get_length(ptr + 11));
308 ut_asserteq(WORD_PREFIX, ptr[14]);
309 ut_asserteq(16, get_unaligned((u16 *)(ptr + 15)));
310 uuid_bin_to_str(ptr + 17, uuid, 1);
311 ut_asserteq_str(ACPI_DP_CHILD_UUID, uuid);
313 /* Package with two children */
314 ut_asserteq(PACKAGE_OP, ptr[0x21]);
315 ut_asserteq(0x28, acpi_test_get_length(ptr + 0x22));
316 ut_asserteq(2, ptr[0x25]);
318 /* First we expect the two children as string/value */
320 for (i = 0; i < 2; i++) {
321 ut_asserteq(PACKAGE_OP, pptr[0]);
322 ut_asserteq(0x11, acpi_test_get_length(pptr + 1));
323 ut_asserteq(2, pptr[4]);
324 ut_asserteq(STRING_PREFIX, pptr[5]);
325 ut_asserteq_str(i ? "john" : "anna", (char *)pptr + 6);
326 ut_asserteq(STRING_PREFIX, pptr[11]);
327 ut_asserteq_str("child", (char *)pptr + 12);
331 /* Write the two children */
332 ut_asserteq(0x4a, pptr - ptr);
333 for (i = 0; i < 2; i++) {
334 const char *prop = i ? "age" : "height";
335 const int datalen = i ? 1 : 2;
336 int len = strlen(prop) + 1;
338 ut_asserteq(NAME_OP, pptr[0]);
339 ut_asserteq_strn("chil", (char *)pptr + 1);
340 ut_asserteq(PACKAGE_OP, pptr[5]);
341 ut_asserteq(0x27 + len + datalen, acpi_test_get_length(pptr + 6));
342 ut_asserteq(2, pptr[9]);
345 ut_asserteq(BUFFER_OP, pptr[10]);
346 ut_asserteq(22, acpi_test_get_length(pptr + 11));
347 ut_asserteq(WORD_PREFIX, pptr[14]);
348 ut_asserteq(16, get_unaligned((u16 *)(pptr + 15)));
349 uuid_bin_to_str(pptr + 17, uuid, 1);
350 ut_asserteq_str(ACPI_DP_UUID, uuid);
353 /* Containing package */
354 ut_asserteq(i ? 0xa1 : 0x6b, pptr - ptr);
355 ut_asserteq(PACKAGE_OP, pptr[0]);
356 ut_asserteq(0xb + len + datalen, acpi_test_get_length(pptr + 1));
357 ut_asserteq(1, pptr[4]);
359 /* Package containing the property-name string and the value */
361 ut_asserteq(i ? 0xa6 : 0x70, pptr - ptr);
362 ut_asserteq(PACKAGE_OP, pptr[0]);
363 ut_asserteq(6 + len + datalen, acpi_test_get_length(pptr + 1));
364 ut_asserteq(2, pptr[4]);
366 ut_asserteq(STRING_PREFIX, pptr[5]);
367 ut_asserteq_str(i ? "age" : "height", (char *)pptr + 6);
370 ut_asserteq(BYTE_PREFIX, pptr[0]);
371 ut_asserteq(TEST_INT8, pptr[1]);
373 ut_asserteq(WORD_PREFIX, pptr[0]);
374 ut_asserteq(TEST_INT16,
375 get_unaligned((u16 *)(pptr + 1)));
379 ut_asserteq(178, pptr - ptr);
385 DM_TEST(dm_test_acpi_dp_child, 0);
387 /* Test emitting a GPIO */
388 static int dm_test_acpi_dp_gpio(struct unit_test_state *uts)
390 struct acpi_ctx *ctx;
394 ut_assertok(alloc_context(&ctx));
396 dp = acpi_dp_new_table("FRED");
397 ut_assertnonnull(dp);
399 /* Try a few different parameters */
400 ut_assertnonnull(acpi_dp_add_gpio(dp, "reset", TEST_REF, 0x23, 0x24,
401 ACPI_GPIO_ACTIVE_HIGH));
402 ut_assertnonnull(acpi_dp_add_gpio(dp, "allow", TEST_REF, 0, 0,
403 ACPI_GPIO_ACTIVE_LOW));
405 ptr = acpigen_get_current(ctx);
406 ut_assertok(acpi_dp_write(ctx, dp));
407 ut_asserteq(0x6e, acpigen_get_current(ctx) - ptr);
409 pptr = ptr + 0x2c; //0x3a;
410 ut_asserteq_str("reset", (char *)pptr);
411 ut_asserteq_strn(EXPECT_REF, (char *)pptr + 0xe);
412 ut_asserteq(0x23, pptr[0x1b]);
413 ut_asserteq(0x24, pptr[0x1d]);
414 ut_asserteq(ZERO_OP, pptr[0x1e]);
417 ut_asserteq_str("allow", (char *)pptr);
418 ut_asserteq_strn(EXPECT_REF, (char *)pptr + 0xe);
419 ut_asserteq(ZERO_OP, pptr[0x1a]);
420 ut_asserteq(ZERO_OP, pptr[0x1b]);
421 ut_asserteq(ONE_OP, pptr[0x1c]);
425 DM_TEST(dm_test_acpi_dp_gpio, 0);
427 /* Test copying info from the device tree to ACPI tables */
428 static int dm_test_acpi_dp_copy(struct unit_test_state *uts)
430 struct acpi_ctx *ctx;
436 ut_assertok(alloc_context(&ctx));
438 dp = acpi_dp_new_table("FRED");
439 ut_assertnonnull(dp);
441 ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
442 ut_asserteq_str("a-test", dev->name);
444 ut_assertok(acpi_dp_dev_copy_int(dev, dp, "int-value"));
445 ut_asserteq(-EINVAL, acpi_dp_dev_copy_int(dev, dp, "missing-value"));
446 ut_assertok(acpi_dp_dev_copy_int(dev, dp, "uint-value"));
448 ut_assertok(acpi_dp_dev_copy_str(dev, dp, "str-value"));
449 ut_asserteq(-EINVAL, acpi_dp_dev_copy_str(dev, dp, "missing-value"));
451 node = ofnode_path("/chosen");
452 ut_assert(ofnode_valid(node));
453 ut_assertok(acpi_dp_ofnode_copy_int(node, dp, "int-values"));
455 acpi_dp_ofnode_copy_int(node, dp, "missing-value"));
457 ut_assertok(acpi_dp_ofnode_copy_str(node, dp, "setting"));
459 acpi_dp_ofnode_copy_str(node, dp, "missing-value"));
461 ptr = acpigen_get_current(ctx);
462 ut_assertok(acpi_dp_write(ctx, dp));
463 ut_asserteq(0x9d, acpigen_get_current(ctx) - ptr);
465 ut_asserteq(STRING_PREFIX, ptr[0x2b]);
466 ut_asserteq_str("int-value", (char *)ptr + 0x2c);
467 ut_asserteq(WORD_PREFIX, ptr[0x36]);
468 ut_asserteq(1234, get_unaligned((u16 *)(ptr + 0x37)));
470 ut_asserteq(STRING_PREFIX, ptr[0x3e]);
471 ut_asserteq_str("uint-value", (char *)ptr + 0x3f);
472 ut_asserteq(DWORD_PREFIX, ptr[0x4a]);
473 ut_asserteq(-1234, get_unaligned((u32 *)(ptr + 0x4b)));
475 ut_asserteq(STRING_PREFIX, ptr[0x54]);
476 ut_asserteq_str("str-value", (char *)ptr + 0x55);
477 ut_asserteq(STRING_PREFIX, ptr[0x5f]);
478 ut_asserteq_str("test string", (char *)ptr + 0x60);
480 ut_asserteq(STRING_PREFIX, ptr[0x71]);
481 ut_asserteq_str("int-values", (char *)ptr + 0x72);
482 ut_asserteq(WORD_PREFIX, ptr[0x7d]);
483 ut_asserteq(0x1937, get_unaligned((u16 *)(ptr + 0x7e)));
485 ut_asserteq(STRING_PREFIX, ptr[0x85]);
486 ut_asserteq_str("setting", (char *)ptr + 0x86);
487 ut_asserteq(STRING_PREFIX, ptr[0x8e]);
488 ut_asserteq_str("sunrise ohoka", (char *)(ptr + 0x8f));
492 DM_TEST(dm_test_acpi_dp_copy, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);