本笔记参考 RehabMan 指南 [Guide] Using Clover to “hotpatch” ACPI
Hotpatch 简述
什么是 Hotpatch?
RehabMan 的介绍是:
That guide uses what is known as “static patching”. In order to inject patched ACPI files, we extract native ACPI, disassemble them, make changes, then recompile and place the files in ACPI/patched, so that Clover injects the patched ACPI instead of native ACPI. With the techniques detailed in this guide, the changes can be made directly to the ACPI binaries provided by BIOS, skipping the extract, disassembly, and recompilation steps.
该指南使用所谓的“静态修补”。 为了注入修补的ACPI文件,我们提取本地ACPI,反汇编,进行更改,然后重新编译并将文件放在ACPI / patched中,以便Clover注入修补的ACPI而不是本机ACPI。 使用本指南中详述的技术,可以直接对BIOS提供的ACPI二进制文件进行更改,跳过提取,反汇编和重新编译步骤。(翻译来自 Google 翻译)
我的理解:
其实 Hotpatch 就是将所有修补 ACPI 文件的补丁变成一个一个模块,通过重命名主板提供的 ACPI 文件原来的 Method (方法/函数) 来禁用原有的方法,再用 SSDT 来放入我们修改后的(已修补)的 Method (方法/函数).
当然上面所说的是终极解决的办法,其实还有很多很简单的方法能够完成 ACPI 补丁的功能.
如果有兴趣可以去看看 RahabMan 帖子.
之前我在 DSDT 打的补丁有.
1 | "Fix _WAK Arg0 v2" |
Clover 常规补丁
Fix _WAK Arg0 v2
→ACPI > DSDT > FIX_WAK_200000
IRQ Fix
和HPET Fix
→ACPI > DSDT > FixHPET_0010
和ACPI > DSDT > FixIPIC_0040
RTC Fix
→ACPI > DSDT > FIX_RTC_20000
OS Check Fix(Windows 7)和 OS Check Fix(Windows 8)
HotPatch 的方式是,将调用 _OSI 的方法重命名为 XOSI. 然后再放入 SSDT-XOSI.aml 到 Clover > ACPI > Patched
1 | Comment: Change _OSI to XOSI |
意思就是,将调用 _OSI 方法的地方都改成调用 XOSI,而 XOSI 方法则是从 SSDT-XOSI.aml 引入的,我们再从 XOSI 方法修补.
Rename GFX0 to IGPU
和上面重命名方法一样
1 | Comment: Rename GFX0 to IGPU |
Brightness fix(Haswell/Broadwell)
这个补丁方法
- GFX 重命名为 IGPU,上一节补丁已经应用了.
- 放入 SSDT-PNLF.aml
- SSDT-Config.aml 需要定义 BKLT 的值为 0.
USB3_PRW 0X6D(instant wake)
这个补丁方法,的方法遇上面的不太一样.
补丁片段
1 | # some _PRW have three entries in the Package |
这样修改后,USB 总线 EHC1和 EHC2 设备中没有了 _PRW 方法了,直接变成了 _PRW 变量.
至于为何需要这样改,我并不清楚,这必须了解 USB 导致睡眠唤醒的代码原理,我看不懂.但是看补丁的修改方法还是会的.
那么将上面的补丁换成 Hotpatch 应该如何表现呢?
搜索了下, DSDT 中还有非常多的 _PRW 方法,他们遍布了整个 DSDT 的各种设备,如果还是使用简单的改名是不可靠的.
因为 Clover 的 Patches 是搜索 DSDT 的二进制版本进行修补,二进制中无法识别整个_PRW 方法是否属于 USB 设备下的,也就是是否属于 EHC1 EHC2 的设备,那么是否就没办法用 Hotpatch 方法来修补这个问题呢?
我们来看看被补丁修补的源代码是什么样的
下面是 EHC1 的 _PRW 方法
1 | Method (_PRW, 0, NotSerialized) // _PRW: Power Resources for Wake |
下面是 EHC2 的 _PRW 方法
1 | Method (_PRW, 0, NotSerialized) // _PRW: Power Resources for Wake |
下面是 XHC 的 _PRW 方法
1 | Method (_PRW, 0, NotSerialized) // _PRW: Power Resources for Wake |
我们可以发现我们补丁修改的每个 _PRW 方法都会调用一个方法 GPRW,并且调用 GPRW 方法的变量内容都是 0X6D.
再看看 RehabMan 写的 SSDT-PRW.dsl 内容
1 | // For solving instant wake by hooking GPRW or UPRW |
上面的逻辑很清晰了, 其实就是要将我们需要改的地方,直接用代码发回我们希望他得到的变量,那么我们就不必想如何识别哪些是 USB 的 _PRW 方法了.
Hotpatch 我觉得就是,复杂的逻辑交给 ASL 代码来解决, Clover 的 Patch 只需要修改源代码的调用即可.
那么上面多了个 XPRW 是什么东东?为啥其余调用 GPRW 方法都调用他呢?
这个就是 Clover 需要做的,我要将所有原来调用 GPRW 方法的都调用到这个 SSDT-PRW 来,原来的 GPRW 我们更名为 XPRW.
明白了吧?所有代码都经过上面的逻辑,最终跑回被我们更名为 XPRW 的方法(也就是原来的GPRW 方法).
故此应用这个 SSDT 之前,我们需要将 DSDT 原来的 GPRW 方法重命名为 XPRW 方法
但是由遇到了一个问题,如何定位 GPRW 方法在二进制文件 aml 中的位置呢?
小笔记: aml 是 ASL 编程语言编译后的二进制文件,但是我们一般反编译或者 Patch都是讨论十六进制,因为每8个二进制代表一个字符
RehabMan 在 [Guide] Using Clover to “hotpatch” ACPI Rename and Replace 章节有讲到这个问题
大概的意思就是因为不同主板可能情况不同,我们需要使用 Hex Fiend 这样的软件来验证 GPRW 方法的十六进制代码.
方法就是用 Hex Fiend 打开 DSDT 的 aml 文件,然后搜索 GPRW, 你会看到有很多 GPRW, 我的 GPRW 方法在 DSDT 的最下面,所以我直接拉到最下面反向搜索.
最终找到以下十六进制代码
1 | 47 50 52 57 02 GPRW |
再看看 GPRW 的十六进制代码是怎么样的?
1 | neros-MBP:test nero$ echo -n GPRW|xxd |
奇怪了,为何我在上面列举的代码多了一个 02 ?
我们看看原来 GPRW 方法源代码
1 | Method (GPRW, 2, NotSerialized) |
看到了吧,方法名称紧挨着就是2,这个2就是 02.
发现下面的方法好像并不是所有都这样,需要验证.
根据上述帖子内容,aml 编译后会留下一个位置符来定义这个前面这个字符到底是方法,还是变量,还是设备.
根据我观察所得,(不同的 ASL 版本或者不同电脑获得的位置符号未必相同)
Method 位置符号是 06 [xx xx xx xx]
Name 位置符号是 08 [xx xx xx xx]
搜索 06 47 50 52 57
一样可以定位到 GPRW 方法上,而且这个代码是唯一的,因为整个 DSDT 里面只有一个 GPRW 函数.
翻看 RM 的帖子,再验证了下,发现一个更好的规律和方法
将我们的 DSDT.dsl 文件使用如下命令编译.
1 | iasl -l DSDT.dsl |
它会产生两个文件
- DSDT.aml 编译后文件
- DSDT.lst 混合列表文件
用文字编辑软件打开 DSDT.lst, 会发现机械码和 iASL 代码混合在一齐,这个就是一个翻译文件一样,列举了各种代码的机械码模式,这样我们就可以更好的找到我们需要打补丁的代码原来是怎么样的.
例如:我们需要将 Method (TACH,1
的方法重命名为 Method(XACH,1
来使得 TACH 方法失效,再注入 SSDT 中写入 TACH 方法,来代替它.
那么我只需要搜索 Method (TACH,1 就能找到他机械码的模样.
1 | 22490: } |
那么我们补丁就可以这样写
1 | Find:14 40 06 54 41 43 48 09 |
将我们字符转换成 Hex 形式可以用如下命令
1 | neros-MBP:~ nero$ echo -n TACH |xxd |
小结
说了那么多,这个 USB3_PRW 0X6D(instant wake) 唤醒补丁的 Hotpatch 的方法就是
- 将 DSDT 的 GPRW 方法重命名为 XPRW
- 放入 RehabMan 写的 SSDT-PRW.aml 到 Clover > ACPI > patch
PS: 后来测试发现开机的时候系统日志会提示没有找到 UPRW ,这个是因为 SSDT-PRW.aml 包含了 UPRW 这个方法,而这个方法对我来说是没用的,故此放入 SSDT-PRW.aml 后如果不想出现 ACPI Error 的话,最好确认下自己的唤醒是调用 GPRW 还是 UPRW,然后将另一个方法注释掉.
SMBUS Fix
这个补丁就是在 SBUS 加入 BUS0 设备,只需要放入 SSDT-SMBUS.aml 即可.
Rename B0D3 to HDAU
先将 B0D3 重命名为 HDAU
1 | Comment: change B0D3 to HDAU, optionally pair with SSDT-HDAU.aml |
再放入 SSDT-HDAU.aml
注意修改 layout-id 的值为你声卡的 layout-id 值,我声卡的 layout-id 是4
1 | // Automatic injection of HDAU properties |
ApplePS2SmartTouchPad 驱动的 Fn 按键补丁
这个补丁需要打上 Fn 功能键才能调整亮度,我们先看看补丁都干了些什么
1 | # Patch by EMlyDinEsH (OSXLatitude) |
上面这个补丁是将 _Q0E 方法和 _Q0F 方法的内容替换如下
1 | Method (_Q0E, 0, NotSerialized) // _Qxx: EC Query |
参考章节 USB3_PRW 0X6D(instant wake) 的方法.
- 重命名 _Q0E 方法和 _Q0F 方法为 XQ0E 和 XQ0F,使原先的方法失效.
- 再放入我们自己定义的 _Q0E 方法和 _Q0F 方法.
替换 _Q0E 和 _Q0F 方法名称
命令行查找下以上两个方法的十六进制代码
1 | neros-MacBook-Pro:hotpatch nero$ echo -n _Q0E | xxd |
那么在 Clover 配置文件 ACPI > DSDT > Patches 写入如下补丁
1 | #补丁-1 |
如果觉得不放心,可以用 Hex Fiend 打开 DSDT.aml 文件来搜索替换一下,之后再用 iasl 来反编译,再用 MaciASL dsl 文件看看,是否已经被重命名为 XQ0E 和 XQ0F
重定义新的 _Q0E 和 _Q0F 方法
我不会编写 SSDT, 但是我会抄~
复制一份 SSDT-PRW.dsl 下来重命名为 SSDT-FN.dsl
用 MaciASL 打开.
将其修改为如下代码
1 | //Enables Fn brightness keys to work with my kext AsusNBFnKeys |
PS:以上代码纯属乱搞,如果能用,纯属巧合哈~
最终将此 SSDT-FN.dsl 编译成 aml, 再放入 Clover > ACPI > patches
电池补丁
方法分析
根据远景论坛的教学贴,我学会了编写自己笔记本的电池电量补丁.
以下是我 华硕 VM510LI 的电量补丁
1 | #Maintained by: Nero for: Laptop Patches |
大家都知道电量修补是一项非常复杂的修改,需要将调用到的变量高于8位的数值拆分成8位来处理.
故此修改代码量非常多,并且变量名称均需要重命名及重新赋值.
Hotpatch 因为是注入 SSDT 来实现补丁效果,故此我们需要找到补丁修改的各个变量赋值与函数调用的变量.
RM 教给大家一个办法,先将 DSDT.dsl 打上电池补丁,然后另存为 DSDT-Patch.dsl 然后使用 DiffMerge 来对比两个文件的修改代码的情况,就可以最简单的知道补丁到底修改了哪些变量.
当然读懂补丁的语法其实并不需要这样做,我们可以读一下补丁到底修改了哪些变量,做了哪些操作就可以了,这个补丁是我自己写的,所以我并不需要用 DiffMerge 来查询.
经过研究,我发现单纯用 Clover Patches 方式来修改变量是行不通的,因为例如
1 | //拆分前 |
拆分前是占用5个字节,拆分后我们需要10个字节的空间,这样打补丁的话,会导致 TAH0 下面的变量被覆盖,导致出错.
那么如此大量的变量更改,我们应当如何修改呢?
我参考了 RM 给 HP ProBook 的电量补丁以及 Hotpatch 电量修补 SSDT
SSDT:https://raw.githubusercontent.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch/master/hotpatch/SSDT-BATT.dsl
电量补丁:https://raw.githubusercontent.com/RehabMan/HP-ProBook-4x30s-DSDT-Patch/master/patches/06_Battery.txt
发现他的解决办法如下
- 新建一个 SSDT 写入 EC 方法,方法中赋予我们拆分后的电池变量.
- 在新建的 SSDT 中复制修改好的方法.
- 利用 MaciASL 编译功能来协助检查缺少的 External().
- 将原来调用电池变量的方法一一用 Clover Patches 更名(将原来的方法全部禁用).
将 EC 赋值的需要拆分的变量写入到 SSDT-BATT.dsl
我不会写 SSDT, 但是我会抄.抄 RM 写的 SSDT 再修改
下面是 EC0 设备拆分后的代码
1 | // battery status patched for Ausu VM510LI |
其中 OperationRegion (ECOR, EmbeddedControl, Zero, 0xFF)
和 OperationRegion (SMBX, EmbeddedControl, 0x18, 0x28)
原来的 DSDT 都存在,按照 RM 修改的方法,他的方式应该是从每个 Offset (0X00)
偏移量定义去写,如果偏移量下面第四个才是需要拆的,那么上面的可以使用 , 16,
这种方法来代替偏移量,好像这样就不会覆盖到原先的变量.(猜测罢了)
2017年04月30日:根据远景坛友 gujiangjiang 提醒,EC Field需要改个名字才能用,不然无效,会出现很多ACPI Error。
将上述的 ECOR 和 SMBX 重命名。
在 Clover DSDT Patches 添加如下补丁
1 | Comment:change ECOR to XCOR |
将调用了以上变量的方法复制到 SSDT-BATT.dsl
从已经打了电量补丁的 DSDT 中找出上方调用这些变量的方法所在地,不要忘记了补丁中 #fix 256 bit registers 的方法,因为电量补丁中,大于32的变量无需拆分,只需要将调动变量的代码用 WECB 方法与 RECB 方法来更改代替即可.
- Method (TACH, 1, Serialized)
- TA00
- TA01
- TA20
- TA21
- Method (_BIX, 0, NotSerialized)
- B001
- B002
- Method (BIFA, 0, NotSerialized)
- B0S0
- B0S1
- B1S0
- B1S1
- Method (SMBR, 3, Serialized)
- WECB(0x1c,256,Zero)
- WECB(0x1c,256,Zero)
- WECB(0x1c,256,Arg4)
- Store (RECB(0x1c,256), Index (Local0, 0x02))
- Method (ECSB, 7, NotSerialized)
- WECB(0x1c,256,DerefOf (Index (Arg6, One)))
- WECB(0x44,256,DerefOf (Index (Arg6, One)))
- Store (RECB(0x1c,256), Index (Local1, 0x04))
- Store (RECB(0x44,256), Index (Local1, 0x04))
- Method (SMBW, 5, Serialized)
- Store (ShiftRight(Arg4,8),DT02)
- Store (Arg4,DT01)
总共发现6个方法,我们将这6个方法一个一个从修不好电量补丁的 DSDT 中复制到 SSDT-BATT.dsl
TACH 方法
1 | Method (TACH, 1, Serialized) |
当你复制这个方法到 SSDT-BATT.dsl 时候,编译时会遇到一个错误.(这里我已经将拆分需要的 B1B2,WE1B,WECB,RE1B,RECB 等方法放入 Scope(\_SB.PCI0.LPCB.EC0)
域里面)
49, 6084, Object does not exist (ECAV)
看看 ECAV 是哪行调用的.
1 | Name (_T_0, Zero) // _T_x: Emitted by ASL Compiler |
这个是一个判断语句内嵌了一个方法的调用,初步判断 ECAV 就是一个方法,那么这个方法在哪里呢?回到我们的 DSDT.dsl
搜索 ECAV ,你会在 _SB.PCI0.LPCB.EC0 中发现 ECAV 这个方法,那么我们需要在 SSDT-BATT.dsl 中外部引入这个方法,来达到编译通过的目的.
只需要在 TACH 上方写入 External(\_SB.PCI0.LPCB.EC0.ECAV, MethodObj)
再次编译,已通过编译.
我们需要注意的是外部引入的路径与外部引入的类型.
路径在 MaciASL 中,只要你光标移动到这个方法上,程序的左下角会显示当前方法(或变量)所在的路径.
一般 Name ( ABCD , 0X10) 这类的变量引入我们使用 IntObj 类型引入.
而上述的 Method (ECAV, 0, NotSerialized) 这一类,当然是使用 MethodObj 类型引入了.
注意,复制方法过来的时候,需要注意该方法本来是在哪个域里面的,我们在 SSDT-BATT.dsl 也要将其放到哪个域里
例如:Method (_BIX, 0, NotSerialized)
这个方法是在 _SB.PCI0.BAT0 这个域里面,那么我们需要将_BIX 方法放在这个域里面
1 | External(\_SB.PCI0, DeviceObj) |
复制了之后,我们还有非常多的错误需要处理
- 135, 6085, Object not found or not accessible from scope (^^LPCB.EC0.BATP)
代码段: If (LNot (^^LPCB.EC0.BATP (Zero)))
^^LPCB.EC0.BATP 这个方法写法中存在 ^^这两个字符,意思上级的上级域里面的,类似于相对路径, LPCB.EC.BATP 方法,完整路径就是 _SB.PCI0.LPCB.EC0.BATP,因为这个方法不在我们的 SSDT 里面,故此我们需要外部引入他.在 External 的部分加入 External(\_SB.PCI0.LPCB.EC0.BATP, MethodObj)
但是上面的 ^^LPCB.EC0.BATP 这样的调用方法猜测应该是同一 SSDT 或是在 DSDT 中存在才能这样写,如果是外部引入后,我们需要将其改成绝对路径.
将 ^^LPCB.EC0.BATP
替换成 \_SB.PCI0.LPCB.EC0.BATP
.
- 140, 6084, Object does not exist (NBIX)
代码段:Return (NBIX)
这个返回值应该是一个变量,我们看看 DSDT 下他是如何定义的.
1 | Name (NBIX, Package (0x14) |
Name (NBIX, Package (0x14) 它是一个对象集,对象集引入的类型应当是 PkgObj
在头部外部引入部分加入 External(\_SB.PCI0.BAT0.NBIX, PkgObj)
剩下错误用同类的方法修补
最终复制完整个 SSDT-BATT.dsl 是这样的:
1 | // battery status patched for Ausu VM510LI |
好了,以上 SSDT 编译已经通过,那么我们进行最后一步,将上述复制过来的 Method 一一的重命名,使得原有的 Method 失效,这样我们注入的 SSDT 的新 Method 才能生效.
我们需要重命名的 Method 有
1 | - Method (TACH, 1, Serialized) |
在 config.plist 中编写补丁 ACPI > DSDT > Patches
1 | # TACH |
提示,不放心自己找的代码,可以拿个从 Ubuntu 提取未修改过的 DSDT.aml, 用 Hex Fiend 来替换下,再反编译看看,反编译后无需修改,直接搜索我们修改的变量名,看是否已经改成 X 开头.
注入显卡 ID
- 将 GFX 更名为 IGPU
- 放入 SSDT-IGPU.aml 至 Clover > ACPI > patched
屏蔽独立显卡
首先复习一下屏蔽独立显卡的方法:
引用自:屏蔽双显卡笔记本的独显
我们的目标非常简单。通常,在SSDT里,笔记本给我们提供了一个 _OFF 方法,我们可以通过调用这个方法,来切段独显的供电。最最简单的方法,就是在 相应的_INI方法里,调用_OFF方法。需要注意,这个_OFF方法,还可能会在DSDT里,或者可能会有不同的名字(如:GPOF、OPOF、_PS3,等等)。
某些_OFF方法的实现,会由于它包含了对EC(Embedded Controller)的依赖,而使得它不能在_INI方法里被调用。对于这样的情况,整个_OFF方法或者它的一部分代码,需要被移动到_REG方法里,以延迟执行(当_REG方法接收的参数Arg0 == 3 且 Arg1==1时,它会在_INI方法之后被执行)(详见ACPI规范)。对于一些情况,在_REG方法里调用_OFF的时机太迟了,从而导致要么屏蔽独显失败,要么系统五国。对于这样的情况,修改_OFF方法,移除它对于EC的依赖,将变得必要。之后,我们就可以在_INI里调用它(移除了对EC的依赖的_OFF)。同时,在_OFF里移除的代码,需要加到_REG里去。这样,虽然EC关联的代码在后(_INI后)执行(因为代码加到了_REG里,所以后执行),但却能达到更好的效果。贴子提供的例子,就是这种情况。
我是根据上面的方法来屏蔽我华硕 VM510LI 的 AMD 显卡的,很不幸的是,我的 _OFF 也包含了对 EC 的依赖,故此我在 hotpatch 当中,我并不能单纯的使用 SSDT-Disable_DGPU.aml 来禁用独立显卡.
那么该如何使用 hotpatch 方法来屏蔽我们的独立显卡呢?
帖子提供了一个例子.https://raw.githubusercontent.com/RehabMan/Lenovo-Z50/master/hotpatch/SSDT-NVDA.dsl
仔细查看例子中的代码会发现和上述屏蔽独立显卡不同的地方.
1 | External(_SB.PCI0, DeviceObj) |
看上述的代码段,他会重新定义一个设备,这个设备叫 RMD20000,然后这个设备有一个 INI 方法,里面就是调用 _OFF, 关闭显卡的系统方法.
那么,其实关闭显卡并不一定要在显卡启动的 INI 方法中运行 OFF 切断显卡电源,我估计是 PCI0 的设备是统一时间初始化的,其他设备的 INI 也一样可以将显卡电源关闭.
而我 _OFF 方法中存在一个 SGOF 的方法,这个方法里面调用了 EC0 的代码,那么需要将他去掉,故此我需要用重命名代替的方法,将原来的 SGOF 方法用重命名方法禁用掉,然后再用 SSDT 注入我们修改的 SGOF 方法, 由于 SGOF 方法中的 EC 相关的代码需要在 _REG 中执行,故此我们也需要将原有的 _REG 方法重命名禁用掉,也在 SSDT 中写入我们的 _REG 方法.
依然老方法,我不会写 SSDT, 但是我会抄.用上述的 SSDT-NVDA.dsl 来改成我们自己的 禁用显卡 SSDT.
最终写出来的 SSDT 应该就是这样
1 | // SSDT-DAMD: Disable AMD |
然后我们需要重命名的就是两个方法,一个 SGOF, 和 _REG.
在 Clover > ACPI > DSDT > Patches 添加如下
1 | # SGOF |
注入声卡 ID
这个非常简单,只需要放入 SSDT-HDEF.aml 到 Clover > ACPI > patched
但是需要注意自己的 DSDT 有没有定义 HDEF 设备,如果没有,打开 SSDT-HDEF.dsl 将以下注释去掉.
1 | // Note: If your ACPI set (DSDT+SSDTs) does not define HDEF (or AZAL) |
另外注意修改自己需要注入的 ID, 我的是4
无需修改 ID,我们只需在 SSDT-Config.aml 的 Name(AUDL, Ones) 定义我们注入的 ID 即可。(关于SSDT-Config.aml 更多的参数细节,后续会提到。
1 | Method(_SB.PCI0.HDEF._DSM, 4) |
但是不清楚为什么上面的注入不正常,我用回 Clover 的 Devices 里面的 Inject 设置为4 RestHDA 设为 yes
终于知道为何放入上面 SSDT 后声卡依然无声,是因为 SSDT-config.dsl 问题。在下面的章节补上对这个非常非常重要的 SSDT-Config.aml 的讲解
上面的 HDEF 只是给声卡出声而已,还需要放入 SSDT-HDAU.aml 以给 HDMI 出声。
最终 HDMI 声音和声卡声音都能正常出声。
SSDT-Config 说明
这个漏了说,而且这个是 Hotpatch 必用的 SSDT,因为里面包含了一些配置。
首先我们来看看 SSDT-Config 有些啥?
1 | // configuration data for other SSDTs in this pack |
上面 RM 都注释了,我以 Google 翻译过来,方便理解。
- 第一个值,TYPE 从 SSDT-IGPU 调用,影响显卡 ID 的注入。查看了下代码,好像是区分是否注入高分屏 ID 有关。
- 第二个值,HIGH 从 SSDT-IGPU 调用,影响显卡 ID 的注入。当 TYPE 设置成笔记本才生效。
- 第三个值,DPTS 从 SSDT-PTSWAK 调用,这个 SSDT 是重写了睡眠和唤醒的方法,加入了一些我们补丁需要用到的代码,这里设置 1 则会在睡眠的时候开启显卡,唤醒后关闭显卡。
- 第四个值,SHUT 从 SSDT-PTSWAK 调用,这个 SSDT 功能同上,这里设置 1 则会在关机的时候禁用 _PTS,和 Shutdown fix 同理。
- 第五个值,AUDL 从 SSDT-HDAU 和 SSDT-HDEF 调用,这两个 SSDT 前者负责注入声卡 ID,后者则负责注入 HDMI 声卡 ID,而这个值就是控制两个 SSDT 注入声卡的行为,如果写 Ones 则什么都不注入,如果写 3,则声卡的 layout-id 则为 3。
- 第六个值,BKLT 从 SSDT-PNLF 调用,这个 SSDT 看名字大家应该都很熟悉,就是加入 PNLF 设备,用来启用我们的笔记本亮度调节驱动的,而这个值是控制亮度调节的驱动是用哪一种,0 是使用 IntelBacklight.kext,1 是使用 AppleBacklight.kext + AppleBacklightInjector.kext。
- 第七个值,LMAX 从 SSDT-PNLF 调用,这个 SSDT 同上,这个值是设置背光的 PWM 最大值,Ones 是使用默认值,Ivy / Sandy 的默认值是 0x710,Haswell / Broadwell 的默认值是 0xad9,你也可以设置其他值,但是这个值必须与 framebuffer 相匹配。
变频\声卡 CC 配置\USB 遮蔽器
这些在黑苹果各大论坛都有介绍,我就不再论述,只需放入 SSDT 即可.
测试
全部修改后,到最重要一步,测试修改的 hotpatch 是否可用.
还挺幸运的,一直写下来的笔记,就 FN 因为完全无脑抄袭没有注意自己的 Q0E 和 Q0F 是在 _SB.PCI0.LPCB.EC0 设备里面,我没把他们放到这个 Scope (域) 里面,故此不生效.