小埋社区

    • Login
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups

    修改DSDT实现电量显示

    科技
    黑苹果 hackintosh
    1
    1
    1580
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • 闲淡酱
      闲淡酱 站长 last edited by

      前言

      玩黑苹果除了要解决显卡、声卡的驱动问题,对于笔记本来说电量显示也是很重要的东西。部分笔记本直接放入ACPIBatteryManager.kext就可以正常显示电量了,大部分笔记本还需要修改DSDT才可以正常驱动。

      屏幕快照 2019-01-19 下午4.49.56.png
      ▲ 没有正确驱动电池

      一开始觉得修改DSDT是一件很难的事情,甚至想放弃……经过四处爬帖摸索,在这里分享一下我的经验,我觉得小白也许都可以看得懂(因为我也是小白

      准备所需的东西

      MaciASL(用于编辑提取的DSDT文件)
      ACPIBatteryManager.kext (放入Clover用来驱动电池)
      iASL(非必须,看情况来使用)

      前期工作

      在Clover的启动界面,按F4提取你机子的DSDT,确保之前没有放过DSDT文件在里面,要提取纯净的DSDT。

      提取好后在clover下找到ACPI目录的origin目录,正常情况下会有这么多的文件。

      屏幕快照 2019-01-19 下午5.00.29.png

      很多人说提取到DSDT后不能直接修改,要进行反编译,不然后面修改会报错。经过我的实测,如果直接打开然后编译没有报错的情况,直接修改是没有影响的。不排除有的机子提取的会有错误,这时候可以尝试下用iASL反编译一下。如果还是有错,请自行排错。

      屏幕快照 2019-01-19 下午5.11.35.png

      用MaciASL打开DSDT.aml,如果0 Errors则说明无报错,可以开始修改,其他的不用管。

      修改阶段

      https://github.com/RehabMan/Laptop-DSDT-Patch/tree/master/battery

      可以先去这个地方,看看有没有自己机型的DSDT。如果很幸运的话,恰巧你只是为了解决电量显示问题,可以直接拿来用了。如果没有,也可以尝试下型号相近的机子的DSDT。

      把里面的代码全部复制,粘贴到如图第2步的位置,然后单击Apply即可。

      QQ20190119-173116.png

      如果没有的话,就可以开始自己做DSDT了。以下的步骤以我的机子为例子来操作。

      电量显示其实只要把大于8位的字段进行拆分即可,只要记住这点就好了。基本上没有烧脑的操作,都是繁琐的重复步骤。

      打开搜索,搜索EmbeddedControl

      QQ20190119-173630.png

      然后搜索 Field (ECOR ,不同机型的参数都不一样。

      QQ20190119-173737.png

      可以看到搜索框后面反馈的有7个,我们就在这7个里找到大于8位的字段出来,新建一个记事本来记录。确保不要有遗漏,可以按Done前面的左右按钮来跳到每一个 Field (ECOR 里。

      QQ20190119-174148.png
      这就是一个大于8位的字段,是一个16位的字段。

      QQ20190119-174312.png
      这里就是两个32位的字段。每找到一个,就把它记录到记事本里。

      记录好后如下
      屏幕快照 2019-01-19 下午5.46.23.png

      只有16和32位的字段才需要拆分,大于32位的不用拆,只需替换访问属性即可。当然,也并不是所有在 Field (ECOR 找出来的的16位和32位的字段都要拆分,只要拆分有访问到的字段就可以了,没有访问的字段不用管。

      如何查看字段是否有访问,可以利用搜索,然后把字段名复制进去。
      QQ20190119-175051.png

      这里我们用SBDC这个字段为例子,可以看到SBDC有4处,意味着这个属性有被访问到。相反,如果字段只找到1处的,就说明这个字段只是被定义了,并没有被访问到。通过这个方法把记录的字段逐个搜索一下,只保留搜索到大于1处的字段。

      拆分之前需要先用两段代码,因为拆分后的字段要存储在B1B2和B1B4的变量里。

      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;
      
      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;
      

      打开Patch,复制上面的代码,然后Apply即可。
      屏幕快照 2019-01-19 下午5.59.16.png

      现在可以开始拆分了。我们用HWAK这个字段举个例子,这是个16位的字段,我们可以拆分成两个8位的字段,可以命名为 AK00 和 AK01 。当然,命名可以随意,但是要确保这个命名没有出现在DSDT里。

      //拆分前
      HWAK, 16
      // 拆分后
      AK00, 8
      AK01, 8
      

      然后,我们需要写一个正则表达式,来替换DSDT里的字段。

      into device label EC code_regex HWAK,\s+16, replace_matched begin AK00,8,AK01,8, end;
      

      device label 后面的EC就是第一步搜索EmbeddedControl,在EmbeddedControl上方的Device,不要和Filed里的参数搞混了。

      然后把刚才写好的正则表达式复制到Patch里,注意一定要以下两个地方都显示出东西才算写好了。

      QQ20190119-181117.png

      再来拆分个32位的字段,跟16位一样,32位就拆分成4个8位的字段。以SBCH为例,可以拆分成CH00,CH01,CH02,CH03。

      //拆分前
      SBCH, 32
      // 拆分后
      CH00, 8
      CH01, 8
      CH02, 8
      CH03, 8
      

      同样来写一个正则表达式

      into device label EC code_regex SBCH,\s+32 replace_matched begin CH00,8,CH01,8,CH02,8,CH03,8 end;
      

      屏幕快照 2019-01-19 下午6.16.56.png

      接着我们可以尝试编译下,点击Compile,这时会发现有报错

      屏幕快照 2019-01-19 下午6.34.17.png

      点击报错信息,看看错误的位置。其实是因为我们只替换了定义的字段名,并没有把其它访问这个字段的地方也一起修改,访问不到字段,固然会报错。

      所以我们需要替换属性访问,把访问的HWAK也换成我们刚刚替换的AK00和AK01。打开搜索,选中刚刚报错的那一行代码,然后搜索框里输入method,我们要找到这段代码包含在哪个method里,用搜索框旁边的左右键,单击“<”,不然就会找到下面的method里去。

      一般情况下直接用下面的正则表达式就可以了。

      into method label \_WAK code_regex \(HWAK, replaceall_matched begin (B1B2(AK00,AK01), end;
      

      当然也有特殊情况,在我的这台机子上,就出现了**\_SB.PCI0.LPC.EC.HWAK**这样的调用。

      into method label \_WAK code_regex \(\\\_SB.PCI0.LPC.EC.HWAK replaceall_matched begin \(\\_SB.B1B2(\\_SB.PCI0.LPC.EC.AK00, \\_SB.PCI0.LPC.EC.AK01) end;
      

      屏幕快照 2019-01-19 下午6.49.52.png

      同样的,在Patch里试试看是否正确替换。后面的报错以此类推的,找出来进行替换即可。32位的字段替换属性访问也类似的操作

      into method label GBIF code_regex \(SBCH, replaceall_matched begin (B1B4(CH00,CH01,CH02,CH03), end;
      

      16位和32位的字段处理完成后,就开始解决大于32位的字段了。以我机子的DSDT为例子,在这里大于32位的字段只找到两个128位的。

      QQ20190119-190257.png

      然后我们需要计算偏移量,偏移量的计算大概是这样的,第一个字段的偏移量从起始值开始。所以,SBMN和SBDN的偏移量就是0xA0。很幸运,我的这台机子不需要自己计算,直接改就可以了。

      需要先Patch一段代码,如果要改的参数挨着左边的括号。例如SBMN这样,就是挨着左边的。

      QQ20190119-191023.png

      用下面的这一段,其中H_EC请改成自己的Device。

      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;
      

      然后直接用正则表达式替换即可。

      into method label GBIF code_regex \(SBMN, replaceall_matched begin (RECB(0xA0,128), end;
      

      如果是56或者64位什么的,就把128改了就可以了。如果需要计算偏移量,逢8进1,从起始值往下算即可。

      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
      

      最后

      把修改好的DSDT.aml保存好,放到clover的ACPI目录下的patched目录里,如果没有就自己手动创建一个,不出意外的话,重启电脑就可以看到电池图标了。

      才疏学浅,如有错漏,欢迎指出。

      参考文献

      • http://bbs.pcbeta.com/viewthread-1778499-1-1.html

      • https://www.tonymacx86.com/threads/guide-how-to-patch-dsdt-for-working-battery-status.116102/

      1 Reply Last reply Reply Quote 0
      • First post
        Last post
      © 2017-2022 小埋社区 All Rights Reserved | 皖ICP备17016228号-2