sleepnet 发表于 2017-6-12 13:10

[翻译]使用hotpatches修补dsdt(很多人应该看过,献丑翻译一下)

原贴地址:https://www.tonymacx86.com/threads/guide-using-clover-to-hotpatch-acpi.200137/
作者:RehabMan
    hotpatch在RehabMan大神维护得elitebook系列机型方面体现得很完美,我是翻elitebook机型的hotpatch后发现的,所以我决定来翻译这个教程,水平有限(大部分东西看不懂,靠有道翻译对付的,凑合吧),错漏之处请各位指出,谢谢。
先贴上国内的几个帖子,都写得很好,方便大家理解,版权归原作者。

1.华硕 VM510LEFI分享9CC3笔记本主板芯片通用 :
https://blog.neroxps.cn/blog/macOS/9CC3-EFI-README.html
2.hotpatch学习笔记:
https://bbs.pcbeta.com/forum.php?mod=viewthread&tid=1733965
3.暗影精灵2代Pro安装macOS Sierra 10.12.5全记录(hotpatch):
https://bbs.pcbeta.com/viewthread-1742550-1-1.html
目前我认为第三篇帖子和RehabMan的hotpatch方法是比较接近的,不过只是个人主观意见。

附上帖子里提到的另一份帖子的翻译(WR123翻译):http://blog.csdn.net/wr132/article/details/54798754

介绍
      在接近MAC配置的非MAC硬件上修补ACPI使之启用(接近)MAC的完整功能。
在这里有一份完整的指导:http://www.tonymacx86.com/threads/guide-patching-laptop-dsdt-ssdts.152573/

      指导使用所谓的“静态修补(static patching)”,为了注入ACPI补丁文件,我们提取本机ACPI,将他们拆开,进行修改,然后重新编译放到\efi\clvoer\ACPI\patch目录下,这是使用clover注入修补ACPI,而不是修改硬件ACPI。本方法涉及到的技术,可以直接从BIOS读取ACPI的修补文件,跳过提取、拆卸和重编译步骤。

      在试图修复ACPI之前,你应该理解ACPI的一些规范、概念,和一些关于二进制补丁和编译的基础。这份指南不会详细讲解这些知识。


Clover的修补机制

Clover提供了一些方法来完成ACPI hotpatch:

- config.plist/ACPI/DSDT/Fixes(在config.plist文件ACPI/DSDT/下添加修复)
- config.plist/ACPI/DSDT/Patches(在config.plist文件ACPI/DSDT/下添加补丁)
- ability to inject additional SSDTs(在ssdt文件下注入额外的功能)
(这一部分体现得最好的是在elitebook机型下面,elitebook机型的hotpatch详见:https://github.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch)

DSDT/Fixes提供固定功能的ACPI修补,每个“Fixes”可以做一种特殊的修补,可以用来代替典型修补你可能与MaciASL和静态修补。例如,“IRQ Fix”可以实现与“Fix HPET_0010”“FixIPIC_0040”“FIX_RTC_20000”和“FIX_TMR_40000”;再看另一个实例,"Fix _WAK Arg0 v2”可以实现WAK Arg0 v2修补。你可以阅读Clover wik了解更多信息。大多数时候,DSDT实现基本功能不需要太多的"Fixes”,DSDT "Fixes" 是难于实现或修补很困难的可以尝试放到ACPI/DSDT/Patches 或者添加到 SSDTs.

Clover允许在config.plst/DSDT/Patches下搜索和替换二进制,三叶草加载本地ACPI文件时,会应用config.plst/DSDT/Patches定的Patches二进制文件进行搜索/替换,然后注入修补ACPI。你需要了解AML的二进制格式。和常用的ACPI规范。

ACPI名称规则是建立、合并DSDT、SSDT在加载时间(这一句翻不出来,意思就是ACPI里面的命名是很重要的),通过在ssdt添加ACPI 代码,实现额外的ACPI修补。因为许多OS X补丁涉及添加属性ioreg _DSM方法,通常SSDT包含足够的简单地添加一个额外的_DSM方法而不是修补本机ACPI文件。一个简单的例子就是使用ssdtPRGen.sh生成ssdt.aml实现CPU变频。

在某些情况下,必须使用一个以上的方法来完成一个目标。例如,您可能使用在本机ACPI使用二进制补丁禁用或重命名组件,然后用额外的ssdt取而代之。

重命名ACPI对象(Renaming ACPI objects)

特定的ACPI对象名称可以供MAC使用,一个常用的方法就是重命名本机ACPI对象集。例如,大多数PC和笔记本使用inter HD(GPU)核显,在ACPI下GPU对象命名为GFX0,在OS X的电源管理中,英特尔图形默认不启用,除非这个设备叫IGPU,使用静态修补(static patching),我们应用"Rename IGPU to GFX0" 重命名GFX0为IGPU,补丁应用到DSDT和所有的ssdt才能使用。

使用hotpatch时,我们在ACPI/DSDT/Patches下添加’GFX0 to IGPU’,这个补丁适用于DSDT和所有本地ssdt(ACPI/patchedDSDT /补丁并不适用于ssdt添加通过ACPI /修补),重命名的补丁将会:

Comment: Rename GFX0 to IGPU
Find: <4746 5830>
Replace: <4947 5055>

十六进制值查找和替换的ASCII码GFX0 IGPU,分别为:

u430:~ RehabMan$ echo -n GFX0|xxd
0000000: 4746 5830                              GFX0
u430:~ RehabMan$ echo -n IGPU|xxd
0000000: 4947 5055                              IGPU

有许多常见的重命名,大多数config.plist在Clover/ hoptpatch项目:
https://github.com/RehabMan/OS-X-Clover-Laptop-Config/tree/master/hotpatch

实际上, SSDT一部分相同的项目也取决于实现的重命名项目:

常见的重命名项目:
GFX0 -> IGPU
SAT0 -> SATA
EHC1 -> EH01
EHC2 -> EH02
XHCI -> XHC
HECI -> IMEI
MEI -> IMEI
LPC -> LPCB
HDAS -> HDEF
AZAL -> HDEF

注意:所有ACPI标识符是4个字符。短名称带下划线。例如,XHC在AML的二进制表示XHC_,EC表示为EC__,美将MEI_等等,EC0表示为EC_,MEI表示为MEI_等等。

删除方法(Removing methods)

使用三叶草二进制补丁很难消除ACPI对象(methods, names, devices, etc),通常,我们必须添加_DSM方法注入属性描述各种硬件属性,但添加_DSM方法可以与现有_DSM方法冲突,也许已经在本机ACPI文件中了。使用静态修补,我们将使用"Remove _DSM methods”。

因为很难去除,我们不希望我们添加的_DSM和本地DSM冲突,解决办法是将本地_DSM重命名为别的名称。

我们使用一个简单的重命名补丁:
Comment: Rename _DSM to XDSM
Find: <5f44534d>
Replace: <5844534d>

有时你重命名的对象可能被禁用了,因此他不会产生其他问题。例如:我的英特尔DH67GD DSDT定义了一个APSS对象,如果这个对象留在DSDT里面,将会干扰电源管理,我将APSS命名为APXX,因为AppleIntelCPUPowerManagement寻找APSS,重命名为APXX解决了问题。

重定向和替换(Redirect and Replace)

在某些情况下,我们想替换代码改变ACPI的行为,为此,我们可以重命名对象,提供另一种方式实现DSDT修补。

一些代码表现得像特定的windows的ACPI代码,一个修补是修改ACPI代码和SSDT来欺骗DSDT。静态修补时,我们可能会使用“OS Check Fix (Windows 8)”。应用时,它改变了代码:

If (_OSI("Windows 2012"))
To:
If (LOr(_OSI("Darwin"),_OSI("Windows 2012"))

因为_OSI实现在OS X只回应"Darwin" 代码改变这个特定_OSI检查也可放置"Darwin" 。

hotpatch采用相反的方法,不是使用_OSI改变代码,我们改变的代码调用方法,模拟_OSI实现将在Windows ACPI。

首先,改变代码来调用XOSI代替_OSI:

Comment: Change _OSI to XOSI
Find: <5f4f 5349>
Replace: <584f 5349>

上面的十六进制代码应该不难理解(ASCII _OSI和XOSI,分别)。
现在代码上面所提到的,在三叶草修补之后,将读取:

If (XOSI("Windows 2012"))

现在我们需要一个实现XOSI的SSDT,你会发现这样在repo库中有一个实现的SSDT(SSDT-XOSI.dsl)。

注意,未经XOSI SSDT实现方法,(修补)调用XOSI将导致一个ACPI中止(ACPI中止原因ACPI的执行方法立即终止与一个错误)。不要使用_OSI->XOSI修补,没有更改为XOSI的修补方法。

重命名和替换(Rename and Replace)

第二个模式,类似于“重定向和替换(Redirect and Replace)”是“重命名和替换(Rename and Replace)”。在这种情况下,我们改变定义的方法,而不是改变调用的位置,这样的方法和重命名作用是不一样的。这种方法调用的目的是取代ACPI定于的对象。

例如一个很常见的USB设备错误是‘及时唤醒’(”instant wake”),在唤醒之后USB将会被禁用,大多数笔记本在BIOS设置里没有这个选项,所以我们采用添加_PRW的方法控制这个特性。

例如,本机 _SB.PCI0.EHC1._PRW方法可能读取:

            Method (_PRW, 0, NotSerialized)// _PRW: Power Resources for Wake
            {
                Return (GPRW (0x6D, 0x03))
            }

为USB设备添加EHCI补丁,结果将变成:

            Method (_PRW, 0, NotSerialized)// _PRW: Power Resources for Wake
            {
                Return (GPRW (0x6D, 0))
            }

通常,有这样几个调用GPRW的位置需要改变(同时需要记住,不是ACPI所有的GORW都使用这一特性),我们可以采用不用添加GPRW定义的方法,而不是尝试去修复。

原来的代码:

Method (GPRW, 2, NotSerialized)
{
   ...
}

改变之后的代码:

Method (XPRW, 2, NotSerialized)
{
   ...
}

如果你不想改变任何地方,你必须构建补丁,这样只影响调用的方法,而不会改变调用的位置。
根据ACPI定义规范,一个方式从14字节的位置定义,后面是大小的定义、方法名称、参数/特性(method name, argument count/flags),您可以使用“- l”选项iasl生成混合ACPI文件的list。例如:Lenovo u430 GPRW混合list如下:

    4323:          Method (GPRW, 2, NotSerialized)

00003F95:14 45 08 47 50 52 57 02   ".E.GPRW."

    4324:          {
    4325:            Store (Arg0, Index (PRWP, Zero))

00003F9D:70 68 ..................    "ph"
00003F9F:88 50 52 57 50 00 00 ...    ".PRWP.."

我们可以找到取代使用报头字节的方法(method header bytes):

Find: <14 45 08 47 50 52 57 02>
Replace: <14 45 08 58 50 52 57 02>

如果在不同的BIOS版本之间,或是类似的配置,配置的方式也有所不同。在这种情况下,14字节改变后变换长度的方法。


我的认为:方法主要是开始不大可能去对比字节的总长度,因此可以采用增加一些额外的字节来进行查找替换:

Find: <47 50 52 57 02 70 68>
Replace: <58 50 52 57 02 70 68>

后续字节的数量取决于你使用多少你需要查找/替换影响该方法定义。您可以验证通过查看本机AML二进制在十六进制编辑器,如Hex Fiend(它是一个很好的十六进制编辑器,也是开源)。

注意:虽然您可以搜索name + arg count/flags,可能会找到一个相同的模式调用网站你不想改变的位置。在u430不是这样,所以我能够查找/替换只有name+flags。

Find: <47505257 02>
Replace: <58505257 02>

在ProBook定义UPRW,有必要使用后续字节定义:

Find: <55505257 0a7012>
Replace: <58505257 0a7012>

现在任何代码调用GPRW(或UPRW该例子),不会调用实现XPRW,因为名称不匹配。原XPRW是不可能达到的,这意味着GPRW实现可以改变我们的目的:

Method(GPRW, 2)
{
    If (0x6d == Arg0) { Return(Package() { 0x6d, 0, }) }
    External(\XPRW, MethodObj)
    Return(XPRW(Arg0, Arg1))
}

解释代码:对于任何调用与第一个参数设置为0 GPRW x6d(GPE我们试图禁用后),而不是返回原始的GPRW,我们返回一个包与0 x6d和0(禁用后)和其他的GPE值,现在使用简单的XPRW命名方法调用原始GPRW。

另一个简单的例子是修补EC解决亮度键查询方法,一个简单的重命名_Qxx为XQxx方法有关,和一种新的定义方法与原来的名字是所需要的。

例如,在HP Envy Haswell repo:

// _Q13 called on brightness/mirror display key
      Method (_Q13, 0, Serialized)// _Qxx: EC Query
      {
            External(\HKNO, FieldUnitObj)
            Store(HKNO, Local0)
            If (LEqual(Local0,7))
            {
                // Brightness Down
                Notify(\_SB.PCI0.LPCB.PS2K, 0x0405)
            }
            If (LEqual(Local0,8))
            {
                // Brightness Up
                Notify(\_SB.PCI0.LPCB.PS2K, 0x0406)
            }
            If (LEqual(Local0,4))
            {
                // Mirror toggle
                Notify(\_SB.PCI0.LPCB.PS2K, 0x046e)
            }
      }

相关的补丁:

Comment: change Method(_Q13,0,S) to XQ13
Find: <5f513133 08>
Replace: <58513133 08>

同样可以使用“重命名和替换”机制的情况下要比这复杂得多。例如,它通常用于块电池的方法,需要修补,避免使用多字节EC字段。

对于复杂的重命名和替换的建议

正如您可能已经知道,修补电池状态(多字节EC字段)可能非常复杂,涉及到很多代码更改许多方法,修补时需要避免使用多字节EC字段。

本节将详细的一些技术和程序用于电池修补。

不建议电池使用hotpatch第一个补丁(DSDT/Fixes),可以尝试使用hotpatch让电源工作,不同的电池采用的修补方式是不一样,这不仅仅是修补代码和修补方式的差别。您可以使用“diffmerge”这样的工具来进行对比,你可以在我的代码库里面逐步尝试里面的修补,选出最适合你的。

一般流程:
-尝试本地ACPI
-对电池池状态使用静态修补(验证它的工作原理)
-使用diffmerge比较修改代码补丁代码
-每个方法都是不同的,尝试实现“重命名和替换”模式
-尝试创建独立的EC代码(使用一个不同于原来的名称),进行字段定义为一种“叠加”,和添加只包含EC字段需要的补丁
-创建EC叠加文件,您可以使用hotpatch 在DCDT里修补Field/OperationRegion,然后消除应用补丁的字段。
-使用外部允许的替代方法在SSDT访问字段定义的其他地方的ACPI设置(通常DSDT)
-让编译器指出您需要使用外部定义
-注意符号重复和名称在不同的范围内

让我们来看一个例子....< todo:使用u430示例>

代码值修补(Code value patching)

考虑解决零SyncLevel互斥的情况下,这个补丁发现所有互斥对象和取代了SyncLevel 0,OS X以来我们使用这个补丁不支持互斥调试正确和中止任何获得互斥锁,有一个非零SyncLevel。

作为一个例子,u430互斥delcared这样:
      Mutex (MSMI, 0x07)

让它兼容OS X必须改变:
      Mutex (MSMI, 0)

ACPI规范定义了一个互斥对象如何在AML编码,但是它可以帮助看混合拆卸的小ACPI文件:

DefinitionBlock ("", "DSDT", 2, "test", "test", 0)
{
    Mutex(ABCD, 7)
}

iasl编译器可以创建一个混合清单文件“- l”选项。
如果我们编译上面的文件:iasl - l测试。dsl,测试。lst包含:


       1:DefinitionBlock ("", "DSDT", 2, "test", "test", 0)

00000000:44 53 44 54 2B 00 00 00   "DSDT+..."
00000008:02 36 74 65 73 74 00 00   ".6test.."
00000010:74 65 73 74 00 00 00 00   "test...."
00000018:00 00 00 00 49 4E 54 4C   "....INTL"
00000020:10 04 16 20 ............    "... "

       2:{
       3:      Mutex(ABCD, 7)

00000024:5B 01 41 42 43 44 07 ...    "[.ABCD."
       4:}

如您所见,互斥锁(ABCD 7),编码是< 5 b 01 41 42 43 44 07>

现在很容易构造一个补丁:

Comment: Change Mutex(ABCD,7) to Mutex(ABCD,0)
Find: <5B 01 41 42 43 44 07>
Replace: <5B 01 41 42 43 44 00>

Clover ACPI configuration

使用静态修补(static patching)DropOem = true和修补DSDT&ssdt被添加到ACPI /patch,而不是只有附加ssdt放置在ACPI /patch,使用DropOem = false。

重要的是要注意config.plist/ACPI /patch仅适用于本地ssdt,而不是作用在ACPI/patched/SSDTs。这意味着,如果你是使用config.plist重命名对象,附加ssdt必须参考新名称,不能使用旧的名称。不同于ACPI/patched/SSDTs,ACPI/patch目录下二进制补丁作用在DSDT(.aml),牢记这一点如果你使用静态(static)和hotpatching的组合。

使用静态修补,SortedOrder用于指定的顺序ACPI/patched目录下的ssdt,hotpatch这并不是必需的,因为它可以构建每个SSDT中,代码中的代码没有固定的依赖关系,尤其是如果你把所有插件的代码放在一个SSDT。除非你的附加ssdt顺序依赖,你没有在SortedOrder更改对应名称。

也没有必要为每个SSDT选择“名称编号”,相反,您可以使用有意义的名称,例如“SSDT-USB.aml”,SSDT-XOSI.aml”等。用数字代替meaningul名字只会迷惑你,不要这样做。

解决问题

您可以使用patchmatic看看你完整ACPI修补后注入的clover,运行 'patchmatic -extract', 提取修复后的DSDT.aml and SSDT*.aml . 你可以使用'iasl -da -dl *.aml’反编译出dsl文件,如果反编译iasl显示错误(例如复制符号)。这些ssdt在OSX中也不会被使用的。

如果你是一个新手,这是一个好主意来实现一个补丁,慢慢建立一套完整的补丁ssdt工作。慢慢地解决问题,不要想着一次解决所有的问题。

问题报告

下载patchmatic: https://bitbucket.org/RehabMan/os-x-maciasl-patchmatic
解压’patchmatic' 并拷贝到 /usr/bin,路径为:/usr/bin/patchmatic,如果你完成了,可以使用以下命令:

if [ -d ~/Downloads/RehabMan ]; then rm -R ~/Downloads/RehabMan; fi
mkdir ~/Downloads/RehabMan
cd ~/Downloads/RehabMan
patchmatic -extract

注意:更容易如果你使用复制/粘贴,而不是手动输入的命令。

同时附上 ioreg: http://www.tonymacx86.com/audio/58368-guide-how-make-copy-ioreg.html. 请使用IORegistryExplorer v2.1,不要使用其他版本,

输出:
kextstat|grep -y acpiplat
kextstat|grep -y appleintelcpu
kextstat|grep -y applelpc

同时,附上EFI/Clover文件夹(按下F4主要clover屏幕前收集)。请删除'themes' 目录,特别是如果你有过多的主题安装。只提供EFI/Clover,不是整个EFI文件夹。

也可以附上重建缓存日志:
sudo touch /System/Library/Extensions && sudo kextcache -u /

翻译到此结束。


附上RehabMan大神的github:
1.OSX clover laptop config:https://github.com/RehabMan/OS-X-Clover-Laptop-Config
这里面提供了一些常见的补丁和说明,还有笔记本的通用config.plist。
2.elitebook/probook/zbook系列机型:https://github.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch
3.Inter NUC 5/6/7系列:https://github.com/RehabMan/Intel-NUC-DSDT-Patch
4.Lenovo U330/U430/U530系列:https://github.com/RehabMan/Lenovo-U430-Touch-DSDT-Patch
5.HP envy J/K/Q/RHaswell系列:https://github.com/RehabMan/HP-Envy-DSDT-Patch
6.Lenovo Z50-70/Z40-70系列:https://github.com/RehabMan/Lenovo-Z50
7.Lenovo Y50/Y40-70系列:https://github.com/RehabMan/Lenovo-Y50-DSDT-Patch


wyhtc 发表于 2017-6-12 14:49

看不懂,帮顶。。

smg_zj 发表于 2017-6-12 15:07

太长,太看不懂,帮顶

zhaiman 发表于 2017-6-12 15:12

hotpatch 用起来挺方便的,而且大部分通用,貌似大家都不怎么喜欢用{:9_355:}

wyhtc 发表于 2017-6-12 15:21

zhaiman 发表于 2017-6-12 15:12 https://www.pcbeta.com/static/image/common/back.gif
hotpatch 用起来挺方便的,而且大部分通用,貌似大家都不怎么喜欢用

主要是看不懂。。

dlhonghan 发表于 2017-6-12 15:26

感谢分享   

zhaiman 发表于 2017-6-12 15:37

wyhtc 发表于 2017-6-12 15:21 https://www.pcbeta.com/static/image/common/back.gif
主要是看不懂。。

把上面楼主提到的那三个教程都认真看一遍就基本没问题的了,比去提取DSDT反编译改错修改再编译简单多了,找到合适的hotpatch直接编译放到clover中就可直接实现想要的功能

徘徊彷徨 发表于 2017-6-12 15:41

路过学习,最近正在学习这个!这个对我帮助很大,谢谢楼主

wyhtc 发表于 2017-6-12 15:43

zhaiman 发表于 2017-6-12 15:37 https://www.pcbeta.com/static/image/common/back.gif
把上面楼主提到的那三个教程都认真看一遍就基本没问题的了,比去提取DSDT反编译改错修改再编译简单多了, ...

好吧。。看了下原来是笔记本用的。。

wcs15wcg 发表于 2017-6-12 16:31

用hotpatch还是太少了,而且好像都是笔记本的

micol 发表于 2017-6-12 16:49

这个必须支持

flyfeng5186 发表于 2017-6-12 16:57

学习学习。

TXLingyu 发表于 2017-6-12 17:22

帮顶,楼主辛苦了

sleepnet 发表于 2017-6-12 18:37

zhaiman 发表于 2017-6-12 15:12 https://www.pcbeta.com/static/image/common/back.gif
hotpatch 用起来挺方便的,而且大部分通用,貌似大家都不怎么喜欢用

愿意去研究的人总是会有收获的,不愿下功夫的摆在面前也没用的。

sleepnet 发表于 2017-6-12 18:45


我结合自己的2570p机型做了个简短的图文说明,有兴趣的可以看看。
内容包括:
1.本帖正文内容;
2.2017年仍在维护关于黑苹果机型的GitHub源地址;
3.2570p机型的config.plist文件以及ssdt文件简短说明,见正文附件。
4.RehabMan大神的laptop-config简要介绍。
5.RehabMan大神的elitebook/zbook/probook系列机型的github简要介绍。

还是那句话,有兴趣的看看,没有兴趣的略过就行。


witcherhope 发表于 2017-6-12 19:02

orange1206 发表于 2017-6-12 19:06

相比自己制作补丁有什么优势?

zhongbuxiao 发表于 2017-6-12 19:45

顶一个,技术贴就是要支持

hjfgt 发表于 2017-6-12 21:11

技术贴,感谢分享。

beyond5201997 发表于 2017-6-12 22:09

sleepnet 发表于 2017-6-12 18:45 https://www.pcbeta.com/static/image/common/back.gif
我结合自己的2570p机型做了个简短的图文说明,有兴趣的可以看看。
内容包括:
1.本帖正文内容;


虽然用不上!支持分享!
页: [1] 2 3 4 5 6 7
查看完整版本: [翻译]使用hotpatches修补dsdt(很多人应该看过,献丑翻译一下)