eATM

ACPI电源补丁(自动翻译)

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 进入睡眠状态,并在移动鼠标或按下键盘按键时唤醒。仍然有可能出现问题,但我充满希望。手指交叉。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注