Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

platform/wmi: Add helper functions for WMI string conversions

WMI strings are encoded using UTF16-LE characters, forcing WMI drivers
to manually convert them to/from standard UTF8 strings. Add a two
helper functions for those tasks.

Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Link: https://patch.msgid.link/20260116204116.4030-4-W_Armin@gmx.de
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

authored by

Armin Wolf and committed by
Ilpo Järvinen
b990a06f 29dfba69

+102 -1
+3
Documentation/driver-api/wmi.rst
··· 16 16 .. kernel-doc:: include/linux/wmi.h 17 17 :internal: 18 18 19 + .. kernel-doc:: drivers/platform/wmi/string.c 20 + :export: 21 + 19 22 .. kernel-doc:: drivers/platform/wmi/core.c 20 23 :export:
+1
drivers/platform/wmi/Kconfig
··· 6 6 menuconfig ACPI_WMI 7 7 tristate "ACPI-WMI support" 8 8 depends on ACPI && X86 9 + select NLS 9 10 help 10 11 This option enables support for the ACPI-WMI driver core. 11 12
+1 -1
drivers/platform/wmi/Makefile
··· 4 4 # ACPI WMI core 5 5 # 6 6 7 - wmi-y := core.o marshalling.o 7 + wmi-y := core.o marshalling.o string.o 8 8 obj-$(CONFIG_ACPI_WMI) += wmi.o 9 9 10 10 # Unit tests
+92
drivers/platform/wmi/string.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * WMI string utility functions. 4 + * 5 + * Copyright (C) 2025 Armin Wolf <W_Armin@gmx.de> 6 + */ 7 + 8 + #include <linux/build_bug.h> 9 + #include <linux/compiler_types.h> 10 + #include <linux/err.h> 11 + #include <linux/export.h> 12 + #include <linux/nls.h> 13 + #include <linux/limits.h> 14 + #include <linux/types.h> 15 + #include <linux/wmi.h> 16 + 17 + #include <asm/byteorder.h> 18 + 19 + static_assert(sizeof(__le16) == sizeof(wchar_t)); 20 + 21 + /** 22 + * wmi_string_to_utf8s - Convert a WMI string into a UTF8 string. 23 + * @str: WMI string representation 24 + * @dst: Buffer to fill with UTF8 characters 25 + * @length: Length of the destination buffer 26 + * 27 + * Convert as WMI string into a standard UTF8 string. The conversion will stop 28 + * once a NUL character is detected or when the buffer is full. Any invalid UTF16 29 + * characters will be ignored. The resulting UTF8 string will always be NUL-terminated 30 + * when this function returns successfully. 31 + * 32 + * Return: Length of the resulting UTF8 string or negative errno code on failure. 33 + */ 34 + ssize_t wmi_string_to_utf8s(const struct wmi_string *str, u8 *dst, size_t length) 35 + { 36 + /* Contains the maximum number of UTF16 code points to read */ 37 + int inlen = le16_to_cpu(str->length) / 2; 38 + int ret; 39 + 40 + if (length < 1) 41 + return -EINVAL; 42 + 43 + /* We must leave room for the NUL character at the end of the destination buffer */ 44 + ret = utf16s_to_utf8s((__force const wchar_t *)str->chars, inlen, UTF16_LITTLE_ENDIAN, dst, 45 + length - 1); 46 + if (ret < 0) 47 + return ret; 48 + 49 + dst[ret] = '\0'; 50 + 51 + return ret; 52 + } 53 + EXPORT_SYMBOL_GPL(wmi_string_to_utf8s); 54 + 55 + /** 56 + * wmi_string_from_utf8s - Convert a UTF8 string into a WMI string. 57 + * @str: WMI string representation 58 + * @max_chars: Maximum number of UTF16 code points to store inside the WMI string 59 + * @src: UTF8 string to convert 60 + * @src_length: Length of the source string without any trailing NUL-characters 61 + * 62 + * Convert a UTF8 string into a WMI string. The conversion will stop when the WMI string is 63 + * full. The resulting WMI string will always be NUL-terminated and have its length field set 64 + * to and appropriate value when this function returns successfully. 65 + * 66 + * Return: Number of UTF16 code points inside the WMI string or negative errno code on failure. 67 + */ 68 + ssize_t wmi_string_from_utf8s(struct wmi_string *str, size_t max_chars, const u8 *src, 69 + size_t src_length) 70 + { 71 + size_t str_length; 72 + int ret; 73 + 74 + if (max_chars < 1) 75 + return -EINVAL; 76 + 77 + /* We must leave room for the NUL character at the end of the WMI string */ 78 + ret = utf8s_to_utf16s(src, src_length, UTF16_LITTLE_ENDIAN, (__force wchar_t *)str->chars, 79 + max_chars - 1); 80 + if (ret < 0) 81 + return ret; 82 + 83 + str_length = (ret + 1) * sizeof(u16); 84 + if (str_length > U16_MAX) 85 + return -EOVERFLOW; 86 + 87 + str->length = cpu_to_le16(str_length); 88 + str->chars[ret] = '\0'; 89 + 90 + return ret; 91 + } 92 + EXPORT_SYMBOL_GPL(wmi_string_from_utf8s);
+5
include/linux/wmi.h
··· 62 62 __le16 chars[]; 63 63 } __packed; 64 64 65 + ssize_t wmi_string_to_utf8s(const struct wmi_string *str, u8 *dst, size_t length); 66 + 67 + ssize_t wmi_string_from_utf8s(struct wmi_string *str, size_t max_chars, const u8 *src, 68 + size_t src_length); 69 + 65 70 int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id, 66 71 const struct wmi_buffer *in, struct wmi_buffer *out); 67 72