| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- // SPDX-License-Identifier: GPL-2.0-or-later
- /*
- * KUnit test for the ACPI-WMI marshalling code.
- *
- * Copyright (C) 2025 Armin Wolf <W_Armin@gmx.de>
- */
- #include <linux/acpi.h>
- #include <linux/align.h>
- #include <linux/module.h>
- #include <linux/slab.h>
- #include <linux/string.h>
- #include <linux/types.h>
- #include <linux/wmi.h>
- #include <kunit/resource.h>
- #include <kunit/test.h>
- #include "../internal.h"
- struct wmi_acpi_param {
- const char *name;
- const union acpi_object obj;
- const struct wmi_buffer buffer;
- };
- struct wmi_string_param {
- const char *name;
- const char *string;
- const struct wmi_buffer buffer;
- };
- struct wmi_invalid_acpi_param {
- const char *name;
- const union acpi_object obj;
- };
- struct wmi_invalid_string_param {
- const char *name;
- const struct wmi_buffer buffer;
- };
- /* 0xdeadbeef */
- static u8 expected_single_integer[] = {
- 0xef, 0xbe, 0xad, 0xde,
- };
- /* "TEST" */
- static u8 expected_single_string[] = {
- 0x0a, 0x00, 0x54, 0x00, 0x45, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00,
- };
- static u8 test_buffer[] = {
- 0xab, 0xcd,
- };
- static u8 expected_single_buffer[] = {
- 0xab, 0xcd,
- };
- static union acpi_object simple_package_elements[] = {
- {
- .buffer = {
- .type = ACPI_TYPE_BUFFER,
- .length = sizeof(test_buffer),
- .pointer = test_buffer,
- },
- },
- {
- .integer = {
- .type = ACPI_TYPE_INTEGER,
- .value = 0x01020304,
- },
- },
- };
- static u8 expected_simple_package[] = {
- 0xab, 0xcd,
- 0x00, 0x00,
- 0x04, 0x03, 0x02, 0x01,
- };
- static u8 test_small_buffer[] = {
- 0xde,
- };
- static union acpi_object complex_package_elements[] = {
- {
- .integer = {
- .type = ACPI_TYPE_INTEGER,
- .value = 0xdeadbeef,
- },
- },
- {
- .buffer = {
- .type = ACPI_TYPE_BUFFER,
- .length = sizeof(test_small_buffer),
- .pointer = test_small_buffer,
- },
- },
- {
- .string = {
- .type = ACPI_TYPE_STRING,
- .length = sizeof("TEST") - 1,
- .pointer = "TEST",
- },
- },
- {
- .buffer = {
- .type = ACPI_TYPE_BUFFER,
- .length = sizeof(test_small_buffer),
- .pointer = test_small_buffer,
- },
- },
- {
- .integer = {
- .type = ACPI_TYPE_INTEGER,
- .value = 0x01020304,
- },
- }
- };
- static u8 expected_complex_package[] = {
- 0xef, 0xbe, 0xad, 0xde,
- 0xde,
- 0x00,
- 0x0a, 0x00, 0x54, 0x00, 0x45, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00,
- 0xde,
- 0x00,
- 0x04, 0x03, 0x02, 0x01,
- };
- static const struct wmi_acpi_param wmi_acpi_params_array[] = {
- {
- .name = "single_integer",
- .obj = {
- .integer = {
- .type = ACPI_TYPE_INTEGER,
- .value = 0xdeadbeef,
- },
- },
- .buffer = {
- .data = expected_single_integer,
- .length = sizeof(expected_single_integer),
- },
- },
- {
- .name = "single_string",
- .obj = {
- .string = {
- .type = ACPI_TYPE_STRING,
- .length = sizeof("TEST") - 1,
- .pointer = "TEST",
- },
- },
- .buffer = {
- .data = expected_single_string,
- .length = sizeof(expected_single_string),
- },
- },
- {
- .name = "single_buffer",
- .obj = {
- .buffer = {
- .type = ACPI_TYPE_BUFFER,
- .length = sizeof(test_buffer),
- .pointer = test_buffer,
- },
- },
- .buffer = {
- .data = expected_single_buffer,
- .length = sizeof(expected_single_buffer),
- },
- },
- {
- .name = "simple_package",
- .obj = {
- .package = {
- .type = ACPI_TYPE_PACKAGE,
- .count = ARRAY_SIZE(simple_package_elements),
- .elements = simple_package_elements,
- },
- },
- .buffer = {
- .data = expected_simple_package,
- .length = sizeof(expected_simple_package),
- },
- },
- {
- .name = "complex_package",
- .obj = {
- .package = {
- .type = ACPI_TYPE_PACKAGE,
- .count = ARRAY_SIZE(complex_package_elements),
- .elements = complex_package_elements,
- },
- },
- .buffer = {
- .data = expected_complex_package,
- .length = sizeof(expected_complex_package),
- },
- },
- };
- static void wmi_acpi_param_get_desc(const struct wmi_acpi_param *param, char *desc)
- {
- strscpy(desc, param->name, KUNIT_PARAM_DESC_SIZE);
- }
- KUNIT_ARRAY_PARAM(wmi_unmarshal_acpi_object, wmi_acpi_params_array, wmi_acpi_param_get_desc);
- /* "WMI\0" */
- static u8 padded_wmi_string[] = {
- 0x0a, 0x00,
- 0x57, 0x00,
- 0x4D, 0x00,
- 0x49, 0x00,
- 0x00, 0x00,
- 0x00, 0x00,
- };
- static const struct wmi_string_param wmi_string_params_array[] = {
- {
- .name = "test",
- .string = "TEST",
- .buffer = {
- .length = sizeof(expected_single_string),
- .data = expected_single_string,
- },
- },
- {
- .name = "padded",
- .string = "WMI",
- .buffer = {
- .length = sizeof(padded_wmi_string),
- .data = padded_wmi_string,
- },
- },
- };
- static void wmi_string_param_get_desc(const struct wmi_string_param *param, char *desc)
- {
- strscpy(desc, param->name, KUNIT_PARAM_DESC_SIZE);
- }
- KUNIT_ARRAY_PARAM(wmi_marshal_string, wmi_string_params_array, wmi_string_param_get_desc);
- static union acpi_object nested_package_elements[] = {
- {
- .package = {
- .type = ACPI_TYPE_PACKAGE,
- .count = ARRAY_SIZE(simple_package_elements),
- .elements = simple_package_elements,
- },
- }
- };
- static const struct wmi_invalid_acpi_param wmi_invalid_acpi_params_array[] = {
- {
- .name = "nested_package",
- .obj = {
- .package = {
- .type = ACPI_TYPE_PACKAGE,
- .count = ARRAY_SIZE(nested_package_elements),
- .elements = nested_package_elements,
- },
- },
- },
- {
- .name = "reference",
- .obj = {
- .reference = {
- .type = ACPI_TYPE_LOCAL_REFERENCE,
- .actual_type = ACPI_TYPE_ANY,
- .handle = NULL,
- },
- },
- },
- {
- .name = "processor",
- .obj = {
- .processor = {
- .type = ACPI_TYPE_PROCESSOR,
- .proc_id = 0,
- .pblk_address = 0,
- .pblk_length = 0,
- },
- },
- },
- {
- .name = "power_resource",
- .obj = {
- .power_resource = {
- .type = ACPI_TYPE_POWER,
- .system_level = 0,
- .resource_order = 0,
- },
- },
- },
- };
- static void wmi_invalid_acpi_param_get_desc(const struct wmi_invalid_acpi_param *param, char *desc)
- {
- strscpy(desc, param->name, KUNIT_PARAM_DESC_SIZE);
- }
- KUNIT_ARRAY_PARAM(wmi_unmarshal_acpi_object_failure, wmi_invalid_acpi_params_array,
- wmi_invalid_acpi_param_get_desc);
- static u8 oversized_wmi_string[] = {
- 0x04, 0x00, 0x00, 0x00,
- };
- /*
- * The error is that 3 bytes can not hold UTF-16 characters
- * without cutting of the last one.
- */
- static u8 undersized_wmi_string[] = {
- 0x03, 0x00, 0x00, 0x00, 0x00,
- };
- static u8 non_ascii_wmi_string[] = {
- 0x04, 0x00, 0xC4, 0x00, 0x00, 0x00,
- };
- static const struct wmi_invalid_string_param wmi_invalid_string_params_array[] = {
- {
- .name = "empty_buffer",
- .buffer = {
- .length = 0,
- .data = ZERO_SIZE_PTR,
- },
- },
- {
- .name = "oversized",
- .buffer = {
- .length = sizeof(oversized_wmi_string),
- .data = oversized_wmi_string,
- },
- },
- {
- .name = "undersized",
- .buffer = {
- .length = sizeof(undersized_wmi_string),
- .data = undersized_wmi_string,
- },
- },
- {
- .name = "non_ascii",
- .buffer = {
- .length = sizeof(non_ascii_wmi_string),
- .data = non_ascii_wmi_string,
- },
- },
- };
- static void wmi_invalid_string_param_get_desc(const struct wmi_invalid_string_param *param,
- char *desc)
- {
- strscpy(desc, param->name, KUNIT_PARAM_DESC_SIZE);
- }
- KUNIT_ARRAY_PARAM(wmi_marshal_string_failure, wmi_invalid_string_params_array,
- wmi_invalid_string_param_get_desc);
- KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *);
- static void wmi_unmarshal_acpi_object_test(struct kunit *test)
- {
- const struct wmi_acpi_param *param = test->param_value;
- struct wmi_buffer result;
- int ret;
- ret = wmi_unmarshal_acpi_object(¶m->obj, &result);
- if (ret < 0)
- KUNIT_FAIL_AND_ABORT(test, "Unmarshalling of ACPI object failed\n");
- kunit_add_action(test, kfree_wrapper, result.data);
- KUNIT_EXPECT_TRUE(test, IS_ALIGNED((uintptr_t)result.data, 8));
- KUNIT_EXPECT_EQ(test, result.length, param->buffer.length);
- KUNIT_EXPECT_MEMEQ(test, result.data, param->buffer.data, result.length);
- }
- static void wmi_unmarshal_acpi_object_failure_test(struct kunit *test)
- {
- const struct wmi_invalid_acpi_param *param = test->param_value;
- struct wmi_buffer result;
- int ret;
- ret = wmi_unmarshal_acpi_object(¶m->obj, &result);
- if (ret < 0)
- return;
- kfree(result.data);
- KUNIT_FAIL(test, "Invalid ACPI object was not rejected\n");
- }
- static void wmi_marshal_string_test(struct kunit *test)
- {
- const struct wmi_string_param *param = test->param_value;
- struct acpi_buffer result;
- int ret;
- ret = wmi_marshal_string(¶m->buffer, &result);
- if (ret < 0)
- KUNIT_FAIL_AND_ABORT(test, "Marshalling of WMI string failed\n");
- kunit_add_action(test, kfree_wrapper, result.pointer);
- KUNIT_EXPECT_EQ(test, result.length, strlen(param->string));
- KUNIT_EXPECT_STREQ(test, result.pointer, param->string);
- }
- static void wmi_marshal_string_failure_test(struct kunit *test)
- {
- const struct wmi_invalid_string_param *param = test->param_value;
- struct acpi_buffer result;
- int ret;
- ret = wmi_marshal_string(¶m->buffer, &result);
- if (ret < 0)
- return;
- kfree(result.pointer);
- KUNIT_FAIL(test, "Invalid string was not rejected\n");
- }
- static struct kunit_case wmi_marshalling_test_cases[] = {
- KUNIT_CASE_PARAM(wmi_unmarshal_acpi_object_test,
- wmi_unmarshal_acpi_object_gen_params),
- KUNIT_CASE_PARAM(wmi_marshal_string_test,
- wmi_marshal_string_gen_params),
- KUNIT_CASE_PARAM(wmi_unmarshal_acpi_object_failure_test,
- wmi_unmarshal_acpi_object_failure_gen_params),
- KUNIT_CASE_PARAM(wmi_marshal_string_failure_test,
- wmi_marshal_string_failure_gen_params),
- {}
- };
- static struct kunit_suite wmi_marshalling_test_suite = {
- .name = "wmi_marshalling",
- .test_cases = wmi_marshalling_test_cases,
- };
- kunit_test_suite(wmi_marshalling_test_suite);
- MODULE_AUTHOR("Armin Wolf <W_Armin@gmx.de>");
- MODULE_DESCRIPTION("KUnit test for the ACPI-WMI marshalling code");
- MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
- MODULE_LICENSE("GPL");
|