xref: /linux/Documentation/wmi/devices/msi-wmi-platform.rst (revision 74f1af95820fc2ee580a775a3a17c416db30b38c)
19c0beb6bSArmin Wolf.. SPDX-License-Identifier: GPL-2.0-or-later
29c0beb6bSArmin Wolf
39c0beb6bSArmin Wolf===================================================
49c0beb6bSArmin WolfMSI WMI Platform Features driver (msi-wmi-platform)
59c0beb6bSArmin Wolf===================================================
69c0beb6bSArmin Wolf
79c0beb6bSArmin WolfIntroduction
89c0beb6bSArmin Wolf============
99c0beb6bSArmin Wolf
109c0beb6bSArmin WolfMany MSI notebooks support various features like reading fan sensors. This features are controlled
119c0beb6bSArmin Wolfby the embedded controller, with the ACPI firmware exposing a standard ACPI WMI interface on top
129c0beb6bSArmin Wolfof the embedded controller interface.
139c0beb6bSArmin Wolf
149c0beb6bSArmin WolfWMI interface description
159c0beb6bSArmin Wolf=========================
169c0beb6bSArmin Wolf
179c0beb6bSArmin WolfThe WMI interface description can be decoded from the embedded binary MOF (bmof)
189c0beb6bSArmin Wolfdata using the `bmfdec <https://github.com/pali/bmfdec>`_ utility:
199c0beb6bSArmin Wolf
209c0beb6bSArmin Wolf::
219c0beb6bSArmin Wolf
229c0beb6bSArmin Wolf  [WMI, Locale("MS\0x409"),
239c0beb6bSArmin Wolf   Description("This class contains the definition of the package used in other classes"),
249c0beb6bSArmin Wolf   guid("{ABBC0F60-8EA1-11d1-00A0-C90629100000}")]
259c0beb6bSArmin Wolf  class Package {
269c0beb6bSArmin Wolf    [WmiDataId(1), read, write, Description("16 bytes of data")] uint8 Bytes[16];
279c0beb6bSArmin Wolf  };
289c0beb6bSArmin Wolf
299c0beb6bSArmin Wolf  [WMI, Locale("MS\0x409"),
309c0beb6bSArmin Wolf   Description("This class contains the definition of the package used in other classes"),
319c0beb6bSArmin Wolf   guid("{ABBC0F63-8EA1-11d1-00A0-C90629100000}")]
329c0beb6bSArmin Wolf  class Package_32 {
339c0beb6bSArmin Wolf    [WmiDataId(1), read, write, Description("32 bytes of data")] uint8 Bytes[32];
349c0beb6bSArmin Wolf  };
359c0beb6bSArmin Wolf
369c0beb6bSArmin Wolf  [WMI, Dynamic, Provider("WmiProv"), Locale("MS\0x409"),
379c0beb6bSArmin Wolf   Description("Class used to operate methods on a package"),
389c0beb6bSArmin Wolf   guid("{ABBC0F6E-8EA1-11d1-00A0-C90629100000}")]
399c0beb6bSArmin Wolf  class MSI_ACPI {
409c0beb6bSArmin Wolf    [key, read] string InstanceName;
419c0beb6bSArmin Wolf    [read] boolean Active;
429c0beb6bSArmin Wolf
439c0beb6bSArmin Wolf    [WmiMethodId(1), Implemented, read, write, Description("Return the contents of a package")]
449c0beb6bSArmin Wolf    void GetPackage([out, id(0)] Package Data);
459c0beb6bSArmin Wolf
469c0beb6bSArmin Wolf    [WmiMethodId(2), Implemented, read, write, Description("Set the contents of a package")]
479c0beb6bSArmin Wolf    void SetPackage([in, id(0)] Package Data);
489c0beb6bSArmin Wolf
499c0beb6bSArmin Wolf    [WmiMethodId(3), Implemented, read, write, Description("Return the contents of a package")]
509c0beb6bSArmin Wolf    void Get_EC([out, id(0)] Package_32 Data);
519c0beb6bSArmin Wolf
529c0beb6bSArmin Wolf    [WmiMethodId(4), Implemented, read, write, Description("Set the contents of a package")]
539c0beb6bSArmin Wolf    void Set_EC([in, id(0)] Package_32 Data);
549c0beb6bSArmin Wolf
559c0beb6bSArmin Wolf    [WmiMethodId(5), Implemented, read, write, Description("Return the contents of a package")]
569c0beb6bSArmin Wolf    void Get_BIOS([in, out, id(0)] Package_32 Data);
579c0beb6bSArmin Wolf
589c0beb6bSArmin Wolf    [WmiMethodId(6), Implemented, read, write, Description("Set the contents of a package")]
599c0beb6bSArmin Wolf    void Set_BIOS([in, out, id(0)] Package_32 Data);
609c0beb6bSArmin Wolf
619c0beb6bSArmin Wolf    [WmiMethodId(7), Implemented, read, write, Description("Return the contents of a package")]
629c0beb6bSArmin Wolf    void Get_SMBUS([in, out, id(0)] Package_32 Data);
639c0beb6bSArmin Wolf
649c0beb6bSArmin Wolf    [WmiMethodId(8), Implemented, read, write, Description("Set the contents of a package")]
659c0beb6bSArmin Wolf    void Set_SMBUS([in, out, id(0)] Package_32 Data);
669c0beb6bSArmin Wolf
679c0beb6bSArmin Wolf    [WmiMethodId(9), Implemented, read, write, Description("Return the contents of a package")]
689c0beb6bSArmin Wolf    void Get_MasterBattery([in, out, id(0)] Package_32 Data);
699c0beb6bSArmin Wolf
709c0beb6bSArmin Wolf    [WmiMethodId(10), Implemented, read, write, Description("Set the contents of a package")]
719c0beb6bSArmin Wolf    void Set_MasterBattery([in, out, id(0)] Package_32 Data);
729c0beb6bSArmin Wolf
739c0beb6bSArmin Wolf    [WmiMethodId(11), Implemented, read, write, Description("Return the contents of a package")]
749c0beb6bSArmin Wolf    void Get_SlaveBattery([in, out, id(0)] Package_32 Data);
759c0beb6bSArmin Wolf
769c0beb6bSArmin Wolf    [WmiMethodId(12), Implemented, read, write, Description("Set the contents of a package")]
779c0beb6bSArmin Wolf    void Set_SlaveBattery([in, out, id(0)] Package_32 Data);
789c0beb6bSArmin Wolf
799c0beb6bSArmin Wolf    [WmiMethodId(13), Implemented, read, write, Description("Return the contents of a package")]
809c0beb6bSArmin Wolf    void Get_Temperature([in, out, id(0)] Package_32 Data);
819c0beb6bSArmin Wolf
829c0beb6bSArmin Wolf    [WmiMethodId(14), Implemented, read, write, Description("Set the contents of a package")]
839c0beb6bSArmin Wolf    void Set_Temperature([in, out, id(0)] Package_32 Data);
849c0beb6bSArmin Wolf
859c0beb6bSArmin Wolf    [WmiMethodId(15), Implemented, read, write, Description("Return the contents of a package")]
869c0beb6bSArmin Wolf    void Get_Thermal([in, out, id(0)] Package_32 Data);
879c0beb6bSArmin Wolf
889c0beb6bSArmin Wolf    [WmiMethodId(16), Implemented, read, write, Description("Set the contents of a package")]
899c0beb6bSArmin Wolf    void Set_Thermal([in, out, id(0)] Package_32 Data);
909c0beb6bSArmin Wolf
919c0beb6bSArmin Wolf    [WmiMethodId(17), Implemented, read, write, Description("Return the contents of a package")]
929c0beb6bSArmin Wolf    void Get_Fan([in, out, id(0)] Package_32 Data);
939c0beb6bSArmin Wolf
949c0beb6bSArmin Wolf    [WmiMethodId(18), Implemented, read, write, Description("Set the contents of a package")]
959c0beb6bSArmin Wolf    void Set_Fan([in, out, id(0)] Package_32 Data);
969c0beb6bSArmin Wolf
979c0beb6bSArmin Wolf    [WmiMethodId(19), Implemented, read, write, Description("Return the contents of a package")]
989c0beb6bSArmin Wolf    void Get_Device([in, out, id(0)] Package_32 Data);
999c0beb6bSArmin Wolf
1009c0beb6bSArmin Wolf    [WmiMethodId(20), Implemented, read, write, Description("Set the contents of a package")]
1019c0beb6bSArmin Wolf    void Set_Device([in, out, id(0)] Package_32 Data);
1029c0beb6bSArmin Wolf
1039c0beb6bSArmin Wolf    [WmiMethodId(21), Implemented, read, write, Description("Return the contents of a package")]
1049c0beb6bSArmin Wolf    void Get_Power([in, out, id(0)] Package_32 Data);
1059c0beb6bSArmin Wolf
1069c0beb6bSArmin Wolf    [WmiMethodId(22), Implemented, read, write, Description("Set the contents of a package")]
1079c0beb6bSArmin Wolf    void Set_Power([in, out, id(0)] Package_32 Data);
1089c0beb6bSArmin Wolf
1099c0beb6bSArmin Wolf    [WmiMethodId(23), Implemented, read, write, Description("Return the contents of a package")]
1109c0beb6bSArmin Wolf    void Get_Debug([in, out, id(0)] Package_32 Data);
1119c0beb6bSArmin Wolf
1129c0beb6bSArmin Wolf    [WmiMethodId(24), Implemented, read, write, Description("Set the contents of a package")]
1139c0beb6bSArmin Wolf    void Set_Debug([in, out, id(0)] Package_32 Data);
1149c0beb6bSArmin Wolf
1159c0beb6bSArmin Wolf    [WmiMethodId(25), Implemented, read, write, Description("Return the contents of a package")]
1169c0beb6bSArmin Wolf    void Get_AP([in, out, id(0)] Package_32 Data);
1179c0beb6bSArmin Wolf
1189c0beb6bSArmin Wolf    [WmiMethodId(26), Implemented, read, write, Description("Set the contents of a package")]
1199c0beb6bSArmin Wolf    void Set_AP([in, out, id(0)] Package_32 Data);
1209c0beb6bSArmin Wolf
1219c0beb6bSArmin Wolf    [WmiMethodId(27), Implemented, read, write, Description("Return the contents of a package")]
1229c0beb6bSArmin Wolf    void Get_Data([in, out, id(0)] Package_32 Data);
1239c0beb6bSArmin Wolf
1249c0beb6bSArmin Wolf    [WmiMethodId(28), Implemented, read, write, Description("Set the contents of a package")]
1259c0beb6bSArmin Wolf    void Set_Data([in, out, id(0)] Package_32 Data);
1269c0beb6bSArmin Wolf
1279c0beb6bSArmin Wolf    [WmiMethodId(29), Implemented, read, write, Description("Return the contents of a package")]
1289c0beb6bSArmin Wolf    void Get_WMI([out, id(0)] Package_32 Data);
1299c0beb6bSArmin Wolf  };
1309c0beb6bSArmin Wolf
1319c0beb6bSArmin WolfDue to a peculiarity in how Windows handles the ``CreateByteField()`` ACPI operator (errors only
1329c0beb6bSArmin Wolfhappen when a invalid byte field is ultimately accessed), all methods require a 32 byte input
1336e73c490SLuis Felipe Hernandezbuffer, even if the Binary MOF says otherwise.
1349c0beb6bSArmin Wolf
1359c0beb6bSArmin WolfThe input buffer contains a single byte to select the subfeature to be accessed and 31 bytes of
1369c0beb6bSArmin Wolfinput data, the meaning of which depends on the subfeature being accessed.
1379c0beb6bSArmin Wolf
1386e73c490SLuis Felipe HernandezThe output buffer contains a single byte which signals success or failure (``0x00`` on failure)
1399c0beb6bSArmin Wolfand 31 bytes of output data, the meaning if which depends on the subfeature being accessed.
1409c0beb6bSArmin Wolf
141*baf2f2c2SArmin Wolf.. note::
142*baf2f2c2SArmin Wolf   The ACPI control method responsible for handling the WMI method calls is not thread-safe.
143*baf2f2c2SArmin Wolf   This is a firmware bug that needs to be handled inside the driver itself.
144*baf2f2c2SArmin Wolf
1459c0beb6bSArmin WolfWMI method Get_EC()
1469c0beb6bSArmin Wolf-------------------
1479c0beb6bSArmin Wolf
1489c0beb6bSArmin WolfReturns embedded controller information, the selected subfeature does not matter. The output
1499c0beb6bSArmin Wolfdata contains a flag byte and a 28 byte controller firmware version string.
1509c0beb6bSArmin Wolf
1519c0beb6bSArmin WolfThe first 4 bits of the flag byte contain the minor version of the embedded controller interface,
1529c0beb6bSArmin Wolfwith the next 2 bits containing the major version of the embedded controller interface.
1539c0beb6bSArmin Wolf
1546e73c490SLuis Felipe HernandezThe 7th bit signals if the embedded controller page changed (exact meaning is unknown), and the
1559c0beb6bSArmin Wolflast bit signals if the platform is a Tigerlake platform.
1569c0beb6bSArmin Wolf
1579c0beb6bSArmin WolfThe MSI software seems to only use this interface when the last bit is set.
1589c0beb6bSArmin Wolf
1599c0beb6bSArmin WolfWMI method Get_Fan()
1609c0beb6bSArmin Wolf--------------------
1619c0beb6bSArmin Wolf
1629c0beb6bSArmin WolfFan speed sensors can be accessed by selecting subfeature ``0x00``. The output data contains
1639c0beb6bSArmin Wolfup to four 16-bit fan speed readings in big-endian format. Most machines do not support all
1649c0beb6bSArmin Wolffour fan speed sensors, so the remaining reading are hardcoded to ``0x0000``.
1659c0beb6bSArmin Wolf
1669c0beb6bSArmin WolfThe fan RPM readings can be calculated with the following formula:
1679c0beb6bSArmin Wolf
1689c0beb6bSArmin Wolf        RPM = 480000 / <fan speed reading>
1699c0beb6bSArmin Wolf
1709c0beb6bSArmin WolfIf the fan speed reading is zero, then the fan RPM is zero too.
1719c0beb6bSArmin Wolf
1729c0beb6bSArmin WolfWMI method Get_WMI()
1739c0beb6bSArmin Wolf--------------------
1749c0beb6bSArmin Wolf
1759c0beb6bSArmin WolfReturns the version of the ACPI WMI interface, the selected subfeature does not matter.
1769c0beb6bSArmin WolfThe output data contains two bytes, the first one contains the major version and the last one
1779c0beb6bSArmin Wolfcontains the minor revision of the ACPI WMI interface.
1789c0beb6bSArmin Wolf
1799c0beb6bSArmin WolfThe MSI software seems to only use this interface when the major version is greater than two.
1809c0beb6bSArmin Wolf
1819c0beb6bSArmin WolfReverse-Engineering the MSI WMI Platform interface
1829c0beb6bSArmin Wolf==================================================
1839c0beb6bSArmin Wolf
1849c0beb6bSArmin Wolf.. warning:: Randomly poking the embedded controller interface can potentially cause damage
1859c0beb6bSArmin Wolf             to the machine and other unwanted side effects, please be careful.
1869c0beb6bSArmin Wolf
1879c0beb6bSArmin WolfThe underlying embedded controller interface is used by the ``msi-ec`` driver, and it seems
1889c0beb6bSArmin Wolfthat many methods just copy a part of the embedded controller memory into the output buffer.
1899c0beb6bSArmin Wolf
1909c0beb6bSArmin WolfThis means that the remaining WMI methods can be reverse-engineered by looking which part of
1919c0beb6bSArmin Wolfthe embedded controller memory is accessed by the ACPI AML code. The driver also supports a
1929c0beb6bSArmin Wolfdebugfs interface for directly executing WMI methods. Additionally, any safety checks regarding
1939c0beb6bSArmin Wolfunsupported hardware can be disabled by loading the module with ``force=true``.
1949c0beb6bSArmin Wolf
1959c0beb6bSArmin WolfMore information about the MSI embedded controller interface can be found at the
1969c0beb6bSArmin Wolf`msi-ec project <https://github.com/BeardOverflow/msi-ec>`_.
1979c0beb6bSArmin Wolf
1989c0beb6bSArmin WolfSpecial thanks go to github user `glpnk` for showing how to decode the fan speed readings.
199