marshalling_kunit.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * KUnit test for the ACPI-WMI marshalling code.
  4. *
  5. * Copyright (C) 2025 Armin Wolf <W_Armin@gmx.de>
  6. */
  7. #include <linux/acpi.h>
  8. #include <linux/align.h>
  9. #include <linux/module.h>
  10. #include <linux/slab.h>
  11. #include <linux/string.h>
  12. #include <linux/types.h>
  13. #include <linux/wmi.h>
  14. #include <kunit/resource.h>
  15. #include <kunit/test.h>
  16. #include "../internal.h"
  17. struct wmi_acpi_param {
  18. const char *name;
  19. const union acpi_object obj;
  20. const struct wmi_buffer buffer;
  21. };
  22. struct wmi_string_param {
  23. const char *name;
  24. const char *string;
  25. const struct wmi_buffer buffer;
  26. };
  27. struct wmi_invalid_acpi_param {
  28. const char *name;
  29. const union acpi_object obj;
  30. };
  31. struct wmi_invalid_string_param {
  32. const char *name;
  33. const struct wmi_buffer buffer;
  34. };
  35. /* 0xdeadbeef */
  36. static u8 expected_single_integer[] = {
  37. 0xef, 0xbe, 0xad, 0xde,
  38. };
  39. /* "TEST" */
  40. static u8 expected_single_string[] = {
  41. 0x0a, 0x00, 0x54, 0x00, 0x45, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00,
  42. };
  43. static u8 test_buffer[] = {
  44. 0xab, 0xcd,
  45. };
  46. static u8 expected_single_buffer[] = {
  47. 0xab, 0xcd,
  48. };
  49. static union acpi_object simple_package_elements[] = {
  50. {
  51. .buffer = {
  52. .type = ACPI_TYPE_BUFFER,
  53. .length = sizeof(test_buffer),
  54. .pointer = test_buffer,
  55. },
  56. },
  57. {
  58. .integer = {
  59. .type = ACPI_TYPE_INTEGER,
  60. .value = 0x01020304,
  61. },
  62. },
  63. };
  64. static u8 expected_simple_package[] = {
  65. 0xab, 0xcd,
  66. 0x00, 0x00,
  67. 0x04, 0x03, 0x02, 0x01,
  68. };
  69. static u8 test_small_buffer[] = {
  70. 0xde,
  71. };
  72. static union acpi_object complex_package_elements[] = {
  73. {
  74. .integer = {
  75. .type = ACPI_TYPE_INTEGER,
  76. .value = 0xdeadbeef,
  77. },
  78. },
  79. {
  80. .buffer = {
  81. .type = ACPI_TYPE_BUFFER,
  82. .length = sizeof(test_small_buffer),
  83. .pointer = test_small_buffer,
  84. },
  85. },
  86. {
  87. .string = {
  88. .type = ACPI_TYPE_STRING,
  89. .length = sizeof("TEST") - 1,
  90. .pointer = "TEST",
  91. },
  92. },
  93. {
  94. .buffer = {
  95. .type = ACPI_TYPE_BUFFER,
  96. .length = sizeof(test_small_buffer),
  97. .pointer = test_small_buffer,
  98. },
  99. },
  100. {
  101. .integer = {
  102. .type = ACPI_TYPE_INTEGER,
  103. .value = 0x01020304,
  104. },
  105. }
  106. };
  107. static u8 expected_complex_package[] = {
  108. 0xef, 0xbe, 0xad, 0xde,
  109. 0xde,
  110. 0x00,
  111. 0x0a, 0x00, 0x54, 0x00, 0x45, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00,
  112. 0xde,
  113. 0x00,
  114. 0x04, 0x03, 0x02, 0x01,
  115. };
  116. static const struct wmi_acpi_param wmi_acpi_params_array[] = {
  117. {
  118. .name = "single_integer",
  119. .obj = {
  120. .integer = {
  121. .type = ACPI_TYPE_INTEGER,
  122. .value = 0xdeadbeef,
  123. },
  124. },
  125. .buffer = {
  126. .data = expected_single_integer,
  127. .length = sizeof(expected_single_integer),
  128. },
  129. },
  130. {
  131. .name = "single_string",
  132. .obj = {
  133. .string = {
  134. .type = ACPI_TYPE_STRING,
  135. .length = sizeof("TEST") - 1,
  136. .pointer = "TEST",
  137. },
  138. },
  139. .buffer = {
  140. .data = expected_single_string,
  141. .length = sizeof(expected_single_string),
  142. },
  143. },
  144. {
  145. .name = "single_buffer",
  146. .obj = {
  147. .buffer = {
  148. .type = ACPI_TYPE_BUFFER,
  149. .length = sizeof(test_buffer),
  150. .pointer = test_buffer,
  151. },
  152. },
  153. .buffer = {
  154. .data = expected_single_buffer,
  155. .length = sizeof(expected_single_buffer),
  156. },
  157. },
  158. {
  159. .name = "simple_package",
  160. .obj = {
  161. .package = {
  162. .type = ACPI_TYPE_PACKAGE,
  163. .count = ARRAY_SIZE(simple_package_elements),
  164. .elements = simple_package_elements,
  165. },
  166. },
  167. .buffer = {
  168. .data = expected_simple_package,
  169. .length = sizeof(expected_simple_package),
  170. },
  171. },
  172. {
  173. .name = "complex_package",
  174. .obj = {
  175. .package = {
  176. .type = ACPI_TYPE_PACKAGE,
  177. .count = ARRAY_SIZE(complex_package_elements),
  178. .elements = complex_package_elements,
  179. },
  180. },
  181. .buffer = {
  182. .data = expected_complex_package,
  183. .length = sizeof(expected_complex_package),
  184. },
  185. },
  186. };
  187. static void wmi_acpi_param_get_desc(const struct wmi_acpi_param *param, char *desc)
  188. {
  189. strscpy(desc, param->name, KUNIT_PARAM_DESC_SIZE);
  190. }
  191. KUNIT_ARRAY_PARAM(wmi_unmarshal_acpi_object, wmi_acpi_params_array, wmi_acpi_param_get_desc);
  192. /* "WMI\0" */
  193. static u8 padded_wmi_string[] = {
  194. 0x0a, 0x00,
  195. 0x57, 0x00,
  196. 0x4D, 0x00,
  197. 0x49, 0x00,
  198. 0x00, 0x00,
  199. 0x00, 0x00,
  200. };
  201. static const struct wmi_string_param wmi_string_params_array[] = {
  202. {
  203. .name = "test",
  204. .string = "TEST",
  205. .buffer = {
  206. .length = sizeof(expected_single_string),
  207. .data = expected_single_string,
  208. },
  209. },
  210. {
  211. .name = "padded",
  212. .string = "WMI",
  213. .buffer = {
  214. .length = sizeof(padded_wmi_string),
  215. .data = padded_wmi_string,
  216. },
  217. },
  218. };
  219. static void wmi_string_param_get_desc(const struct wmi_string_param *param, char *desc)
  220. {
  221. strscpy(desc, param->name, KUNIT_PARAM_DESC_SIZE);
  222. }
  223. KUNIT_ARRAY_PARAM(wmi_marshal_string, wmi_string_params_array, wmi_string_param_get_desc);
  224. static union acpi_object nested_package_elements[] = {
  225. {
  226. .package = {
  227. .type = ACPI_TYPE_PACKAGE,
  228. .count = ARRAY_SIZE(simple_package_elements),
  229. .elements = simple_package_elements,
  230. },
  231. }
  232. };
  233. static const struct wmi_invalid_acpi_param wmi_invalid_acpi_params_array[] = {
  234. {
  235. .name = "nested_package",
  236. .obj = {
  237. .package = {
  238. .type = ACPI_TYPE_PACKAGE,
  239. .count = ARRAY_SIZE(nested_package_elements),
  240. .elements = nested_package_elements,
  241. },
  242. },
  243. },
  244. {
  245. .name = "reference",
  246. .obj = {
  247. .reference = {
  248. .type = ACPI_TYPE_LOCAL_REFERENCE,
  249. .actual_type = ACPI_TYPE_ANY,
  250. .handle = NULL,
  251. },
  252. },
  253. },
  254. {
  255. .name = "processor",
  256. .obj = {
  257. .processor = {
  258. .type = ACPI_TYPE_PROCESSOR,
  259. .proc_id = 0,
  260. .pblk_address = 0,
  261. .pblk_length = 0,
  262. },
  263. },
  264. },
  265. {
  266. .name = "power_resource",
  267. .obj = {
  268. .power_resource = {
  269. .type = ACPI_TYPE_POWER,
  270. .system_level = 0,
  271. .resource_order = 0,
  272. },
  273. },
  274. },
  275. };
  276. static void wmi_invalid_acpi_param_get_desc(const struct wmi_invalid_acpi_param *param, char *desc)
  277. {
  278. strscpy(desc, param->name, KUNIT_PARAM_DESC_SIZE);
  279. }
  280. KUNIT_ARRAY_PARAM(wmi_unmarshal_acpi_object_failure, wmi_invalid_acpi_params_array,
  281. wmi_invalid_acpi_param_get_desc);
  282. static u8 oversized_wmi_string[] = {
  283. 0x04, 0x00, 0x00, 0x00,
  284. };
  285. /*
  286. * The error is that 3 bytes can not hold UTF-16 characters
  287. * without cutting of the last one.
  288. */
  289. static u8 undersized_wmi_string[] = {
  290. 0x03, 0x00, 0x00, 0x00, 0x00,
  291. };
  292. static u8 non_ascii_wmi_string[] = {
  293. 0x04, 0x00, 0xC4, 0x00, 0x00, 0x00,
  294. };
  295. static const struct wmi_invalid_string_param wmi_invalid_string_params_array[] = {
  296. {
  297. .name = "empty_buffer",
  298. .buffer = {
  299. .length = 0,
  300. .data = ZERO_SIZE_PTR,
  301. },
  302. },
  303. {
  304. .name = "oversized",
  305. .buffer = {
  306. .length = sizeof(oversized_wmi_string),
  307. .data = oversized_wmi_string,
  308. },
  309. },
  310. {
  311. .name = "undersized",
  312. .buffer = {
  313. .length = sizeof(undersized_wmi_string),
  314. .data = undersized_wmi_string,
  315. },
  316. },
  317. {
  318. .name = "non_ascii",
  319. .buffer = {
  320. .length = sizeof(non_ascii_wmi_string),
  321. .data = non_ascii_wmi_string,
  322. },
  323. },
  324. };
  325. static void wmi_invalid_string_param_get_desc(const struct wmi_invalid_string_param *param,
  326. char *desc)
  327. {
  328. strscpy(desc, param->name, KUNIT_PARAM_DESC_SIZE);
  329. }
  330. KUNIT_ARRAY_PARAM(wmi_marshal_string_failure, wmi_invalid_string_params_array,
  331. wmi_invalid_string_param_get_desc);
  332. KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *);
  333. static void wmi_unmarshal_acpi_object_test(struct kunit *test)
  334. {
  335. const struct wmi_acpi_param *param = test->param_value;
  336. struct wmi_buffer result;
  337. int ret;
  338. ret = wmi_unmarshal_acpi_object(&param->obj, &result);
  339. if (ret < 0)
  340. KUNIT_FAIL_AND_ABORT(test, "Unmarshalling of ACPI object failed\n");
  341. kunit_add_action(test, kfree_wrapper, result.data);
  342. KUNIT_EXPECT_TRUE(test, IS_ALIGNED((uintptr_t)result.data, 8));
  343. KUNIT_EXPECT_EQ(test, result.length, param->buffer.length);
  344. KUNIT_EXPECT_MEMEQ(test, result.data, param->buffer.data, result.length);
  345. }
  346. static void wmi_unmarshal_acpi_object_failure_test(struct kunit *test)
  347. {
  348. const struct wmi_invalid_acpi_param *param = test->param_value;
  349. struct wmi_buffer result;
  350. int ret;
  351. ret = wmi_unmarshal_acpi_object(&param->obj, &result);
  352. if (ret < 0)
  353. return;
  354. kfree(result.data);
  355. KUNIT_FAIL(test, "Invalid ACPI object was not rejected\n");
  356. }
  357. static void wmi_marshal_string_test(struct kunit *test)
  358. {
  359. const struct wmi_string_param *param = test->param_value;
  360. struct acpi_buffer result;
  361. int ret;
  362. ret = wmi_marshal_string(&param->buffer, &result);
  363. if (ret < 0)
  364. KUNIT_FAIL_AND_ABORT(test, "Marshalling of WMI string failed\n");
  365. kunit_add_action(test, kfree_wrapper, result.pointer);
  366. KUNIT_EXPECT_EQ(test, result.length, strlen(param->string));
  367. KUNIT_EXPECT_STREQ(test, result.pointer, param->string);
  368. }
  369. static void wmi_marshal_string_failure_test(struct kunit *test)
  370. {
  371. const struct wmi_invalid_string_param *param = test->param_value;
  372. struct acpi_buffer result;
  373. int ret;
  374. ret = wmi_marshal_string(&param->buffer, &result);
  375. if (ret < 0)
  376. return;
  377. kfree(result.pointer);
  378. KUNIT_FAIL(test, "Invalid string was not rejected\n");
  379. }
  380. static struct kunit_case wmi_marshalling_test_cases[] = {
  381. KUNIT_CASE_PARAM(wmi_unmarshal_acpi_object_test,
  382. wmi_unmarshal_acpi_object_gen_params),
  383. KUNIT_CASE_PARAM(wmi_marshal_string_test,
  384. wmi_marshal_string_gen_params),
  385. KUNIT_CASE_PARAM(wmi_unmarshal_acpi_object_failure_test,
  386. wmi_unmarshal_acpi_object_failure_gen_params),
  387. KUNIT_CASE_PARAM(wmi_marshal_string_failure_test,
  388. wmi_marshal_string_failure_gen_params),
  389. {}
  390. };
  391. static struct kunit_suite wmi_marshalling_test_suite = {
  392. .name = "wmi_marshalling",
  393. .test_cases = wmi_marshalling_test_cases,
  394. };
  395. kunit_test_suite(wmi_marshalling_test_suite);
  396. MODULE_AUTHOR("Armin Wolf <W_Armin@gmx.de>");
  397. MODULE_DESCRIPTION("KUnit test for the ACPI-WMI marshalling code");
  398. MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
  399. MODULE_LICENSE("GPL");