This log documents ACPI calls and driver calls found through reverse engineering the MECHREVO Wujie 14XA laptop (marketed as 机械革命无界 14X 暴风雪版, or Mechrevo Boundless 14X Blizzard Edition).
I am playing with:
- BIOS version:
N.1.14MRO17 - AP (control center) version:
5.56.51.17
Windows comes with an ACPI debugger called AMLI.
- Booting a Windows 11 with debug mode on (you can execute
bcdedit -debug onand reboot to toggle the debug mode); - Install Sysinternals's DebugView to read the kernel logs, and WinDbg to issue debug commands;
- Open WinDbg, attach to the local kernel, execute
!amli set traceon spewonto start tracing all ACPI events. If it complains about missing symbols (failed to to get the address of XXX), execute.reloadto reload them; - Open DebugView and enjoy your kernel logs.
- A great Linux kernel module for Wujie 14 (Not to be confused with the 14X, which is a completely different model): https://github.com/xuwd1/mechrevo-wujie14-kmod
- Some tweaks and fixes for 14X: https://github.com/sund3RRR/mechrevo14X-linux
- An open-source control center for controlling various features of Tongfang-based laptops: https://gitlab.com/siphomateke/tongfang-control
- which is based on TUXEDO Control Center: https://github.com/tuxedocomputers/tuxedo-control-center
Invocation: \_SB.INOU.ECRR(0x7a6)
Return: 0x8, 0x18 and 0x28 for different battery modes (respectively Long-lasting Mode, Balanced Mode, and Workstation Mode)
Raw procedure:
AMLI: FFFFC1839B9B3080: \_SB.INOU.ECRR(0x7a6)
ffffc1837ef8212a: {
ffffc1837ef8212a: | Add(0xfed50000,Arg0=0x7a6,Local0) = 0xfed507a6
ffffc1837ef82132: | Store(MMRW(Local0=0xfed507a6,Zero,Zero,Zero)
ffffc1837ef818b2: | {
ffffc1837ef818b2: | | Acquire(UWOL,0xffff) = 0x0
ffffc1837ef818ba: | | OperationRegion(MMNM,0x0,Arg0=0xfed507a6,0x4)
ffffc1837ef818c4: | | Field(MMNM,0x1)
ffffc1837ef818cc: | | {
ffffc1837ef818d1: | | | MM08,8
ffffc1837ef818d1: | | }
ffffc1837ef818d1: | | Field(MMNM,0x1)
ffffc1837ef818d9: | | {
ffffc1837ef818de: | | | MM16,16
ffffc1837ef818de: | | }
ffffc1837ef818de: | | Field(MMNM,0x1)
ffffc1837ef818e6: | | {
ffffc1837ef818eb: | | | MM32,32
ffffc1837ef818eb: | | }
ffffc1837ef818eb: | | Store(0xfffffffe,Local0) = 0xfffffffe
ffffc1837ef818f2: | | If(LEqual(Arg1=0x0,Zero) = 0xffffffffffffffff)
ffffc1837ef818f7: | | {
ffffc1837ef818f7: | | | If(LEqual(Arg2=0x0,Zero) = 0xffffffffffffffff)
ffffc1837ef818fc: | | | {
ffffc1837ef818fc: | | | | Store(MM08 = 0x28,Local0) = 0x28 // or Store(MM08 = 0x18,Local0) = 0x18 // or Store(MM08 = 0x8,Local0) = 0x8
ffffc1837ef81902: | | | }
ffffc1837ef8191d: | | }
ffffc1837ef8195a: | | Release(UWOL)
ffffc1837ef81960: | | Return(Local0=0x28)
ffffc1837ef81962: | },Local1) = 0x28
ffffc1837ef8213c: | Return(Local1=0x28)
ffffc1837ef8213e: }
Invocation: \_SB.INOU.ECRW(0x7a6,0xffffc118) (where new_mode = argument_1 & 0xff)
Return: 0xfffffffe for success
Raw procedure:
AMLI: FFFFC1839B9B3080: \_SB.INOU.ECRW(0x7a6,0xffffc118)
{
Add(0xfed50000,Arg0=0x7a6,Local0)=0xfed507a6
MMRW(Local0=0xfed507a6,One,Zero,Arg1=0xffffc118)
{
Acquire(UWOL,0xffff) = 0x0
OperationRegion(MMNM,0x0,Arg0=0xfed507a6,0x4)
Field(MMNM,0x1)
{
MM08,8
}
Field(MMNM,0x1)
{
MM16,16
}
Field(MMNM,0x1)
{
MM32,32
}
Store(0xfffffffe,Local0) = 0xfffffffe
If(LEqual(Arg1=0x1,Zero) = 0x0)
{
If(LEqual(Arg1=0x1,One) = 0xffffffffffffffff)
{
If(LEqual(Arg2=0x0,Zero) = 0xffffffffffffffff)
{
Store(And(Arg3=0xffffc118,0xff,)=0x18,MM08)=0x18 // 0x8, 0x28
}
}
}
Release(UWOL)
Return(Local0=0xfffffffe)
}
}
Invocation: \_SB.INOU.ECRR(0x78c)
Return: 0x1 for keyboard backlight on; 0x3 for off
Invocation: \_SB.INOU.ECRW(0x78c, 0xffffc101) (where keyboard status = argument_1 & 0xff)
Return: 0xfffffffe for success
It appears that the backlight timeout is not controlled by ACPI calls. Maybe OEM Windows service-based?
Dozens of ACPI calls are issued during power mode changes. It's likely that some other mechanism (driver?) is actually the one doing most of the work.
See switch_balanced_to_quiet.log for an example.
Interestingly, I happened to check GCUService.exe, the main service process for the control center, and found that it's written in C# .NET and not obfuscated at all!
So, I decompiled it using dnSpy, and you can find all the logic related to the tray menu in MyControlCenter.TrayView:
private void item_OfficeMode_Click(object sender, EventArgs e)
{
TrayView.m_MyFan.m_Manager.UserSet_Mode2();
if (App.OsdOnly == 1)
{
App.m_Osd.ShowOSDByName(TrayView.m_MyFan.m_Manager.g_FanMode, "");
}
TrayView.m_MyFan.m_Manager.UpdateStatusToClient(1, 0, 0, true);
}In short, on the 14XA, setting the ACPI Platform Profile (like Office, Gaming, or Turbo modes) primarily just changes the fan curve, CPU Boost, and some power-related logic (depending on charger status, etc.).
I won’t bore you with all the details here because the setup code is quite long and basically just a bunch of ACPI calls. The good news is, they're all in MyControlCenter.MyFanManager.setFanMode. So grab your decompiler and start testing! 😉
Real solid work! Good to see these reverse engineering results. I think this might be a very good starting point to make dedicated kernel modules for the 14X and 15X families.