Jump to content
Astarael

Rozpoznawanie stanu baterii

Recommended Posts

Jak niektórzy pewnie zauważyli, w Mac OS X 10.7.x Apple dokonało pewnych wewnętrznych zmian, przez które sprawdzony kext AppleACPIBatteryManager przestał działać. Problem można było obejść, przywracając kexty ze Snow Leoparda, jednak nie wszystkich takie połowiczne rozwiązanie zadowala, zwłaszcza że rollback trzeba wykonywać po każdej aktualizacji systemu.

 

Problem tkwi w DSDT, dokładniej w sekcji urządzenia EC. Lion pobiera informacje o statusie baterii w porcjach ośmiobitowych, zaś w większości laptopów dane te są przechowywane w polach szesnastobitowych. Efekt? Przekreślona ikona baterii lub jej zupełny brak - nieważne, czy używamy AppleACPIBattery czy VoodooBattery. Na szczęście ktoś mądry stworzył kext kombatybilny z Lionem. Na nieszczęście trzeba modyfikować DSDT, żeby kext ten zadziałał, dokładniej trzeba podzielić większe pola na fragmenty po 8 bitów każdy, żeby nasze DSDT nie kłóciło się z nową filozofią Liona. Modyfikacja, choć czasochłonna, jest naprawdę prosta.

 

Na początku w DefinitionBlock (zaraz po pierwszej klamrze otwierającej) dodajemy metody, które wykorzystamy później:

	//Metody na użytek rozpoznawania statusu bateryjki
Method (B1B2, 2, NotSerialized) 
   { 
	Or (ShiftLeft(Arg1,0x08), Arg0, Local0) 
       Return (Local0) 
   } //pola 16-bitowe 

Method (B1B4, 4, NotSerialized)      
{ 
       Or (ShiftLeft(Arg1,0x08), Arg0, Local0) 
       Or (ShiftLeft(Arg2,0x10), Local0, Local0) 
       Or (ShiftLeft(Arg3,0x18), Local0, Local0) 
   	Return (Local0) 
} //pola 32-bitowe

Method (L1L4, 4, NotSerialized)//32*4=128
{ 
       Or (ShiftLeft(Arg1,0x20), Arg0, Local0) 
       Or (ShiftLeft(Arg2,0x40), Local0, Local0) 
       Or (ShiftLeft(Arg3,0x60), Local0, Local0) 
       Return (Local0) 
}//pola 128-bitowe

Następnie oszukujemy w DSDT sekcję urządzenia EC (Device (EC) - może się ona nazywać różnie, np. EC0, H_EC itp. Zwykle znajduje się wewnątrz sekcji LPC. Następnie przewijamy w dół aż natrafimy na coś, co wygląda m/w tak:

                    OperationRegion (ECR, EmbeddedControl, 0x00, 0xFF) 
   Field (ECR, ByteAcc, Lock, Preserve) 
   { 
           Offset (0x18), 
       SPTR,   8, 
       SSTS,   8, 
       SADR,   8, 
       ...

Przy czym nazwy pól ani nazwa sekcji wcale nie muszą się pokrywać z powyższym przykładem!

Teraz należy każde pole 16-bitowe zmienić na dwa pola 8-bitowe, każde 32-bitowe na cztery 8-bitowe, a 128-bitowe na 16(!) 8-bitowych. Poniżej przykłady dokonywanych zmian.

 

Pole 16-bitowe

	SBTI,   16,

zastępujemy

	BTI0,    8,
BTI1, 	8,

 

Pole 32-bitowe

	B1AF,   32,

zastępujemy

	BAF0,	8,
   BAF1,	8,
   BAF2,	8,
   BAF3,	8,

 

Pole 128-bitowe

	SBMN,    128,

	BMN0,   8, 
   BMN1,   8, 
   BMN2,   8, 
   BMN3,   8, 
   BMN4,   8, 
   BMN5,   8, 
   BMN6,   8, 
   BMN7,   8, 
   BMN8,   8, 
   BMN9,   8,
   BMNA,   8, 
   BMNB,   8, 
   BMNC,   8, 
   BMND,   8, 
   BMNE,   8, 
BMNF,   8,

 

Nazewnictwo

Ponieważ specyfikacja ACPI nie pozwala na nazwy pól dłuższe niż cztery znaki, rozbijając dane pole, np. ABCD musimy zrobić miejsce dla indeksu i skasować którąś literę. W przykładzie dla 16 i 128 bitów zdecydowałem się na usunięcie pierwszej, co dla pola ABCD dałoby nam BCD + indeks. Indeks to po prostu cyfra rozróżniająca poszczególne fragmenty danego pola. Dla 16 bitów mamy BCD0 oraz BCD1 (komputery liczą od zera).

 

Dla pola 128-bitowego braknie nam "normalnych" cyfr do indeksowania, więc musimy wykorzystać również litery (lub jak kto woli – cyfry szesnastkowe). Gdybyśmy pole ABCD rozbili na 16 składowych, moglibyśmy nadać im następujące nazwy:

BCD0, BCD1, BCD2, BCD3, BCD3, BCD4, BCD5, BCD6, BCD7, BCD8, BCD9, BCDA, BCDB, BCDC, BCDD, BCDE, BCDF

Wyżej przytoczony przykład dla pola 32-bitowego jest nieco inny, ponieważ drugi znak w jego nazwie, to cyfra. Gdybyśmy po prostu usunęli pierwszy znak, zostałaby ona umieszczona na pierwszym miejscu, a taka nazwa pola mogłaby się nie spodobać kompilatorowi, dlatego też w tym przykładzie usunąłem właśnie ową cyfrę. Dla hipotetycznego pola 32-bitowego o nazwie A1BC podział mógłby wyglądać tak:

ABC0, ABC1, ABC2, ABC3

Co począć w sytuacji, gdy gdzieś dalej w kodzie pojawi się pole o niemalże identycznej nazwie, różniącej się tylko cyfrą, np. A2BC? Można po prostu "liczyć dalej", a więc przyjąć następujący podział:

ABC4, ABC5, ABC6, ABC7

Oczywiście można stosować właściwie dowolne nazewnictwo, jednakże pola muszą być rozróżnialne, to znaczy nazwy nie mogą się powtarzać - sugeruję każdorazowe sprawdzanie przed dokonaniem podziału - warto jest jednak przyjąć pewien w miarę konsekwentny schemat nadawania nazw, który ułatwi niepogubienie się ;)

 

 

Teraz trochę trudniejsza część: trzeba zmienić wszystkie odwołania do pól, bo inaczej nie dość, że bateria nie zadziała, to jeszcze DSDT się nie skompiluje :D Do tego posłużą nam dodane wcześniej metody.

 

Odwołania do pól 16-bitowych, np:

Store (SBTI, Local0)

zastępujemy

Store (B1B2(BTI0, BTI1), Local0)

 

Odwołania do pól 32-bitowych, np:

Store (B1AF, Local0)

zastępujemy

Store (B1B4(BAF0, BAF1, BAF2, BAF3), Local0)

 

Odwołania do pól 128-bitowych, np:

Store (SBMN, Local0)

zastępujemy

Store (L1L4 (B1B4 (BMN0, BMN1, BMN2, BMN3),
B1B4 (BMN4, BMN5, BMN6, BMN7),
B1B4 (BMN8, BMN9, BMNA, BMNB),
B1B4 (BMNC, BMND, BMNE, BMNF)), Local0)

 

Na koniec kompilujemy DSDT i umieszczamy je w stosownym miejscu (zwykle /Extra/) oraz instalujemy kext z załącznika pochodzący z forum pcbeta (najwygodniej za pomocą programu KextWizard). Jeszcze raz przypominam, że stary AppleACPIBatteryManager nie będzie działać, powyższa modyfikacja przeznaczona jest wyłącznie dla nowej wersji!

 

Korzystałem z tego tematu:

http://www.insanelymac.com/forum/index.php?showtopic=272459&st=0

Podziękowania:

oswaldini – za podlinkowanie w/w tematu na naszym forum, dokładniej tutaj

man_of_the_oak – za znalezienie AppleACPIBatteryManager, na którym nie występują opóźnienia po odłączeniu zasilacza

MietasSR - za przetestowanie DSDT zmodyfikowanego wg w/w metody na Mountain Lionie z pozytywnym skutkiem :D

AppleACPIBatteryManager_10.7.3_no_delay.kext.zip

Share this post


Link to post
Share on other sites

Należy w ten sposób zamienić wszystkie sekcje z rejestrami, czy tylko jakąś konkretną? Na przykład ja mam coś takiego (zaraz za Device (EC)):

                    OperationRegion (ECOR, EmbeddedControl, 0x00, 0x0100) 
                   Field (ECOR, ByteAcc, NoLock, Preserve) 
                   { 
                       HDBM,   1, 
                           ,   1, 
                           ,   1, 
                       ...
                               Offset (0xB0), 
                       HDEN,   32, 
                       HDEP,   32, 
                       HDEM,   8, 
                       HDES,   8, 
                       ...
                               Offset (0xED), 
                           ,   4, 
                       HDDD,   1
                   }

 

Kilkadziesiąt linijek dalej mam np. takie sekcje:

                    Method (_Q25, 0, NotSerialized) 
                   { 
                       If (And (^BAT1.B1ST, ^BAT1.XB1S)) 
                       { 
                           CLPM () 
                           Notify (BAT1, 0x80) 
                       } 
                   } 

                   Field (ECOR, ByteAcc, NoLock, Preserve) 
                   { 
                               Offset (0xA0), 
                       SBRC,   16, 
                       ...
                       SBBS,   16
                   } 

                   Field (ECOR, ByteAcc, NoLock, Preserve) 
                   { 
                               Offset (0xA0), 
                           ,   15, 
                       SBCM,   1, 
                       SBMD,   16, 
                       SBCC,   16
                   } 

                   Field (ECOR, ByteAcc, NoLock, Preserve) 
                   { 
                               Offset (0xA0), 
                       SBDC,   16, 
                       ...
                       SBSN,   16
                   } 

                   Field (ECOR, ByteAcc, NoLock, Preserve) 
                   { 
                               Offset (0xA0), 
                       SBCH,   32
                   } 

                   Field (ECOR, ByteAcc, NoLock, Preserve) 
                   { 
                               Offset (0xA0), 
                       SBMN,   128
                   } 

                   Field (ECOR, ByteAcc, NoLock, Preserve) 
                   { 
                               Offset (0xA0), 
                       SBDN,   128
                   }

Share this post


Link to post
Share on other sites
Masakra, przecież to bite 2-3 godziny roboty non stop, ale łatwe do zrobienia - ciekawe czy działa :D
Trochę przejaskrawiasz, ale istotnie - sporo roboty. Tyle dobrego, że nie do wszystkich pól są odwołania ;)
Należy w ten sposób zamienić wszystkie sekcje z rejestrami, czy tylko jakąś konkretną? Na przykład ja mam coś takiego (zaraz za Device (EC)):
Zmieniasz wszystkie sekcje z rejestrami wewnątrz EC. Jak testowałem moda u siebie, niechcący jedną pominąłem. Zgadnij, co się stało... Śliczne kp!

Share this post


Link to post
Share on other sites
Co jeśli ktoś nie ma "Device (EC)"

To występuje pod inną nazwą. Patrz tutek.

Nie mogę znaleść tego u siebie, tak samo jak DTGP

Życzę powodzenia w szukaniu... Tego standardowo nie ma, tą sekcję się dodaje samemu ! Patrz tutki o DSDT, podstawowe modyfikacje.

Share this post


Link to post
Share on other sites

Postanowiłem się za to zabrać aby już nie robić rollbacka szczególnie, że DP2 z kextem z 10.6.7 jakoś długo się uruchamia a z oryginalnym o wiele lepiej. Mam małe pytanie odnośnie tej modyfikacji :

 

...
SPTR,   8, 
                       SSTS,   8, 
                       SADR,   8, 
                       SCMD,   8, 
                       SBFR,   256, 
                       SCNT,   8, 
...

 

Jak zmodyfikować SBFR ? Jak widać ma wartość 256, mam z tego zrobić 32 sekcje po 8 ? Czy może modyfikacja ogranicza się tylko do 16,32,64 i 128 ?

Share this post


Link to post
Share on other sites

Tak jak w instrukcji w pierwszym poście. Rany julek ludzie czytać.

dokładniej trzeba podzielić większe pola na fragmenty po 8 bitów każdy

256/8 = 32 - czyli z jednej sekcji 256 bitów musisz zrobić 32 sekcje po 8 bitów.

Share this post


Link to post
Share on other sites
Rany julek ludzie czytać.

 

Ehh.. Rany julek :) czytam i to dokładnie. W sekcji którą dodaje się zaraz po DefinitionBlock nie ma kodu dla wartości 256bit. Dlatego zadałem pytanie o konieczność dzielenia tej wartości na 8 tym samym proponując rozwiązanie które Ty potwierdziłeś więc : 1. Czytam. 2. Pytam aby się upewnić.

 

Poległem na 2 liniach - nie mam pojęcia jak je zmodyfikować :

 

If (LNotEqual (\_SB.PCI0.LPCB.H_EC.B1DF, \_SB.BFCC))

 

Nie ma już B1DF bo jak wiadomo wartość została rozbita na BDF0 i BDF1

 

Store (\_SB.PCI0.LPCB.H_EC.B1DF, \_SB.BFCC)

 

Ta sama sytuacja...

Share this post


Link to post
Share on other sites
W sekcji którą dodaje się zaraz po DefinitionBlock nie ma kodu dla wartości 256bit.
To dlatego, że na 99% do pola 256-bitowego, nawet jeśli takowe wystąpi w DSDT, nie ma nigdzie odwołań. Sprawdź, czy ta nazwa jest gdzieś używana, ale obstawiam, że nie jest.
Poległem na 2 liniach - nie mam pojęcia jak je zmodyfikować :
Nie wiem, w czym masz problem... zastąp odwołanie do pola wywołaniem odpowiedniej metody i po krzyku.

Share this post


Link to post
Share on other sites

1. Nie rozbijałem tej wartości 256bitowej - zostawiłem jak była. (brak odwołań)

2.

If (LNotEqual (\_SB.PCI0.LPCB.H_EC.B1DF, \_SB.BFCC))

=

If (LNotEqual (B1B2 (\_SB.PCI0.LPCB.H_EC.BDF0, \_SB.PCI0.LPCB.H_EC.BDF1), \_SB.BFCC))

3.

Store (\_SB.PCI0.LPCB.H_EC.B1DF, \_SB.BFCC)

=

Store (B1B2 (\_SB.PCI0.LPCB.H_EC.BDF0, \_SB.PCI0.LPCB.H_EC.BDF1), \_SB.BFCC)

4. Bateria działa jak marzenie :) Lion oraz M. Lion DP2 - Dzięki za pomoc i poradnik !!

 

[ Komentarz dodany przez: 314TeR: 2012-03-19, 10:52 ]

Tak będzie czytelniej, a przy okazji będzie dobry przykład jak modyfikować kod.

Share this post


Link to post
Share on other sites

Spróbuj dodaj jeszcze jedną metodę, np:

    Method (D1D2, 2, NotSerialized)//128*2=256
   { 
       Or (ShiftLeft(Arg1,0x80), Arg0, Local0) 
       Return (Local0) 
   }//pola 128-bitowe	

Jako argumenty musisz podać wynik L1L4, więc całe wywołanie będzie dość długie. Niemniej spróbować musisz, bo ja nie posiadam dostępu do OS X i sam tego sprawdzić nie mogę ;)

Share this post


Link to post
Share on other sites
Ja także pisze w związku z wartościami 256. Mam takie dwie w moim urządzeniu EC0 i obie mają późniejsze odwołania w DSDT.

Jakie i dokąd te odwołania... być może nie mają znaczenia i je zwyczajnie zostaw nietknięte.

Share this post


Link to post
Share on other sites

No to wszystko jasne :) Sobie wymyślę jakiś pattern i wyedytuję co trzeba :)

 

EDIT

Pierwszy KP za mną - na bank coś poknociłem. Niby plik się skompilował (kompilowałem przez Chameleon Wizzard) ale może coś zapomniałem :)

Sprawdziłem sobie, że XX** , XY** i XZ** nie są nigdzie w pliku używane, więc teraz polecę sobie XXA0,XXA1, XXB0, XXB1 itp :) W swoim DSDT mam tylko 16bit

 

 OperationRegion (ECOR, EmbeddedControl, Zero, 0xFF) 
           Field (ECOR, ByteAcc, Lock, Preserve) 
           { 
               Offset (0x04), 
               CMD1,   8, 
               CDT1,   8, 
               CDT2,   8, 
               CDT3,   8, 
               Offset (0x80), 
               EPWS,   8, 
               EB0S,   8, 
               EB1S,   8, 
               EB0R,   8, 
               EB1R,   8, 
               EPWF,   8, 
               Offset (0x87), 
               EB0T,   8, 
               EB1T,   8, 
               Offset (0x8A), 
               HKEN,   1, 
               Offset (0x93), 
               TAH0,   16, 
               TAH1,   16, 
               TSTP,   8, 
               Offset (0x9C), 
               CDT4,   8, 
               CDT5,   8, 
               Offset (0xA0), 
               ECPU,   8, 
               ECRT,   8, 
               EPSV,   8, 
               EACT,   8, 
               TH1R,   8, 
               TH1L,   8, 
               TH0R,   8, 
               TH0L,   8, 
               Offset (0xB0), 
               B0PN,   16, 
               B0VL,   16, 
               B0RC,   16, 
               B0FC,   16, 
               B0MD,   16, 
               B0ST,   16, 
               B0CC,   16, 
               B0TM,   16, 
               B0C1,   16, 
               B0C2,   16, 
               B0C3,   16, 
               B0C4,   16, 
               Offset (0xD0), 
               B1PN,   16, 
               B1VL,   16, 
               B1RC,   16, 
               B1FC,   16, 
               B1MD,   16, 
               B1ST,   16, 
               B1CC,   16, 
               B1TM,   16, 
               B1C1,   16, 
               B1C2,   16, 
               B1C3,   16, 
               B1C4,   16, 
               Offset (0xF0), 
               B0DC,   16, 
               B0DV,   16, 
               B0SN,   16, 
               Offset (0xF8), 
               B1DC,   16, 
               B1DV,   16, 
               B1SN,   16
           }

Mam rozumieć, że tylko te mam pozamieniać na 2 pary 8 bitowe a potem w każdym miejscu, gdzie te zmienne występują muszę je zastąpić funkcją?

 

EDIT2

Mam problem ... wcześniej jest napisane, że muszę wszystkie wartości w sekcji EC "zdegradować" do 8 bitowych.

Zatem zaraz pod sekcją przytoczoną poniżej mam to:

 

Name (SMBF, Zero) 
           OperationRegion (SMBX, EmbeddedControl, 0x18, 0x28) 
           Field (SMBX, ByteAcc, NoLock, Preserve) 
           { 
               PRTC,   8, 
               SSTS,   5, 
                   ,   1, 
               ALFG,   1, 
               CDFG,   1, 
               ADDR,   8, 
               CMDB,   8, 
               BDAT,   256, 
               BCNT,   8, 
                   ,   1, 
               ALAD,   7, 
               ALD0,   8, 
               ALD1,   8
           } 

Jest tu wartość 256bit ... niby jak nie ma odwołań w pliku to nie muszę nic zmieniać, ale ... u mnie ta zmienna występuje

 

Method (ASBR, 2, NotSerialized) 
       { 
           If (LLess (Arg1, 0x30)) 
           { 
               Return (0x02) 
           } 

           OperationRegion (\F112, SystemMemory, Arg0, Arg1) 
           Field (F112, DWordAcc, NoLock, Preserve) 
           { 
               Offset (0x08), 
               BATN,   8, 
               BATA,   8, 
               REGS,   8, 
               BDAT,   16, 
               BLEN,   8, 

 

If (LEqual (BATA, Zero)) 
           { 
               Store (^^PCI0.SBRG.EC0.SMBR (^^PCI0.SBRG.EC0.RDWD, ^^PCI0.SBRG.EC0.BADR, REGS), Local0) 
               Store (DerefOf (Index (Local0, 0x02)), BDAT) 

 

If (LEqual (BATA, One)) 
           { 
               Store (^^PCI0.SBRG.EC0.SMBW (^^PCI0.SBRG.EC0.WRWD, ^^PCI0.SBRG.EC0.BADR, REGS, 0x02, BDAT), Local0) 

 

Field (F113, DWordAcc, NoLock, Preserve) 
           { 
               Offset (0x08), 
               BATN,   8, 
               BATA,   8, 
               REGS,   8, 
               BDAT,   8
           } 

 

If (LEqual (BATA, Zero)) 
           { 
               Store (^^PCI0.SBRG.EC0.RBEP (REGS), Local2) 
               And (Local2, 0xFF, Local3) 
               Store (Local3, BDAT) 

 

If (LEqual (BATA, One)) 
           { 
               Store (^^PCI0.SBRG.EC0.WBEP (REGS, BDAT), Local2) 

 

Store (Zero, BDAT) 

 

 Store (BDAT, Index (Local0, 0x02))

 

I klika innych ... skołowany jestem ... :/

Share this post


Link to post
Share on other sites

Hmmm... zrobiłem tak jak opisałeś i jedyne co, to działa wyświetlanie baterii na pasku, ale samo rozpoznawanie baterii nie

http://cl.ly/image/1l2Z0x0m1V2h

 

[ Dodano: 2012-12-04, 06:18 ]

O, po którymś reboocie się pojawiła ^^

Także potwierdzam działanie w/w metody na 10.8.2 ;)

 

[ Dodano: 2012-12-04, 12:46 ]

No dobra, koniec końców: raz działa, raz nie działa, w zależności od kaprysu systemu... any ideas?

Share this post


Link to post
Share on other sites

Nie wiem, czy to działanie na okrętkę, ale na czystym Mountain Lion zainstalowałem to:

http://www.osx86.net/downloads.php?do=file&id=3169

 

O dziwo pojawiła się ikona baterii ... wyczuwa podłączenie kabla, odłączenie kabla oraz poziom naładowania w %

 

W DSDT nie było fixa, bo nie znalazłem nigdzie odpowiedzi na 256 bitową wartość

Share this post


Link to post
Share on other sites

Tam jest napisane, że trzeba rozbić na 32 sekcje 8bit - to jest proste ...

Ale niżej w postach osoba pytająca pisze, że w metodach dodanych zaraz po sekcji EC nie ma dla 256bit - jest dla 16, 32 i 128. Dalej dostaje info, że do 256bit nie trzeba, bo najczęściej nie ma do nich odwołań a ta osoba to potwierdza więc nie musiała nic więcej robić.

U mnie jest inaczej, gdyż do pola 256bit mam odwołanie i muszę te wartości połączyć ...

Pisałem zresztą o tym kilka postów wyżej.

Po prostu jak wpiszę w wyszukiwarkę BDAT to jest tego kilka w pliku ...

 

Dziś jeszcze korzystając z wolnego czasu i tego, że mam dwa dyski (jeden w kieszeni) i na obu działa ML to się pobawię. Jak będzie KP to bootuje z drugiego dysku i przywracam.

Share this post


Link to post
Share on other sites

Ma ktoś aktualną i sprawdzoną pod 10.8.2 wersję AppleACPIBatteryManager, u mnie po wrzuceniu samego kexta do /S/L/E, nawet bez DSDT w ogóle powoduje piękny KP i restart podczas ładowania systemu z cloverem.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.