Contribute
Register

[Guide] How to patch DSDT for working battery status

The OEM DSDT has conflict between SSDT-4 [SaSsdt] and SSDT-6 [NvOptTbl]. The same problem appeared on my previous Yoga 3 14. https://www.tonymacx86.com/threads/guide-lenovo-yoga-3-14-broadwell-hd5500.187138/

Eliminate the SSDT that is not actually loading.
Your profile indicates you don't have Nvidia, so, assuming your profile is accurate, you can simply drop NvOptTbl SSDT.

File updated and still cannot get battery fixed.

It is because BAT0._STA is returning zero.
Look at the code for BAT0._STA:
Code:
                Method (_STA, 0, NotSerialized)  // _STA: Status
                {
                    If (LEqual (ECON, One))
                    {
                        If (ECAV)
                        {
                            If (LEqual (Acquire (LFCM, 0xA000), Zero))
                            {
                                Store (BA1P, Local0)
                                Release (LFCM)
                            }
                        }

                        If (And (Local0, One))
                        {
                            Return (0x1F)
                        }
                        Else
                        {
                            Return (0x0F)
                        }
                    }
                    Else
                    {
                        Return (Zero)
                    }
                }

Ok... so if ECON is not set, it will return zero.
If it returns zero, macOS doesn't even enter it into ACPIplane, it never gets to IOService, and ACPIBatteryManager.kext never starts.

ECON is not set until _REG is called.
See:
Code:
            Method (_REG, 2, NotSerialized)  // _REG: Region Availability
            {
...
                    Store (One, ECON)

Unfortunately, _STA determination is done way before _REG.

You need to fix _STA so it returns 0xF instead of zero in the case ECON is not set yet.
As in:
Code:
                Method (_STA, 0, NotSerialized)  // _STA: Status
                {
                    If (LEqual (ECON, One))
                    {
                        If (ECAV)
                        {
                            If (LEqual (Acquire (LFCM, 0xA000), Zero))
                            {
                                Store (BA1P, Local0)
                                Release (LFCM)
                            }
                        }

                        If (And (Local0, One))
                        {
                            Return (0x1F)
                        }
                        Else
                        {
                            Return (0x0F)
                        }
                    }
                    Else
                    {
                        Return (0xf)
                    }
                }
 
Eliminate the SSDT that is not actually loading.
Your profile indicates you don't have Nvidia, so, assuming your profile is accurate, you can simply drop NvOptTbl SSDT.



It is because BAT0._STA is returning zero.
Look at the code for BAT0._STA:
Code:
                Method (_STA, 0, NotSerialized)  // _STA: Status
                {
                    If (LEqual (ECON, One))
                    {
                        If (ECAV)
                        {
                            If (LEqual (Acquire (LFCM, 0xA000), Zero))
                            {
                                Store (BA1P, Local0)
                                Release (LFCM)
                            }
                        }

                        If (And (Local0, One))
                        {
                            Return (0x1F)
                        }
                        Else
                        {
                            Return (0x0F)
                        }
                    }
                    Else
                    {
                        Return (Zero)
                    }
                }

Ok... so if ECON is not set, it will return zero.
If it returns zero, macOS doesn't even enter it into ACPIplane, it never gets to IOService, and ACPIBatteryManager.kext never starts.

ECON is not set until _REG is called.
See:
Code:
            Method (_REG, 2, NotSerialized)  // _REG: Region Availability
            {
...
                    Store (One, ECON)

Unfortunately, _STA determination is done way before _REG.

You need to fix _STA so it returns 0xF instead of zero in the case ECON is not set yet.
As in:
Code:
                Method (_STA, 0, NotSerialized)  // _STA: Status
                {
                    If (LEqual (ECON, One))
                    {
                        If (ECAV)
                        {
                            If (LEqual (Acquire (LFCM, 0xA000), Zero))
                            {
                                Store (BA1P, Local0)
                                Release (LFCM)
                            }
                        }

                        If (And (Local0, One))
                        {
                            Return (0x1F)
                        }
                        Else
                        {
                            Return (0x0F)
                        }
                    }
                    Else
                    {
                        Return (0xf)
                    }
                }

It works! Thank you!
I have spent too much time figuring out the raw value of battery status and found nothing.
BTW, to create hotpatch for the _STA modify, do I need to replace whole Device (BAT0) to such like BATX, then inject another patched BAT0? or just a long binpatch could fix it?
 
It works! Thank you!
I have spent too much time figuring out the raw value of battery status and found nothing.
BTW, to create hotpatch for the _STA modify, do I need to replace whole Device (BAT0) to such like BATX, then inject another patched BAT0? or just a long binpatch could fix it?

Use "Rename/Replace" pattern for BAT0._STA (eg. rename it to XSTA, then provide replacement that calls original, but returns 0xf in the case that ECON==0).

If you look at a mixed listing for native DSDT.aml, you find BAT0._STA (created with iasl -l DSDT.aml):
Code:
                Method (_STA, 0, NotSerialized)  // _STA: Status
                {

  F865: 14 3E 5F 53 54 41 00                             // .>_STA.

                    If ((ECON == One))
                    {

  F86C: A0 33 93 45 43 4F 4E 01                          // .3.E

The pattern: 14 3E 5F 53 54 41 00, is unique enough (verified in hex editor) for Find/Replace to rename to XSTA:
Find: 14 3E 5F 53 54 41 00
Replace: 14 3E 58 53 54 41 00

From there, you can create replacement BAT0._STA.
Something like:
Code:
External(_SB.PCI0.LPCB.EC0.BAT0, DeviceObj)
External(_SB.PCI0.LPCB.EC0.BAT0.XSTA, MethodObj)
External(ECON, FieldUnitObj)
Method(_SB.PCI0.LPCB.EC0.BAT0._STA)
{
   if (!ECON) { Return(0xf) }
   Return(XSTA())
}

Note: Static patch for the same...
Code:
#RehabMan: fixing BAT0._STA logic bug
into method label _STA parent_label BAT0 code_regex ([\s\S]*) replace_matched
begin
If(!ECON) { Return(0xf) }\n
%1
end;
 
Last edited:
Use "Rename/Replace" pattern for BAT0._STA (eg. rename it to XSTA, then provide replacement that calls original, but returns 0xf in the case that ECON==0).

If you look at a mixed listing for native DSDT.aml, you find BAT0._STA (created with iasl -l DSDT.aml):
Code:
                Method (_STA, 0, NotSerialized)  // _STA: Status
                {

  F865: 14 3E 5F 53 54 41 00                             // .>_STA.

                    If ((ECON == One))
                    {

  F86C: A0 33 93 45 43 4F 4E 01                          // .3.E

The pattern: 14 3E 5F 53 54 41 00, is unique enough (verified in hex editor) for Find/Replace to rename to XSTA:
Find: 14 3E 5F 53 54 41 00
Replace: 14 3E 58 53 54 41 00

From there, you can create replacement BAT0._STA.
Something like:
Code:
External(_SB.PCI0.LPCB.EC0.BAT0, DeviceObj)
External(_SB.PCI0.LPCB.EC0.BAT0.XSTA, MethodObj)
External(ECON, FieldUnitObj)
Method(_SB.PCI0.LPCB.EC0.BAT0._STA)
{
   if (!ECON) { Return(0xf) }
   Return(XSTA())
}

Note: Static patch for the same...
Code:
#RehabMan: fixing BAT0._STA logic bug
into method label _STA parent_label BAT0 code_regex ([\s\S]*) replace_matched
begin
If(!ECON) { Return(0xf) }\n
%1
end;

Hotpatch also works! I really appreciate your help.
 
Hi guys,
Since I couldn't find the battery patch for Acer Aspire 7720G, just wanted to contribute a text file with a working one. Other DSDT patches for Acer were close but didn't exactly match, so it took me a while to write the correct one. The file might need to be checked by RehabMan, but I confirm it works on my build.
I also wanted to thank RehabMan for a fantastic work he is doing.

UPDATE:
Added both the patch file and native DSDT.
 

Attachments

  • Acer-Aspire-7720g-bat.txt
    4.9 KB · Views: 94
  • DSDT-Acer-7720g-native.aml
    32.3 KB · Views: 96
Last edited:
How to patch DSDT for working battery status

:clap:WOW! Thank you! You are the STAR! Such a admirable work.

I tried it out with my own DSDT. It seemed I only have the 16 bit registers to patch.(hooray!)
But here comes my embarrasing....

The code in my DSDT to store value is:
Code:
Store (^^EC0.BVLT, local0)

Maybe that's the reason why my following patch doesn't work:
Code:
into method label _BST code_regex \BVLT, replaceall_matched begin B1B2(VLT0,VLT1), end;

And the funny thing is.. when I use regex to request replace "BVLT" , it only replaces "VLT", when I use the code above..

Is there any way to solve it please?

P.S. my patch code is:
Code:
# 16-bit registers
into device label EC0 code_regex BVLT,\s+16, replace_matched begin VLT0,8,VLT1,8, end;
into device label EC0 code_regex BRMC,\s+16, replace_matched begin RMC0,8,RMC1,8, end;
into device label EC0 code_regex BFCC,\s+16, replace_matched begin FCC0,8,FCC1,8, end;
into device label EC0 code_regex BDSC,\s+16, replace_matched begin DSC0,8,DSC1,8, end;
into device label EC0 code_regex BDSV,\s+16, replace_matched begin DSV0,8,DSV1,8, end;
into device label EC0 code_regex BPRA,\s+16, replace_matched begin PRA0,8,PRA1,8, end;


into method label B1B2 remove_entry;
into definitionblock code_regex . insert
begin
Method (B1B2, 2, NotSerialized) { Return(Or(Arg0, ShiftLeft(Arg1, 8))) }\n
end;


# fix 16-bit methods
into method label _BST code_regex \BVLT, replaceall_matched begin B1B2(VLT0,VLT1), end;
into method label _BST code_regex \BRMC, replaceall_matched begin B1B2(RMC0,RMC1), end;
into method label _BIF code_regex \BFCC, replaceall_matched begin B1B2(FCC0,FCC1), end;
into method label _BIF code_regex \BDSC, replaceall_matched begin B1B2(DSC0,DSC1), end;
into method label _BIF code_regex \BDSV, replaceall_matched begin B1B2(DSV0,DSV1), end;
into method label _BST code_regex \BPRA, replaceall_matched begin B1B2(PRA0,PRA1), end;

and here is my dsdt.amlView attachment 73965


Hi, I follow the method above you to my Surface Pro 3 battery patch, and used ACPIBatteryManager.kext (the current version is RehabMan-Battery-2014-1016), and I found some bug, specifically a normal display power, while the emergence of a small battery fork. I have tried a higher version (including version 2017). For me, only a small battery fork is displayed after the boot (there is no indication of power at all). The system is macOS 10.12.6.

Note: it has been put on“Fix Mutex with non-zero SyncLevel” but still ineffective

Is that my patch problem or ACPIBatteryManager.kext's problem? Could you please take a look at it for me? Thank you very much.


Normal for a while
Normal for a while.png

For a while is not normal
For a while is not normal.png
 

Attachments

  • DSDT_Original.dsl
    494.5 KB · Views: 90
  • DSDT_Revised.dsl
    498.8 KB · Views: 87
Hi guys,
Since I couldn't find the battery patch for Acer Aspire 7720G, just wanted to contribute a text file with a working patch. Other patches for Acer were close but didn't exactly match, so it took me a while to write the correct one. The file might need to be checked by RehabMan.
I also wanted to thank RehabMan for a fantastic work he is doing.


Read post #1, "Contributing".
 
Hi, I follow the method above you to my Surface Pro 3 battery patch, and used ACPIBatteryManager.kext (the current version is RehabMan-Battery-2014-1016), and I found some bug, specifically a normal display power, while the emergence of a small battery fork. I have tried a higher version (including version 2017). For me, only a small battery fork is displayed after the boot (there is no indication of power at all). The system is macOS 10.12.6.

Note: it has been put on“Fix Mutex with non-zero SyncLevel” but still ineffective

Is that my patch problem or ACPIBatteryManager.kext's problem? Could you please take a look at it for me? Thank you very much.


Normal for a while
View attachment 268813
For a while is not normal
View attachment 268814

Read post #1, "Problem Reporting".
 
Read post #1, "Problem Reporting".
into method label FBST code_regex If\s\(CHGS\s\(Zero\)\)[\s]+\{[\s]+Store\s\(0x02,\sLocal0\)[\s]+\}[\s]+Else[\s]+\{[\s]+Store\s\(One,\sLocal0\)[\s]+\} replaceall_matched begin

If (CHGS (Zero))\n

{\n

Store (0x02, Local0)\n

}\n

Else\n

{\n

Store (Zero, Local0)\n

}

end;
12.png
I don't seem to understand the code. Can you tell me exactly how to do it? Or you can change it for me
 

Attachments

  • DSDT_Revised.dsl
    498.8 KB · Views: 99
Back
Top