这篇帖子主要来源于论坛https://github.com/RehabMan/Laptop-DSDT-Patch。
但是很多笔记本并未出现在这个补丁源里,并且我们要了解补丁的意思才知道它适不适合我们的电脑。
电量补丁制作过程
我们需要确定DSDT里的哪些部分需要改。
用
MaciASL
软件打开DSDT,搜索**EmbeddedControl
。在DSDT
里,可能会有一到多个。同时注意一个计算机名字如下图为EC0
**
1 | OperationRegion (ECF2, EmbeddedControl, Zero, 0xFF) |
上面的代码,我们只需要关注ec
域声明的名字,即**ECF2
(别的可能是ECF0
等)。
我们开始搜索Field(ECF2
**。
- 我们需要查看Field里所有大于8位的元素,例如:
1 | Field (ECF2, ByteAcc, Lock, Preserve) |
可以看到**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神的帖子,也希望你们都能搞定电量显示的问题,另外,如果成功请回馈社会将补丁放于最上面所说帖子的补丁源!