小白都能看懂的DSDT电量显示补丁教程
简介知识储备
[*]DSDT
[*]正则匹配(不懂就依葫芦画瓢)
背景
由于普通PC的电池设备并不兼容与苹果的SMbus设备,所以,对于黑苹果,只能够通过ACPI来获取电池状态。为了解决电量显示我可是爬了不少帖子、花了不少时间呢。但是从我参考的中外教程来看,我觉得都不太理想,作为一个程序员的我都要看好几遍,普通用户怕是望而却步。再说作为小白用户其实没必要搞清楚里面的弯弯道道,能正常显示电量就是目标,所以萌生了写这篇文章的念头。
参考资料
[*]修改DSDT实现电量显示方法【转载】
[*] How to patch DSDT for working battery status
[*]Laptop-DSDT-Patch)下载了battery_HP-Envy-14(我的是HP Envy 13,当时认为应该是最接近的)参考对照,补丁和源文件都有的留下,补丁有源文件没有的删了,再依葫芦画瓢把源文件有补丁没有的补上,最后编译,除了16位、32位拆字节补丁无效(也就是类似下面的代码),其它的都正常,然后就傻不拉几的手工拆
into device label H_EC code_regex BDC0,\s+16 replace_matched begin DC00,8,DC01,8 end;//我确定自己的设备标识也是H_EC
……
特别注意类型如下代码
# 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|replace_content|store_%8|store_%9这些
[*]begin end里面的就是主体
拆字节补丁例子# 在范围为^LPCB中查找(即)BDC0, 16的内容(s+就是有至少一个空格),替换成DC00,8,DC01,8
# 也就是将BDC0, 16拆成两个字节DC00,8,DC01,8
# 注意这里16后面没有逗号(,),替换第二个8后面也没有,所以即使是}前一个也是通用的
# 这个是GitHub下载补丁里的,我的设备标识是H_EC,但我发现无效,原因未知,于是我改了
into device label H_EC code_regex BDC0,\s+16 replace_matched begin DC00,8,DC01,8 end;
into scope label ^^LPCB code_regex BDC0,\s+16 replace_matched begin DC00,8,DC01,8 end;
# 拆分32位属性
into scope code_regex BTY0,\s+32 replace_matched begin TY00,8,TY01,8,TY02,8,TY03,8 end;
# 所有大于32位的都不用拆http://wailian.work/images/2018/05/06/DSDT-Patch-1.png
从上面的图片可以看到补丁完美实现拆字节,下面再看看调用例子
访问属性补丁例子
# 16位属性访问替换补丁
# 注意BFC0在两个方法中有调用,都要写补丁替换
into method label BTIF code_regex \(BFC0, replaceall_matched begin (B1B2(FC00,FC01), end;
into method label _Q09 code_regex \^\^BFC0\) replaceall_matched begin ^^B1B2(FC00,FC01)) end;
# 32位属性访问替换补丁
into method label GBTI code_regex \(BTY0, replaceall_matched begin (B1B4(TY00,TY01,TY02,TY03), end;
# 56位属性替换补丁
into method label GBTI code_regex \(BDN0, replaceall_matched begin (RECB(0x10,56), end;
# 128位属性替换补丁
into method label GBTI code_regex \(BMN0, replaceall_matched begin (RECB(0x20,128), end;
# 从56位和128位属性访问补丁可以看到是通过RECB(偏移量, 位数)这个方法实现的,理论上16位、32位的也可以不拆,访问的时候用这个方法,但是回到准备阶段第4部我们发现算每个属性的偏移量这工作比拆字节还头大
http://wailian.work/images/2018/05/06/DSDT-Patch-2.png
其它举例
# 在做Thinakpad E430电量补丁的时候发现有类型\_SB.PCI0.LPCB.EC.HWAK这样的调用,我用下面的补丁修正
into method label _L43 code_regex \(\\\_SB.PCI0.LPCB.EC.HWAK replaceall_matched begin \(\\_SB.B1B2(\\_SB.PCI0.LPCB.EC.AK00, \\_SB.PCI0.LPCB.EC.AK01) end;
# 理论上不需要上面那个补丁应该都能替换掉所有的,但发现不彻底,原因未知
into ALL code_regex \(\\\_SB.PCI0.LPCB.EC.HWAK replaceall_matched begin \(\\_SB.B1B2(\\_SB.PCI0.LPCB.EC.AK00, \\_SB.PCI0.LPCB.EC.AK01) end;
ehabMan大神提供通用代码
## RehabMan大神提供通用代码
# 这部分之间拷贝到你的补丁文件前面
# 特别注意部分行后面的\n,因为补丁里你即使输入了换行也是当一行出来的,所以加入了硬换行代码
# 删除原有B1B2方法(一般都没)
into method label B1B2 remove_entry;
# 新插入B1B2方法
# 这里需要注意一下,一般情况下默认的都没问题
# 有些型号可能会导致打完补丁的少量代码访问不了B1B2方法
# 这时候要么调整补丁绝对路径访问,要么插入的时候改个位置
into definitionblock code_regex . insert
# into Scope label \_SB code_regex . insert // 这是我改的位置
begin
Method (B1B2, 2, NotSerialized) { Return(Or(Arg0, ShiftLeft(Arg1, 8))) }
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 method label RE1B parent_label EC0 remove_entry;
into method label RECB parent_label EC0 remove_entry;
into device label EC0 insert
begin\n
Method (RE1B, 1, NotSerialized)\n
// Arg0 - offset in bytes from zero-based EC\n
{\n
OperationRegion(ECOR, EmbeddedControl, Arg0, 1)\n
Field(ECOR, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
Return(BYTE)\n
}\n
Method (RECB, 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))
Increment(Arg0)
Increment(Local0)
}
Return(TEMP)\n
}\n
end;
into method label RE1B parent_label EC remove_entry;
into method label RECB 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(ECOR, EmbeddedControl, Arg0, 1)\n
Field(ECOR, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
Return(BYTE)\n
}\n
Method (RECB, 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;补丁例子
提供我做的两个型号(HP-ENVY-13及ThinkaPad E430)的补丁及原始DSL文件参考
链接: https://pan.baidu.com/s/1Y8Vcnzn-SFTEZ_itMcRvKw 密码: gryy 谢谢分享 占楼备用 谢谢分享。。 因为发这贴的时候一直被拦截,删掉了一下内容才发成功,然后又进入审核,审核过了又没法再次编辑,
嗯,远景发帖很蛋疼
完整阅读请移步blog
http://xiegengcai.github.io/2018/05/05/how-to-create-battery-dsdt-fix/ 我是小白,小白是我,嘻嘻。
谢谢 分享{:5_264:} 非常感谢,爬楼好久才找到这教程,谢谢 非常感谢,爬楼好久才找到这教程,谢谢 这种普及型的帖子多点最好 。感谢分享。 感谢分享。 谢谢分享~ 希望提供word教程下载。 感谢对小白的支持,很有用处
收藏了,感谢楼主 看不懂xili
厉害楼主 应回复提供附件文档 liugj47 发表于 2018-6-9 20:36 https://www.pcbeta.com/static/image/common/back.gif
希望提供word教程下载。
远景动不动要审核,很麻烦,4楼有我博客的地址 技术贴吧支持 感谢分享,DSDT太复杂了 写的好详细,可以好好的研究一下,不在做伸手党
页:
[1]
2