시스템 사양 선택 | 3번 |
---|
안녕하세요.
노트북의 안정화 작업 중에서 ACPI 에 직접 배터리 패치를 진행하려는 경우
배터리 관련 변수가 호출되어 어떻게 사용되는지에 따라 달라지는
구문 별 패치 방법에 대해서 설명드리고자 글을 작성하게 되었습니다.
ACPI 에 직접 배터리 패치를 진행하려는 경우 배터리 세분화 관련 Method 를 추가하고
세분화한 배터리 관련 변수를 인수로 하여 Call(호출)하는데 구문을 잘 확인하고 패치해야 합니다.
배터리 관련 변수가 호출되어 어떻게 사용되는지에 따라서 패치를 다르게 해줘야 하는 부분이 있기 때문입니다.
⬛️ 배터리 세분화 관련 Method 의 원리
OEM ACPI 에서 EmbeddedControl Region 에 정의된 배터리 관련 FieldUnitObject 중에서
배터리와 EC 관련된 부분에서 사용되는 16 Bit 이상의 변수들을 8 Bit 로 세분화합니다.
예를 들어, 16 Bit 변수는 2개로, 32 Bit 변수는 4개로, 48 Bit 변수는 6개로 분할하여 세분화합니다.
EmbeddedControl Region 에 정의된 배터리 관련 FieldUnitObject 를 세분화하면서
단순히 각 레지스터가 액세스하는 데이터의 크기가 달라질 뿐입니다.
예전에 원도리님께서 작성하신 배터리 패치 강좌는 32 Bit 를 초과하는 배터리 관련 변수를 직접 세분화하고
이를 Method 에 담아서 Call(호출)하는 방법으로 패치하셨지만,
이 방법은 배터리 관련 변수의 Bit 크기가 클 수록 노가다 작업이기도 하고 번거롭습니다.
256 Bit 변수를 위의 방법으로 패치하려면 256 / 8 = 32 이므로 8 Bit 변수 32개로 분할해야 하므로 번거롭고 힘듭니다.
그 대신에, 특정 Offset 값으로 직접 레지스터에 접근하여 읽고 쓰도록 하는
RECB / WECB Method 를 사용하면 훨씬 더 편리합니다.
예전에 뽀로로님께서 RECB / WECB Method 를 사용하여
Hot Patch & Override 방식의 배터리 패치 SSDT 를 만드는 과정에 대해 설명한 글이 있습니다.
또한, 주로 16, 32, 64, 128, 256 Bit 처럼 x2 씩 곱해지는 크기의 변수가 대부분이지만,
일부 노트북은 24 Bit, 48 Bit, 72 Bit 크기의 변수가 존재하는 경우도 있습니다.
24 Bit 변수는 B1B3 Method 를 사용하면 되지만
48 Bit, 72 Bit 크기의 변수는 RECB / WECB Method 를 사용하는 것이 편리합니다.
자세한 내용은 아래에서 설명하겠습니다.
추가로, 배터리 관련 FieldUnitObject 가 EmbeddedControl Region 이 아닌
SystemMemory Region 에 정의된 경우에는 8 Bit 로 세분화하지 않아도 됩니다.
OEM ACPI 상에서 EmbeddedControl Region 이 존재하지 않고 모든 배터리 관련 변수가 SystemMemory Region 에 정의되어 있다면
ECEnabler.kext 와 배터리 패치는 필요하지 않으며 바로 SMCBatteryManager.kext 를 활성화하면 됩니다.
⬛️ 배터리 세분화 관련 Method 의 종류
아래에 제시된 배터리 세분화 관련 Method 중에서
자신의 노트북에 배터리 패치를 진행하는데 필요한 Method 를 복사하고
DSDT 또는 SSDT 에 붙여 넣어서 Static 또는 Hot Patch & Override 방식으로 패치를 진행하면 됩니다.
⚫️ 16 Bit 분할 레지스터 읽기 : B1B2 Method (R16B Method)
Method (B1B2, 2, NotSerialized)
{
Return ((Arg0 | (Arg1 << 0x08)))
}
⚫️ 24 Bit 분할 레지스터 읽기 : B1B3 Method (R24B Method)
Method (B1B3, 3, NotSerialized)
{
Local0 = Arg2
Local0 = (Arg1 | (Local0 << 0x08))
Local0 = (Arg0 | (Local0 << 0x08))
Return (Local0)
}
⚫️ 32 Bit 분할 레지스터 읽기 : B1B4 Method (R32B Method)
Method (B1B4, 4, NotSerialized)
{
Local0 = Arg3
Local0 = (Arg2 | (Local0 << 0x08))
Local0 = (Arg1 | (Local0 << 0x08))
Local0 = (Arg0 | (Local0 << 0x08))
Return (Local0)
}
⚫️ 32 Bit 를 초과하는 분할 레지스터 읽기 : RE1B & RECB Method
Method (RE1B, 1, NotSerialized)
{
OperationRegion (ERAM, EmbeddedControl, Arg0, One)
Field (ERAM, ByteAcc, NoLock, Preserve)
{
BYTE, 8
}
Return (BYTE) /* \_SB_.PCI0.LPCB.EC0_.RE1B.BYTE */
}
Method (RECB, 2, Serialized)
{
Arg1 = ((Arg1 + 0x07) >> 0x03)
Name (TEMP, Buffer (Arg1){})
Arg1 += Arg0
Local0 = Zero
While ((Arg0 < Arg1))
{
TEMP [Local0] = RE1B (Arg0)
Arg0++
Local0++
}
Return (TEMP) /* \_SB_.PCI0.LPCB.EC0_.RECB.TEMP */
}
⚫️ 16 Bit 분할 레지스터에 쓰기 : W16B Method
Method (W16B, 3, NotSerialized)
{
Arg0 = Arg2
Arg1 = (Arg2 >> 0x08)
}
⚫️ 32 Bit 이상의 분할 레지스터에 쓰기 : WE1B & WECB Method
Method (WE1B, 2, NotSerialized)
{
OperationRegion (ERAM, EmbeddedControl, Arg0, One)
Field (ERAM, ByteAcc, NoLock, Preserve)
{
BYTE, 8
}
BYTE = Arg1
}
Method (WECB, 3, Serialized)
{
Arg1 = ((Arg1 + 0x07) >> 0x03)
Name (TEMP, Buffer (Arg1){})
TEMP = Arg2
Arg1 += Arg0
Local0 = Zero
While ((Arg0 < Arg1))
{
WE1B (Arg0, DerefOf (TEMP [Local0]))
Arg0++
Local0++
}
}
⬛️ 호출된 배터리 관련 변수를 배터리 세분화 관련 Method 로 치환하여 패치하기
⚫️ 1. 16 Bit 분할 레지스터 읽기 : B1B2 Method (R16B Method)
☑️ 문법
B1B2 (Arg0, Arg1)
- Arg0 : 세분화한 첫 번째의 배터리 변수
- Arg1 : 세분화한 두 번재의 배터리 변수
▪️ 1-가. 대입 연산자 구문
🟠 수정 전 구문
Local0 = B1DV
PBIF [One] = ^^PCI0.LPCB.EC0.DSCP
🟢 수정 후 구문
Local0 = B1B2 (BDV0, BDV1)
PBIF [One] = B1B2 (^^PCI0.LPCB.EC0.SCP0, ^^PCI0.LPCB.EC0.SCP1)
💬 설명 : 대입 연산자 "=" 우측(배터리 관련 변수)의 값을 읽어서 좌측에 쓰는(저장/할당)하는 구문입니다.
배터리 관련 변수에 저장되어 있는 값을 읽어서 Local0 에 저장/할당하는 구문이므로 B1B2(R16B) Method 를 사용합니다.
▪️ 1-나. 비교 연산자 구문
🟠 수정 전 구문
If ((^^PCI0.LPCB.EC0.BADC < 0x0C80))
🟢 수정 후 구문
If ((B1B2 (^^PCI0.LPCB.EC0.BDC0, ^^PCI0.LPCB.EC0.BDC1) < 0x0C80))
💬 설명 : 비교 연산자를 사용하여 비교 판단하는 구문은 읽기 조작에 속하므로 B1B2(R16B) Method 를 사용합니다.
⚫️ 2. 16 Bit 분할 레지스터에 쓰기 : W16B Method
☑️ 문법
W16B (Arg0, Arg1, Arg2)
- Arg0 : 세분화한 첫 번째의 배터리 변수
- Arg1 : 세분화한 두 번재의 배터리 변수
- Arg2 : 배터리 관련 변수에 쓰여지는(저장/할당되는) 값
🟠 수정 전 구문
BTPC = Local0
SMW0 = Arg3
🟢 수정 후 구문
W16B (BPC0, BPC1, Local0)
W16B (MW00, MW01, Arg3)
💬 설명 : 어떤 특정 값을 배터리 관련 변수에 쓰는(저장/할당)하는 구문이므로 W16B Method 를 사용합니다.
16 Bit 변수이지만 B1B2(R16B) Method 와 달리 W16B Method 는 Call(호출)할 때 인수가 하나 더 많습니다.
세 번째 자리의 인수인 Arg2 에는 배터리 관련 변수에 쓰여지는(저장/할당되는) 값을 입력하면 됩니다.
⚫️ 3. 32 Bit 분할 레지스터 읽기 : B1B4 Method (R32B Method)
☑️ 문법
B1B4 (Arg0, Arg1, Arg2, Arg3)
- Arg0 : 세분화한 첫 번째의 배터리 변수
- Arg1 : 세분화한 두 번재의 배터리 변수
- Arg2 : 세분화한 세 번째의 배터리 변수
- Arg3 : 세분화한 네 번재의 배터리 변수
🟠 수정 전 구문
Local4 = B1PV
If ((B1CH == 0x0050694C))
🟢 수정 후 구문
Local4 = B1B4 (BPV0,BPV1, BPV2, BPV3)
If ((B1B4 (BC0H, BC1H, BC2H, BC3H) == 0x0050694C))
💬 설명 : B1B2(R16B) Method 와 원리는 동일하며 32 Bit 이므로 인수가 4개로 조금 더 많습니다.
대입 연산자와 비교 연산자 모두 읽기 조작에 해당되므로 B1B4(R32B) Method 를 사용합니다.
⚫️ 4. 32 Bit 를 초과하는 분할 레지스터 읽기 : RE1B & RECB Method
☑️ 문법
RECB (Offset, Length)
- Offset : 배터리 관련 변수를 세분화하기 전의 원래 레지스터의 Offset 주소 (16진수)
- Length : 배터리 관련 변수를 세분화하기 전의 원래 레지스터의 Bit 크기 (16진수)
▪️ 4-가. Offset 구문 바로 아래에 세분화하려는 배터리 관련 변수가 정의된 경우
🟡 원본 정의 구문
Offset (0x8F),
B1MA, 64,
🟠 수정 전 구문
IFMN = B1MA
🟢 수정 후 구문
IFMN = RECB (0x8F, 0x40)
💬 설명 : 배터리 관련 변수를 세분화하기 전에 B1MA 레지스터의 원래 주소는 0x8F 이며, 64 Bit 입니다.
64 를 16진수로 변환하면 0x40 이므로 RECB (0x8F, 0x40) 으로 수정합니다.
▪️ 4-나. Offset 구문과 조금 떨어진 위치에서 배터리 관련 변수가 정의된 경우
🟡 원본 정의 구문
Offset (0xA0),
SBBM, 8,
SBDC, 8,
SBDV, 8,
SBMN, 128,
🟠 수정 전 구문
Local0 = SBMN
🟢 수정 후 구문
Local0 = RECB (0xA3, 0x80)
💬 설명 : 배터리 관련 변수를 세분화하기 전에 SBMN 레지스터의 원래 주소는 0xA3 이며, 128 Bit 입니다.
128 을 16진수로 변환하면 0x80 이므로 RECB (0xA3, 0x80) 으로 수정합니다.
⚫️ 5. 32 Bit 이상의 분할 레지스터에 쓰기 : WE1B & WECB Method
☑️ 문법
WECB (Offset, Length, Obj)
- Offset : 배터리 관련 변수를 세분화하기 전의 원래 레지스터의 Offset 주소 (16진수)
- Length : 배터리 관련 변수를 세분화하기 전의 원래 레지스터의 Bit 크기 (16진수)
- Obj : 배터리 관련 변수에 쓰여지는(저장/할당되는) 값
🟡 원본 정의 구문
Offset (0x77),
BANA, 64,
...
Offset (0x88),
SMPR, 8,
SMST, 8,
SMAD, 8,
SMCM, 8,
SMD0, 256,
🟠 수정 전 구문
^^PCI0.LPCB.EC0.BANA = Zero
SMD0 = FB4
🟢 수정 후 구문
WECB (0x77, 0x40, Zero)
WECB (0x8C, 0x0100, FB4)
💬 설명 : 배터리 관련 변수를 세분화하기 전에 BANA 레지스터의 원래 주소는 0x77 이며, 64 Bit 입니다.
64 를 16진수로 변환하면 0x40 이며 쓰여지는 값은 Zero 이므로 WECB (0x77, 0x40, Zero) 으로 수정합니다.
마찬가지로, SMD0 레지스터의 원래 주소는 0x8C 이며, 256 Bit 입니다.
256 을 16진수로 변환하면 0x100 이며 쓰여지는 값은 FB4 라는 변수에 저장된 값이므로 WECB (0x8C, 0x0100, FB4) 으로 수정합니다.
⬛️ 마무리
위의 내용을 모두 이해하고 마스터하였다면, 거의 모든 노트북의 배터리 패치는 완벽하게 진행할 수 있을 것입니다. 🙂
ACPI 에 배터리 패치를 진행하지 않는 대신에 ECEnabler.kext 를 사용하는 방법이 있지만,
ECEnabler.kext 를 사용하여도 배터리 잔량 표시가 잘 작동하지 않는 노트북도 일부 있습니다.
ACPI 에 직접 배터리 패치를 진행하는 데에 많은 도움이 되었으면 좋겠습니다. 🍀
🌿 배터리 패치 관련 강좌 글
❄️ 참고한 사이트
shl628님의 새글 알림을 받으실려면 구독
*적용중인 도장
제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|
macOS Ventura 13.7 22H123 정식버젼 고스트 이미지 OC 1.0.1 ft: 전체 공개 +2 | 좌절금지 | 24.09.1917:09 | 67 |
macOS Sonoma 14.7 23H124 정식버젼 고스트 이미지 OC 1.0.1 ft: 전체공개 +14 | 좌절금지 | 24.09.1723:58 | 172 |
[중급편] 노트북 해킨 +8 | Stultus | 24.07.1219:19 | 749 |
[초급편] 문제 스스로 해결하기 +17 | Stultus | 24.03.2920:07 | 3530 |
[입문편] 첫 해킨 길라잡이 +32 | Stultus | 24.01.1218:54 | 4295 |
[필독 - 안정화] macOS 해킨토시 설치 후 안정화 작업 목록 및 글타래 모음 총정리 📋 +63 | shl628 | 23.01.0913:39 | 5만 |
Sonoma 14.7(23H124) i9-12900, GA-Z690 Proart Creator + BCM WiFi Support +2 | 좌절금지 | 24.09.1722:40 | 194 |
2020 그램 sonoma efi 15Z90N +1 | 맥가즈아 | 24.09.1717:13 | 88 |
macOS Sequoia 15 설치 후기 + Bcm94360NG WiFi 작동함 | 좌절금지 | 24.09.1919:17 | 160 |
좌절금지 | 24.09.1919:17 | 160 | |
좌절금지 | 24.09.1917:09 | 67 | |
Stultus | 24.09.1813:37 | 146 | |
좌절금지 | 24.09.1723:58 | 172 | |
좌절금지 | 24.09.1722:40 | 194 | |
맥가즈아 | 24.09.1717:13 | 88 | |
김경석 | 24.09.1708:13 | 216 | |
Panictosh | 24.09.1617:47 | 95 | |
Tamy | 24.09.1504:35 | 465 | |
Stultus | 24.09.1319:18 | 434 | |
치토 | 24.09.1019:44 | 468 | |
머핀X | 24.09.0118:13 | 393 | |
해킨도전자 | 24.09.0112:54 | 294 | |
머핀X | 24.08.3115:34 | 371 | |
화정큐삼 | 24.08.2601:42 | 239 | |
하나브 | 24.08.2422:59 | 206 | |
화정큐삼 | 24.08.2316:25 | 247 | |
CanBe | 24.08.1810:56 | 328 | |
화정큐삼 | 24.08.1800:04 | 205 | |
화정큐삼 | 24.08.1722:03 | 189 | |
jbhlyk | 24.08.1710:14 | 166 | |
Stultus | 24.08.1622:06 | 251 | |
hackillious | 24.08.1511:16 | 159 | |
세유니 | 24.08.1421:30 | 124 | |
Stultus | 24.08.1419:58 | 345 | |
오디세이 | 24.08.1311:26 | 271 | |
좌절금지 | 24.08.1115:46 | 194 | |
티타보르 | 24.08.1111:21 | 141 | |
Stultus | 24.08.1022:46 | 183 | |
오디세이 | 24.08.1022:10 | 390 | |
jbhlyk | 24.08.1019:05 | 126 | |
RogerT | 24.08.0923:20 | 144 | |
좌절금지 | 24.08.0717:18 | 286 | |
RogerT | 24.08.0609:17 | 115 | |
줌바이퍼 | 24.08.0606:14 | 457 | |
jbhlyk | 24.08.0523:34 | 81 | |
수인과윤슈 | 24.08.0521:10 | 185 | |
좌절금지 | 24.08.0521:08 | 836 | |
Stultus | 24.08.0221:07 | 425 | |
Tamy | 24.07.3019:12 | 328 | |
해킨도전자 | 24.07.2915:37 | 260 | |
june119 | 24.07.2813:52 | 206 | |
Stultus | 24.07.2112:43 | 245 | |
BlueGuerrilla | 23.05.0502:19 | 3993 | |
Stultus | 24.07.1219:19 | 749 | |
김태국 | 21.08.0213:10 | 3679 | |
Stultus | 24.07.1122:47 | 215 | |
Stultus | 24.07.1020:44 | 137 | |
Stultus | 24.07.0921:44 | 137 | |
Stultus | 24.07.0820:57 | 223 | |
의정이 | 24.07.0811:28 | 171 | |
Stultus | 24.07.0721:25 | 264 | |
bsiugr | 24.07.0604:41 | 287 | |
애플브리크 | 24.07.0509:56 | 492 | |
광호 | 24.02.1715:21 | 2182 | |
치토 | 24.06.2723:24 | 397 | |
talas | 24.06.2617:24 | 193 | |
블루사탕 | 24.06.2120:58 | 116 | |
gtrfxdsp | 24.06.1609:01 | 511 | |
Mactopia | 24.06.1401:04 | 345 | |
Stultus | 24.06.1120:40 | 725 | |
새콤칠리 | 24.06.1115:07 | 671 | |
좌절금지 | 23.02.2118:35 | 118만 | |
Steer | 24.06.1001:11 | 275 | |
Door | 24.06.0810:09 | 155 | |
Tamy | 24.06.0107:41 | 415 | |
ssdwe346 | 24.05.2923:53 | 299 | |
joy | 24.05.2809:58 | 264 | |
거니 | 24.05.2601:07 | 243 | |
RogerT | 24.05.2520:14 | 247 | |
좌절금지 | 24.05.1812:40 | 909 | |
wjdgkdus | 24.05.1615:02 | 211 | |
Tamy | 24.05.1417:36 | 797 | |
줌바이퍼 | 24.05.1002:04 | 1007 | |
의정이 | 24.05.0821:05 | 144 | |
ryzen | 23.10.0921:28 | 2403 | |
챠니앤차니 | 24.05.0319:15 | 146 | |
챠니앤차니 | 24.05.0220:17 | 173 | |
고맹이 | 24.05.0210:00 | 633 | |
shl628 | 24.04.3013:54 | 1067 |
예전에 shl628님 도움으로 제 x1 yoga의 배터리 배치 도움받은 기억이 나네요.
여전히 도움을 많이 주시고 계셔서 든든합니다.
감사합니다.