SSDT简要解析,以华硕Z490为例

前言

目前第六代酷睿之后的平台,安装黑苹果是非常容易的,但小众配置和笔记本机型也有一些不容易解决的问题,这类问题一般无法用引导工具或 Kext 文件解决,此时就是 SSDT 发光发热证明自己的时候了。虽然 SSDT 也不是任何问题都能够解决,但在特定条件下使用 SSDT 比 Kext 要更加灵活易用。本文接下来主要以定制华硕 Z490 SSDT 文件来进行简要的思路和方法解析。

「注意」SSDT 编写需要编程基础和 ACPI 知识,本文只做解析,不做新手式教学。

 

ACPI、DSDT 和 SSDT

  • ACPI:Advanced Configuration and Power Management Interface,一般翻译成高级配置与电源管理接口,由英特尔、惠普、微软、Phoenix 和东芝制订提出,其中最为广泛认可的就是电源管理标准。ACPI 中包含了 DSDT 和 SSDT 信息,每套个人电脑理论上都具有不同的 ACPI,有时候即使是同一厂家的同一产品,也会因为 BIOS 版本、内存大小、设置差异等,造成 ACPI 的不同,因此 ACPI 文件需要自行提取。苹果公司的 Mac 产品并不完全支持 ACPI 规范,但其中 DSDT 功能是完整支持的,对于黑苹果来说,ACPI 里会有涉及硬件兼容和驱动/睿频/休眠/显卡控制等重要功能。ACPI 文件可以在 Windows、Linux 下提取,黑苹果也可以通过 Clover 或 DPCIManager 软件提取。
  • DSDT:Secondary System Description Table,字面翻译是“差异系统描述表”,是 ACPI 规范的一部分。其包含了所有除基本系统以外所有不同设备的信息,也就是每台计算机设备的基本系统是相同的,而不相同的设备用 DSDT 来描述。
    • 初始设备制造厂家(OEM)必须提供一个 DSDT 给 ACPI 以兼容操作系统。DSDT 包含差异定义块(DefinitionBlock),它提供关于基本系统(Base System)的执行和配置信息。操作系统总是在系统启动时将 DSDT 信息插入到 ACPI 命名空间(NameSpace)并且不移除。
    • 基本上,可以把 DSDT 归结为来描述你的系统配置的。它包括所有 ACPI 支持的设备的定义并描述它们的兼容性。例如,它描述电池、交流适配器、嵌入式控制器、风扇、发热区。它以分级形式呈现这些信息,所以 ACPI(和兼容操作系统)能够了解系统硬件之间的依存关系。DSDT 在启动时加载。基本上,它告诉 ACPI 驱动要注意些什么。
    • 简单说 DSDT 就是包含了所有和基本系统(Base System)不同的设备的信息,Base System 每台机器都是一样的,这个是在 ACPI 规范里指定的,但是每台机器都是不相同的,所以不相同的设备大都是由 DSDT 表来描述。它包含了很多 AML 代码。标准的 DSDT 编译器是英特尔的 iASL,而很多 DSDT 是由微软的编译器编译出来。问题是,微软的 DSDT 编译器对源代码的标准比较宽松(比如说 iASL 的很多 Error 到微软这里就只是 Warning 了),从而导致一个不标准的、充满 BUG 的 DSDT。因此这些 DSDT 可以在 Windows 下正常工作,而到了 macOS、Linux 就不行了。
  • SSDT:System Services Descriptor Table,字面翻译是“系统服务描述符表”,是 ACPI 规范的一部分。SSDT 相当于系统内部 API(Application Programming Interface,应用程序接口)的指向标,作用就是告诉系统,需要调用的 API 在什么地方。黑苹果主要通过新增或修改 SSDT 文件进行 ACPI 的打补丁操作。
    • SSDT 是 DSDT 的延续。多个 SSDT 可以用来作为平台描述的一部分。在 DSDT 被加载到 ACPI 命名空间后,每个 RSDT/XSDT 列举的 SSDT 和它唯一的 OEM 表识别号被加载。这允许 OEM 在一个表里提供基本支持,同时添加在其他表里添加小的系统选项。
    • 注意:附加的表只能添加数据,不能覆盖之前表里的数据。一台电脑可能有多个 SSDT 表。也就是说,DSDT 可能只含有设备(Device)的基本信息,然后将详细信息放在具有唯一识别号的 SSDT 中,这也是为什么我们有时候需要让 Clover/OpenCore 加载 SSDT 实现 CPU 睿频或者让 Thunderbolt 3 接口正常工作。
  • .dsl:Disassembled ASL File,ASL 指的是 ACPI Source Language,就是没有编译的 SSDT 源文件后缀名,可以理解为源代码。
  • .aml:ACPI Machine Language Binary,这是编译好的 SSDT 文件后缀名,可以直接使用引导工具(Clover/OpenCore)加载使用。
  • MaciASL.app 是用于编辑/编译 dsl 和 aml 文件的编辑工具,这个软件仅支持 macOS,Windows 里应该也有编辑 dsl 文件的工具,可是笔者没有在 Windows 下编辑过,所以也不清楚。第六代酷睿以后的黑苹果大部分情况下可以只使用 OpenCore 提供的标准 ssdt 文件,进入系统后根据自己硬件的需要再行编辑就好了。

 

SSDT 文件解析

定义块(DefinitionBlock)

「注意」以下所有代码仅供参考不可直接编译,下同。

SSDT 所有的内容都包含在定义块中:

DefinitionBlock ("", "SSDT", 2, "Asus", "Z490", 0x00001000) 
{

    Name ( xxx ) { xxx }
    Device ( xxx ) { xxx }
    Scope (xxx) { xxx }
    Method (xxx) { xxx }

}

 

解决 OC 引导 Windows 的冲突

由于 OpenCore 采用了全局 API,因此引导其他系统时会将 Windows 不需要的 SSDT 一同加载,为解决这个问题,需要将针对 macOS 的 ssdt 添加一个判断语句,即系统是 macOS 时,SSDT 内容生效,否则无效。

If (_OSI ("Darwin")) { 

    //判断如果操作系统是macOS,生效此行为
}

如果其中的方法没有返回(Return)时,可能需要 else 部分:

If (_OSI ("Darwin")) {

    //判断如果操作系统是macOS,生效此行为

} else {

    //如果之后没有 Return,则需要 else 这个部分

}

下面以 GPRW(6D0D)「睡了即醒」补丁为例介绍了 OpenCore 下编写和修改 SSDT 的思路。

//
// In config ACPI, GPRW to XPRW
// Find:     47505257 02
// Replace:  58505257 02
//
// 需要注意的是,ACPI 里不支持非 ASCII 字符注释,这里仅做示例,不可直接用于编译
DefinitionBlock ("", "SSDT", 2, "OCLT", "GPRW", 0)
{
    External(XPRW, MethodObj) // 对 XPRW 函数的外部引用
    Method (GPRW, 2, NotSerialized)
    {
        If (_OSI ("Darwin")) // 如果当前的操作系统是 macOS,生效以下行为
        {
            If ((0x6D == Arg0)) // 如果第一个参数是 0x6D
            {
                Return (Package () // 返回 06D,0x00 函数结束
                {
                    0x6D, 
                    Zero
                })
            }

            If ((0x0D == Arg0)) // 如果第一个参数是 0x0D
            {
                Return (Package () // 返回 0x0D,0x00 函数结束
                {
                    0x0D, 
                    Zero
                })
            }
        }
        // 否则,直接返回 XPRW 函数。由于这个函数是以 Return 结束,所以 If 后面可以不带 Else。
        // 只有三种情况下会走到这一步:第一个参数不是 0x6D;第一个参数不是 0x0D;当前操作系统不是 macOS
        // XPRW 是 DSDT 中原始的 GPRW 函数重命名而来,实际上是调用了原始 DSDT 中原始的 GPRW 函数
        Return (XPRW (Arg0, Arg1))
    }
}

 

引用外部对象(Objects)

如果不在开始进行引用,会造成错误。

/* 引用其他表中的对象 */
    External (_SB_.PCI0, DeviceObj)
    External (_SB_.PCI0.HDAS, DeviceObj)
    External (_SB_.PCI0.LPCB, DeviceObj)
    External (_SB_.PCI0.LPCB.EC0_, DeviceObj)
    External (_SB_.PCI0.SBUS.BUS0, DeviceObj)
    External (_SB_.PCI0.WMI1, DeviceObj)
    External (_SB_.PR00, ProcessorObj)
    External (_SB_.WFDE, DeviceObj)
    External (_SB_.WFTE, DeviceObj)
    External (_SB_.WMTF, DeviceObj)
    External (_TZ_.FAN0, DeviceObj)
    External (_TZ_.FAN1, DeviceObj)
    External (_TZ_.FAN2, DeviceObj)
    External (_TZ_.FAN3, DeviceObj)
    External (_TZ_.FAN4, DeviceObj)
    External (_TZ_.TZ00, PkgObj)
    External (ABAW, DeviceObj)
    External (ACCE, DeviceObj)
    External (AMW0, DeviceObj)
    External (ATW0, DeviceObj)
    External (AWW0, DeviceObj)

 

移除 macOS 不需要的设备

移除 macOS 运行不使用的设备,增加稳定性。

    Name (_SB.STAS, One)
    Name (\_TZ.FAN0._STA, Zero)  // _STA: Status
    Name (\_TZ.FAN1._STA, Zero)  // _STA: Status
    Name (\_TZ.FAN2._STA, Zero)  // _STA: Status
    Name (\_TZ.FAN3._STA, Zero)  // _STA: Status
    Name (\_TZ.FAN4._STA, Zero)  // _STA: Status
    Name (_SB.PCI0.WMI1._STA, Zero)  // _STA: Status
    Name (ABAW._STA, Zero)  // _STA: Status
    Name (ACCE._STA, Zero)  // _STA: Status
    Name (AMW0._STA, Zero)  // _STA: Status
    Name (ATW0._STA, Zero)  // _STA: Status
    Name (AWW0._STA, Zero)  // _STA: Status
    Name (_SB.WFDE._STA, Zero)  // _STA: Status
    Name (_SB.WMTF._STA, Zero)  // _STA: Status
    Name (_SB.WFTE._STA, Zero)  // _STA: Status

 

HDAS 替换为 HDEF

这个其实可以不做,因为根据 AppleALC 文档说明,它可以自动处理好这个问题。以下内容删除了 HDAS 在原位置添加了 HDEF,并注入了 AppleALC 的 layout-id。

    Name (_SB.PCI0.HDAS._STA, Zero)  // _STA: Status
    Device (_SB.PCI0.HDEF)
    {
        Name (_ADR, 0x001F0003)  // _ADR: Address
        Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
        {
            If ((Arg2 == Zero))
            {
                Return (Buffer (One)
                {
                    0x03                                             // .
                })
            }

            Return (Package (0x06)
            {
                "hda-gfx", 
                Buffer (0x0A)
                {
                    "onboard-1"
                }, 

                "layout-id", 
                Buffer (0x04)
                {
                     0x07, 0x00, 0x00, 0x00                           // ....
                }, 

                "PinConfigurations", 
                Buffer (Zero){}
            })
        }
    }

 

伪造白果中的设备

以下内容添加了白苹果中存在的设备 DMA Controller。

Device (_SB.PCI0.LPCB.DMAC)
        {
            Name (_HID, EisaId ("PNP0200") /* PC-class DMA Controller */)  // _HID: Hardware ID
            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
            {
                IO (Decode16,
                    0x0000,             // Range Minimum
                    0x0000,             // Range Maximum
                    0x01,               // Alignment
                    0x20,               // Length
                    )
                IO (Decode16,
                    0x0081,             // Range Minimum
                    0x0081,             // Range Maximum
                    0x01,               // Alignment
                    0x11,               // Length
                    )
                IO (Decode16,
                    0x0093,             // Range Minimum
                    0x0093,             // Range Maximum
                    0x01,               // Alignment
                    0x0D,               // Length
                    )
                IO (Decode16,
                    0x00C0,             // Range Minimum
                    0x00C0,             // Range Maximum
                    0x01,               // Alignment
                    0x20,               // Length
                    )
                DMA (Compatibility, NotBusMaster, Transfer8_16, )
                    {4}
            })
        }

以下添加了白果中的设备 Firmware Hub Device。

Device (_SB.PCI0.LPCB.FWHD)
        {
            Name (_HID, EisaId ("INT0800") /* Intel 82802 Firmware Hub Device */)  // _HID: Hardware ID
            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
            {
                Memory32Fixed (ReadOnly,
                    0xFF000000,         // Address Base
                    0x01000000,         // Address Length
                    )
            })
        }

以下添加了白果中的设备 Intel PCH PMC。

Device (_SB.PCI0.LPCB.PMCR)
        {
            Name (_HID, EisaId ("APP9876"))  // _HID: Hardware ID
            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
            {
                Memory32Fixed (ReadWrite,
                    0xFE000000,         // Address Base
                    0x00010000,         // Address Length
                    )
            })
        }

以下添加了白果中的设备 SMBUS。

Device (_SB.PCI0.MCHC)
{
     Name (_ADR, Zero)  // _ADR: Address
}
Device (_SB.PCI0.SBUS.BUS0)
        {
            Name (_CID, "smbus")  // _CID: Compatible ID
            Name (_ADR, Zero)  // _ADR: Address
            Device (DVL0)
            {
                Name (_ADR, 0x57)  // _ADR: Address
                Name (_CID, "diagsvault")  // _CID: Compatible ID
                Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
                {
                    If ((Arg2 == Zero))
                    {
                        Return (Buffer (One)
                        {
                             0x57                                             // W
                        })
                    }

                    Return (Package (0x02)
                    {
                        "address", 
                        0x57
                    })
                }
            }
        }

 

关闭 EC0 设备

因为让 macOS 直接调用 EC0(Embeded Controller)比较危险,因此关闭原设备。

    Name (_SB.PCI0.LPCB.EC0._STA, Zero)  // _STA: Status

 

添加 EC 设备

关闭 EC0 后,添加一个 macOS 能识别和正常调用的 EC(Embeded Controller)设备。

Device (_SB.PCI0.LPCB.EC)
        {
            Name (_HID, EisaId ("PNP0C09") /* Embedded Controller Device */)  // _HID: Hardware ID
            Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
            {
                IO (Decode16,
                    0x0062,             // Range Minimum
                    0x0062,             // Range Maximum
                    0x00,               // Alignment
                    0x01,               // Length
                    )
                IO (Decode16,
                    0x0066,             // Range Minimum
                    0x0066,             // Range Maximum
                    0x00,               // Alignment
                    0x01,               // Length
                    )
            })
            Name (_GPE, 0x16)  // _GPE: General Purpose Events
        }

 

注入 USB 供电参数

这部分内容在 OpenCore 附带的 ACPI 样本 SSDT-USBX.aml 中有,注入供电参数以让 EC 设备正确工作。

Device (_SB.USBX)
        {
            Name (_ADR, Zero)  // _ADR: Address
            Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
            {
                If ((Arg2 == Zero))
                {
                    Return (Buffer (One)
                    {
                         0x03                                             // .
                    })
                }

                Return (Package (0x08)
                {
                    "kUSBSleepPowerSupply", 
                    0x13EC, 
                    "kUSBSleepPortCurrentLimit", 
                    0x0834, 
                    "kUSBWakePowerSupply", 
                    0x13EC, 
                    "kUSBWakePortCurrentLimit", 
                    0x0834
                })
            }
        }

 

添加 CPU 电源管理

添加 plugin-type 1 以开启 XCPM,使用 macOS 的 CPU 原生电源管理,这个部分在 OpenCore 附带的 ACPI 样本 SSDT-PLUG.aml 中有。

Scope (_SB.PR00)
{
    Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
    {
        If ((Arg2 == Zero))
        {
            Return (Buffer (One)
            {
                0x03                                             // .
            })
        }

        Return (Package (0x02)
        {
            "plugin-type", 
            One
        })
    }
}

如果你的 CPU 电源管理存在问题,可通过添加合并 ssdtPRGen.shCPUFriend.kext 的数据尝试解决。

 

尾声

在黑苹果进入 OpenCore 时代后,SSDT 和 DSDT 的编辑修改几乎成了黑果必修课,难的是这个东东门槛实在有点高,对小白非常不友好。好在 OpenCore 团队意识到了这个问题,并提供了大量的 ACPI 样本可供参考甚至直接使用;另外由国内几位大神维护的 OC-little 热补丁库也是宝藏。

如果你愿意深入学习了解运作原理,以下几个链接非常具有参考价值:

 

 

0. 本站所有资源解压密码均为 heipg.cn
1. 本站资源收集于网络,仅做学习和交流使用,请于下载后24小时内删除。如果你喜欢我们推荐的软件,请购买正版支持作者。
2. 如有无法下载的链接,联系:admin#heipg.cn,或到QQ群进行反馈,我们将及时进行处理。
3. 本站发布的内容若侵犯到您的权益,请联系站长删除,联系方式:admin#heipg.cn,我们将第一时间配合处理!

黑苹果星球 » SSDT简要解析,以华硕Z490为例

发表评论