Add guarded WMI CMS (method 4) logo test tools

This commit is contained in:
Hermes 2026-05-11 21:12:17 +02:00
parent b9b81466c8
commit f5211ec40b
5 changed files with 228 additions and 0 deletions

View file

@ -1,3 +1,4 @@
obj-m += oxp-wmi-ec-read.o
obj-m += oxp-ec-write-once.o
obj-m += oxp-wmi-write-once.o
obj-m += oxp-wmi-cms-write-once.o

30
tools/oxp-logo-wmi-cms-once.sh Executable file
View file

@ -0,0 +1,30 @@
#!/usr/bin/env bash
# Guarded one-shot test for SuperX logo candidates via OneX WMI CMS method 4.
set -euo pipefail
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
REPO_DIR=$(cd -- "$SCRIPT_DIR/.." && pwd)
MODULE="$SCRIPT_DIR/oxp-wmi-cms-write-once.ko"
ADDR=${1:-0xF0}
VALUE=${2:-0x01}
if [[ ! -f "$MODULE" ]]; then
echo "module not found: $MODULE" >&2
echo "build it with: make -C /lib/modules/$(uname -r)/build M=$SCRIPT_DIR modules" >&2
exit 1
fi
cleanup() {
if lsmod | awk '{print $1}' | grep -qx 'oxp_wmi_cms_write_once'; then
sudo rmmod oxp_wmi_cms_write_once || true
fi
}
trap cleanup EXIT
cd "$REPO_DIR"
echo "About to write OneX WMI CMS addr ${ADDR}=${VALUE} once. This is low-level hardware control."
sudo insmod "$MODULE" addr="$ADDR" value="$VALUE" yes_i_understand_this_writes_to_hardware=1
sleep 0.2
sudo dmesg --ctime | tail -120 | grep 'oxp-wmi-cms-write-once' || true
cleanup
trap - EXIT

View file

@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Interactive guarded test for one OneX WMI CMS byte.
set -euo pipefail
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
WRITER="$SCRIPT_DIR/oxp-logo-wmi-cms-once.sh"
ADDR=${1:?usage: $0 <addr> <value> [label]}
VALUE=${2:?usage: $0 <addr> <value> [label]}
LABEL=${3:-cms-candidate}
echo "[${LABEL}] testing CMS ${ADDR}=${VALUE}"
"$WRITER" "$ADDR" "$VALUE"
echo
read -r -p "Did the deckel RGB change? Type 'keep' to keep; Enter reverts. [revert/keep] " answer
case "${answer,,}" in
keep)
echo "Keeping ${ADDR}=${VALUE}."
;;
*)
echo "Reverting ${ADDR}=0x00."
"$WRITER" "$ADDR" 0x00
;;
esac

29
tools/oxp-wmi-cms-scan.sh Executable file
View file

@ -0,0 +1,29 @@
#!/usr/bin/env bash
# Scan WMI CMS bytes with revert-by-default.
set -euo pipefail
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
TESTER="$SCRIPT_DIR/oxp-wmi-cms-candidate-test.sh"
START=${1:-0xF0}
END=${2:-0xFF}
LABEL=${3:-deckel-cms}
values=(0x00 0x01 0x02 0x04 0x08 0x10 0x20 0x40 0x80 0xff)
start_dec=$((START))
end_dec=$((END))
(( start_dec <= end_dec )) || { echo "start must be <= end" >&2; exit 1; }
echo "Scanning CMS offsets ${START}..${END} (label=${LABEL})"
echo "Type 'keep' only if deckel RGB visibly changes."
for ((a=start_dec; a<=end_dec; a++)); do
addr=$(printf '0x%X' "$a")
for v in "${values[@]}"; do
echo
echo "=== TEST addr=${addr} value=${v} ==="
"$TESTER" "$addr" "$v" "$LABEL"
done
done
echo "Done."

View file

@ -0,0 +1,144 @@
// SPDX-License-Identifier: GPL-2.0
/*
* OneXPlayer Super X guarded one-shot WMI CMS writer.
*
* ACPI WMBB dispatch:
* MethodId 3: CMSR(addr) read
* MethodId 4: CMSW(addr, value) write then read
*/
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/types.h>
#define OXP_UMA_WMI_GUID "1F72B0F1-BFEA-4472-9877-6E62937AB616"
#define OXP_WMI_METHOD_CMS_READ 3
#define OXP_WMI_METHOD_CMS_WRITE 4
static uint addr = 0xF0;
static uint value = 0x01;
static bool yes_i_understand_this_writes_to_hardware;
module_param(addr, uint, 0444);
MODULE_PARM_DESC(addr, "CMS byte address to write, default 0xF0");
module_param(value, uint, 0444);
MODULE_PARM_DESC(value, "Byte value to write, default 0x01");
module_param(yes_i_understand_this_writes_to_hardware, bool, 0444);
MODULE_PARM_DESC(yes_i_understand_this_writes_to_hardware, "Required safety acknowledgement");
static const struct dmi_system_id dmi_table[] = {
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER SUPER X"),
},
},
{},
};
static int oxp_wmi_call(u8 method_id, u8 a, u8 v, u64 *out_value)
{
u8 inbuf[4] = { a, 0x00, v, 0x00 };
struct acpi_buffer input = {
.length = sizeof(inbuf),
.pointer = inbuf,
};
union acpi_object *obj;
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_status status;
int ret = 0;
status = wmi_evaluate_method(OXP_UMA_WMI_GUID, 0, method_id, &input, &output);
if (ACPI_FAILURE(status))
return -EIO;
obj = output.pointer;
if (!obj) {
ret = -ENODATA;
goto out;
}
switch (obj->type) {
case ACPI_TYPE_INTEGER:
*out_value = obj->integer.value;
break;
case ACPI_TYPE_BUFFER:
if (obj->buffer.length < 1) {
ret = -ENODATA;
break;
}
*out_value = obj->buffer.pointer[0];
break;
default:
ret = -EPROTO;
break;
}
out:
kfree(output.pointer);
return ret;
}
static int __init oxp_wmi_cms_write_once_init(void)
{
u64 before = 0;
u64 after = 0;
int ret;
if (!dmi_first_match(dmi_table)) {
pr_err("oxp-wmi-cms-write-once: refusing: not ONEXPLAYER SUPER X\n");
return -ENODEV;
}
if (!yes_i_understand_this_writes_to_hardware) {
pr_err("oxp-wmi-cms-write-once: refusing: set yes_i_understand_this_writes_to_hardware=1\n");
return -EPERM;
}
if (addr > 0xff || value > 0xff) {
pr_err("oxp-wmi-cms-write-once: refusing: addr/value must be bytes\n");
return -EINVAL;
}
if (wmi_instance_count(OXP_UMA_WMI_GUID) <= 0) {
pr_err("oxp-wmi-cms-write-once: refusing: OneX WMI GUID not present\n");
return -ENODEV;
}
ret = oxp_wmi_call(OXP_WMI_METHOD_CMS_READ, (u8)addr, 0, &before);
if (ret) {
pr_err("oxp-wmi-cms-write-once: pre-read [0x%02x] failed ret=%d\n", addr, ret);
return ret;
}
pr_warn("oxp-wmi-cms-write-once: WMI CMS write [0x%02x] 0x%02llx -> 0x%02x\n",
addr, before & 0xff, value);
ret = oxp_wmi_call(OXP_WMI_METHOD_CMS_WRITE, (u8)addr, (u8)value, &after);
if (ret) {
pr_err("oxp-wmi-cms-write-once: write [0x%02x]=0x%02x failed ret=%d\n",
addr, value, ret);
return ret;
}
pr_warn("oxp-wmi-cms-write-once: returned/readback [0x%02x]=0x%02llx\n",
addr, after & 0xff);
return 0;
}
static void __exit oxp_wmi_cms_write_once_exit(void)
{
pr_info("oxp-wmi-cms-write-once: unloaded\n");
}
module_init(oxp_wmi_cms_write_once_init);
module_exit(oxp_wmi_cms_write_once_exit);
MODULE_AUTHOR("Hermes");
MODULE_DESCRIPTION("Guarded one-shot OneXPlayer Super X WMI CMS byte writer");
MODULE_LICENSE("GPL");