但是很多笔记本并未出现在这个补丁源里,并且我们要了解补丁的意思才知道它适不适合我们的电脑。
电量补丁制作过程
-
我们需要确定 DSDT 里的哪些部分需要改。
用
MaciASL
软件打开 DSDT,搜索 **EmbeddedControl
。在DSDT
里,可能会有一到多个。同时注意一个计算机名字如下图为EC0
**
1 |
OperationRegion (ECF2, EmbeddedControl, Zero, 0xFF)
|
上面的代码,我们只需要关注 ec
域声明的名字,即 **ECF2
(别的可能是 ECF0
等)。
我们开始搜索Field(ECF2
**。
- 我们需要查看 Field 里所有 大于 8 位 的元素,例如:
12345 |
Field (ECF2, ByteAcc, Lock, Preserve) { Offset (0x10), BDN0, 56,...
|
可以看到 **BDN0
** 是一个大于 8 位的字段。
我们对其进行记录。之后我们要确定除了这里还有没有其他地方调用了这个字段。搜索他的名字:BDN0
。如果 ** 只有这里被用到则不用拆分可以删除记录,** 如果除了这里还有其他地方用到,则进行记录。
整理到如下的结果:
可以看到我有意对 16 位 32 位以及高于 32 位进行了一个空行的区分,大家也可以这样,这对下面的修改操作有着重要意义。
补丁的制作方法
对于 16 位和 32 位字段的处理
对于 16 位的 BDC0
,我么需要把它拆分为两部分(低字节,高字节)。在拆分的时候, 需要注意两点:
1. 拆分后,它的名字应该是 4 个字符。不能多,也不能少。如图
- // 拆分前:BDC0, 16
- DC00, 8,
- DC01, 8,
复制代码
2.拆分后到名字不能已经出现在 dsdt 中(最好也不要与拆分到名字重复,虽然没什么问题,但是如果多次打这个补丁就会发生错误),可以先想好几个名字,然后在 dsdt 中搜索,如果没有就可以。
然后。重点来了,拆分 16 位字段的补丁结构。(这里只会拆分 ec 域内的名称)
- into device label H_EC code_regex BDC0,/s+16, replace_matched begin DC00,8,DC01,8, end;
复制代码
对于各部分的含义以及修改方法:
1.into device label** H_EC**
含义:针对 H_EC 这个设备操作。对于自己电脑的名称请查看 制作过程第一步的截屏处 。
2.code_regex** BDC0,/s+16,**
含义:code_regex 表示寻找后面的匹配项。后面的 BDC0,/s+16, 是寻找的内容,对于小白,只要知道把 BDC0 替换成你所记录的 16 位名称即可。
相关解释:/s+ 表示多个空格。所以这句话的意思是搜索 BDCO,16,
个人建议:这一步中的最后的“,”个人觉得没必要加,因为如果这个数据出现在右括号前贼不会有这个“,”。
3.replace_matched begin** DC00,8,DC01,8,** end;
含义:replace_matched begin…end 表示将前面搜索到的字段替换为省略后里的字段。**DC00,8,DC01,8,** 即替换为的内容。这里 DC00 DC01 即你要改为的名 字。
注意和上文的对应,如过上文按照我的建议不加最后的“,”则这里应为“DC00,8,DC01,8”!
到了这里,我们已经可以自己写替换(或者说拆分)16 位字段的补丁了。但是,对于示例 DSDT,BDC0 是被用到的字段,因此,只是拆分它是不行的。用到它的地方也需要修改。例如这些地方:
- Store (BDC0, Index (DerefOf (Index (Local0, 0x02)), Zero))
- Store (ShiftRight (BDC0, 0x08), Index (DerefOf (Index (Local0, 0x02)), One))
复制代码
由于拆分,BDC0 已经变成两个字段了,于是,我们需要 1 个工具方法来处理拆分后的字段。
- into method label B1B2 remove_entry;
- into definitionblock code_regex . insert
- begin
- Method (B1B2, 2, NotSerialized)/n
- {/n
- Return(Or(Arg0, ShiftLeft(Arg1, 8)))/n
- }/n
- end;
复制代码
对于小白直接将这个加入加入你的补丁中就 ok。
对这个补丁的解读:
1.into method label B1B2 remove_entry; 查找 B1B2 方法,如果有,删除它。
2.into definitionblock code_regex . insert 把后面的内容插入 DefinitionBlock {}(每个 dsdt 的第一个就是这个)内。
对于 dsdt 内其他部分的修改,如下:上面是本身的效果,下面为修改结束的效果:
- Store (BDC0, Index (DerefOf (Index (Local0, 0x02)), Zero))
- Store (ShiftRight (BDC0, 0x08), Index (DerefOf (Index (Local0, 0x02)), One))
复制代码
- Store (B1B2(DC00,DC01), Index (DerefOf (Index (Local0, 0x02)), Zero))
- Store(ShiftRight (B1B2(DC00,DC01), 0x08), Index (DerefOf (Index (Local0, 0x02)), One))
复制代码
于是有了这个补丁:
- into method label GBTI code_regex (BDC0, replaceall_matched begin (B1B2(DC00,DC01), end;
复制代码
主要介绍下几个参数:
1.into method label GBTI
这部分 GBTI 为 dsdt 出现的 BDC0 的方法,至于如何查看,点中你想要的参数,maciasl 自然会显示,如下图:灰色部分即为你要修改为的名称,注意有些是有_的也要完全相同的加进去
2.code_regex (BDC0,
这部分(BDC0, 与上面的查找相同,不过这部分并不能直接把 BDC0 改成你自己的方法就完事!!!举个例子:
- Store (^^PCI0.LPCB.EC0.XIF1, Index (PAK0, One))
复制代码
如果我要改这个中的 XIF1 应该怎么写?应该写为:(^^PCI0.LPCB.EC0.XIF1,
所以这个地方就是看自己的代码具体的情况,改成自己的形式,并且每个标点符号左边要加 ""
3. replaceall_matched begin (B1B2(DC00,DC01), end;
这部分括号内就是你要修改为的内容,还以 2 中例子,应该改成什么?
应该改为:(B1B2(^PCI0.LPCB.EC0.XID1,^PCI0.LPCB.EC0.XID2),
这个地方就是把 B1B2 括号内的两个参数改成你本身括号内的内容,并且把你想改的参数分别改掉。
** 特别提醒:1.以上都是对于在 dsdt 中,store(要修改参数,xxx)的形式
** 如果出现 store(xxx,要修改的参数)则我们要改前改后的形式如下:
- Store (Arg0, ENCR)// 修改前
- Store (ShiftRight(Arg0,8),ENC2)
- Store (Arg0,ENC1)
复制代码
具体代码请结合上处解释自行书写,另外 换行为 /n,空格为 /s。2.如果出现 Or(你要修改的参数,xxx,你要修改的参数)的形式则应该修改为如下形式:
- Or (BATD, 0xC0, BATD)// 修改前
- Store(ShiftRight(Or(B1B2(BTD0,BTD1),0xC0),8), BTD1)
- Store(Or(B1B2(BTD0,BTD1),0xC0), BTD0)
复制代码
3.如果出现 ****And(你要修改的参数,xxx,你要修改的参数)的 形式则修改形式如下:
- And (BATD, 0xFF3F, BATD)// 修改前
- Store(ShiftRight(And(B1B2(BTD0,BTD1),0xFF3F),8), BTD1)
- Store(And(B1B2(BTD0,BTD1),0xFF3F), BTD0)
复制代码
至此,16 位修改完毕,得到形如下补丁:
- # 16-bit registers
- into device label H_EC code_regex BDC0,/s+16 replace_matched begin DC00,8,DC01,8 end;
- into device label H_EC code_regex BDC1,/s+16 replace_matched begin DC10,8,DC11,8 end;
- into device label H_EC code_regex BFC0,/s+16 replace_matched begin FC00,8,FC01,8 end;
- into device label H_EC code_regex BFC1,/s+16 replace_matched begin FC10,8,FC11,8 end;
- into device label H_EC code_regex BDV0,/s+16 replace_matched begin DV00,8,DV01,8 end;
- into device label H_EC code_regex BDV1,/s+16 replace_matched begin DV10,8,DV11,
- # fix 16-bit methods
- into method label GBTI code_regex (BDC0, replaceall_matched begin (B1B2(DC00,DC01), end;
- into method label GBTI code_regex (BDC1, replaceall_matched begin (B1B2(DC10,DC11), end;
- into method label GBTI code_regex (BFC0, replaceall_matched begin (B1B2(FC00,FC01), end;
- into method label GBTI code_regex (BFC1, replaceall_matched begin (B1B2(FC10,FC11), end;
- into method label BTIF code_regex (BFC0, replaceall_matched begin (B1B2(FC00,FC01), end;
- into method label BTIF code_regex (BFC1, replaceall_matched begin (B1B2(FC10,FC11), end;
- into method label ITLB code_regex (BFC1, replaceall_matched begin (B1B2(FC10,FC11), end;
复制代码
接着是 32 位字段的修改
这是与 16 位类似的处理方法:直接打进去就好
- nto 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;
复制代码
32 位的修改方法与 16 位差不多。形如:
- # 32-bit registers
- into device label H_EC code_regex BTY0,/s+32 replace_matched begin TY00,8,TY01,8,TY02,8,TY03,8 end;
- into device label H_EC code_regex BTY1,/s+32 replace_matched begin TY10,8,TY11,8,TY12,8,TY13,8 end;
- # fix 32-bit methods
- into method label GBTI code_regex (BTY0, replaceall_matched begin (B1B4(TY00,TY01,TY02,TY03), end;
复制代码
这部分不懂的去看 16 位的修改方法,完全相同,只是数据变成了四个!二、大于 32 位的字段补丁处理
对于大于 32 位的字段不用进行拆分操作,只需要将用到的地方进行处理就行了。
** 我们先来认识个东西:偏移量。偏移量是啥?看看图中的 offset 代表的就是偏移量。中间的咋算?**
** 偏移量逢 8 进 1,所以在对嘴上面的 offset 往下加就可以得出,如图:**
- Offset (0x04),
- CMCM, 8, //0x04
- CMD1, 8, //0x05(8 位是 1 字节,所以加 1)
- CMD2, 8, //0x06
- CMD3, 8, //0x07
- Offset (0x18), 这里空了一些,不用纠结,按原始 DSDT 给出的偏移量计算就好(会给开头的偏移量)
- Offset (0x19),
- SMST, 8, //0x19
- MBMN, 80, //0x1A
- MBPN, 96, //0x25 = 0x1A+A+1(0x1A 是上一个的起始地址,A 的得来:80 除以 8 得 10,也就是上一个占了 10 个字节,16 进制表示就是 A。0x2A+ A 是它占到了哪个地址,它的下一个地址才是下一个开始,所以再加 1。)
- GPB1, 8, // 0x32 = 0x25 + C(96 位占了 12 个字节)+1
- GPB2, 8, //0x33
- GPB3, 8, //0x34
- GPB4, 8, //0x35
复制代码
另外上 r 神的方法:(其中的 H_EC 同上 请改为自己的设备名,不知道在呢?去看一!)
- # utility methods to read/write buffers from/to EC
- into method label RE1B parent_label H_EC remove_entry;
- into method label RECB parent_label H_EC remove_entry;
- into device label H_EC insert
- begin
- Method (RE1B, 1, NotSerialized)/n
- {/n
- OperationRegion(ERAM, EmbeddedControl, Arg0, 1)/n
- Field(ERAM, 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;
复制代码
- into method label WE1B parent_label H_EC remove_entry;
- into method label WECB parent_label H_EC remove_entry;
- into device label H_EC insert
- begin
- Method (WE1B, 2, NotSerialized)/n
- {/n
- OperationRegion(ERAM, EmbeddedControl, Arg0, 1)/n
- Field(ERAM, ByteAcc, NoLock, Preserve) {BYTE, 8}/n
- Store(Arg1, BYTE)/n
- }/n
- Method (WECB, 3, Serialized)/n
- // Arg0 – offset in bytes from zero-based EC/n
- // Arg1 – size of buffer in bits/n
- // Arg2 – value to write/n
- {/n
- ShiftRight(Add(Arg1,7), 3, Arg1)/n
- Name(TEMP, Buffer(Arg1) {})/n
- Store(Arg2, TEMP)/n
- Add(Arg0, Arg1, Arg1)/n
- Store(0, Local0)/n
- While (LLess(Arg0, Arg1))/n
- {/n
- WE1B(Arg0, DerefOf(Index(TEMP, Local0)))/n
- Increment(Arg0)/n
- Increment(Local0)/n
- }/n
- }/n
- end;
复制代码
两个方法不用同时打,简单来说如果你要改的参数挨着左括号则用一,如果你改的参数离右括号进就用二!修改形式:如图改法:
- Store(MBMN, XXXX) -> Store(RECB(0x1A, 80), XXXX)
复制代码
这时补丁就是
- into method label XXXX code_regex (MBMN, replaceall_matched begin (RECB(0x1A,80), end;
- into method label XXXX code_regex (MBPN, replaceall_matched begin (RECB(0x25,96), end;
复制代码
对比 16 位改对应的位置 如果你的要改参数离右括号进则:
- Store (Arg3, _SB.PCI0.LPCB.EC0.SMD0) -> _SB.PCI0.LPCB.EC0.WECB(0x1C,264,Arg3)
复制代码
这时补丁则为:
- nto method label SMRW code_regex Store/s(Arg3,/s/_SB.PCI0.LPCB.EC0.SMD0) replaceall_matched begin /_SB.PCI0.LPCB.EC0.WECB(0x1C,264,Arg3) end;
复制代码
最后总结下补丁结构:
- # Tip: If you get a 0% battery status,you should also patch the Rehabman’s“Fix Mutex with non-zero SyncLevel”patch.
- # You also can patch the both of your computer’s battery patch and the Rehabman’s patch at one time.
- # 注意:如果打过电量补丁后,有获取的电池状态显示为 0% 的情况,还需要打 Rehabman 的“Fix Mutex with non-zero SyncLevel”补丁。
- # 你也可以,一次性打好 自己电脑的电量补丁 和 Rehabman 的那个补丁。
- # ==== Field devide 字段拆分 ====
- # ==== Replace called method 替换调用方法 ====
- # ==== Data handling method 数据处理方法 ====
复制代码
最后的解释:文中多次提到特殊情况和离括号的的远近不同的处理方法,这是为什么呢?
很简答的原因是 sotre(A,B)是一个从左到右的操作,也就是将 A 写到 B
所以如果 A 是你的参数则是读的操作,而如果是 B 则是写的操作,也就用到不同的方法。
而 Or 的第三个参数,是把前两个数的计算结果,写入到第三个参数的意思。
And 的第三个参数,是把前两个数的计算结果,写入到第三个参数的意思。
不过能理解 store 就够了。
** 将整理好的补丁保存位 txt 格式就能打入了 软件中点 patch。点 open 就行 **
最后,特别感谢翻译贴和 r 神的帖子,也希望你们都能搞定电量显示的问题,另外,如果成功请回馈社会将补丁放于最上面所说帖子的补丁源!