[TOC]
简介
知识储备
- DSDT
- 正则匹配(不懂就依葫芦画瓢)
背景
由于普通PC的电池设备并不兼容与苹果的SMbus设备,所以,对于黑苹果,只能够通过ACPI来获取电池状态。为了解决电量显示我可是爬了不少帖子、花了不少时间呢。但是从我参考的中外教程来看,我觉得都不太理想,作为一个程序员的我都要看好几遍,普通用户怕是望而却步。再说作为小白用户其实没必要搞清楚里面的弯弯道道,能正常显示电量就是目标,所以萌生了写这篇文章的念头。
参考资料
准备阶段
汇集中外教程资料,准备步骤如下
在DSDT文件中搜索关键词“EmbeddedControl” ,有些机型可能会有多个
1
2# 定义一个0xFF(255)字节的EC域ECF2
OperationRegion (ECF2, EmbeddedControl, Zero, 0xFF)接着搜关键词“ECF2”(上面EmbeddedControl搜索到多个EC域的都要找),有些机型即使只有一个EC域也在多个块有声明(如例子附件中E430)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19Field (ECF2, ByteAcc, Lock, Preserve)
{
MBVR, 8,
Offset (0x10),
BDN0, 56,
Offset (0x18),
BME0, 8,
Offset (0x1C),
DAY0, 8,
HUR0, 8,
MIN0, 8,
SEC0, 8,
BMN0, 128,
BCT0, 128,
Offset (0x59),
EC59, 1,
DPDS, 1,
……
}将第二步中所有Field里大于8位的属性定义且在别的地方有访问的都找出来,把这些变量名及调用的代码都一一用文本文件记录下来,后面高级进阶要用。任何属性在任何位置只是声明没有调用的都不用管
计算大于32位属性的偏移量,如上述代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 16进制记法:0到15(即0 1 2 3 4 5 6 7 8 9 A B C D E F),满16进位(0x10=16)
Field (ECF2, ByteAcc, Lock, Preserve)
{
MBVR, 8,
Offset (0x10), // 空10位
BDN0, 56, // 0x10
Offset (0x18),
BME0, 8, // 0x18
Offset (0x1C), //
DAY0, 8, // 0x1C
HUR0, 8, // 0x1D=0x1C+1 8位是1字节,所以加1)
MIN0, 8, // 0x1E
SEC0, 8, // 0x1F
BMN0, 128, // 0x20
BCT0, 128, // 0x31=0x20+0x10(16)+1
Offset (0x59),
EC59, 1,
DPDS, 1,
……
}
修改阶段
暴力修改
从Laptop-DSDT-Patch下载了battery_HP-Envy-14(我的是HP Envy 13,当时认为应该是最接近的)参考对照,补丁和源文件都有的留下,补丁有源文件没有的删了,再依葫芦画瓢把源文件有补丁没有的补上,最后编译,除了16位、32位拆字节补丁无效(也就是类似下面的代码),其它的都正常,然后就傻不拉几的手工拆
1 | # 我确定自己的设备标识也是H_EC,所以我改成into scope label ^^LPCB |
特别注意类型如下代码1
2
3
4
5
6# 0x10即上面找出来的BDN0偏移量
into method label GBTI code_regex \(BDN0, replaceall_matched begin (RECB(0x10,56), end;
# 0x20即上面找出来的BMN0偏移量
into method label GBTI code_regex \(BMN0, replaceall_matched begin (RECB(0x20,128), end;
# 0x31即上面找出来的BCT0偏移量
into method label GBTI code_regex \(BCT0, replaceall_matched begin (RECB(0x31,128), end;
编译成功另存为aml文件替换重启正常显示电量。至此,如果你不想继续看,用我一样的笨方法理论上是能解决问题的。码农天生喜欢折腾,不然也不会玩黑苹果了,于是我把补丁文件研究了一番寻求优雅方式
高级进阶
通过分析补丁文件,我发现了一个特点,就是除了增加方法,其它的都是正则匹配替换(在这里我假设你懂正则),于是我去看了Patching Syntax Grammar,下面我简单说明一下
第一部分into|into_all就是在什么范围(后面跟着的限定),into应该的匹配第一个,into_all有多少匹配多少
第二部分即限定,可以有All|DefinitionBlock|Scope|Method|Device|Processor|ThermalZone这些值
第三部分即名称标识啥的了,支持标签名称、正则匹配、父项名称等
第四部分selector,即选择器(支持正则)
第五部分动作(就是在匹配项里干什么),支持
insert|set_label|replace_matched|replaceall_matched|remove_matched|removeall_matched|remove_entry|replacecontent|store%8|store_%9这些
begin end里面的就是主体
拆字节补丁例子
1 | # 在范围为^LPCB中查找(即)BDC0, 16的内容(s+就是有至少一个空格),替换成DC00,8,DC01,8 |
从上面的图片可以看到补丁完美实现拆字节,下面再看看调用例子
访问属性补丁例子
1 | # 16位属性访问替换补丁 |
其它举例
1 | # 在做Thinakpad E430电量补丁的时候发现有类型\_SB.PCI0.LPCB.EC.HWAK这样的调用,我用下面的补丁修正 |
RehabMan大神提供通用代码
1 | # 这部分之间拷贝到你的补丁文件前面 |
补丁例子
提供我做的两个型号(HP-ENVY-13及ThinkaPad E430)的补丁及原始DSL文件参考
链接: https://pan.baidu.com/s/1Y8Vcnzn-SFTEZ_itMcRvKw 密码: gryy