Contribute
Register

[Guide] How to patch DSDT for working battery status

Hi Rehabman,
It may be a stupid question, and maybe someone already asked it, but going through all 356 pages of this thread was an ultimate journey. So here is.
In my dsdt, I have two 128bit register on EC region
Code:
                    Field (ECOR, ByteAcc, NoLock, Preserve)
                    {
                        Offset (0xA0),
                        SBMN,128
                    }

                    Field (ECOR, ByteAcc, NoLock, Preserve)
                    {
                        Offset (0xA0),
                        SBDN,   128
                    }
How come those two register have the same offset?
Does it means I have to use the same offset for two opcode that read those two register?
Code:
Store (SBMN, Index (Arg1, 0x0C))
and
Code:
Store (SBDN, Index (Arg1, 0x09))
change with the same
Code:
(RECB(0xA0,128)

Attached half patched dsdt, for all 16 and 32 bit register.
 

Attachments

  • DSDT.aml
    64.8 KB · Views: 143
Hi Rehabman,
It may be a stupid question, and maybe someone already asked it, but going through all 356 pages of this thread was an ultimate journey. So here is.
In my dsdt, I have two 128bit register on EC region
Code:
                    Field (ECOR, ByteAcc, NoLock, Preserve)
                    {
                        Offset (0xA0),
                        SBMN,128
                    }

                    Field (ECOR, ByteAcc, NoLock, Preserve)
                    {
                        Offset (0xA0),
                        SBDN,   128
                    }
How come those two register have the same offset?

Because they are two names for exactly the same region in the EC.

Does it means I have to use the same offset for two opcode that read those two register?
Code:
Store (SBMN, Index (Arg1, 0x0C))
and
Code:
Store (SBDN, Index (Arg1, 0x09))
change with the same
Code:
(RECB(0xA0,128)

Yes.
 
You can see in ioreg that BAT0._STA is returning 0x0b. Should be 0x1f for battery present. So... your DSDT is reporting no battery present.

This is based on BNUM which is set in H_EC._REG based on some calls to ECRD. You could debug this code with ACPIDebug.kext. You might have to rewrite the code to not use ECRD with RefOf... for example this line:
Code:
                    Or (BNUM, ShiftRight (And (ECRD (RefOf (ECWR)), 0x02), One), BNUM)

Can be written:
Code:
                    Or (BNUM, ShiftRight (And (ECWR, 0x02), One), BNUM)

It could be also that previous patches put the EC in a bad state... so make sure you do EC reset.

Okies, so I realized that BIF[4] is initialized with a huge value and never actually set to a sane value. Fixing that I got working battery status now although BAT0._STA is still returning 0x0b.

Is it worth trying to fix that or should I just leave it be?
 
Still more mistakes...
- SMD0 is not at offset 0x0a.
- removing and replacing existing native RECB/WECB methods is a bad idea
- other misc...

Here is my proposed fixed patch (so far):
Code:
#Maintained by: RehabMan for: Laptop Patches
#battery_Lenovo-L420.txt

# Created by kosakgroove 2016-12-02.  Some additions/fixes by RehabMan

# Works for:
#   Lenovo L420

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

into method label B1B4 remove_entry;
into definitionblock code_regex . insert
begin
Method (B1B4, 4, NotSerialized)\n
{\n
    Store(Arg3, Local0)\n
    Or(Arg2, ShiftLeft(Local0, 8), Local0)\n
    Or(Arg1, ShiftLeft(Local0, 8), Local0)\n
    Or(Arg0, ShiftLeft(Local0, 8), Local0)\n
    Return(Local0)\n
}\n
end;

into device label EC code_regex BATD,\s+16, replace_matched begin ATD0,8,ATD1,8, end;
into device label EC code_regex SMW0,\s+16 replace_matched begin MW00,8,MW01,8 end;
into device label EC code_regex SBRC,\s+16, replace_matched begin BR00,8,BR01,8, end;
into device label EC code_regex SBFC,\s+16, replace_matched begin BF00,8,BF01,8, end;
into device label EC code_regex SBVO,\s+16, replace_matched begin BV00,8,BV01,8, end;
into device label EC code_regex SBSN,\s+16 replace_matched begin SN00,8,SN01,8 end;
into device label EC code_regex SBDC,\s+16, replace_matched begin DC00,8,DC01,8, end;
into device label EC code_regex SBDV,\s+16, replace_matched begin DV00,8,DV01,8, end;
into device label EC code_regex SBAE,\s+16, replace_matched begin BA00,8,BA01,8, end;
into device label EC code_regex SBAF,\s+16, replace_matched begin BB00,8,BB01,8, end;
into device label EC code_regex SBBS,\s+16, replace_matched begin BD00,8,BD01,8, end;
into device label EC code_regex SBMD,\s+16, replace_matched begin SB00,8,SB01,8, end;
into device label EC code_regex SBCC,\s+16, replace_matched begin CC00,8,CC01,8, end;
into device label EC code_regex SBOM,\s+16, replace_matched begin OM00,8,OM01,8, end;
into device label EC code_regex SBSI,\s+16, replace_matched begin SI00,8,SI01,8, end;
into device label EC code_regex SBDT,\s+16, replace_matched begin DT00,8,DT01,8, end;
into device label EC code_regex SBAC,\s+16, replace_matched begin AC00,8,AC01,8, end;

into method label SELE code_regex \(BATD, replaceall_matched begin (B1B2(ATD0,ATD1), end;
into method label SMRD code_regex \(SMW0, replaceall_matched begin (B1B2(MW00,MW01), end;
into method label SMWR code_regex \(\^PCI0\.LPCB\.EC\.SMW0, replaceall_matched begin (B1B2(^PCI0.LPCB.EC.MW00,^PCI0.LPCB.EC.MW01), end;
into method label GBST code_regex \(\^PCI0\.LPCB\.EC\.SBRC, replaceall_matched begin (B1B2(^PCI0.LPCB.EC.BR00,^PCI0.LPCB.EC.BR01), end;
into method label GBIF code_regex \(\^PCI0\.LPCB\.EC\.SBFC, replaceall_matched begin (B1B2(^PCI0.LPCB.EC.BF00,^PCI0.LPCB.EC.BF01), end;
into method label GBST code_regex \(\^PCI0\.LPCB\.EC\.SBVO, replaceall_matched begin (B1B2(^PCI0.LPCB.EC.BV00,^PCI0.LPCB.EC.BV01), end;
into method label GBIF code_regex \(\^PCI0\.LPCB\.EC\.SBSN, replaceall_matched begin (B1B2(^PCI0.LPCB.EC.SN00,^PCI0.LPCB.EC.SN01), end;
into method label GBIF code_regex \(\^PCI0\.LPCB\.EC\.SBDC, replaceall_matched begin (B1B2(^PCI0.LPCB.EC.DC00,^PCI0.LPCB.EC.DC01), end;
into method label GBIF code_regex \(\^PCI0\.LPCB\.EC\.SBDV, replaceall_matched begin (B1B2(^PCI0.LPCB.EC.DV00,^PCI0.LPCB.EC.DV01), end;
into method label GBST code_regex \(\^PCI0\.LPCB\.EC\.SBAC, replaceall_matched begin (B1B2(^PCI0.LPCB.EC.AC00,^PCI0.LPCB.EC.AC01), end;

into device label EC code_regex SBCH,\s+32 replace_matched begin SH00,8,SH01,8,SH02,8,SH03,8, end;
into method label GBIF code_regex \(\^PCI0\.LPCB\.EC\.SBCH, replaceall_matched begin (B1B4(^PCI0.LPCB.EC.SH00,^PCI0.LPCB.EC.SH01,^PCI0.LPCB.EC.SH02,^PCI0.LPCB.EC.SH03), end;
into method label SMWR code_regex Store\s\(Arg3,\sSMW0\) replaceall_matched begin Store (Arg3,MW00) Store(ShiftRight(Arg3,8),MW01)  end;

into method label RE1B parent_label EC remove_entry;
into method label RXCB parent_label EC remove_entry;
into device label EC insert
begin
Method (RE1B, 1, NotSerialized)\n
// Arg0 - offset in bytes from zero-based EC\n
{\n
    OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
    Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
    Return(BYTE)\n
}\n
Method (RXCB, 2, Serialized)\n
// Arg0 - offset in bytes from zero-based EC\n
// Arg1 - size of buffer in bits\n
{\n
    ShiftRight(Arg1, 3, Arg1)\n
    Name(TEMP, Buffer(Arg1) { })\n
    Add(Arg0, Arg1, Arg1)\n
    Store(0, Local0)\n
    While (LLess(Arg0, Arg1))\n
    {\n
        Store(RE1B(Arg0), Index(TEMP, Local0))\n
        Increment(Arg0)\n
        Increment(Local0)\n
    }\n
    Return(TEMP)\n
}\n
end;

into device label EC code_regex (SBMN,)\s+(128) replace_matched begin BMNX,%2,//%1%2 end;
into device label EC code_regex (SBDN,)\s+(128) replace_matched begin BDNX,%2,//%1%2 end;
into device label EC code_regex (FLD0,)\s+(64) replace_matched begin FL0X,%2,//%1%2 end;
into device label EC code_regex (FLD1,)\s+(128) replace_matched begin FL1X,%2,//%1%2 end;
into device label EC code_regex (FLD2,)\s+(192) replace_matched begin FL2X,%2,//%1%2 end;
into device label EC code_regex (FLD3,)\s+(256) replace_matched begin FL3X,%2,//%1%2 end;
into device label EC code_regex (SMD0,)\s+(100) replace_matched begin SMDX,%2,//%1%2 end;

into method label GBIF code_regex \(\^PCI0\.LPCB\.EC\.SBMN, replaceall_matched begin (^PCI0.LPCB.EC.RXCB(0xA0,128), end;
into method label GBIF code_regex \(\^PCI0\.LPCB\.EC\.SBDN, replaceall_matched begin (^PCI0.LPCB.EC.RXCB(0xA0,128), end;
into method label SMRD code_regex \(\FLD1, replaceall_matched begin (RXCB(0x54,128), end;
into method label SMRD code_regex \(\FLD2, replaceall_matched begin (RXCB(0x54,192), end;
into method label SMRD code_regex \(\FLD3, replaceall_matched begin (RXCB(0x54,256), end;
into method label BFWL code_regex \(SMD0, replaceall_matched begin (RXCB(0x54,100), end;

into method label WE1B parent_label EC remove_entry;
into method label WXCB parent_label EC remove_entry;
into device label EC insert
begin
Method (WE1B, 2, NotSerialized)\n
{\n
    OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
    Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
    Store(Arg1, BYTE)\n
}\n
Method (WXCB, 3, Serialized)\n
// Arg0 - offset in bytes from zero-based EC\n
// Arg1 - size of buffer in bits\n
// Arg2 - value to write\n
{\n
    ShiftRight(Add(Arg1,7), 3, Arg1)\n
    Name(TEMP, Buffer(Arg1) { })\n
    Store(Arg2, TEMP)\n
    Add(Arg0, Arg1, Arg1)\n
    Store(0, Local0)\n
    While (LLess(Arg0, Arg1))\n
    {\n
        WE1B(Arg0, DerefOf(Index(TEMP, Local0)))\n
        Increment(Arg0)\n
        Increment(Local0)\n
    }\n
}\n
end;

# Calling WXCB method to write into SMDX (offset 0x54)
into method label SMWR code_regex Store\s?\(Arg3,\s?\SMD0\) replaceall_matched begin WXCB (0x54,100,Arg3) end;

It works perfect with your modifications to the patch, you should upload it to your repo,
http://www.insanelymac.com/forum/topic/320306-guide-lenovo-thinkpad-l420-with-el-capitan/
 
Okies, so I realized that BIF[4] is initialized with a huge value and never actually set to a sane value. Fixing that I got working battery status now although BAT0._STA is still returning 0x0b.

Is it worth trying to fix that or should I just leave it be?

0x0b is invalid. It indicates "no battery present".
 
As far as I know, I've made no "modifications" as you seem to imply.
New patches or corrections should be submitted to the battery patch thread as per post #1, "Contributing".
Whatever, I don't really care if it is uploaded or not, I just thought it would be useful, do whatever you want with the patch buddy
 
Whatever, I don't really care if it is uploaded or not, I just thought it would be useful, do whatever you want with the patch buddy

No idea what patch you're referring to.
I don't see anything meeting the requirements set out in post #1, "Contributing".
Sorry... no time to dig around for things (it takes enough time to add new patches when properly submitted).
 
0x0b is invalid. It indicates "no battery present".

Yeah, I know that this isn't correct. I am just asking if it could be bad if I just hardcoded "0x1f" for example. Since it is a tablet PC there is pretty much always a battery in there anyway. Even if I wanted I couldn't easily remove the battery. It just seems a lot of work trying to fix something, that might not be important at all.

In any case, thanks for helping us all out here RehabMan, you rock =) If it wasn't for you and guys like you all this wouldn't be possible.
 
Yeah, I know that this isn't correct. I am just asking if it could be bad if I just hardcoded "0x1f" for example. Since it is a tablet PC there is pretty much always a battery in there anyway. Even if I wanted I couldn't easily remove the battery. It just seems a lot of work trying to fix something, that might not be important at all.

In any case, thanks for helping us all out here RehabMan, you rock =) If it wasn't for you and guys like you all this wouldn't be possible.

Hardcoding it to 0x1f is fine in a scenario where you know the battery cannot be removed.
 
Back
Top