https://aplus.rs/2021/hackintosh-sleep-wake/
在 AMD Hackintosh 领域,成功配置您的构建以执行睡眠/唤醒是“Holly Shit!”之一。有用!” 时刻。
尽管 Intel 和 AMD CPU 很大程度上兼容(几乎没有什么显着差异),但它们相应的芯片组却有所不同。直到最近,苹果公司还专门使用英特尔 CPU 及其芯片组(在某种程度上)。因此,如果您根据所选的 SMBIOS 值使用相同的组件,OpenCore 构建开箱即用的睡眠/唤醒功能也就不足为奇了。
与计算的许多其他方面相同:在最近的 Big Sur 版本中,我的Z490+i7-10700K+RX-5500XT 版本开始随机显示黑屏一两秒,然后恢复正常。虽然总体上无害,但它非常烦人,严重扰乱了我妻子的日常工作(她正在使用该版本)。最初我使用iMacPro1,1SMBIOS,尽管硬件构建几乎是iMac20,1. 你瞧,只需将 SMBIOS 更改为后者,所有这些黑屏问题就消失了。
我确信通过对 ACPI 进行足够多的探索,可以找到其他解决方案,但正如我们将看到的,这是一条漫长而艰苦的道路。
AMD 芯片组则不同,因为它们使用不同的设备组件及其各自的配置和固件。特别是 USB 控制器:X570 芯片组本身有 3 个 USB 控制器。再加上制造商可以为同一个该死的东西编写明显不同的 ACPI——出于某种原因,MSI 制造的主板无法启动 Monterey超过 beta 3——你可能会发现自己陷入了相当混乱的境地。
近一年来,我自己使用 AMD 5900X 在华擎 X570 ITX 主板上运行的构建已禁用睡眠。它是一款非常出色的 CPU,为您提供 12 核 / 24 线程,运行频率为 3.7GHz(4.9GHz 增强),并且包含主板的成本仅为约 750 欧元(我敢说,尝试使用英特尔指定配置)。但睡眠……睡眠只是“一座遥远的桥梁”。
即使在我映射我的 USB、添加USB 电源属性、从 SMBIOS 切换到iMacPro1,1之后MacPro7,1……不,也没有改变。机器会关闭屏幕,但永远不会真正进入睡眠状态。更糟糕的是,它会严重锁定,以至于没有任何反应。甚至电源按钮都不起作用,因此关闭它的唯一方法是拔掉墙上的电源。在对HibernationFixup和我在网上找到的一些随机 SSDT 进行了一些半途而废的尝试后,我决定深入研究并了解 ACPI 睡眠的实际工作原理。
ACPI 规范庞大且不易深入研究。首先要确定目标:我到底追求什么。在台式机中,我想实现S3睡眠状态,这意味着“挂起到RAM”。S4 是休眠或“挂起到磁盘”,这对于笔记本电脑非常有用,但对于台式机则不然。S0 是完全唤醒状态。
在阅读了电源管理部分并结合之前尝试的知识后,睡眠的关键是_PRW方法的正确实现。通过实现唤醒方法的电源资源,设备告诉操作系统它们可以进入什么睡眠状态,同时仍然保持唤醒系统的能力。它还指定设备正确唤醒所需的其他电源资源(如果有)。
查看示例总是有用的。因此,这是取自实际 MacPro DSDT 表的典型表:
Method (_PRW, 0, NotSerialized) { If (OSDW ()) { Return (Package (0x02) { 0x69, 0x03 }) } Else { Return (Package (0x02) { 0x69, 0x04 }) } }
OSDW是 Apple 用于检查活动操作系统是否为 Darwin (macOS) 的 ACPI 方法。所以我们看到这个方法的返回值是两个元素的包:第一个参数是相同的,而第二个参数适用3于 macOS,4适用于其他(Windows、Linux 等)。
ACPI 规范告诉我们此方法的包格式意味着:
Package { EventInfo // Integer DeepestSleepState // Integer }
DeepestSleepState 是一个整数,包含可进入的最深电源系统睡眠状态,同时仍提供唤醒功能。
好的,所以该设备可以在 macOS 上进入 S3 睡眠状态,在其他设备上进入 S4 睡眠状态。纵观 MacPro ACPI 中的许多其他 _PRW 实现,都存在类似的模式。
好的,现在让我们看看我的华擎 X570 主板 ACPI 的 DSDT。它有大约 20 个_PRW实现,除了一种情况外,在所有情况下,第二个参数都是0x04。这是一个:
Method (_PRW, 0, NotSerialized) // _PRW: Power Resources for Wake { Return (GPRW (0x08, 0x04)) }
根据 Apple 的实现,我们应该将第二个参数重写为0x03。如何在 OpenCore 中做到这一点?
我们采用了经验丰富的 iOS 开发人员所熟知的“swizzling”技巧:用我们自己的 API 替换现有的 API,提供自定义实现。我们需要对制造商提供的 ACPI 进行热补丁,并将现有GPRW方法重命名为其他名称,例如XPRW.
(1) 在 OpenCoreconfig.plist下添加此字典ACPI/Patch:
<dict> <key>Base</key> <string></string> <key>BaseSkip</key> <integer>0</integer> <key>Comment</key> <string>GPRW to XPRW Rename</string> <key>Count</key> <integer>0</integer> <key>Enabled</key> <true/> <key>Find</key> <data> R1BSVwI= </data> <key>Limit</key> <integer>0</integer> <key>Mask</key> <data> </data> <key>OemTableId</key> <data> </data> <key>Replace</key> <data> WFBSVwI= </data> <key>ReplaceMask</key> <data> </data> <key>Skip</key> <integer>0</integer> <key>TableLength</key> <integer>0</integer> <key>TableSignature</key> <data> </data> </dict>
因此,系统提供的 GPRW 方法现在称为 XPRW。
(2)使用 GPRW 的新实现创建自定义 SSDT表:
DefinitionBlock ("", "SSDT", 2, "ATNV", "GPRW", 0x00000000) { External (XPRW, MethodObj) // 2 Arguments Method (GPRW, 2, NotSerialized) { If (_OSI ("Darwin")) { If ((0x04 == Arg1)) { Return (XPRW (Arg0, 0x03)) } } Return (XPRW (Arg0, Arg1)) } }
如果第二个参数 ( Arg1) 是0x04,请将其替换为,同时按原样0x03传递第一个参数 ( ) 。Arg0在所有其他情况下,只需传递到原始方法实现。
我将此命名为SSDT-GPRW.aml并将其包含ACPI/Add在 config.plist 中。
那么……它有效吗?我对于是否可以 100% 确定地声称有些犹豫,但到目前为止——确实如此。键盘直接连接到 USB 端口,键盘作为蓝牙工作,均经过多次尝试。我的 USB 端口通常有外部 USB 磁盘、Glorious 和 Logitech USB 鼠标、Blue Yeti USB 麦克风以及 LG 27GN950 显示器中的供电 USB 集线器。显示器显示通过 DisplayPort 从 RX 570 GPU 进行。
Build 进入睡眠状态,并在移动鼠标或按下键盘按键时唤醒。仍然有可能出现问题,但我充满希望。手指交叉。