[翻译]使用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
看不懂,帮顶。。 太长,太看不懂,帮顶 hotpatch 用起来挺方便的,而且大部分通用,貌似大家都不怎么喜欢用{:9_355:} zhaiman 发表于 2017-6-12 15:12 https://www.pcbeta.com/static/image/common/back.gif
hotpatch 用起来挺方便的,而且大部分通用,貌似大家都不怎么喜欢用
主要是看不懂。。 感谢分享 wyhtc 发表于 2017-6-12 15:21 https://www.pcbeta.com/static/image/common/back.gif
主要是看不懂。。
把上面楼主提到的那三个教程都认真看一遍就基本没问题的了,比去提取DSDT反编译改错修改再编译简单多了,找到合适的hotpatch直接编译放到clover中就可直接实现想要的功能 路过学习,最近正在学习这个!这个对我帮助很大,谢谢楼主 zhaiman 发表于 2017-6-12 15:37 https://www.pcbeta.com/static/image/common/back.gif
把上面楼主提到的那三个教程都认真看一遍就基本没问题的了,比去提取DSDT反编译改错修改再编译简单多了, ...
好吧。。看了下原来是笔记本用的。。 用hotpatch还是太少了,而且好像都是笔记本的 这个必须支持 学习学习。 帮顶,楼主辛苦了 zhaiman 发表于 2017-6-12 15:12 https://www.pcbeta.com/static/image/common/back.gif
hotpatch 用起来挺方便的,而且大部分通用,貌似大家都不怎么喜欢用
愿意去研究的人总是会有收获的,不愿下功夫的摆在面前也没用的。
我结合自己的2570p机型做了个简短的图文说明,有兴趣的可以看看。
内容包括:
1.本帖正文内容;
2.2017年仍在维护关于黑苹果机型的GitHub源地址;
3.2570p机型的config.plist文件以及ssdt文件简短说明,见正文附件。
4.RehabMan大神的laptop-config简要介绍。
5.RehabMan大神的elitebook/zbook/probook系列机型的github简要介绍。
还是那句话,有兴趣的看看,没有兴趣的略过就行。
相比自己制作补丁有什么优势? 顶一个,技术贴就是要支持 技术贴,感谢分享。 sleepnet 发表于 2017-6-12 18:45 https://www.pcbeta.com/static/image/common/back.gif
我结合自己的2570p机型做了个简短的图文说明,有兴趣的可以看看。
内容包括:
1.本帖正文内容;
虽然用不上!支持分享!