Patch pin
Tìm hiểu thuật ngữ
Trước tiên ta phải hiểu nguyên tác hoạt động:
Các bản AppleACPIPlatform
mới không thể nào truy cập chính xác vào trường EC (Embedded Controller
) nên nó sẽ gây ra 1 số lỗi khi sử dụng các kext hiển thị phần trăm pin, bạn phải tiến hành sửa đổi DSDT để nó nhận chính xác mặc dù bạn có thể dùng các bản AppleACPIPlatform
cũ hơn (Snow Leopard
) nhưng vì các CPU đời Ivy Birdge +
có hỗ trợ tính năng quản lý năng lượng nên mình khuyên các bạn nên dùng bản mới nhất. Để làm điều đó, chúng ta cần thay đổi các trường trong EC thành 8 bit để có thể truy cập cùng 1 lúc.
Tiến hành
Dùng kext ECEnabler
ECEnabler
Khi dùng cách này thì khả năng 90% là nhận pin
B1: Tải kext ECEnabler từ nguồn sau và bỏ vào thư mục EFI ⇒ OC
hoặc EFI ==> CLOVER ==> KEXT ==> OTHER
B2 Snapshot config nếu dùng OpenCore.
B3: Tải SMCBattery.kext bỏ vô mục kext và snapshot lại
nếu dùng OpenCore
tải ở đây nhé Releases · acidanthera/VirtualSMC · GitHub
B4: Reboot và tận hưởng.
Dùng các patch sẵn của RehabMan
B2: Các bạn download patch phù hợp với máy của các bạn tại đây.
Hầu hết các máy ASUS và Lenovo đều có patch.
B3: Xem patch nào hỗ trợ máy của bạn:
Các bạn vào các patch phù hợp với model máy và tìm xuống phần
works for
B4: Tải patch và MaciASL tại đây.
B5: Dump DSDT và compile theo hướng dẫn tại đây.
B6: Áp dụng các patch theo hướng dẫn tại đây.
Lưu ý : Khi làm theo cách này thì lúc các bạn update firmware sẽ phải làm lại, nếu không muốn làm lại thì các bạn có thể trích DSDT theo hướng dẫn tại đây.
Static patch
Xác định phần cần patch:
B1: Các bạn dump DSDT theo hướng dẫn tại đây.
B2: Biên dịch DSDT thành .dsl theo hướng dẫn tại đây.
B3: Mở DSDT lên và search Embedded
để xác định các trường EC.
Ở đây ta có 4 trường EC
ECOR
SMBX
SMB2
NSBS
B4: Ta tiến hành search các trường EC đã xác định ở trên
Ở đây ta có:
Biến
NSBS
xuất hiện ở 1field
Biến
SMB2
xuất hiện ở 2field
Biến
SMBX
xuất hiện ở 3field
Và biến
ECOR
xuất hiện ở 1field
B5: Các bạn tiến hành nhìn vào các biến ở các field đã xác định ở trên.
Biến nào trên 8 bit thì ghi lại.
Lưu ý:
Đối với những trường 16 bit và 32 bit các bạn tiết hành search các trường đó nếu chỉ trả về 1 giá trị có nghĩa là trường đó không được sử dụng và có thể bỏ qua.
Ở đây ta có trường B0TM có 16 bit
Tuy nhiên khi search lại trường này tả chỉ thấy có 1 kết quả trả về. Tức trường này không được sử dụng và có thể bỏ qua.
Làm tương tự như vậy ta có:
Patch các trường 16 bit và 32 bit
Trường 16 bit:
Để fix các trường 16 bit bạn sẽ tiến hành chia nhỏ các trường 16 bit thành 2 trường 8 bit
B1: Đặt tên cho 2 trường vừa tách. Tên mới không được trùng với các tên đã có trong DSDT
mẹo ở đây là bạn sẽ lấy tên của trường chính bỏ đi ký tự đầu tiên và thêm sau là các sô thứ tự. Cần tránh các tên bắt đầu bằn chữ số
B2: Tiến hành viết patch để tách các trường thành các trường nhỏ 8 bit.
B3: Tiến hành apply patch vừa viết theo hướng dẫn tại đây. Sau khi apply sẽ được như hình:
hình ảnh chỉ mang tính chất minh họa
B4: Ta sẽ tiến hành fix các lỗi. Do ở bước trên bạn đã tiên hành tách các trường 16 bit nên những method call qua trường này sẽ bị lỗi. Để fix lỗi đó các bạn sẽ tiến hành add method b1b2 vào:
B5: Nhấn compiler
để tiến hành check lỗi.
B6: Các bạn sẽ ân vào vùng lỗi và tìm xem nó ở method nào.
B7: Ta sẽ tiến hành phân tích lỗi và viết patch.
Ở đây ta thấy nó báo lỗi trường B1SN
khi nhấn vào thì sẽ hiện dòng code bị lỗi là Store (B1SN, Local0)
ở method BIFA
thì ta sẽ có cách dạng lỗi thường gặp:
Store (variableOrig, )
Đối với dạng này ta sẽ có cấu trúc fix chung là:
into method label <method> code_regex \(<variableOrig>, replaceall_matched begin (B1B2(<variable1>,<variable2>), end;
Ví dụ:
into method label BIFA code_regex \(B1SN, replaceall_matched begin (B1B2(B1SX,B1SK), end;
Store ( ,variableOrig)
Đối với dạn này ta sẽ có câu trúc fix chung là:
into method label <method> code_regex \<variableOrig>) replaceall_matched begin B1B2(<variable1>,<variable2>)) end;
Ví dụ:
into method label SMBW code_regex \DT2B) replaceall_matched begin B1B2(T2B1,T2B2)) end;
Ở trên là 2 dạng khá phổ biến mà bạn có thể gặp phải. Ngoài ra còn 1 dạng lỗi đặc biệt nữa như sau:
Ta có thể thấy biến bị lỗi được gắn với 1 đường dẫn. Vì vậy để fix lỗi này ta sẽ tiến hành thay toàn bộ đường dẫn bằng b1b2. Tuy nhiên bạn phải tiến hành gắn các biến trong b1b2 với đường dẫn đã thay thế
Cấu trúc chung:
into method label<method> code_regex \<path variableOrig>, replaceall_matched begin B1B2(<path variable1>, <path variable2>), end;
Xem các xác định path
variable
ở mục lưu ý
Ví dụ:
into method label _BIX code_regex \^\^LPCB.EC.B0C3, replaceall_matched begin B1B2(^\^LPCB.EC.B0CX, ^\^LPCB.EC.B0CK), end;
Chú ý:
Có nghĩa là method chứa dòng code lỗi như ở trên sẽ là
_BIX
Vậy để xác định được method của dòng code lỗi ta sẽ ấn nút compiler để check lỗi và ấn vào lỗi cần fix nhìn vào gốc dưới bên trái để xác định được method cần dùng.
Cách xác định
path variable1
vàpath variable2
:path variable Orig:_SB.PCI0.LPCB.EC.<variable Orig> ==>
path variable1:_SB.PCI0.LPCB.EC.<variable1>
path variable2:_SB.PCI0.LPCB.EC.<variable2>
Ví dụ:
path variable Orig: _SB.PCI0.LPCB.EC.B0C3 ==>
path variable1:_SB.PCI0.LPCB.EC.B0CX
path variable2:_SB.PCI0.LPCB.EC.B0CK
B8: Sau khi làm như trên ta sẽ được các patch:
Apply các patch theo hướng dẫn tại đây.
Trường 32 bit
Ở đây do DSDT patch ở trên không có trường 32 bit nên ta sẽ dùng tạm DSDT khác để tiến hành patch trường 32 bit. Làm tương tự như P1 ta có các trường 32 bit sau:
B1: Ta sẽ tiến hành tách các trường 32 bit thành 4 trường 8 bit và đặt tên cho 4 trường đó:
B2: Ta tiến hành viết patch trương tự như ở trường 16 bit. Nhưng thay vì thay bằng 2 trường 8 bit ta sẽ tiến hành thay bằng 4 trường 8 bit. Sau khi làm xong ta được:
Tương tự như trường 16 bit ta vẫn sẽ gặp error.
B3: Để khắc phục điều này ta sẽ tiến hành tương tự như trường 16 bit nhưng thay vì add method B1B2 ta sẽ add method B1B4:
B4: Ta sẽ tiến hành add các patch fix lỗi tương tự như trường 16 bit nhưng thay B1B2 thành B1B4. Sau khi làm xong ta sẽ được:
B5: Tiến hành apply các patch.
P3: Patch các trường lớn hơn 32 bit
Như đã xác định ở P1 ta có các trường lớn hơn 32 bit là:
B1: Ta sẽ tiến hành đổi tên các trường này:
B2: Tiến hành viết patch
Cấu trúc chung:
into device label EC code_regex (<variableOrig>,)\s+(56) replace_matched begin <variablerenamed>,%2,//%1%2 end;
Giải thích cú pháp:
into device label EC code_regex (<variableOrig>,)\s+(56)
: tìm trong device EC đoạn code làBDAT, 256
replace_matched begin <variablerenamed>,%2,//%1%2 end;
: là thay đoạn tìm thấy bằngDATX,256,//BDAT,256,
Ví dụ:
into device label EC code_regex (BDAT,)\s+(256) replace_matched begin DATX,%2,//%1%2 end;
into device label EC code_regex (BDA2,)\s+(256) replace_matched begin DA2X,%2,//%1%2 end;
B3: Apply patch vào DSDT.
B4: Ta tiến hành xác định offset ở các trường này. Có 2 trường hợp có thể xảy ra:
Thông thường thì ở các field sẽ có ít nhất 1 offset được cho trước
Như vậy ta có các offset sau:
B1TM: 0xDE
B1C1: 0xE0
B1C2: 0xE2
B1C3: 0xE4
Ta sẽ nhìn vào
OperationRegion (SMB2, EmbeddedControl, 0x40, 0x28)
vàOperationRegion (SMBX, EmbeddedControl, 0x18, 0x28)
ta có như sau:0x28
thì đang chỉ vị trị của Region này0x40
và0x18
chính là offset lần củaSMB2
vàSMBX
Vậy ta sẽ có các offset sau:
BDAT: 0x1C
BDA2: 0x44
B5: Vì ta đã rename ở bước 2 nên khi compiler
sẽ có error. Để khắc phục ta sẽ tiến hành add method RECB
(Read EC Buffer
) và WECB
(Write EC Buffer
)
Khi bạn check lỗi mà nhận được lỗi có dạng
Store(<variableOrig>, )
thì nó sẽ thuộc
method RECB
Ví dụ:
Store (BDAT, )
Khi check lỗi mà có dạng là
Store( ,<variableOrig>)
thì nó sẽ thuộc
method WECB
Ví dụ:
Store ( ,BDAT)
B6: Ta tiến hành viết patch. Tương tự như trường 16 bit và 32 bit việc đầu tiên ta cần làm là xác định đoạn code lỗi nằm ở method nào.
Như ảnh thì ta có thể thấy đoạn code lỗi nằm ở method
SMBR
. Tiến hành viết patch:
WECB
Cú pháp chung:
into method label <method> code_regex Store\s+((.*),\s+<variableOrig>) replaceall_matched begin WECB(<offset>,<size>,%1) end;
Ví dụ:
into method label SMBR code_regex Store\s+((.*),\s+BDAT) replaceall_matched begin WECB(0x1c,256,%1) end;
Giải thích cú pháp:
into method label SMBR code_regex Store\s+((.*),\s+BDAT)
: tức là sẽ tìm trong methodSMBR
đoạn codeStore (zero, BDAT)
(kí hiệu.*
tức là đoạn code sẽ lấy giá trị ở trước trườngBDAT
trong đoạn code ở DSDT)replaceall_matched begin WECB(0x1c,256,%1) end;
: tức là tất cả đoạn code được tìm thấy ở trên sẽ được thay thế bằng(0x1c,256,zero)
(kí hiệu%1
có nghĩa là lấy phần tử T1 trong đoạn code được tìm thấy)
RECB
Cú pháp chung:
into method label <method> code_regex (variableOrig, replaceall_matched begin (RECB(<offset>,<size>), end;
Ví dụ:
into method label SMBR code_regex (BDAT, replaceall_matched begin (RECB(0x1c,256), end;
Giải thích cú pháp:
into method label SMBR code_regex (BDAT,
: tức là sẽ tìm trong method SMBR đoạn code(BDAT,
replaceall_matched begin (RECB(0x1c,256), end;
: tức là sẽ thay thế tất cả các đoạn code được tìm thấy trong method SMBR bằng(RECB(0x1c,256),
Chú ý:
<offset>
là offset mà bạn đã xác định ở B4<method>
là method mà bạn đã xác định ở B6
Sau khi làm xong ta sẽ có:
B7: Apply patch vào DSDT.
B8: Đối với 1 số dòng Asus thì bạn cần thêm patch Logic bug with charging/discharging status
Vì 1 số laptop ASUS có thể gặp tình trạng khi sạc đầy nhưng hệ thống vẫn báo chưa đầy hoặc khi hết pin nhưng hệ thống vẫn báo chưa hết pin dẫn đến các lỗi như sập nguồn bất chợt ( lỗi nãy vẫn có thể xảy ra ở 1 só máy model khác ) cách fix là các bạn add đoạn sau vào
Sau khi làm xong tất cả các phần trên ta sẽ có đoạn patch sau:
File cho các bạn tham khảo: DSDT-Orig, DSDT-patched
Lưu ý: Bạn nên trích DSDT ra SSDT theo hướng dẫn tại đây. Vì nếu dùng DSDT thì khi update bios các patch sẽ bị mất tác dụng. Hoặc bạn có thể save file patched.txt lại để apply lại vào DSDT khi update BIOS.
Lưu ý 2: Khi các bạn không thể nào tìm thấy
EmbeddedControl
trong DSDT tức là pin của bạn không thuộc sự quản lý của EC Controler. Để khắc phục tình trạng này các bạn sẽ tiến hành update bios để cập nhật lại DSDT
Source tham khảo: [Guide] How to patch DSDT for working battery status | tonymacx86.com | [Guide] Laptop Battery Indicator – The DSDT Patching Horror – Page 14 – Guides and Tutorials – Olarila ( thank you )
Last updated