diff options
Diffstat (limited to 'Documentation/wmi/devices')
-rw-r--r-- | Documentation/wmi/devices/alienware-wmi.rst | 322 | ||||
-rw-r--r-- | Documentation/wmi/devices/dell-wmi-ddv.rst | 319 | ||||
-rw-r--r-- | Documentation/wmi/devices/index.rst | 22 | ||||
-rw-r--r-- | Documentation/wmi/devices/msi-wmi-platform.rst | 198 | ||||
-rw-r--r-- | Documentation/wmi/devices/wmi-bmof.rst | 25 |
5 files changed, 886 insertions, 0 deletions
diff --git a/Documentation/wmi/devices/alienware-wmi.rst b/Documentation/wmi/devices/alienware-wmi.rst new file mode 100644 index 000000000000..1d9d43e2e314 --- /dev/null +++ b/Documentation/wmi/devices/alienware-wmi.rst @@ -0,0 +1,322 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +============================================== +Dell AWCC WMI interface driver (alienware-wmi) +============================================== + +Introduction +============ + +The WMI device WMAX has been implemented for many Alienware and Dell's G-Series +models. Throughout these models, two implementations have been identified. The +first one, used by older systems, deals with HDMI, brightness, RGB, amplifier +and deep sleep control. The second one used by newer systems deals primarily +with thermal control and overclocking. + +It is suspected that the latter is used by Alienware Command Center (AWCC) to +manage manufacturer predefined thermal profiles. The alienware-wmi driver +exposes Thermal_Information and Thermal_Control methods through the Platform +Profile API to mimic AWCC's behavior. + +This newer interface, named AWCCMethodFunction has been reverse engineered, as +Dell has not provided any official documentation. We will try to describe to the +best of our ability its discovered inner workings. + +.. note:: + The following method description may be incomplete and some operations have + different implementations between devices. + +WMI interface description +------------------------- + +The WMI interface description can be decoded from the embedded binary MOF (bmof) +data using the `bmfdec <https://github.com/pali/bmfdec>`_ utility: + +:: + + [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); + }; + +Methods not described in the following document have unknown behavior. + +Argument Structure +------------------ + +All input arguments have type **uint32** and their structure is very similar +between methods. Usually, the first byte corresponds to a specific *operation* +the method performs, and the subsequent bytes correspond to *arguments* passed +to this *operation*. For example, if an operation has code 0x01 and requires an +ID 0xA0, the argument you would pass to the method is 0xA001. + + +Thermal Methods +=============== + +WMI method GetFanSensors([in] uint32 arg2, [out] uint32 argr) +------------------------------------------------------------- + ++--------------------+------------------------------------+--------------------+ +| Operation (Byte 0) | Description | Arguments | ++====================+====================================+====================+ +| 0x01 | Get the number of temperature | - Byte 1: Fan ID | +| | sensors related with a fan ID | | ++--------------------+------------------------------------+--------------------+ +| 0x02 | Get the temperature sensor IDs | - Byte 1: Fan ID | +| | related to a fan sensor ID | - Byte 2: Index | ++--------------------+------------------------------------+--------------------+ + +WMI method Thermal_Information([in] uint32 arg2, [out] uint32 argr) +------------------------------------------------------------------- + ++--------------------+------------------------------------+--------------------+ +| Operation (Byte 0) | Description | Arguments | ++====================+====================================+====================+ +| 0x01 | Unknown. | - None | ++--------------------+------------------------------------+--------------------+ +| 0x02 | Get system description number with | - None | +| | the following structure: | | +| | | | +| | - Byte 0: Number of fans | | +| | - Byte 1: Number of temperature | | +| | sensors | | +| | - Byte 2: Unknown | | +| | - Byte 3: Number of thermal | | +| | profiles | | ++--------------------+------------------------------------+--------------------+ +| 0x03 | List an ID or resource at a given | - Byte 1: Index | +| | index. Fan IDs, temperature IDs, | | +| | unknown IDs and thermal profile | | +| | IDs are listed in that exact | | +| | order. | | +| | | | +| | Operation 0x02 is used to know | | +| | which indexes map to which | | +| | resources. | | +| | | | +| | **Returns:** ID at a given index | | ++--------------------+------------------------------------+--------------------+ +| 0x04 | Get the current temperature for a | - Byte 1: Sensor | +| | given temperature sensor. | ID | ++--------------------+------------------------------------+--------------------+ +| 0x05 | Get the current RPM for a given | - Byte 1: Fan ID | +| | fan. | | ++--------------------+------------------------------------+--------------------+ +| 0x06 | Get fan speed percentage. (not | - Byte 1: Fan ID | +| | implemented in every model) | | ++--------------------+------------------------------------+--------------------+ +| 0x07 | Unknown. | - Unknown | ++--------------------+------------------------------------+--------------------+ +| 0x08 | Get minimum RPM for a given FAN | - Byte 1: Fan ID | +| | ID. | | ++--------------------+------------------------------------+--------------------+ +| 0x09 | Get maximum RPM for a given FAN | - Byte 1: Fan ID | +| | ID. | | ++--------------------+------------------------------------+--------------------+ +| 0x0A | Get balanced thermal profile ID. | - None | ++--------------------+------------------------------------+--------------------+ +| 0x0B | Get current thermal profile ID. | - None | ++--------------------+------------------------------------+--------------------+ +| 0x0C | Get current `boost` value for a | - Byte 1: Fan ID | +| | given fan ID. | | ++--------------------+------------------------------------+--------------------+ + +WMI method Thermal_Control([in] uint32 arg2, [out] uint32 argr) +--------------------------------------------------------------- + ++--------------------+------------------------------------+--------------------+ +| Operation (Byte 0) | Description | Arguments | ++====================+====================================+====================+ +| 0x01 | Activate a given thermal profile. | - Byte 1: Thermal | +| | | profile ID | ++--------------------+------------------------------------+--------------------+ +| 0x02 | Set a `boost` value for a given | - Byte 1: Fan ID | +| | fan ID. | - Byte 2: Boost | ++--------------------+------------------------------------+--------------------+ + +These are the known thermal profile codes: + ++------------------------------+----------+------+ +| Thermal Profile | Type | ID | ++==============================+==========+======+ +| Custom | Special | 0x00 | ++------------------------------+----------+------+ +| G-Mode | Special | 0xAB | ++------------------------------+----------+------+ +| Quiet | Legacy | 0x96 | ++------------------------------+----------+------+ +| Balanced | Legacy | 0x97 | ++------------------------------+----------+------+ +| Balanced Performance | Legacy | 0x98 | ++------------------------------+----------+------+ +| Performance | Legacy | 0x99 | ++------------------------------+----------+------+ +| Balanced | USTT | 0xA0 | ++------------------------------+----------+------+ +| Balanced Performance | USTT | 0xA1 | ++------------------------------+----------+------+ +| Cool | USTT | 0xA2 | ++------------------------------+----------+------+ +| Quiet | USTT | 0xA3 | ++------------------------------+----------+------+ +| Performance | USTT | 0xA4 | ++------------------------------+----------+------+ +| Low Power | USTT | 0xA5 | ++------------------------------+----------+------+ + +If a model supports the User Selectable Thermal Tables (USTT) profiles, it will +not support the Legacy profiles and vice-versa. + +Every model supports the CUSTOM (0x00) thermal profile. GMODE replaces +PERFORMANCE in G-Series laptops. + +WMI method GameShiftStatus([in] uint32 arg2, [out] uint32 argr) +--------------------------------------------------------------- + ++--------------------+------------------------------------+--------------------+ +| Operation (Byte 0) | Description | Arguments | ++====================+====================================+====================+ +| 0x01 | Toggle *Game Shift*. | - None | ++--------------------+------------------------------------+--------------------+ +| 0x02 | Get *Game Shift* status. | - None | ++--------------------+------------------------------------+--------------------+ + +Game Shift Status does not change the fan speed profile but it could be some +sort of CPU/GPU power profile. Benchmarks have not been done. + +This method is only present on Dell's G-Series laptops and it's implementation +implies GMODE thermal profile is available, even if operation 0x03 of +Thermal_Information does not list it. + +G-key on Dell's G-Series laptops also changes Game Shift status, so both are +directly related. + +Overclocking Methods +==================== + +WMI method MemoryOCControl([in] uint32 arg2, [out] uint32 argr) +--------------------------------------------------------------- + +AWCC supports memory overclocking, but this method is very intricate and has +not been deciphered yet. + +GPIO control Methods +==================== + +Alienware and Dell G Series devices with the AWCC interface usually have an +embedded STM32 RGB lighting controller with USB/HID capabilities. It's vendor ID +is ``187c`` while it's product ID may vary from model to model. + +The control of two GPIO pins of this MCU is exposed as WMI methods for debugging +purposes. + ++--------------+--------------------------------------------------------------+ +| Pin | Description | ++==============+===============================+==============================+ +| 0 | Device Firmware Update (DFU) | **HIGH**: Enables DFU mode | +| | mode pin. | on next MCU boot. | +| | +------------------------------+ +| | | **LOW**: Disables DFU mode | +| | | on next MCU boot. | ++--------------+-------------------------------+------------------------------+ +| 1 | Negative Reset (NRST) pin. | **HIGH**: MCU is ON. | +| | | | +| | +------------------------------+ +| | | **LOW**: MCU is OFF. | +| | | | ++--------------+-------------------------------+------------------------------+ + +See :ref:`acknowledgements` for more information on this MCU. + +.. note:: + Some GPIO control methods break the usual argument structure and take a + **Pin number** instead of an operation on the first byte. + +WMI method FWUpdateGPIOtoggle([in] uint32 arg2, [out] uint32 argr) +------------------------------------------------------------------ + ++--------------------+------------------------------------+--------------------+ +| Operation (Byte 0) | Description | Arguments | ++====================+====================================+====================+ +| Pin number | Set the pin status | - Byte 1: Pin | +| | | status | ++--------------------+------------------------------------+--------------------+ + +WMI method ReadTotalofGPIOs([out] uint32 argr) +---------------------------------------------- + ++--------------------+------------------------------------+--------------------+ +| Operation (Byte 0) | Description | Arguments | ++====================+====================================+====================+ +| N/A | Get the total number of GPIOs | - None | ++--------------------+------------------------------------+--------------------+ + +.. note:: + Due to how WMI methods are implemented on the firmware level, this method + requires a dummy uint32 input argument when invoked. + +WMI method ReadGPIOpPinStatus([in] uint32 arg2, [out] uint32 argr) +------------------------------------------------------------------ + ++--------------------+------------------------------------+--------------------+ +| Operation (Byte 0) | Description | Arguments | ++====================+====================================+====================+ +| Pin number | Get the pin status | - None | ++--------------------+------------------------------------+--------------------+ + +.. note:: + There known firmware bug in some laptops where reading the status of a pin + also flips it. + +Other information Methods +========================= + +WMI method ReadChassisColor([out] uint32 argr) +---------------------------------------------- + +Returns the chassis color internal ID. + +.. _acknowledgements: + +Acknowledgements +================ + +Kudos to + +* `AlexIII <https://github.com/AlexIII/tcc-g15>`_ +* `T-Troll <https://github.com/T-Troll/alienfx-tools/>`_ +* `Gabriel Marcano <https://gabriel.marcanobrady.family/blog/2024/12/16/dell-g5-5505-se-acpi-or-figuring-out-how-to-reset-the-rgb-controller/>`_ + +for documenting and testing some of this device's functionality, making it +possible to generalize this driver. diff --git a/Documentation/wmi/devices/dell-wmi-ddv.rst b/Documentation/wmi/devices/dell-wmi-ddv.rst new file mode 100644 index 000000000000..109d4c5c922e --- /dev/null +++ b/Documentation/wmi/devices/dell-wmi-ddv.rst @@ -0,0 +1,319 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +============================================ +Dell DDV WMI interface driver (dell-wmi-ddv) +============================================ + +Introduction +============ + +Many Dell notebooks made after ~2020 support a WMI-based interface for +retrieving various system data like battery temperature, ePPID, diagnostic data +and fan/thermal sensor data. + +This interface is likely used by the `Dell Data Vault` software on Windows, +so it was called `DDV`. Currently the ``dell-wmi-ddv`` driver supports +version 2 and 3 of the interface, with support for new interface versions +easily added. + +.. warning:: The interface is regarded as internal by Dell, so no vendor + documentation is available. All knowledge was thus obtained by + trial-and-error, please keep that in mind. + +Dell ePPID (electronic Piece Part Identification) +================================================= + +The Dell ePPID is used to uniquely identify components in Dell machines, +including batteries. It has a form similar to `CC-PPPPPP-MMMMM-YMD-SSSS-FFF` +and contains the following information: + +* Country code of origin (CC). +* Part number with the first character being a filling number (PPPPPP). +* Manufacture Identification (MMMMM). +* Manufacturing Year/Month/Date (YMD) in base 36, with Y being the last digit + of the year. +* Manufacture Sequence Number (SSSS). +* Optional Firmware Version/Revision (FFF). + +The `eppidtool <https://pypi.org/project/eppidtool>`_ python utility can be used +to decode and display this information. + +All information regarding the Dell ePPID was gathered using Dell support +documentation and `this website <https://telcontar.net/KBK/Dell/date_codes>`_. + +WMI interface description +========================= + +The WMI interface description can be decoded from the embedded binary MOF (bmof) +data using the `bmfdec <https://github.com/pali/bmfdec>`_ utility: + +:: + + [WMI, Dynamic, Provider("WmiProv"), Locale("MS\\0x409"), Description("WMI Function"), guid("{8A42EA14-4F2A-FD45-6422-0087F7A7E608}")] + class DDVWmiMethodFunction { + [key, read] string InstanceName; + [read] boolean Active; + + [WmiMethodId(1), Implemented, read, write, Description("Return Battery Design Capacity.")] void BatteryDesignCapacity([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(2), Implemented, read, write, Description("Return Battery Full Charge Capacity.")] void BatteryFullChargeCapacity([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(3), Implemented, read, write, Description("Return Battery Manufacture Name.")] void BatteryManufactureName([in] uint32 arg2, [out] string argr); + [WmiMethodId(4), Implemented, read, write, Description("Return Battery Manufacture Date.")] void BatteryManufactureDate([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(5), Implemented, read, write, Description("Return Battery Serial Number.")] void BatterySerialNumber([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(6), Implemented, read, write, Description("Return Battery Chemistry Value.")] void BatteryChemistryValue([in] uint32 arg2, [out] string argr); + [WmiMethodId(7), Implemented, read, write, Description("Return Battery Temperature.")] void BatteryTemperature([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(8), Implemented, read, write, Description("Return Battery Current.")] void BatteryCurrent([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(9), Implemented, read, write, Description("Return Battery Voltage.")] void BatteryVoltage([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(10), Implemented, read, write, Description("Return Battery Manufacture Access(MA code).")] void BatteryManufactureAceess([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(11), Implemented, read, write, Description("Return Battery Relative State-Of-Charge.")] void BatteryRelativeStateOfCharge([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(12), Implemented, read, write, Description("Return Battery Cycle Count")] void BatteryCycleCount([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(13), Implemented, read, write, Description("Return Battery ePPID")] void BatteryePPID([in] uint32 arg2, [out] string argr); + [WmiMethodId(14), Implemented, read, write, Description("Return Battery Raw Analytics Start")] void BatteryeRawAnalyticsStart([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(15), Implemented, read, write, Description("Return Battery Raw Analytics")] void BatteryeRawAnalytics([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); + [WmiMethodId(16), Implemented, read, write, Description("Return Battery Design Voltage.")] void BatteryDesignVoltage([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(17), Implemented, read, write, Description("Return Battery Raw Analytics A Block")] void BatteryeRawAnalyticsABlock([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); + [WmiMethodId(18), Implemented, read, write, Description("Return Version.")] void ReturnVersion([in] uint32 arg2, [out] uint32 argr); + [WmiMethodId(32), Implemented, read, write, Description("Return Fan Sensor Information")] void FanSensorInformation([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); + [WmiMethodId(34), Implemented, read, write, Description("Return Thermal Sensor Information")] void ThermalSensorInformation([in] uint32 arg2, [out] uint32 RawSize, [out, WmiSizeIs("RawSize") : ToInstance] uint8 RawData[]); + }; + +Each WMI method takes an ACPI buffer containing a 32-bit index as input argument, +with the first 8 bit being used to specify the battery when using battery-related +WMI methods. Other WMI methods may ignore this argument or interpret it +differently. The WMI method output format varies: + +* if the function has only a single output, then an ACPI object + of the corresponding type is returned +* if the function has multiple outputs, when an ACPI package + containing the outputs in the same order is returned + +The format of the output should be thoroughly checked, since many methods can +return malformed data in case of an error. + +The data format of many battery-related methods seems to be based on the +`Smart Battery Data Specification`, so unknown battery-related methods are +likely to follow this standard in some way. + +WMI method GetBatteryDesignCapacity() +------------------------------------- + +Returns the design capacity of the battery in mAh as an u16. + +WMI method BatteryFullCharge() +------------------------------ + +Returns the full charge capacity of the battery in mAh as an u16. + +WMI method BatteryManufactureName() +----------------------------------- + +Returns the manufacture name of the battery as an ASCII string. + +WMI method BatteryManufactureDate() +----------------------------------- + +Returns the manufacture date of the battery as an u16. +The date is encoded in the following manner: + +- bits 0 to 4 contain the manufacture day. +- bits 5 to 8 contain the manufacture month. +- bits 9 to 15 contain the manufacture year biased by 1980. + +WMI method BatterySerialNumber() +-------------------------------- + +Returns the serial number of the battery as an u16. + +WMI method BatteryChemistryValue() +---------------------------------- + +Returns the chemistry of the battery as an ASCII string. +Known values are: + +- "Li-I" for Li-Ion + +WMI method BatteryTemperature() +------------------------------- + +Returns the temperature of the battery in tenth degree kelvin as an u16. + +WMI method BatteryCurrent() +--------------------------- + +Returns the current flow of the battery in mA as an s16. +Negative values indicate discharging. + +WMI method BatteryVoltage() +--------------------------- + +Returns the voltage flow of the battery in mV as an u16. + +WMI method BatteryManufactureAccess() +------------------------------------- + +Returns the health status of the battery as a u16. +The health status encoded in the following manner: + + - the third nibble contains the general failure mode + - the fourth nibble contains the specific failure code + +Valid failure modes are: + + - permanent failure (``0x9``) + - overheat failure (``0xa``) + - overcurrent failure (``0xb``) + +All other failure modes are to be considered normal. + +The following failure codes are valid for a permanent failure: + + - fuse blown (``0x0``) + - cell imbalance (``0x1``) + - overvoltage (``0x2``) + - fet failure (``0x3``) + +The last two bits of the failure code are to be ignored when the battery +signals a permanent failure. + +The following failure codes a valid for a overheat failure: + + - overheat at start of charging (``0x5``) + - overheat during charging (``0x7``) + - overheat during discharging (``0x8``) + +The following failure codes are valid for a overcurrent failure: + + - overcurrent during charging (``0x6``) + - overcurrent during discharging (``0xb``) + +WMI method BatteryRelativeStateOfCharge() +----------------------------------------- + +Returns the capacity of the battery in percent as an u16. + +WMI method BatteryCycleCount() +------------------------------ + +Returns the cycle count of the battery as an u16. + +WMI method BatteryePPID() +------------------------- + +Returns the ePPID of the battery as an ASCII string. + +WMI method BatteryeRawAnalyticsStart() +-------------------------------------- + +Performs an analysis of the battery and returns a status code: + +- ``0x0``: Success +- ``0x1``: Interface not supported +- ``0xfffffffe``: Error/Timeout + +.. note:: + The meaning of this method is still largely unknown. + +WMI method BatteryeRawAnalytics() +--------------------------------- + +Returns a buffer usually containing 12 blocks of analytics data. +Those blocks contain: + +- a block number starting with 0 (u8) +- 31 bytes of unknown data + +.. note:: + The meaning of this method is still largely unknown. + +WMI method BatteryDesignVoltage() +--------------------------------- + +Returns the design voltage of the battery in mV as an u16. + +WMI method BatteryeRawAnalyticsABlock() +--------------------------------------- + +Returns a single block of analytics data, with the second byte +of the index being used for selecting the block number. + +*Supported since WMI interface version 3!* + +.. note:: + The meaning of this method is still largely unknown. + +WMI method ReturnVersion() +-------------------------- + +Returns the WMI interface version as an u32. + +WMI method FanSensorInformation() +--------------------------------- + +Returns a buffer containing fan sensor entries, terminated +with a single ``0xff``. +Those entries contain: + +- fan type (u8) +- fan speed in RPM (little endian u16) + +WMI method ThermalSensorInformation() +------------------------------------- + +Returns a buffer containing thermal sensor entries, terminated +with a single ``0xff``. +Those entries contain: + +- thermal type (u8) +- current temperature (s8) +- min. temperature (s8) +- max. temperature (s8) +- unknown field (u8) + +.. note:: + TODO: Find out what the meaning of the last byte is. + +ACPI battery matching algorithm +=============================== + +The algorithm used to match ACPI batteries to indices is based on information +which was found inside the logging messages of the OEM software. + +Basically for each new ACPI battery, the serial numbers of the batteries behind +indices 1 till 3 are compared with the serial number of the ACPI battery. +Since the serial number of the ACPI battery can either be encoded as a normal +integer or as a hexadecimal value, both cases need to be checked. The first +index with a matching serial number is then selected. + +A serial number of 0 indicates that the corresponding index is not associated +with an actual battery, or that the associated battery is not present. + +Some machines like the Dell Inspiron 3505 only support a single battery and thus +ignore the battery index. Because of this the driver depends on the ACPI battery +hook mechanism to discover batteries. + +Reverse-Engineering the DDV WMI interface +========================================= + +1. Find a supported Dell notebook, usually made after ~2020. +2. Dump the ACPI tables and search for the WMI device (usually called "ADDV"). +3. Decode the corresponding bmof data and look at the ASL code. +4. Try to deduce the meaning of a certain WMI method by comparing the control + flow with other ACPI methods (_BIX or _BIF for battery related methods + for example). +5. Use the built-in UEFI diagnostics to view sensor types/values for fan/thermal + related methods (sometimes overwriting static ACPI data fields can be used + to test different sensor type values, since on some machines this data is + not reinitialized upon a warm reset). + +Alternatively: + +1. Load the ``dell-wmi-ddv`` driver, use the ``force`` module param + if necessary. +2. Use the debugfs interface to access the raw fan/thermal sensor buffer data. +3. Compare the data with the built-in UEFI diagnostics. + +In case the DDV WMI interface version available on your Dell notebook is not +supported or you are seeing unknown fan/thermal sensors, please submit a +bugreport on `bugzilla <https://bugzilla.kernel.org>`_ so they can be added +to the ``dell-wmi-ddv`` driver. + +See Documentation/admin-guide/reporting-issues.rst for further information. diff --git a/Documentation/wmi/devices/index.rst b/Documentation/wmi/devices/index.rst new file mode 100644 index 000000000000..c08735a9d7df --- /dev/null +++ b/Documentation/wmi/devices/index.rst @@ -0,0 +1,22 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +============================= +Driver-specific Documentation +============================= + +This section provides information about various devices supported by +the Linux kernel, their protocols and driver details. + +.. toctree:: + :maxdepth: 1 + :numbered: + :glob: + + * + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/wmi/devices/msi-wmi-platform.rst b/Documentation/wmi/devices/msi-wmi-platform.rst new file mode 100644 index 000000000000..73197b31926a --- /dev/null +++ b/Documentation/wmi/devices/msi-wmi-platform.rst @@ -0,0 +1,198 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +=================================================== +MSI WMI Platform Features driver (msi-wmi-platform) +=================================================== + +Introduction +============ + +Many MSI notebooks support various features like reading fan sensors. This features are controlled +by the embedded controller, with the ACPI firmware exposing a standard ACPI WMI interface on top +of the embedded controller interface. + +WMI interface description +========================= + +The WMI interface description can be decoded from the embedded binary MOF (bmof) +data using the `bmfdec <https://github.com/pali/bmfdec>`_ utility: + +:: + + [WMI, Locale("MS\0x409"), + Description("This class contains the definition of the package used in other classes"), + guid("{ABBC0F60-8EA1-11d1-00A0-C90629100000}")] + class Package { + [WmiDataId(1), read, write, Description("16 bytes of data")] uint8 Bytes[16]; + }; + + [WMI, Locale("MS\0x409"), + Description("This class contains the definition of the package used in other classes"), + guid("{ABBC0F63-8EA1-11d1-00A0-C90629100000}")] + class Package_32 { + [WmiDataId(1), read, write, Description("32 bytes of data")] uint8 Bytes[32]; + }; + + [WMI, Dynamic, Provider("WmiProv"), Locale("MS\0x409"), + Description("Class used to operate methods on a package"), + guid("{ABBC0F6E-8EA1-11d1-00A0-C90629100000}")] + class MSI_ACPI { + [key, read] string InstanceName; + [read] boolean Active; + + [WmiMethodId(1), Implemented, read, write, Description("Return the contents of a package")] + void GetPackage([out, id(0)] Package Data); + + [WmiMethodId(2), Implemented, read, write, Description("Set the contents of a package")] + void SetPackage([in, id(0)] Package Data); + + [WmiMethodId(3), Implemented, read, write, Description("Return the contents of a package")] + void Get_EC([out, id(0)] Package_32 Data); + + [WmiMethodId(4), Implemented, read, write, Description("Set the contents of a package")] + void Set_EC([in, id(0)] Package_32 Data); + + [WmiMethodId(5), Implemented, read, write, Description("Return the contents of a package")] + void Get_BIOS([in, out, id(0)] Package_32 Data); + + [WmiMethodId(6), Implemented, read, write, Description("Set the contents of a package")] + void Set_BIOS([in, out, id(0)] Package_32 Data); + + [WmiMethodId(7), Implemented, read, write, Description("Return the contents of a package")] + void Get_SMBUS([in, out, id(0)] Package_32 Data); + + [WmiMethodId(8), Implemented, read, write, Description("Set the contents of a package")] + void Set_SMBUS([in, out, id(0)] Package_32 Data); + + [WmiMethodId(9), Implemented, read, write, Description("Return the contents of a package")] + void Get_MasterBattery([in, out, id(0)] Package_32 Data); + + [WmiMethodId(10), Implemented, read, write, Description("Set the contents of a package")] + void Set_MasterBattery([in, out, id(0)] Package_32 Data); + + [WmiMethodId(11), Implemented, read, write, Description("Return the contents of a package")] + void Get_SlaveBattery([in, out, id(0)] Package_32 Data); + + [WmiMethodId(12), Implemented, read, write, Description("Set the contents of a package")] + void Set_SlaveBattery([in, out, id(0)] Package_32 Data); + + [WmiMethodId(13), Implemented, read, write, Description("Return the contents of a package")] + void Get_Temperature([in, out, id(0)] Package_32 Data); + + [WmiMethodId(14), Implemented, read, write, Description("Set the contents of a package")] + void Set_Temperature([in, out, id(0)] Package_32 Data); + + [WmiMethodId(15), Implemented, read, write, Description("Return the contents of a package")] + void Get_Thermal([in, out, id(0)] Package_32 Data); + + [WmiMethodId(16), Implemented, read, write, Description("Set the contents of a package")] + void Set_Thermal([in, out, id(0)] Package_32 Data); + + [WmiMethodId(17), Implemented, read, write, Description("Return the contents of a package")] + void Get_Fan([in, out, id(0)] Package_32 Data); + + [WmiMethodId(18), Implemented, read, write, Description("Set the contents of a package")] + void Set_Fan([in, out, id(0)] Package_32 Data); + + [WmiMethodId(19), Implemented, read, write, Description("Return the contents of a package")] + void Get_Device([in, out, id(0)] Package_32 Data); + + [WmiMethodId(20), Implemented, read, write, Description("Set the contents of a package")] + void Set_Device([in, out, id(0)] Package_32 Data); + + [WmiMethodId(21), Implemented, read, write, Description("Return the contents of a package")] + void Get_Power([in, out, id(0)] Package_32 Data); + + [WmiMethodId(22), Implemented, read, write, Description("Set the contents of a package")] + void Set_Power([in, out, id(0)] Package_32 Data); + + [WmiMethodId(23), Implemented, read, write, Description("Return the contents of a package")] + void Get_Debug([in, out, id(0)] Package_32 Data); + + [WmiMethodId(24), Implemented, read, write, Description("Set the contents of a package")] + void Set_Debug([in, out, id(0)] Package_32 Data); + + [WmiMethodId(25), Implemented, read, write, Description("Return the contents of a package")] + void Get_AP([in, out, id(0)] Package_32 Data); + + [WmiMethodId(26), Implemented, read, write, Description("Set the contents of a package")] + void Set_AP([in, out, id(0)] Package_32 Data); + + [WmiMethodId(27), Implemented, read, write, Description("Return the contents of a package")] + void Get_Data([in, out, id(0)] Package_32 Data); + + [WmiMethodId(28), Implemented, read, write, Description("Set the contents of a package")] + void Set_Data([in, out, id(0)] Package_32 Data); + + [WmiMethodId(29), Implemented, read, write, Description("Return the contents of a package")] + void Get_WMI([out, id(0)] Package_32 Data); + }; + +Due to a peculiarity in how Windows handles the ``CreateByteField()`` ACPI operator (errors only +happen when a invalid byte field is ultimately accessed), all methods require a 32 byte input +buffer, even if the Binary MOF says otherwise. + +The input buffer contains a single byte to select the subfeature to be accessed and 31 bytes of +input data, the meaning of which depends on the subfeature being accessed. + +The output buffer contains a single byte which signals success or failure (``0x00`` on failure) +and 31 bytes of output data, the meaning if which depends on the subfeature being accessed. + +.. note:: + The ACPI control method responsible for handling the WMI method calls is not thread-safe. + This is a firmware bug that needs to be handled inside the driver itself. + +WMI method Get_EC() +------------------- + +Returns embedded controller information, the selected subfeature does not matter. The output +data contains a flag byte and a 28 byte controller firmware version string. + +The first 4 bits of the flag byte contain the minor version of the embedded controller interface, +with the next 2 bits containing the major version of the embedded controller interface. + +The 7th bit signals if the embedded controller page changed (exact meaning is unknown), and the +last bit signals if the platform is a Tigerlake platform. + +The MSI software seems to only use this interface when the last bit is set. + +WMI method Get_Fan() +-------------------- + +Fan speed sensors can be accessed by selecting subfeature ``0x00``. The output data contains +up to four 16-bit fan speed readings in big-endian format. Most machines do not support all +four fan speed sensors, so the remaining reading are hardcoded to ``0x0000``. + +The fan RPM readings can be calculated with the following formula: + + RPM = 480000 / <fan speed reading> + +If the fan speed reading is zero, then the fan RPM is zero too. + +WMI method Get_WMI() +-------------------- + +Returns the version of the ACPI WMI interface, the selected subfeature does not matter. +The output data contains two bytes, the first one contains the major version and the last one +contains the minor revision of the ACPI WMI interface. + +The MSI software seems to only use this interface when the major version is greater than two. + +Reverse-Engineering the MSI WMI Platform interface +================================================== + +.. warning:: Randomly poking the embedded controller interface can potentially cause damage + to the machine and other unwanted side effects, please be careful. + +The underlying embedded controller interface is used by the ``msi-ec`` driver, and it seems +that many methods just copy a part of the embedded controller memory into the output buffer. + +This means that the remaining WMI methods can be reverse-engineered by looking which part of +the embedded controller memory is accessed by the ACPI AML code. The driver also supports a +debugfs interface for directly executing WMI methods. Additionally, any safety checks regarding +unsupported hardware can be disabled by loading the module with ``force=true``. + +More information about the MSI embedded controller interface can be found at the +`msi-ec project <https://github.com/BeardOverflow/msi-ec>`_. + +Special thanks go to github user `glpnk` for showing how to decode the fan speed readings. diff --git a/Documentation/wmi/devices/wmi-bmof.rst b/Documentation/wmi/devices/wmi-bmof.rst new file mode 100644 index 000000000000..ca1ee9a29be3 --- /dev/null +++ b/Documentation/wmi/devices/wmi-bmof.rst @@ -0,0 +1,25 @@ +.. SPDX-License-Identifier: GPL-2.0-only + +============================== +WMI embedded Binary MOF driver +============================== + +Introduction +============ + +Many machines embed WMI Binary MOF (Managed Object Format) metadata used to +describe the details of their ACPI WMI interfaces. The data can be decoded +with tools like `bmfdec <https://github.com/pali/bmfdec>`_ to obtain a +human readable WMI interface description, which is useful for developing +new WMI drivers. + +The Binary MOF data can be retrieved from the ``bmof`` sysfs attribute of the +associated WMI device. Please note that multiple WMI devices containing Binary +MOF data can exist on a given system. + +WMI interface +============= + +The Binary MOF WMI device is identified by the WMI GUID ``05901221-D566-11D1-B2F0-00A0C9062910``. +The Binary MOF can be obtained by doing a WMI data block query. The result is +then returned as an ACPI buffer with a variable size. |