leo168 发表于 2020-1-7 11:00

适合初学者学习的电量补丁教程(转载,附件附工具)

   
简介知识储备
[*]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位拆字节补丁无效(也就是类似下面的代码),其它的都正常,然后就傻不拉几的手工拆复制
1
2
3
# 我确定自己的设备标识也是H_EC,所以我改成into scope label ^^LPCB
into device label H_EC code_regex BDC0,\s+16 replace_matched begin DC00,8,DC01,8 end;
……


特别注意类型如下代码
复制
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
2
3
4
5
6
7
8
9
10
# 在范围为^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从上面的图片可以看到补丁完美实现拆字节,下面再看看调用例子访问属性补丁例子复制
1
2
3
4
5
6
7
8
9
10
11
12
# 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其它举例复制
1
2
3
4
# 在做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;


RehabMan大神提供通用代码复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# 这部分之间拷贝到你的补丁文件前面
# 特别注意部分行后面的\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;



loveqp 发表于 2020-1-7 20:13

学习一些

ysx25261465 发表于 2020-1-7 20:15

插眼看好帖

爱游泳的山鸡 发表于 2020-1-8 22:03

正好需要的行动

40190246 发表于 2020-1-8 23:17

密密麻麻,有点费眼,空了慢慢学习!!

心不止境 发表于 2020-1-9 00:00

谢谢分享。。

AKillWum 发表于 2020-1-9 17:57

看的我一脸懵逼……但还是支持下

scvkyl 发表于 2020-1-10 00:44

大神 所有操作都在device (bat)里面吗

ZOUYONQUN 发表于 2020-1-10 02:12

学习了大神

maojinbing 发表于 2020-1-13 05:29

支持发表

003128 发表于 2024-4-26 00:25

无限烧脑啊
页: [1]
查看完整版本: 适合初学者学习的电量补丁教程(转载,附件附工具)