6. Uniwill Notebook driver (uniwill-laptop)¶
6.1. Introduction¶
Many notebooks manufactured by Uniwill (either directly or as ODM) provide a EC interface
for controlling various platform settings like sensors and fan control. This interface is
used by the uniwill-laptop driver to map those features onto standard kernel interfaces.
6.2. EC WMI interface description¶
The EC WMI interface description can be decoded from the embedded binary MOF (bmof) data using the bmfdec utility:
[WMI, Dynamic, Provider("WmiProv"), Locale("MS\\0x409"),
Description("Class used to operate methods on a ULong"),
guid("{ABBC0F6F-8EA1-11d1-00A0-C90629100000}")]
class AcpiTest_MULong {
[key, read] string InstanceName;
[read] boolean Active;
[WmiMethodId(1), Implemented, read, write, Description("Return the contents of a ULong")]
void GetULong([out, Description("Ulong Data")] uint32 Data);
[WmiMethodId(2), Implemented, read, write, Description("Set the contents of a ULong")]
void SetULong([in, Description("Ulong Data")] uint32 Data);
[WmiMethodId(3), Implemented, read, write,
Description("Generate an event containing ULong data")]
void FireULong([in, Description("WMI requires a parameter")] uint32 Hack);
[WmiMethodId(4), Implemented, read, write, Description("Get and Set the contents of a ULong")]
void GetSetULong([in, Description("Ulong Data")] uint64 Data,
[out, Description("Ulong Data")] uint32 Return);
[WmiMethodId(5), Implemented, read, write,
Description("Get and Set the contents of a ULong for Dollby button")]
void GetButton([in, Description("Ulong Data")] uint64 Data,
[out, Description("Ulong Data")] uint32 Return);
};
Most of the WMI-related code was copied from the Windows driver samples, which unfortunately means that the WMI-GUID is not unique. This makes the WMI-GUID unusable for autoloading.
6.2.1. WMI method GetULong()¶
This WMI method was copied from the Windows driver samples and has no function.
6.2.2. WMI method SetULong()¶
This WMI method was copied from the Windows driver samples and has no function.
6.2.3. WMI method FireULong()¶
This WMI method allows to inject a WMI event with a 32-bit payload. Its primary purpose seems to be debugging.
6.2.4. WMI method GetSetULong()¶
This WMI method is used to communicate with the EC. The Data argument holds the following
information (starting with the least significant byte):
16-bit address
16-bit data (set to
0x0000when reading)16-bit operation (
0x0100for reading and0x0000for writing)16-bit reserved (set to
0x0000)
The first 8 bits of the Return value contain the data returned by the EC when reading.
The special value 0xFEFEFEFE is used to indicate a communication failure with the EC.
6.3. Reverse-Engineering the EC WMI interface¶
Warning
Randomly poking the EC can potentially cause damage to the machine and other unwanted side effects, please be careful.
The EC behind the GetSetULong method is used by the OEM software supplied by the manufacturer.
Reverse-engineering of this software is difficult since it uses an obfuscator, however some parts
are not obfuscated. In this case dnSpy could also be helpful.
The EC can be accessed under Windows using powershell (requires admin privileges):
> $obj = Get-CimInstance -Namespace root/wmi -ClassName AcpiTest_MULong | Select-Object -First 1
> Invoke-CimMethod -InputObject $obj -MethodName GetSetULong -Arguments @{Data = <input>}
6.4. WMI event interface description¶
The WMI interface description can also be decoded from the embedded binary MOF (bmof) data:
[WMI, Dynamic, Provider("WmiProv"), Locale("MS\\0x409"),
Description("Class containing event generated ULong data"),
guid("{ABBC0F72-8EA1-11d1-00A0-C90629100000}")]
class AcpiTest_EventULong : WmiEvent {
[key, read] string InstanceName;
[read] boolean Active;
[WmiDataId(1), read, write, Description("ULong Data")] uint32 ULong;
};
Most of the WMI-related code was again copied from the Windows driver samples, causing this WMI interface to suffer from the same restrictions as the EC WMI interface described above.
6.4.1. WMI event data¶
The WMI event data contains a single 32-bit value which is used to indicate various platform events.
6.5. Reverse-Engineering the Uniwill WMI event interface¶
The driver logs debug messages when receiving a WMI event. Thus enabling debug messages will be useful for finding unknown event codes.
6.6. EC ACPI interface description¶
The INOU0000 ACPI device is a virtual device used to access various hardware registers
available on notebooks manufactured by Uniwill. Reading and writing those registers happens
by calling ACPI control methods. The uniwill-laptop driver uses this device to communicate
with the EC because the ACPI control methods are faster than the WMI methods described above.
ACPI control methods used for reading registers take a single ACPI integer containing the address of the register to read and return a ACPI integer containing the data inside said register. ACPI control methods used for writing registers however take two ACPI integers, with the additional ACPI integer containing the data to be written into the register. Such ACPI control methods return nothing.
6.6.1. System memory¶
System memory can be accessed with a granularity of either a single byte (MMRB for reading and
MMWB for writing) or four bytes (MMRD for reading and MMWD for writing). Those ACPI
control methods are unused because they provide no benefit when compared to the native memory
access functions provided by the kernel.
6.6.2. EC RAM¶
The internal RAM of the EC can be accessed with a granularity of a single byte using the ECRR
(read) and ECRW (write) ACPI control methods, with the maximum register address being 0xFFF.
The OEM software waits 6 ms after calling one of those ACPI control methods, likely to avoid
overwhelming the EC when being connected over LPC.
6.6.3. PCI config space¶
The PCI config space can be accessed with a granularity of four bytes using the PCRD (read) and
PCWD (write) ACPI control methods. The exact address format is unknown, and poking random PCI
devices might confuse the PCI subsystem. Because of this those ACPI control methods are not used.
6.6.4. IO ports¶
IO ports can be accessed with a granularity of four bytes using the IORD (read) and IOWD
(write) ACPI control methods. Those ACPI control methods are unused because they provide no benefit
when compared to the native IO port access functions provided by the kernel.
6.6.5. CMOS RAM¶
The CMOS RAM can be accessed with a granularity of a single byte using the RCMS (read) and
WCMS ACPI control methods. Using those ACPI methods might interfere with the native CMOS RAM
access functions provided by the kernel due to the usage of indexed IO, so they are unused.
6.6.6. Indexed IO¶
Indexed IO with IO ports with a granularity of a single byte can be performed using the RIOP
(read) and WIOP (write) ACPI control methods. Those ACPI methods are unused because they
provide no benifit when compared to the native IO port access functions provided by the kernel.
Special thanks go to github user pobrn which developed the qc71_laptop driver on which this driver is partly based. The same is true for Tuxedo Computers, which developed the tuxedo-drivers package which also served as a foundation for this driver.