从 Clover 到 OpenCore —— Clover 迁移 OpenCore 指南

从 Clover 到 OpenCore —— Clover 迁移 OpenCore 指南

黑苹果约 8.7 千字

随着 OpenCore 日渐成熟、acidanthera 团队宣布放弃旗下绝大部分内核驱动(包括 Lilu、VirtualSMC、WhateverGreen、AppleALC 等)对 Clover 的兼容性支持,与其届时被迫更换,不如主动从 Clover 迁移 OpenCore。

当然面对迁移,有的人会选择直接抛弃之前 Clover 的全部成果,直接从零开始配置 OpenCore。但是我相信对于大部分人来说更希望通过简简单单的修补,在现有的 EFI 的基础上迁移到 OpenCore,因此我开始撰写这篇文章。

然而不幸的是从 Clover 切换到 OpenCore 并不是一个简单的任务,因此这种迁移应该是渐进式的,不可能一蹴而就。那什么是「渐进式」呢?意思就是,如果你按照本文的步骤一步一步按顺序进行,那么大部分迁移步骤产生的修改,在 Clover 下一样可用,你不需要一下子就扔掉 Clover。

序言以外应该写在最前面的话

  1. OpenCore 丢掉了不少 Clover 的历史包袱。毫无疑问依然有不少 Clover 设置在 OpenCore 是没有可以直接替代的。因此 Clover 完全照搬到 OpenCore 是肯定行不通的。
  2. 在迁移到 OpenCore 之前,Clover 的大部分设置都要精简:用 SSDT 代替、改为注入设备属性(Device Properties)。这篇教程就是在教你这些。
  3. 如果你一开始在组织 Clover 的 EFI 时就有洁癖的话,你会发现迁移到 OpenCore 出人意料地简单。
  4. 只有完美的 Clover 的 EFI,在按照本文档的步骤精简后能获得完美的 OpenCore 的 EFI。如果你的 EFI 是不完美的,那么迁移到 OpenCore 也一定是不完美的。因此,如果你是为了解决不完美、才想迁移到 OpenCore,那么我建议先在 Clover 下完善。
  5. 独木难成林。这篇教程初次发布以后,Bat.bat 等许多大佬在 远景论坛、Telegram 上提供了许多意见,正是在他们的帮助下,这篇教程得以不断完善。

更新日志

  • 2020-06-01:更新关于 OpenCore 0.5.8 和 OpenCore 0.5.9 的内容。
  • 2020-04-21:补充关于 macOS、Windows 的时钟设备的说明;补充了可以被删除的 XCPM KextsToPatch 列表。
  • 2020-04-13:在 SSDT 修改教程中为 SSDT 样例代码补充了注释,便于新手理解。

修改 SSDT / DSDT 以兼容 OpenCore

OpenCore 和 Clover 最大的不同之一是,acidanthera 决定在 OpenCore 中设置的 SMBIOS 机型信息、DSDT 和 SSDT,都将一视同仁地对所有操作系统生效。这样做的目的是让黑苹果更像白苹果,但是却有可能导致在 macOS 上正常可用的 ACPI 表到了 Windows 上反而会出问题。

因此,我个人推荐迁移到 OpenCore 从修改现有的 SSDT 和 DSDT 开始。虽然修改 SSDT、DSDT 并不简单,但是却是每一个黑苹果玩家必须掌握的知识。而且在 OpenCore 下能用的 SSDT、DSDT 在 Clover 下一定也是可用的,所以当你完成对 SSDT、DSDT 的修改后,你可以继续使用 Clover 而不受影响。

这里主要介绍对 ACPI 中 Method 函数的修改方法。以 GPRW(6D0D)「睡了即醒」补丁为例,在 Clover 上我们的补丁一般长这样:

//
// In config ACPI, GPRW to XPRW
// Find:     47505257 02
// Replace:  58505257 02
//
DefinitionBlock ("", "SSDT", 2, "SUKA", "GPRW", 0)
{
    External(XPRW, MethodObj)
    Method (GPRW, 2, NotSerialized)
    {
        If ((0x6D == Arg0))
        {
            Return (Package ()
            {
                0x6D, 
                Zero
            })
        }

        If ((0x0D == Arg0))
        {
            Return (Package ()
            {
                0x0D, 
                Zero
            })
        }
        Return (XPRW (Arg0, Arg1))
    }
}

这个 SSDT 的原理是,通过 DSDT 重命名将原始的 GPRW,2 函数重命名为 XPRW,2 ,然后通过 SSDT 新增一个 GPRW 函数;ACPI 调用 GPRW 函数时其实是调用的 SSDT 里添加的 GPRW 函数。

在 Clover 下,所有 ACPI 相关设置(SSDT、DSDT 以及 DSDT 重命名)只会对 macOS 生效;但是现在,OpenCore 一视同仁,所有 SSDT、DSDT 重命名会对包括 Windows 在内的所有操作系统生效,那么现有 SSDT 中的 GPRW 函数也会在 Windows 生效,可能就会导致未知的后果。所以,我们需要通过 OSI 操作系统判断函数,确保 SSDT 中的 GPRW 函数的行为只对 macOS 操作系统生效:

//
// 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))
    }
}

上面以 GPRW(6D0D)「睡了即醒」补丁为例介绍了 OpenCore 下编写 SSDT 的相关思路,接下来我们以亮度快捷键补丁为例,讲解如何逐步修改 Clover 下可用的 SSDT、使其兼容 OpenCore。

大部分亮度快捷键都是通过 EC Query 触发的,因此在 Clover 中我们的亮度快捷键 SSDT 可能是这样的:

// In config ACPI, _Q14 renamed XQ14
// Find:     5F 51 31 34
// Replace:  58 51 31 34

// In config ACPI, _Q15 renamed XQ15
// Find:     5F 51 31 35
// Replace:  58 51 31 35

DefinitionBlock("", "SSDT", 2, "SUKA", "BrightFN", 0)
{
    External(_SB.PCI0.LPCB.KBD, DeviceObj)
    External(_SB.PCI0.LPCB.EC, DeviceObj)
    
    Scope (_SB.PCI0.LPCB.EC)
    {
        Method (_Q14, 0, NotSerialized)//up
        {
            Notify(\_SB.PCI0.LPCB.KBD, 0x0406)
        }
    
        Method (_Q15, 0, NotSerialized)//down
        {
            Notify(\_SB.PCI0.LPCB.KBD, 0x0405)
        }
    }
}

亮度快捷键补丁的具体工作原理,请参看我的另一篇文章「黑苹果自定义键盘 Fn 快捷键」。

根据同样的思路,我们先在 Method 定义中添加 OSI 函数判断操作系统:

DefinitionBlock("", "SSDT", 2, "SUKA", "BrightFN", 0)
{
    External(_SB.PCI0.LPCB.KBD, DeviceObj)
    External(_SB.PCI0.LPCB.EC, DeviceObj)
    
    Scope (_SB.PCI0.LPCB.EC)
    {
        Method (_Q14, 0, NotSerialized)//up
        {
+            If (_OSI ("Darwin"))
+            {
                  Notify(\_SB.PCI0.LPCB.KBD, 0x0406)
+            }
        }
    
        Method (_Q15, 0, NotSerialized)//down
        {
+            If (_OSI ("Darwin"))
+            {
                  Notify(\_SB.PCI0.LPCB.KBD, 0x0405)
+            }
        }
    }
}

由于这里的函数不是以 Return 结束的,所以我们要为 If 加上 Else

DefinitionBlock("", "SSDT", 2, "SUKA", "BrightFN", 0)
{
    External(_SB.PCI0.LPCB.KBD, DeviceObj)
    External(_SB.PCI0.LPCB.EC, DeviceObj)

    Scope (_SB.PCI0.LPCB.EC)
    {
        Method (_Q14, 0, NotSerialized)//up
        {
+            If (_OSI ("Darwin"))
+            {
                  Notify(\_SB.PCI0.LPCB.KBD, 0x0406)
+            } Else {
+
+            }
        }
    
        Method (_Q15, 0, NotSerialized)//down
        {
+            If (_OSI ("Darwin"))
+            {
                  Notify(\_SB.PCI0.LPCB.KBD, 0x0405)
+            } Else {
+
+            }
        }
    }
}

Else 区域中,调用原始 DSDT 中原始的 _Q14_Q15 函数、也就是现在已经被重命名为 XQ14XQ15 的函数。当然,别忘了在文件头部添加对 XQ14XQ15 的函数的外部引用(函数的外部引用类型为 MethodObj):

DefinitionBlock("", "SSDT", 2, "SUKA", "BrightFN", 0)
{
    External(_SB.PCI0.LPCB.KBD, DeviceObj)
    External(_SB.PCI0.LPCB.EC, DeviceObj)
+    External(_SB.PCI0.LPCB.EC.XQ14, MethodObj)
+    External(_SB.PCI0.LPCB.EC.XQ15, MethodObj)
    
    Scope (_SB.PCI0.LPCB.EC)
    {
        Method (_Q14, 0, NotSerialized)//up
        {
+            If (_OSI ("Darwin"))
+            {
                  Notify(\_SB.PCI0.LPCB.KBD, 0x0406)
+            } Else {
+                  \_SB.PCI0.LPCB.EC.XQ14()
+            }
        }
    
        Method (_Q15, 0, NotSerialized)//down
        {
+            If (_OSI ("Darwin"))
+            {
                  Notify(\_SB.PCI0.LPCB.KBD, 0x0405)
+            } Else {
+                  \_SB.PCI0.LPCB.EC.XQ15()
+            }
        }
    }
}

这样就大功告成了。

是不是有些头昏脑涨?实际上,和 Clover 现成的 SSDT 补丁库一样,OpenCore 也有现成的 SSDT 补丁库 OC-little,由资深黑苹果爱好者们维护。我也在其中贡献了一些补丁(如 PTWSAK 关机变重启修复)。 你在 Clover 中使用的 SSDT 补丁,大部分都有对应的 OpenCore 下可用的 SSDT 替代,免去了你手动修改的痛苦。而且,你还可能通过 OC-little 库里的其他补丁修复了一些你之前没有解决的问题。

当然,对于一些 OC-little 中没有等价替代的补丁,你仍然需要手动修改、添加操作系统判断;对于直接修补的 DSDT,你也只能自己在 Method 中添加对应的判断。

如果你完成了对 SSDT、DSDT 的修改,现在备份你的 EFI、然后修改后的 SSDT、DSDT 放到 EFI/Clover/ACPI/patched 之中,然后以 -v 重启,看看能不能正常开机。如果可以正常开机,登录以后打开终端执行以下命令、查看日志中是否包括 ACPI Error

$ log show --last boot | grep -Ei "ACPI"

如果正常开机,日志中没有 ACPI Error,那么恭喜你,你已经迈出了向 OpenCore 迁移的第一步。此时你依然可以继续使用 Clover,你的黑苹果没有受到任何影响。

减少不必要的 DSDT 重命名

acidanthera 团队认为,不恰当的 DSDT 重命名可能会对设备硬件造成伤害;而且,OpenCore 下的 DSDT 重命名会对包括 Windows 在内的所有操作系统生效。
因此,迁移到 OpenCore 时很重要的一步是减少不必要的 DSDT 重命名:既降低伤害硬件的概率、又尽可能避免 Windows 等其它操作系统受到影响。

以下是一些不再需要的 DSDT 重命名,可以参考这个表进行精简、使用 SSDT 代替:

  • EHC1 to EH01EHC2 to EH02 :六代(Skylake)及以上的机器已经没有 EHC 控制器了,建议用 OpenCore 官方的 SSDT-EHCx_OFF 关闭 EHC 控制器、并把重命名删除。六代以下机器保留该重命名。
  • SAT0 to SATASAT1 to SATA :实质上完全没用。
  • HECI to IMEIHEC1 to IMEIMEI to IMEIIDER to MEIDWhateverGreen 能够处理这个问题。
  • GFX0 to IGPUPEG0 to GFX0PEGP to GFX0SL01 to PEGP:WhateverGreen 能够处理这个问题。除非你没有使用 WhateverGreen,否则没必要保留这些重命名。
  • EC0 to ECH_EC to ECECDV to ECPGEC to EC :虽然 macOS 的 USB 电源管理需要名称为 EC 的控制器,但是你完全可以使用 OC-little 中的「仿冒 EC」补丁。随意重命名 EC 控制器可能会对硬件造成伤害!
  • HDAS to HDEFCAVS to HDEFAZAL to HDEFAppleALC 能够处理这个问题。除非你在用 VoodooHDA 万能声卡驱动,否则没必要保留这些重命名。
  • STAS to Noop :建议由 OC-little 中的 SSDT-AWAC 相关补丁替代。

虽然新的时钟设备 AWAC 逐渐普及,但是 macOS 尚不支持 AWAC,因此在 macOS 下需要使用传统的 RTC。
在 DSDT 中有一个 STAS 变量使 AWAC 和 RTC 互锁、避免两个时钟设备同时启用。
由于部分机器无法在 BIOS 中禁用 AWAC 启用 RTC,传统的解决方法是将 STAS 重命名为 Noop,从而同时启用两个时钟设备,而在 macOS 下只有一个 RTC 能正常工作。
但是如果这一重命名在 Windows 下也生效,意味着在 Windows 下将会暴露两个时间设备,这无疑对系统有害。同时,这也严重违反 ACPI 规范。
因此,在 OpenCore 下应该通过 SSDT-AWAC 修改 STAS 变量的值,实现在 macOS 下禁用 AWAC、启用 RTC。
感谢 Bat.bat 大佬指出。

  • PXSX to ANS1PXSX to ANS2 :建议用 NVMeFix.kext 修复 NVMe SSD 的电源管理。
  • LPC0 to LPCB :如果你要添加 SMBUS 支持,OC-little 中分别有 SBUS 的 SSDT 注入补丁和 MCHC 设备补丁。

顺便提醒一下,使用 OC-little 的补丁的时候,需要注意设备的原始 DSDT 中的 LPC 总线名称,并且必要时要自己修改 SSDT 以使 LPC 总线名称匹配。

  • PC00 to PCIOFPU to MATHTMR to TIMRGBE1 to ETH0PIC to IPIC :这些重命名实质上也是完全没用的。
  • _OSI to XOSIOSID to XSID :除非你的某些硬件设备只能在 Windows 下工作(比如 I2C 触摸板只能在 Windows 下使用,再比如 ThinkPad 对 FreeBSD 的特殊优化),否则完全没有必要使用 SSDT-XOSI 补丁来伪装操作系统。而且大部分情况下,直接定制 SSDT 也可以解除某些硬件的操作系统限制。

关于「定制 SSDT 以解除限制」,一种方法是通过「预置变量法」(详见 OC-little 的「总述」章节)禁用原始设备的函数如 _STA,另一种方法是通过延长 Find 和 Replace 的上下文实现对相关 _STA 的函数的精确重命名,然后通过 SSDT 添加新的 _STA 函数。
感谢 Bat.bat 大佬补充说明。

  • _DSM to XDSM :首先遍历一下你的 SSDT 补丁中没有依赖 _DSM 的,如果没有,这个重命名也应该删除,因为这个重命名涉及的范围实在太大了、太过于危险。

我的建议是,尽可能只添加和 Method 名称有关的重命名(如 GPRW to XPRW_Q14 to XQ14),而且随后要通过 SSDT 确保在非 macOS 操作系统下要调用并返回原始函数,确保在非 macOS 操作系统下的原始 DSDT 行为不会被改变。如果万不得已要添加其它重命名(如通过重命名禁用某些设备),那么就要权衡这一重命名的后果。

如果你完成了精简 DSDT 重命名并保存了 config,接下来的操作还是一样的,备份原始 EFI、然后以 -v 重启,看看能不能正常开机。如果可以正常开机,登录以后打开终端执行以下命令、查看日志中是否包括 ACPI Error

$ log show --last boot | grep -Ei "ACPI"

上述修改和 Clover 依然是兼容的,完成精简 DSDT 重命名后依然可以继续使用 Clover。

摆脱对 Clover ACPI Quirks 的依赖

Clover 的 ACPI Quirks 的确是非常方便。一个开关,关机变重启就修复了;三个开关,声卡 HPET、IRQ、TIMR 就修复了;等等等等。但是在 OpenCore 是没有内置这些 ACPI 修复的,所以在 Clover 下的 ACPI Quirk 现在都必须用 SSDT 实现。所幸的是,我们依然可以从 OC-little 里找到绝大部分我们需要的补丁。

  • FixIPIC:使用 OC-little 的「声卡 IRQ 补丁」章节中的 SSDT-IPIC
  • FixSBUS:参考 OC-little 的「注入设备」章节中的「SBUS_SMBU 补丁」
  • FixShutdown:参考 OC-little 的「PTSWAK 综合补丁章节」,需要添加其中的 EXT1 插件补丁(该补丁由我贡献)
  • FixDisplay:使用 WhateverGreen 和在缓冲帧补丁中定制显示接口解决
  • AddMCHC:使用 OC-little 的「添加缺失的设备」章节中的 SSDT-MCHC
  • FixHDA:该修复已包含在 AppleALC 中,使用 AppleALC 即可。
  • FixHPET、FixRTC 和 FixTIMR:使用 OC-little 的「声卡 IRQ 补丁」章节中的 SSDT-HPET_RTC_TIMR-fix

注意根据原始 DSDT 查看 _STA 内变量是 HPAE 还是 HPTE,并自行修改 SSDT。

  • FixSATA:这个先不管它,OpenCore 中有对应的 ExternalDiskIcons 的 Quirk,也可以使用 innie.kext 解决
  • AddPNLF:参考 OC-little 的「注入设备」章节中的「PNLF 注入方法」
  • AddIMEI:使用 WhateverGreen 即可
  • FixIntelGfx:使用 WhateverGreen 即可
  • AddHDMI:使用 WhateverGreen 即可
  • FixADP1:有两种修复方法
    • 直接 DSDT 重命名 AC0_ to ADP1,根据原始 DSDT 中对 AC0_ 设备的定义,可能还需要用 SSDT 为 ADP1 设备注入 Name (_PRW, Package (0x02) {0x1C,0x03})
    • 使用 SSDT 的方法,禁用原始 AC0_ 设备,并新增 ADP1 设备。根据原始 DSDT,可能还要为新增的 ADP1 设备添加 Name (_PRW, Package (0x02) {0x1C,0x03})
DefinitionBlock ("", "SSDT", 2, "SUKA", "FixADP1", 0x00001000)
{
    External (_SB_.ADP1, DeviceObj)
    External (_SB_.AC0_, DeviceObj)

    If (_OSI ("Darwin"))
    {
        Scope (\_SB)
        {
            Scope (AC0_)
            {
                Method (_STA, 0, NotSerialized)
                {
                    Return (Zero)
                }
            }

            Device (ADP1)
            {
                Name (_ADR, Zero)
                Name (_PRW, Package (0x02) {
                    0x1C,
                    0x03
                })
                Method (_STA, 0, NotSerialized)
                {
                    Return (0x0F)
                }
            }
        }
    }
}

除了这些开关以外,Clover 还有一些其它的 ACPI 设定,也有与之对应的替代。

  • DisableASPM:没有很好的代替方法,可以在设备属性(Device Properties)中分别添加相关设备的 PCI 总线位置、并注入属性 pci-aspm-default | DATA | <00>
  • PluginType:参考 OC-little 的「注入 X86」章节添加 SSDT-PLUG 补丁。
  • Generate P States 和 Generate C States:这些是六代以前 CPU 才需要的设置,可以用 ssdtPRGen.sh 生成对应的 SSDT。
  • 降压和超频功能:Clover 的实现相当简陋,即使 Clover 官方也不建议使用;降压推荐使用 VoltageShift

完成上述配置项的精简后,还是以 -v 重启,正常开机后在终端查看日志中是否包括 ACPI Error

$ log show --last boot | grep -Ei "ACPI"

当你把所有 Clover 的开关都用 SSDT 代替以后,你离迁移到 OpenCore 就越来越近了。

更新设备属性

注入设备属性以驱动 Intel 核显

如果你还在用 Clover 的 InjectIntel 的方式来驱动 Intel 核显的话,是时候更换到通过设备属性(Device Properties)中注入缓冲帧补丁、搭配WhateverGreen 的方式了。

建议参考以下文章:

新的声卡 layout-id 注入方式

大部分 AppleALC 驱动声卡的教程都已经推荐 Clover 中将此处留空、直接在设备属性(Device Properties)中注入 layout-id 了,不过我还是再冗笔一下。

下载 acidanthera 开发的工具 gfxutils,使用下述命令找出声卡的 PCI 总线位置:

$ path/to/gfxutils -f HDEF
$ path/to/gfxutils -f HDAS
$ path/to/gfxutils -f HDAU

然后在设备属性中添加声卡的 PCI 总线位置、注入 layout-id 属性。

Clover 中还有两个声卡相关的 Quirk,但是在 OpenCore 中并没有等效替代的配置:

  • AFGLowPowerState,需要手动在设备属性中为声卡设备注入 AFGLowPowerState 属性,类型和值为 DATA | <01000000>
  • ResetHDA,推荐安装 JackFix 以及配套的守护进程,除了支持 ResetHDA、还支持 3.5mm 耳机接口的类型切换。

开始迁移到 OpenCore

终于,所有的准备工作都完成了!你可以抽出一天(最好占卜一下是否是吉日),沐浴更衣,然后开始将你的 EFI 迁移 OpenCore。

下载 OpenCore 所需文件

  • OpenCorePkg - OpenCore 本体、一些 SSDT 补丁、目录结构
  • AppleSupportPkg - 包括三个 EFI 驱动,ApfsDriverLoader、VBoxHfs、AudioDxe

从 OpenCore 0.5.8 开始,ApfsDriverLoader 已经合并为 OpenCore 的一部分;VBoxHfs 和 AudioDxe 已和 OpenCorePkg 打包在一起。因此已经无需再额外下载 AppleSupportPkg(同时该项目已经存档),只需下载一个 OpenCorePkg 即可。

  • OcBinaryData - 包含两个闭源驱动 HfsPlus.efiExFatDxe.efi,以及 OpenCore 官方主题的图标文件。
    • 非常推荐安装 OpenCore 官方做的主题,和真 Mac 的 BootPicker 一模一样(除了没有网络图标)。不过那可能是另一篇文章的内容了。

决定你使用的配置文件编辑器

  • ProperTree:一个 Python 编写的 plist 编辑器,专门优化了 OpenCore 和 Clover 配置文件编写。
    • 据说在处理大整数方面存在问题,但我在 GitHub Issue 中并没有看到。如果有人遇到了建议前往 GitHub Issue 提交反馈。
  • Xcode:非常不推荐,Xcode 11 不仅花里胡哨、而且处理 plist data 和大整数方面存在问题。
    • 简单来说,Apple 没有再开放旧版的 Xcode 10 下载、而且 Apple 的 CDN 还有防盗链。因此如果我要写一篇从 Apple 官方下载 Xcode 10 的教程,那么会比你现在看的这篇的「从 Clover 到 OpenCore」要长得多。
    • 如果你和我一样成功下载了 Xcode 10 或者就没有升级到 Xcode 11:我刚才什么都没写,你什么都没看见。
  • OpenCore Configurator:Clover Configurator 开发者的新作品。很适合新手使用。
    • OpenCore 的配置文件变更非常频繁,因此只应该用 最新版的 OpenCore Configurator 搭配 最新的正式版的 OpenCore,否则配置文件格式错误将会导致无法引导。
    • OpenCore Configurator 有不少低级 Bug(不过之后更新时都修复了),比如之前有一个版本,在应对 VoodooPS2ControllerVooooI2C 这种嵌套 kext 时,会只添加内部 kext 的 dsYM 签名文件、却不添加内部 kext 本体。
    • 反正就是,使用后果自负。

组织 OpenCore 的目录

解压前一步下载的 OpenCorePkg,将其中的 EFI 目录 复制到别处

直到配置好以后,再将这个目录合并进 硬盘/U 盘 上的 EFI 分区。

Docs 目录下的 Sample.list 复制到 EFI/OC 目录下、并重命名为 config.plist

SampleFull.plist 相比 Sample.plist除 SMBIOS 机型设置部分更加完整以外,没有其它差别。除非你在模拟 2011 年以前的 Mac 机型,否则请不要使用 SampleFull.plist
如果你下载的是 OpenCore 0.5.7 版本,还需要额外将 Reources 目录复制到 EFI/OC 目录之中。这是由于 OpenCore 编译脚本错误导致的,OpenCore 0.5.8 已经修复了这一问题。

解压下载的 AppleSupportPkg,将其中的 Drivers 目录和 Tools 目录中的文件复制到 EFI/OC/Drivers 目录和 EFI/OC/Tools 目录中。

如上文所述,AppleSupportPks 已经存档,其中的 UEFI 驱动和 UEFI Tools 已经全部合并进 OpenCorePkg。从 OpenCorePkg 中解压得到的 EFI 目录已经包含了全部的驱动。

解压下载的 OcBinaryData,将其中 Drivers 目录复制到 EFI/OC/Drivers 目录中。

删除不需要的文件

根据你的实际情况(机型、Intel CPU 世代、安装的 macOS 版本),选择性的删除 Drivers 目录中的这些文件:

  • ExFatDxe.efiExFatDxeLegacy.efi:除非你的 EFI 分区或者某个系统分区是 ExFAT 分区格式的,否则不需要保留。在四代以前机型上应该用 ExFatDxeLegacy.efi 而不是 ExFatDxe.efi
  • HfsPlus.efiHfsPlusLegacy.efiVBoxHfs.efi:三者只要留其中一个即可。一般推荐用 HfsPlus.efi,比 VBoxHfs.efi 速度快三倍。在四代以前机型上应该用 HfsPlusLegcay.efi 而不是 HfsPlus.efi
  • OpenUsbKbDxe.efi(原名为 AppleUsbKbDxe.efi):为三代以前主板在引导时的键盘驱动,现代的机器应该直接使用 OpenCore 中的 KeySupport 这个 Quirk。在 三代以后的机器上使用这一驱动会破坏硬件!
  • NvmExpressDxe.efi:供四代以前主板在引导时的 NVMe 硬盘驱动,现代的机器已经不需要了。
  • XhciDxe.efi:为二代以前主板提供 XHCI 支持的,现代的机器已经不需要了。
  • HiiDatabase.efi:为四代以前主板提供 UEFI 界面字体渲染支持的,现代的机器已经不需要了。
  • ExFatDxe.efi:除非你有某些系统安装在 ExFAT 分区中、或者你的 EFI 分区时 ExFAT 格式的,否则可以删除。
  • EnhancedFatDxe.efi:除非你的 EFI 分区格式为 FAT16、而且在开机过程中可能会往 EFI 分区写入文件(如引导日志、截图等),否则可以删除。
  • Ps2KeyboardDxe.efiPs2MouseDxe.efiUsbMouseDxe.efi:为三代以前机型准备的 PS/2 键盘鼠标、USB 鼠标的驱动。
  • PartitionDxe.efi:这是一个用于加载旧版 macOS(早于 macOS 10.9)分区映像文件(DMG)的驱动。在四代以前机型上应该用 PartitionDxeLegacy 而不是 PartitionDxe

删除 Tools 目录中的这些文件:

  • BootKicker.efi:调用 Mac 内置的引导界面(即 BootPicker),是用于在白苹果上使用 OpenCore 时、通过 OpenCore 引导苹果官方引导菜单的。黑苹果无法使用苹果的引导菜单,可以直接删除。

删除上述不需要的文件以后,你的 OpenCore EFI 目录的结构应该是这样的:

EFI
├── BOOT
│   └── BOOTx64.efi
└── OC
    ├── ACPI
    ├── config.plist
    ├── Drivers
    │   ├── ApfsDriverLoader.efi // OpenCore 0.5.8 不再包含这一文件
    │   ├── AudioDxe.efi
    │   ├── HfsPlus.efi
    │   ├── OpenCanopy.efi
    │   └── OpenRuntime.efi
    ├── Kexts
    ├── OpenCore.efi
    ├── Resources
    └── Tools
        ├── ChipTune.efi
        ├── ......
        └── VerifyMsrE2.efi

现在,你可以把你在之前步骤中修改过的 SSDT、DSDT 从 Clover/ACPI/Patched 中复制到 EFI/OC/ACPI 目录中;将 Kext 从 Clover/Kexts/*/ 中复制到 EFI/OC/Kexts 目录中。

配置 OpenCore

由于已经有许多 OpenCore 配置的教程了,因此这里我就不再赘述。这里推荐几个写的不错的教程和足够有用的参考资料。

  • OpenCore 参考手册。当你解压下载的 OpenCorePkg 时,Docs/Configuration.pdf 文件就是 OpenCore 的官方文档。这是 最权威的 OpenCore 参考资料没有之一
  • OpenCore 简体中文参考手册。OpenCore 参考手册的非官方简体中文翻译。这份翻译目前由我和一些黑苹果爱好者们共同在维护。

上面两份资料适合你在配置时不知道某个选项的 具体作用和副作用 时作为参考,但是新手不适合直接对照它们配置 config.plist
如果想要快速上手 OpenCore 配置,应该参考下面的教程:

Clover 中的部分配置,如 DSDT 重命名,由于之前已经经过精简,因此可以直接将 Find 和 Replace 逐对复制到 OpenCore 的配置文件中。

需要注意的是,Clover 的 DSDT 重命名中提供了 TgtBridge,但是这一实现充满 Bug,连 Clover 官方都不推荐使用。OpenCore 为 DSDT 属性添加了 CountLimitMask 等属性以实现精确重命名。如果你在 Clover 中部分 DSDT 重命名依赖 TgtBridge、建议舍弃或使用其它方法代替。

Clover 配置项在 OpenCore 中的等效配置

现在你开始跟着我推荐的教程和参考资料开始配置 OpenCore 了。本文接下来的内容包括 Clover 中的一些选项在 OpenCore 的对应等效配置,在配置 OpenCore 时别忘了跟着看看。

ACPI 相关设置

  • HaltEnabler:在 OpenCore 中有一个等效的 Quirk ACPI -> Quirks -> FadtEnableReset -> YES

Boot 相关设置

  • 引导参数:OpenCore 中 NVRAM -> Add -> 7C436110-AB2A-4BBB-A880-FE41995C9F82 -> boot-args
  • NeverHibernate:Misc -> Boot -> HibernateMode -> None
    • 其实不再建议禁用休眠,由于 OpenCore 的行为和白苹果更加接近,已经可以实现 macOS 的完美休眠。
  • Default Boot Volume:OpenCore 中 Misc - Security - AllowSetDefaults - true
    • 然后在 OpenCore 的引导菜单处使用 Ctrl + Enter 按键进行选择
    • 你也可以直接使用 macOS「系统偏好设置」中的「启动磁盘」设置
    • OpenCore 不支持 Clover 的 LastBootedVolume
  • DefaultBackgroundColor:需要注入到 NVRAM 中
    • NVRAM -> Add -> 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14-> DefaultBackgroundColor ,需要自行将 RGB 转换为 HEX 然后填入。
  • EFILoginHiDPI:需要注入到 NVRAM 中
    • NVRAM -> Add -> 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14 -> EFILoginHiDPI | Data | <>
    • Clover: 0 -> NVRAM: <00000000>
    • Clover: 1 -> NVRAM: <01000000>
  • flagstate:需要注入到 NVRAM 中
    • NVRAM -> Add -> 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14 -> flagstate | Data | <>
    • Clover: 0 -> NVRAM: <00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000>
    • 注意自行判断 NVRAM 键值对位置
  • UIScale:需要注入到 NVRAM 中
    • NVRAM -> Add -> 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14 -> UIScale | Data | <>
    • Clover: 1 -> NVRAM: <01>
    • Clover: 2 -> NVRAM: <02>

CPU 相关设置

  • Type:在 OpenCore 中有对应的 Platforminfo -> SMBIOS -> ProcessorType 可以设置处理器类型
    • EfiPkg 查看可以选用的值
  • HWPEnable:如果你真的要依赖 MSR 0x770 (注意这里说的不是原生电源管理 MSR 0xe2)的 HWP 电源管理,建议安装 headkaze 开发的 HWPEnable.kext。HackinTool 也是他开发的。
  • QEMU:OpenCore 已经完整支持各种虚拟机,因此 OpenCore 中不包含对应选项。
  • TurboDisable:建议用 CPUFriend 或者 ssdtPRGen.sh 来修复变频和电源管理。

设备属性相关设置

USB

  • FixOwnership:OpenCore 中 UEFI -> Quirk -> ReleaseUsbOwnership
  • ClockID:需要自己注入对应的设备属性(Device Properties),属性为 AAPL,clock-id
  • HighCurrent:需要自己注入对应的设备属性(Device Properties),属性为 AAPL,HighCurrent
    • 对于 macOS 10.11 来说 HighCurrent 已经没啥用了。对于更新版的 macOS,推荐用 OC-little 中的 SSDT-USBX 补丁。

FakeID

同样使用 gfxutils 工具找到 PCI 总线位置,然后分别注入相关属性:

  • USB
    • device-id
    • device_type
    • device_type
  • IMEI
    • device-id
    • vendor-id
  • WIFI
    • name
    • compatible
  • LAN
    • device-id
    • compatible
    • vendor-id
  • XHCI
    • device-id
    • device_type: UHCI
    • device_type: OHCI
    • device_type: EHCI
      • device-id
      • AAPL,current-available
      • AAPL,current-extra
      • AAPL,current-available
      • AAPL,current-extra
      • AAPL,current-in-sleep
      • built-in
    • device_type: XHCI
      • device-id
      • AAPL,current-available
      • AAPL,current-extra
      • AAPL,current-available
      • AAPL,current-in-sleep
      • built-in

图形属性相关设置

和前文一样,这些在 Clover 中设置的属性都需要改为注入对应的设备属性(Device Properties)即可。

  • InjectAti:
    • DeviceProperties -> Add -> PCIRoot... -> deviceID
    • DeviceProperties -> Add -> PCIRoot... -> Connectors
  • InjectNvidia:
    • DeviceProperties -> Add -> PCIRoot... -> DeviceID
    • DeviceProperties -> Add -> PCIRoot... -> Family
  • FakeAti:
    • DeviceProperties -> Add -> PCIRoot... -> device-id
    • DeviceProperties -> Add -> PCIRoot... -> ATY,DeviceID
    • DeviceProperties -> Add -> PCIRoot... -> @0,compatible
    • DeviceProperties -> Add -> PCIRoot... -> vendor-id
    • DeviceProperties -> Add -> PCIRoot... -> ATY,VendorID
  • BootDisplay:
    • DeviceProperties -> Add -> PCIRoot... -> @0,AAPL,boot-display

Intel 核显依然推荐使用 WhateverGreen 和缓冲帧补丁驱动。

一般的,在注入仿造显卡或仿造 VBIOS 的时候,更推荐使用 SSDT 搭配 WhateverGreen 的方式(成功率较高)。至于 EDID 注入,WhateverGreen 的文档中有 详细介绍

内核扩展驱动(Kext)相关

  • KernelPmAppleIntelCPUPM:对应 OpenCore 中 Kernel -> Quirks -> AppleXcpmCfgLock -> YESKernel -> Quirks -> AppleCpuPmCfgLock -> YES
  • DellSMBIOSPatch :在 OpenCore 中对应了两个 Quirk:
    • Kernel -> Quirks -> CustomSMBIOSGuid -> YES
    • PlatformInfo -> UpdateSMBIOSMode -> Custom
  • Kernel LAPICKernelXCPM:分别对应 OpenCore 中的 Kernel -> Quirks -> LapicKernelPanic -> YESKernel -> Quirks -> AppleXcpmExtraMsrs -> YES
  • AppleRTC
    • Comment:Disable RTC checksum update on poweroff
    • Enabled:YES
    • Count:1
    • Base:__ZN8AppleRTC14updateChecksumEv
    • Identifier:com.apple.driver.AppleRTC
    • Limit:0
    • Find:
    • Replace:c3
  • FakeCPUID:OpenCore 提供了专门的 Emulate 功能。

除此以外,一些常用的 Kext Patch 在 OpenCore 中也有对应的 Quirks。

  • 解除 USB 15 端口限制,以前根据不同的系统需要打不同的 Kext Patch,现在只需要 OpenCore 一个 Quirk:Kernel -> Quirks -> XhciPortLimit -> YES
  • 内置硬盘变外置硬盘,也只需要一个 Quirk:kernel -> Quirks -> ExternalDiskIcons -> YES
    • 和之前提到的 FixSATA 不同,FixSATA 顾名思义只修复 SATA 硬盘,而 OpenCore 这个 Quirks 会修复所有的硬盘。
  • 为不支持的 SATA SSD 提供 TRIM 现在也只需要启用一个 Quirk:Kernel -> Quirks -> ThirdPartyDrive
    • 除非使用 sudo trimforce enable 后,「系统报告」中仍然提示 SATA 控制器下的硬盘没有启用 TRIM,否则不需要打开这个 Quirk。
  • IOPCIFamily Patch 对应 OpenCore 中 Kernel -> Quirks -> IncreasePciBarSize
  • Disable board-ID check 可以用 WhateverGreen 代替。
  • AppleHDA Patch 已经包含在 AppleALC 中。
  • IONVMe Patches 在 macOS 10.13 及其之后的版本上已经没有必要了。如果要修复 macOS 10.14 及其之后版本的 NVMe 电源管理,请使用 NVMeFix.kext
  • MSR 0xE2 _xcpm_idle instant reboot (c) Pike R. Alpha(避免写入 MSR 0xE2)对应的是 OpenCore 中这个 Quirk:Kernel -> Quirks -> AppleXcpmCfgLock
  • 除此以外,Pike R. Alpha 提供的下述 Kext Patch 也都已经包含在 Kernel -> Quirk -> AppleXcpmExtraMsrs 中:
    • _xcpm_bootstrap
    • _xcpm_pkg_scope_msrs
    • _xcpm_SMT_scope_msrs #1
    • _xcpm_SMT_scope_msrs #2
    • _xcpm_core_scope_msrs
    • _xcpm_performance_patch
    • xcpm MSR Patch 1 and 2
    • /0x82D390/MSR_PP0_POLICY 0x63a xcpm support patch 1 and 2

SMBIOS 机型信息和系统参数

  • Product NamePlatformInfo -> Generic -> SystemProductName
  • Serial NumberPlatformInfo --> Generic -> SystemSerialNumber
  • Board Serial NumberPlatformInfo -> Generic -> MLB
  • SmUUIDPlatformInfo -> Generic -> SystemUUID
  • Slots AAPL Injection:需要注入到设备属性中
    • DeviceProperties -> Add -> PCIRoot... -> APPL,slot-name | string | Add slot
  • CustomUUID:就连 Clover 都不推荐配置这一项,OpenCore 直接就不提供硬件 UUID 配置功能
  • InjectSystemID:兼容变色龙的历史遗留配置,Clover 不推荐配置这一项,OpenCore 也不再提供该项配置
  • BacklightLevel:需要注入到 NVRAM 中
    • NVRAM -> Add -> 7C436110-AB2A-4BBB-A880-FE41995C9F82 -> backlight-level | Data | <Insert value>
  • NvidiaWeb:需要注入到 NVRAM 中
    • NVRAM -> Add -> 7C436110-AB2A-4BBB-A880-FE41995C9F82 -> nvda_drv: <31>

配置好 OpenCore 以后,可以将 OpenCore 复制到 U 盘或者硬盘中。需要注意的是,EFI/BOOT/BOOTx64.efi 需要直接替换。在添加引导项时,OpenCore 必须EFI/BOOT/BOOTx64.efi 启动而不是从 EFI/OC/OpenCore.efi 启动。如果启动项中添加的不是 EFI/BOOT/BOOTx64.efi,那么有很大的概率你会遇到各种奇怪的、无法引导的问题。

清理 Clover 残余

重启到 OpenCore 引导之前,务必清理掉 Clover 的残留文件:

# 删除 Clover 位于系统偏好设置中的面板
sudo rm -rf "/Library/PreferencePanes/Clover.prefPane"
# 删除 Clover 的自动脚本
rm -rf "/etc/rc.clover.lib"
rm -rf "/etc/rc.boot.d/10.save_and_rotate_boot_log.local"
rm -rf "/etc/rc.boot.d/20.mount_ESP.local"
rm -rf "/etc/rc.boot.d/70.disable_sleep_proxy_client.local.disabled"
rm -rf "/etc/rc.boot.d/80.save_nvram_plist.local"
rm -rf "/etc/rc.shutdown.local"
rm -rf "/etc/rc.boot.d"
rm -rf "/etc/rc.shutdown.d"
# 删除 Clover 的守护进程
launchctl unload '/Library/LaunchDaemons/com.slice.CloverDaemonNew.plist'
rm -rf '/Library/LaunchDaemons/com.slice.CloverDaemonNew.plist'
rm -rf '/Library/Application Support/Clover/CloverDaemonNew'
rm -rf '/Library/Application Support/Clover/CloverLogOut'
rm -rf '/Library/Application Support/Clover/CloverWrapper.sh'

除此以外,在使用 OpenCore 引导 macOS 之前需要重置 NVRAM。如果你之前使用的是模拟 NVRAM,那么还需要删除 EFI 分区中的 nvram.plist 文件。

  • 如果在 OpenCore 中启用了 AllowNvramReset 这个 Quirk,那么可以在 OpenCore 引导菜单中,按下空格键显示隐藏条目,最后一个条目就是 OpenCore 内置的重置 NVRAM 功能。
  • 也可以在 Clover 中重置 NVRAM:删除模拟 NVRAM 驱动和 nvram.plist 以后,在 Clover 引导菜单中按下 F11 来清除 NVRAM。

当 OpenCore 已经可以正常引导 macOS 后,你就可以将 EFI 分区中删除 EFI/Clover 目录、将 Clover 启动项从 BIOS 中删除了。

从 Clover 到 OpenCore —— Clover 迁移 OpenCore 指南
本文作者
Sukka
发布于
2020-04-12
更新于
2020-06-01
许可协议
转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!
如果你喜欢我的文章,或者我的文章有帮到你,可以考虑一下打赏作者
评论加载中...