好咧
就这样吧

专为小白设计的电量补丁教程【超详细】

本贴来自:http://bbs.pcbeta.com/viewthread-1751487-1-3.html


个帖子主要针对零基础的小白而设计的,因为大部分人都没学过编程理论。这帖子结合了“daxuexinsheng”和“shiy05”而写的,希望能对笔记本电脑电池还未解决的小伙伴们增添一丝光环!

首先我们来了解下为什么要制作电量补丁?制作电量补丁的好处是什么?

答:

    1)首先,自己制作的电量补丁会更适合自己的机器(其实国外也有很多类似机型的补丁,但是有些补丁太旧导致在新系统中不能良好发挥它的功能)

    2)自己手动制作电量补丁不仅可以提高自己的动手能力,也能提高你的思维方式。

    3)方便交流!使用相同机型的朋友可以相互之间使用同一个补丁,或者一起来修复补丁什么的,是不是很有意思呢?

    4)最大的优势在于你以后加入要从新制作DSDT时,就可以打上你之前制作好的补丁,免得又需要花费大量的时间折腾电量补丁方面!实现一劳永逸!


下面引用“daxuexinsheng”对制作补丁的概要:

背景:

      由于普通PC的电池设备并不兼容与苹果的SMbus设备,所以,对于黑苹果,我们只能够通过ACPI来获取电池状态。Rehabman为此发布了一个通用性的电池驱动。项目地址:https://github.com/RehabMan/OS-X-ACPI-Battery-Driver

      新版的AppleACPIPlatform不能正确地访问EC设备(embedded controller),使得ACPIBatteryManager驱动不能通过普通PC的DSDT里的一些ACPI的方法获取电池信息(例如,_BIF, _STA, _BST等方法,都会获取失败)。虽然可以通过替换旧版AppleACPIPlatform的实现,但不建议这么做,例如,对于三代酷睿平台,原配的AppleACPIPlatform,是启用原生电源管理的前提。综上,为了能够使用系统原配的AppleACPIPlatform,我们就需要修改DSDT来实现电量显示了。

      特别地,任何定义在EC设备里的长度超过8位的字段,都需要被拆分为若干个8位。包括,16位的、32位的、64位的,以及长度更长的。


综上所述::电池状态主要由一些字段存储,而黑苹果目前的电池kext只能处理8位大小的字段。于是,对于大于8位的字段,需要手工修改。



以下为HP-Envy-DV6电量补丁的制作,及简略分析过程,不懂的可以往下面看!!

  1. # created by shiy05 06/28/2017
  2. # based on: HP Envy dv6 battery patch (by RehabMan)
  3. # works for:
  4. #  Lenovo rescuer 14-ISK (tested)
  5. #  Lenovo rescuer 15-ISK (not tested)


  6. # add method B1B2                  //添加16位拆分的方法
  7. into method label B1B2 remove_entry;
  8. into definitionblock code_regex . insert
  9. begin
  10. Method (B1B2, 2, NotSerialized)\n
  11. {\n
  12. Return(Or(Arg0, ShiftLeft(Arg1, 8)))\n
  13. }\n
  14. end;

  15. # add method B1B4                  //添加32位拆分的方法
  16. into method label B1B4 remove_entry;
  17. into definitionblock code_regex . insert
  18. begin
  19. Method (B1B4, 4, NotSerialized)\n
  20. {\n
  21.     Store(Arg3, Local0)\n
  22.     Or(Arg2, ShiftLeft(Local0, 8), Local0)\n
  23.     Or(Arg1, ShiftLeft(Local0, 8), Local0)\n
  24.     Or(Arg0, ShiftLeft(Local0, 8), Local0)\n
  25.     Return(Local0)\n
  26. }\n
  27. end;

  28. //32位以上的字段 不需要拆分,只需要通过工具方法RECB、WECB,来改用到字段的地方。
  29.   //==============添加读写缓存的方法=======================
  30. # add utility methods to read/write buffers from/to \_SB.PCI0.LPCB.H_EC                 
  31. into method label RE1B parent_label \_SB.PCI0.LPCB.H_EC remove_entry;
  32. into method label RECB parent_label \_SB.PCI0.LPCB.H_EC remove_entry;           
  33. into Scope label \_SB.PCI0.LPCB.H_EC insert
  34. begin
  35. Method (RE1B, 1, NotSerialized)\n                     
  36. {\n
  37.     OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
  38.     Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
  39.     Return(BYTE)\n
  40. }\n
  41. Method (RECB, 2, Serialized)\n                                                                                     //RECB代表了” Read EC Buffer”,读取EC缓存
  42. // Arg0 - offset in bytes from zero-based \_SB.PCI0.LPCB.H_EC\n
  43. // Arg1 - size of buffer in bits\n
  44. {\n
  45.     ShiftRight(Arg1, 3, Arg1)\n
  46.     Name(TEMP, Buffer(Arg1) { })\n
  47.     Add(Arg0, Arg1, Arg1)\n
  48.     Store(0, Local0)\n
  49.     While (LLess(Arg0, Arg1))\n
  50.     {\n
  51.         Store(RE1B(Arg0), Index(TEMP, Local0))\n
  52.         Increment(Arg0)\n
  53.         Increment(Local0)\n
  54.     }\n
  55.     Return(TEMP)\n
  56. }\n
  57. end;
  58.   //==============添加写入缓存的方法=======================
  59. into method label WE1B parent_label \_SB.PCI0.LPCB.H_EC remove_entry;                
  60. into method label WECB parent_label \_SB.PCI0.LPCB.H_EC remove_entry;
  61. into Scope label \_SB.PCI0.LPCB.H_EC insert
  62. begin
  63. Method (WE1B, 2, NotSerialized)\n
  64. {\n
  65.     OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
  66.     Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
  67.     Store(Arg1, BYTE)\n
  68. }\n
  69. Method (WECB, 3, Serialized)\n                                                                                     //RECB代表了” Write EC Buffer”,写入EC缓存
  70. // Arg0 - offset in bytes from zero-based EC\n
  71. // Arg1 - size of buffer in bits\n
  72. // Arg2 - value to write\n
  73. {\n
  74.     ShiftRight(Arg1, 3, Arg1)\n
  75.     Name(TEMP, Buffer(Arg1) { })\n
  76.     Store(Arg2, TEMP)\n
  77.     Add(Arg0, Arg1, Arg1)\n
  78.     Store(0, Local0)\n
  79.     While (LLess(Arg0, Arg1))\n
  80.     {\n
  81.         WE1B(Arg0, DerefOf(Index(TEMP, Local0)))\n
  82.         Increment(Arg0)\n
  83.         Increment(Local0)\n
  84.     }\n
  85. }\n
  86. end;



  87. # patch battery status        //为电池状态补丁

  88. # rename 16 variable     //为16位重命名
  89. into Scope label \_SB.PCI0.LPCB.H_EC code_regex B1DT,\s+16, replace_matched begin BDT0,8,BDT1,8, end;
  90. into method label GSBI code_regex B1DT replaceall_matched begin B1B2(BDT0,BDT1) end;

  91. into Scope label \_SB.PCI0.LPCB.H_EC code_regex B1CY,\s+16, replace_matched begin BCY0,8,BCY1,8, end;
  92. into method label GBID code_regex B1CY replaceall_matched begin B1B2(BCY0,BCY1) end;

  93. into Scope label \_SB.PCI0.LPCB.H_EC code_regex RTEP,\s+16, replace_matched begin RTP0,8,PTP1,8, end;
  94. into method label GSBI code_regex RTEP replaceall_matched begin B1B2(RTP0,PTP1) end;

  95. into Scope label \_SB.PCI0.LPCB.H_EC code_regex BET2,\s+16, replace_matched begin B0ET,8,B1ET,8, end;
  96. into method label SMTF code_regex BET2 replaceall_matched begin B1B2(B0ET,B1ET) end;
  97. into method label GSBI code_regex BET2 replaceall_matched begin B1B2(B0ET,B1ET) end;

  98. into Scope label \_SB.PCI0.LPCB.H_EC code_regex B1TM,\s+16, replace_matched begin BTM0,8,BTM1,8, end;
  99. into method label GSBI code_regex B1TM replaceall_matched begin B1B2(BTM0,BTM1) end;

  100. into Scope label \_SB.PCI0.LPCB.H_EC code_regex BAPV,\s+16, replace_matched begin B0PV,8,B1PV,8, end;
  101. into method label _BST code_regex BAPV replaceall_matched begin B1B2(B0PV,B1PV) end;
  102. into method label GSBI code_regex BAPV replaceall_matched begin B1B2(B0PV,B1PV) end;

  103. into Scope label \_SB.PCI0.LPCB.H_EC code_regex BARC,\s+16, replace_matched begin BAC0,8,BAC1,8, end;
  104. into method label _BST code_regex BARC replaceall_matched begin B1B2(BAC0,BAC1) end;
  105. into method label GSBI code_regex BARC replaceall_matched begin B1B2(BAC0,BAC1) end;

  106. into Scope label \_SB.PCI0.LPCB.H_EC code_regex BADC,\s+16, replace_matched begin BDC0,8,BDC1,8, end;
  107. into method label _BIF code_regex BADC replaceall_matched begin B1B2(BDC0,BDC1) end;
  108. into method label GSBI code_regex BADC replaceall_matched begin B1B2(BDC0,BDC1) end;

  109. into Scope label \_SB.PCI0.LPCB.H_EC code_regex BADV,\s+16, replace_matched begin BDV0,8,BDV1,8, end;
  110. into method label _BIF code_regex BADV replaceall_matched begin B1B2(BDV0,BDV1) end;
  111. into method label GSBI code_regex BADV replaceall_matched begin B1B2(BDV0,BDV1) end;

  112. into Scope label \_SB.PCI0.LPCB.H_EC code_regex BAFC,\s+16, replace_matched begin BFC0,8,BFC1,8, end;
  113. into method label _BIF code_regex BAFC replaceall_matched begin B1B2(BFC0,BFC1) end;
  114. into method label GSBI code_regex BAFC replaceall_matched begin B1B2(BFC0,BFC1) end;

  115. into Scope label \_SB.PCI0.LPCB.H_EC code_regex B1CR,\s+16, replace_matched begin BCR0,8,BCR1,8, end;
  116. into method label _BST code_regex B1CR replaceall_matched begin B1B2(BCR0,BCR1) end;
  117. into method label GSBI code_regex B1CR replaceall_matched begin B1B2(BCR0,BCR1) end;

  118. # rename 32 variable     //为32位重命名
  119. into Scope label \_SB.PCI0.LPCB.H_EC code_regex B1CH,\s+32, replace_matched begin BC0H,8,BC1H,8,BC2H,8,BC3H,8, end;
  120. into method label _BIF code_regex B1CH replaceall_matched begin B1B4(BC0H,BC1H,BC2H,BC3H) end;
  121. into method label GSBI code_regex B1CH replaceall_matched begin B1B4(BC0H,BC1H,BC2H,BC3H) end;

  122. # rename 64 variable     //为64位重命名
  123. # 读取缓存
  124. into Scope label \_SB.PCI0.LPCB.H_EC code_regex (B1MA,)\s+(64) replace_matched begin BXMA,%2,//%1%2 end;
  125. into method label GSBI code_regex B1MA replaceall_matched begin RECB(0x8F, 64) end;        //” Read EC Buffer”,读取EC缓存

  126. into Scope label \_SB.PCI0.LPCB.H_EC code_regex (B2MA,)\s+(64) replace_matched begin BYMA,%2,//%1%2 end;     
  127. into method label GSBI code_regex B2MA replaceall_matched begin RECB(0x98, 64) end;       //” Read EC Buffer”,读取EC缓存

  128. # rename 256 variable     //为256位重命名
  129. into Scope label \_SB.PCI0.LPCB.H_EC code_regex (SMD0,)\s+(256) replace_matched begin SMDX,%2,//%1%2 end;
  130. into method label MHPF code_regex Store\s\(FB4,\sSMD0\) replaceall_matched begin WECB(0x1C,256,FB4) end;               //” Write EC Buffer”,写入EC缓存
  131. into method label MHPF code_regex SMD0 replaceall_matched begin RECB(0x1C, 256) end;        #this line must followed the previous line
复制代码

看到以上补丁是不是感觉到一种眼花缭乱,无从下手的感觉?没关系,我领大伙一步一步来分析!

在研究之前需要把制作补丁个部分的定义参数搞清楚!

补丁各部分含义解释:


into  针对

device label 关于这个的设备名范围里

Scope label   范围用于字样软件的左下角,就会有当前这个地方在DSDT里的位置。比如\_SB.PCI0.LPCB._BIF

H_EC     设备的名称

code_regex    匹配(搜索)这样的代码

BDC0,\s+16,   被搜索的代码  

                  

replace_matched      替换匹配

begin … end     begin开始,end; 结束。




补充知识,Bit是位,Byte是字节。1 Byte = 8 Bits,也就是,1个字节等于8位。)


关于16进制的运算:

1. 通过口算或笔算(针对于有编程基础的人): 0. 1. 2 .... 9.A. B. C. D. E. F.

          其中:十六进制数码:A    B    C    D    E    F   

                  十进制数值:   10    11   12   13   14   15   

2. 通过Mac或Windows自带的科学编程计算器计算(适合初级小白)

-----------------------------------------------------------------------------------------------------------------------------------------------------

所需准备的工具:

  iASL;MaciASL;记事本;Mac或Windows自带的科学编程(可有可无)


以下分针对如上补丁进行分析和详解!

具体步骤:

1)用Clover或别的方法提取DSDT和SSDT,为什么还要连SSDT也提取呢?因为有些笔记本的电池读写参数会在SSDT出现。

     2)回到Mac,在桌面新建一个名为“AHCI”的文件夹,把刚提取的DSDT和SSDT丢进去。

     3)下载 iASL  

             cd ~/Downloads

             git clone [url]https://github.com/RehabMan/Intel-iasl.git iasl.git

             cd iasl.git

             make

             sudo make install

          拷贝你下载的iASL

             sudo cp /usr/bin/iasl /Applications/MaciASL.app/Contents/MacOS/iasl61

     4)用 iASL把.aml编译成.dsl,并删除所后缀名为.aml的文件

             cd Desktop

             cd ACPI

             iasl -da -dl *.aml

     5)用命令 grep -i EmbeddedControl *.dsl可以快速找出EmbeddedControl字样的.dsl文件,或许是DSDT,也可能是某个SSDT

     6)找到出EmbeddedControl字样的.dsl文件,用MaciASL打开编辑(建议用最新版本)。本例子出现EmbeddedControl字样的.dsl文件为SSDT-1.dsl

     7)打开SSDT-1.dsl,搜索EmbeddedControl的字样,或许会有几处。本例子只有两处。

             OperationRegion (ECF4, EmbeddedControl, Zero, 0xFF)  

             OperationRegion (ECF3, EmbeddedControl, Zero, 0xFF)


     8)找到embeddedcontrol后,还需要作进一步查找,找embeddedcontrol前面的那个名字,如上面的ERAM、ECOR、SMBX、SMB2等。例如:

              我们要对于embeddedcontro大于8位的字段的地方进行修改,OperationRegion (ECF4, EmbeddedControl, Zero, 0xFF)  没有大于8的字段,所以主要心思还是要放在OperationRegion (ECF3, EmbeddedControl, Zero, 0xFF)里面。


     9)把整个ECF3的设备范围复制到记事本中加以整理(字段分组,8字节的可以忽略;依次分成:16字段、32字段、32以上字段),这样不仅能提高你的补丁制作思路,而且减少不必要的缺漏,大大提高补丁制作的成功率。 例如:

整理后:


被调用16位字段(B1DT,B1CY,RTEP,BET2,B1TM,BAPV,BARC,BADC,BADV,BAFC,B1CR)红色表示只调用了一处,紫色表示只被调用了2处

被调用32位字段(B1CH)紫色表示只被调用了2处

被调用64位字段(B1MA,B2MA)红色表示只调用了一处            

被调用256位字段(SMD0)红色表示只调用了一处



     10)新建一个记事本,先把以下方法复制进去,其中包括16位字段处理方法“B1B2”;32位字段处理方法“B1B4”;32位字段以上读写缓存“WECB”和“RECB”

  1. # created by xxxx

  2. # add method B1B2 
  3. into method label B1B2 remove_entry;
  4. into definitionblock code_regex . insert
  5. begin
  6. Method (B1B2, 2, NotSerialized)\n
  7. {\n
  8. Return(Or(Arg0, ShiftLeft(Arg1, 8)))\n
  9. }\n
  10. end;

  11. # add method B1B4
  12. into method label B1B4 remove_entry;
  13. into definitionblock code_regex . insert
  14. begin
  15. Method (B1B4, 4, NotSerialized)\n
  16. {\n
  17.     Store(Arg3, Local0)\n
  18.     Or(Arg2, ShiftLeft(Local0, 8), Local0)\n
  19.     Or(Arg1, ShiftLeft(Local0, 8), Local0)\n
  20.     Or(Arg0, ShiftLeft(Local0, 8), Local0)\n
  21.     Return(Local0)\n
  22. }\n
  23. end;

  24. # add utility methods to read/write buffers from/to \_SB.PCI0.LPCB.H_EC
  25. into method label RE1B parent_label \_SB.PCI0.LPCB.H_EC remove_entry;
  26. into method label RECB parent_label \_SB.PCI0.LPCB.H_EC remove_entry;
  27. into Scope label \_SB.PCI0.LPCB.H_EC insert
  28. begin
  29. Method (RE1B, 1, NotSerialized)\n
  30. {\n
  31.     OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
  32.     Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
  33.     Return(BYTE)\n
  34. }\n
  35. Method (RECB, 2, Serialized)\n
  36. // Arg0 - offset in bytes from zero-based \_SB.PCI0.LPCB.H_EC\n
  37. // Arg1 - size of buffer in bits\n
  38. {\n
  39.     ShiftRight(Arg1, 3, Arg1)\n
  40.     Name(TEMP, Buffer(Arg1) { })\n
  41.     Add(Arg0, Arg1, Arg1)\n
  42.     Store(0, Local0)\n
  43.     While (LLess(Arg0, Arg1))\n
  44.     {\n
  45.         Store(RE1B(Arg0), Index(TEMP, Local0))\n
  46.         Increment(Arg0)\n
  47.         Increment(Local0)\n
  48.     }\n
  49.     Return(TEMP)\n
  50. }\n
  51. end;

  52. into method label WE1B parent_label \_SB.PCI0.LPCB.H_EC remove_entry;
  53. into method label WECB parent_label \_SB.PCI0.LPCB.H_EC remove_entry;
  54. into Scope label \_SB.PCI0.LPCB.H_EC insert
  55. begin
  56. Method (WE1B, 2, NotSerialized)\n
  57. {\n
  58.     OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
  59.     Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
  60.     Store(Arg1, BYTE)\n
  61. }\n
  62. Method (WECB, 3, Serialized)\n
  63. // Arg0 - offset in bytes from zero-based EC\n
  64. // Arg1 - size of buffer in bits\n
  65. // Arg2 - value to write\n
  66. {\n
  67.     ShiftRight(Arg1, 3, Arg1)\n
  68.     Name(TEMP, Buffer(Arg1) { })\n
  69.     Store(Arg2, TEMP)\n
  70.     Add(Arg0, Arg1, Arg1)\n
  71.     Store(0, Local0)\n
  72.     While (LLess(Arg0, Arg1))\n
  73.     {\n
  74.         WE1B(Arg0, DerefOf(Index(TEMP, Local0)))\n
  75.         Increment(Arg0)\n
  76.         Increment(Local0)\n
  77.     }\n
  78. }\n
  79. end;
复制代码

  10)借助刚才整理后的字段,进行不同的处理。


【8位字段,及8位字段以下】  以整型数据的形式被存取

AppleACPIPlatform能8位字段,及8位字段以下能正常读取,所以不用理会!


【16位字段处理】  以整型数据的形式被存取   通常拆分为2个字节


     16字段(B1DT,B1CY,RTEP,BET2,B1TM,BAPV,BARC,BADC,BADV,BAFC,B1CR)红色表示只调用了一处,紫色表示只被调用了2处


由于16字段较多,这里不一一举例,只列出一个例子,大家要学会灵活贯通。

             BET2,   16,    —>  B0ET,8,B1ET,8,             //把BET2的16位拆分为2个字节

    被调用BET2的16字段(BET2)  一般1-2处,或许更多,看情况而定


在声明字段那里对字段进行拆分

Store (B1CH, IFCH) —> Store (B1B4 (BC0H, BC1H, BC2H, BC3H), IFCH)    //把被调用B1CH两处拆分为2个字节

处理补丁:

[backcolor=rgba(47, 47, 47, 0.0470588)]         into Scope label \_SB.PCI0.LPCB.H_EC code_regex BET2,\s+16, replace_matched begin B0ET,8,B1ET,8, end;


解释:

[backcolor=rgba(47, 47, 47, 0.0470588)]    into Scope label \_SB.PCI0.LPCB.H_EC:into(针对 )\_SB.PCI0.LPCB.H_EC中方法为H_EC这个范围里面

[backcolor=rgba(47, 47, 47, 0.0470588)]    code_regex :匹配(搜索)

[backcolor=rgba(47, 47, 47, 0.0470588)]    BET2,\s+16,:被搜索的匹配的内容

[backcolor=rgba(47, 47, 47, 0.0470588)]    replace_matched:替换匹配

    begin B0ET,8,B1ET,8, end:替换掉的内容    //把BET2拆成两部分,命名的名字应该为4个字符(名字一定要好记,而且不要重复其他DSDT或SSDT地方,否则会发生错误。)


再整体地理解一下这个补丁:

[backcolor=rgba(47, 47, 47, 0.0470588)]    整体的含义: \_SB.PCI0.LPCB.H_EC {} 的范围里,搜索“BET2,\s+16”, 如果有,就把它替换为“B0ET,8,B1ET,8,” 。


被调用的字段那里对字段进行拆分

Return (BET2) —> Return (B1B2 (B0ET, B1ET))   //把被调用B1CH两处拆分为2个字节

处理补丁:

[backcolor=rgba(47, 47, 47, 0.0470588)]         into method label SMTF code_regex BET2 replaceall_matched begin B1B2(B0ET,B1ET) end;

[backcolor=rgba(47, 47, 47, 0.0470588)]         into method label GSBI code_regex BET2 replaceall_matched begin B1B2(B0ET,B1ET) end;


解释第一个被调用到的字段拆分命名处理:

[backcolor=rgba(47, 47, 47, 0.0470588)]    into method label SMTF:into(针对 )method为SMTF这个方法范围里面

[backcolor=rgba(47, 47, 47, 0.0470588)]    code_regex :匹配(搜索)

    BET2:被搜索的匹配的内容

[backcolor=rgba(47, 47, 47, 0.0470588)]    replace_matched:替换匹配

[backcolor=rgba(47, 47, 47, 0.0470588)]   begin B1B2(B0ET,B1ET) end:替换掉的内容  


再整体地理解一下这两段补丁:

[backcolor=rgba(47, 47, 47, 0.0470588)]    整体的含义: 在method为SMTF这个范围里面,搜索“BET2,\s+16”, ,如果有,就把它替换为“B0ET,8,B1ET,8,” 。


1)第一处:

未处理:

            Method (SMTF, 1, NotSerialized)

            {

                If (LEqual (Arg0, Zero))

                {

                    Return (BET2)

                }


                If (LEqual (Arg0, One))

                {

                    Return (Zero)

                }


                Return (Zero)

            }

打入补丁后:

            Method (SMTF, 1, NotSerialized)

            {

                If (LEqual (Arg0, Zero))

                {

                    Return (B1B2 (B0ET, B1ET))

                }


                If (LEqual (Arg0, One))

                {

                    Return (Zero)

                }


                Return (Zero)

            }


2)第二处:

未处理:

             Method (GSBI, 1, NotSerialized)

            {

                Store (BET2, IFAF)                                                                 //未处理前

            }

打入补丁后:

            Method (GSBI, 1, NotSerialized)

            {

                Store (B1B2 (B0ET, B1ET), IFAF)                                               //把被调用B1CH两处拆分为4个字节

            }


【32位字段处理】  以整型数据的形式被存取

     32字段(B1CH)

在声明字段那里对字段进行拆分

             B1CH,   32,    —>  BC0H,8,BC1H,8,BC2H,8,BC3H,8,             //把32位拆分为4个字节

处理补丁:

[backcolor=rgba(47, 47, 47, 0.0470588)]         into Scope label \_SB.PCI0.LPCB.H_EC code_regex B1CH,\s+32, replace_matched begin BC0H,8,BC1H,8,BC2H,8,BC3H,8, end;


解释:

[backcolor=rgba(47, 47, 47, 0.0470588)]    into Scope label \_SB.PCI0.LPCB.H_EC:into(针对 )\_SB.PCI0.LPCB.H_EC这个范围里面

[backcolor=rgba(47, 47, 47, 0.0470588)]    code_regex :匹配(搜索)

[backcolor=rgba(47, 47, 47, 0.0470588)]    B1CH,\s+32,:被搜索的匹配的内容

[backcolor=rgba(47, 47, 47, 0.0470588)]    replace_matched:替换匹配

    begin BC0H,8,BC1H,8,BC2H,8,BC3H,8,end:替换掉的内容    //把BET2拆成两部分,命名的名字应该为4个字符(名字一定要好记,而且不要重复其他DSDT或SSDT地方,否则会发生错误。)


再整体地理解一下这个补丁:

[backcolor=rgba(47, 47, 47, 0.0470588)]    整体的含义: \_SB.PCI0.LPCB.H_EC {} 的范围里,搜索“B1CH,\s+32,” ,如果有,就把它替换为“BC0H,8,BC1H,8,BC2H,8,BC3H,8,” 。



被调用的字段那里对字段进行拆分一般1-2处,或许更多,看情况而定

Return (BET2) —> Return (B1B2 (B0ET, B1ET))   //把被调用B1CH两处拆分为4个字节


处理补丁:

[backcolor=rgba(47, 47, 47, 0.0470588)]         into method label _BIF code_regex B1CH replaceall_matched begin B1B4(BC0H,BC1H,BC2H,BC3H) end;

[backcolor=rgba(47, 47, 47, 0.0470588)]         into method label GSBI code_regex B1CH replaceall_matched begin B1B4(BC0H,BC1H,BC2H,BC3H) end;


解释第一个被调用到的字段拆分命名处理:

[backcolor=rgba(47, 47, 47, 0.0470588)]    into method label _BIF:into(针对 )method为_BIF这个方法范围里面

[backcolor=rgba(47, 47, 47, 0.0470588)]    code_regex :匹配(搜索)

    B1CH:被搜索的匹配的内容

[backcolor=rgba(47, 47, 47, 0.0470588)]    replace_matched:替换匹配

[backcolor=rgba(47, 47, 47, 0.0470588)]   begin B1B4(BC0H,BC1H,BC2H,BC3H)end:替换掉的内容  


再整体地理解一下这两段补丁:

[backcolor=rgba(47, 47, 47, 0.0470588)]    整体的含义: 在method为_BIF这个范围里面,搜索“B1CH”, ,如果有,就把它替换为“B1B4(BC0H,BC1H,BC2H,BC3H)” 。


1)第一处:


第一处:

未处理:

            Method (GSBI, 1, NotSerialized)

            {

                Store (B1CH, IFCH)                                                                  //未处理前

            }

打入补丁后:

            Method (GSBI, 1, NotSerialized)

            {

                Store (B1B4 (BC0H, BC1H, BC2H, BC3H), IFCH)                          //把被调用B1CH两处拆分为4个字节

            }


第二处:

未处理:

            Method (_BIF, 0, NotSerialized)

            {

                If (LEqual (B1CH, 0x0050694C))                                                  //未处理前

            }

打入补丁后:

            Method (_BIF, 0, NotSerialized)

            {

                If (LEqual (B1B4 (BC0H, BC1H, BC2H, BC3H), 0x0050694C))         //把被调用B1CH两处拆分为4个字节

            }



【以下为32位字段以上的处理】

关于偏移量怎么算,我刚发了一个贴,大伙可以参考下。

[教程]关于电量补丁大于32位字段补丁偏移计算


目前帖子还是编辑,等待完善!


读一下内容前需了解


1)处理32为以上的字段的方法。这些字段不用拆分,只要给这个方法传递一下字段的偏移量和字段的长度就可以了。修改32位以上字段的另一个重点,是明确字段所在的偏移量。


  这个方法接受两个参数(偏移量,字段长度),其中,字段长度是8的整数倍

      例如:

            RECB(0x98, 64)                                                           // RECB(偏移量, 字段长度)                                         读取EC缓存

            WECB (0x1C, 256, FB4)                                             // WECB(偏移量, 字段长度,未处理前的前参数 )           写入EC缓存


2)关于 Store ( ) 的操作:Store (前参数,后参数)

需要特别说明,Store的操作顺序是 从左到右 的。


例如:

Store (Arg0, ENCR)  (ENCR是16位的情况)

操作说明:从左到右,也就是,是把 Arg0 的值,“写到” ENCR 里,这时。操作就和“读”不一样了。需要改为:

Store (ShiftRight(Arg0,8),ENC2) (ENC2是16位拆分后的第二个)

Store (Arg0,ENC1) (ENC1是16位拆分后的第一个)



所以,对于字段在括号右边。也就是这样是写入操作补丁如下:


into method label SMRW code_regex Store\s\(Arg3,\s\\_SB.PCI0.LPCB.EC0. ENCR\) replaceall_matched beginStore(ShiftRight(Arg3,8),\\_SB.PCI0.LPCB.EC0. ENC2)\nStore(Arg3, \\_SB.PCI0.LPCB.EC0. ENC1) end;


说明:\s表示1个空白符。搜索匹配的那里,括号 和 斜杠 前面,都需要用 反斜杠 转义。要替换的代码那里,括号不需要 反斜杠转义,斜杠 仍然需要反斜杠转义 。\n 是换行符,意思是另起一行。


补丁的操作结果。

Store (Arg0, ENCR)

修改为

Store (ShiftRight(Arg0,8),ENC2)

Store (Arg0,ENC1)


关于 Store (xxxx, xxxx ),字段在前 是读取操作,字段在后 是写入操作。


【64位字段处理】     大于32位的数据,会以缓存(Buffer)的形式被存取

未打补丁前:

    被调用64位字段(SMD0)

            Offset (0x8F),        //(基地址)

            B1MA,   64,           // 从基地址起 ,为0x8F

Store (B1MA, IFMN) —> Store (RECB(0x8F, 64), IFMN)        //字段B1MA在前 是读取操作

处理补丁:

[backcolor=rgba(47, 47, 47, 0.0470588)]into method label GSBI code_regex B1MA replaceall_matched begin RECB(0x8F, 64) end;  

解释:

  RECB:读取EC缓存

  0x8F:“B1MA,   64 ”字段中的偏移量

    64:表示B1MA的字段长度   

    被调用64位字段(SMD0)

            Offset (0x98),        //(基地址)

            B1MA,   64,           // 从基地址起 ,为0x98

Store (B2MA, IFMN) —> Store (RECB(0x98, 64), IFMN)        //字段B2MA在前 是读取操作

处理补丁:

[backcolor=rgba(47, 47, 47, 0.0470588)]into method label GSBI code_regex B2MA replaceall_matched begin RECB(0x98, 64) end;   

解释:

  RECB:读取EC缓存

  0x98:“B2MA,   64 ”字段中的偏移量

    64:表示B2MA的字段长度   


已打补丁后:

Store (B1MA, IFMN) —> Store (RECB(0x8F, 64), IFMN)

打补丁之后为:Store (RECB (0x8F, 0x40), IFMN)                // 0x40是套入公式后已计算好的值


Store (B2MA, IFMN) —> Store (RECB(0x98, 64), IFMN)


打补丁之后为:Store (RECB (0x98, 0x40), IFDN)                // 0x40是套入公式后已计算好的值

【256位字段处理】     大于32位的数据,会以缓存(Buffer)的形式被存取

    被调用256位字段(SMD0)

            Offset (0x18),          //(基地址)  

            SMPR,   8,              // 从基地址起 ,为0x18

            SMST,   8,              //8,为1个字节;  计算:上一个的起始地址0x18+0x1(上一个的8位占了1个字节,10转为16进制为0x1)值为0x19

            SMAD,   8,             //8,为1个字节;  计算:上一个的起始地址0x19+0x1(上一个的8位占了1个字节,10转为16进制为0x1)值为0x1a

            SMCM,   8,            //8,为1个字节;  计算:上一个的起始地址0x1a+0x1(上一个的8位占了1个字节,10转为16进制为0x1)值为0x1b

            SMD0,   256,       //8,为1个字节;  计算:上一个的起始地址0x1b+0x1(上一个的8位占了1个字节,10转为16进制为0x1)值为0x1c  


未打补丁前:

在“Store (FB4, SMD0)”中,SMD0在后,属于写入操作,套入公式即可:

Store (FB4, SMD0) —> WECB (0x1C, 256, FB4)

处理补丁:

[backcolor=rgba(47, 47, 47, 0.0470588)]into method label MHPF code_regex Store\s\(FB4,\sSMD0\) replaceall_matched begin WECB(0x1C,256,FB4) end;      

解释:

  WECB:写入EC缓存

  0x1C:“SMD0,   256 ”字段中的偏移量

    256:表示SMD0的字段位数                                             


在“Store (SMD0, FB4)”中,SMD0在前,属于读取操作,套入公式即可:

Store (SMD0, FB4) —> Store (RECB (0x1C, 0x0100), FB4)

处理补丁:

[backcolor=rgba(47, 47, 47, 0.0470588)]into method label MHPF code_regex SMD0 replaceall_matched begin RECB(0x1C, 256) end;

解释:

  RECB:读取EC缓存

    256:表示SMD0的字段位数     

已打补丁后:

属于写入操作:

Store (FB4, SMD0) —> WECB (0x1C, 256, FB4)

打补丁之后为:WECB (0x1C, 0x0100, FB4)                 // 0x0100是套入公式后已计算好的值


属于读取操作:

Store (SMD0, FB4) —> Store (RECB (0x1C, 0x0100), FB4)


打补丁之后为:Store (RECB (0x1C, 0x0100), FB4)                 // 0x0100是套入公式后已计算好的值

补充1) 在结尾处最好补上解决电量补丁后,有获取的电池状态显示为0%的情况

# deal with the Mutex problem     

into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;

into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;

into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;

into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;

into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;

into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;

into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;

into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;

into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;

into_all all code_regex Mutex\s+\(([^,]*),\s+[^)]*\) replaceall_matched begin Mutex(%1, 0) end;




补充2) 当电池有时能正常显示电量,有时不能会出现一个小叉,则可能是多个电池的位置导致的,如图有两个位置,分别为“BAT0”和“BAT1”,我们需要禁用掉“BAT1”这个位置,以达到正常读取电量

RehabMan的回复:

Your ioreg shows multiple battery objects active (BAT0, BAT1).

But there is only a battery attached to BAT0, not BAT1.

As per post #1, you must disable the BAT1 by returning zero from _STA.

There are plenty of examples of patching _STA in the repo...

补丁为:

         into method label _STA parent_label BAT1 replace_content begin Return(0) end;


其他牌子的电池可以参考如下:

         SPEEDY-NUC:battery rehabman$ grep into.*method.*_STA.*Return *.txt

         battery_HP-Envy-14.txt:into method label _STA parent_label BAT1 replace_content begin Return (Zero) end;

         battery_HP-ProBook-4x0s-G1.txt:into method label _STA parent_label BAT1 replace_content begin Return (Zero) end;

         battery_HP-ProBook-Generic.txt:into method label _STA parent_label BAT1 replace_content begin Return (Zero) end;

         battery_Lenovo-G50-70.txt:into method label _STA parent_label BAT1 replace_content begin Return (Zero) end;

         battery_Lenovo-X201.txt:into method label _STA parent_label BAT1 replace_content begin Return(0) end;

         battery_Lenovo-X220.txt:into method label _STA parent_label BAT1 replace_content begin Return(0) end;

         battery_Lenovo-X230i.txt:into method label _STA parent_label BAT1 replace_content begin Return(0) end;

         battery_Partaker_G3.txt:into method label _STA parent_label BAT2 replace_content begin Return(0) end;

         battery_Sony-VAIO-S.txt:into method label _STA parent_label BAT1 replace_content begin Return (0x1F) end;

         battery_Sony-VAIO-S.txt:into method label _STA parent_label BAT2 replace_content begin Return (Zero) end;


         battery_Sony-VAIO-S.txt:into method label _STA parent_label H_EC replace_content begin Return (0x0F) end;

打补丁后,IOREG只显示“BAT0”。


相关推荐

最新回复