1. Dell AWCC WMI 接口驱动程序 (alienware-wmi)

1.1. 简介

WMI 设备 WMAX 已在许多 Alienware 和 Dell 的 G 系列型号中实现。在这些型号中,已识别出两种实现。第一个由较旧的系统使用,处理 HDMI、亮度、RGB、放大器和深度睡眠控制。第二个由较新的系统使用,主要处理散热、超频和 GPIO 控制。

据推测,后者由 Alienware Command Center (AWCC) 用于管理制造商预定义的散热配置文件。alienware-wmi 驱动程序通过平台配置文件 API 公开 Thermal_Information 和 Thermal_Control 方法,以模拟 AWCC 的行为。

这个较新的接口,名为 AWCCMethodFunction,已被逆向工程,因为 Dell 没有提供任何官方文档。我们将尽最大努力描述其已发现的内部工作原理。

注意

以下方法描述可能不完整,并且某些操作在不同设备之间具有不同的实现。

1.1.1. WMI 接口描述

可以使用 bmfdec 实用程序从嵌入式二进制 MOF (bmof) 数据中解码 WMI 接口描述

[WMI, Dynamic, Provider("WmiProv"), Locale("MS\\0x409"), Description("WMI Function"), guid("{A70591CE-A997-11DA-B012-B622A1EF5492}")]
class AWCCWmiMethodFunction {
  [key, read] string InstanceName;
  [read] boolean Active;

  [WmiMethodId(13), Implemented, read, write, Description("Return Overclocking Report.")] void Return_OverclockingReport([out] uint32 argr);
  [WmiMethodId(14), Implemented, read, write, Description("Set OCUIBIOS Control.")] void Set_OCUIBIOSControl([in] uint32 arg2, [out] uint32 argr);
  [WmiMethodId(15), Implemented, read, write, Description("Clear OC FailSafe Flag.")] void Clear_OCFailSafeFlag([out] uint32 argr);
  [WmiMethodId(19), Implemented, read, write, Description("Get Fan Sensors.")] void GetFanSensors([in] uint32 arg2, [out] uint32 argr);
  [WmiMethodId(20), Implemented, read, write, Description("Thermal Information.")] void Thermal_Information([in] uint32 arg2, [out] uint32 argr);
  [WmiMethodId(21), Implemented, read, write, Description("Thermal Control.")] void Thermal_Control([in] uint32 arg2, [out] uint32 argr);
  [WmiMethodId(23), Implemented, read, write, Description("MemoryOCControl.")] void MemoryOCControl([in] uint32 arg2, [out] uint32 argr);
  [WmiMethodId(26), Implemented, read, write, Description("System Information.")] void SystemInformation([in] uint32 arg2, [out] uint32 argr);
  [WmiMethodId(28), Implemented, read, write, Description("Power Information.")] void PowerInformation([in] uint32 arg2, [out] uint32 argr);
  [WmiMethodId(32), Implemented, read, write, Description("FW Update GPIO toggle.")] void FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr);
  [WmiMethodId(33), Implemented, read, write, Description("Read Total of GPIOs.")] void ReadTotalofGPIOs([out] uint32 argr);
  [WmiMethodId(34), Implemented, read, write, Description("Read GPIO pin Status.")] void ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr);
  [WmiMethodId(35), Implemented, read, write, Description("Read Chassis Color.")] void ReadChassisColor([out] uint32 argr);
  [WmiMethodId(36), Implemented, read, write, Description("Read Platform Properties.")] void ReadPlatformProperties([out] uint32 argr);
  [WmiMethodId(37), Implemented, read, write, Description("Game Shift Status.")] void GameShiftStatus([in] uint32 arg2, [out] uint32 argr);
  [WmiMethodId(128), Implemented, read, write, Description("Caldera SW installation.")] void CalderaSWInstallation([out] uint32 argr);
  [WmiMethodId(129), Implemented, read, write, Description("Caldera SW is released.")] void CalderaSWReleased([out] uint32 argr);
  [WmiMethodId(130), Implemented, read, write, Description("Caldera Connection Status.")] void CalderaConnectionStatus([in] uint32 arg2, [out] uint32 argr);
  [WmiMethodId(131), Implemented, read, write, Description("Surprise Unplugged Flag Status.")] void SurpriseUnpluggedFlagStatus([out] uint32 argr);
  [WmiMethodId(132), Implemented, read, write, Description("Clear Surprise Unplugged Flag.")] void ClearSurpriseUnpluggedFlag([out] uint32 argr);
  [WmiMethodId(133), Implemented, read, write, Description("Cancel Undock Request.")] void CancelUndockRequest([out] uint32 argr);
  [WmiMethodId(135), Implemented, read, write, Description("Devices in Caldera.")] void DevicesInCaldera([in] uint32 arg2, [out] uint32 argr);
  [WmiMethodId(136), Implemented, read, write, Description("Notify BIOS for SW ready to disconnect Caldera.")] void NotifyBIOSForSWReadyToDisconnectCaldera([out] uint32 argr);
  [WmiMethodId(160), Implemented, read, write, Description("Tobii SW installation.")] void TobiiSWinstallation([out] uint32 argr);
  [WmiMethodId(161), Implemented, read, write, Description("Tobii SW Released.")] void TobiiSWReleased([out] uint32 argr);
  [WmiMethodId(162), Implemented, read, write, Description("Tobii Camera Power Reset.")] void TobiiCameraPowerReset([out] uint32 argr);
  [WmiMethodId(163), Implemented, read, write, Description("Tobii Camera Power On.")] void TobiiCameraPowerOn([out] uint32 argr);
  [WmiMethodId(164), Implemented, read, write, Description("Tobii Camera Power Off.")] void TobiiCameraPowerOff([out] uint32 argr);
};

其中一些方法变得非常复杂,因此我们将使用大致类似于原始 ASL 代码的伪代码来描述它们。

以下文档中未描述的方法具有未知的行为。

1.1.2. 参数结构

所有输入参数都具有类型 uint32,并且它们在方法之间的结构非常相似。通常,第一个字节对应于方法执行的特定操作,随后的字节对应于传递给此操作参数。例如,如果操作的代码为 0x01 并且需要 ID 0xA0,则您将传递给方法的参数为 0xA001。

1.2. 散热方法

1.2.1. WMI 方法 Thermal_Information([in] uint32 arg2, [out] uint32 argr)

if BYTE_0(arg2) == 0x01:
        argr = 1

if BYTE_0(arg2) == 0x02:
        argr = SYSTEM_DESCRIPTION

if BYTE_0(arg2) == 0x03:
        if BYTE_1(arg2) == 0x00:
                argr = FAN_ID_0

        if BYTE_1(arg2) == 0x01:
                argr = FAN_ID_1

        if BYTE_1(arg2) == 0x02:
                argr = FAN_ID_2

        if BYTE_1(arg2) == 0x03:
                argr = FAN_ID_3

        if BYTE_1(arg2) == 0x04:
                argr = SENSOR_ID_CPU | 0x0100

        if BYTE_1(arg2) == 0x05:
                argr = SENSOR_ID_GPU | 0x0100

        if BYTE_1(arg2) == 0x06:
                argr = THERMAL_MODE_QUIET_ID

        if BYTE_1(arg2) == 0x07:
                argr = THERMAL_MODE_BALANCED_ID

        if BYTE_1(arg2) == 0x08:
                argr = THERMAL_MODE_BALANCED_PERFORMANCE_ID

        if BYTE_1(arg2) == 0x09:
                argr = THERMAL_MODE_PERFORMANCE_ID

        if BYTE_1(arg2) == 0x0A:
                argr = THERMAL_MODE_LOW_POWER_ID

        if BYTE_1(arg2) == 0x0B:
                argr = THERMAL_MODE_GMODE_ID

        else:
                argr = 0xFFFFFFFF

if BYTE_0(arg2) == 0x04:
        if is_valid_sensor(BYTE_1(arg2)):
                argr = SENSOR_TEMP_C
        else:
                argr = 0xFFFFFFFF

if BYTE_0(arg2) == 0x05:
        if is_valid_fan(BYTE_1(arg2)):
                argr = FAN_RPM()

if BYTE_0(arg2) == 0x06:
        skip

if BYTE_0(arg2) == 0x07:
        argr = 0

If BYTE_0(arg2) == 0x08:
        if is_valid_fan(BYTE_1(arg2)):
                argr = 0
        else:
                argr = 0xFFFFFFFF

if BYTE_0(arg2) == 0x09:
        if is_valid_fan(BYTE_1(arg2)):
                argr = FAN_UNKNOWN_STAT_0()

        else:
                argr = 0xFFFFFFFF

if BYTE_0(arg2) == 0x0A:
        argr = THERMAL_MODE_BALANCED_ID

if BYTE_0(arg2) == 0x0B:
        argr = CURRENT_THERMAL_MODE()

if BYTE_0(arg2) == 0x0C:
        if is_valid_fan(BYTE_1(arg2)):
                argr = FAN_UNKNOWN_STAT_1()
        else:
                argr = 0xFFFFFFFF

操作 0x02 返回具有以下结构的系统描述缓冲区

out[0] -> Number of fans
out[1] -> Number of sensors
out[2] -> 0x00
out[3] -> Number of thermal modes

操作 0x03 按顺序列出所有可用的风扇 ID、传感器 ID 和散热配置文件代码,但不同的型号可能具有不同数量的风扇和散热配置文件。以下是已知的范围

  • 风扇 ID:从 2 到 4

  • 传感器 ID:2

  • 散热配置文件代码:从 1 到 7

总共,BYTE_1(ARG2) 的范围可能从 0x5 到 0xD,具体取决于型号。

1.2.2. WMI 方法 Thermal_Control([in] uint32 arg2, [out] uint32 argr)

if BYTE_0(arg2) == 0x01:
        if is_valid_thermal_profile(BYTE_1(arg2)):
                SET_THERMAL_PROFILE(BYTE_1(arg2))
                argr = 0

if BYTE_0(arg2) == 0x02:
        if is_valid_fan(BYTE_1(arg2)):
                SET_FAN_SPEED_MULTIPLIER(BYTE_2(arg2))
                argr = 0
        else:
                argr = 0xFFFFFFFF

注意

虽然您可以使用此方法手动更改风扇速度倍增器,但 Dell 的 BIOS 往往会覆盖这些更改。

以下是已知的散热配置文件代码

CUSTOM                         0x00

BALANCED_USTT                  0xA0
BALANCED_PERFORMANCE_USTT      0xA1
COOL_USTT                      0xA2
QUIET_USTT                     0xA3
PERFORMANCE_USTT               0xA4
LOW_POWER_USTT                 0xA5

QUIET                          0x96
BALANCED                       0x97
BALANCED_PERFORMANCE           0x98
PERFORMANCE                    0x99

GMODE                          0xAB

通常,如果型号不支持前四个配置文件,它们将支持用户可选散热表 (USTT) 配置文件,反之亦然。

GMODE 取代了 G 系列笔记本电脑中的 PERFORMANCE。

1.2.3. WMI 方法 GameShiftStatus([in] uint32 arg2, [out] uint32 argr)

if BYTE_0(arg2) == 0x1:
        TOGGLE_GAME_SHIFT()
        argr = GET_GAME_SHIFT_STATUS()

if BYTE_0(arg2) == 0x2:
        argr = GET_GAME_SHIFT_STATUS()

Game Shift Status 不会更改风扇速度配置文件,但它可能是某种 CPU/GPU 电源配置文件。尚未进行基准测试。

此方法仅存在于 Dell 的 G 系列笔记本电脑上,并且其实现暗示 GMODE 散热配置文件可用,即使 Thermal_Information 的操作 0x03 没有列出它。

Dell G 系列笔记本电脑上的 G 键也会更改 Game Shift 状态,因此两者直接相关。

1.2.4. WMI 方法 GetFanSensors([in] uint32 arg2, [out] uint32 argr)

if BYTE_0(arg2) == 0x1:
       if is_valid_fan(BYTE_1(arg2)):
               argr = 1
       else:
               argr = 0

if BYTE_0(arg2) == 0x2:
       if is_valid_fan(BYTE_1(arg2)):
               if BYTE_2(arg2) == 0:
                       argr == SENSOR_ID
               else
                       argr == 0xFFFFFFFF
       else:
               argr = 0

1.3. 超频方法

警告

这些方法尚未经过测试,并且仅部分经过逆向工程。

1.3.1. WMI 方法 Return_OverclockingReport([out] uint32 argr)

CSMI (0xE3, 0x99)
argr = 0

CSMI 是一种未知操作。

1.3.2. WMI 方法 Set_OCUIBIOSControl([in] uint32 arg2, [out] uint32 argr)

CSMI (0xE3, 0x99)
argr = 0

CSMI 是一种未知操作。

1.3.3. WMI 方法 Clear_OCFailSafeFlag([out] uint32 argr)

CSMI (0xE3, 0x99)
argr = 0

CSMI 是一种未知操作。

1.3.4. WMI 方法 MemoryOCControl([in] uint32 arg2, [out] uint32 argr)

AWCC 支持内存超频,但此方法非常复杂,尚未被破译。

1.4. GPIO 方法

这些方法可能与通过 GPIO 设备进行的某种固件更新系统有关。

警告

这些方法尚未经过测试,并且仅部分经过逆向工程。

1.4.1. WMI 方法 FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr)

if BYTE_0(arg2) == 0:
        if BYTE_1(arg2) == 1:
                SET_PIN_A_HIGH()
        else:
                SET_PIN_A_LOW()

if BYTE_0(arg2) == 1:
        if BYTE_1(arg2) == 1:
                SET_PIN_B_HIGH()

        else:
                SET_PIN_B_LOW()

else:
        argr = 1

1.4.2. WMI 方法 ReadTotalofGPIOs([out] uint32 argr)

argr = 0x02

1.4.3. WMI 方法 ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr)

if BYTE_0(arg2) == 0:
        argr = PIN_A_STATUS

if BYTE_0(arg2) == 1:
        argr = PIN_B_STATUS

1.5. 其他信息方法

1.5.1. WMI 方法 ReadChassisColor([out] uint32 argr)

argr = CHASSIS_COLOR_ID

1.6. 致谢

感谢 AlexIII 记录和测试可用的散热配置文件代码。