Skip to content

Instantly share code, notes, and snippets.

@w568w
Last active September 5, 2026 11:17
Show Gist options
  • Select an option

  • Save w568w/b2fc5f9d1f4dff13efe751abec27b396 to your computer and use it in GitHub Desktop.

Select an option

Save w568w/b2fc5f9d1f4dff13efe751abec27b396 to your computer and use it in GitHub Desktop.
MECHREVO Wujie 14XA (Ryzen 7 8845HS) Reverse-engineering

MECHREVO Wujie 14XA (Ryzen 7 8845HS) Reverse-engineering

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

"How did you capture these calls?"

Windows comes with an ACPI debugger called AMLI.

  1. Booting a Windows 11 with debug mode on (you can execute bcdedit -debug on and reboot to toggle the debug mode);
  2. Install Sysinternals's DebugView to read the kernel logs, and WinDbg to issue debug commands;
  3. Open WinDbg, attach to the local kernel, execute !amli set traceon spewon to start tracing all ACPI events. If it complains about missing symbols (failed to to get the address of XXX), execute .reload to reload them;
  4. Open DebugView and enjoy your kernel logs.

"Any useful resourses?"

Read Current Battery Mode

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: }

Set Current Battery Mode

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)
	}
}

Read Keyboard Backlight Status

Invocation: \_SB.INOU.ECRR(0x78c)

Return: 0x1 for keyboard backlight on; 0x3 for off

Set Keyboard Backlight Status

Invocation: \_SB.INOU.ECRW(0x78c, 0xffffc101) (where keyboard status = argument_1 & 0xff)

Return: 0xfffffffe for success

About Keyboard Backlight Timeout

It appears that the backlight timeout is not controlled by ACPI calls. Maybe OEM Windows service-based?

About ACPI Platform Profile

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! 😉

00000036 0.00000510 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x744,0xffffc15f)
00000071 0.01432340 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x751,0xffffc1a0)
00000106 0.03026440 AMLI: FFFFC183A3489080: \_SB.INOU.ECRR(0x727)
00000139 0.04622660 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x727,0xffffc100)
00000174 0.06148090 AMLI: FFFFC183A3489080: \_SB.INOU.ECRR(0x726)
00000207 0.07745980 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x726,0xffffc100)
00000242 0.09461000 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x751,0xffffc1a0)
00000277 0.10852740 AMLI: FFFFC183A3489080: \_SB.INOU.ECRR(0x727)
00000310 0.12456160 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x727,0xffffc100)
00000345 0.14053030 AMLI: FFFFC183A3489080: \_SB.INOU.ECRR(0x726)
00000378 0.15601569 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x726,0xffffc100)
00000413 0.17155820 AMLI: FFFFC183A3489080: \_SB.INOU.ECRR(0x7a5)
00000446 0.18661080 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRR(0x7c6)
00000479 0.20255619 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x783,0xffffc100)
00000514 0.21855800 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0x7c6,0xffffc100)
00000549 0.23372900 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x784,0xffffc100)
00000584 0.24972050 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRR(0x7c5)
00000617 0.26571679 AMLI: FFFFC183A3489080: \_SB.INOU.ECRR(0x727)
00000650 0.28084320 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0x7c5,0xffffc100)
00000685 0.29703659 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x785,0xffffc100)
00000720 0.31278151 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf00,0xffffc104)
00000755 0.32876530 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x786,0xffffc100)
00000790 0.34392330 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf11,0xffffc1af)
00000825 0.35989061 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x787,0xffffc100)
00000860 0.37599701 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf20,0xffffc1f6)
00000895 0.39192191 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf01,0xffffc174)
00000930 0.40796569 AMLI: FFFFC183A3489080: \_SB.INOU.ECRR(0x743)
00000963 0.42304030 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf12,0xffffc13f)
00000998 0.43904111 AMLI: FFFFC183A3489080: \_SB.INOU.ECRW(0x743,0xffffc100)
00001033 0.45466590 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf21,0xffffc122)
00001068 0.47072801 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf02,0xffffc1c0)
00001103 0.48682401 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf13,0xffffc1ef)
00001138 0.50279158 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf22,0xffffc1ae)
00001173 0.51880050 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf03,0xffffc1f0)
00001208 0.53429359 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf14,0xffffc170)
00001243 0.55024391 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf23,0xffffc13e)
00001350 0.56631720 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf04,0xffffc17f)
00001385 0.58230281 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf15,0xffffc10c)
00001420 0.59753120 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf24,0xffffc1c2)
00001455 0.61352181 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf05,0xffffc105)
00001490 0.62971002 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf16,0xffffc1af)
00001525 0.64473581 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf25,0xffffc1ee)
00001560 0.66036379 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf06,0xffffc112)
00001595 0.67595130 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf17,0xffffc132)
00001630 0.69151968 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf26,0xffffc194)
00001665 0.70751858 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf07,0xffffc10f)
00001700 0.72309059 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf18,0xffffc1ef)
00001735 0.73909640 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf27,0xffffc108)
00001770 0.75504780 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf08,0xffffc11a)
00001805 0.77104461 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf19,0xffffc170)
00001840 0.78705209 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf28,0xffffc174)
00001875 0.80316877 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf09,0xffffc112)
00001910 0.81907678 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf1a,0xffffc107)
00001945 0.83516628 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf29,0xffffc180)
00001980 0.85111851 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf0a,0xffffc146)
00002015 0.86632133 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf1b,0xffffc178)
00002050 0.88241982 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf2a,0xffffc194)
00002085 0.89848948 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf0b,0xffffc18f)
00002120 0.91348863 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf1c,0xffffc1b2)
00002155 0.92906022 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf2b,0xffffc180)
00002190 0.94468540 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf0c,0xffffc1af)
00002225 0.96028233 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf1d,0xffffc1e6)
00002260 0.97579569 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf2c,0xffffc150)
00002295 0.99159741 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf0d,0xffffc132)
00002330 1.00694311 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf1e,0xffffc154)
00002365 1.02272415 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf2d,0xffffc110)
00002400 1.03770673 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf0e,0xffffc102)
00002435 1.05334628 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf1f,0xffffc1fb)
00002470 1.06878805 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf2e,0xffffc1ae)
00002505 1.08383656 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf0f,0xffffc1ff)
00002540 1.09945035 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf2f,0xffffc13e)
00002575 1.11502409 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf30,0xffffc100)
00002610 1.13048995 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf41,0xffffc100)
00002645 1.14575362 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf50,0xffffc100)
00002680 1.16078627 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf31,0xffffc100)
00002715 1.17629826 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf42,0xffffc100)
00002750 1.19279945 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf51,0xffffc100)
00002785 1.20795310 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf32,0xffffc100)
00002820 1.22382641 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf43,0xffffc100)
00002855 1.23971939 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf52,0xffffc100)
00002890 1.25603676 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf33,0xffffc100)
00002925 1.27175975 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf44,0xffffc100)
00002960 1.28742433 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf53,0xffffc100)
00002995 1.30333412 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf34,0xffffc100)
00003030 1.31849802 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf45,0xffffc100)
00003065 1.33446085 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf54,0xffffc100)
00003100 1.35044539 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf35,0xffffc100)
00003135 1.36646855 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf46,0xffffc100)
00003170 1.38177514 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf55,0xffffc100)
00003205 1.39749610 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf36,0xffffc100)
00003240 1.41335475 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf47,0xffffc100)
00003275 1.42940855 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf56,0xffffc100)
00003310 1.44501567 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf37,0xffffc100)
00003345 1.46065652 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf48,0xffffc100)
00003380 1.47636318 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf57,0xffffc100)
00003415 1.49191833 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf38,0xffffc100)
00003450 1.50749588 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf49,0xffff8700)
00003485 1.52255869 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf58,0xffffc100)
00003520 1.53414690 AMLI: FFFFF803C9DD0640: \_SB.PCI0.SBRG.EC0._Q89()
00003526 1.53441179 AMLI: FFFFC18382FF5040: \_SB.BAT0._STA()
00003608 1.53600812 AMLI: FFFFC18382FF5040: \_SB.BAT0._BTP(0x1435)
00003674 1.53841364 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf39,0xffffc100)
00003709 1.55442441 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf4a,0xffffc100)
00003744 1.56941175 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf59,0xffffc100)
00003779 1.58533347 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf3a,0xffffc100)
00003814 1.60076249 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf4b,0xffffc100)
00003849 1.61699629 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf5a,0xffffc100)
00003884 1.63299561 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf3b,0xffffc100)
00003919 1.64902079 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf4c,0xffffc100)
00003954 1.66453564 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf5b,0xffffc100)
00003989 1.67987084 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf3c,0xffffc100)
00004024 1.69488394 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf4d,0xffffc100)
00004059 1.71043682 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf5c,0xffffc100)
00004094 1.72608280 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf3d,0xffffc100)
00004129 1.74216723 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf4e,0xffffc100)
00004164 1.75799119 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf5d,0xffffc100)
00004199 1.77354038 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf3e,0xffffc100)
00004234 1.78942883 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf4f,0xffffc100)
00004269 1.80496681 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf5e,0xffffc100)
00004304 1.82056236 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf3f,0xffffc1ff)
00004339 1.83623695 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0xf5f,0xffffc100)
00004374 1.85213244 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRR(0xf00)
00004407 1.86785340 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRR(0xf01)
00004440 1.88386559 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRR(0x7c6)
00004473 1.89915085 AMLI: FFFFC183A37F6080: \_SB.INOU.ECRW(0x7c6,0xffffc104)
@minortex

minortex commented Jul 14, 2026

Copy link
Copy Markdown

Tried flashing SLIMBOOK.Evo_AMD8845HS_BIOS_N.1.14GOS05_EC_2.10.00.zip, first EC then BIOS.

What?! In the BIOS, battery limit occured!
图片

I set ~80%, rebooted into system, and drain my battery with s-tui, until the level was below 80%, started to charge. When the level reached 80%, charge stopped!!
And I set 81% it started to charge again, then stop right at 81%.

I thought we finally made it. Cheers!

This picture says it all:

Snipaste_2026-07-14_22-07-31

Anyway, the last thing: It's time to replace my battery.😂

@w568w

w568w commented Jul 14, 2026

Copy link
Copy Markdown
Author

@minortex Amazing! So it was due to the broken OEM BIOS firmware, right?

How did you find the BIOS firmware? I would like to compare it with the official Mechrevo ones for functional differences.

@minortex

Copy link
Copy Markdown

You can get it from the hyperlink to my repo above. I search "GX4HRXL" and related information, and found some slimbook users talk about it on reddit, and here is the official link: https://cloud.slimbook.net/s/download?dir=/Laptops/Evo-14/Ryzen-8845HS

@w568w

w568w commented Jul 14, 2026

Copy link
Copy Markdown
Author

@minortex Thanks! I've done the analysis with help of GPT-5.6 and Codex, and (possibly) identified a bug in the EC firmware:

The bug in EC 2.04 (fixed in EC 2.08)

In Mechrevo Firmware (EC Version 2.04), the code related to charge-decision is semantically:

static bool state_is(uint8_t value) {
    return xram[0x07C3] == value ||
           xram[0x0770] == value;
}

bool enable_limit_control = state_is(4) || state_is(5);

if (!enable_limit_control) {
    xram[CHARGE_LIMIT_GATE] &= (uint8_t)~LIMIT_GATE_BIT; // disables the charge-limit control path
    xram[LIVE_LIMIT] &= LIMIT_VALUE_MASK; // clear "limit reached" state
    return;
}

xram[CHARGE_LIMIT_GATE] |= LIMIT_GATE_BIT; // enable the limit
update_limit_latch_and_persistence(); // write the limit to store

While in EC Version 2.10, it becomes:

 static bool state_is(uint8_t value) {
     return xram[0x07C3] == value ||
            xram[0x0770] == value;
 }

 bool enable_limit_control = state_is(4) || state_is(5);

+if (!enable_limit_control) {
+    uint8_t stored_limit = xram[0x07B9] & LIMIT_VALUE_MASK; // read limit from store
+    enable_limit_control = stored_limit != 0 && stored_limit <= 100; // CRITIC: if limit is a valid number, still apply the battery limit
+}
+
 if (!enable_limit_control) {
     xram[CHARGE_LIMIT_GATE] &= (uint8_t)~LIMIT_GATE_BIT; // disables the charge-limit control path
     xram[LIVE_LIMIT] &= LIMIT_VALUE_MASK; // clear "limit reached" state
     return;
 }

 xram[CHARGE_LIMIT_GATE] |= LIMIT_GATE_BIT; // enable the limit
 update_limit_latch_and_persistence(); // write the limit to store

Besides, EC Version 2.10 also added logic to restore limit at boot time in its ec_init().


According to the code, the EC firmware bug path is possibly that:

  1. OS triggers the ACPI call.
  2. The EC runs its charge-limit update routine.
  3. But state_is(4) || state_is(5) is somehow always false at the moment;
  4. Thus it simply disables the charge limit and returns. Nothing is applied.

Edit: BUT it's NOT the only bug, otherwises MRO50 upgrades (with EC 2.12) should fix this completely. The truth is that, even writing to 0x07B9 on MRO50, the charging limit still doesn't take effect. There should be other reason for this… I am stuck here. Maybe dig it deeper when having more spare time.

@minortex

Copy link
Copy Markdown

@w568w
Actually the version of latest EC(bundled with BIOS N.1.14MRO50) from custom service is 2.12, but still reproduce this issue, why did this regression occurs?

So our best bet is calling Mechrevo to upgrade their EC firmware version as soon as possible.

I don't think they'll update it because it has been two years since the model launched.


I haven't encounter any side effects with Slimbook's BIOS so far, it might be a good choice. However, the charge minimum level doesn't take effect in this BIOS either. Compared with the charge maximum limit, I don't think that's a serious problem.

@w568w

w568w commented Jul 14, 2026

Copy link
Copy Markdown
Author

@minortex @LongSang01 Thanks for your research. I managed to analyze the firmwares and found the root cause (I thought so).

I can now control the charging limit without reflashing the firmware. Please check out my write-up: https://gist.github.com/w568w/957976b59906e0ce5d6c13ad342e1593

@gxyrl

gxyrl commented Sep 2, 2026

Copy link
Copy Markdown

I have implemented some control functions without official console, and they work flawlessly when GCUService is stopped. Now It works on both windows and linux, is it necessary to make it a kernel module? https://github.com/minortex/mech-forza-control

update: all the functions controlled by EC has been added to my script, except charging control. Anybody who can test it out will be appreciated!

大佬这个怎么在windows下运行啊?我看没有编译好的可执行文件啊?求教

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment