1 .. SPDX-License-Identifier: GPL-2.0-or-later 1 .. SPDX-License-Identifier: GPL-2.0-or-later 2 2 3 ============================================== 3 =================================================== 4 MSI WMI Platform Features driver (msi-wmi-plat 4 MSI WMI Platform Features driver (msi-wmi-platform) 5 ============================================== 5 =================================================== 6 6 7 Introduction 7 Introduction 8 ============ 8 ============ 9 9 10 Many MSI notebooks support various features li 10 Many MSI notebooks support various features like reading fan sensors. This features are controlled 11 by the embedded controller, with the ACPI firm 11 by the embedded controller, with the ACPI firmware exposing a standard ACPI WMI interface on top 12 of the embedded controller interface. 12 of the embedded controller interface. 13 13 14 WMI interface description 14 WMI interface description 15 ========================= 15 ========================= 16 16 17 The WMI interface description can be decoded f 17 The WMI interface description can be decoded from the embedded binary MOF (bmof) 18 data using the `bmfdec <https://github.com/pal 18 data using the `bmfdec <https://github.com/pali/bmfdec>`_ utility: 19 19 20 :: 20 :: 21 21 22 [WMI, Locale("MS\0x409"), 22 [WMI, Locale("MS\0x409"), 23 Description("This class contains the defini 23 Description("This class contains the definition of the package used in other classes"), 24 guid("{ABBC0F60-8EA1-11d1-00A0-C90629100000 24 guid("{ABBC0F60-8EA1-11d1-00A0-C90629100000}")] 25 class Package { 25 class Package { 26 [WmiDataId(1), read, write, Description("1 26 [WmiDataId(1), read, write, Description("16 bytes of data")] uint8 Bytes[16]; 27 }; 27 }; 28 28 29 [WMI, Locale("MS\0x409"), 29 [WMI, Locale("MS\0x409"), 30 Description("This class contains the defini 30 Description("This class contains the definition of the package used in other classes"), 31 guid("{ABBC0F63-8EA1-11d1-00A0-C90629100000 31 guid("{ABBC0F63-8EA1-11d1-00A0-C90629100000}")] 32 class Package_32 { 32 class Package_32 { 33 [WmiDataId(1), read, write, Description("3 33 [WmiDataId(1), read, write, Description("32 bytes of data")] uint8 Bytes[32]; 34 }; 34 }; 35 35 36 [WMI, Dynamic, Provider("WmiProv"), Locale(" 36 [WMI, Dynamic, Provider("WmiProv"), Locale("MS\0x409"), 37 Description("Class used to operate methods 37 Description("Class used to operate methods on a package"), 38 guid("{ABBC0F6E-8EA1-11d1-00A0-C90629100000 38 guid("{ABBC0F6E-8EA1-11d1-00A0-C90629100000}")] 39 class MSI_ACPI { 39 class MSI_ACPI { 40 [key, read] string InstanceName; 40 [key, read] string InstanceName; 41 [read] boolean Active; 41 [read] boolean Active; 42 42 43 [WmiMethodId(1), Implemented, read, write, 43 [WmiMethodId(1), Implemented, read, write, Description("Return the contents of a package")] 44 void GetPackage([out, id(0)] Package Data) 44 void GetPackage([out, id(0)] Package Data); 45 45 46 [WmiMethodId(2), Implemented, read, write, 46 [WmiMethodId(2), Implemented, read, write, Description("Set the contents of a package")] 47 void SetPackage([in, id(0)] Package Data); 47 void SetPackage([in, id(0)] Package Data); 48 48 49 [WmiMethodId(3), Implemented, read, write, 49 [WmiMethodId(3), Implemented, read, write, Description("Return the contents of a package")] 50 void Get_EC([out, id(0)] Package_32 Data); 50 void Get_EC([out, id(0)] Package_32 Data); 51 51 52 [WmiMethodId(4), Implemented, read, write, 52 [WmiMethodId(4), Implemented, read, write, Description("Set the contents of a package")] 53 void Set_EC([in, id(0)] Package_32 Data); 53 void Set_EC([in, id(0)] Package_32 Data); 54 54 55 [WmiMethodId(5), Implemented, read, write, 55 [WmiMethodId(5), Implemented, read, write, Description("Return the contents of a package")] 56 void Get_BIOS([in, out, id(0)] Package_32 56 void Get_BIOS([in, out, id(0)] Package_32 Data); 57 57 58 [WmiMethodId(6), Implemented, read, write, 58 [WmiMethodId(6), Implemented, read, write, Description("Set the contents of a package")] 59 void Set_BIOS([in, out, id(0)] Package_32 59 void Set_BIOS([in, out, id(0)] Package_32 Data); 60 60 61 [WmiMethodId(7), Implemented, read, write, 61 [WmiMethodId(7), Implemented, read, write, Description("Return the contents of a package")] 62 void Get_SMBUS([in, out, id(0)] Package_32 62 void Get_SMBUS([in, out, id(0)] Package_32 Data); 63 63 64 [WmiMethodId(8), Implemented, read, write, 64 [WmiMethodId(8), Implemented, read, write, Description("Set the contents of a package")] 65 void Set_SMBUS([in, out, id(0)] Package_32 65 void Set_SMBUS([in, out, id(0)] Package_32 Data); 66 66 67 [WmiMethodId(9), Implemented, read, write, 67 [WmiMethodId(9), Implemented, read, write, Description("Return the contents of a package")] 68 void Get_MasterBattery([in, out, id(0)] Pa 68 void Get_MasterBattery([in, out, id(0)] Package_32 Data); 69 69 70 [WmiMethodId(10), Implemented, read, write 70 [WmiMethodId(10), Implemented, read, write, Description("Set the contents of a package")] 71 void Set_MasterBattery([in, out, id(0)] Pa 71 void Set_MasterBattery([in, out, id(0)] Package_32 Data); 72 72 73 [WmiMethodId(11), Implemented, read, write 73 [WmiMethodId(11), Implemented, read, write, Description("Return the contents of a package")] 74 void Get_SlaveBattery([in, out, id(0)] Pac 74 void Get_SlaveBattery([in, out, id(0)] Package_32 Data); 75 75 76 [WmiMethodId(12), Implemented, read, write 76 [WmiMethodId(12), Implemented, read, write, Description("Set the contents of a package")] 77 void Set_SlaveBattery([in, out, id(0)] Pac 77 void Set_SlaveBattery([in, out, id(0)] Package_32 Data); 78 78 79 [WmiMethodId(13), Implemented, read, write 79 [WmiMethodId(13), Implemented, read, write, Description("Return the contents of a package")] 80 void Get_Temperature([in, out, id(0)] Pack 80 void Get_Temperature([in, out, id(0)] Package_32 Data); 81 81 82 [WmiMethodId(14), Implemented, read, write 82 [WmiMethodId(14), Implemented, read, write, Description("Set the contents of a package")] 83 void Set_Temperature([in, out, id(0)] Pack 83 void Set_Temperature([in, out, id(0)] Package_32 Data); 84 84 85 [WmiMethodId(15), Implemented, read, write 85 [WmiMethodId(15), Implemented, read, write, Description("Return the contents of a package")] 86 void Get_Thermal([in, out, id(0)] Package_ 86 void Get_Thermal([in, out, id(0)] Package_32 Data); 87 87 88 [WmiMethodId(16), Implemented, read, write 88 [WmiMethodId(16), Implemented, read, write, Description("Set the contents of a package")] 89 void Set_Thermal([in, out, id(0)] Package_ 89 void Set_Thermal([in, out, id(0)] Package_32 Data); 90 90 91 [WmiMethodId(17), Implemented, read, write 91 [WmiMethodId(17), Implemented, read, write, Description("Return the contents of a package")] 92 void Get_Fan([in, out, id(0)] Package_32 D 92 void Get_Fan([in, out, id(0)] Package_32 Data); 93 93 94 [WmiMethodId(18), Implemented, read, write 94 [WmiMethodId(18), Implemented, read, write, Description("Set the contents of a package")] 95 void Set_Fan([in, out, id(0)] Package_32 D 95 void Set_Fan([in, out, id(0)] Package_32 Data); 96 96 97 [WmiMethodId(19), Implemented, read, write 97 [WmiMethodId(19), Implemented, read, write, Description("Return the contents of a package")] 98 void Get_Device([in, out, id(0)] Package_3 98 void Get_Device([in, out, id(0)] Package_32 Data); 99 99 100 [WmiMethodId(20), Implemented, read, write 100 [WmiMethodId(20), Implemented, read, write, Description("Set the contents of a package")] 101 void Set_Device([in, out, id(0)] Package_3 101 void Set_Device([in, out, id(0)] Package_32 Data); 102 102 103 [WmiMethodId(21), Implemented, read, write 103 [WmiMethodId(21), Implemented, read, write, Description("Return the contents of a package")] 104 void Get_Power([in, out, id(0)] Package_32 104 void Get_Power([in, out, id(0)] Package_32 Data); 105 105 106 [WmiMethodId(22), Implemented, read, write 106 [WmiMethodId(22), Implemented, read, write, Description("Set the contents of a package")] 107 void Set_Power([in, out, id(0)] Package_32 107 void Set_Power([in, out, id(0)] Package_32 Data); 108 108 109 [WmiMethodId(23), Implemented, read, write 109 [WmiMethodId(23), Implemented, read, write, Description("Return the contents of a package")] 110 void Get_Debug([in, out, id(0)] Package_32 110 void Get_Debug([in, out, id(0)] Package_32 Data); 111 111 112 [WmiMethodId(24), Implemented, read, write 112 [WmiMethodId(24), Implemented, read, write, Description("Set the contents of a package")] 113 void Set_Debug([in, out, id(0)] Package_32 113 void Set_Debug([in, out, id(0)] Package_32 Data); 114 114 115 [WmiMethodId(25), Implemented, read, write 115 [WmiMethodId(25), Implemented, read, write, Description("Return the contents of a package")] 116 void Get_AP([in, out, id(0)] Package_32 Da 116 void Get_AP([in, out, id(0)] Package_32 Data); 117 117 118 [WmiMethodId(26), Implemented, read, write 118 [WmiMethodId(26), Implemented, read, write, Description("Set the contents of a package")] 119 void Set_AP([in, out, id(0)] Package_32 Da 119 void Set_AP([in, out, id(0)] Package_32 Data); 120 120 121 [WmiMethodId(27), Implemented, read, write 121 [WmiMethodId(27), Implemented, read, write, Description("Return the contents of a package")] 122 void Get_Data([in, out, id(0)] Package_32 122 void Get_Data([in, out, id(0)] Package_32 Data); 123 123 124 [WmiMethodId(28), Implemented, read, write 124 [WmiMethodId(28), Implemented, read, write, Description("Set the contents of a package")] 125 void Set_Data([in, out, id(0)] Package_32 125 void Set_Data([in, out, id(0)] Package_32 Data); 126 126 127 [WmiMethodId(29), Implemented, read, write 127 [WmiMethodId(29), Implemented, read, write, Description("Return the contents of a package")] 128 void Get_WMI([out, id(0)] Package_32 Data) 128 void Get_WMI([out, id(0)] Package_32 Data); 129 }; 129 }; 130 130 131 Due to a peculiarity in how Windows handles th 131 Due to a peculiarity in how Windows handles the ``CreateByteField()`` ACPI operator (errors only 132 happen when a invalid byte field is ultimately 132 happen when a invalid byte field is ultimately accessed), all methods require a 32 byte input 133 buffer, even if the Binary MOF says otherwise. 133 buffer, even if the Binary MOF says otherwise. 134 134 135 The input buffer contains a single byte to sel 135 The input buffer contains a single byte to select the subfeature to be accessed and 31 bytes of 136 input data, the meaning of which depends on th 136 input data, the meaning of which depends on the subfeature being accessed. 137 137 138 The output buffer contains a single byte which 138 The output buffer contains a single byte which signals success or failure (``0x00`` on failure) 139 and 31 bytes of output data, the meaning if wh 139 and 31 bytes of output data, the meaning if which depends on the subfeature being accessed. 140 140 141 WMI method Get_EC() 141 WMI method Get_EC() 142 ------------------- 142 ------------------- 143 143 144 Returns embedded controller information, the s 144 Returns embedded controller information, the selected subfeature does not matter. The output 145 data contains a flag byte and a 28 byte contro 145 data contains a flag byte and a 28 byte controller firmware version string. 146 146 147 The first 4 bits of the flag byte contain the 147 The first 4 bits of the flag byte contain the minor version of the embedded controller interface, 148 with the next 2 bits containing the major vers 148 with the next 2 bits containing the major version of the embedded controller interface. 149 149 150 The 7th bit signals if the embedded controller 150 The 7th bit signals if the embedded controller page changed (exact meaning is unknown), and the 151 last bit signals if the platform is a Tigerlak 151 last bit signals if the platform is a Tigerlake platform. 152 152 153 The MSI software seems to only use this interf 153 The MSI software seems to only use this interface when the last bit is set. 154 154 155 WMI method Get_Fan() 155 WMI method Get_Fan() 156 -------------------- 156 -------------------- 157 157 158 Fan speed sensors can be accessed by selecting 158 Fan speed sensors can be accessed by selecting subfeature ``0x00``. The output data contains 159 up to four 16-bit fan speed readings in big-en 159 up to four 16-bit fan speed readings in big-endian format. Most machines do not support all 160 four fan speed sensors, so the remaining readi 160 four fan speed sensors, so the remaining reading are hardcoded to ``0x0000``. 161 161 162 The fan RPM readings can be calculated with th 162 The fan RPM readings can be calculated with the following formula: 163 163 164 RPM = 480000 / <fan speed reading> 164 RPM = 480000 / <fan speed reading> 165 165 166 If the fan speed reading is zero, then the fan 166 If the fan speed reading is zero, then the fan RPM is zero too. 167 167 168 WMI method Get_WMI() 168 WMI method Get_WMI() 169 -------------------- 169 -------------------- 170 170 171 Returns the version of the ACPI WMI interface, 171 Returns the version of the ACPI WMI interface, the selected subfeature does not matter. 172 The output data contains two bytes, the first 172 The output data contains two bytes, the first one contains the major version and the last one 173 contains the minor revision of the ACPI WMI in 173 contains the minor revision of the ACPI WMI interface. 174 174 175 The MSI software seems to only use this interf 175 The MSI software seems to only use this interface when the major version is greater than two. 176 176 177 Reverse-Engineering the MSI WMI Platform inter 177 Reverse-Engineering the MSI WMI Platform interface 178 ============================================== 178 ================================================== 179 179 180 .. warning:: Randomly poking the embedded cont 180 .. warning:: Randomly poking the embedded controller interface can potentially cause damage 181 to the machine and other unwanted 181 to the machine and other unwanted side effects, please be careful. 182 182 183 The underlying embedded controller interface i 183 The underlying embedded controller interface is used by the ``msi-ec`` driver, and it seems 184 that many methods just copy a part of the embe 184 that many methods just copy a part of the embedded controller memory into the output buffer. 185 185 186 This means that the remaining WMI methods can 186 This means that the remaining WMI methods can be reverse-engineered by looking which part of 187 the embedded controller memory is accessed by 187 the embedded controller memory is accessed by the ACPI AML code. The driver also supports a 188 debugfs interface for directly executing WMI m 188 debugfs interface for directly executing WMI methods. Additionally, any safety checks regarding 189 unsupported hardware can be disabled by loadin 189 unsupported hardware can be disabled by loading the module with ``force=true``. 190 190 191 More information about the MSI embedded contro 191 More information about the MSI embedded controller interface can be found at the 192 `msi-ec project <https://github.com/BeardOverf 192 `msi-ec project <https://github.com/BeardOverflow/msi-ec>`_. 193 193 194 Special thanks go to github user `glpnk` for s 194 Special thanks go to github user `glpnk` for showing how to decode the fan speed readings.
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.