Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,27 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# ACPI WMI KUnit tests
#
config ACPI_WMI_MARSHALLING_KUNIT_TEST
tristate "KUnit Test for ACPI-WMI marshalling" if !KUNIT_ALL_TESTS
depends on KUNIT
default KUNIT_ALL_TESTS
help
This builds unit tests for the ACPI-WMI marshalling code.
For more information on KUnit and unit tests in general, please refer
to the KUnit documentation in Documentation/dev-tools/kunit/.
If unsure, say N.
config ACPI_WMI_STRING_KUNIT_TEST
tristate "KUnit Test for ACPI-WMI string conversion" if !KUNIT_ALL_TESTS
depends on KUNIT
default KUNIT_ALL_TESTS
help
This builds unit tests for the ACPI-WMI string conversion code.
For more information on KUnit and unit tests in general, please refer
to the KUnit documentation in Documentation/dev-tools/kunit/.
If unsure, say N.
@@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Makefile for linux/drivers/platform/x86/wmi/tests
# ACPI WMI KUnit tests
#
wmi_marshalling_kunit-y := marshalling_kunit.o
obj-$(CONFIG_ACPI_WMI_MARSHALLING_KUNIT_TEST) += wmi_marshalling_kunit.o
wmi_string_kunit-y := string_kunit.o
obj-$(CONFIG_ACPI_WMI_STRING_KUNIT_TEST) += wmi_string_kunit.o
@@ -0,0 +1,472 @@
// 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(&param->obj, &result, param->buffer.length);
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(&param->obj, &result, 0);
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(&param->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(&param->buffer, &result);
if (ret < 0)
return;
kfree(result.pointer);
KUNIT_FAIL(test, "Invalid string was not rejected\n");
}
static void wmi_unmarshal_acpi_object_undersized_test(struct kunit *test)
{
const union acpi_object obj = {
.integer = {
.type = ACPI_TYPE_INTEGER,
.value = 0xdeadbeef,
},
};
struct wmi_buffer result;
int ret;
ret = wmi_unmarshal_acpi_object(&obj, &result, sizeof(expected_single_integer) + 1);
if (ret < 0)
return;
kfree(result.data);
KUNIT_FAIL(test, "Undersized unmarshalling result 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),
KUNIT_CASE(wmi_unmarshal_acpi_object_undersized_test),
{}
};
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");
@@ -0,0 +1,296 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* KUnit test for the ACPI-WMI string conversion code.
*
* Copyright (C) 2025 Armin Wolf <W_Armin@gmx.de>
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/wmi.h>
#include <kunit/resource.h>
#include <kunit/test.h>
#include <asm/byteorder.h>
struct wmi_string_param {
const char *name;
const struct wmi_string *wmi_string;
/*
* Remember that using sizeof() on a struct wmi_string will
* always return a size of two bytes due to the flexible
* array member!
*/
size_t wmi_string_length;
const u8 *utf8_string;
size_t utf8_string_length;
};
#define TEST_WMI_STRING_LENGTH 12
static const struct wmi_string test_wmi_string = {
.length = cpu_to_le16(10),
.chars = {
cpu_to_le16(u'T'),
cpu_to_le16(u'E'),
cpu_to_le16(u'S'),
cpu_to_le16(u'T'),
cpu_to_le16(u'\0'),
},
};
static const u8 test_utf8_string[] = "TEST";
#define SPECIAL_WMI_STRING_LENGTH 14
static const struct wmi_string special_wmi_string = {
.length = cpu_to_le16(12),
.chars = {
cpu_to_le16(u'Ä'),
cpu_to_le16(u'Ö'),
cpu_to_le16(u'Ü'),
cpu_to_le16(u'ß'),
cpu_to_le16(u'€'),
cpu_to_le16(u'\0'),
},
};
static const u8 special_utf8_string[] = "ÄÖÜ߀";
#define MULTI_POINT_WMI_STRING_LENGTH 12
static const struct wmi_string multi_point_wmi_string = {
.length = cpu_to_le16(10),
.chars = {
cpu_to_le16(u'K'),
/* 🐧 */
cpu_to_le16(0xD83D),
cpu_to_le16(0xDC27),
cpu_to_le16(u'!'),
cpu_to_le16(u'\0'),
},
};
static const u8 multi_point_utf8_string[] = "K🐧!";
#define PADDED_TEST_WMI_STRING_LENGTH 14
static const struct wmi_string padded_test_wmi_string = {
.length = cpu_to_le16(12),
.chars = {
cpu_to_le16(u'T'),
cpu_to_le16(u'E'),
cpu_to_le16(u'S'),
cpu_to_le16(u'T'),
cpu_to_le16(u'\0'),
cpu_to_le16(u'\0'),
},
};
static const u8 padded_test_utf8_string[] = "TEST\0";
#define OVERSIZED_TEST_WMI_STRING_LENGTH 14
static const struct wmi_string oversized_test_wmi_string = {
.length = cpu_to_le16(8),
.chars = {
cpu_to_le16(u'T'),
cpu_to_le16(u'E'),
cpu_to_le16(u'S'),
cpu_to_le16(u'T'),
cpu_to_le16(u'!'),
cpu_to_le16(u'\0'),
},
};
static const u8 oversized_test_utf8_string[] = "TEST!";
#define INVALID_TEST_WMI_STRING_LENGTH 14
static const struct wmi_string invalid_test_wmi_string = {
.length = cpu_to_le16(12),
.chars = {
cpu_to_le16(u'T'),
/* 🐧, with low surrogate missing */
cpu_to_le16(0xD83D),
cpu_to_le16(u'E'),
cpu_to_le16(u'S'),
cpu_to_le16(u'T'),
cpu_to_le16(u'\0'),
},
};
/* We have to split the string here to end the hex escape sequence */
static const u8 invalid_test_utf8_string[] = "T" "\xF0\x9F" "EST";
static const struct wmi_string_param wmi_string_params_array[] = {
{
.name = "ascii_string",
.wmi_string = &test_wmi_string,
.wmi_string_length = TEST_WMI_STRING_LENGTH,
.utf8_string = test_utf8_string,
.utf8_string_length = sizeof(test_utf8_string),
},
{
.name = "special_string",
.wmi_string = &special_wmi_string,
.wmi_string_length = SPECIAL_WMI_STRING_LENGTH,
.utf8_string = special_utf8_string,
.utf8_string_length = sizeof(special_utf8_string),
},
{
.name = "multi_point_string",
.wmi_string = &multi_point_wmi_string,
.wmi_string_length = MULTI_POINT_WMI_STRING_LENGTH,
.utf8_string = multi_point_utf8_string,
.utf8_string_length = sizeof(multi_point_utf8_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_string, wmi_string_params_array, wmi_string_param_get_desc);
static void wmi_string_to_utf8s_test(struct kunit *test)
{
const struct wmi_string_param *param = test->param_value;
ssize_t ret;
u8 *result;
result = kunit_kzalloc(test, param->utf8_string_length, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, result);
ret = wmi_string_to_utf8s(param->wmi_string, result, param->utf8_string_length);
KUNIT_EXPECT_EQ(test, ret, param->utf8_string_length - 1);
KUNIT_EXPECT_MEMEQ(test, result, param->utf8_string, param->utf8_string_length);
}
static void wmi_string_from_utf8s_test(struct kunit *test)
{
const struct wmi_string_param *param = test->param_value;
struct wmi_string *result;
size_t max_chars;
ssize_t ret;
max_chars = (param->wmi_string_length - sizeof(*result)) / 2;
result = kunit_kzalloc(test, param->wmi_string_length, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, result);
ret = wmi_string_from_utf8s(result, max_chars, param->utf8_string,
param->utf8_string_length);
KUNIT_EXPECT_EQ(test, ret, max_chars - 1);
KUNIT_EXPECT_MEMEQ(test, result, param->wmi_string, param->wmi_string_length);
}
static void wmi_string_to_utf8s_padded_test(struct kunit *test)
{
u8 result[sizeof(padded_test_utf8_string)];
ssize_t ret;
ret = wmi_string_to_utf8s(&padded_test_wmi_string, result, sizeof(result));
KUNIT_EXPECT_EQ(test, ret, sizeof(test_utf8_string) - 1);
KUNIT_EXPECT_MEMEQ(test, result, test_utf8_string, sizeof(test_utf8_string));
}
static void wmi_string_from_utf8s_padded_test(struct kunit *test)
{
struct wmi_string *result;
size_t max_chars;
ssize_t ret;
max_chars = (PADDED_TEST_WMI_STRING_LENGTH - sizeof(*result)) / 2;
result = kunit_kzalloc(test, PADDED_TEST_WMI_STRING_LENGTH, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, result);
ret = wmi_string_from_utf8s(result, max_chars, padded_test_utf8_string,
sizeof(padded_test_utf8_string));
KUNIT_EXPECT_EQ(test, ret, sizeof(test_utf8_string) - 1);
KUNIT_EXPECT_MEMEQ(test, result, &test_wmi_string, sizeof(test_wmi_string));
}
static void wmi_string_to_utf8s_oversized_test(struct kunit *test)
{
u8 result[sizeof(oversized_test_utf8_string)];
ssize_t ret;
ret = wmi_string_to_utf8s(&oversized_test_wmi_string, result, sizeof(result));
KUNIT_EXPECT_EQ(test, ret, sizeof(test_utf8_string) - 1);
KUNIT_EXPECT_MEMEQ(test, result, test_utf8_string, sizeof(test_utf8_string));
}
static void wmi_string_from_utf8s_oversized_test(struct kunit *test)
{
struct wmi_string *result;
size_t max_chars;
ssize_t ret;
max_chars = (TEST_WMI_STRING_LENGTH - sizeof(*result)) / 2;
result = kunit_kzalloc(test, TEST_WMI_STRING_LENGTH, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, result);
ret = wmi_string_from_utf8s(result, max_chars, oversized_test_utf8_string,
sizeof(oversized_test_utf8_string));
KUNIT_EXPECT_EQ(test, ret, sizeof(test_utf8_string) - 1);
KUNIT_EXPECT_MEMEQ(test, result, &test_wmi_string, sizeof(test_wmi_string));
}
static void wmi_string_to_utf8s_invalid_test(struct kunit *test)
{
u8 result[sizeof(invalid_test_utf8_string)];
ssize_t ret;
ret = wmi_string_to_utf8s(&invalid_test_wmi_string, result, sizeof(result));
KUNIT_EXPECT_EQ(test, ret, sizeof(test_utf8_string) - 1);
KUNIT_EXPECT_MEMEQ(test, result, test_utf8_string, sizeof(test_utf8_string));
}
static void wmi_string_from_utf8s_invalid_test(struct kunit *test)
{
struct wmi_string *result;
size_t max_chars;
ssize_t ret;
max_chars = (INVALID_TEST_WMI_STRING_LENGTH - sizeof(*result)) / 2;
result = kunit_kzalloc(test, INVALID_TEST_WMI_STRING_LENGTH, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, result);
ret = wmi_string_from_utf8s(result, max_chars, invalid_test_utf8_string,
sizeof(invalid_test_utf8_string));
KUNIT_EXPECT_EQ(test, ret, -EINVAL);
}
static struct kunit_case wmi_string_test_cases[] = {
KUNIT_CASE_PARAM(wmi_string_to_utf8s_test, wmi_string_gen_params),
KUNIT_CASE_PARAM(wmi_string_from_utf8s_test, wmi_string_gen_params),
KUNIT_CASE(wmi_string_to_utf8s_padded_test),
KUNIT_CASE(wmi_string_from_utf8s_padded_test),
KUNIT_CASE(wmi_string_to_utf8s_oversized_test),
KUNIT_CASE(wmi_string_from_utf8s_oversized_test),
KUNIT_CASE(wmi_string_to_utf8s_invalid_test),
KUNIT_CASE(wmi_string_from_utf8s_invalid_test),
{}
};
static struct kunit_suite wmi_string_test_suite = {
.name = "wmi_string",
.test_cases = wmi_string_test_cases,
};
kunit_test_suite(wmi_string_test_suite);
MODULE_AUTHOR("Armin Wolf <W_Armin@gmx.de>");
MODULE_DESCRIPTION("KUnit test for the ACPI-WMI string conversion code");
MODULE_LICENSE("GPL");