acpi_dp.c 13 KB

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