Add guarded WMI CMS (method 4) logo test tools
This commit is contained in:
parent
b9b81466c8
commit
f5211ec40b
5 changed files with 228 additions and 0 deletions
|
|
@ -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
30
tools/oxp-logo-wmi-cms-once.sh
Executable 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
|
||||
24
tools/oxp-wmi-cms-candidate-test.sh
Executable file
24
tools/oxp-wmi-cms-candidate-test.sh
Executable 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
29
tools/oxp-wmi-cms-scan.sh
Executable 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."
|
||||
144
tools/oxp-wmi-cms-write-once.c
Normal file
144
tools/oxp-wmi-cms-write-once.c
Normal 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");
|
||||
Loading…
Add table
Reference in a new issue