目录

  • 介绍
    • 1.1 通用术语
  • 配置
    • 2.2 配置处理
    • 2.3 配置结构
  • 设置
    • 3.1 目录结构
    • 3.2 安装和升级
    • 3.3 贡献代码
    • 3.4 代码约定
  • ACPI
    • 4.1 简介
    • 4.2 属性列表
      • 1. `Add`
      • 2. `Delete`
      • 3. `Patch`
      • 4. `Quirks`
    • 4.3 Add 属性
      • 1. `Comment`
      • 2. `Enabled`
      • 3. `Path`
    • 4.4 Delete 属性
      • 1. `All`
      • 2. `Comment`
      • 3. `Enabled`
      • 4. `OemTableId`
      • 5. `TableLength`
      • 6. `TableSignature`
    • 4.5 Patch 属性
      • 1. `Base`
      • 2. `BaseSkip`
      • 3. `Comment`
      • 4. `Count`
      • 5. `Enabled`
      • 6. `Find`
      • 7. `Limit`
      • 8. `Mask`
      • 9. `OemTableId`
      • 10. `Replace`
      • 11. `ReplaceMark`
      • 12. `Skip`
      • 13. `TableLength`
      • 14. `TableSignature`
    • 4.6 Quirks 属性
      • 1. `FadtEnableReset`
      • 2. `NormalizeHeaders`
      • 3. `RebaseRegions`
      • 4. `ResetHwSig`
      • 5. `ResetLogoStatus`
  • Booter
    • 5.1 简介
    • 5.2 属性列表
      • 1. `MmioWhitelist`
      • 2. `Patch`
      • 3. `Quirks`
    • 5.3 MmioWhitelist 属性
      • 1. `Address`
      • 2. `Comment`
      • 3. `Enabled`
    • 5.4 Patch 属性
      • 1. `Arch`
      • 2. `Comment`
      • 3. `Count`
      • 4. `Enabled`
      • 5. `Find`
      • 6. `Identifier`
      • 7. `Limit`
      • 8. `Mask`
      • 9. `Replace`
      • 10. `ReplaceMask`
      • 11. `Skip`
    • 5.5 Quirks 属性
      • 2. `AllowRelocationBlock`
      • 2. `AvoidRuntimeDefrag`
      • 3. `DevirtualiseMmio`
      • 4. `DisableSingleUser`
      • 5. `DisableVariableWrite`
      • 6. `DiscardHibernateMap`
      • 7. `EnableSafeModeSlide`
      • 8. `EnableWriteUnprotector`
      • 9. `ForceExitBootServices`
      • 10. `ProtectMemoryRegions`
      • 11. `ProtectSecureBoot`
      • 12. `ProtectUefiServices`
      • 13. `ProvideCustomSlide`
      • 14. `ProvideMaxSlide`
      • 15. `RebuildAppleMemoryMap`
      • 16. `SetupVirtualMap`
      • 17. `SignalAppleOS`
      • 18. `SyncRuntimePermissions`
  • DeviceProperties
    • 6.1 简介
    • 6.2 属性列表
      • 1. `Add`
      • 2. `Delete`
    • 6.3 常见属性
  • Kernel
    • 7.1 简介
    • 7.2 属性列表
      • 1. Add
      • 2. Block
      • 3. Emulate
      • 4. Force
      • 5. Patch
      • 6. Quirks
      • 7. Scheme
    • 7.3 Add 属性
      • 1. `Arch`
      • 2. `BundlePath`
      • 3. `Comment`
      • 4. `Enabled`
      • 5. `ExecutablePath`
      • 6. `MaxKernel`
      • 7. `MinKernel`
      • 8. `PlistPath`
    • 7.4 Block 属性
      • 1. `Arch`
      • 2. `Comment`
      • 3. `Enabled`
      • 4. `Identifier`
      • 5. `MaxKernel`
      • 6. `MinKernel`
    • 7.5 Emulate 属性
      • 1. `Cpuid1Data`
      • 2. `Cpuid1Mask`
      • 3. `DummyPowerManagement`
      • 4. `MaxKernel`
      • 5. `MinKernel`
    • 7.6 Force 属性
      • 1. `Arch`
      • 2. `BundlePath`
      • 3. `Comment`
      • 4. `Enabled`
      • 5. `ExecutablePath`
      • 6. `Identifier`
      • 7. `MaxKernel`
      • 8. `MinKernel`
      • 9. `PlistPath`
    • 7.7 Patch 属性
      • 1. `Arch`
      • 2. `Base`
      • 3. `Comment`
      • 4. `Count`
      • 5. `Enabled`
      • 6. `Find`
      • 7. `Identifier`
      • 8. `Limit`
      • 9. `Mask`
      • 10. `MaxKernel`
      • 11. `MinKernel`
      • 12. `Replace`
      • 13. `ReplaceMask`
      • 14. `Skip`
    • 7.8 Quirks 属性
      • 1. `AppleCpuPmCfgLock`
      • 2. `AppleXcpmCfgLock`
      • 3. `AppleXcpmExtraMsrs`
      • 4. `AppleXcpmForceBoost`
      • 5. `CustomSMBIOSGuid`
      • 6. `DisableIoMapper`
      • 7. `DisableLinkeditJettison`
      • 8. `DisableRtcChecksum`
      • 9. `ExtendBTFeatureFlags`
      • 10. `ExternalDiskIcons`
      • 11. `ForceSecureBootScheme`
      • 12. `IncreasePciBarSize`
      • 13. `LapicKernelPanic`
      • 14. `LegacyCommpage`
      • 15. `PanicNoKextDump`
      • 16. `PowerTimeoutKernelPanic`
      • 17. `SetApfsTrimTimeout`
      • 18. `ThirdPartyDrives`
      • 19. `XhciPortLimit`
    • 7.9 Scheme 属性
      • 1. `FuzzyMatch`
      • 2. `KernelArch`
      • 3. `KernelCache`
  • Misc
    • 8.1 简介
    • 8.2 属性列表
      • 1. `Boot`
      • 2. `BlessOverride`
      • 3. `Debug`
      • 4. `Entries`
      • 5. `Security`
      • 6. `Tools`
    • 8.3 Boot 属性
      • 1. `ConsoleAttributes`
      • 2. `HibernateMode`
      • 3. `HideAuxiliary`
      • 4. `LauncherOption`
      • 5. `LauncherPath`
      • 6. `PickerAttributes`
      • 7. `PickerAudioAssist`
      • 8. `PollAppleHotKeys`
      • 9. `ShowPicker`
      • 10. `TakeoffDelay`
      • 11. `Timeout`
      • 12. `PickerMode`
      • 13. `PickerVariant`
    • 8.4 Debug 属性
      • 1. `AppleDebug`
      • 2. `ApplePanic`
      • 3. `DisableWatchDog`
      • 4. `DisplayDelay`
      • 5. `DisplayLevel`
      • 6. `SerialInit`
      • 7. `SysReport`
      • 8. `Target`
    • 8.5 Security 属性
      • 1. `AllowNvramReset`
      • 2. `AllowSetDefault`
      • 3. `AllowToggleSip`
      • 4. `ApECID`
      • 5. `AuthRestart`
      • 6. `BlacklistAppleUpdate`
      • 7. `DmgLoading`
      • 8. `EnablePassword`
      • 9. `ExposeSensitiveData`
      • 10. `HaltLevel`
      • 11. `PasswordHash`
      • 12. `PasswordSalt`
      • 13. `Vault`
      • 14. `ScanPolicy`
      • 15. `SecureBootModel`
    • 8.6 Entry 属性
      • 1. `Arguments`
      • 2. `Auxiliary`
      • 3. `Comment`
      • 4. `Enabled`
      • 5. `Flavour`
      • 6. `Name`
      • 7. `Path`
      • 8. `RealPath`
      • 9. TextMode
  • NVRAM
    • 9.1 简介
    • 9.2 属性列表
      • 1. `Add`
      • 2. `Delete`
      • 3. `LegacyEnable`
      • 4. `LegacyOverwrite`
      • 5. `LegacySchema`
      • 6. `WriteFlash`
    • 9.3 必需变量
    • 9.4 建议变量
    • 9.5 其他变量
  • PlatformInfo
    • 10.1 属性列表
      • 1. `Automatic`
      • 2. `CustomMemory`
      • 3. `UpdateDataHub`
      • 4. `UpdateNVRAM`
      • 5. `UpdateSMBIOS`
      • 6. `UpdateSMBIOSMode`
      • 7. `UseRawUuidEncoding`
      • 7. `Generic`
      • 8. `DataHub`
      • 9. `Memory`
      • 10. `PlatformNVRAM`
      • 11. `SMBIOS`
    • 10.2 Generic 属性
      • 1. `SpoofVendor`
      • 2. `AdviseWindows`
      • 3. `MaxBIOSVersion`
      • 4. `SystemMemoryStatus`
      • 5. `ProcessorType`
      • 6. `SystemProductName`
      • 7. `SystemSerialNumber`
      • 8. `SystemUUID`
      • 9. `MLB`
      • 10. `ROM`
    • 10.3 DataHub 属性
      • 1. `PlatformName`
      • 2. `SystemProductName`
      • 3. `SystemSerialNumber`
      • 4. `SystemUUID`
      • 5. `BoardProduct`
      • 6. `BoardRevision`
      • 7. `StartupPowerEvents`
      • 8. `InitialTSC`
      • 9. `FSBFrequency`
      • 10. `ARTFrequency`
      • 11. `DevicePathsSupported`
      • 12. `SmcRevision`
      • 13. `SmcBranch`
      • 14. `SmcPlatform`
    • 10.4 Memory 属性
      • 1. `DataWidth`
      • 2. `Devices`
      • 3. `ErrorCorrection`
      • 4. FormFactor
      • 5. `MaxCapacity`
      • 6. `TotalWidth`
      • 7. `Type`
      • 8. `TypeDetail`
    • 10.4.1 Memory Device 属性
      • 1. `AssetTag`
      • 2. `BankLocator`
      • 3. `DeviceLocator`
      • 4. `Manufacturer`
      • 5. `PartNumber`
      • 6. `SerialNumber`
      • 7. `Size`
      • 8. `Speed`
    • 10.5 PlatformNVRAM 属性
      • 1. `BID`
      • 2. `ROM`
      • 3. `MLB`
      • 4. `FirmwareFeatures`
      • 5. `FirmwareFeaturesMask`
      • 6. `SystemUUID`
    • 10.6 SMBIOS 属性
      • 1. `BIOSVendor`
      • 2. `BIOSVersion`
      • 3. `BIOSReleaseDate`
      • 4. `SystemManufacturer`
      • 5. `SystemProductName`
      • 6. `SystemVersion`
      • 7. `SystemSerialNumber`
      • 8. `SystemUUID`
      • 9. `SystemSKUNumber`
      • 10. `SystemFamily`
      • 11. `BoardManufacturer`
      • 12. `BoardProduct`
      • 13. `BoardVersion`
      • 14. `BoardSerialNumber`
      • 15. `BoardAssetTag`
      • 16. `BoardType`
      • 17. `BoardLocationInChassis`
      • 18. `ChassisManufacturer`
      • 19. `ChassisType`
      • 20. `ChassisVersion`
      • 21. `ChassisSerialNumber`
      • 22. `ChassisAssetTag`
      • 23. `PlatformFeature`
      • 24. `SmcVersion`
      • 25. `FirmwareFeatures`
      • 26.`FirmwareFeaturesMask`
      • 27. `ProcessorType`
  • UEFI
    • 11.1 简介
    • 11.2 驱动列表
    • 11.3 工具与应用程序
    • 11.4 OpenCanopy
    • 11.5 OpenRuntime
    • 11.6 属性列表
      • 1. `APFS`
      • 2. `Audio`
      • 3. `ConnectDrivers`
      • 4. `Drivers`
      • 5. `Input`
      • 6. `Output`
      • 7. `ProtocolOverrides`
      • 8. `Quirks`
      • 9. `ReservedMemory`
    • 11.7 APFS 属性
      • 1. `EnableJumpstart`
      • 2. `GlobalConnect`
      • 3. `HideVerbose`
      • 4. `JumpstartHotPlug`
      • 5. `MinDate`
      • 6. `MinVersion`
    • 11.8 Audio 属性
      • 1. `AudioCodec`
      • 2. `AudioDevice`
      • 3. `AudioOut`
      • 4. `AudioSupport`
      • 5. `MinimumVolume`
      • 6. `PlayChime`
      • 7. `SetupDelay`
      • 8. `VolumeAmplifier`
    • 11.9 Input 属性
      • 1. `KeyFiltering`
      • 2. `KeyForgetThreshold`
      • 3. `KeyMergeThreshold`
      • 4. `KeySupport`
      • 5. `KeySupportMode`
      • 6. `KeySwap`
      • 7. `PointerSupport`
      • 8. `PointerSupportMode`
      • 9. `TimerResolution`
    • 11.10 Output 属性
      • 1. `TextRenderer`
      • 2. `ConsoleMode`
      • 3. `Resolution`
      • 4. `ForceResolution`
      • 4. `ClearScreenOnModeSwitch`
      • 5. `DirectGopRendering`
      • 6. `IgnoreTextInGraphics`
      • 7. `ReplaceTabWithSpace`
      • 8. `ProvideConsoleGop`
      • 9. `ReconnectOnResChange`
      • 10. `SanitiseClearScreen`
      • 11. `UgaPassThrough`
    • 11.11 ProtocolOverrides 属性
      • 1. `AppleAudio`
      • 2. `AppleBootPolicy`
      • 3. `AppleDebugLog`
      • 4. `AppleEvent`
      • 5. `AppleFramebufferInfo`
      • 6. `AppleImageConversion`
      • 7. `AppleImg4Verification`
      • 8. `AppleKeyMap`
      • 9. `AppleRtcRam`
      • 10. `AppleSecureBoot`
      • 11. `AppleSmcIo`
      • 12. `AppleUserInterfaceTheme`
      • 13. `DataHub`
      • 14. `DeviceProperties`
      • 15. `FirmwareVolume`
      • 16. `HashServices`
      • 17. `OSInfo`
      • 18. `UnicodeCollation`
    • 11.12 Quirks 属性
      • 1. `DisableSecurityPolicy`
      • 1. `ExitBootServicesDelay`
      • 2. `IgnoreInvalidFlexRatio`
      • 3. `ReleaseUsbOwnership`
      • 4. `RequestBootVarRouting`
      • 5. `TscSyncTimeout`
      • 6. `UnblockFsConnect`
    • 11.13 ReservedMemory 属性
      • 1. `Address`
      • 2. `Comment`
      • 3. `Size`
      • 4. `Type`
      • 5. `Enabled`
  • 排错
    • 12.1 旧版 Apple 操作系统
      • 1. macOS 10.8 和 10.9
      • 2. macOS 10.7
      • 3. macOS 10.6
      • 4. macOS 10.5
      • 5. macOS 10.4
    • 12.2 UEFI 安全启动
    • 12.3 Windows 支持
      • 1. 我能安装 Windows 系统吗?
      • 2. 我需要安装其他什么软件吗?
      • 3. 为什么我会在 Boot Camp 启动硬盘 控制面板 中看到 `Basic data partition`?
      • 4. 如何选择 NTFS 驱动程序
    • 12.4 调试
    • 12.5 技巧和窍门
      • 1. 啊呀呀呀我系统没法启动了我该怎么看日志啊?
      • 2. macOS 启动失败我该怎么调试?
      • 3. 如何自定义启动项?
      • 4. 如何选择默认启动的系统?
      • 5. 安装 macOS 最简单的方法是什么?
      • 6. 为什么无法加载 Recovery 恢复镜像 进行在线安装?
      • 7. 我可以在 Apple 的硬件、或虚拟机中使用 OpenCore 吗?
      • 8. 为什么 Find 和 Replace 的补丁的长度必须相等?
      • 9. 我应该如何决定哪些 `Booter` Quirk 需要被启用?

介绍

1.1 通用术语

  • plist — 是一种用 XML 编写的、储存 ASCII 属性列表格式的集合文件,又称 XML 1.0 版。 统一类型标识符(UTI): com.apple.property-list。 plist 由多个 plist object 组成,这些对象组合在一起形成一种具有层次的结构。 由于 plist 格式的定义不明确,因此本文中的所有定义只有在运行 plutil -lint 有效后才能被应用。外部参考: https://www.apple.com/DTDs/PropertyList-1.0.dtd, man plutil
  • plist type — 指 plist 集合(plist array, plist dictionary, plist key)和基本类型(plist string, plist data, plist date, plist boolean, plist integer, plist real)。
  • plist object — 是用来定义 plist type 的实现形式,可以理解为值。
  • plist array — 类数组集合,参数为 array。包含零个或多个 plist object
  • plist dictionary — 类地图(关联数组)集合,参数为 dict 。包含零个或多个 plist key
  • plist key — 包含一个以 plist key 名称命名的 plist object,参数为 key。由 7 位 ASCII 集的可打印字符组成。
  • plist string — 7 位 ASCII 集的可打印字符串,参数为 string
  • plist data — base64 编码的对象,参数为 data
  • plist date — ISO-8601 日期表示法,参数为 date,不支持。
  • plist boolean — 逻辑声明对象,其值为 true (1) 或 false (0),参数为 truefalse
  • plist integer — 带符号的 10 进制,参数为 integer。适用于以二进制补码表示的 64 位无符号整数,除非在特定的 plist object 描述中明确提及一个更小的、有或无符号的整数类型。
  • plist real — 浮点数,参数为 real,不支持。
  • plist metadata — 实现将 value 强制转换为 data。 允许传递 plist string,此时的结果用空结果字节序列(即 C 字符串)表示;允许传递 plist integer,此时的结果用二进制补码形式的 32 位小尾数字节序列表示;允许传递 plist boolean, 此时的值为一个字节:01 表示 true00 表示 false;允许传递 plist data 本身。其他类型或更大的整数会导致未定义、非预期的行为。

配置

2.2 配置处理

如果 OpenCore 发现了 OC Config,则至少会读取并处理一次。根据 OpenCore 的引导机制的不同,如果存在多个 OC Config 文件,OpenCore 可能会读取其中任何一个或数个。如果硬盘中没有 OC Config,OpenCore 将会使用可选值和无效值的规则。

OC Config 有大小、嵌套和键值数量的限制。OC Config 的大小不得超过 16 MB,嵌套层数不得超过 8 层,每个 plist object 中最多有 16384 个节点(一个 plist dictionary 将被计为一对节点)。不符合上述规则的 OC Config 文件将可能导致未定义、非预期的行为。常见的 OC Config 错误格式包括:

  • 不符合 plist DTD
  • 存在本文档中没有记载的 plist object
  • 违反文件大小、嵌套层级和键值数量的限制

我们建议(但非强制)遇到格式错误的 OC Config 时中止、当作 OC Config 不存在的情况来处理。为了能够向前兼容,我们建议(但非强制)对采用无效值的行为进行警告。采用无效值的建议做法是在使用的情况下遵守以下规则:

Type Value
plist string Empty string (<string></string>)
plist data Empty data (<data></data>)
plist integer 0 (<integer>0</integer>)
plist boolean False (<false/>)
plist tristate False (<false/>)

2.3 配置结构

OC Config 包括以下几个独立部分,将在本文档中分别进行介绍。默认情况下配置文件将尽可能不启用任何功能以及禁用某些功能。总的来说,这些配置一般由如下的操作构成:

  • Add:为数据提供 添加 操作支持。已经存在的值不会被覆盖,必要时请使用 Delete。
  • Delete:为数据提供 删除 操作支持。
  • Patch:为数据提供 补丁 操作支持。
  • Quirks:提供特定的黑科技支持。

配置文件分为以下几个独立部分:

  • ACPI
  • Booter
  • DeviceProperties
  • Kernel
  • Misc
  • NVRAM
  • PlatformInfo
  • UEFI

设置

3.1 目录结构

ESP
├── EFI
│    ├── BOOT
│    │    └── BOOTx64.efi
│    └── OC
│        ├── ACPI
│        │    ├── DSDT.aml
│        │    ├── SSDT-1.aml
│        │    └── MYTABLE.aml
│        ├── Drivers
│        │    ├── MyDriver.efi
│        │    └── OtherDriver.efi
│        ├── Kexts
│        │    ├── MyKext.kext
│        │    └── OtherKext.kext
│        ├── Resources
│        │    ├── Audio
│        │    ├── Font
│        │    ├── Image
│        │    └── Label
│        ├── Tools
│        │    └── Tool.efi
│        ├── OpenCore.efi
│        ├── config.plist
│        ├── vault.plist
│        └── vault.sig
├── boot
├── nvram.plist
├── opencore-YYYY-MM-DD-HHMMSS.txt
├── panic-YYYY-MM-DD-HHMMSS.txt
└── SysReport
Figure 1: 目录结构

使用目录引导时,使用的目录结构应该遵循上述目录结构。可用的条目有:

  • BOOTx64.efiBOOTIa32.efi — 初始引导程序,用来加载 OpenCore.efi。对于大部分固件来说,BOOTx64.efi 是 UEFI 默认启动项,但也可以重命名后放到自定义位置,避免因 BOOTx64.efi 被其它操作系统(如 Windows)所覆盖而导致 OpenCore 无法启动。更多细节请参见 LauncherOption
  • boot — Duet bootstrap loader,用于在传统 BIOS 固件上模拟 UEFI 环境、并加载 OpenCore.efi
  • ACPI — 用于存储 ACPI 补充信息的目录。
  • Drivers — 用于存储 UEFI 补充驱动程序的目录。
  • Kexts — 用于存储内核驱动(kext)补充的目录。
  • Resources — 媒体资源使用的目录,如 屏幕朗读 的语音文件(见「UEFI Audio 属性」章节)。这一目录同时也用于存放 GUI 界面所使用的图片,见 OpenCanopy 相关章节。
  • Tools — 用于存储补充工具的目录。
  • OpenCore.efi — 主引导应用程序,负责操作系统加载。OpenCore.efi 所在的目录称为 根目录。默认 根目录 为 “EFI/OC”,但是当直接启动 OpenCore.efi 或通过自定义启动器启动 OpenCore.efi 时,其他包含 OpenCore.efi 的目录也同样支持。
  • config.plist — OC Config(即 OpenCore 的配置文件,见「配置术语」)。
  • vault.plist — OC Config 可能加载的所有文件的哈希。
  • vault.sigvault.plist 的签名文件。
  • SysReport — 存放 SysReport 功能产生的系统错误报告。
  • nvram.plist — OpenCore 变量导入文件。
  • opencore-YYYY-MM-DD-HHMMSS.txt — OpenCore 日志文件。
  • panic-YYYY-MM-DD-HHMMSS.txt — Kernal Panic 日志文件。

: 受限于固件的实现行为,OpenCore 可能无法访问绝对路径长度大于 OC_STORAGE_SAFE_PATH_MAX(默认值为 128)的目录。

3.2 安装和升级

如果要安装 OpenCore,请在使用 GPT 格式的硬盘上、按照上一节的文件夹结构建立文件和文件夹。尽管本文档的相应部分的确提供了有关你所需的外部资源(如 ACPI 表、UEFI 驱动程序或 kexts)的某些信息,但是本文档不保证会提供关于这些外部资源的全部信息。关于 kext 的完整信息可以查看由 OpenCore 提供的 可选 kext 列表;而本文档也在安全属性的相关章节提供了 Vauting 的相关信息。

OpenCore 的配置文件可以使用任何常规的文本编辑器(如 nano、vim、VSCode)进行编辑,但是专用软件可以带来更好的体验。在 macOS 上我们推荐使用 Xcode。你也可以使用 ProperTree ,这是一个轻量级的跨平台的开源 plist 编辑器。

如果要通过 BIOS 进行开机,你必须使用第三方 UEFI 环境提供程序。OpenDuetPkg 是一个常用的为旧操作系统提供 Legacy 引导的 UEFI 环境提供程序。要在这样的旧操作系统上运行 OpenCore,你可以使用一个独立的工具 BootInstall 安装 OpenDuetPkg(目前已和 OpenCore 打包在一起发布)。

如果要升级 OpenCore,Differences.pdf 提供了 OpenCore 配置文件变更的相关信息,Changelog.md 提供了 OpenCore 的更新日志。

3.3 贡献代码

OpenCore 可以作为普通的 EDK II 进行编译。由于 TianoCore 放弃了对 UDK 的开发,因此 OpenCore 需要使用 EDK II Stable。目前支持的 EDK II 版本托管在 acidanthera/audk。软件包所需的补丁在 Patches 目录下。

XCODE5 是官方唯一支持的工具链。使用其他工具链虽然也有可能正常工作,但我们的态度是既不推荐、也不支持。也欢迎贡献一些干净、简洁的补丁,代码规范务必遵循 EDK II C Codestyle。

要使用 XCODE5 编译,除了 Xcode 之外,还需要安装 NASM 和 MTOC。建议使用最新的 Xcode 版本,不必因为工具链叫 XCODE5 而纠结于 Xcode 的版本号。命令行举例如下:

git clone --depth=1 https://github.com/acidanthera/audk UDK
cd UDK
git submodule update --init --recommend-shallow
git clone --depth=1 https://github.com/acidanthera/OpenCorePkg
source edksetup.sh
make -C BaseTools
build -a X64 -b RELEASE -t XCODE5 -p OpenCorePkg/OpenCorePkg.dsc
Listing 1: 编译指令

对于 IDE 的用法,Xcode 项目可在资源库的根目录下使用。还有一种方法是使用 Sublime Text 并带有 EasyClangComplete 插件。在你的 UDK 根目录下添加类似内容的 .clang_complete 文件:

-I/UefiPackages/MdePkg
-I/UefiPackages/MdePkg/Include
-I/UefiPackages/MdePkg/Include/X64
-I/UefiPackages/OpenCorePkg/Include/AMI
-I/UefiPackages/OpenCorePkg/Include/Acidanthera
-I/UefiPackages/OpenCorePkg/Include/Apple
-I/UefiPackages/OpenCorePkg/Include/Apple/X64
-I/UefiPackages/OpenCorePkg/Include/Duet
-I/UefiPackages/OpenCorePkg/Include/Generic
-I/UefiPackages/OpenCorePkg/Include/Intel
-I/UefiPackages/OpenCorePkg/Include/Microsoft
-I/UefiPackages/OpenCorePkg/Include/VMware
-I/UefiPackages/OvmfPkg/Include
-I/UefiPackages/UefiCpuPkg/Include
-IInclude
-include
/UefiPackages/MdePkg/Include/Uefi.h
-fshort-wchar
-Wall
-Wextra
-Wno-unused-parameter
-Wno-missing-braces
-Wno-missing-field-initializers
-Wno-tautological-compare
-Wno-sign-compare
-Wno-varargs
-Wno-unused-const-variable
-DOC_TARGET_NOOPT=1
-DNO_MSABI_VA_FUNCS=1
Listing 2: ECC 配置

{% note danger 警告 %}
工具开发人员修改 config.plist 或其他任何 OpenCore 文件时,都务必检查 opencore-version NVRAM 变量(详见后面的 Debug Properties 章节),如果版本号不支持或尚未发布,则需警告用户。OpenCore 配置可能因版本不同而改变,因此工具开发应仔细遵循本文档,否则可能会当作恶意软件并阻止发布。
{% endnote %}

3.4 代码约定

和其他项目一样,我们在开发过程中也有一些约定。强烈建议所有第三方贡献者在提交补丁之前仔细阅读并遵循以下约定。另外,我们也建议在发送补丁之前先在 Acidanthera Bugtracker 里讨论一下,以免与其他人的工作重复,导致你的补丁被拒绝。

组织结构。代码库包含在 OpenCorePkg 仓库中,它是主要的 EDK II 软件包。

  • 每当需要在多个仓库中进行修改时,都应当分别向每个仓库发送拉取请求(Pull Requests)。
  • 提交更改应该首先提交至依赖仓库,其次才是主仓库,以避免自动构建错误。
  • 每个独立的提交都应该用 XCODE5 编译,并最好也用其他工具链编译。在大多数情况下都可以通过 CI interface 进行检查。最好确保静态分析不提示任何警告。
  • 外部的拉取请求和标记的提交都必须经过验证。也就是说,在 master 中的提交可能会被构建,但并不一定成功。
  • 内部分支应命名如下:作者-名字-日期,比如 vit9696-ballooning-20191026
  • 提交说明(Commit Messages)应该以更改的主要模块(如库或代码模块)为前缀。例如,OcGuardLib: Add OC_ALIGNED macro。对于非库的改变,则应使用 Docs 或者 Build 作为前缀。

设计。代码库是使用独立的 C11 (C17) 子集编写的,能够被 EDK II 使用的大多数较新的工具链支持。如果下面没有讨论特殊情况,建议使用常见的软件开发操作,或者另附解释说明。

  • 永远不要依赖未定义的行为,也要尽量避免实施定义的行为,除非明确涉及到下面的情况(如果缺少相关案例,随时都可以创建一个 Issue,不必拘谨)。
  • 使用 OcGuardLib 来确保安全的积分运算,避免溢出。依赖无符号数回绕(Unsigned Wraparound)时应当谨慎,不要增加不必要的数量。
  • OcGuardLib 检查指针是否正确对齐,虽然架构能够反引用未对齐的指针,但是不要依赖它。
  • 必要时使用柔性数组成员(Flexible Array Member)替代长度为 0 或为 1 的数组。
  • 使用静态断言(STATIC_ASSERT)进行类型和值的假设,使用运行时断言(ASSERT)进行前提条件和不变指标的合理性检查。不要使用运行时断言来检查错误,因为他们绝不应该控制业务流程,并且有可能被排除。
  • UINT32/INT32 默认为 int 大小,并用 %u%d%x 来打印。
  • UINTN/INTN 默认为未定大小,转换为 UINT64/INT64,与 %Lu%Ld 等正常打印。
  • 不要为了数字字面量而依赖整型提升。当类型为实现依赖(implementation-dependent)的时候,使用显式转换(Explicit Cast);当类型大小已知的时候,使用后缀。默认 U 代表 UINT32ULL 代表 UINT64
  • 尤其要确保按位运算时、特别是按位移位时,作无符号的算术。
  • sizeof 运算符应该尽可能地采用变量,而不是类型,否则容易出错。使用 ARRAY_SIZE 获取数组的元素大小。使用 OcStringLib 中的 L_STR_LENL_STR_SIZE 宏,获取字符串文字大小,以保证编译器的优化。
  • 不要使用 goto 关键词。宁可在未能通过错误检查时,提前使用 returnbreakcontinue,也不要嵌套条件语句。
  • 使用 EFIAPI,强制执行 UEFI 调用约定,只在模块之间的协议、外部回调和带有变量参数的函数中使用。
  • 为每一个新增函数提供行内注释,至少要描述其输入、输出、前置条件、后置条件,并给出简要说明。
  • 不要使用 RETURN_STATUS。把 EFI_STATUS 默认为一个当 BOOLEAN 不够用时将始终使用的、相匹配的超集。
  • 违反安全规定的行为应停止系统运行或强制重启。

代码规范。代码库遵循 EDK II codestyle,并作了些许改动和解释。

  • 只为函数和变量写一次行内注释:在头文件中(如果有头文件原型)和 static 变量、函数的行内书写。
  • 行长在 120 个字符(100 个字符更好)以内。
  • 在转换后使用空格,如 (VOID *)(UINTN) Variable
  • 换行时使用两个空格来缩进。
  • 在公共函数前加上 Oc 或其他含义清晰的前缀。
  • 私有的 static 函数不要加上前缀,私有的 non-static 函数要使用 Internal 前缀。
  • 使用 SPDX 许可证标头,如 acidanthera/bugtracker#483 所示。

排错。代码库中加入了 EDK II 调试和一些自定义功能,以改善体验。

  • 调试信息应使用模块前缀,2-5 个字母,后面加一个冒号(:)。对于 OpenCorePkg 使用 OC:,对于库和驱动程序则使用自己独特的前缀。
  • 不要在调试信息结尾使用句点(.),要将 %r 打印的 EFI_STATUS 用连字符隔开(例如 OCRAM: Allocation of %u bytes failed - **%rtextbackslash n)。
  • 使用 DEBUG_CODE_BEGIN ()DEBUG_CODE_END () 结构来看守 可能会降低版本构建性能的 和 在其他方面不必要的 调试检查。
  • 在正常工作时,使用 DEBUG 宏打印调试信息,在 EXIT_BOOT_SERVICES 后使用 RUNTIME_DEBUG 进行调试。
  • 使用 DEBUG_VERBOSE 调试级别留下信息,这些信息虽然目前用不到,但可以方便用于以后的调试。默认情况下, DEBUG_VERBOSE 信息即使在 DEBUG 构建中也会被忽略。
  • 使用 DEBUG_INFO 调试级别来处理所有非关键信息(包括错误),使用 DEBUG_BULK_INFO 来处理不应该出现在 NVRAM 日志中的大量信息,因为 NVRAM 日志的大小十分受限。这些信息在 RELEASE 构建中会被忽略。
  • 使用 DEBUG_ERROR 来打印关键的、可以看见的、可能会停止启动过程的信息,使用 DEBUG_WARN 来打印所有其他可被看见的错误信息,这些都包含在 RELEASE 构建中。

当试图找到有问题的更改时,依靠 git-bisect 功能会很有帮助。另外还有一些非官方资源,提供了按照逐条 Commit 更新的 OpenCore 编译文件,如 Dortania。

ACPI

4.1 简介

ACPI(Advanced Configuration and Power Interface,高级配置和电源接口)是发现和配置计算机硬件的开放标准。
ACPI 规格 定义了实现用的标准表(如 DSDTSSDTFACSDMAR)和各种方法(如 _DSM_PRW)。现代硬件几乎不需要更改即可保持 ACPI 兼容性,但是 OpenCore 仍然提供了修改 ACPI 的方法。

要反汇编和编译 ACPI 表,可以使用由 ACPICA 开发的 iASL compiler。你可以从 Acidanthera/MaciASL 下载 iASL 的图形界面程序。

对 ACPI 的修补按照如下顺序执行:

  • Patch
  • Delete
  • Add
  • Quirks

为了解决操作系统检测的问题,所有对 ACPI 的更改会在所有操作系统上生效。但是在某些场景下(ACPI 编写不规范、操作系统链式引导启动、ACPI 调试)会出现问题。因此在修补 ACPI 时,需要使用 \_OSI 方法。

在系统引导前加载补丁使得编写「代理」补丁成为可能 —— 「代理」补丁即通过重命名的方法修补 DSDT 中的原始行为,然后通过 SSDT 注入同名的行为进行替代。

OpenCore、WhateverGreen、VirtualSmc、VoodooPS2 的 GitHub 仓库中都包含了部分 SSDT 和其他 ACPI 修补的方法。在 AppleLife 的 Laboratory 版块、DSDT 版块提供了不少教程和样例(如 笔记本电池修补教程)。Dortania 也编写了许多 ACPI 有关的教程。但是请注意,这些教程和 OpenCore 无关,他们提供的解决方法也不一定有用。

译者注:对于中国黑苹果玩家,强烈推荐 OC-little 项目,提供了众多 SSDT 范例和相关指导;笔记本用户电池修补请参考 这篇教程。

4.2 属性列表

1. Add

Type: plist array
Failsafe: Empty
Description: 从 OC/ACPI 目录加载指定的 ACPI 表。

设计为用 plist dict 值填充以描述每个块级项目。请参阅下面 4.3 Add 属性 章节。

2. Delete

Type: plist array
Failsafe: Empty
Description: 从 ACPI 栈中删除选定的表。

设计为用 plist dict 值填充以描述每个块级项目。请参阅下面 4.4 Delete 属性 章节。

3. Patch

Type: plist array
Failsafe: Empty
Description: 在添加或删除 ACPI 表之前执行的二进制修补。

设计为用 plist dictionary 值填充以描述每个块级项目。请参阅下面 4.5 Patch 属性 章节。

4. Quirks

Type: plist dict
Description: 应用下文 4.6 Quirks 属性 章节中描述的 Quirks。

4.3 Add 属性

1. Comment

Type: plist string
Failsafe: Empty string
Description: 用于为条目提供人类可读参考的任意 ASCII 字符串(译者注:即注释)。

2. Enabled

Type: plist boolean
Failsafe: false
Description: 除非此值为 true,否则此 ACPI 表不会被添加。

3. Path

Type: plist string
Failsafe: Empty string
Description: 需要加载的 ACPI 表所在的路径。示例值如 DSDT.amlSubDir/SSDT-8.amlSSDT-USBX.aml

所有 ACPI 表都从 OC/ACPI 目录加载,加载顺序遵循数组中的项目顺序。

: 除具有 DSDT 表标识符(由解析得到的数据、而非由其文件名决定)的表外,所有表都将作为新表插入 ACPI 栈。而 DSDT 表与其余的表不同,将会执行 DSDT 表的替换。

4.4 Delete 属性

1. All

Type: plist boolean
Failsafe: false
Description: 如果设置为 true,则所有符合条件的 ACPI 表都会被舍弃。 否则,只舍弃第一个匹配到的。

2. Comment

Type: plist string
Failsafe: Empty string
Description: 用于为条目提供人类可读参考的任意 ASCII 字符串(译者注:即注释)。

3. Enabled

Type: plist boolean
Failsafe: false
Description: 除非此值为 true,否则此 ACPI 表不会被舍弃。

4. OemTableId

Type: plist data, 8 bytes
Failsafe: All zero
Description: 将表的 OEM ID 匹配为此处所填的值,全部为 0 时忽略。

5. TableLength

Type: plist integer
Failsafe: 0
Description: 将表的大小匹配为此处所填的值,填 0 时忽略。

6. TableSignature

Type: plist data, 4 bytes
Failsafe: All zero
Description: 将表的签名匹配为此处的值,全部为 0 时忽略。

:当序列需要在多处替换的时候,务必注意不要指定表的签名,尤其是在进行不同类型的重命名操作的时候。

4.5 Patch 属性

1. Base

Type: plist string
Failsafe: Empty string
Description: 为重命名补丁指定一个 ACPI 路径,让 OC 通过取得该路径的偏移量来查找(或替换)重命名补丁。留空时忽略。

只有正确的绝对路径被支持(例如:\_SB.PCI0.LPCB.HPET)。目前支持的 Object 类型有:DeviceFieldMethod

:应谨慎使用,并非所有 OEM 的 ACPI 表都能被正确处理。如果遇到问题,可使用 Utilities 中的 ACPIe 工具来进行调错。使用 DEBUG=1 参数来编译 ACPIe 将会使该工具输出有助于调试的 ACPI 路径查找过程。

2. BaseSkip

Type: plist integer
Failsafe: 0
Description: 在重命名补丁被应用之前跳过多少次 Base 指定的路径。如果将此值设置为 0,补丁将会被应用于指定 Base 中的所有匹配。

3. Comment

Type: plist string
Failsafe: Empty string
Description: 用于为条目提供人类可读参考的任意 ASCII 字符串(译者注:即注释)。

4. Count

Type: plist integer
Failsafe: 0
Description: 补丁应用的次数。如果将此值设置为 0,补丁将会被应用于所有匹配。

5. Enabled

Type: plist boolean
Failsafe: false
Description: 除非设置为 true,否则此处的 ACPI 补丁不会生效。

6. Find

Type: plist data
Failsafe: Empty data
Description: 需要寻找的 Data,长度必须和 Replace 相等。

7. Limit

Type: plist integer
Failsafe: 0
Description: 要搜索的最大字节数。当此值为 0 时会遍历整个 ACPI 表。

8. Mask

Type: plist data
Failsafe: Empty data
Description: 查找比较期间使用的数据按位掩码。 通过忽略未屏蔽(设置为零)位来进行模糊搜索。可以设置为空数据以忽略,否则此值的长度必须和 Replace 的长度相等。

9. OemTableId

Type: plist data, 8 bytes
Failsafe: All zero
Description: 将表的 OEM ID 匹配为此处所填的值,全部为 0 时忽略。

10. Replace

Type: plist data
Failsafe: Empty data
Description: 一个或多个字节的替换数据。

11. ReplaceMark

Type: plist data
Failsafe: Empty data
Description: 替换数据期间使用的数据按位掩码。 通过忽略未屏蔽(设置为零)位来进行模糊搜索。可以设置为空数据以忽略,否则此值的长度必须和 Replace 的长度相等。

12. Skip

Type: plist integer
Failsafe: 0
Description: 完成替换之前要跳过的匹配数。

13. TableLength

Type: plist integer
Failsafe: 0
Description: 将表的大小匹配为此处所填的值,填 0 时忽略。

14. TableSignature

Type: plist data, 4 bytes
Failsafe: All zero
Description: 将表的签名匹配为此处的值,全部为 0 时忽略。

大多数情况下,ACPI 补丁是有害而无益的:

  • 避免用 ACPI 补丁重命名设备。这样做可能会使设备重命名失败,或者会对不相关的设备进行错误地重命名(如 ECEC0)。为了保证 ACPI 的一致性,在 I/O 注册表级别重命名设备会更加安全,比如 WhateverGreen 的做法。
  • 尽量避免为了支持更高级的功能集而给 _OSI 打补丁,除非你非常需要。这样做通常会侵入 APTIO 固件,从而导致需要用打更多的补丁去填坑。现代的固件基本不需要,而真正需要的那些固件只要打一些更小的补丁就可以了。然而,笔记本厂商通常依靠这种方法来确定是否有现代 I2C 输入支持、散热调节功能,或用来添加其他自定义功能。
  • 避免为了启用亮度调节键而给 EC 事件 _Qxx 打补丁。传统的方法通常需要在 DSDT 和 SSDT 上进行大量的修改,而且新系统上的 debug kext 并不稳定。请改用 BrightnessKeys 内置亮度调节键检测机制。
  • 尽量避免重命名 _PRW_DSM 之类的魔改举动。

在某些情况下,打补丁确实是有意义的:

  • 刷新 HPET(或其他设备)的 method header 来避免老硬件上的 _OSI 兼容性检查。可通过将 A0 10 93 4F 53 46 4C 00 替换为 A4 0A 0F A3 A3 A3 A3 A3 的办法,使带有 if ((OSFL () == Zero)) { If (HPTE) ... Return (Zero)_STA method 达到强制返回 0xF 的目的。
  • 在 SSDT 中实现自定义 method,比如在某些计算机上注入关机修复,可以通过将 _PTS 替换为 ZPTS,把原来的 method 替换为一个假的名字,并添加一个 callback 回调到原 method 中。

TianoCore 源文件 AcpiAml.h 可能会对于理解 ACPI 操作码有所帮助。

FindReplace 的长度 必须完全一样,否则 ACPI 表可能会被破坏、导致系统不稳定。必要时请使用「代理」补丁的方法、或使用 NOP 填充剩余区域

4.6 Quirks 属性

1. FadtEnableReset

Type: plist boolean
Failsafe: false
Description: 在 FADT 表中提供寄存器复位标志,用于修复旧硬件的重启和关机。除非需要,否则不建议启用。

只有在传统硬件和少数笔记本上需要。这一 Quirk 也可以修复电源快捷键(译者注:Command + 电源键)。不建议启用,除非不启用就无法关机和重启。

2. NormalizeHeaders

Type: plist boolean
Failsafe: false
Description: 清理 ACPI 表头字段以解决 macOS ACPI 实现错误导致的引导崩溃。参考:由 Alex James(theracermaster)在调试 AppleACPIPlatform 时发现。从 macOS Mojave (10.14) 开始,这个错误已经被修复。

3. RebaseRegions

Type: plist boolean
Failsafe: false
Description: 尝试试探性地重定位 ACPI 内存区域。不建议启用这一选项,除非你需要自定义 DSDT。

ACPI 表通常由底层固件动态生成。在与位置无关的代码中,ACPI 表可能包含用于设备配置的 MMIO 区域的物理地址,通常按区域(例如 OperationRegion)分组。 更改固件设置或硬件配置,升级或修补固件不可避免地会导致动态生成的 ACPI 代码发生变化,这有时会导致上述 OperationRegion 结构中的地址发生变化。

因此,对 ACPI 表进行任何形式的修改都是非常危险的。最合理的方法是对 ACPI 进行尽可能少的更改,并尝试不替换任何表,尤其是 DSDT。

如果无法不得不替换 DSDT,则至少应尝试确保自定义 DSDT 基于最新的 DSDT 或避免对受影响区域的读写。如果没有其他帮助,可以尝试通过尝试修复 ACPI 地址来避免在 macOS 引导的 PCI Configuration Begin 阶段出现停顿的情况。

4. ResetHwSig

Type: plist boolean
Failsafe: false
Description: 将 FACS 表中 HardwareSignature 的值重置为 0

启用这一选项可以解决固件无法在重新启动过程中保持硬件签名导致的休眠唤醒问题。

5. ResetLogoStatus

Type: plist boolean
Failsafe: false
Description: 将 BGRT 表中 Displayed 状态字段重置为 false

这适用于提供 BGRT 表、但随后无法处理屏幕更新的固件。如果在开机时无法显示 OEM Windows 标志可以尝试开启。

Booter

5.1 简介

本部分允许在 Apple BootLoader(boot.efi)上应用不同种类的 UEFI 修改。目前,这些修改为不同的固件提供了各种补丁和环境更改。其中一些功能最初是作为 AptioMemoryFix.efi 的一部分,如今 AptioMemoryFix.efi 已经不再维护。如果你还在使用,请参考 技巧和窍门 章节提供的迁移步骤。

如果您是第一次在自定义固件上使用此功能,则首先需要执行一系列检查。开始之前,请确保您符合以下条件:

  • 具有最新版本的 UEFI 固件(去主板厂家的官网上看看)。
  • 禁用了 Fast BootHardware Fast Boot。如果 BIOS 里有相关选项,禁用掉。
  • 如果有 Above 4G Decoding 或类似功能,请在固件设置中启用。注意,在某些主板上(特别是 ASUS WS-X299-PRO)这个选项会造成不良影响,必须禁用掉。虽然目前还不知道是不是其他主板也有同样问题,但是如果你遇到了不稳定的启动故障,可以首先考虑检查一下这个选项。
  • 启用了 DisableIoMapper Quirk、或者在 BIOS 中禁用 VT-d、或者删去了 ACPI DMAR 表。
  • 启动参数中 没有 slide。 除非你没法开机、并且在日志里看见了 No slide values are usable! Use custom slide!,否则不论如何也不要使用这个启动参数。
  • CFG Lock (MSR 0xE2 写保护) 在 BIOS 中被禁用。如果 BIOS 中没有、而且你心灵手巧,你可以考虑 手动打补丁将其禁用 。更多细节请参考 VerifyMsrE2。
  • 在 BIOS 中禁用 CSM (Compatibility Support Module)。NVIDIA 6xx / AMD 2xx 或更老的平台可能需要刷新 GOP ROM,具体步骤参考 GopUpdate 或者 AMD UEFI GOP MAKER。
  • 如果有 EHCI / XHCI Hand-off 功能,建议仅在出现 USB 设备连接时启动停滞的情况下启用。
  • 在 BIOS 中启用 VT-xHyper ThreadingExecute Disable Bit
  • 有时你还可能需要在 BIOS 中禁用 Thunderbolt SupportIntel SGXIntel Platform Trust。但是这一操作不是必须的。

在调试睡眠问题时,可能需要(临时)禁用 Power Nap 和自动关闭电源,因为这二者似乎有时会导致旧的平台唤醒黑屏或循环启动。具体问题可能因人而异,但通常你应首先检查 ACPI 表,比如这是在 Z68 主板 上找到的一些 Bug。要关闭 Power Nap 和其他功能,请在终端中运行以下命令:

sudo pmset autopoweroff 0
sudo pmset powernap 0
sudo pmset standby 0

:这些设置可能会在硬件更改、操作系统更新和某些其他情况下重置。要查看它们的当前状态,请在终端中使用 pmset -g 命令。

5.2 属性列表

1. MmioWhitelist

Type: plist array
Description: 设计为用 plist dict 值填充,用来描述在启用 DevirtualiseMmio 这个 Quirk 时特定固件能够运作的关键地址。详见下面的 MmioWhitelist 属性章节。

译者注:如果开机卡在 PCI... 可以尝试开启 Item 1 下的 Patch。

2. Patch

Type: plist array
Failsafe: Empty
Description: 在启动器中执行二进制补丁。

设计为用 plist dictionary 值填充,用来描述每个补丁。参加下面的 Patch 属性部分。

3. Quirks

Type: plist dict
Description: 应用下面的 Quirks 属性部分中所述的各个引导 Quirk。

5.3 MmioWhitelist 属性

1. Address

Type: plist integer
Failsafe: 0
Description: 指排除在外的 MMIO 地址,其内存描述符(Memory Descriptor)应被 DevirtualiseMmio 虚拟化(保持不变)。该值所在的区域会被分配一个虚拟地址,因此在操作系统运行期间,固件能够直接与该内存区域进行通信。

这里写入的地址必须是内存映射的一部分,具有 EfiMemoryMappedIO 类型和 EFI_MEMORY_RUNTIME 属性(最高 bit)。可以使用调试日志找到可能的地址。

2. Comment

Type: plist string
Failsafe: Empty string
Description: 用于为条目提供人类可读参考的任意 ASCII 字符串(译者注:即注释)。

3. Enabled

Type: plist boolean
Failsafe: false
Description: 设置为 true 时,所添加的地址将被虚拟化(保持不变)。

5.4 Patch 属性

1. Arch

Type: plist string
Failsafe: Any
Description: 启动器补丁架构(Any, i386, x86_64)。

2. Comment

Type: plist string
Failsafe: Empty
Description: 用于为条目提供人类可读参考的任意 ASCII 字符串(译者注:即注释)。

3. Count

Type: plist integer
Failsafe: 0
Description: 修补的次数,超过这一次数后便不再修补。0 表示修补所有查找到的地方。

4. Enabled

Type: plist boolean
Failsafe: false
Description: 除非设置为 true,否则将不会应用该补丁。

5. Find

Type: plist data
Failsafe: Empty
Description: 要查找的数据。必须与 Replace 的大小相等。

6. Identifier

Type: plist string
Failsafe: Empty
Description: Apple 代表 macOS 启动器(通常是 boot.efi);带有后缀的名称(如 bootmgfw.efi)代表特定的启动器;Any 或空字符串(默认)代表任何启动器。

7. Limit

Type: plist integer
Failsafe: 0
Description: 搜索的最大字节数。可以设置为 0 来查找整个启动器。

8. Mask

Type: plist data
Failsafe: Empty
Description: 在查找比较的过程中使用数据位掩码。允许通过忽略未被屏蔽的 bit(设置为 0)进行模糊搜索。若留空则代表忽略,否则其大小必须等于 Find

9. Replace

Type: plist data
Failsafe: Empty
Description: 一个或多个字节的替换数据。

10. ReplaceMask

Type: plist data
Failsafe: Empty
Description: 替换时使用的数据位掩码。允许通过更新掩码(设置为非 0)来进行模糊替换。若留空则代表忽略,否则其大小必须等于 Replace

11. Skip

Type: plist integer
Failsafe: 0
Description: 在替换前要跳过的发现事件数。

5.5 Quirks 属性

2. AllowRelocationBlock

Type: plist boolean
Failsafe: false
Description: 允许通过重定位块来启动 macOS。

重定位块(Relocation Block)是一个分配在低位 4GB 内存的缓冲区。EfiBoot 使用该这部分内存加载内核和相关结构,否则这部分区块会被「非运行时」数据(假定)所占用。在内核启动之前,重定位块的内容会被复制回位于低位的保留内存。同理,所有指向重定位块的其他内存地址也会作出相应调整。在下述情况中重定位块会被使用:

  • 没有更好的 slide(所有内存都被使用了)
  • 强制 slide=0(通过参数或安全模式设置)
  • 不支持 KASLR (slide)(macOS 10.7 及更旧的版本)

这个 Quirk 需要同时启用 ProvideCustomSlide(必需)和 AvoidRuntimeDefrag(通常情况下)。使用重定位块启动时不支持休眠(但启用这个 Quirk 并不意味着总是使用重定位块)。

:虽然某些低层内存被占用的平台需要这个 Quirk 来运行旧版 macOS 系统,但是这个 Quirk 并不兼容某些硬件及 macOS 11。这种情况下可能需要用 EnableSafeModeSlide 来替代。

2. AvoidRuntimeDefrag

Type: plist boolean
Failsafe: false
Description: 防止 boot.efi 运行时执行内存碎片整理。

这个选项通过提供对可变存储的支持,修复了包括日期、时间、NVRAM、电源控制等 UEFI Runtime 服务。

:除 Apple 和 VMware 固件外,都需要启用此选项。

3. DevirtualiseMmio

Type: plist boolean
Failsafe: false
Description: 从选定的 MMIO 区域中删除 Runtime 属性。

通过删除已知内存区域的 Runtime bit,此选项可减少内存映射中 Stolen Memory Footprint。 这个 Quirk 可能会使可用的 KASLR slide 增加,但如果没有其他措施,则不一定与目标主板兼容。 通常,这会释放 64 到 256 MB 的内存(具体数值会显示在调试日志中)。在某些平台上这是引导 macOS 的唯一方法,否则在引导加载程序阶段会出现内存分配错误。

该选项通常对所有固件都有用,除了一些非常古老的固件(例如 Sandy Bridge)。在某些固件上,可能需要一个例外映射列表。为了使 NVRAM 和休眠功能正常工作,获取其虚拟地址仍然是必要的。 请参考 MmioWhitelist 章节来实现。

译者注:对于某些 300 系列主板是必须的

4. DisableSingleUser

Type: plist boolean
Failsafe: false
Description: 禁用 Apple 单用户模式。

这个选项可以禁用 CMD+S 热键和 -s 启动参数来限制单用户模式。启用这一 Quirk 后预期行为应和 T2 的机型行为类似。请参考 Apple 的 这篇文章(译者注:原文章已被关闭,此为网站时光机的存档副本)以了解如何在启用这一 Quirk 后继续使用单用户模式。

5. DisableVariableWrite

Type: plist boolean
Failsafe: false
Description: 防止 macOS 获取 NVRAM 的写入权限。

这个选项可以限制 macOS 对 NVRAM 的写入。这个 Quirk 需要 OpenRuntime.efi(原名 FwRuntimeServices.efi)提供了 OC_FIRMWARE_RUNTIME 协议的实现。

:这个 Quirk 也可以避免由于无法将变量写入 NVRAM 而导致的对操作系统的破坏。

译者注:在 Z390/HM370 等没有原生 macOS 支持 NVRAM 的主板上需要开启。

6. DiscardHibernateMap

Type: plist boolean
Failsafe: false
Description: 复用原始的休眠内存映射。

这一选项强制 XNU 内核忽略新提供的内存映射、认定设备从休眠状态唤醒后无需对其更改。如果你在使用 Windows,则 务必启用 这一选项,因为 Windows 要求 S4 唤醒后保留运行内存的大小和位置。

:这可能用于解决较旧硬件上的错误内存映射。如 Insyde 固件的 Ivy Bridge 笔记本电脑,比如 Acer V3-571G。除非您完全了解这一选项可能导致的后果,否则请勿使用此功能。

7. EnableSafeModeSlide

Type: plist boolean
Failsafe: false
Description: 修补引导加载程序以在安全模式下启用 KASLR。

这个选项与启动到安全模式(启动时按住 Shift 或用了 -x 启动参数)有关。默认情况下,安全模式会使用 slide=0,这个 Quirk 会试图通过修补 boot.efi 解除这一限制。只有当 ProvideCustomSlide 启用后才可以启用本 Quirks。

:除非启动到安全模式失败,否则不需要启用此选项。

8. EnableWriteUnprotector

Type: plist boolean
Failsafe: false
Description: 关闭 CR0 寄存器中的写入保护。

这个选项会在 UEFI Runtime Services 执行过程中,删除 CR0 寄存器中的写保护 WP bit,从而绕过其代码页的 RX 权限。这个 Quirk 需要配合 OpenRuntime.efi(原 FwRuntimeServices.efi)里的 OC_FIRMWARE_RUNTIME 协议来实现。

:这个 Quirk 可能会破坏你的固件的安全性。如果你的固件支持内存属性表 (MAT),请优先使用下文中的 RebuildAppleMemoryMap Quirk。是否支持 MAT,请参考 OCABC: MAT support is 1/0 日志条目来确定。

9. ForceExitBootServices

Type: plist boolean
Failsafe: false
Description: 在失败时用新的内存映射(Memory Map)重试 ExitBootServices

开启后会确保 ExitBootServices 即使在 MemoryMap 参数过期时也能调用成功,方法主要是获取当前的内存映射,并重试调用 ExitBootServices

:是否启用这个 Quirk 取决于你是否遇到了 Early Boot 故障。除非你详细了解这一选项可能导致的后果,否则请勿启用这一选项。

10. ProtectMemoryRegions

Type: plist boolean
Failsafe: false
Description: 保护内存区域免于不正确的读写。

有些固件会错误映射内存区域:

  • CSM 区域会被标记为引导服务的代码或数据,从而成为 XNU 内核的空闲内存。
  • MMIO 区域会被标记为预留内存,保持不被映射的状态,但在运行时可能需要在 NVRAM 的支持下才能访问。

这一 Quirk 会尝试修复这些区域的类型,比如用 ACPI NVS 标记 CSM,MMIO 标记 MMIO。

:是否启用这一 Quirk 取决于你是否遇到了休眠、睡眠无法唤醒、启动失败或其他问题。一般来说,只有古董固件才需要启用。

11. ProtectSecureBoot

Type: plist boolean
Failsafe: false
Description: 保护 UEFI 安全启动变量不被写入。

尝试从操作系统写入 dbdbxPKKEK 时生成报告。

:这个 Quirk 主要试图避免碎片整理导致的 NVRAM 相关问题,如 Insyde 或 MacPro5,1

12. ProtectUefiServices

Type: plist boolean
Failsafe: false
Description: 保护 UEFI 服务不被固件覆盖。

某些现代固件(包括硬件和 VMware 之类的虚拟机)可能会在加载驱动及相关操作的过程中,更新 UEFI 服务的指针。这一行为会直接破坏其他影响内存管理的 Quirk,如 DevirtualiseMmioProtectMemoryRegions,或 RebuildAppleMemoryMap;也可能会破坏其他 Quirk,具体取决于 Quirk 的作用。

:在 VMware 上,是否需要开启这个 Quirk 取决于是否有 Your Mac OS guest might run unreliably with more than one virtual core. 这样的消息。

13. ProvideCustomSlide

Type: plist boolean
Failsafe: false
Description: 为低内存设备提供自定义 KASLR slide 值。

开启这个选项后,将会对固件进行内存映射分析,检查所有 slide(从 1255)中是否有可用的。由于 boot.efi 私用 rdrand 或伪随机 rdtsc 随机生成此值,因此有可能出现冲突的 slide 值被使用并导致引导失败。如果出现潜在的冲突,这个选项将会强制为 macOS 选择一个伪随机值。这同时确保了 slide= 参数不会被传递给操作系统。

:OpenCore 会自动检查是否需要启用这一选项。如果 OpenCore 的调试日志中出现 OCABC: Only N/256 slide values are usable! 则请启用这一选项。

14. ProvideMaxSlide

Type: plist integer
Failsafe: 0
Description: 当更大的 KASLR slide 值不可用时,手动提供最大 KASLR slide 值。

ProvideCustomSlide 启用时,该选项通过用户指定的 1254(含)之间的值来覆盖上限为 255 的最大 slide 值。较新的固件会从上到下分配内存池中的内存,导致扫描 slide 时的空闲内存被当作内核加载时的临时内存来使用。如果这些内存不可用,启用这个选项则不会继续评估更高的 slide 值。

:当 ProvideCustomSlide 启用、并且随机化的 slide 落入不可用的范围时,如果出现随机的启动失败,则有必要开启这个 Quirk。开启 AppleDebug 时,调试日志通常会包含 AAPL: [EB|‘LD:LKC] } Err(0x9) 这样的信息。如果要找到最合适的值,请手动将 slide=X 追加到 boot-args 里,并用日志记录下不会导致启动失败的最大值。

15. RebuildAppleMemoryMap

Type: plist boolean
Failsafe: false
Description: 生成与 macOS 兼容的内存映射。

Apple 内核在解析 UEFI 内存映射时有几个限制:

  • 内存映射的大小不能超过 4096 字节,因为 Apple 内核将其映射为一个 4 KiB 页面。由于某些固件的内存映射大小非常大(大约超过 100 个条目),Apple 内核会在启动时崩溃。
  • 内存属性表会被忽略。EfiRuntimeServicesCode 内存静态获得 RX 权限,其他内存类型则获得 RW 权限。某些固件驱动会在运行时把数据写到全局变量中,因此 Apple 内核在调用 UEFI Runtime Services 时会崩溃,除非驱动的 .data 部分有 EfiRuntimeServicesData 类型。

为了解决这些限制,这个 Quirk 将内存属性表的权限应用到传递给 Apple 内核的内存映射中,如果生成的内存映射超过 4KiB,则可选择尝试统一类似类型的连续插槽。

注 1:由于许多固件自带的内存保护不正确,所以这个 Quirk 一般要和 SyncRuntimePermissions 一起启用。

注 2:根据是否遇到第一阶段启动失败再决定是否启用这一 Quirk。在支持内存属性表 (MAT) 的平台上,这一 Quirk 是 EnableWriteUnprotector 更好的替代。在使用 OpenDuetPkg 时一般是不需要启用这个 Quirk 的,但如果要启动 macOS 10.6 或更早的版本则可能需要启用,原因暂不明确。

16. SetupVirtualMap

Type: plist boolean
Failsafe: false
Description: 将 SetVirtualAddresses 调用修复为虚拟地址。

选择让固件在调用 SetVirtualAddresses 后通过虚拟地址访问内存,可能会导致 Early Boot 故障。这个 Quirk 可通过对分配的虚拟地址和物理内存进行 Early Boot 身份映射来解决这个问题。

:是否启用这个 Quirk 取决于你是否遇到了 Early Boot 故障。目前具有内存保护支持的新固件(例如 OVMF )由于一些原因不支持此 Quirk: acidanthera/bugtracker#719。

17. SignalAppleOS

Type: plist boolean
Failsafe: false
Description: 不论使用什么操作系统,总是向 OS Info 报告启动的是 macOS。

Mac 设备在不同的操作系统中具有不同的行为,因此如果你在使用 Mac 设备,这一功能会非常有用。例如,你可以通过启用这一选项为某些双 GPU 的 MacBook 型号中在 Windows 和 Linux 中启用 Intel GPU。

18. SyncRuntimePermissions

Type: plist boolean
Failsafe: false
Description: 更新运行时环境的内存权限。

某些固件无法正确处理运行时权限,表现为:

  • OpenRuntime 在内存映射中错误地标记为不可执行。
  • OpenRuntime 在内存属性表中错误的标记为不可执行。
  • OpenRuntime 加载之后丢失内存属性表中的条目。
  • 把内存属性表中的项目标记为 read-write-execute。

这个 Quirk 会通过更新内存映射和内存属性表来纠正这一问题。

:是否开启这一 Quirk 取决于是否遇到 Early Boot 故障。一般来说,只有 2017 年以后发布的固件才会受到影响。

DeviceProperties

6.1 简介

设备相关配置通过专用的缓存区(EfiDevicePathPropertyDatabase)提供给 macOS,这个缓冲区是设备路径到属性名称与值的键值对的序列化映射。

属性相关数据可以使用 gfxutil 进行调试。在 macOS 下获取当前属性数据请使用 ioreg

ioreg -lw0 -p IODeviceTree -n efi -r -x | grep device-properties |sed 's/.*<//;s/>.*//' > /tmp/device-properties.hex &&gfxutil /tmp/device-properties.hex /tmp/device-properties.plist &&cat /tmp/device-properties.plist

设备属性属于 macOS IO Registry 中的 IODeviceTree(gIODT) 层面,这个层面有很多与平台初始化相关的构建阶段(Construction Stage)。尽管早期的构建阶段是由 XNU 内核用 IODeviceTreeAlloc Method 来执行的,绝大部分仍然是由 Platform Expert 来构建、用 AppleACPIPlatformExpert.kext 来实现的。

AppleACPIPlatformExpert 包含了两个阶段的 IODeviceTree 构建,通过调用AppleACPIPlatformExpert::mergeDeviceProperties 来实现:

  1. 在 ACPI 表初始化过程中,通过调用 AppleACPIPlatformExpert::createDTNubs 递归扫描 ACPI 命名空间。
  2. 在 IOService 注册(IOServices::registerService)回调过程中,作为 AppleACPIPlatformExpert::platformAdjustService 函数和它私有的、针对 PCI 设备的 Worker Method AppleACPIPlatformExpert::platformAdjustPCIDevice 的一部分。

各阶段的应用取决于 ACPI 表中存在的设备。第一阶段适用于很早、但只适用于存在于 ACPI 表中的设备。第二阶段适用于所有晚于 PCI 配置的设备,如果设备没有出现在 ACPI 中,则会重复第一阶段。

所有的内核驱动可以在不探测设备的情况下检查 IODeviceTree 层面(例如 Lilu 和它的插件 WhateverGreen 等),因此确保 ACPI 表中的设备存在是尤其重要的。如果不这样做,则可能会因为注入的设备属性被忽略而导致各种不稳定的行为,原因是它们没有在第一阶段被构建出来。参见 SSDT-IMEI.dslSSDT-BRG0.dsl 的例子。

6.2 属性列表

1. Add

Type: plist dict
Description: 将设备属性从设备路径的映射(plist dict)设置为变量名称和值的映射(plist dict),其中变量名称和值的格式为 plist metadata。设备路径必须以规范化字符串格式(Canonical String Format)提供,例如: PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)。添加的属性只有在不存在且未被屏蔽的情况下才会被设置。

:目前,属性只能通过原始驱动程序添加。因此除非安装了单独的驱动程序,否则没有理由 Delete 变量。

2. Delete

Type: plist dict
Description: 从设备路径的映射(plist dict)到 plist string 格式的变量名数组(数据类型 plist array)中删除设备属性。

译者注:这里的设置等同于 Clover 里的 ACPI 重命名 _DSM → XDSM => TgtBridge

6.3 常见属性

一些常见的属性包括:

  • device-id
    用户指定的设备标识符,用于 I/O 套件匹配。数据类型为 4 byte data。
  • vendor-id
    用户指定的供应商标识符,用于 I/O 套件匹配。数据类型为 4 byte data。
  • AAPL,ig-platform-id
    Intel GPU 缓冲帧标识符,用于在 Ivy Bridge 上选择缓冲帧区域。数据类型为 4 byte data。
  • AAPL,snb-platform-id
    Intel GPU 缓冲帧标识符,用于在 Sandy Bridge 上选择缓冲帧区域。数据类型为 4 byte data。
  • layout-id
    AppleHDA 的音频布局,4 byte data。

Kernel

7.1 简介

本章节介绍了如何在 Apple Kernel(XNU)上应用各种不同的内核空间修改,包括内核驱动程序(Kext)注入、修补以及屏蔽。

7.2 属性列表

1. Add

Type: plist array
Failsafe: Empty
Description: 从 OC/Kexts 目录加载选定的 Kext 驱动。

设计为使用 plist dict 数据填充以描述每个驱动程序。请参阅下述 Add 属性章节。Kext 驱动程序加载的顺序遵照数组中项目的顺序,因此如 Lilu 这种其他驱动程序的依赖驱动应该位于前面。

可以通过检查 Kext 驱动中 Info.plistOSBundleLibraries 值的方法来确定其依赖驱动的加载顺序。OSBundleLibraries 中的任何依赖驱动都必须在此 Kext 之前加载。

:Kext 驱动的内部可能也附带另外的 Kext (Plug-Ins),每个内部的 Kext 也都必须单独添加(参考下文 Add 属性章节)。

2. Block

Type: plist array
Failsafe: Empty
Description: 从 Prelinked Kernel 中移除选定的 Kext。

设计为使用 plist dict 数据填充以描述每个驱动程序。请参阅下述 Block 属性章节。Kext 驱动程序加载的顺序遵照数组中项目的顺序,因此如 Lilu 这种其他驱动程序的依赖驱动应该位于前面。

3. Emulate

Type: plist dict
Description: 在内核空间中仿真选定的硬件。请参考下文 Emulate 属性。

4. Force

Type: plist array
Failsafe: Empty
Description: 如果内核驱动没有被缓存,则从系统卷宗强制加载内核驱动。

设计为使用 plist dict 值来填充,用于描述驱动程序。参见下面的 Force 属性部分。依赖其他驱动的驱动程序不能被缓存,该部分着重解决了这种驱动程序注入的难点。这个问题会映像到旧的操作系统,在旧的操作系统中存在各种依赖性的 Kext,比如 IOAudioFamilyIONetworkingFamily,可能默认不存在于内核缓存中。内核驱动的加载是有顺序的,因此依赖驱动应该排在前面。Force 发生在 Add

:「强制加载」的内核驱动不会被检查,因此,使用安全启动的同时使用这个功能是不可取的。另外,这个功能可能无法在较新的操作系统的加密分区上工作。

5. Patch

Type: plist array
Failsafe: Empty
Description: 在添加和删除驱动程序步骤之前执行的对现有 Kext 驱动程序的二进制修补。

设计为使用 plist dictionary 数据填充以描述每个驱动程序。请参阅下述 Patch 属性章节。

6. Quirks

Type: plist dict
Description: 应用下面的 Quirks 属性章节中描述的各个内核和驱动程序 Quirk。

7. Scheme

Type: plist dict
Description: 通过参数来定义内核空间的操作模式,具体参数见下面 Scheme 属性部分的描述。

7.3 Add 属性

1. Arch

Type: plist string
Failsafe: Any
Description: Kext 架构(Any, i386, x86_64)。

2. BundlePath

Type: plist string
Failsafe: Empty string
Description: Kext 相对于 EFI/OC/kexts/Other/ 的路径,如 Lilu.kextMyKext.kext/Contents/PlugIns/MySubKext.kext

译者注:如 VoodooPS2Controller.kext 这种包括其他 Kext 驱动的,需要分别单独添加,如 VoodooPS2Controller.kext/Contents/PlugIns/VoodooPS2Keyboard.kext

3. Comment

Type: plist string
Failsafe: Empty string
Description: 用于为条目提供人类可读参考的任意 ASCII 字符串(译者注:即注释)。

4. Enabled

Type: plist boolean
Failsafe: false
Description: 是否加载该驱动。

5. ExecutablePath

Type: plist string
Failsafe: Empty string
Description: Kext 中实际可执行文件的路径(如 Lilu.kext 中的可执行文件路径是 Contents/MacOS/Lilu)。

译者注:空壳 Kext 没有可执行文件(如 USBPorts.kext),此项留空即可。

6. MaxKernel

Type: plist string
Failsafe: Empty string
Description: 在小于等于指定的 macOS 版本中添加该 Kext 驱动程序。

你可以使用 uname -r 指令获取当前内核版本,一般为三个整数、中间由半角局点分隔,如 18.7.0 代表的是 10.14.6。OpenCore 对内核版本解释的实现方式如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-55s6AWeV-1655985958727)(/img/7-1.svg)]

内核版本比较的实现如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dyUI563m-1655985958732)(/img/7-2.svg)]

将 Darwin 内核版本号字符串从左到右以 . 符号作为分隔符分割成三个整数,即为 ParseDarwinVersion 的三个参数。FindDarwinVersion 函数将会通过在内核镜像中查找形如 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Vg6OVVh-1655985958734)(/img/7-3.svg)] 的字符串来定位 Darwin 内核版本号。

7. MinKernel

Type: plist string
Failsafe: Empty string
Description: 在大于等于指定的 macOS 版本中添加该 Kext 驱动程序。

:匹配逻辑请参阅 Add MaxKernel 的描述。

译者注:以上两个属性定义了这个驱动将在什么版本范围的 macOS 中加载。留空表示在所有的 macOS 版本下都加载。

8. PlistPath

Type: plist string
Failsafe: Empty string
Description: Kext 中 Info.plist 文件的路径。一般为 Contents/Info.plist

7.4 Block 属性

1. Arch

Type: plist string
Failsafe: Any
Description: Kext block 架构(Any, i386, x86_64)。

2. Comment

Type: plist string
Failsafe: Empty string
Description: 用于为条目提供人类可读参考的任意 ASCII 字符串(译者注:即注释)。

3. Enabled

Type: plist boolean
Failsafe: false
Description: 除非设置为 true,否则这个内核驱动不会被加载。

4. Identifier

Type: plist string
Failsafe: Empty string
Description: Kext Bundle 标识符(比如 com.apple.driver.AppleTyMCEDriver)。

5. MaxKernel

Type: plist string
Failsafe: Empty string
Description: 在小于等于指定的 macOS 版本中阻止 Kext 驱动程序。

:匹配逻辑请参阅 Add MaxKernel 的描述。

6. MinKernel

Type: plist string
Failsafe: Empty string
Description: 在大于等于指定的 macOS 版本中阻止 Kext 驱动程序。

:匹配逻辑请参阅 Add MaxKernel 的描述。

7.5 Emulate 属性

1. Cpuid1Data

Type: plist data, 16 bytes
Failsafe: All zero
Description: EAXEBXECXEDX 值的序列,用来取代 XNU 内核中的 CPUID (1) 调用。

该属性主要应用于以下三种需求:

  • 对不支持的 CPU 型号启用支持(比如英特尔的奔腾处理器)。
  • 对特定 macOS 版本(通常是旧版)不支持的 CPU 型号启用支持。
  • 对不支持的 CPU Variant 启用 XCPM 支持。

注 1:还有一种可能的情况,即 CPU 型号是支持的,但其电源管理不支持(比如虚拟机)。在这种情况下,可以通过设置 MinKernelMaxKernel 来限制特定 macOS 内核版本的 CPU 虚拟化和虚拟电源管理补丁。

注 2:通常来讲只需要处理 EAX 的值,因为它代表完整的 CPUID。剩余的字节要留为 0。字节顺序是小端字节序(Little Endian),比如 C3 06 03 00 代表 CPUID 0x0306C3 (Haswell)。

注 3:推荐使用下面的组合启用 XCPM 支持:

  • Haswell-E (0x0306F2) to Haswell (0x0306C3):
    Cpuid1Data: C3 06 03 00 00 00 00 00 00 00 00 00 00 00 00 00
    Cpuid1Mask: FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00
  • Broadwell-E (0x0406F1) to Broadwell (0x0306D4):
    Cpuid1Data: D4 06 03 00 00 00 00 00 00 00 00 00 00 00 00 00
    Cpuid1Mask: FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00

注 4:请记住,目前以下配置不被 XCPM 兼容(至少还没有人成功过):

  • 消费级的 Ivy Bridge(0x0306A9),因为苹果针对它禁用了 XCPM 并推荐用户使用传统的电源管理。如果要使用这一选项,你还需要手动添加 _xcpm_patch 二进制修补以强制启用 XCPM。
  • 低端处理器(如基于 Haswell 或更新架构奔腾处理器),因为它们不被 macOS 支持。如果要启用这些 CPU 请参阅 acidanthera/bugtracker#365 中的 Special NOTES 相关内容。

2. Cpuid1Mask

Type: plist data, 16 bytes
Failsafe: All zero
Description: Cpuid1Data 中激活的 bit 的位掩码。

当每个 Cpuid1Mask bit 都设置为 0 时将使用原始的 CPU bit,否则取 Cpuid1Data 的值。

3. DummyPowerManagement

Type: plist boolean
Failsafe: false
Requirement: 10.4
Description: 禁用 AppleIntelCpuPowerManagement

注 1:这一选项旨在替代 NullCpuPowerManagement.kext,用于 macOS 中没有相应电源管理驱动程序的 CPU。

注 2:虽然通常只有不支持的平台才需要启用这个选项来禁用 AppleIntelCpuPowerManagement,但是如果想要禁用这个 Kext 本身而不考虑其他情况(比如 Cpuid1Data 留空),也依然可以启用这个选项。

4. MaxKernel

Type: plist string
Failsafe: Empty string
Description: 模拟 CPUID,并在指定的或更低的 macOS 版本上使用 DummyPowerManagement

:匹配逻辑请参阅 Add MaxKernel 的描述。

5. MinKernel

Type: plist string
Failsafe: Empty string
Description: 模拟 CPUID,并在指定的或更高的 macOS 版本上使用 DummyPowerManagement

:匹配逻辑请参阅 Add MaxKernel 的描述。

7.6 Force 属性

1. Arch

Type: plist string
Failsafe: Any
Description: Kext 架构(Any, i386, x86_64)。

2. BundlePath

Type: plist string
Failsafe: Empty
Description: Kext 路径,如 System/Library/Extensions/IONetworkingFamily.kext

3. Comment

Type: plist string
Failsafe: Empty string
Description: 用于为条目提供人类可读参考的任意 ASCII 字符串(译者注:即注释)。

4. Enabled

Type: plist boolean
Failsafe: false
Description: 是否加载该驱动。

5. ExecutablePath

Type: plist string
Failsafe: Empty string
Description: Kext 中实际可执行文件的路径,如 Contents/MacOS/IONetworkingFamily

6. Identifier

Type: plist string
Failsafe: Empty string
Description: Kext 标识符,以便在添加前检查是否存在,如 com.apple.iokit.IONetworkingFamily。只有在缓存中找不到标识符的驱动程序才会被添加。

7. MaxKernel

Type: plist string
Failsafe: Empty string
Description: 在小于等于指定的 macOS 版本中添加 Kext 驱动程序。

:匹配逻辑请参阅 Add MaxKernel 的描述。

8. MinKernel

Type: plist string
Failsafe: Empty string
Description: 在大于等于指定的 macOS 版本中添加 Kext 驱动程序。

:匹配逻辑请参阅 Add MaxKernel 的描述。

9. PlistPath

Type: plist string
Failsafe: Empty string
Description: Kext 中 Info.plist 文件的路径。一般为 Contents/Info.plist

7.7 Patch 属性

1. Arch

Type: plist string
Failsafe: Any
Description: Kext patch 架构(Any, i386, x86_64)。

2. Base

Type: plist string
Failsafe: Empty string
Description: 通过获取所提供的 Symbol 名称的地址,来选择 Symbol 匹配的 Base 进行补丁查找(或直接替换)。可以设置为空字符串以忽略。

3. Comment

Type: plist string
Failsafe: Empty string
Description: 用于为条目提供人类可读参考的任意 ASCII 字符串(译者注:即注释)。

4. Count

Type: plist integer
Failsafe: 0
Description: 修补的次数,超过这一次数后便不再修补。0 表示修补所有查找到的地方。

5. Enabled

Type: plist boolean
Failsafe: false
Description: 除非设置为 true,否则不对内核进行该修补。

6. Find

Type: plist data
Failsafe: Empty data
Description: 需要查找的数据。可留空,在 Base 处直接替换。若不留空,其大小必须等于 Replace

7. Identifier

Type: plist string
Failsafe: Empty string
Description: Kext Bundle 标识符(如 com.apple.driver.AppleHDA)或内核补丁的 kernel

8. Limit

Type: plist integer
Failsafe: 0
Description: 搜索的最大字节数。可以设置为 0 来查找整个 Kext 或内核。

9. Mask

Type: plist data
Failsafe: Empty data
Description: 在查找比较的过程中使用数据位掩码。允许通过忽略未被屏蔽的 bit(设置为 0)进行模糊搜索。若留空则代表忽略,否则其大小必须等于 Replace

10. MaxKernel

Type: plist string
Failsafe: Empty string
Description: 在指定的或更早的 macOS 版本上打补丁。

:匹配逻辑请参阅 Add MaxKernel 的描述。

11. MinKernel

Type: plist string
Failsafe: Empty string
Description: 在指定的或更新的 macOS 版本上打补丁。

:匹配逻辑请参阅 Add MaxKernel 的描述。

12. Replace

Type: plist data
Failsafe: Empty data
Description: 一个或多个字节的替换数据。

13. ReplaceMask

Type: plist data
Failsafe: Empty data
Description: 替换时使用的数据位掩码。允许通过更新掩码(设置为非 0)来进行模糊替换。若留空则代表忽略,否则其大小必须等于 Replace

14. Skip

Type: plist integer
Failsafe: 0
Description: 在替换前要跳过的发现事件数。

7.8 Quirks 属性

1. AppleCpuPmCfgLock

Type: plist boolean
Failsafe: false
Requirement: 10.4
Description: 禁用 AppleIntelCPUPowerManagement.kext 中的 PKG_CST_CONFIG_CONTROL (0xE2) 修改,从而避免早期 Kernel Panic。

某些固件会锁定 PKG_CST_CONFIG_CONTROL MSR 寄存器。可以使用附带的 VerifyMsrE2 工具检查其状态。

由于现代固件已经提供了 CFG Lock 相关设置、从而可以配置 PKG_CST_CONFIG_CONTROL 寄存器锁定,此选项应该尽可能避免。对于一些不显示 CFG Lock 配置的固件,可以按照下述配置进行修改:

  1. 下载 UEFITool 和 IFR-Extractor
  2. 使用 UEFITool 中打开固件镜像文件,找到 CFG Lock 的 Unicode 字符串。如果你没有找到,意味着你的固件可能不支持 CFG Lock 解锁,那么你现在可以停下来了。
  3. 从 UEFITool 菜单中的 Extract Body 选项提取 Setup.bin 中的 PE32 镜像部分。
  4. 对提取出来的文件执行 IFR-Extractor(./ifrextract Setup.bin Setup.txt)。
  5. 从 Setup.txt 中找到 CFG Lock, VarStoreInfo (VarOffset/VarName):,记住紧随其后的偏移量值(例如 0x123)。
  6. 下载并执行由 brainsucker 编译的 修改版 GRUB Shell。你也可以使用 datasone 制作的 新版 GRUB Shell。
  7. 在 GRUB Shell 中,使用 setup_var 0x123 0x00(其中 0x123 应该被替换为你在前几步找到的偏移值),然后重启电脑。

{% note danger 警告 %}
可变偏移量对于每个主板乃至每一个固件版本都是唯一的。永远不要尝试使用别人的偏移量!
{% endnote %}

2. AppleXcpmCfgLock

Type: plist boolean
Failsafe: false
Requirement: 10.8 (not required for older)
Description: 禁用 XNU 内核对 PKG_CST_CONFIG_CONTROL (0xE2) 修改,从而避免早期 Kernel Panic。

:这一选项应该避免被使用,请参考上文中关于 AppleCpuPmCfgLock 的介绍。

3. AppleXcpmExtraMsrs

Type: plist boolean
Failsafe: false
Requirement: 10.8 (not required for older)
Description: 对于没有 XCMP 支持的设备,禁用对选定 CPU 的多 MSR 访问。

通常将其与 Haswell-E,Broadwell-E,Skylake-SP 和类似 CPU 的 Emulate 结合使用。更多关于 XCPM 修补的信息可以在 acidanthera/bugtracker#365 找到。

:Ivy Bridge 或 Pentium CPU 将需要其他未提供的补丁。建议对前者使用 AppleIntelCpuPowerManagement.kext

4. AppleXcpmForceBoost

Type: plist boolean
Failsafe: false
Requirement: 10.8 (not required for older)
Description: 在 XCPM 模式下强制使用最大性能。

该补丁将 0xFF00 写入 MSR_IA32_PERF_CONTROL (0x199),有效地做到了一直保持最大倍数。

:尽管有助于提高性能,但是在所有操作系统上都强烈建议不要启用这一选项。只有在某些 Xeon 型号的 CPU 才有可能从这个选项中受益。

5. CustomSMBIOSGuid

Type: plist boolean
Failsafe: false
Requirement: 10.4
Description: 对 UpdateSMBIOSMode 自定义模式执行 GUID 修补,通常用于戴尔笔记本电脑。

6. DisableIoMapper

Type: plist boolean
Failsafe: false
Requirement: 10.8 (not required for older)
Description: 禁用 XNU (VT-d) 中的 IOMapper 支持,这可能与固件的实现相冲突。

:相比直接在 ACPI 表中删除 DMAR,我们更推荐大家使用这一选项。这样不会破坏其他操作系统中的 VT-d 支持(总会有人需要用到的,对吧?)。

7. DisableLinkeditJettison

Type: plist boolean
Failsafe: false
Requirement: 11.0
Description: 禁止丢弃 __LINKEDIT

这个选项能让 Lilu.kext 和其他一些功能在 macOS Big Sur 中以最佳性能运行,而不需要 keepsyms=1 启动参数。

8. DisableRtcChecksum

Type: plist boolean
Failsafe: false
Requirement: 10.4
Description: 禁用 AppleRTC 初始校验和(0x58 - 0x59)写入。

注 1:这个选项不能确保其他区域不被覆盖,如有需要,请使用 RTCMemoryFixup。

注 2:这个选项不能确保区域在固件阶段不被覆盖(例如 macOS bootloader)。如有需要,请参阅 AppleRtcRam 协议描述。

9. ExtendBTFeatureFlags

Type: plist boolean
Failsafe: false
Requirement: 10.8
Description: 将 FeatureFlags 设置为 0x0F,以实现蓝牙的全部功能(包括连续互通功能)。

:由于原先的 BT4LEContinuityFixup.kext 的补丁过程较迟而不起作用,因此合并至 OpenCore 来替代 BT4LEContinuityFixup.kext

10. ExternalDiskIcons

Type: plist boolean
Failsafe: false
Requirement: 10.4
Description: 修补 AppleAHCIPort.kext 图标,使 macOS 将所有 AHCI 存储设备显示为内部硬盘。

:这一选项应尽量避免使用。现代固件通常情况下都是兼容的。

11. ForceSecureBootScheme

Type: plist boolean
Failsafe: false
Requirement: 11
Description: 强制采用 x86 方案进行 IMG4 核查。

:在虚拟机上使用 x86legacy 以外的 SecureBootModel 时需要开启此选项。

12. IncreasePciBarSize

Type: plist boolean
Failsafe: false
Requirement: 10.10
Description: 将 IOPCIFamily 中 32 位 PCI Bar 的大小从 1 GB 增加到 4 GB。

:你应该尽可能避免使用这一选项。通常这一选项只需要在配置错误或损坏的固件上开启。

译者注:如果你的 BIOS 中存在 Above4GDecoding 选项,请直接在 BIOS 中启用。

13. LapicKernelPanic

Type: plist boolean
Failsafe: false
Requirement: 10.6 (64-bit)
Description: 禁用 LAPIC 中断导致的 Kernal Panic。

译者注:惠普电脑可能需要启用这一选项。

14. LegacyCommpage

Type: plist boolean
Failsafe: false
Requirement: 10.4 - 10.6
Description: 默认的 64 位 commpage bcopy 的实现需要 SSSE3,这个选项把它替换为「不需要 SSSE3」的实现,这对于不支持 SSSE3 的旧平台很有必要,防止因不存在「不需要 SSSE3 的 64 位 bcopy 函数」而导致的 commpage no match for last Panic。

15. PanicNoKextDump

Type: plist boolean
Failsafe: false
Requirement: 10.13 (not required for older)
Description: 在发生内核崩溃时阻止输出 Kext 列表,提供可供排错参考的崩溃日志。

16. PowerTimeoutKernelPanic

Type: plist boolean
Failsafe: false
Requirement: 10.15 (not required for older)
Description: 修复 macOS Catalina 中由于设备电源状态变化超时而导致的内核崩溃。

macOS Catalina 新增了一项额外的安全措施,导致在电源切换超时的时候会出现 Kernel Panic。配置错误的硬件可能会因此出现问题(如数字音频设备)、有的时候会导致睡眠唤醒的问题。这一 Quirk 和引导参数 setpowerstate_panic=0 功能大部分一致,但是后者只应该用于调试用途。

17. SetApfsTrimTimeout

Type: plist integer
Failsafe: -1
Requirement: 10.14 (not required for older)
Description: 为 SSD 上的 APFS 文件系统设置微秒级的 trim 超时时间。

APFS 文件系统的设计方式是,空间由 Spaceman (The Space Manager) 结构控制,要么为已使用,要么为空闲。而其他文件系统,则可以被标记为 已使用、空闲 或 未映射。macOS 启动时,所有空闲的空间都会被 trim 处理。由于 DSM 命令的特性,每个命令最多拥有 256 个范围,因此 NVMe 驱动器的 trim 过程发生在 LBA 范围内。硬盘上存储的内容越分散,就需要越多的命令对所有空闲空间进行 trim。

Trim 过程耗时取决于 SSD 控制器和硬盘碎片,可能需要相当长的时间,导致启动时间肉眼可见地变长,APFS 驱动程序忽略之前未映射的区域,并在启动时一次又一次地对这些区域进行 trim。为了解决开机速度慢的问题,macOS 驱动引入了一个超时时间(9.999999 秒)来中止未能及时完成的 trim 操作。许多控制器(如三星)解除分配的过程较慢,很容易达到超时时间,也就是说,macOS 会尝试 trim 所有已经解除分配的低位区块,但一旦碎片增加,就再也没有足够的时间去解除分配高位区块了。这意味着这些 SSD 安装后不久,trim 指令就会被破坏,从而造成闪存的额外损耗。

解决这个问题的方法之一是将超时时间设置为一个非常高的值(如 4294967295),这样将会以较长的启动时间(数分钟)为代价来确保所有的区块都被 trim 处理。

另一种方法是利用超额配置(如果支持),或者创建一个专用的未映射分区,控制器可以在该分区中找到保留块。在这种情况下,可以设置一个非常低的超时时间来禁止 trim 操作,例如 999。更多细节详见 这篇文章。

18. ThirdPartyDrives

Type: plist boolean
Failsafe: false
Requirement: 10.6 (not required for older)
Description: 修补 IOAHCIDeleteStorage.kext,以在第三方驱动器启用 TRIM、硬盘休眠等功能。

:NVMe SSD 通常无需这一修改。对于 AHCI SSD(如 SATA SSD),macOS 从 10.15 开始提供 trimforce,可以将 01 00 00 00 值写入 APPLE_BOOT_VARIABLE_GUID 命名空间中的 EnableTRIM 变量。

19. XhciPortLimit

Type: plist boolean
Failsafe: false
Requirement: 10.11 (not required for older)
Description: 修补 AppleUSBXHCI.kextAppleUSBXHCIPCI.kextIOUSBHostFamily.kext 以移除 15 端口限制。

:请尽可能避免使用这一选项。USB 端口数量限制是由 locationID 的 bit 决定的,想要移除限制就需要对操作系统进行大量修改。真正长期有效的解决方案是限制可用的 USB 端口个数在 15 以下(通过 USB 定制的方法)。

7.9 Scheme 属性

这些属性对于旧版 macOS 操作系统尤为重要。更多关于如何安装此类 macOS 及相关排错的详细信息,请参考 旧版 Apple 操作系统。

1. FuzzyMatch

Type: plist boolean
Failsafe: false
Description: 使用校验值不同的 kernelcache(如果可用)。

在 macOS 10.6 和更早的版本中,kernelcache 文件名有一个校验值,本质上是对 SMBIOS 产品名称和 EfiBoot 设备路径进行 adler32 校验和的计算。在某些固件上,由于 ACPI 或硬件的特殊性,UEFI 和 macOS 的 EfiBoot 设备路径不同,使得 kernelcache 的校验和总是不同。

这一设置可以在无后缀的 kernelcache 不可用时,将最新的 kernelcache 与合适的架构进行匹配,从而提高 macOS 10.6 在多个平台上的启动性能。

2. KernelArch

Type: plist string
Failsafe: Auto
Description: 如果可用,优先选择指定的内核架构(Auto, i386, i386-user32, x86_64)。

macOS 10.7 和更早的 XNU 内核可能不会使用 x86_64 架构来启动,具体选择取决于很多因素,包括启动参数、SMBIOS 以及操作系统类型。当 macOS 和配置支持时,该设置将使用指定的架构来启动 macOS:

  • Auto — 自动选择首选的架构。
  • i386 — 如果可用,则使用 i386(32 位)内核。
  • i386-user32 — 在可用的情况下使用 i386(32 位)内核,并在 64 位处理器上强制使用 32 位用户空间(前提是系统支持)。在 macOS 上,64 位处理器会被认为支持 SSSE3 指令集,但对于较老的 64 位奔腾处理器来说,实际情况并非如此,因此会导致一些应用程序在 macOS 10.6 上崩溃。该行为对应 -legacy 内核启动参数。由于 XNU 内核中存在一段未被初始化的 64 位片段,导致 AppleEFIRuntime 错误地将 64 位代码作为 16 位来执行,因此该选项对于 64 位固件上运行的 10.4 和 10.5 系统是不可用的。
  • x86_64 — 如果可用,则使用 x86_64(64 位)内核。

下面是确定内核架构的计算过程:

  1. arch 参数位于映像参数(比如从 UEFI Shell 启动时)或 boot-args 变量中,覆盖兼容性检查,强制指定架构,并完成此计算过程。
  2. 对于 32 位 CPU Variant,OpenCore 会将架构兼容性限制在 i386i386-user32 模式。
  3. 确定 EfiBoot 版本所限制的架构:
    • 10.4-10.5 — i386i386-user32(仅限用于 32 位固件)
    • 10.6 — i386i386-user32x86_64
    • 10.7 — i386x86_64
    • 10.8 及更新的版本 — x86_64
  4. 如果 KernelArch 被设置为 Auto,并且 CPU 不支持 SSSE3 指令集, 则兼容性会被限制为 i386-user32(如果 EfiBoot 支持的话)。
  5. 主板标识符(来自 SMBIOS)基于 EfiBoot 版本,如果有任何 i386 的 CPU Variant 与之兼容,就会在不支持的机型上禁用 x86_64 架构。Auto 不参与这个过程,因为在 EfiBoot 中,该列表是不可覆盖的。
  6. 当没有设置为 Auto 时,KernelArch 会把系统支持限制在明确指定的架构(如果该架构兼容)。
  7. 按以下顺序选择参数可以获得最佳的架构支持:x86_64i386i386-user32

macOS 10.7 只会将特定的主板标识符视为仅 i386 架构的设备,macOS 10.5 或更早版本的内核则不支持 x86_64,而 macOS 10.6 非常特殊,与这二者都不同。macOS 10.6 上的架构选择取决于很多因素,不仅包括主板标识符,还包括 macOS 的类型(客户端 或 服务器端)、macOS 发布时间和内存容量。检测这些因素很复杂,也不实用,因为好几个发布版本都有 bug,不能在第一时间正确地进行服务器检测。因此,对于 macOS 10.6,无论主板支持情况如何,OpenCore 都会回退到 x86_64 架构,就像 macOS 10.7 那样。以下是 64 位 Mac 型号的兼容性介绍,对应于 macOS 10.6.8 和 10.7.5 EfiBoot 的实际行为:

Model 10.6 (minimal) 10.6 (client) 10.6 (server) 10.7 (any)
Macmini 4,x (Mid 2010) 5,x (Mid 2011) 4,x (Mid 2010) 3,x (Early 2009)
MacBook Unsupported Unsupported Unsupported 5,x (2009/09)
MacBookAir Unsupported Unsupported Unsupported 2,x (Late 2008)
MacBookPro 4,x (Early 2008) 8,x (Early 2011) 8,x (Early 2011) 3,x (Mid 2007)
iMac 8,x (Early 2008) 12,x (Mid 2011) 12,x (Mid 2011) 7,x (Mid 2007)
MacPro 3,x (Early 2008) 5,x (Mid 2010) 3,x (Early 2008) 3,x (Early 2008)
Xserve 2,x (Early 2008) 2,x (Early 2008) 2,x (Early 2008) 2,x (Early 2008)

:不支持用热键 3+26+4 来选择偏好架构,这是因为这个热键是由 EfiBoot 处理的,很难正确地检测到。

3. KernelCache

Type: plist string
Failsafe: Auto
Description: 如果可用,优先选择指定的内核缓存(Kernel Cache)类型(Auto, Cacheless, Mkext, Prelinked)。

macOS 的版本不同,支持的内核缓存变量也不同,其目的是提高启动性能。如果出于调试和稳定性的考虑,可利用这个设置防止使用较快的内核缓存变量。举个例子,如果指定 Mkext,那么会为 10.6 禁用 Prelinked,10.7 则不受影响。

可用的内核缓存类型及其当前在 OpenCore 中的支持情况列表如下:

macOS i386 NC i386 MK i386 PK x86_64 NC x86_64 MK x86_64 PK x86_64 KC
10.4 YES YES (V1) NO (V1)
10.5 YES YES (V1) NO (V1)
10.6 YES YES (V2) YES (V2) YES YES (V2) YES (V2)
10.7 YES YES (V3) YES YES (V3)
10.8-10.9 YES YES (V3)
10.10-10.15 YES (V3)
11+ YES (V3) YES

:不支持第一个版本(V1)的 32 位 prelinkedkernel ,因为 Kext 符号表被工具破坏了,这些版本中 Auto 会阻止 prelinkedkernel 启动。同时,这也会使 keepsyms=1 在这些系统上不可用。

Misc

8.1 简介

本部分包含关于 OpenCore 行为的其他配置,以及不能被分类到其它章节的配置条目的说明。

OpenCore 尽可能地遵循 bless 模式,即 Apple Boot Policybless 模式的主要特点是允许在文件系统中嵌入启动选项(而且能通过专门的驱动程序访问),同时,相比于 UEFI 规范中的可移动媒体列表,它还支持更多的预定义启动路径。

只有当分区符合 Scan policy 时才能被启动(Scan policy 是一组限制条件,能够使其仅使用特定文件系统和特定设备类型的分区)。具体的扫描策略(Scan policy)将在下面的 ScanPolicy 属性中阐述。

扫描过程从获取 Scan policy 过滤过的分区开始。每个分区可能会产生多个主选项和备用选项。主选项描述的是安装在这个介质上的操作系统。备用选项描述的是介质上的操作系统的恢复项。备用选项可以在没有主选项的情况下存在,反之亦然。请注意,这些选项描述的操作系统不一定都在同一个分区上。每个主选项和备用选项都可以作为辅助选项(Auxiliary Option),也可以不作为辅助选项,具体细节参考下面的 HideAuxiliary 章节。用来确定启动选项的算法如下:

  1. 通过 Scan policy(和驱动可用性)过滤,获取所有可用的分区句柄。
  2. BootOrder UEFI 变量中,获取所有可用的启动选项。
  3. 对于每个找到的启动选项:
    • 检索该启动选项的设备路径。
    • 执行对设备路径的修复(如 NVMe 子类型修复)和扩展(如 Boot Camp)。
    • 通过定位到所产生的设备路径,来获取句柄(失败时忽略)。
    • 在分区句柄列表中找到设备句柄(缺失时忽略)。
    • 对磁盘设备路径(不指定引导程序)执行 bless(可能返回不止一个条目)。
    • 对文件设备路径直接检查其文件系统。
    • 在 OpenCore 启动分区中,通过 Header Check 排除所有 OpenCore Bootstrap 文件。
    • 如果有分区句柄列表,则在列表中将设备句柄标记为 used
    • 将生成的条目注册为主选项,并确定他们的类型。某些类型的选项作为辅助选项(如 Apple HFS Recovery)。
  4. 对于每个分区句柄:
    • 如果分区句柄被标记为 unused,则执行 bless 主选项列表检索。如果设置了 BlessOverride 列表,那么不仅能找到标准的 bless 路径,还能找到自定义的路径。
    • 在 OpenCore 启动分区中,通过 Header Check 排除所有 OpenCore Bootstrap 文件。
    • 将生成的条目注册为主选项,并确定他们的类型。某些类型的选项作为辅助选项(如 Apple HFS Recovery)。
    • 如果分区已经具有来 Apple Recovery 类型的主选项,则继续处理下一个句柄。
    • 通过 bless 恢复选项列表检索和预定义路径,来查找备用条目。
    • 将生成的条目注册为备用辅助选项,并确定它们的类型。
  5. 把自定义条目和工具添加为主选项,不做有关 Auxiliary 的任何检查。
  6. 把系统条目(如 Reset NVRAM)添加为主要的辅助选项。

启动选择器中的启动选项的显示顺序和启动过程,是通过扫描算法分别来确定的。显示顺序如下:

  • 备用选项跟随主选项,即,Apple Recovery 会尽可能地跟随相关的 macOS 选项。
  • 选项会按照文件系统句柄固件的顺序列出,以便在整个启动过程中保持一个既定的顺序,不因加载操作系统的不同而变化。
  • 自定义条目、工具和系统条目会被添加到所有选项之后。
  • 辅助选项只有在进入「高级模式」后才会显示(一般是按 空格 键)。

启动过程如下:

  • 尝试通过 BootNext UEFI 变量查找第一个有效的主选项。
  • 如果失败,则通过 BootOrder UEFI 变量继续查找。
  • 将该选项标记为默认启动选项。
  • 是否通过启动选择器来启动选项,取决于 ShowPicker 选项的设置。
  • 如果还失败,则显示启动选择器。

注 1:这个过程只有在启用了 RequestBootVarRouting 选项,或者固件不控制 UEFI 启动选项(如 OpenDuetPkg 或其他自定义 BDS)时,才会可靠地工作。如果不启用 LauncherOption,那么其他操作系统有可能会覆盖 OpenCore,如果你打算使用 OpenCore,请确保启用这个选项。

注 2:UEFI 变量引导选项的引导参数,如果存在的话则会被丢弃,因为它们包含的一些参数可能会对操作系统产生不利影响,一旦启用了安全引导,这种影响是我们不希望看到的。

注 3:某些操作系统(说的就是你,Windows)会在第一次启动时,或 NVRAM 重置后,创建他们的启动选项,并将其标记为最上面的选项。这种情况发生时,默认的启动条目选择将会更新,直到下一次重新手动配置。

8.2 属性列表

1. Boot

Type: plist dict
Description: 应用本章节 Boot 属性中的引导相关设置。

2. BlessOverride

Type: plist array
Description: 通过 Bless Model 添加自定义扫描路径。

设计为填充 plist string 条目,其中包含指向自定义引导程序的绝对 UEFI 路径,例如,用于 Debian 引导程序的 \EFI\debian\grubx64.efi。这允许引导选择器自动发现异常的引导路径。在设计上它们等效于预定义的 Bless 路径(如 \System\Library\CoreServices\boot.efi\EFI\Microsoft\Boot\bootmgfw.efi),但与预定义的 Bless 路径不同,它们具有最高优先级。

3. Debug

Type: plist dict
Description: 应用本章节 Debug 属性中的调试相关设置。

4. Entries

Type: plist array
Description: 在开机引导菜单中添加引导项。

应填入 plist dict 类型的值来描述相应的加载条目。详见 Entry 属性部分。

5. Security

Type: plist dict
Description: 应用本章节 Security 属性中的安全相关设置。

6. Tools

Type: plist array
Description: 将工具条目添加到开机引导菜单。

应填入 plist dict 类型的值来描述相应的加载条目。详见 Entry 属性部分。

:选择工具(比如 UEFI shell)是很危险的事情,利用这些工具可以轻易地绕过安全启动链,所以 千万不要 出现在生产环境配置中,尤其是设置了 Vault 和安全启动保护的设备(译者注:即,工具仅作调试用)。具体的工具示例参见本文档的 UEFI 章节。

8.3 Boot 属性

1. ConsoleAttributes

Type: plist integer
Failsafe: 0
Description: 为控制台设置特定的属性。

根据 UEFI 规范,文本渲染器支持的颜色参数为前景色与背景色之和。黑色背景色和黑色前景色 (0) 的值是预留的。以下是颜色名称一览:

  • 0x00EFI_BLACK(黑色字体)
  • 0x01EFI_BLUE(蓝色字体)
  • 0x02EFI_GREEN(绿色字体)
  • 0x03EFI_CYAN(青色字体)
  • 0x04EFI_RED(红色字体)
  • 0x05EFI_MAGENTA(紫色字体)
  • 0x06EFI_BROWN(棕色字体)
  • 0x07EFI_LIGHTGRAY(亮灰色字体)
  • 0x08EFI_DARKGRAY(暗灰色字体)
  • 0x09EFI_LIGHTBLUE(淡蓝色字体)
  • 0x0AEFI_LIGHTGREEN(淡绿色字体)
  • 0x0BEFI_LIGHTCYAN(淡青色字体)
  • 0x0CEFI_LIGHTRED(淡红色字体)
  • 0x0DEFI_LIGHTMAGENTA(淡紫色字体)
  • 0x0EEFI_YELLOW(黄色字体)
  • 0x0FEFI_WHITE(白色字体)
  • 0x00EFI_BACKGROUND_BLACK(黑色背景)
  • 0x10EFI_BACKGROUND_BLUE(蓝色背景)
  • 0x20EFI_BACKGROUND_GREEN(绿色背景)
  • 0x30EFI_BACKGROUND_CYAN(青色背景)
  • 0x40EFI_BACKGROUND_RED(红色背景)
  • 0x50EFI_BACKGROUND_MAGENTA(紫色背景)
  • 0x60EFI_BACKGROUND_BROWN(棕色背景)
  • 0x70EFI_BACKGROUND_LIGHTGRAY(亮灰色背景)

:这个选项可能和 TextRenderer 的 System 参数有冲突,设置一个非黑的背景可以用来测试 GOP 是否正常运行。

2. HibernateMode

Type: plist string
Failsafe: None
Description: 休眠检测模式。 支持以下模式:

  • None — 禁用休眠(推荐)
  • Auto — 从 RTC 或 NVRAM 中检测
  • RTC — 从 RTC 检测
  • NVRAM — 从 NVRAM 检测

:如果固件自身能处理休眠(大多数 Mac 的 EFI 固件都可以),你应该在此处设置为 None 来让固件处理休眠状态并传递给 OpenCore。

3. HideAuxiliary

Type: plist boolean
Failsafe: false
Description: 默认情况下,隐藏开机引导项菜单中的辅助条目。

满足任一以下条件的引导项条目即会被视为「辅助项目」

  • 该引导项是 macOS Recovery 分区
  • 该引导项是 macOS Time Machine 分区
  • 该引导项被标记为 Auxiliary
  • 该引导项是系统提供的(如 Reset NVRAM

即使被隐藏,你仍然可以通过 空格 进入「扩展模式」查看所有条目(引导项菜单会被重新加载):

一般来说,隐藏辅助条目有助于加快启动速度。

4. LauncherOption

Type: plist string
Failsafe: Disabled
Description: 在固件偏好设置中注册启动器选项,以保证 bootloader 的持久与一致性。

有效值有:

  • Disabled — 什么都不做。
  • Full — 在 bootloader 启动时,在 UEFI 变量存储中创建或更新最高优先级的启动项。要使用这个选项,必须同时开启 RequestBootVarRouting
  • Short — 创建一个短的、非完整的启动项。此值对于某些固件很有用,比如 Insyde,或者其他无法处理完整设备路径的固件。
  • System — 不创建启动项,而是认为该项是 blessed 的。This variant is useful when relying on ForceBooterSignature quirk and OpenCore launcher path management happens through bless utilities without involving OpenCore.

在安装和升级第三方操作系统时 \EFI\BOOT\BOOTx64.efi 文件可能会被覆盖掉,该选项则保证了出现覆盖情况时 bootloader 的一致性。创建一个自定义启动项后,\EFI\BOOT\BOOTx64.efi 这个文件路径将不再用于引导 OpenCore。自定义的引导路径在 LauncherPath 选项中指定。

注 1:某些固件的 NVRAM 本身存在问题,可能会出现无启动项支持,或者其他各种不兼容的情况。虽然可能性不大,但使用此选项可能会导致启动失败。请在已知兼容的主板上使用,风险自行考虑。请查看 acidanthera/bugtracker#1222 来了解与 Haswell 及其他一些主板相关的已知问题。

注 2:虽然从 OpenCore 执行的 NVRAM 重置不会清除在 Bootstrap 模式中创建的启动选项,但在加载 OpenCore 之前重置 NVRAM 则会同时清除。在进行某些涉及重要实现的更新时(如 OpenCore 0.6.4),须确保在禁用 Bootstrap 的情况下执行一次 NVRAM 重置,然后再重新启用。

5. LauncherPath

Type: plist string
Failsafe: Default
Description: LauncherOption 的启动引导路径。

Default 用于引导 OpenCore.efi。其他的路径(如 \EFI\Launcher.efi)可用来提供自定义加载器,用于自行加载 OpenCore.efi

6. PickerAttributes

Type: plist integer
Failsafe: 0
Description: 设置开机引导菜单的属性。

可以用属性掩码来设置引导菜单的不同属性,其中掩码包含 OpenCore 的预留值(BIT0 ~ BIT15)和 OEM 特定值(BIT16 ~ BIT31)。

目前 OpenCore 的预留值有:

  • 0x0001OC_ATTR_USE_VOLUME_ICON,为启动项提供自定义图标:

    对于 Tools,OpenCore 会优先加载以下自定义图标,不存在时回退到默认图标:

    • ResetNVRAMResources\Image\ResetNVRAM.icns — 图标目录下的 ResetNVRAM.icns
    • Tools\<TOOL_RELATIVE_PATH>.icns — 与工具文件同目录下的对应图标,扩展名为 .icns

    对于自定义的启动项 Entries,OpenCore 会优先加载以下自定义图标,不存在时回退到卷宗或默认图标:

    • <ENTRY_PATH>.icns — 与启动项文件同目录下的对应图标,扩展名为 .icns

    对于其他条目,OpenCore 会优先加载以下卷宗图标,不存在时回退到默认图标:

    • APFS 卷宗图标的 .VolumeIcon.icns 文件,置于 Preboot 卷宗目录下(如果存在)。
    • APFS 卷宗图标的 .VolumeIcon.icns 文件,置于 Preboot 根目录下(其他情况)。
    • 其他文件系统的 .VolumeIcon.icns 文件,置于其卷宗根目录下。

    卷宗图标可以在访达中设置。注意,启用此功能后可能会难以区分 外部可移除硬盘 和 内部不可移除硬盘 的图标。

    • 0x0002OC_ATTR_USE_DISK_LABEL_FILE,为启动项的标题提供自定义渲染:
    • .disk_label (.disk_label_2x) 文件与 bootloader 文件放在同一目录,适用于所有文件系统。
    • <TOOL_NAME>.lbl (<TOOL_NAME>.l2x) 文件与工具文件放在同一目录,适用于 Tools

    预渲染标签可用 disklabel 实用工具或 bless 命令来生成。当预渲染标签被禁用或者缺失时,将以文本标签 (.contentDetails.disk_label.contentDetails) 来代为渲染。

  • 0x0004OC_ATTR_USE_GENERIC_LABEL_IMAGE,为没有自定义条目的启动项提供预定义的标签图像。可能会缺少实际启动项的详细信息。

  • 0x0008OC_ATTR_HIDE_THEMED_ICONS,优先选择特定图标集的图标,以配合主题风格,比如可以强制显示特定图标集内置的 Time Machine 图标。需要同时启用 OC_ATTR_USE_VOLUME_ICON

  • 0x0010OC_ATTR_USE_POINTER_CONTROL,在启动选择器中启用指针控制。例如,可以利用鼠标或触摸板来控制 UI 元素。

  • 0x0020 - OC_ATTR_SHOW_DEBUG_DISPLAY,在启动选择器中显示额外的时间和调试信息。仅在 Dubug 和 NOOPT 版本的 Builtin picker 中生效。

  • 0x0040 - OC_ATTR_USE_MINIMAL_UI,显示最小化 UI,不显示关机或重启的按钮。在 OpenCanopy 和 Builtin picker 中生效。

  • 0x0080 - OC_ATTR_USE_FLAVOUR_ICON,提供弹性的启动项内容描述,可以在不同的图标集中选择最好的图标:

    当启用的时候,OpenCanopy 中的启动项和 audio assist 项目音频以及 Builtin boot picker 可以被 content flavor 指定。要指定 content flavor,请参考以下规则:

    • 对于一个 Tool 项目,将会从其 Flavour 中读取
    • 对于一个自动发现项目,将会从 bootloader 同目录下的 .contentFlavour 文件中读取(如果有的话)
    • 对于一个自定义项目,如果其 FlavourAuto,则从 bootloader 同目录下的 .contentFlavour 文件中读取,否则由 Flavour 指定
    • 如果读取到的 Flavour 项目为 Auto.contentFlavour 文件不存在,则根据启动项类型来选择图标(如:Windows 将会被自动设置为 Windows 图标)

    Flavour 的值是一个由 : 分隔的名字,必须是可打印的 7-bit ASCII,最长限制在64字符内。此项目大约能填写五个名字,最前面的名字有最高的优先级,最后面的名字由最低的优先级。这样的结构允许用一个更具体的方式来描述一个启动项,使用被音频-图标集支持的自选图标。如果找不到音频或图标文件,则启动器会自动尝试下一个 flavour,而如果所有的 flavour 都找不到文件,则启动器会根据启动项类型来自动选择图标。以下是一个 flavour 的例子:BigSur:Apple, Windows10:Windows. OpenShell:UEFIShell:Shell.

    使用 flavour 意味着你可以容易地在图标集之中选择自己想要的图标,在图标集所有的图标中选择一个最合适的图标。比如,指定一个 flavour 图标 Debian:Linux 则将会尝试使用 Debian.icns 这个图标,如果没找到的话则尝试 Linux.icns,如果还没找到的话则会回退到 OS 的默认图标,也就是 HardDrive.icns

    一些需要注意的事情:

    • 为了安全考虑,Ext.icns 和 .icns 都会被支持,并且当启动项是外接硬盘时仅有 Ext.icns 会被使用(就像默认的 ExtHardDrive.icns 那样)。
    • .VolumeIcon.icns.contentFlavour 都存在时,以 .VolumeIcon.icns 为准。
    • 为了使 tools 的图标和屏幕朗读工作正常(例如 UEFI Shell),在 Flavour 设置中指定的系统的默认启动项图标(见 Docs/Flavours.md)将仍然被应用,即使 Flavour 是禁用状态。在这个情况下非系统的图标将会被忽略。此外,UEFIShell 和 NVRAMReset 的 flavours 将会被特殊处理,以辨识它们的正确的屏幕朗读器、默认 builtin 标签等。
    • 一个推荐的 falvours 列表在 Docs/Flavours.md 中

7. PickerAudioAssist

Type: plist boolean
Failsafe: false
Description: 在开机引导菜单中启用 屏幕朗读。

macOS Bootloader 屏幕朗读 的偏好设置是存在 isVOEnabled.int32 文件的 preferences.efires 中、并受操作系统控制。这里仅提供一个等效的开关。切换 OpenCore 开机引导菜单和 macOS BootLoader FileVault 2 登录界面也可以使用快捷键 Command + F5

:屏幕朗读 依赖可以正常工作的音频设备。

8. PollAppleHotKeys

Type: plist boolean
Failsafe: false
Description: 在开机引导菜单中启用 Modifier Hotkey

除了 Action Hotkey(在 PickerMode 一节中有所描述,由 Apple BDS 处理),还有由操作系统 bootloader(即 boot.efi)处理的 Modifier Hotkey。这些键可以通过提供不同的启动模式来改变操作系统的行为。

在某些固件上,由于驱动程序不兼容,使用 Modifier Hotkey 可能会有问题。为了解决问题,这个选项允许你在启动选择器中以更宽松的方式注册选择的热键,比如:在按住 Shift 和其他按键的同时支持敲击按键,而不是只按 Shift,这在许多 PS/2 键盘上是无法识别的。已知的 Modifier Hotkey 包括:

  • CMD+C+MINUS — 禁用主板兼容性检查。
  • CMD+K — 从 RELEASE 版本的内核启动,类似于 kcsuffix=release 参数。
  • CMD+R — 从恢复分区启动。
  • CMD+S — 启动至单用户模式。
  • CMD+S+MINUS — 禁用 KASLR slide,需要事先禁用 SIP。
  • CMD+V — 启用 -v
  • Shift+Enter, Shift+Index — 启用安全模式。

9. ShowPicker

Type: plist boolean
Failsafe: false
Description: 是否显示开机引导菜单。

10. TakeoffDelay

Type: plist integer, 32 bit
Failsafe: 0
Description: 在 处理引导项启动 和 处理 Action Hotkey 之前的延迟,以微秒为单位。

引入这一延迟有助于为你争取时间去完成按住 Action Hotkey 的操作,比如启动到恢复模式。在某些平台上,可能需要把此项设置为至少 5000-10000 来使 Action Hotkey 生效,具体取决于键盘驱动程序的性质。

11. Timeout

Type: plist integer, 32 bit
Failsafe: 0
Description: 开机引导菜单中,启动默认启动项之前超时时间(以秒为单位)。 使用 0 禁用倒计时。

译者注:0 为关闭倒计时而非跳过倒计时,相当于 Clover 的 -1

12. PickerMode

Type: plist string
Failsafe: Builtin
Description: 选择启动管理器的界面。

这里描述的是具有可选用户界面的底层启动管理器,支持以下值:

  • Builtin — 使用由 OpenCore 处理的启动管理器,简单的文本用户界面。
  • External — 如果可用,则使用外部启动管理器协议,否则使用 Builtin 模式。
  • Apple — 如果可用,则使用 Apple 启动管理器,否则使用 Builtin 模式。

External 模式一旦成功,就会完全禁用 OpenCore 中的除策略强制执行的所有其他启动管理器,而 Apple 模式下可以绕过策略的强制执行。请参阅 ueficanopy 插件以了解自定义用户界面的实例。

OpenCore 内置的启动选择器包含了一系列在启动过程中选择的操作。支持的操作与 Apple BDS 类似,一般来说能够通过在启动过程中按住 Action Hotkey 来实现,目前有以下几种:

  • Default — 此项为默认选项,可以让 OpenCore 内置的启动选择器按照 启动磁盘 偏好设置中指定的方式加载默认的启动项。
  • ShowPicker — 此项会强制显示启动选择器,通常可以在启动时按住 OPT 键来实现。将 ShowPicker 设置为 true 会使 ShowPicker 成为默认选项。
  • ResetNvram — 此项会擦除 UEFI 变量,通常是在启动时按住 CMD+OPT+P+R 组合键来实现。另一种擦除 UEFI 变量的方法是在选择器中选择 Reset NVRAM,要使用这种方式需要将 AllowNvramReset 设置为 true
  • BootApple — 此项会启动到第一个找到的 Apple 操作系统,除非 Apple 已经默认选择了操作系统。按住 X 来选择此选项。
  • BootAppleRecovery — 此项会启动到 Apple 操作系统的恢复系统。这里的系统要么是「与默认选中的操作系统相关的恢复系统」,要么是「第一个找到的非 Apple 的默认操作系统的恢复系统」,要么是「无恢复系统」。按住 CMD+R 组合键来选择此选项。

注 1:需要激活 KeySupportOpenUsbKbDxe 或类似的驱动程序才能工作。无法获得全部按键功能的固件有很多。

注 2:当禁用 ShowPicker 时,除了 OPT 键之外,OpenCore 还支持 Escape 键来显示启动选项。这个键不仅适用于 Apple 启动选择器模式,也适用于 PS/2 键盘的固件,因为这种键盘无法提交按住 OPT 键的请求,需要连续点按 Escape 键来进入启动选择菜单。

注 3:有些 Mac 的 GOP 很棘手,可能很难进入 Apple 启动选择器。还有一些 Mac,BootKicker 不能从 OpenCore 运行。可以通过直接 bless BootKicker 实用工具来解决这个问题,不需要加载 OpenCore。

13. PickerVariant

Type: plist string
Failsafe: Auto
Description: 选择启动管理器所使用的图标集。

支持以下值:

  • Auto — 基于 DefaultBackground 的设置,自动选择相应的图标集。
  • Default — 常规图标集(无前缀)。
  • Old — 复古图标集(文件名有 Old 前缀)。
  • Modern — 新颖图标集(文件名有 Modern 前缀)。
  • 其他值 — 自定义图标集,需要在 Resources 中添加相应图标集。

8.4 Debug 属性

1. AppleDebug

Type: plist boolean
Failsafe: false
Description: 启用将 boot.efi 调试日志保存到 OpenCore 日志。

:此项仅适用于 10.15.4 和更新版本。

2. ApplePanic

Type: plist boolean
Failsafe: false
Description: 将 macOS Kernel Panic 保存到 OpenCore 根分区。

保存的文件为 panic-YYYY-MM-DD-HHMMSS.txt。强烈建议使用 keepsyms=1 引导参数来查看 Panic 日志中的调试符号。如果没有,可以用 kpdescribe.sh 实用工具(OpenCore 绑定)来部分恢复堆栈跟踪。

开发者内核和调试内核会产生更有用的 Kernel Panic。调试的时候,可以考虑从 developer.apple.com 下载并安装 KernelDebugKit。如果要激活开发者内核,需要添加一个 kcsuffix=development 引导参数。使用 uname -a 命令来确保你当前加载的内核是一个开发者(或调试)内核。

如果没有使用 OpenCore 的 Kernel Panic 保存机制,仍然可以在 /Library/Logs/DiagnosticReports 目录下找到 Panic 日志。从 macOS Catalina 开始,Kernel Panic 会以 JSON 格式储存,所以在传递给 kpdescribe.sh 之前需要预处理:

cat Kernel.panic | grep macOSProcessedStackshotData | python -c 'import json,sys;print(json.load(sys.stdin)["macOSPanicString"])'

3. DisableWatchDog

Type: plist boolean
Failsafe: false
Description: 某些固件启动操作系统的速度可能不够快(尤其是调试模式下),看门狗定时器会因此中止引导过程。此选项用来关闭看门狗定时器。

4. DisplayDelay

Type: plist integer
Failsafe: 0
Description: 屏幕上打印每行输出之间的延迟。

5. DisplayLevel

Type: plist integer, 64 bit
Failsafe: 0
Description: 与屏幕显示相关的 EDK II 调试级别的位掩码(总和)。除非 Target 启用了控制台在屏幕上输出日志,否则屏幕上的调试输出将不可见。支持以下级别(更多信息参见 DebugLib.h):

  • 0x00000002 (bit 1) — DEBUG_WARN in DEBUG, NOOPT, RELEASE.
  • 0x00000040 (bit 6) — DEBUG_INFO in DEBUG, NOOPT.
  • 0x00400000 (bit 22) — DEBUG_VERBOSE in custom builds.
  • 0x80000000 (bit 31) — DEBUG_ERROR in DEBUG, NOOPT, RELEASE.

6. SerialInit

Type: plist boolean
Failsafe: false
Description: 执行串行端口初始化。

该选项会在任何调试日志启用之前,初始化 OpenCore 的串行端口设置。串行端口配置是在编译时,在 gEfiMdeModulePkgTokenSpaceGuid GUID 中通过 PCD 来定义的。MdeModulePkg.dec 中的默认值如下:

  • PcdSerialBaudRate — 波特率:115200。
  • PcdSerialLineControl — 线路控制参数:无奇偶校验,8 位数据位,1 位停止位。

具体细节见 Debugging 部分。

7. SysReport

Type: plist boolean
Failsafe: false
Description: 在 EFI 分区中保存系统报告。

启用这一选项后,EFI 分区中将会新建一个 SysReport 目录。这一目录中将会保存 ACPI、SMBIOS 和音频编解码器的调试信息。保存音频编解码器信息需要加载音频后端驱动。

:基于安全的考虑,RELEASE 构建的 OpenCore 将不会内置这一功能。如果需要使用这一功能请使用 DEBUG 构建版。

8. Target

Type: plist integer
Failsafe: 0
Description: 启用日志记录目标的位掩码(总和)。默认所有日志的输出都是隐藏的,所以当需要调试时,有必要设置这个选项。

支持以下日志记录目标:

  • 0x01 (bit 0) — 启用日志记录,否则所有日志都会被丢弃
  • 0x02 (bit 1) — 在屏幕上输出日志
  • 0x04 (bit 2) — 启用把日志记录到 Data Hub
  • 0x08 (bit 3) — 启用串行端口记录
  • 0x10 (bit 4) — 启用 UEFI 变量记录
  • 0x20 (bit 5) — 启用非易失性 UEFI 变量记录
  • 0x40 (bit 6) — 启用在 ESP 分区生成日志文件

控制台日志会比其他日志少,根据 build 类型(RELEASEDEBUGNOOPT)的不同,读取到的日志量也会不同(从最少到最多)。

Data Hub 日志中不包括 Kernel 和 Kext 的日志。要获取 Data Hub 日志,请使用 ioreg:

ioreg -lw0 -p IODeviceTree | grep boot-log | sort | sed 's/.*<\(.*\)>.*/\1/' | xxd -r -p

UEFI 变量日志中不包含某些信息,也没有性能数据。为了安全起见,日志大小被限制在 32 KB。有些固件可能会提前截断它,或者在它无内存时完全删除它。使用非易失性 flag 将会在每打印一行后把日志写入 NVRAM 闪存。如要获取 UEFI 变量日志,请在 macOS 中使用以下命令:

nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:boot-log | awk '{gsub(/%0d%0a%00/,"");gsub(/%0d%0a/,"\n")}1'

{% note danger 警告 %}
有些固件的 NVRAM 垃圾收集据说存在问题,它们可能无法做到在每次变量删除后都释放空间。在这类设备上,没有额外需要的话,请不要使用非易失性 NVRAM 日志。
{% endnote %}

虽然 OpenCore 的引导日志已经包含了基本的版本信息(包括 build 类型和日期),但即使在禁用引导日志的情况下,这些数据也可以在 NVRAM 中的 opencore-version 变量中找到。

文件记录会在 EFI 卷宗的根目录下创建一个名为 opencore-YYYY-MM-DD-HHMMSS.txt 的文件,其中包含了日志的内容(大写字母部分会被替换为固件中的日期和时间)请注意,固件中的一些文件系统驱动程序不可靠,并且可能会通过 UEFI 写入文件时损坏数据。因此,OpenCore 会尝试用最安全同时也是最慢的方式来写入日志。当你在使用慢速存储驱动器时,请确保已将 DisableWatchDog 设置为 true。如果你在使用 SSD,应该尽量避免使用这一选项,大量的 I/O 操作会很快耗尽 SSD 的寿命。

注意,每一行日志都包含有一个描述日志类型的前缀,从而确定该行日志的归属。以下是已知的前缀列表:

Drivers and tools:

  • BMF — OpenCanopy, bitmap font
  • BS — Bootstrap
  • GSTT — GoptStop
  • HDA — AudioDxe
  • KKT — KeyTester
  • MMDD — MmapDump
  • OCPAVP — PavpProvision
  • OCRST — ResetSystem
  • OCUI — OpenCanopy
  • OC — OpenCore main, also OcMainLib
  • VMOPT — VerifyMemOpt

Libraries:

  • AAPL — OcDebugLogLib, Apple EfiBoot logging
  • OCABC — OcAfterBootCompatLib
  • OCAE — OcAppleEventLib
  • OCAK — OcAppleKernelLib
  • OCAU — OcAudioLib
  • OCAV — OcAppleImageVerificationLib
  • OCA — OcAcpiLib
  • OCBP — OcAppleBootPolicyLib
  • OCB — OcBootManagementLib
  • OCCL — OcAppleChunkListLib
  • OCCPU — OcCpuLib
  • OCC — OcConsoleLib
  • OCDC — OcDriverConnectionLib
  • OCDH — OcDataHubLib
  • OCDI — OcAppleDiskImageLib
  • OCFS — OcFileLib
  • OCFV — OcFirmwareVolumeLib
  • OCHS — OcHashServicesLib
  • OCI4 — OcAppleImg4Lib
  • OCIC — OcImageConversionLib
  • OCII — OcInputLib
  • OCJS — OcApfsLib
  • OCKM — OcAppleKeyMapLib
  • OCL — OcDebugLogLib
  • OCMCO — OcMachoLib
  • OCME — OcHeciLib
  • OCMM — OcMemoryLib
  • OCPE — OcPeCoffLib, OcPeCoffExtLib
  • OCPI — OcFileLib, partition info
  • OCPNG — OcPngLib
  • OCRAM — OcAppleRamDiskLib
  • OCRTC — OcRtcLib
  • OCSB — OcAppleSecureBootLib
  • OCSMB — OcSmbiosLib
  • OCSMC — OcSmcLib
  • OCST — OcStorageLib
  • OCS — OcSerializedLib
  • OCTPL — OcTemplateLib
  • OCUC — OcUnicodeCollationLib
  • OCUT — OcAppleUserInterfaceThemeLib
  • OCXML — OcXmlLib

8.5 Security 属性

1. AllowNvramReset

Type: plist boolean
Failsafe: false
Description: 启用这一选项后将允许使用 CMD+OPT+P+R 快捷键重置 NVRAM,同时 NVRAM Reset 条目也会出现在开机引导菜单中。

注 1:据说部分联想笔记本存在固件 bug,执行 NVRAM 重置后无法启动。更多细节请参见 acidanthera/bugtracker#995。

注 2:重置 NVRAM 后,未经过 bless 工具备份过的开机项(如 Linux)会被全部删除。

译者注:BootCamp Windows 因为符合 bless 模型而不受影响。

2. AllowSetDefault

Type: plist boolean
Failsafe: false
Description: 允许使用 CTRL+EnterCTRL+[数字] 设置默认启动项。

3. AllowToggleSip

Type: plist boolean
Failsafe: false
Description: 在 OC 的启动项中加入一个切换 SIP (System Integrity Protection) 的选项。

这会在 Apple 的 NVRAM 变量 csr-active-config 中,从 0 ,即启用 SIP,和一个禁用 SIP 的值,目前是 0x26F 之间切换。

注1:强烈不推荐将 macOS 运行在禁用 SIP 的状态下。使用这一个启动选项有助于在需要的情况下快速的禁用 SIP,当操作完成后应当将 SIP 再次启用。

注2:尽管在 Big Sur 中,csrutil disable 命令会将值设置为 0x7F,OC 依然使用 0x26F 这个值,因为:

  • csrutil disable --no-internal 将值设置为 0x6F,这是比较推荐的,因为 CSR_ALLOW_APPLE_INTERNAL (0x10) 将会阻止系统更新。
  • 一般来说 CSR_ALLOW_UNAPPROVED_KEXTS (0x200) 是可以使用的,在这个状态下你不需要关闭 SIP 也可以安装未签名的 kext 而不需要手动在系统设置中选择允许。
  • 不推荐使用 CSR_ALLOW_UNAUTHENTICATED_ROOT (0x800) 因为这会屏蔽操作系统的增量 OTA 更新(非完整更新)。

注3:对于其他你可能用到的值,你可以将 CsrUtil.efi 配置为一个 TextMode Tools 启动项来指定不同的参数,例如,将参数设置为 0x6F 来将禁用 SIP 的值设置为 Big Sur 中 csrutil disable --no-internal 的默认值。

4. ApECID

Type: plist integer, 64 bit
Failsafe: 0
Description: Apple Enclave 标识符。

将此值设置为任何非零的 64 位整数,将允许使用个性化的 Apple 安全启动标识符。如果你想使用此设置,请确保使用加密的随机数生成器生成一个 64 位的随机数。还有一种方法是将 SystemUUID 的前 8 个字节用于 ApECID,没有 T2 芯片的 Mac 的 macOS 11 就是这样做的。

如果这个值设置妥当,并且 SecureBootModel 值有效且不是 Disabled,那么就可以实现 Apple 安全启动的 完整安全性。

要使用个性化的 Apple 安全启动,必须重新安装操作系统,或对其进行个性化定制。在操作系统被个性化定制之前,只能加载 macOS DMG 恢复镜像。DMG 恢复镜像可以随时用 macrecovery 实用工具下载,然后放到 com.apple.recovery.boot 里,如 技巧和窍门 部分所述。请记住,DmgLoading 需要设置为 Signed 才能通过 Apple 安全启动来加载 DMG。

如果要对现有的操作系统进行个性化定制,请在加载 macOS DMG 恢复镜像之后使用 bless 命令。确保已挂载到系统卷分区,并执行以下命令:

bless bless --folder "/Volumes/Macintosh HD/System/Library/CoreServices" \--bootefi --personalize

macOS 11 为没有 T2 芯片的 Mac 引入了专用的 x86legacy 机型,对于 macOS 11.0 之前的版本,这个机型的 Apple 安全启动可能无法达到预期效果。如果要使用个性化的 Apple 安全启动重新安装操作系统,请记住,当前版本的 macOS 安装器(测试版本 10.15.6)通常会把 /var/tmp 分区的可用内存耗尽,因此在 macOS 安装器镜像下载后不久,就会出现 Unable to verify macOS 的错误信息。为了解决这个问题,需要在开始安装前,在 macOS Recovery 终端输入如下命令,为 macOS 个性化分配一个 2MB 的专用 RAM 磁盘:

disk=$(hdiutil attach -nomount ram://4096)
diskutil erasevolume HFS+ SecureBoot $disk
diskutil unmount $disk
mkdir /var/tmp/OSPersonalizationTemp
diskutil mount -mountpoint /var/tmp/OSPersonalizationTemp $disk

5. AuthRestart

Type: plist boolean
Failsafe: false
Description: 启用与 VirtualSMC 兼容的 authenticated restart。

authenticated restart 可以在重启 FileVault2 分区时不用再次输入密码。你可以使用下述指令执行一次 authenticated restartsudo fdesetup authrestart。macOS 在安装系统更新使用的也是 authenticated restart

VirtualSMC 通过将磁盘加密密钥拆分保存在 NVRAM 和 RTC 中来执行 authenticated restart。虽然 OpenCore 在启动系统后立刻删除密钥,但是这仍然可能被视为安全隐患。

6. BlacklistAppleUpdate

Type: plist boolean
Failsafe: false
Description: 忽略某些用于更新 Apple 外设固件的启动项(如 MultiUpdater.efi)。

:由于某些操作系统(如 macOS Big Sur)无法利用 NVRAM 变量 run-efi-updater 禁用固件更新,因此单独设立了此项。

7. DmgLoading

Type: plist string
Failsafe: Signed
Description: 定义用于 macOS Recovery 的磁盘映像(Disk Image, DMG)加载策略。

有效值如下:

  • Disabled — 加载 DMG 磁盘映像的行为将会失败。大多数情况下 Disabled 策略仍会允许加载 macOS Recovery,因为通常会有 boot.efi 文件,它与 Apple 安全启动兼容。但是,手动下载存储在 com.apple.recovery.boot 目录中的 DMG 磁盘映像将无法被加载。
  • Signed — 仅加载 Apple 签名的 DMG 磁盘映像。由于 Apple 安全启动的设计,不管 Apple 安全启动是什么状态,Signed 策略都会允许加载任何 Apple 签名的 macOS Recovery,这可能不是我们所希望的那样。
  • Any — 任何 DMG 磁盘映像都会作为普通文件系统挂载。强烈不建议使用 Any 策略,当激活了 Apple 安全启动时会导致启动失败。

8. EnablePassword

Type: plist boolean
Failsafe: false
Description: 为敏感操作启用密码保护。

启动非默认操作系统(如 macOS Recovery 或工具)、启动到非默认模式(如详细模式或安全模式)或重置 NVRAM 等,以上这些行为属于敏感操作,密码保护可以很好地保证这些操作都是由本人或授权人操作。目前,密码和盐(Salt)用 5000000 次 SHA-512 迭代来进行哈希运算。

:此功能尚在开发阶段,不推荐日常使用。

9. ExposeSensitiveData

Type: plist integer
Failsafe: 0x6
Description: 用于向操作系统暴露敏感数据的位掩码(总和)。

  • 0x01 — 将可打印的引导器路径作为 UEFI 变量暴露出来
  • 0x02 — 将 OpenCore 版本作为 UEFI 变量暴露出来
  • 0x04 — 将 OpenCore 版本暴露在启动选择菜单的标题位置
  • 0x08 — 将 OEM 信息作为一组 UEFI 变量暴露出来

根据加载顺序,暴露的启动器路径指向 OpenCore.efi 或其引导器。如要获得引导器路径,请在 macOS 中使用以下命令:

nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:boot-path

如要使用启动器路径加载启动器卷宗,请在 macOS 中使用以下命令:

u=$(nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:boot-path | sed 's/.*GPT,\([^,]*\),.*/\1/'); \
if [ "$u" != "" ]; then sudo diskutil mount $u ; fi

如要获取 OpenCore 版本信息,请在 macOS 中使用以下命令:

nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:opencore-version

如要获取 OEM 信息,请在 macOS 中使用以下命令:

nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-product # SMBIOS Type1 ProductName
nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-vendor # SMBIOS Type2 Manufacturer
nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-board # SMBIOS Type2 ProductName

10. HaltLevel

Type: plist integer, 64 bit
Failsafe: 0x80000000 (DEBUG_ERROR)
Description: EDK II 调试级别的位掩码(总和),使 CPU 在获得 HaltLevel 消息后中止(停止执行)。可能的值与 DisplayLevel 值相匹配。

11. PasswordHash

Type: plist data 64 bytes
Failsafe: all zero
Description: 密码使用的哈希值(Hash)。

12. PasswordSalt

Type: plist data
Failsafe: empty
Description: 密码使用的盐值(Salt)。

13. Vault

Type: plist string
Failsafe: Secure
Description: 启用 OpenCore 的 Vault 机制。

有效值:

  • Optional — 无要求,不设置 Vault,不安全。
  • Basic — 需要有 vault.plist 文件存放在 OC 目录下。这个值提供了基本的文件系统完整性验证,可以防止无意中的文件系统损坏。
  • Secure — 需要有 vault.sig 签名的 vault.plist 文件存放在 OC 目录下。这个值包括了 Basic 完整性检查,但也会尝试建立一个可信的引导链。

vault.plist 文件应该包含 OpenCore 使用的所有文件的 SHA-256 哈希值。强烈建议使用这个文件,以确保无意中的文件修改(包括文件系统损坏)不会被忽视。要自动创建这个文件,请使用 create_vault.sh 脚本。无论底层的文件系统如何,路径名和大小写必须在 config.plistvault.plist 之间相匹配。

vault.sig 文件应该包含一个来自 vault.plist SHA-256 哈希值的原始的 256 字节 RSA-2048 签名。这个签名是根据嵌入到 OpenCore.efi 中的公钥来验证的。如要嵌入公钥,以下任一步骤均可:

  • OpenCore.efi 编译过程中,在 OpenCoreVault.c 文件中提供公钥。
  • 用二进制补丁的方式将 OpenCore.efi=BEGIN OC VAULT===END OC VAULT== ASCII 码之间的 0 替换为公钥。

RSA 公钥的 520 字节格式可参阅 Chromium OS 文档。如要从 X.509 证书或 PEM 文件中转换公钥,请使用 RsaTool。

以下操作的完整指令:

  • 创建 vault.plist
  • 创建一个新的 RSA 密钥(总是要这样做,以避免加载旧配置)
  • 将 RSA 密钥嵌入到 OpenCore.efi
  • 创建 vault.sig

可以参照如下指令:

cd /Volumes/EFI/EFI/OC
/path/to/create_vault.sh .
/path/to/RsaTool -sign vault.plist vault.sig vault.pub
off=$(($(strings -a -t d OpenCore.efi | grep "=BEGIN OC VAULT=" | cut -f1 -d' ')+16))
dd of=OpenCore.efi if=vault.pub bs=1 seek=$off count=528 conv=notrunc
rm vault.pub

注 1:必须使用外部方法来验证 OpenCore.efiBOOTx64.efi 的安全启动路径,尽管它们看似显而易见。为此,建议你至少使用自定义证书来启用 UEFI 的 SecureBoot,并使用自定义的密钥来签名 OpenCore.efiBOOTx64.efi 。关于在现代固件上定制安全启动的更多细节,请参见 Taming UEFI SecureBoot(俄文)。

注 2:当 vault.plist 存在,或者当公钥嵌入到 OpenCore.efi 中的时候,无论这个选项是什么,vault.plistvault.sig 都会被使用。设置这个选项仅仅会确保配置的合理性,否则启动过程会中止。

14. ScanPolicy

Type: plist integer, 32 bit
Failsafe: 0xF0103
Description: 定义操作系统检测策略。

通过设置该值来根据所选 flag 的位掩码(总和)防止从非信任源扫描(和启动)。由于不可能可靠地检测到每一个文件类型或设备类型,因此在开放环境中不能完全依赖此功能,需要采取额外的措施。

第三方驱动程序可能会根据提供的扫描策略引入额外的安全(和性能)措施。扫描策略暴露在 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102 GUID的 scan-policy 变量中,仅适用于 UEFI 启动服务。

  • 0x00000001 (bit 0) — OC_SCAN_FILE_SYSTEM_LOCK,将扫描限制于仅扫描此策略定义的已知文件系统。文件系统驱动可能感知不到这个策略,为了避免挂载不必要的文件系统,最好不要加载它的驱动程序。此 bit 不影响 dmg 挂载,因为它可能有各种文件系统。已知文件系统的前缀为 OC_SCAN_ALLOW_FS_
  • 0x00000002 (bit 1) — OC_SCAN_DEVICE_LOCK,将扫描限制于仅扫描此策略定义的已知设备类型。由于协议隧道并不一定能被检测到,因此请注意,在某些系统上可能会出现 USB 硬盘被识别成 SATA 等情况。如有类似情况,请务必报告。已知设备类型的前缀为 OC_SCAN_ALLOW_DEVICE_
  • 0x00000100 (bit 8) — OC_SCAN_ALLOW_FS_APFS,允许扫描 APFS 文件系统。
  • 0x00000200 (bit 9) — OC_SCAN_ALLOW_FS_HFS,允许扫描 HFS 文件系统。
  • 0x00000400 (bit 10) — OC_SCAN_ALLOW_FS_ESP,允许扫描 EFI 系统分区文件系统。
  • 0x00000800 (bit 11) — OC_SCAN_ALLOW_FS_NTFS,允许扫描 NTFS(MSFT Basic Data)文件系统。
  • 0x00001000 (bit 12) — OC_SCAN_ALLOW_FS_EXT,允许扫描 EXT(Linux Root)文件系统。
  • 0x00010000 (bit 16) — OC_SCAN_ALLOW_DEVICE_SATA,允许扫描 SATA 设备。
  • 0x00020000 (bit 17) — OC_SCAN_ALLOW_DEVICE_SASEX,允许扫描 SAS 和 Mac NVMe 设备。
  • 0x00040000 (bit 18) — OC_SCAN_ALLOW_DEVICE_SCSI,允许扫描 SCSI 设备。
  • 0x00080000 (bit 19) — OC_SCAN_ALLOW_DEVICE_NVME,允许扫描 NVMe 设备。
  • 0x00100000 (bit 20) — OC_SCAN_ALLOW_DEVICE_ATAPI,允许扫描 CD/DVD 和旧的 SATA 设备。
  • 0x00200000 (bit 21) — OC_SCAN_ALLOW_DEVICE_USB,允许扫描 USB 设备。
  • 0x00400000 (bit 22) — OC_SCAN_ALLOW_DEVICE_FIREWIRE,允许扫描 FireWire 设备。
  • 0x00800000 (bit 23) — OC_SCAN_ALLOW_DEVICE_SDCARD,允许扫描读卡器设备。

:举例:根据以上描述,0xF0103 值允许扫描带有 APFS 文件系统的 SATA、SAS、SCSI 和 NVMe 设备,不扫描 USB、CD 和 FireWire 设备上的 APFS 文件系统,也不扫描任何带有 HFS 或 FAT32 文件系统的设备。该值表示如下组合:

  • OC_SCAN_FILE_SYSTEM_LOCK
  • OC_SCAN_DEVICE_LOCK
  • OC_SCAN_ALLOW_FS_APFS
  • OC_SCAN_ALLOW_DEVICE_SATA
  • OC_SCAN_ALLOW_DEVICE_SASEX
  • OC_SCAN_ALLOW_DEVICE_SCSI
  • OC_SCAN_ALLOW_DEVICE_NVME

15. SecureBootModel

Type: plist string
Failsafe: Default
Description: Apple 安全启动的机型。

定义 Apple 安全启动的机型和策略。指定此值能够定义哪些操作系统可以启动。早于指定机型发布时间的操作系统将无法启动。有效值如下:

  • Default — 最近的可用型号,目前设置为 j137
  • Disabled — 无机型,禁用 Apple 安全启动
  • j137 — iMacPro1,1 (December 2017). Minimum macOS 10.13.2 (17C2111)
  • j680 — MacBookPro15,1 (July 2018). Minimum macOS 10.13.6 (17G2112)
  • j132 — MacBookPro15,2 (July 2018). Minimum macOS 10.13.6 (17G2112)
  • j174 — Macmini8,1 (October 2018). Minimum macOS 10.14 (18A2063)
  • j140k — MacBookAir8,1 (October 2018). Minimum macOS 10.14.1 (18B2084)
  • j780 — MacBookPro15,3 (May 2019). Minimum macOS 10.14.5 (18F132)
  • j213 — MacBookPro15,4 (July 2019). Minimum macOS 10.14.5 (18F2058)
  • j140a — MacBookAir8,2 (July 2019). Minimum macOS 10.14.5 (18F2058)
  • j152f — MacBookPro16,1 (November 2019). Minimum macOS 10.15.1 (19B2093)
  • j160 — MacPro7,1 (December 2019). Minimum macOS 10.15.1 (19B88)
  • j230k — MacBookAir9,1 (March 2020). Minimum macOS 10.15.3 (19D2064)
  • j214k — MacBookPro16,2 (May 2020). Minimum macOS 10.15.4 (19E2269)
  • j223 — MacBookPro16,3 (May 2020). Minimum macOS 10.15.4 (19E2265)
  • j215 — MacBookPro16,4 (June 2020). Minimum macOS 10.15.5 (19F96)
  • j185 — iMac20,1 (August 2020). Minimum macOS 10.15.6 (19G2005)
  • j185f — iMac20,2 (August 2020). Minimum macOS 10.15.6 (19G2005)
  • x86legacy — Macs and VMs without T2 chip. Minimum macOS 11.0.1 (20B29)

Apple 安全启动最初出现于搭载 T2 芯片的机型上的 macOS 10.13。PlatformInfoSecureBootModel 是相互独立的,因此可以在任何 SMBIOS 上启用 Apple 安全启动。将 SecureBootModel 设置为除 Disabled 以外的任意有效值,相当于实现了 Apple 安全启动的 中等安全性。如要实现「完整安全性」,还需要指定 ApECID 值。

启用 Apple 安全启动的要求很多,任何不正确的配置、错误的 macOS 安装或者不支持的安装设置都可能会增加启用难度,记住以下几点:

  • 和配备 Apple T2 安全芯片的 Mac 电脑一样,你将无法安装任何未签名的内核驱动程序。还有一些内核驱动程序尽管已签名,但也无法安装,包括但不限于 NVIDIA Web Drivers。
  • 驱动程序缓存的列表可能不同,因此需要改变 AddForce 内核驱动程序列表。比如,在这种情况下 IO80211Family 不能被注入。
  • 某些系统(比如 macOS 11)是封装保护的,更改受保护的系统卷可能会导致操作系统无法启动。除非禁用了 Apple 安全启动,否则不要禁用系统卷加密。
  • 如果你的平台需要某些特定设置,但由于之前调试时没有触发明显问题而没有被启用,那么可能会导致启动失败。要格外小心 IgnoreInvalidFlexRatioHashServices
  • 在 Apple 推出安全启动功能之前发布的操作系统(如 macOS 10.12 或更早的版本)仍然会正常启动,除非启用了 UEFI 安全启动。之所以如此,是因为从 Apple 安全启动的角度来看,它们都是不兼容的系统,会被认为应该由 BIOS 来处理,就像微软的 Windows 一样。
  • 在较旧的 CPU 上(如 Sandy Bridge 之前),启用 Apple 安全启动可能会使加载速度略微变慢,最长可达 1 秒。
  • 由于 Default 的值会随着时间的推移而变化,以支持最新的 macOS 主版本,因此不建议同时使用 ApECIDDefault 值。
  • 启用 Apple 安全启动时,HFS+ 文件系统的卷宗无法作为目标卷宗安装 macOS。没有其他备用 APFS 硬盘的情况下,HFS+ 文件系统的硬盘也同样无法安装。

有时,已安装的系统 Preboot 分区上的 Apple 安全启动清单是过时的,从而导致启动失败。如果你看到 OCB: Apple Secure Boot prohibits this boot entry, enforcing! 这样的信息,很可能就是出现了上述这种情况。想要解决这个问题,要么重新安装操作系统,要么把 /usr/standalone/i386 中的清单(扩展名为 .im4m 的文件,如 boot.efi.j137.im4m)复制到 /Volumes/Preboot/<UUID>/System/Library/CoreServices<UUID> 为系统卷的标识符)。HFS+ 文件系统则须复制到系统卷上的 /System/Library/CoreServices 目录。

关于如何结合 UEFI 安全启动来配置 Apple 安全启动的细节,请参考本文档 UEFI 安全启动 部分。

8.6 Entry 属性

1. Arguments

Type: plist string
Failsafe: Empty string
Description: 对该引导条目使用的引导参数。

2. Auxiliary

Type: plist boolean
Failsafe: false
Description: 当 HideAuxiliary 被启用时,这一值为 true 的引导条目将不会显示在开机引导菜单中。

3. Comment

Type: plist string
Failsafe: Empty string
Description: 用于为条目提供人类可读参考的任意 ASCII 字符串(译者注:即注释)。

4. Enabled

Type: plist boolean
Failsafe: false
Description: 除非设置为 true,否则该引导条目不会显示在开机引导菜单中。

5. Flavour

Type: plist string
Failsafe: Auto
Description: 为该启动项指定 flavour,详见文档中的 OC_ATTR_USE_FLAVOUR_ICON 标识。

6. Name

Type: plist string
Failsafe: Empty string
Description: 引导条目在开机引导菜单中显示的名字。

7. Path

Type: plist string
Failsafe: Empty string
Description: 引导入口。

  • Entries 用于指定外部启动选项,因此会在 Path 中取设备路径。这些值不会被检查,所以要非常小心。例如:PciRoot(0x0)/Pci(0x1,0x1)/.../\EFI\COOL.EFI
  • Tools 用于指定内部引导选项,这些选项隶属于 bootloader vault,因此会取相对于 OC/Tools 目录的文件路径。例如:OpenShell.efi

8. RealPath

Type: plist boolean
Failsafe: false
Description: 启动时将完整的路径传递给工具。

传递目录可能会使工具在没有检查文件完整性的情况下就意外地访问了文件,降低了安全性,因此通常应该禁用。需要启用该项的情况有:工具需要外部文件来正常工作;工具需要外部文件来更好地实现某些功能(如 memtest86 的记录和配置功能,Shell 自动执行脚本的功能)。

:此属性的开关仅对工具有效。对于 Entries 该属性始终为 true

9. TextMode

Type: plist boolean
Failsafe: false
Description: 以文本模式而非图形模式运行条目。

某些需要文本输出的旧工具需要用到此项。默认情况下所有工具都以图形模式启动。更多关于文本模式的内容,请参阅 Output 属性。

NVRAM

9.1 简介

设置易失性 UEFI 变量(通常被称作 NVRAM 变量),数据类型为 plist dict。使用 man nvram 获取详细信息。macOS 广泛使用 NVRAM 变量使 操作系统、BootLoader、固件 之间互通,因此需要提供多个 NVRAM 变量才能正常运行 macOS。

每个 NVRAM 变量均由其名称、值、属性(参考 UEFI 规范)以及 GUID 组成,表示 NVRAM 变量属于哪一区域。macOS 使用如下(包括但不限于)几种 GUID:

  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14 (APPLE_VENDOR_VARIABLE_GUID)
  • 7C436110-AB2A-4BBB-A880-FE41995C9F82 (APPLE_BOOT_VARIABLE_GUID)
  • 8BE4DF61-93CA-11D2-AA0D-00E098032B8C (EFI_GLOBAL_VARIABLE_GUID)
  • 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102 (OC_VENDOR_VARIABLE_GUID)

:某些变量可以通过 PlatformNVRAMPlatformInfo 节的 Generic 子节添加。请确保本节中的变量不会与它们发生冲突,否则可能导致未定义的行为。

为了使 macOS 正常运行,通常需要使用 OC_FIRMWARE_RUNTIME 协议。该协议的实现目前是 OpenRuntime(原名 FwRuntimeServices.efi)驱动程序的一部分。虽然可能带来一些好处,但根据用途不同也会存在某些限制。

  • 并非所有工具都可能知道受保护的名称空间。当使用 RequestBootVarRouting 时,在独立的命名空间中会限制对 Boot 前缀的变量访问。要访问原始变量,工具必须了解 OC_FIRMWARE_RUNTIME 协议的工作原理。

9.2 属性列表

1. Add

Type: plist dict
Description: 从一组 GUID 映射(plist dict)中读取格式为 plist metadata 的变量映射,并将其添加到 NVRAM 中。GUID 必须以 Canonical String 格式提供,大写或小写均可(如 8BE4DF61-93CA-11D2-AA0D-00E098032B8C)。

创建的变量会设置 EFI_VARIABLE_BOOTSERVICE_ACCESSEFI_VARIABLE_RUNTIME_ACCESS 的属性。变量只有在不存在且未被屏蔽的情况下才会被设置,也就是说,如果想要覆盖一个现有的变量值,请将该变量的名称添加到 Delete 部分,这种方法能够提供一个默认的值,直到操作系统接手为止。

:如果 plist key 不符合 GUID 格式,则可能出现一些未定义的行为。

2. Delete

Type: plist dict
Description: 从一组 GUID 映射(plist dict)读取一组包含 plist string 的数组(plist array),这些将会被从 NVRAM 变量中被删除。

3. LegacyEnable

Type: plist boolean
Failsafe: false
Description: 允许从 ESP 分区的根目录中的 nvram.plist 文件读取 NVRAM 变量。

该文件必须以 plist dictionary 为文件根格式,并包含以下两个字段:

  • Versionplist integer,文件版本,必须设定为 1。
  • Addplist dictionary,等同于 config.plist 中的 Add

变量加载优先于 Delete(以及 Add)阶段。除非启用了 LegacyOverwrite,否则不会覆盖现有的任何变量。允许设置的变量必须指定于 LegacySchema 中。第三方脚本可以用来创建 nvram.plist 文件,脚本示例可参照 Utilities。使用第三方脚本可能要将 ExposeSensitiveData 设置为 0x3 来为 boot-path 变量提供 OpenCore EFI 分区的 UUID。

{% note danger 警告 %}
这一功能非常危险,因为会将不受保护的数据传递给固件中的变量服务。只有在你的硬件不提供硬件 NVRAM 或与之不兼容时才使用。
{% endnote %}

4. LegacyOverwrite

Type: plist boolean
Failsafe: false
Description: 允许用 nvram.plist 文件中的变量覆盖现有 NVRAM 中的变量。

:只有操作系统访问的到的变量会被覆盖。

5. LegacySchema

Type: plist dict
Description: 允许从 GUID 映射(plist dict)中选择 NVRAM 变量设置到一个变量名称数组(plist array),格式为 plist string

可用 * 值来接受所有用来选择 GUID 的变量。

{% note danger 警告 %}
选择变量要非常慎重,因为 nvram.plist 不会被存储。比如,不要把 boot-argscsr-active-config 放进去,因为会绕过 SIP。
{% endnote %}

6. WriteFlash

Type: plist boolean
Failsafe: false
Description: 允许将所有添加的变量写入闪存。

:这个 Quirk 本应该在大多数固件上启用,但是由于可能存在 NVRAM 变量存储 GC 或类似的问题的固件,所以我们将这个 Quirk 设计为可配置的。

要从 macOS 中读取 NVRAM 变量的值,可以使用 nvram,并将变量 GUID 和名称用 : 符号隔开,形如 nvram 7C436110-AB2A-4BBB-A880-FE41995C9F82:boot-args

变量列表可参照相关文档(持续更新):NVRAM Variables。

9.3 必需变量

{% note danger 警告 %}
这些变量可通过 PlatformNVRAM 或 PlatformInfo 的 Generic 部分添加。推荐使用 PlatformInfo 来设置这些变量。
{% endnote %}

以下变量为 macOS 运行必需:

  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:FirmwareFeatures
    32 位 FirmwareFeatures。存在于所有 Mac 上,用来避免额外解析 SMBIOS 表。
  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:FirmwareFeaturesMask
    32 位 FirmwareFeaturesMask。存在于所有 Mac 上,用来避免额外解析 SMBIOS 表。
  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:MLB
    BoardSerialNumber。存在于较新的 Mac 上(至少 2013 年以后),用来避免额外解析 SMBIOS 表,尤其是在 boot.efi 中。
  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ROM
    主要的网络适配器的 MAC 地址或替换值。存在于较新的 Mac(至少 2013 年以后)上,用来避免访问特殊内存区域,尤其是在 boot.efi 中。

9.4 建议变量

建议使用以下变量来加快启动速度或改善其他表现:

  • 7C436110-AB2A-4BBB-A880-FE41995C9F82:csr-active-config
    系统完整性保护的位掩码(32-bit),声明于 XNU 源码 csr.h。
  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeatures
    结合 FirmwareFeaturesExtendedFirmwareFeatures。存在于较新的 Mac 上,用来避免额外解析 SMBIOS 表。
  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeaturesMask
    结合 FirmwareFeaturesMaskExtendedFirmwareFeaturesMask。存在于较新的 Mac 上,用来避免额外解析 SMBIOS 表。
  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:HW_BID
    硬件 BoardProduct(如 Mac-35C1E88140C3E6CF)。在真正的 Mac 上不存在,但可用于避免额外解析 SMBIOS 表,尤其是在 boot.efi 中。
  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:HW_MLB
    硬件 BoardSerialNumber。覆盖 MLB,存在于较新的 Mac 上(至少 2013 年以后)。
  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:HW_ROM
    硬件 ROM。覆盖 ROM,存在于较新的 Mac 上(至少 2013 年以后)。
  • 7C436110-AB2A-4BBB-A880-FE41995C9F82:prev-lang:kbd
    定义默认键盘布局的 ASCII 字符串。格式为 lang-COUNTRY:keyboard,例如 ru-RU:252 代表俄语和 ABC 键盘。也接受简短形式:ru:252ru:0(美国键盘,兼容 10.9)。完整的键盘列表解码来自 AppleKeyboardLayouts-L.dat,可前往这里查看。与之前或之后的 macOS 版本不同,在 10.14 上,使用非拉丁语键盘将无法启用 ABC 键盘,因此假如你需要使用 10.14 版本则不建议你使用这一变量。
  • 7C436110-AB2A-4BBB-A880-FE41995C9F82:security-mode
    定义 FireWire 安全模式的 ASCII 字符串。这一变量旧版本才有,可在 IOFireWireController.cpp 中的 IOFireWireFamily 源码里找到。建议不要设置这个变量,这样可能会加快启动速度。设置为 full 等同于不设置该变量,设置为 none 将禁用 FireWire 安全性。
  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:UIScale
    定义 boot.efi 用户界面缩放比例的一字节数据。普通屏幕应为 01,HiDPI 屏幕应为 02
  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:DefaultBackgroundColor
    定义 boot.efi 用户界面背景色的四字节 BGRA 数据。标准色包括 BF BF BF 00(浅灰)和 00 00 00 00(西拉黑)。其他颜色可根据用户喜好设置。

9.5 其他变量

以下变量对于某些特定的配置或进行故障排除可能会很有用:

  • 7C436110-AB2A-4BBB-A880-FE41995C9F82:boot-args
    内核参数,用于将配置传递给 Apple 内核和驱动程序。很多参数可以通过在内核或驱动程序代码中寻找 PE_parse_boot_argn 函数找到。已知的引导参数包括:

    • acpi_layer=0xFFFFFFFF
    • acpi_level=0xFFFF5F — 表示 ACPI_ALL_COMPONENTS
    • arch=i386 — 强制内核架构为 i386,详见 KernelArch 选项
    • batman=VALUEAppleSmartBatteryManager 调试掩码
    • batman-nosmc=1 — 禁用 AppleSmartBatteryManager SMC 接口
    • cpus=VALUE — 最大可用 CPU 数量
    • debug=VALUE — Debug 掩码
    • io=VALUEIOKit 调试掩码
    • ioaccel_debug=VALUEIOAccelerator 调试掩码
    • keepsyms=1 — 显示 Panic 日志调试符号
    • kextlog=VALUE — Kext 调试掩码
    • nvram-log=1 — 启用 AppleEFINVRAM 日志
    • nv_disable=1 — 禁用 NVIDIA GPU 加速
    • nvda_drv=1 — 启用 NVIDIA web driver 的传统方法,这一参数在 macOS 10.12 中被去除
    • npci=0x2000 — 旧方法 禁用 kIOPCIConfiguratorPFM64
    • lapic_dont_panic=1 — 禁用 AP 内核的 LAPIC Panic 伪中断行为
    • panic_on_display_hang=1 — 显示设备挂起时触发 Panic
    • panic_on_gpu_hang=1 — GPU 挂起时触发 Panic
    • slide=VALUE — 手动设置 KASLR 偏移值
    • smcdebug=VALUEAppleSMC 调试掩码
    • spin_wait_for_gpu=1 — 减少 GPU 高负载情况下的超时时间
    • -amd_no_dgpu_accel — 替代 WhateverGreen 的 -radvesa,用于较新的 GPUs
    • -nehalem_error_disable
    • -no_compat_check — 禁用机型检查(适用于 10.7 以上的版本)
    • -s — 单用户模式
    • -v — 啰嗦模式
    • -x — 安全模式

    这里有一些网站收集了 macOS 内置的启动参数列表:列表 1、列表 2.

  • 7C436110-AB2A-4BBB-A880-FE41995C9F82:bootercfg
    Booter 参数,类似于 boot-args,但用于 boot.efi 。接受参数为一组十六进制的 64 位值,带或不带 0x。在不同阶段,boot.efi 会请求不同的调试(日志)模式(例如,在 ExitBootServices 之后它只会打印到串行调试接口)。有些 Booter 参数会控制这些请求是否成功。下面是已知请求的列表:

    • 0x00INIT
    • 0x01VERBOSE (如 -v,强制控制台记录日志)
    • 0x02EXIT
    • 0x03RESET:OK
    • 0x04RESET:FAIL (如未知的 board-id,休眠错配,Panic 循环,等等)
    • 0x05RESET:RECOVERY
    • 0x06RECOVERY
    • 0x07REAN:START
    • 0x08REAN:END
    • 0x09DT (不再将日志记录到设备树)
    • 0x0AEXITBS:START (仅强制的串行调试接口)
    • 0x0BEXITBS:END (仅强制的串行调试接口)
    • 0x0CUNKNOWN

    在 10.15 中,由于某种重构和 新调试协议 的引入,10.15.4 之前的调试支持基本上不能用了。下面的一些参数和值可能不适用于 10.15.4 之前的版本。以下是已知参数的列表:

    • boot-save-log=VALUE — 正常启动时的调试日志保存模式

      • 0
      • 1
      • 2 — 默认
      • 3
      • 4 — 保存到文件
    • wake-save-log=VALUE — 休眠唤醒时的调试日志保存模式
      • 0 — 禁用
      • 1
      • 2 — 默认
      • 3 — 不可用
      • 4 — 保存到文件,不可用
    • breakpoint=VALUE — 调试中断相关(在产品 boot.efi 中缺少)
      • 0 — 禁用错误时的调试中断(默认)
      • 1 — 启用错误时的调试中断
    • console=VALUE — 启用控制台日志记录
      • 0 — 禁用控制台日志记录
      • 1 — 当缺少调试协议时,启用控制台日志记录(默认)
      • 2 — 无条件启用控制台日志记录(不可用)
    • embed-log-dt=VALUE — 设备树日志记录相关
      • 0 — 禁用设备树日志记录
      • 1 — 启用设备树日志记录
    • kc-read-size=VALUE — 用于网络或磁盘缓冲 I/O 的数据块大小,用于预链接内核读取和相关用途。默认设置为 1MB
      (0x100000),可以通过调整使启动更快
    • log-level=VALUE — 日志等级位掩码
      • 0x01 — 启用跟踪记录(默认)
    • serial=VALUE — 串行控制台日志记录相关
      • 0 — 禁用串行日志记录(默认)
      • 1 — 从 EXITBS:END 开始启用串行日志记录
      • 2 — 从 EXITBS:START 开始启用串行日志记录
      • 3 — 当缺少调试协议时,启用串行日志记录
      • 4 — 无条件启用串行日志记录
    • timestamps=VALUE — 时间戳日志记录相关
      • 0 — 禁用时间戳记录
      • 1 — 启用时间戳记录(默认)
    • log=VALUE — 10.15 开始弃用
      • 1 — AppleLoggingConOutOrErrSet/AppleLoggingConOutOrErrPrint (classical ConOut/StdErr)
      • 2 — AppleLoggingStdErrSet/AppleLoggingStdErrPrint (StdErr or serial?)
      • 4 — AppleLoggingFileSet/AppleLoggingFilePrint (BOOTER.LOG/BOOTER.OLD file on EFI partition)
    • debug=VALUE — 10.15 开始弃用
      • 1 — 启用输出到 BOOTER.LOG(如果出现了被精简过的代码,则意味着可能发生过崩溃)
      • 2 — 启用性能日志(Perf Log),记录到 /efi/debug-log
      • 4 — 为调用 printf 启用时间戳输出
    • level=VALUE — 10.15 开始弃用
      DEBUG 输出的详细程度。默认除 0x80000000 以外,其他内容都会被精简掉。

    :如要查看现代 macOS 版本上的 boot.efi verbose 输出,请启用 AppleDebug 选项。这样会把日志保存到通用 OpenCore 日志中。对于 10.15.4 之前的版本,将 bootercfg 设置为 log=1,可以将 verbose 输出打印在屏幕上。

  • 7C436110-AB2A-4BBB-A880-FE41995C9F82:efiboot-perf-record
    启用 boot.efi 中的性能日志保存功能。性能日志会被保存到物理内存中,并通过 efiboot-perf-record-dataefiboot-perf-record-size 变量进行指向。从 10.15.4 开始,它也可以通过 AppleDebug 选项保存到 OpenCore 日志中。

  • 7C436110-AB2A-4BBB-A880-FE41995C9F82:bootercfg-once
    在首次启动后删除 Booter 参数覆盖,否则等同于 bootercfg

  • 7C436110-AB2A-4BBB-A880-FE41995C9F82:fmm-computer-name
    当前保存的主机名称,格式为 ASCII 字符串。

  • 7C436110-AB2A-4BBB-A880-FE41995C9F82:nvda_drv
    NVIDIA Web Driver 的控制变量。用 ASCII 数字 1 来启用或用 0 来禁用已安装的驱动程序。

  • 7C436110-AB2A-4BBB-A880-FE41995C9F82:run-efi-updater
    覆盖 macOS 中对 EFI 固件更新(MultiUpdater、ThorUtil)等的支持。将此值设置为 No 或其他可以转换为布尔类型的值将能够禁用 10.10 起的 macOS 固件更新。

  • 7C436110-AB2A-4BBB-A880-FE41995C9F82:StartupMute
    开机时禁用固件引导提示音。8 进制整数。0x00 指代不静音、其他任何值(或缺少该值)表示静音。

  • 7C436110-AB2A-4BBB-A880-FE41995C9F82:SystemAudioVolume
    固件音频支持的系统音频音量等级。8 进制整数。0x80 指代静音。低位用于编码安装的音频编码解码器的音量范围。该值以 MaximumBootBeepVolume AppleHDA layout 值为上限,以避免固件中的音频播放声音过大。

PlatformInfo

10.1 属性列表

1. Automatic

Type: plist boolean
Failsafe: false
Description: 基于 Generic 属性而不是 DataHubNVRAMSMBIOS 属性生成机型信息。

考虑到 Generic 部分的数据十分灵活,启用这个选项会很有用:

  • 当启用这个选项时,SMBIOSDataHubPlatformNVRAM 中的数据将不会被使用。
  • 当禁用这个选项时,Generic 部分的数据将不会被使用。

{% note danger 警告 %}
强烈不建议把此项设置为 false。只有在需要对 SMBIOS 进行小规模修正的情况下,才有理由不使用 Automatic,否则可能会导致 debug 困难。
{% endnote %}

2. CustomMemory

Type: plist boolean
Failsafe: false
Description: 使用在 Memory 部分所填写的自定义内存配置。该选项将完全取代 SMBIOS 中任何现有的内存配置,只有当 UpdateSMBIOS 设置为 true 时才生效。

3. UpdateDataHub

Type: plist boolean
Failsafe: false
Description: 更新 Data Hub 字段。根据 Automatic 的值,这些字段会从 GenericDataHub 中读取。

4. UpdateNVRAM

Type: plist boolean
Failsafe: false
Description: 是否更新 NVRAM 中关于机型信息的相关字段。

根据 Automatic 的值,这些字段会从 GenericPlatformNVRAM 中读取。所有其他字段都将在 NVRAM 部分中指定。

如果将此值设置为 false,则可以使用 nvram 部分更新上述变量;反之若将此值设置为 true,而同时 nvram 部分存在任何字段,会产生未定义行为。

5. UpdateSMBIOS

Type: plist boolean
Failsafe: false
Description: 更新 SMBIOS 字段。根据 Automatic 的值,这些字段会从 GenericSMBIOS 中读取。

6. UpdateSMBIOSMode

Type: plist string
Failsafe: Create
Description: 更新 SMBIOS 字段的方式有:

  • TryOverwrite — 如果新的数据大小 小于等于 按页对齐的原始数据,且对解锁 legacy region 没有影响,则选择 Overwrite 方式;否则选择 Create 方式。在某些硬件上可能会有问题。
  • Create — 在 AllocateMaxAddress 将表替换为新分配的 EfiReservedMemoryType,没有回退机制。
  • Overwrite — 如果数据大小合适则覆盖现有的 gEfiSmbiosTableGuid 和 gEfiSmbiosTable3Guid,否则将以不明状态中止。
  • Custom — 把第一个 SMBIOS 表(gEfiSmbios(3)TableGuid)写入 gOcCustomSmbios(3)TableGuid,以此来解决固件在 ExitBootServices 覆盖 SMBIOS 内容的问题;否则等同于 Create。需要 AppleSmbios.kext 和 AppleACPIPlatform.kext 打补丁来读取另一个 GUID: "EB9D2D31" - "EB9D2D35" (in ASCII), 这一步由 CustomSMBIOSGuid Quirk 自动完成。

: 使用 Custom 有一个副作用(译者注:我怎么感觉是好事)使得 SMBIOS 设置只对 macOS 生效,避免了与现有的 Windows 激活和依赖机型的 OEM 设置的相关问题。不过,苹果在 Windows 下的特定工具(译者注:如 BootCamp for Windows)可能会受到影响。

7. UseRawUuidEncoding

Type: plist boolean
Failsafe: false
Description: 对 SMBIOS 的 UUID 使用原始编码。

基本上每个 UUID AABBCCDD-EEFF-GGHH-IIJJ-KKLLMMNNOOPP 都是 16 字节的十六进制数字,编码方式有两种:

  • Big Endian — 按原样书写所有字节,顺序不作任何变化({AA BB CC DD EE FF GG HH II JJ KK LL MM NN OO PP})。这种方法也被称为 RFC 4122 编码,或 Raw 编码。
  • Little Endian — 将字节解释为数字,并使用小字节序(Little Endian)编码格式({DD CC BB AA FF EE HH GG II JJ KK LL MM NN OO PP})。

SMBIOS 规范没有明确规定 UUID 的编码格式,直到 SMBIOS 2.6 才说明应使用 Little Endian 编码,这就导致了固件实现和系统软件的双重混乱,因为在此之前不同的厂商使用不同的编码格式。

  • Apple 普遍使用 Big Endian 编码格式,唯一例外的是 macOS 的 SMBIOS UUID。
  • dmidecode 对 SMBIOS 2.5.x 或更低的版本使用 Big Endian 编码格式。对 2.6 或更高的版本使用 Little Endian 编码格式。这三种格式 Acidanthera dmidecode 均可打印。
  • Windows 普遍使用 Little Endian 编码格式,但它只影响数值的观感。

OpenCore 在生成修改过的 DMI 表时,总是设置最新的 SMBIOS 版本(目前是 3.2)。如果启用了 UseRawUuidEncoding,则使用 Big Endian 编码格式来存储 SystemUUID 数据,否则使用 Little Endian 编码格式。

:由于 DataHub 和 NVRAM 中使用的 UUID 是由 Apple 添加的,未经过标准化,所以这个选项并不会影响它们。与 SMBIOS 不同,它们总是以 Big Endian 编码格式存储。

7. Generic

Type: plist dictonary
Description: 在 Automatic 模式下更新所有字段。

:当 Automaticfalse 时将自动忽略此部分,但不可将此部分整段删除。

8. DataHub

Type: plist dictonary
Optional: Automatictrue 时可不填
Description: 在非 Automatic 模式下更新 Data Hub 字段。

:当 Automatictrue 时将自动忽略此部分,但不可将此部分整段删除。

9. Memory

Type: plist dictionary
Optional: When CustomMemory is false
Description: 用于设置自定义的内存配置。

:当 CustomMemoryfalse 时将自动忽略此部分,但不可将此部分整段删除。

10. PlatformNVRAM

Type: plist dictonary
Optional: Automatictrue 时可不填
Description: 在非 Automatic 模式下更新 platform NVRAM 字段。

:当 Automatictrue 时将自动忽略此部分,但不可将此部分整段删除。

11. SMBIOS

Type: plist dictonary
Optional: Automatictrue 时可不填
Description: 在非 Automatic 模式下更新 SMBIOS 字段。

:当 Automatictrue 时将自动忽略此部分,但不可将此部分整段删除。

10.2 Generic 属性

1. SpoofVendor

Type: plist boolean
Failsafe: false
Description: 将 SMBIOS 中的 Vendor 字段设置为 Acidanthera

由于在 SystemManufacturer 中阐述的原因,在 SMBIOS 的 Vendor 字段中使用 Apple 是危险的。但是,某些固件可能无法提供有效值,可能会导致某些软件的破坏。

2. AdviseWindows

Type: plist boolean
Failsafe: false
Description: 在 FirmwareFeatures 中强制提供 Windows 支持。

FirmwareFeatures 中添加如下 bit:

  • FW_FEATURE_SUPPORTS_CSM_LEGACY_MODE (0x1) - 如果没有此 bit,且 EFI 分区不是硬盘中的第一个分区,那么则无法重新启动到硬盘里的 Windows 系统。
  • FW_FEATURE_SUPPORTS_UEFI_WINDOWS_BOOT (0x20000000) - 如果没有此 bit,且 EFI 分区是硬盘中的第一个分区,那么则无法重新启动到硬盘里的 Windows 系统。

3. MaxBIOSVersion

Type: plist boolean
Failsafe: false
Description: 将 BIOSVersion 设置为 9999.999.999.999.999,建议使用 Automatic 选项的旧款 Mac 这样设置, 在运行非官方支持的 macOS 版本时可避免 BIOS 升级。

4. SystemMemoryStatus

Type: plist string
Failsafe: Auto
Description: 用来表示内存是否可以更换和升级,此值也控制着「关于本机」中「内存」选项卡的可见性。

有效值如下:

  • Auto — 使用原始的 PlatformFeature 值。
  • Upgradable — 显式取消设置 PlatformFeaturePT_FEATURE_HAS_SOLDERED_SYSTEM_MEMORY (0x2)
  • Soldered — 显式设置 PlatformFeature 中的 PT_FEATURE_HAS_SOLDERED_SYSTEM_MEMORY (0x2)

:在某些型号的 Mac 上,SPMemoryReporter.spreporter 会自动忽略 PT_FEATURE_HAS_SOLDERED_SYSTEM_MEMORY,并认为其内存是不可升级的,如 MacBookPro10,x 和所有的 MacBookAir

5. ProcessorType

Type: plist integer
Failsafe: 0 (Automatic)
Description: 请参考下文 SMBIOS 章节中的 ProcessorType

6. SystemProductName

Type: plist string
Failsafe: OEM specified or not installed
Description: 请参考下文 SMBIOS 章节中的 SystemProductName

7. SystemSerialNumber

Type: plist string
Failsafe: OEM specified or not installed
Description: 请参考下文 SMBIOS 章节中的 SystemSerialNumber

8. SystemUUID

Type: plist string, GUID
Failsafe: OEM specified or not installed
Description: 请参考下文 SMBIOS 章节中的 SystemUUID

9. MLB

Type: plist string
Failsafe: OEM specified or not installed
Description: 请参考下文 SMBIOS 章节中的 BoardSerialNumber

10. ROM

Type: plist data, 6 bytes
Failsafe: OEM specified or not installed
Description: 参考 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ROM

10.3 DataHub 属性

1. PlatformName

Type: plist string
Failsafe: Not installed
Description: 在 gEfiMiscSubClassGuid 中设置 name。在 Mac 上找到的值为 ASCII 码形式的 platform

2. SystemProductName

Type: plist string
Failsafe: Not installed
Description: 在 gEfiMiscSubClassGuid 中设置 Model。在 Mac 上找到的值等于 Unicode 形式的 SMBIOS SystemProductName

3. SystemSerialNumber

Type: plist string
Failsafe: Not installed
Description: 在 gEfiMiscSubClassGuid 中设置 SystemSerialNumber。在 Mac 上找到的值等于 Unicode 形式的 SMBIOS SystemSerialNumber

4. SystemUUID

Type: plist string, GUID
Failsafe: Not installed
Description: 在 gEfiMiscSubClassGuid 中设置 system-id。在 Mac 上找到的值等于 SMBIOS SystemUUID(字节顺序调换)。

5. BoardProduct

Type: plist string
Failsafe: Not installed
Description: 在 gEfiMiscSubClassGuid 中设置 board-id。在 Mac 上找到的值等于 ASCII 码形式的 SMBIOS BoardProduct

6. BoardRevision

Type: plist data, 1 byte
Failsafe: 0
Description: 在 gEfiMiscSubClassGuid 中设置 board-rev。在 Mac 上找到的值似乎与 Internal Board Revision 相对应(如 01)。

7. StartupPowerEvents

Type: plist integer, 64-bit
Failsafe: 0
Description: 在 gEfiMiscSubClassGuid Sets 中设置 StartupPowerEvents。在 Mac 上找到的值是 Power Management State 位掩码,通常为 0。X86PlatformPlugin.kext 能读取的已知 bit 有:

  • 0x00000001 — Shutdown cause was a PWROK event (Same as GEN_PMCON_2 bit 0)
  • 0x00000002 — Shutdown cause was a SYS_PWROK event (Same as GEN_PMCON_2 bit 1)
  • 0x00000004 — Shutdown cause was a THRMTRIP#event (Same as GEN_PMCON_2 bit 3)
  • 0x00000008 — Rebooted due to a SYS_RESET# event (Same as GEN_PMCON_2 bit 4)
  • 0x00000010 — Power Failure (Same as GEN_PMCON_3 bit 1 PWR_FLR)
  • 0x00000020 — Loss of RTC Well Power (Same as GEN_PMCON_3 bit 2 RTC_PWR_STS)
  • 0x00000040 — General Reset Status (Same as GEN_PMCON_3 bit 9 GEN_RST_STS)
  • 0xffffff80 — SUS Well Power Loss (Same as GEN_PMCON_3 bit 14)
  • 0x00010000 — Wake cause was a ME Wake event (Same as PRSTS bit 0, ME_WAKE_STS)
  • 0x00020000 — Cold Reboot was ME Induced event (Same as PRSTS bit 1 ME_HRST_COLD_STS)
  • 0x00040000 — Warm Reboot was ME Induced event (Same as PRSTS bit 2 ME_HRST_WARM_STS)
  • 0x00080000 — Shutdown was ME Induced event (Same as PRSTS bit 3 ME_HOST_PWRDN)
  • 0x00100000 — Global reset ME Wachdog Timer event (Same as PRSTS bit 6)
  • 0x00200000 — Global reset PowerManagment Wachdog Timer event (Same as PRSTS bit 15)

8. InitialTSC

Type: plist integer, 64-bit
Failsafe: 0
Description: 在 gEfiProcessorSubClassGuid 中设置 InitialTSC。设置初始 TSC 值,通常为 0。

9. FSBFrequency

Type: plist integer, 64-bit
Failsafe: 0 (Automatic)
Description: 在 gEfiProcessorSubClassGuid 中设置 FSBFrequency

设置 CPU FSB 频率。此值等于 CPU 主频除以最高总线比率,以 Hz 为单位。请参考 MSR_NEHALEM_PLATFORM_INFO(CEh) MSR 值来确定 Intel CPU 的最高总线比率。

:此值虽然不是用于 Skylake 或更新的平台,但也可设置。

10. ARTFrequency

Type: plist integer, 64-bit
Failsafe: 0 (Automatic)
Description: 在 gEfiProcessorSubClassGuid 中设置 ARTFrequency

此值包含 CPU ART 频率,即晶体时钟频率。为 Skylake 或更新的平台独有,以 Hz 为单位。Client Intel segment 通常为 24 MHz,Server Intel segment 通常为 25 MHz,Intel Atom CPUs 通常为 19.2 MHz。macOS 10.15 及以下均默认为 24 MHz。

:由于 Intel Skylake X 平台特有 EMI-reduction 电路,其 ART 频率可能会比 24 或 25 MHz 有所损失(大约 0.25%)。参考 Acidanthera Bugtracker。

11. DevicePathsSupported

Type: plist integer, 32-bit
Failsafe: Not installed
Description: 在 gEfiMiscSubClassGuid 中设置 DevicePathsSupported。必须设置为 1 才能确保 AppleACPIPlatform.kext 将 SATA 设备路径添加到 Boot####efi-boot-device-data 变量。所有新款 Mac 都设置为 1

12. SmcRevision

Type: plist data, 6 bytes
Failsafe: Not installed
Description: 在 gEfiMiscSubClassGuid 中设置 REV。自定义属性由 VirtualSMCFakeSMC 读取,用于生成 SMC REV key。

13. SmcBranch

Type: plist data, 8 bytes
Failsafe: Not installed
Description: 在 gEfiMiscSubClassGuid 中设置 RBr。自定义属性由 VirtualSMCFakeSMC 读取,用于生成 SMC RBr key。

14. SmcPlatform

Type: plist data, 8 bytes
Failsafe: Not installed
Description: 在 gEfiMiscSubClassGuid 中设置 RPlt。自定义属性由 VirtualSMCFakeSMC 读取,用于生成 SMC RPlt key。

10.4 Memory 属性

1. DataWidth

Type: plist integer, 16-bit
Failsafe: 0xFFFF (unknown)
SMBIOS: Memory Device (Type 17) — Data Width
Description: 指定内存的数据宽度,以位为单位。DataWidth0TotalWidth8 时,表示改设备仅用于提供 8 个纠错位。

2. Devices

Type: plist array
Failsafe: Empty
Description: 指定要添加的自定义内存设备。

plist dictionary 来描述每个内存设备,具体参见下面的 Memory Devices 属性部分。这里应该填写所有的内存插槽,包括没有插内存的插槽。

3. ErrorCorrection

Type: plist integer, 8-bit
Failsafe: 0x03
SMBIOS: Physical Memory Array (Type 16) — Memory Error Correction
Description: 指定内存支持的主要硬件纠错或检测方法。

  • 0x01 — Other
  • 0x02 — Unknown
  • 0x03 — None
  • 0x04 — Parity
  • 0x05 — Single-bit ECC
  • 0x06 — Multi-bit ECC
  • 0x07 — CRC

4. FormFactor

Type: plist integer, 8-bit
Failsafe: 0x02
SMBIOS: Memory Device (Type 17) — Form Factor
Description: 指定内存的规格。在 Mac 上通常是 DIMM 或 SODIMM。下面列举的是一些常见的规格。

CustomMemory 设置为 false 时,该值会根据所设置的 Mac 机型自动设置。

  • 0x01 — Other
  • 0x02 — Unknown
  • 0x09 — DIMM
  • 0x0D — SODIMM
  • 0x0F — FB-DIMM

5. MaxCapacity

Type: plist integer, 64-bit
Failsafe: 0
SMBIOS: Physical Memory Array (Type 16) — Maximum Capacity
Description: 指定系统支持的最大内存量,以字节为单位。

6. TotalWidth

Type: plist integer, 16-bit
Failsafe: 0xFFFF (unknown)
SMBIOS: Memory Device (Type 17) — Total Width
Description: 指定内存的总宽度,以位为单位,包括任何检查或纠错位。如果没有纠错位,则这个值应该等于 DataWidth

7. Type

Type: plist integer, 8-bit
Failsafe: 0x02
SMBIOS: Memory Device (Type 17) — Memory Type
Description: 指定内存类型。常用的类型如下:

  • 0x01 — Other
  • 0x02 — Unknown
  • 0x0F — SDRAM
  • 0x12 — DDR
  • 0x13 — DDR2
  • 0x14 — DDR2 FB-DIMM
  • 0x18 — DDR3
  • 0x1A — DDR4
  • 0x1B — LPDDR
  • 0x1C — LPDDR2
  • 0x1D — LPDDR3
  • 0x1E — LPDDR4

8. TypeDetail

Type: plist integer, 16-bit
Failsafe: 0x4
SMBIOS: Memory Device (Type 17) — Type Detail
Description: 指定附加的内存类型信息。

  • Bit 0 — Reserved, set to 0
  • Bit 1 — Other
  • Bit 2 — Unknown
  • Bit 7 — Synchronous
  • Bit 13 — Registered (buffered)
  • Bit 14 — Unbuffered (unregistered)

10.4.1 Memory Device 属性

1. AssetTag

Type: plist string
Failsafe: Unknown
SMBIOS: Memory Device (Type 17) — Asset Tag
Description: 指定该内存的资产标签。

2. BankLocator

Type: plist string
Failsafe: Unknown
SMBIOS: Memory Device (Type 17) — Bank Locator
Description: 指定内存设备所在的物理标签库。

3. DeviceLocator

Type: plist string
Failsafe: Unknown
SMBIOS: Memory Device (Type 17) — Device Locator
Description: 指定内存设备所在的物理标签插槽或主板上的位置。

4. Manufacturer

Type: plist string
Failsafe: Unknown
SMBIOS: Memory Device (Type 17) — Manufacturer
Description: 指定该内存设备的制造商。

5. PartNumber

Type: plist string
Failsafe: Unknown
SMBIOS: Memory Device (Type 17) — Part Number
Description: 指定该内存设备的部件号。

6. SerialNumber

Type: plist string
Failsafe: Unknown
SMBIOS: Memory Device (Type 17) — Serial Number
Description: 指定该内存设备的序列号。

7. Size

Type: plist integer, 32-bit
Failsafe: 0
SMBIOS: Memory Device (Type 17) — Size
Description: 指定内存设备的大小,以兆字节为单位。0 表示该插槽未插入内存。

8. Speed

Type: plist integer, 16-bit
Failsafe: 0
SMBIOS: Memory Device (Type 17) — Speed
Description: 指定设备的最大速度,单位为每秒百万传输量(MT/s)。0 表示未知速度。

10.5 PlatformNVRAM 属性

1. BID

Type: plist string
Failsafe: Not installed
Description: 指定 NVRAM 变量 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:HW_BID

2. ROM

Type: plist data, 6 bytes
Failsafe: Not installed
Description: 指定 NVRAM 变量 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:HW_ROM4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ROM

3. MLB

Type: plist string
Failsafe: Not installed
Description: 指定 NVRAM 变量 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:HW_MLB4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:MLB

4. FirmwareFeatures

Type: plist data, 8 bytes
Failsafe: Not installed
Description: 此变量与 FirmwareFeaturesMask 配对使用。指定 NVRAM 变量:

  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:FirmwareFeatures
  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeatures

5. FirmwareFeaturesMask

Type: plist data, 8 bytes
Failsafe: Not installed
Description: 此变量与 FirmwareFeatures 配对使用。指定 NVRAM 变量:

  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:FirmwareFeaturesMask
  • 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeaturesMask

6. SystemUUID

Type: plist string
Failsafe: Not installed
Description: 指定 NVRAM 变量 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:system-id 的值,仅用于启动服务。在 Mac 上找到的值等于 SMBIOS SystemUUID

10.6 SMBIOS 属性

1. BIOSVendor

Type: plist string
Failsafe: OEM specified
SMBIOS: BIOS Information (Type 0) — Vendor
Description: BIOS 供应商。SystemManufacturer 的所有规则都适用。

2. BIOSVersion

Type: plist string
Failsafe: OEM specified
SMBIOS: BIOS Information (Type 0) — BIOS Version
Description: 固件版本。此值更新时会同时影响更新推送配置文件以及 macOS 版本的兼容性。在较旧的固件中看起来类似于 MM71.88Z.0234.B00.1809171422,并且在 BiosId.h 中有所描述。在较新的固件中看起来类似于 236.0.0.0.0220.230.16.0.0 (iBridge: 16.16.2542.0.0,0)。 iBridge 版本是从 BridgeOSVersion 变量中读取的,并且只在具有 T2 芯片的 Mac 上有显示。

Apple ROM VersionBIOS ID:      MBP151.88Z.F000.B00.1811142212Model:        MBP151EFI Version:  220.230.16.0.0Built by:     root@quinoaDate:         Wed Nov 14 22:12:53 2018Revision:     220.230.16 (B&I)ROM Version:  F000_B00Build Type:   Official Build, RELEASECompiler:     Apple LLVM version 10.0.0 (clang-1000.2.42)UUID:         E5D1475B-29FF-32BA-8552-682622BA42E1UUID:         151B0907-10F9-3271-87CD-4BF5DBECACF5

3. BIOSReleaseDate

Type: plist string
Failsafe: OEM specified
SMBIOS: BIOS Information (Type 0) — BIOS Release Date
Description: 固件发布日期。与 BIOSVersion 类似,看起来像是 12/08/2017 这种格式。

4. SystemManufacturer

Type: plist string
Failsafe: OEM specified
SMBIOS: System Information (Type 1) — Manufacturer
Description: 特定主板的 OEM 制造商。除非特别需要,否则最好不要设定,也不要包含 Apple Inc. 字样,这样做会混淆操作系统中的大量服务,例如固件更新、eficheck 以及 Acidanthera 开发的内核扩展(如 Lilu 及其插件)。此外还可能导致某些操作系统(如 Linux)无法引导。

5. SystemProductName

Type: plist string
Failsafe: OEM specified
SMBIOS: System Information (Type 1) — Product Name
Description: 选择偏好的 Mac 机型来把设备标记为系统支持的机型。在任何配置中都应指定该值,以便之后自动生成 SMBIOS 表的相关值和相关配置参数。如果 SystemProductName 与目标操作系统不兼容,可用引导参数 -no_compat_check 来覆盖。

:如果 SystemProductName 未知,并且相关字段也未指定,则默认值会被设定为 MacPro6,1。目前已知产品的列表详见 MacInfoPkg

6. SystemVersion

Type: plist string
Failsafe: OEM specified
SMBIOS: System Information (Type 1) — Version
Description: 产品迭代版本号。看起来类似于 1.1

7. SystemSerialNumber

Type: plist string
Failsafe: OEM specified
SMBIOS: System Information (Type 1) — Serial Number
Description: 按照格式定义的产品序列号。已知的序列号的格式在 macserial 中可以找到。

8. SystemUUID

Type: plist string, GUID
Failsafe: OEM specified
SMBIOS: System Information (Type 1) — UUID
Description: UUID 被设计为在时间和空间上都是唯一的标识符,其生成是随机与去中心化的。

9. SystemSKUNumber

Type: plist string
Failsafe: OEM specified
SMBIOS: System Information (Type 1) — SKU Number
Description: Mac 主板 ID (board-id)。在旧型号的机器中看起来类似于 Mac-7BA5B2D9E42DDD94Mac-F221BEC8。有时可以直接留空。

10. SystemFamily

Type: plist string
Failsafe: OEM specified
SMBIOS: System Information (Type 1) — Family
Description: 机型名称,看起来类似于 iMac Pro

11. BoardManufacturer

Type: plist string
Failsafe: OEM specified
SMBIOS: Baseboard (or Module) Information (Type 2) — Manufacturer
Description: 主板制造商。SystemManufacturer 的所有规则都适用。

12. BoardProduct

Type: plist string
Failsafe: OEM specified
SMBIOS: Baseboard (or Module) Information (Type 2) — Product
Description: Mac 主板 ID (board-id)。在旧型号机器中看起来类似于 Mac-7BA5B2D9E42DDD94Mac-F221BEC8

13. BoardVersion

Type: plist string
Failsafe: OEM specified
SMBIOS: Baseboard (or Module) Information (Type 2) — Version
Description: 主板版本号。有各种各样,可能与 SystemProductNameSystemProductVersion 匹配。

14. BoardSerialNumber

Type: plist string
Failsafe: OEM specified
SMBIOS: Baseboard (or Module) Information (Type 2) — Serial Number
Description: 主板序列号,有对应的格式,具体格式见 macserial 的描述。

15. BoardAssetTag

Type: plist string
Failsafe: OEM specified
SMBIOS: Baseboard (or Module) Information (Type 2) — Asset Tag
Description: 资产标签号。有各种各样,可以留空或填 Type2 - Board Asset Tag

16. BoardType

Type: plist integer
Failsafe: OEM specified
SMBIOS: Baseboard (or Module) Information (Type 2) — Board Type
Description: 0xA (Motherboard (includes processor, memory, and I/O)) 或 0xB (Processor/Memory Module),详见 Table 15 — Baseboard: Board Type。

译者注:此处提及的 Table 请参见 DMTF Specifications 中的相关文档。

17. BoardLocationInChassis

Type: plist string
Failsafe: OEM specified
SMBIOS: Baseboard (or Module) Information (Type 2) — Location in Chassis
Description: 各种各样,可以留空或填 Part Component

18. ChassisManufacturer

Type: plist string
Failsafe: OEM specified
SMBIOS: System Enclosure or Chassis (Type 3) — Manufacturer
Description: 主板制造商。SystemManufacturer 的所有规则都适用。

19. ChassisType

Type: plist integer
Failsafe: OEM specified
SMBIOS: System Enclosure or Chassis (Type 3) — Type
Description: 机箱类型,详见 Table 17 — System Enclosure or Chassis Types。

译者注:此处所提及的 Table 请参见 DMTF Specifications 中的相关文档。

20. ChassisVersion

Type: plist string
Failsafe: OEM specified
SMBIOS: System Enclosure or Chassis (Type 3) — Version
Description: 应和 BoardProduct 符合。

21. ChassisSerialNumber

Type: plist string
Failsafe: OEM specified
SMBIOS: System Enclosure or Chassis (Type 3) — Version
Description: 应和 SystemSerialNumber 符合。

22. ChassisAssetTag

Type: plist string
Failsafe: OEM specified
SMBIOS: System Enclosure or Chassis (Type 3) — Asset Tag Number
Description: 机箱类型名称。有各种各样,可以留空或填 MacBook-Aluminum

23. PlatformFeature

Type: plist integer, 32-bit
Failsafe: 0xFFFFFFFF
SMBIOS: APPLE_SMBIOS_TABLE_TYPE133 - PlatformFeature
Description: 平台功能位掩码,详见 AppleFeatures.h。填写 0xFFFFFFFF 值时不提供此表。

24. SmcVersion

Type: plist data, 16 bytes
Failsafe: All zero
SMBIOS: APPLE_SMBIOS_TABLE_TYPE134 - Version
Description: ASCII 字符串,包含 SMC 版本号(大写)。配备 Apple T2 安全芯片的 Mac 没有这一字段。当此值设置为零时,这一选项会被忽略。

25. FirmwareFeatures

Type: plist data, 8 bytes
Failsafe: 0
SMBIOS: APPLE_SMBIOS_TABLE_TYPE128 - FirmwareFeatures and ExtendedFirmwareFeatures
Description: 64 位固件功能位掩码。详见 AppleFeatures.h。低 32 位与 FirmwareFeatures 匹配,高 64 位与 ExtendedFirmwareFeatures 匹配。

26.FirmwareFeaturesMask

Type: plist data, 8 bytes
Failsafe: 0
SMBIOS: APPLE_SMBIOS_TABLE_TYPE128 - FirmwareFeaturesMask and ExtendedFirmwareFeaturesMask
Description: 扩展固件功能位掩码。详见 AppleFeatures.h。低 32 位与 FirmwareFeatures 匹配,高 64 位与 ExtendedFirmwareFeatures 匹配。

27. ProcessorType

Type: plist integer, 16-bit
Failsafe: 0 (Automatic)
SMBIOS: APPLE_SMBIOS_TABLE_TYPE131 - ProcessorType
Description: 由处理器的主要和次要类型组成。

自动生成的值(Automatic)是根据当前的 CPU 规格提供的最准确的值,一般不会有问题,如果有问题请务必到 bugtracker 创建一个 Issue,并附上 sysctl machdep.cpudmidecode 的输出结果。所有可用值及其限制条件(指该值只有在核心数匹配的情况下才适用)都可以在 Apple SMBIOS 定义 头文件 里找到。

UEFI

11.1 简介

UEFI(统一可扩展固件接口)是一种规范,用于定义操作系统和平台固件之间的软件接口。本部分允许加载其他 UEFI 模块 和/或 对板载固件进行调整。要检查固件内容,应用修改并执行升级,可以使用 UEFITool 和其他实用程序。

11.2 驱动列表

根据固件不同、可能需要不同的驱动程序。加载不兼容的驱动程序可能会导致无法启动系统,甚至导致固件永久性损坏。OpenCore 目前对以下 UEFI 驱动提供支持。OpenCore 可能兼容其他 UEFI 驱动,但不能确定。

  • AudioDxe* — UEFI 固件中的 HDA 音频驱动程序,适用于大多数 Intel 和其他一些模拟音频控制器。参考 acidanthera/bugtracker#740 来了解 AudioDxe 的已知问题。
  • CrScreenshotDxe* — 截图驱动。启用后,按下 F10 将能够截图并保存在 EFI 分区根目录下。该驱动基于 Nikolaj Schlej 修改的 LongSoft 开发的 CrScreenshotDxe
  • ExFatDxe — 用于 Bootcamp 支持的专有 ExFAT 文件系统驱动程序,通常可以在 Apple 固件中找到。 对于 Sandy Bridge 和更早的 CPU,由于缺少 RDRAND 指令支持,应使用 ExFatDxeLegacy 驱动程序。
  • HfsPlus — Apple 固件中常见的具有 Bless 支持的专有 HFS 文件系统驱动程序。对于 Sandy Bridge 和更早的 CPU,由于这些 CPU 缺少 RDRAND 指令支持,应使用 HfsPlusLegacy 驱动程序。
  • HiiDatabase* — 来自 MdeModulePkg 的 HII 服务驱动。Ivy Bridge 及其以后的大多数固件中都已内置此驱动程序。某些带有 GUI 的应用程序(例如 UEFI Shell)可能需要此驱动程序才能正常工作。
  • EnhancedFatDxe — 来自 FatPkg 的 FAT 文件系统驱动程序。这个驱动程序已经被嵌入到所有 UEFI 固件中,无法为 OpenCore 使用。众所周知,许多固件的 FAT 支持实现都有错误,导致在尝试写操作时损坏文件系统。如果在引导过程中需要写入 EFI 分区,则可能需要将此驱动程序嵌入固件中。
  • NvmExpressDxe* — 来自MdeModulePkg 的 NVMe 驱动程序。从 Broadwell 开始的大多数固件都包含此驱动程序。对于 Haswell 以及更早的固件,如果安装了 NVMe SSD 驱动器,则将其嵌入固件中可能会更理想。
  • OpenCanopy* — OpenCore 插件之一,用于实现图形引导界面。
  • OpenRuntime* — OpenCore 插件之一,原名 FwRuntimeServices.efi,用于实现 OC_FIRMWARE_RUNTIME 协议,通过支持只读、只写 NVRAM 变量,提升了 OpenCore 和 Lilu 的安全性。有些 Quirk 如 RequestBootVarRouting 依赖此驱动程序。由于 Runtime 驱动的性质(与目标操作系统并行运行),因此它不能在 OpenCore 本身实现,而是与 OpenCore 捆绑在一起。
  • OpenUsbKbDxe* — USB 键盘驱动,在自定义 USB 键盘驱动程序的基础上新增了对 AppleKeyMapAggregator 协议的支持。这是内置的 KeySupport 的等效替代方案。根据固件不同,效果可能会更好或者更糟。
  • PartitionDxe — 一个专门的分区管理驱动程序,用于加载旧版 macOS 的 DMG 映像(如 macOS 10.9 的分区映像)。对于 Sandy Bridge 或者更早的 CPU,由于缺少 RDRAND 指令支持,应使用 PartitionDxeLegacy 驱动程序。
  • Ps2KeyboardDxe* — 从 MdeModulePkg 提取出来的 PS/2 键盘驱动。OpenDuetPkg 和一些固件可能不包括这个驱动,但对于 PS/2 键盘来说该驱动是必须的。注意,和 OpenUsbKbDxe 不同,该驱动不提供对 AppleKeyMapAggregator 的支持、因此需要启用 KeySupport 这个 Quirk。
  • Ps2MouseDxe* — 从 MdeModulePkg 提取出来的 PS/2 鼠标驱动。一些非常老旧的笔记本的固件中可能不包含该驱动,但是这些笔记本需要依赖该驱动才能在引导界面使用触控板。
  • UsbMouseDxe* — 从 MdeModulePkg 提取出来的 USB 鼠标驱动。一般只有虚拟机(如 OVMF)的固件中可能不包含该驱动,这些虚拟机需要依赖该驱动才能在引导界面使用鼠标。
  • VBoxHfs — 带有 Bless 支持的 HFS 文件系统驱动。是 Apple 固件中 HfsPlus 驱动的开源替代。虽然功能完善,但是启动速度比 HFSPlus 慢三倍,并且尚未经过安全审核。
  • XhciDxe* — 来自 MdeModulePkg 的 XHCI USB controller 驱动程序。从 Sandy Bridge 开始的大多数固件中都包含此驱动程序。在较早的固件或旧系统可以用于支持外部 USB 3.0 PCI 卡。

标有 * 的驱动程序是 OpenCore 附带的。如果要从 UDK(EDK II)编译驱动程序,请使用编译 OpenCore 的相同命令,但要注意选择相应的软件包:

git clone https://github.com/acidanthera/audk UDK
cd UDK
source edksetup.sh
make -C BaseTools
build -a X64 -b RELEASE -t XCODE5 -p FatPkg/FatPkg.dsc
build -a X64 -b RELEASE -t XCODE5 -p MdeModulePkg/MdeModulePkg.dsc

11.3 工具与应用程序

一些不依赖 OpenCore 的工具可以帮助调试固件和硬件。下面列出了一些已知的工具。虽然有些工具可以从 OpenCore 启动,但大部分工具都应该直接或从 OpenCoreShell 中单独运行。

要启动到 OpenShell 或任何其他工具,直接将 OpenShell.efi 保存在 FAT32 分区中的 EFI/BOOT/BOOTX64.EFI 下。此时分区方案是 GPT 还是 MBR 并不重要。

这种方法在 Mac 和其他计算机上都可以使用。还有一种只能在 Mac 上的 HFS+ 或 APFS 分区上使用的方法:

sudo bless --verbose --file /Volumes/VOLNAME/DIR/OpenShell.efi --folder /Volumes/VOLNAME/DIR/ --setBoot
Listing 3: Bless 工具

注 1:你可能需要将 /System/Library/CoreServices/BridgeVersion.bin 拷贝到 /Volumes/VOLNAME/DIR

注 2:为了能够使用 bless,你可能需要 禁用系统完整性保护。

注 3:为了能够正常启动,你可能需要 禁用 Apple 安全启动(如果有的话)。

一些已知的 UEFI 工具(内置工具已用 * 标出):

  • BootKicker* — 进入 Apple 的 BootPicker 菜单(仅 Mac 同款显卡才可以使用)。
  • ChipTune* — 测试 BeepGen 协议,生成不同频率和长度的音频信号。
  • CleanNvram* — 重置 NVRAM,以一个单独的工具呈现。
  • FwProtect* — 解锁和回锁 NVRAM 保护,让其他工具在从 OpenCore 启动时能够获得完整的 NVRAM 访问权限。
  • GopStop* — 用一个 简单的场景 测试 GraphicOutput 协议。
  • KeyTester* — 在 SimpleText 模式下测试键盘输入。
  • MemTest86 — 内存测试工具。
  • OpenCore Shell* — 由 OpenCore 配置的 UEFI Shell,与绝大部分固件兼容。
  • PavpProvision — 执行 EPID 配置(需要配置证书数据)。
  • ResetSystem* — 用于执行系统重置的实用程序。以重置类型作为参数:ColdReset, Firmware, WarmReset, Shutdown。默认为 ColdReset
  • RtcRw* — 读取和写入 RTC (CMOS) 存储器的使用程序。
  • VerifyMsrE2* — 检查 CFG Lock(MSR 0xE2 写保护)在所有 CPU 核心之间的一致性。

11.4 OpenCanopy

OpenCanopy 是一个 OpenCore 的图形化界面接口,基于 OpenCorePkg OcBootManagementLib 实现,提供与现有的文字模式类似的功能。当 PickerMode 设置为 External 时启用。

OpenCanopy 所需的图象资源位于 Resources 目录下,一些简单的资源(字体和图标)可以在 OcBinaryData 仓库 中获取。可以在网络上找到自定义图标(比如 这里 和 这里)。

OpenCanopy 为 PickerAttributes 提供了全面的支持,并提供了一套可配置的内置图标集。默认选择的图标由 DefaultBackgroundColor 变量决定,当该变量的值定义为浅灰时,则使用 Old 前缀的图标,定义为其他颜色时则使用没有前缀名的图标。

预定义的图标放在 \EFI\OC\Resources\Image 目录下。下面提供了所支持的图标的完整列表(.icns 格式)。可选图标如未提供,将使用最接近的可用的图标。外置设备的条目将使用 Ext 前缀的图标(如 OldExtHardDrive.icns)。

:以下标注的所有尺寸均为 1x 缩放级别的标准尺寸,其他缩放级别的尺寸须作相应调整。

  • Cursor — 鼠标光标(必需,最大尺寸 144x144)。
  • Selected — 选定的项目(必需,144x144)。
  • Selector — 选择项目(必需,最大尺寸 144x40)。
  • Left — 向左滚动(必需,最大尺寸 40x40)。
  • Right — 向右滚动(必需,最大尺寸 40x40)。
  • HardDrive — 通用的 OS(必需,128x128)。
  • Background — 居中的背景图片。
  • Apple — Apple OS (128x128)。
  • AppleRecv — Apple Recovery OS (128x128)。
  • AppleTM — Apple Time Machine (128x128)。
  • Windows — Windows (128x128)。
  • Other — 自定义条目(见 Entries,128x128)。
  • ResetNVRAM — 重置 NVRAM 工具或系统动作(128x128)。
  • Shell — 具有 UEFI Shell 名称的条目(如 OpenShell,128x128)。
  • Tool — 其他工具(128x128)。

预定义的标签放在 \EFI\OC\Resources\Label 目录下。每个标签都有 .lbl.l2x 的后缀,以代表缩放级别。完整的标签列表如下所示。所有标签都是必需的。

  • EFIBoot — 通用的 OS。
  • Apple — Apple OS。
  • AppleRecv — Apple Recovery OS。
  • AppleTM — Apple Time Machine。
  • Windows — Windows。
  • Other — 自定义条目(见 Entries)。
  • ResetNVRAM — 重置 NVRAM 工具或系统动作。
  • Shell — 具有 UEFI Shell 名称的条目(如 OpenShell)。
  • Tool — 其他工具。

:所有标签的高度必须为 12px,宽度不限。

可以通过附带的实用程序来生成标签和图标:disklabelicnspack。字体为 12pt 的 Helvetica,比例缩放。

字体格式对应于 AngelCode binary BMF。虽然有很多工具可以生成字体文件,但目前还是建议使用 dpFontBaker 来生成位图字体(用 CoreText 达到最佳效果),并使用 fonverter 将其导出为二进制格式。

11.5 OpenRuntime

OpenRuntime 是一个 OpenCore 的插件,提供了对 OC_FIRMWARE_RUNTIME 协议的实现。该协议对 OpenCore 的部分功能提供了支持,而这部分功能由于需要 Runtime(如操作系统)中运行、因此无法内置在 OpenCore 中。该协议提供了包括但不限于如下功能:

  • NVRAM 命名空间,允许隔离操作系统对所选变量的访问(如 RequestBootVarRoutingProtectSecureBoot)。
  • 只读和只写的 NVRAM 变量,增强了 OpenCore、Lilu 以及 Lilu 插件的安全性,比如 VirtualSMC,实现了 AuthRestart 支持。
  • NVRAM 隔离,能够保护所有变量避免被不信任的操作系统写入(如 DisableVariableWrite)。
  • UEFI Runtime Services 内存保护管理,以避开只读映射的问题(如 EnableWriteUnprotector)。

11.6 属性列表

1. APFS

Type: plist dict
Failsafe: None
Description: 配置 APFS 分区驱动,具体配置内容参见下文 APFS 属性部分。

2. Audio

Type: plist dict
Failsafe: None
Description: 配置音频后端支持,具体配置如下文所述。

音频支持为上游协议提供了一种与所选硬件和音频资源交互的方式。所有音频资源应该保存在 \EFI\OC\Resources\Audio 目录。目前支持的音频文件格式为 MP3 和 WAVE PCM。虽然支持哪种音频流格式取决于驱动程序,但大多数常见的音频卡都支持 44100 或 48000Hz 的 16 位立体声。

音频文件的路径是由音频的类型、本地化语言和路径决定的。每个文件名看起来都类似于:[audio type]_[audio localisation]_[audio path].[audio ext]。对于没有本地化的文件,其文件名不包含语言代码,看起来类似于:[audio type]_[audio path].[audio ext]。其中音频扩展名为 mp3wav

  • OpenCore 音频文件的音频类型可以是 OCEFIAudio,macOS 引导程序的音频文件的音频类型可以是 AXEFIAudio
  • 音频本地化语言由两个字母的语言代码表示(如 en),中文、西班牙语和葡萄牙语除外。具体请看 APPLE_VOICE_OVER_LANGUAGE_CODE 的定义 来了解所有支持的本地化列表。
  • 音频路径是对应于文件标识符的基本文件名。macOS 引导程序的音频路径参考 APPLE_VOICE_OVER_AUDIO_FILE 的定义。OpenCore 的音频路径参考 OC_VOICE_OVER_AUDIO_FILE 的定义。唯一例外的是 OpenCore 启动提示音文件:OCEFIAudio_VoiceOver_Boot.mp3

macOS 引导程序和 OpenCore 的音频本地化是分开的。macOS 引导程序是在 systemLanguage.utf8 文件中的 preferences.efires 归档中设置,并由操作系统控制。OpenCore 则是使用 prev-lang:kbd 变量的值来控制。当某一特定文件的音频本地化缺失时,将会使用英语(en)来代替。示例音频文件可以在 OcBinaryData 仓库 中找到。

3. ConnectDrivers

Type: plist boolean
Failsafe: false
Description: 驱动程序加载后执行 UEFI 控制器连接操作。

此选项对于加载某些遵循 UEFI 驱动模型的 驱动程序(如文件系统驱动、音频输出驱动)很有用,因为这些驱动可能无法自行启动。此选项对会自动连接的驱动程序来说是不必要的,并且可能会稍微减慢启动速度。

:某些固件(特别是 Apple 的)仅连接包含操作系统的驱动器以加快启动过程。启用此选项可以在拥有多个驱动器时查看所有引导选项。

4. Drivers

Type: plist array
Failsafe: None
Description: 从 OC/Drivers 目录下加载选择的驱动。设计为填充 UEFI 驱动程序加载的文件名。

5. Input

Type: plist dict
Failsafe: None
Description: 从下面的 Input 属性部分,应用为输入(键盘和鼠标)而设计的个性化设置。

6. Output

Type: plist dict
Failsafe: None
Description: 从下面的 Output 属性部分,应用为输出(文本和图形)而设计的个性化设置。

7. ProtocolOverrides

Type: plist dict
Failsafe: None
Description: 强制执行从下面的 ProtocolOverrides 属性部分所选协议的内置版本。

:所有协议实例的安装都优先于驱动程序的加载。

8. Quirks

Type: plist dict
Failsafe: None
Description: 从下面的 Quirks 属性部分,应用个性化的固件 Quirks。

9. ReservedMemory

Type: plist array
Description: 设计为用 plist dict 值填充,用于描述对特定固件和硬件功能要求很高的内存区域,这些区域不应该被操作系统使用。比如被 Intel HD 3000 破坏的第二个 256MB 区域,或是一个有错误的 RAM 的区域。

11.7 APFS 属性

1. EnableJumpstart

Type: plist boolean
Failsafe: False
Description: 从一个 APFS 容器中加载 APFS 驱动。

APFS 的 EFI 驱动内置在所有可以作为系统启动盘的 APFS 容器之中。这一选项将会根据基于 ScanPolicy 找到的 APFS 容器,从中加载 APFS 驱动。更多详情请查看 苹果 APFS 文件系统参考手册 中的 EFI Jummpstart 章节。

2. GlobalConnect

Type: plist boolean
Failsafe: false
Description: 在 APFS 加载期间执行完整的设备连接。

代替通常情况下用于 APFS 驱动程序加载的分区句柄连接,每一个句柄都是递归连接的。这可能会比平时花费更多的时间,但是是某些固件访问 APFS 分区的唯一方法,比如在旧的惠普笔记本电脑上发现的那样。

3. HideVerbose

Type: plist boolean
Failsafe: False
Description: 是否隐藏 APFS 驱动的 verbose 信息。

APFS 驱动的 verbose 信息有助于 debug。

4. JumpstartHotPlug

Type: plist boolean
Failsafe: False
Description: 允许从进入 OpenCore 引导菜单后插入的可移除硬盘上的 APFS 容器中加载 APFS 驱动。

这一选项不仅提供了进入 OpenCore 以后再插入 U 盘的支持,而且还允许了在 OpenCore 引导菜单下 APFS U 盘的热插拔。

5. MinDate

Type: plist integer
Failsafe: 0
Description: 允许加载的最老 APFS 驱动的发布日期。

APFS 驱动的版本号基于其发布日期。较旧版本的 APFS 驱动可能与较新的系统不兼容、或者有未修补的漏洞。通过这一选项可以避免 OpenCore 加载过旧版本的 APFS 驱动。

  • 0 — 使用默认数值。随着未来的更新,OpenCore 内置的默认数值也会不断更新。如果你会一直更新你的系统,我们推荐使用这一数值。目前默认数值为 2018/06/21
  • -1 — 允许使用任何版本的 APFS 驱动(强烈不推荐)。
  • 其他数值 — 数值格式应为形如 20200401 的格式。你可以从 OpenCore 的启动日志和 OcApfsLib 中找到 APFS 驱动的版本号。

6. MinVersion

Type: plist integer
Failsafe: 0
Description: 允许加载的最老 APFS 驱动的版本号。

APFS 驱动的版本号和 macOS 版本相关。较旧版本的 APFS 驱动可能与较新的系统不兼容、或者有未修补的漏洞。通过这一选项可以避免 OpenCore 加载过旧版本的 APFS 驱动。

  • 0 — 使用默认数值。随着未来的更新,OpenCore 内置的默认数值也会不断更新。如果你会一直更新你的系统,我们推荐使用这一数值。目前默认数值选自 App Store 中能够下载到的 High Sierra(748077008000000)。
  • -1 — 允许使用任何版本的 APFS 驱动(强烈不推荐)。
  • 其他数值 — 数值格式应为形如 1412101001000000 的格式(这是 macOS Catalina 10.15.4 的 APFS 驱动版本号),你可以从 OpenCore 的启动日志和 OcApfsLib 中找到 APFS 驱动的版本号。

11.8 Audio 属性

1. AudioCodec

Type: plist integer
Failsafe: 0
Description: 特定音频控制器上的编解码器地址,用于音频支持。

一般来说,这里包含了内置模拟音频控制器(HDEF)上的第一个音频编解码器地址。音频编解码器地址(比如 2)可以在调试日志中找到(已用粗斜体标出):

OCAU: 1/3 PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x1)/VenMsg(<redacted>,00000000) (4 outputs)
OCAU: 2/3 PciRoot(0x0)/Pci(0x3,0x0)/VenMsg(<redacted>,00000000) (1 outputs)
OCAU: 3/3 PciRoot(0x0)/Pci(0x1B,0x0)/VenMsg(<redacted>,02000000) (7 outputs)

除此之外,该值还可以在 I/O 注册表的 IOHDACodecDevice class 中获得,包含在 IOHDACodecAddress 字段中。

2. AudioDevice

Type: plist string
Failsafe: empty string
Description: 特定音频控制器的设备路径,用于音频支持。

一般来说,这里包含了内置模拟音频控制器(HDEF)的设备路径,比如 PciRoot(0x0)/Pci(0x1b,0x0)。认可的音频控制器列表可以在调试日志中找到(已用粗斜体标出):

OCAU: 1/3 PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x1)/VenMsg(<redacted>,00000000) (4 outputs)
OCAU: 2/3 PciRoot(0x0)/Pci(0x3,0x0)/VenMsg(<redacted>,00000000) (1 outputs)
OCAU: 3/3 PciRoot(0x0)/Pci(0x1B,0x0)/VenMsg(<redacted>,02000000) (7 outputs)

除此之外,该值还可以在 macOS 中通过 gfxutil -f HDEF 命令来获取。如果指定了空的设备路径,则会使用第一个可用的音频控制器。

3. AudioOut

Type: plist integer
Failsafe: 0
Description: 特定编解码器的输出端口的索引,从 0 开始。

一般来说,这里包含了内置模拟音频控制器(HDEF)的绿色输出的索引。调试日志中输出节点的数量如下(已用粗斜体标出):

OCAU: 1/3 PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x1)/VenMsg(<redacted>,00000000) (4 outputs)
OCAU: 2/3 PciRoot(0x0)/Pci(0x3,0x0)/VenMsg(<redacted>,00000000) (1 outputs)
OCAU: 3/3 PciRoot(0x0)/Pci(0x1B,0x0)/VenMsg(<redacted>,02000000) (7 outputs)

找到正确端口的最快办法就是暴力地尝试 0N - 1 的值。

4. AudioSupport

Type: plist boolean
Failsafe: false
Description: 通过连接到固件音频驱动程序以激活音频支持。

启用此设置可将音频播放从内置协议路由到音频控制器(AudioDevice)上指定编解码器(AudioCodec)的专用音频端口(AudioOut)。

5. MinimumVolume

Type: plist integer
Failsafe: 0
Description: 听到的最小音量水平,从 0100

当计算出的音量小于 MinimumVolume 时,屏幕阅读器将使用这个音量。当计算出的音量小于 MinimumVolume,则不播放 Mac 特有的开机启动声音。

6. PlayChime

Type: plist string
Failsafe: Auto
Description: 开机时播放 Mac 特有的风铃的声音。

启用此设置可通过内置的音频支持来播放开机时播放的声音。音量大小由 MinimumVolumeVolumeAmplifier 的设置,以及 SystemAudioVolume NVRAM 变量来决定。可用的值有:

  • Auto — 当 StartupMute NVRAM 变量不存在或设置为 00 时,启用开机声音。
  • Enabled — 无条件启用开机声音。
  • Disabled — 无条件禁用开机声音。

Enable 是可以与 StartupMute NVRAM 变量分开使用的,以此来避免在固件能够播放启动铃声时发生冲突。

7. SetupDelay

Type: plist integer
Failsafe: 0
Description: 音频编解码器重新配置的延迟,单位为微秒。

某些编解码器在重新配置后需要特定延迟(由供应商提供,例如音量设置),此选项可对其进行配置。一般来说,必要的延迟时间可能长达 0.5 秒。

8. VolumeAmplifier

Type: plist integer
Failsafe: 0
Description: 系统音量到原始音量的线性换算的乘法系数,从 01000

SystemAudioVolume 读取的音量范围会因编解码器的不同而不同。为了将 [0, 127] 范围内的值转换为原始音量范围 [0, 100] 内的值,所读取的值按比例调整为 VolumeAmplifier 的百分数:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nq60L2Zd-1655987034338)(/img/11-1.svg)]

:macOS 中使用的转换并不是线性的,但非常接近,因此我们忽略了这种细微差别。

11.9 Input 属性

1. KeyFiltering

Type: plist boolean
Failsafe: false
Description: 启用键盘输入的合理性检查。

显然,有些主板,如 GA Z77P-D3,可能会在 EFI_INPUT_KEY 中返回所有输入协议的未初始化数据。这个选项会舍弃那些既不是 ASCII 码,也不是 UEFI 规范中定义的键(见版本 2.8 的表 107 和 108)。

2. KeyForgetThreshold

Type: plist integer
Failsafe: 0
Description: 两次按键之间的间隔时间,单位为毫秒。

AppleKeyMapAggregator 协议应该包含当前按下的键的固定长度的缓冲。但是大部分驱动程序仅将按键按下报告为中断、并且按住按键会导致在一定的时间间隔后再提交按下行为。一旦超时到期,我们就是用超时从缓冲区中删除一次按下的键,并且没有新提交。

此选项允许根据你的平台设置此超时。在大多数平台上有效的推荐值为 5 毫秒。作为参考,在 VMWare 上按住一个键大约每 2 毫秒就会重复一次,而在 APTIO V 上是 3 - 4 毫秒。因此,可以在较快的平台上设置稍低的值、在较慢的平台设置稍高的值,以提高响应速度。

:某些平台可能需要更高或者更低的值。例如,当 OpenCanopy 检测到按键丢失的时候,尝试稍高的值(比如增加到 10),当检测到按键停滞时,尝试稍低的值。由于每个平台各不相同,因此检查从 125 的每个值可能会比较合理。

3. KeyMergeThreshold

Type: plist integer
Failsafe: 0
Description: 按住按键被重置的间隔时间,单位为毫秒。

KeyForgetThreshold 类似,这一选项适用于按键提交的顺序。为了能够识别同时按下的按键,我们需要设置一个超时时间,在这个时间内可以假定这两个按键是同时按下的。

对于 VMWare,同时按下多个键的间隔是 2 毫秒。对于 APTIO V 平台为 1 毫秒。一个接一个地按下按键会导致 6 毫秒和 10 毫秒的延迟。此选项的建议值为 2 毫秒,但对于较快的平台可以选取较小的值,反之亦然。

4. KeySupport

Type: plist boolean
Failsafe: false
Description: 启用这一选项后将会开启内置键盘支持。

这一选项基于 AppleGenericInputAptioInputFix),激活内部键盘拦截器驱动程序以填充 AppleKeyMapAggregator 数据库以实现输入功能。如果使用了单独的驱动程序(如 AppleUsbKbDxe),则永远不要开启这一选项。

5. KeySupportMode

Type: plist string
Failsafe: Auto
Description: 将内部键盘的输入转换设置为 AppleKeyMapAggregator 协议模式。

  • Auto — 从下述选项中自动选择
  • V1 — UEFI 传统输入协议 EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
  • V2 — UEFI 现代标准输入协议 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
  • AMI — APTIO 输入协议 AMI_EFIKEYCODE_PROTOCOL.

:目前 V1V2AMI 区别于 Auto,只对特定的协议进行过滤。这种情况在未来的版本中可能会改变。

6. KeySwap

Type: plist boolean
Failsafe: false
Description: 启用后将交换 CommandOption

此选项对于 Option 键位于 Command 右侧的键盘来说会很有用。

7. PointerSupport

Type: plist boolean
Failsafe: false
Description: 启用后将试图修复 UEFI 选择器协议。

该选项通过选择 OEM 协议实现标准 UEFI 指针协议 EFI_SIMPLE_POINTER_PROTOCOL。该选项在 Z87 华硕主板可能有用(该主板的 EFI_SIMPLE_POINTER_PROTOCOL 存在问题)。

8. PointerSupportMode

Type: plist string
Failsafe: empty string
Description: 设置用于内部指针驱动程序的 OEM 协议。

目前只支持 ASUS 值,使用的是 Z87 和 Z97 主板上的特殊协议。更多详情请参考 LongSoft/UefiTool#116。如果启用了 PointerSupport,此处值不能为空。

9. TimerResolution

Type: plist integer
Failsafe: 0
Description: 固件始终刷新的频率(单位 100 纳秒)

设置较低的值可以提高界面和输入处理性能的响应能力。建议值为 50000(即 5 毫秒)或稍高一些。选择 ASUS Z87 主板时,请使用 60000,苹果主板请使用 100000。你也可以将此值保留为 0,由 OpenCore 自动计算。

11.10 Output 属性

1. TextRenderer

Type: plist string
Failsafe: BuiltinGraphics
Description: 选择通过标准控制台输出的渲染器。

目前支持两种渲染器:BuiltinSystemSystem 渲染器使用固件服务进行文本渲染。Builtin 渲染器则绕过固件服务,自行渲染文本。不同的渲染器支持的选项也不同。建议使用 Builtin 渲染器,因为它支持 HiDPI 模式,并能够使用全屏分辨率。

UEFI 固件一般用两种渲染模式来支持 ConsoleControlGraphicsText。有些固件不支持 ConsoleControl 和渲染模式。OpenCore 和 macOS 希望文本只在 Graphics 模式下显示,而图形可以在任何模式下绘制。由于 UEFI 规范并不要求这样做,因此具体的行为各不相同。

有效值为文本渲染器和渲染模式的组合:

  • BuiltinGraphics — 切换到 Graphics 模式,并使用 Builtin 渲染器和自定义 ConsoleControl
  • BuiltinText — 切换到 Text 模式,并使用 Builtin 渲染器和自定义 ConsoleControl
  • SystemGraphics — 切换到 Graphics 模式,并使用 System 渲染器和自定义 ConsoleControl
  • SystemText — 切换到 Text 模式,并使用 System 渲染器和自定义 ConsoleControl
  • SystemGeneric — 使用 System 渲染器和系统 ConsoleControl,前提是它们能正常工作。

BuiltinGraphics 的用法通常是比较直接的。对于大多数平台,需要启用 ProvideConsoleGop,将 Resolution 设置为 Max。某些非常老旧且问题很多的笔记本只能在 Text 模式下绘图,对它们来说,BuiltinTextBuiltinGraphics 的替代选择。

System 协议的用法比较复杂。一般来说,首选设置 SystemGraphicsSystemText。启用 ProvideConsoleGop,将 Resolution 设置为 Max,启用 ReplaceTabWithSpace 几乎在所有平台上都很有用。SanitiseClearScreenIgnoreTextInGraphicsClearScreenOnModeSwitch 比较特殊,它们的用法取决于固件。

:某些 Mac,比如 MacPro5,1,在使用较新的 GPU 时,可能会出现控制台输出中断的情况,因此可能只有 BuiltinGraphics 对它们有效。

2. ConsoleMode

Type: plist string
Failsafe: Empty string
Description: 按照 WxH(例如 80x24)格式的字符串所指定的方式设置控制台的输出模式。

设置为空字符串则不会改变控制台模式。设置为 Max 则会尝试最大的可用控制台模式。目前 Builtin 文本渲染器只支持一种控制台模式,所以该选项可以忽略。

:在大多数固件上,这个字段最好留空。

3. Resolution

Type: plist string
Failsafe: Empty string
Description: 设置控制台的屏幕分辨率。

  • 设置为 WxH@Bpp(如 1920x1080@32)或 WxH(如 1920x1080)格式的字符串,向 GOP 请求自定义分辨率。
  • 设置为空字符串,不改变屏幕分辨率。
  • 设置为 Max,尝试使用最大的可用屏幕分辨率。

在 HiDPI 屏幕上,APPLE_VENDOR_VARIABLE_GUID UIScale NVRAM 变量可能需要设置为 02,以便在 Builtin 文本渲染器、FileVault 2 UEFI 密码界面和启动界面 logo 启用 HiDPI 缩放。更多细节请参考 建议变量 部分。

:当控制台句柄没有 GOP 协议时,这些设置会失败。当固件不再提供时,可以将 ProvideConsoleGop 设置为 true 并添加。

4. ForceResolution

Type: plist boolean
Failsafe: false
Description: 当默认情况下无法获得所需分辨率时,强制设置 Resolution 中所填写的分辨率,多用于老的 Intel GMA 和第一代 Intel HD Graphics (Ironlake/Arrandale)。将 Resolution 设置为 Max 时,将尝试从所连接的显示器的 EDID 中提取最大的可用分辨率。

:该选项依赖 OC_FORCE_RESOLUTION_PROTOCOL 协议。目前只有 OpenDuetPkg 支持该协议,而 OpenDuetPkg 的实现目前仅支持 Intel iGPU。

4. ClearScreenOnModeSwitch

Type: plist boolean
Failsafe: false
Description: 有些固件在从图形模式切换到文本模式时,只会清除部分屏幕、而会留下一部分之前绘制的图像。启用这一选项后,在切换到文本模式之前会用黑色填充整个图形屏幕。

:这一选项只会在 System 渲染器上生效。

5. DirectGopRendering

Type: plist boolean
Failsafe: false
Description: 为控制台使用内置的图形输出协议渲染器。

在某些固件上,这样做可能会提供更优的性能,甚至修复渲染问题,比如 MacPro5,1。但是,除非有明显的好处,否则还是建议不要使用这个选项,因为可能会导致滚动速度变慢。

6. IgnoreTextInGraphics

Type: plist boolean
Failsafe: false
Description: 选择固件同时在图形和文本两种模式下在屏幕上输出文本。通常不会这样做,因为随机的文本可能会出现在图形图像上,并导致用户界面出错。将此选项设置为 true 时,会在控制台处于与 Text 不同的模式时,舍弃所有文本输出。

:这一选项只会在 System 渲染器上生效。

7. ReplaceTabWithSpace

Type: plist boolean
Failsafe: false
Description: 有些固件不会打印 tab 符号,甚至不打印 tab 后面的所有内容,导致很难或根本无法用 UEFI Shell 内置的文本编辑器来编辑属性列表和其他文档。这个选项会使控制台输出空格来替代 tab。

:这一选项只会在 System 渲染器上生效。

8. ProvideConsoleGop

Type: plist boolean
Failsafe: false
Description: 确保控制台句柄上有 GOP (Graphics Output Protocol)。

macOS bootloader 要求控制台句柄上必须有 GOP 或 UGA(适用于 10.4 EfiBoot),但 UEFI 规范并未涵盖图形协议的确切位置。此选项会确保 GOP 和 UGA(如果存在)在控制台句柄上可用。

:这个选项也会替换掉控制台句柄上损坏的 GOP 协议,在使用较新的 GPU 的 MacPro5,1 时可能会出现这种情况。

9. ReconnectOnResChange

Type: plist boolean
Failsafe: false
Description: 改变屏幕分辨率后重新连接控制台控制器。

当通过 GOP 改变屏幕分辨率时,某些固件需要重新连接产生控制台协议(简单的文本输出)的控制器,否则它们不会根据新的分辨率生成文本。

:当 OpenCore 从 Shell 启动时,这个逻辑可能会导致某些主板黑屏,因此这个选项是非必须的。在 0.5.2 之前的版本中,这个选项是强制性的,不可配置。除非需要,否则请不要使用该选项。

10. SanitiseClearScreen

Type: plist boolean
Failsafe: false
Description: 有些固件在使用较大的显示器(如 2K 或 4K)时,清除屏幕内容会导致屏幕分辨率重置为 failsafe 值(如 1024x768)。这个选项为这种情况提供了一个变通方法。

:这一选项只会在 System 渲染器上生效。在所有已知的受影响的系统中,ConsoleMode 必须设置为空字符串才能正常工作。

11. UgaPassThrough

Type: plist boolean
Failsafe: false
Description: 在 GOP 协议的顶部提供 UGA 协议实例。

有些固件不会去实现老旧的 UGA 协议,但是有些更老的 EFI 应用程序(如 10.4 的 EfiBoot)可能需要用它来进行屏幕输出。

11.11 ProtocolOverrides 属性

1. AppleAudio

Type: plist boolean
Failsafe: false
Description: 重新安装内置版本的 Apple 音频协议。

Apple 音频协议允许 macOS bootloader 和 OpenCore 播放声音和信号,用于屏幕阅读或可闻及的错误报告。支持的协议有生成「哔」声和 VoiceOver。VoiceOver 协议是带有 T2 芯片的机器特有的,不支持 macOS High Sierra (10.13) 之前的版本。旧版 macOS 版本使用的是 AppleHDA 协议,目前还没有实现。

每次只能有一组音频协议可用,所以如果为了在 Mac 系统上的 OpenCore 用户界面实现其中一些协议的音频播放,这一设置应该启用。

:后端音频驱动需要在 UEFI Audio 部分进行配置,以便这些协议能够流式传输音频。

2. AppleBootPolicy

Type: plist boolean
Failsafe: false
Description: 重新安装内置的 Apple Boot Policy 协议,可用于确保 VM 或旧版 Mac 设备上的 APFS 兼容性。

:某些 Mac 设备(如 MacPro5,1)虽然兼容 APFS,但是其 Apple Boot Policy 协议包含了恢复分区检测问题,因此也建议启用这一选项。

3. AppleDebugLog

Type: plist boolean
Failsafe: false
Description: 重新安装内置的 Apple 调试日志输出协议。

4. AppleEvent

Type: plist boolean
Failsafe: false
Description: 重新安装内置的 Apple Event 协议,可以确保在 VM 或旧版 Mac 设备上的 FileVault 2 兼容性。

5. AppleFramebufferInfo

Type: plist boolean
Failsafe: false
Description: 重新安装内置的 Apple Framebuffer Info 协议。这样可以覆盖虚拟机或者旧款 Mac 上的缓冲帧信息,从而提高与旧版 EfiBoot(如 macOS 10.4 中的 EfiBoot)的兼容性。

6. AppleImageConversion

Type: plist boolean
Failsafe: false
Description: 重新安装内置的 Apple Image Conservation 协议。

7. AppleImg4Verification

Type: plist boolean
Failsafe: false
Description: 重新安装内置的 Apple IMG4 验证协议。该协议用于验证 Apple 安全启动所使用的 im4m 清单文件。

8. AppleKeyMap

Type: plist boolean
Failsafe: false
Description: 重新安装内置的 Apple Key Map 协议。

9. AppleRtcRam

Type: plist boolean
Failsafe: false
Description: 重新安装内置的 Apple RTC RAM 协议。

:内置的 Apple RTC RAM 协议可能会过滤掉 RTC 内存地址的潜在 I/O。地址列表可以在 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:rtc-blacklist 中以数组的方式指定。

10. AppleSecureBoot

Type: plist boolean
Failsafe: false
Description: 重新安装内置的 Apple 安全启动协议。

11. AppleSmcIo

Type: plist boolean
Failsafe: false
Description: 重新安装内置的 SMC I/O 协议。

这一协议代替了传统的 VirtualSmc.efi,并与所有 SMC Kext 驱动兼容。如果你在用 FakeSMC,可能需要手动往 NVRAM 中添加键值对。

12. AppleUserInterfaceTheme

Type: plist boolean
Failsafe: false
Description: 重新安装内置的 Apple User Interface Theme 协议。

13. DataHub

Type: plist boolean
Failsafe: false
Description: 重新安装具有内置版本的 Data Hub 协议。如果已经安装了协议,这将删除所有先前的属性。

14. DeviceProperties

Type: plist boolean
Failsafe: false
Description: 重新安装内置版本的 Device Property 协议。 如果已经安装,它将删除所有以前的属性。这一选项可用于确保在 VM 或旧版 Mac 设备上的兼容性。

15. FirmwareVolume

Type: plist boolean
Failsafe: false
Description: 强制包装固件卷协议或安装新版本以支持 FileVault 2 的自定义光标图像。建议启用这一选项以确保 FileVault 2 在除 VM 和传统 Mac 设备之外的兼容性。

:包括 VMWare 在内的多个虚拟机在 HiDPI 模式下光标会损坏,因此建议为所有虚拟机启用这一选项。

16. HashServices

Type: plist boolean
Failsafe: false
Description: 强制重新安装内置版本的 Hash Services 协议。为了在 SHA-1 哈希协议不完整的固件上确保 FileVault 2 的兼容性,这一 Quirk 应设置为 true。对于大多数固件来说,你可以通过将 UIScale 设置为 02 查看是否会出现禁行图标,来诊断你的固件是否需要这一 Quirk。一般来说,APTIO V(Haswell 和更早的平台)之前的平台都会受到影响。

17. OSInfo

Type: plist boolean
Failsafe: false
Description: 强制使用内置版本重新安装 OS Info 协议。该协议通常用于通过固件或其他应用程序从 macOS 引导加载程序接收通知。

18. UnicodeCollation

Type: plist boolean
Failsafe: false
Description: 强制重新安装内置版本的 Unicode Collation 服务。建议启用这一选项以确保 UEFI Shell 的兼容性。一些较旧的固件破坏了 Unicode 排序规则,启用后可以修复这些系统上 UEFI Shell 的兼容性 (通常为用于 IvyBridge 或更旧的设备)

11.12 Quirks 属性

1. DisableSecurityPolicy

Type: plist boolean
Failsafe: false
Description: 禁用平台安全策略。

:此设置可禁用固件的各种安全功能,因此也会同时破坏安全启动策略。如果打算使用 UEFI 安全启动,请勿启用此项。

1. ExitBootServicesDelay

Type: plist integer
Failsafe: 0
Description: 在 EXIT_BOOT_SERVICES 事件后添加延迟,单位为毫秒。

这是一个非常丑陋的 Quirk,用于修复 Still waiting for root device 提示信息。在使用 FileVault 2 时,特别是华硕 Z87-Pro 等 APTIO IV 固件这种错误经常发生。似乎因为某种原因,FileVault 与 EXIT_BOOT_SERVICES 同时执行、导致 macOS 无法访问 SATA 控制器。未来应该会找到一个更好的方法。如果需要启用这一选项,设置 3-5 秒的延时就可以了。

2. IgnoreInvalidFlexRatio

Type: plist boolean
Failsafe: false
Description: 某些固件,即 APTIO IV,可能在 MSR_FLEX_RATIO (0x194) MSR 寄存器中含有无效值。这些值可能会导致 macOS 在 Intel 平台上启动失败。

:虽然该选项不会对不受影响的固件造成损害,但在不需要的情况下不建议启用。

3. ReleaseUsbOwnership

Type: plist boolean
Failsafe: false
Description: 尝试从固件驱动程序中分离 USB 控制器所有权。尽管大多数固件都设法正确执行了该操作或者提供有一个选项,但某些固件没有,从而导致操作系统可能会在启动时冻结。除非需要,否则不建议启用这一选项。

4. RequestBootVarRouting

Type: plist boolean
Failsafe: false
Description: 请求将所有带有 Boot 前缀的变量从 EFI_GLOBAL_VARIABLE_GUID 重定向到 OC_VENDOR_VARIABLE_GUID

启用这个 Quirk 需要用到在 OpenRuntime.efi 中实现的 OC_FIRMWARE_RUNTIME 协议。当固件删除不兼容的启动条目时,这一 Quirk 可以让默认的启动条目保存在引导菜单中。简单地说就是,如果你想使用「系统偏好设置」中的「启动磁盘」,就必须启用这一 Quirk。

借助 RequestBootVarRoutingBoot 前缀变量重定向至单独的 GUID 命名空间,可实现以下效果:

  • 囚禁操作系统,使其只受 OpenCore 引导环境的控制,从而提高了安全性。
  • 如遇到中途需要通过 OpenCore 来重启的情况,操作系统不会搞乱 OpenCore 的引导优先级,保证了系统更新和休眠唤醒的流畅性。
  • macOS 等潜在的不兼容的启动项,现在不会被意外删除或损坏了。

5. TscSyncTimeout

Type: plist integer
Failsafe: 0
Description: 尝试用指定的 Timeout 执行 TSC 同步。

这个 Quirk 的主要目的是在运行 XNU 调试内核时,在一些服务器和笔记本型号上实现早期引导 TSC 同步。对于调试内核,在任何 Kext 可能导致其他解决方案出现问题之前,TSC 需要在各个内核之间保持同步。Timeout 以微秒为单位,取决于平台上存在的核心数量,推荐的起始值是 500000

这是一个实验性的 Quirk,只能被用于上述问题。在其他情况下,这个 Quirk 可能会导致操作系统不稳定,所以并不推荐使用。在其他情况下,推荐的解决办法是安装一个内核驱动,如 VoodooTSCSync、TSCAdjustReset 或 CpuTscSync(是 VoodooTSCSync 的一个更有针对性的变种,适用于较新的笔记本电脑)。

:这个 Quirk 不能取代内核驱动的原因是它不能在 ACPI S3 模式(睡眠唤醒)下运行,而且 UEFI 固件提供的多核心支持非常有限,无法精确地更新 MSR 寄存器。

6. UnblockFsConnect

Type: plist boolean
Failsafe: false
Description: 某些固件通过「按驱动程序」模式下来阻止引导项加载,导致文件系统协议无法安装。

:如果惠普笔记本在 OpenCore 界面没有看到引导项,启用这一选项。

11.13 ReservedMemory 属性

1. Address

Type: plist integer
Failsafe: 0
Description: 保留内存区域的起始地址,该区域应被分配为保留区,有效地将此类型的内存标记标记为操作系统不可访问。

这里写的地址必须是内存映射的一部分,具有 EfiConventionalMemory 类型,并且按页对齐(4KB)。

:禁用 CSM 后,某些固件可能不会为 S3(睡眠)和 S4(休眠)分配内存区域,因此导致唤醒失败。你可以分别比较禁用和启用 CSM 的内存映射,从低层内存中找到这些区域,并保留该区域来修复这个问题。详见 Sample.plist

2. Comment

Type: plist string
Failsafe: Empty string
Description: 用于为条目提供人类可读参考的任意 ASCII 字符串(译者注:即注释)。该值取决于具体的实现定义。

3. Size

Type: plist integer
Failsafe: 0
Description: 保留的内存区域的大小,必须按页对齐(4KB)。

4. Type

Type: plist string
Failsafe: Reserved
Description: 内存区域类型,与 UEFI 规范的内存描述符类型的匹配映射如下:

  • ReservedEfiReservedMemoryType
  • LoaderCodeEfiLoaderCode
  • LoaderDataEfiLoaderData
  • BootServiceCodeEfiBootServicesCode
  • BootServiceDataEfiBootServicesData
  • RuntimeCodeEfiRuntimeServicesCode
  • RuntimeDataEfiRuntimeServicesData
  • AvailableEfiConventionalMemory
  • PersistentEfiPersistentMemory
  • UnusableMemoryEfiUnusableMemory
  • ACPIReclaimMemoryEfiACPIReclaimMemory
  • ACPIMemoryNVSEfiACPIMemoryNVS
  • MemoryMappedIOEfiMemoryMappedIO
  • MemoryMappedIOPortSpaceEfiMemoryMappedIOPortSpace
  • PalCodeEfiPalCode

5. Enabled

Type: plist boolean
Failsafe: false
Description: 除非设置为 true,否则该区域不会被保留。

排错

12.1 旧版 Apple 操作系统

旧版操作系统的安装可能比较复杂,但有时出于各种原因还是需要用到。主板标识符和 CPUID 的兼容性是旧版操作系统正常运行的基础,除此之外还有一些细枝末节的事情需要注意。本章节将尽量阐述与旧版 macOS 操作系统相关的一系列常见问题。

尽管较新的操作系统可以通过互联网下载,但旧版操作系统并不是每个次要版本都有安装介质的,因此要想获得兼容的发行版,可能需要下载特定设备的镜像,并在必要时进行修改。Mac 电脑随附的 macOS 旧版本和旧版号列表,可以从这篇 Apple 支持的 存档文章 中找到,但由于它并不一定准确,下面列出了一些旧版 Apple 操作系统最后发布的版本。

1. macOS 10.8 和 10.9

  • 这两个系统的磁盘映像使用的是 Apple 分区方案(Apple Partitioning Scheme),需要 OpenPartitionDxe 驱动程序来进行 DMG 恢复和安装(OpenDuet 中也同样需要)。可以将 DmgLoading 设置为 Disabled,这样就可以在不加载 DMG 的情况下运行恢复功能,同时也避免了 OpenPartitionDxe 的需求。
  • 缓存的内核映像通常不包括网络(IONetworkingFamily)或音频(IOAudioFamily)的家族驱动,这些家族驱动往往需要使用 Force 加载来注入。

2. macOS 10.7

  • 同上。
  • SSSE3 支持(不要和 SSE3 混淆)是 macOS 10.7 内核的硬性要求。
  • 包括 Lilu(使用 32 位内核时)及其插件在内的许多 Kext 在 macOS 10.7 或更低版本上都不支持,它们所需的内核 API 比较新,不在 macOS 10.7 SDK 之中。
  • macOS 10.8 之前的系统不支持 KASLR slide,因此会导致内存较低的固件分配内存失败,详见 acidanthera/bugtracker#1125。

3. macOS 10.6

  • 上述问题均存在。
  • SSSE3 支持是启用了 64 位用户空间的 macOS 10.6 内核的要求。这个限制大多可以通过启用 LegacyCommpage Quirk 来解除。
  • 最近发布的 macOS 10.6 安装镜像为 macOS 10.6.7 版本号 10J3250MacBookPro8,x 专用)和 10J4139iMac12,x 专用,不含 Xcode)。这些镜像仅限于特定的几款机型,并且不支持使用 -no_compat_check 来忽略兼容性检查。如果你拥有 macOS 10.6 的合法副本,又不想被上述限制所约束,可以在 这里(或 MEGA 镜像)找到无机型限制的修改版镜像(ACDT 后缀),更多细节在 DIGEST.txt 中。记住,这些都是经过 OpenCore 测试的最早的 macOS 10.6 版本。

机型检查可以被手动去除,大体思路是用 Flat Package Editor 之类的工具编辑 OSInstall.mpkg,让 Distribution 脚本在 hwbeModelCheck 函数中总是返回 true。仅更新映像中某一的文件而不影响到其他文件是相当困难的,而且还有可能因为内核缓存日期的改变而导致启动速度变慢,因此建议按照如下命令重建映像:

#!/bin/bash
# Original.dmg is original image, OSInstall.mpkg is patched package
mkdir RO
hdiutil mount Original.dmg -noverify -noautoopen -noautoopenrw -noautofsck -mountpoint RO cp RO/.DS_Store DS_STORE
hdiutil detach RO -force
rm -rf RO
hdiutil convert Original.dmg -format UDRW -o ReadWrite.dmg
mkdir RW
xattr -c OSInstall.mpkg
hdiutil mount ReadWrite.dmg -noverify -noautoopen -noautoopenrw -noautofsck -mountpoint RW cp OSInstall.mpkg RW/System/Installation/Packages/OSInstall.mpkg
killall Finder fseventsd
rm -rf RW/.fseventsd
cp DS_STORE RW/.DS_Store
hdiutil detach RW -force
rm -rf DS_STORE RW

4. macOS 10.5

  • 上述问题均存在。
  • 这个版本的 macOS 不支持 x86_64 内核,需要 i386 内核扩展和补丁。
  • 这个版本的 macOS 使用了第一个版本(V1)的 prelinkedkernel,但它的 Kext 符号表被 Kext 工具破坏了。这个细微的差别使得 prelinkedkernel Kext 无法被 OpenCore 注入。Mkext Kext 的注入仍然正常,也不会有明显的性能消耗,而且当 KernelCache 设置为 Auto 时,Mkext 会被自动选择。
  • 最后发布的 macOS 10.5 的安装镜像是 macOS 10.5.7 版本号 9J3050MacBookPro5,3 专用)。与其他版本系统不同的是,这个镜像不受机型限制,可以原样使用。如果你拥有 macOS 10.5 的合法副本,可以在 这里(或 MEGA 镜像)找到原始的 9J3050 镜像,更多细节在 DIGEST.txt 中。注意,这是经过 OpenCore 测试的最早的 macOS 10.5 版本。

5. macOS 10.4

  • 上述问题均存在。
  • 这个版本的 macOS 有一个硬性要求,即需要两张光盘或两个 USB 安装介质来访问第二张 DVD 盘安装介质上的所有可选包。
  • 最后发布的 macOS 10.4 的安装镜像是 macOS 10.4.10 版本号 8R4061aMacBookPro3,1 专用)和 8R4088iMac7,1 专用)。这些镜像与新版 macOS 一样,仅限于特定的几款机型。如果你拥有 macOS 10.4 的合法副本,可以在 这里(或 MEGA 镜像)找到无机型限制的修改版 8R4088 镜像(后缀为 ACDT),更多细节在 DIGEST.txt 中。注意,这些是经过 OpenCore 测试的最早的 macOS 10.4 版本。

12.2 UEFI 安全启动

OpenCore 的设计初衷是在 固件 和 操作系统 之间提供一个安全的启动链。在大多数 x86 平台上,可信加载(Trusted Loading)是通过 UEFI 安全启动 模式实现的。OpenCore 不仅完全支持这种模式,还扩展了它的功能,以确保通过 Vault 进行配置的加密存储,并使用自定义的验证过程向操作系统提供可信加载,例如 Apple 安全启动。正确的安全启动链需要通过以下步骤来仔细配置:

  1. 如果要启动的系统是 macOS,则需要通过设置 SecureBootModel 来启用 Apple 安全启动。请注意,并不是每个 macOS 版本都能使用 Apple 安全启动,具体限制详见 Apple 安全启动 章节。
  2. 旧的 DMG 恢复镜像往往很脆弱、易受攻击,如果担心因为加载它而突破防线,可以通过设置 DmgLoadingDisabled 来禁用 DMG 加载。非必需,但建议使用。参阅 DMG 加载 部分来权衡利弊。
  3. MinDateMinVersion 设置为 0,以确保 APFS JumpStart 功能限制旧的驱动程序加载。更多细节参见 APFS JumpStart 部分。除此之外,手动安装 apfs.efi 驱动也可以达到相同效果。
  4. 确保你想要运行的操作系统不加载 Force 驱动也能正常启动。
  5. 确保使用 ScanPolicy 限制加载不受信任的设备。要想做到足够安全,最好的办法是禁止加载 所有可移动设备 和 未知的文件系统。
  6. 使用私钥给所有已安装的驱动程序和工具签名。不要对提供管理员权限的工具(如 UEFI Shell)签名。
  7. 加密存储你的配置,详见 Vault 部分。
  8. 使用同一私钥签名该系统使用的所有 OpenCore 二进制文件(BOOTX64.efi, BOOTIa32.efi, OpenCore.efi, 自定义启动器)。
  9. 如果需要用到第三方操作系统(非微软或 Apple 制造)的 bootloader,也同样为它们签名。对于 Linux,可以选择安装微软签名的 Shim bootloader,具体解释见 Debian Wiki。
  10. 在 BIOS 中开启 UEFI 安全启动,并用自己的私钥安装证书。很多文章都介绍了生成证书的具体方法,比如 这篇文章,本文档不再赘述。如果需要启动 Windows,还需要添加 Microsoft Windows Production CA 2011 证书。如果需要启动 Option ROM,或决定使用已签名的 Linux 驱动程序,还需要添加 Microsoft UEFI Driver Signing CA。
  11. 设置密码保护防止固件设置被篡改,避免 UEFI 安全启动在你不知情的情况下被禁用。

12.3 Windows 支持

1. 我能安装 Windows 系统吗?

虽然 OpenCore 并没有提供官方的 Windows 支持,但是使用 Boot Camp 安装 64 位 UEFI Windows(即 Windows 8 及更高版本)应该是可以正常工作的。安装第三方 UEFI、或者仅部分支持 UEFI 引导的系统(如 Windows 7)可能需要额外注意。不论如何,记住以下几点:

  • MBR (Master Boot Record) 属于 Legacy 引导,因此将不会被支持。
  • 在 OpenCore 上应用的所有更改(ACPI、NVRAM、SMBIOS)都应该与操作系统本身无关。OpenCore 会将这些改动生效于所有操作系统,这样在 Windows 上可以获得 Boot Camp 的体验。
  • macOS 要求硬盘中的第一份分区为 EFI 分区,并且与 Windows 的默认布局不支持。尽管 OpenCore 确实提供了一个 解决方法,但是强烈建议不要依赖这个方法。
  • Windows 系统可能需要重新激活。为了避免这种情况发生,请考虑将 SystemUUID 设置为原始固件的 UUID。请注意,在旧固件上 UUID 可能是无效的(非随机的)。如果你还遇到了什么问题,可以考虑使用 HWID 或 KMS38 的 Windows 许可证。从 OpenCore 0.5.8 开始,你还可以通过设置 UpdateSMBIOSModeCustom 来避免 OEM 激活失效。Windows 激活的细节不在本文档的讨论范围内,你应该能够在网上查找到相关资料。

2. 我需要安装其他什么软件吗?

在大多数情况下,要启用多操作系统切换、安装相关驱动程序,你将需要 Boot Camp 提供的 Windows 支持软件。为了简化下载过程、或者配置硬盘中已经安装好的 Windows,可以使用 Brigadier 这个实用软件。请注意在使用 Brigadier 之前,你可能需要先下载并安装 7-Zip。

译者注:7-zip 官方中文网站

记住,一定要使用最新版本的 Boot Camp 的 Windows 支持软件。6.1 之前的版本不支持 APFS 文件系统、因此无法运行。要下载最新的软件,请将最新 Mac 的型号作为参数传递给 Brigadier,如 ./brigadier.exe -m iMac19,1。之后,在不受支持的 Mac 型号上安装 Boot Camp,请以管理员身份运行 PowerShell,输入 msiexec /i BootCamp.msi 即可。如果你之前不小心已经安装了旧版本的 Boot Camp,则必须先通过运行 msiexec /x BootCamp.msi 将其卸载。BootCamp.msi 文件位于 BootCamp/Drivers/Apple 目录中、可以通过资源管理器访问。

译者注:在资源管理器下,按住 Shift 同时右击窗口中空白处,此时菜单中会显示「在此处运行 PowerShell」,即在当前目录下运行 PowerShell。但是这种方式启动的 PowerShell 不具备管理员权限。

尽管 Boot Camp 提供的 Windows 支持软件解决了大多数兼容性问题,但是有时候您还是需要手动解决一些问题:

  • 要反转鼠标滚轮的滚动方向,必须按照 这个网站 提供的方法、设置 FlipFlopWheel 的值为 1

    译者注:
    涉及到的注册表是 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\HID\VID_???\VID_???\Device Parameters.
    你可以在 PowerShell 中执行下述命令进行设置;

    # 获取当前设置
    Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Enum\HID\*\*\Device` Parameters FlipFlopWheel -EA 0
    # 修改设置
    # 鼠标滚动方向 相反 FlipFlopWheel 1
    # 鼠标滚动方向 自然滚动 FlipFlopWheel 0
    Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Enum\HID\*\*\Device` Parameters FlipFlopWheel -EA 0 | ForEach-Object { Set-ItemProperty $_.PSPath FlipFlopWheel 1 }
    

    如果需要撤销更改,可以使用下述命令:

    # 恢复鼠标滚动方向
    Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Enum\HID\*\*\Device` Parameters FlipFlopWheel -EA 1 | ForEach-Object { Set-ItemProperty $_.PSPath FlipFlopWheel 0 }
    
  • RealTimeIsUniversal 必须设置为 1 以避免 Windows 和 macOS 之间的时间不同步。

    译者注:众所周知,Windows 将硬件时间视为本地时间,而 macOS 会计算 UTC 后当做系统时间。通过修改上述提到的注册表值,可以让 Windows 将硬件时间视为 UTC 时间。用到的 CMD 命令如下所示:

    Reg add HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation /v RealTimeIsUniversal /t REG_DWORD /d 1
    
  • 如果要访问 Apple 的文件系统(APFS、HFS),你可能需要安装单独的软件。已知的工具有 Apple HFS+ driver (hack for Windows 10)、HFSExplorer、MacDrive、Paragon APFS、Paragon HFS+、TransMac,等等。

    译者注:切记不要在 Windows 下写入 APFS 或 HFS,十有八九你会导致分区表错误和无法恢复的数据丢失。别怪我们没有警告过你!!

3. 为什么我会在 Boot Camp 启动硬盘 控制面板 中看到 Basic data partition

Boot Camp 使用 GPT 分区表获取每个引导选项的名称。独立安装 Windows 后,你必须手动重新标记分区。这可以通过许多工具完成,比如开源的 gdisk,使用方法如下:

PS C:\gdisk> .\gdisk64.exe \\.\physicaldrive0
GPT fdisk (gdisk) version 1.0.4Command (? for help): p
Disk \\.\physicaldrive0: 419430400 sectors, 200.0 GiB
Sector size (logical): 512 bytes
Disk identifier (GUID): DEC57EB1-B3B5-49B2-95F5-3B8C4D3E4E12
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 419430366
Partitions will be aligned on 2048-sector boundaries
Total free space is 4029 sectors (2.0 MiB)Number  Start (sector)    End (sector)  Size       Code  Name1            2048         1023999   499.0 MiB   2700  Basic data partition2         1024000         1226751   99.0 MiB    EF00  EFI system partition3         1226752         1259519   16.0 MiB    0C01  Microsoft reserved ...4         1259520       419428351   199.4 GiB   0700  Basic data partitionCommand (? for help): c
Partition number (1-4): 4
Enter name: BOOTCAMPCommand (? for help): wFinal checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!!Do you want to proceed? (Y/N): Y
OK; writing new GUID partition table (GPT) to \\.\physicaldrive0.
Disk synchronization succeeded! The computer should now use the new partition table.
The operation has completed successfully.
Listing 4: 重新标记 Windows 卷宗

4. 如何选择 NTFS 驱动程序

提供 NTFS 读写支持的第三方驱动程序,如 NTFS-3G、Paragon NTFS、Tuxera NTFS 或 希捷移动硬盘 Paragon 驱动程序 会破坏 macOS 的功能,比如 系统偏好设置 中的 启动磁盘 选项。
虽然我们仍然不建议使用这些经常破坏文件系统的驱动程序(我们推荐使用 macOS 内建的 NTFS 读写支持,可以通过 终端 或 GUI 启用),但是这些驱动程序的厂商也提供了他们各自的解决方案,在这里我们仅列举两个:

  • Tuxera 的常见问题解答页面
  • Paragon 相关的技术支持文档

译者注:虽然 acidanthera 团队推荐使用 macOS 内置的 NTFS 支持,但是译者强烈反对这种方法(不论是直接方法还是使用类似 Mounty 的第三方工具)。修改 fstab 的风险是极高的。在你清楚你在做什么之前,不要轻举妄动!!

12.4 调试

与其他硬件相关的项目类似,OpenCore 也支持审计与调试。使用 NOOPTDEBUG 构建版本(而非 RELEASE 构建版本)可以产生更多的调试输出。对于 NOOPT 构建版本,你还可以使用 GDB 或 IDA Pro 进行调试。对于 GDB 请查看 OpenCore Debug 相关页面;对于 IDA Pro,你需要 7.3 或更高版本,更多详细信息请参考 IDA Pro 提供的页面:Debugging the XNU Kernel with IDA Pro。

可以使用串口调试来获取启动过程中的日志。串口调试是在 Target 中开启的,例如 0xB 代表在屏幕上显示并输出串行。可使用 SerialInit 配置选项来初始化串行。对于 macOS 来说,最好是选择基于 CP2102 的 UART 设备。将主板 TX 连接到 USB UART RX,主板 GND 连接到 USB UART GND。使用 screen 实用工具,或者下载 GUI 软件获取输出,如 CoolTerm。

:在一些主板(可能还有一些 USB UART 转换器)上,PIN 的命名可能是不正确的。GNDRX 互换是很常见的,因此你需要将主板 "TX" 连接到 USB UART GND,主板 "GND" 连接到 USB UART RX

务必记得在固件设置中启用 COM 口,一定不要使用超过 1 米的 USB 线缆,以免输出数据损坏。如果要额外启用 XNU 内核串行输出,则需要添加 debug=0x8 启动参数。

12.5 技巧和窍门

1. 啊呀呀呀我系统没法启动了我该怎么看日志啊?

通常情况下,获取实际的错误信息就足够了。为此,请确保:

  • 你正在使用 OpenCore 的 DEBUGNOOPT 版本。
  • 日志已启用(1)并且在屏幕上显示(2):Misc → Debug → Target = 3.
  • 将以下这些等级的日志输出到屏幕上:DEBUG_ERROR (0x80000000)、DEBUG_WARN (0x00000002) 和 DEBUG_INFO (0x00000040):Misc → Debug → DisplayLevel = 0x80000042.
  • 遇到 DEBUG_ERROR 这样的致命错误时中止启动:Misc → Security → HaltLevel = 0x80000000
  • 禁用 Watch Dog 以避免自动重启:Misc → Debug → DisableWatchDog = true
  • 已启用 启动菜单 显示:Misc → Boot → ShowPicker = true

如果你在日志中看不出明显的错误,请逐一检查 Quirks 部分中可用的 hacks。例如,对于 Early Boot 出现的问题(如 OpenCore 启动菜单无法显示),通过 UEFI Shell(随 OpenCore 打包在一起)可以查看相关调试信息。

2. macOS 启动失败我该怎么调试?

  • boot-args 中添加 debug=0x100keepsyms=1-v 或其他类似的值。
  • 不要忘记开启 AppleDebugApplePanic 属性。
  • 调整 BooterKernelUEFI 里的 Quirk。
  • 可以考虑通过串行端口来检查早期的内核启动失败。为此你可能需要用到 debug=0x108serial=5msgbuf=1048576 启动参数。如果在串行初始化前就失败了,Sample.plist 中有相关补丁供你参考。
  • 一定要仔细阅读日志。

3. 如何自定义启动项?

OpenCore 遵循 Apple Bless 标准模型、从引导目录中的 .contentDetails.disk_label.contentDetails 文件中提取条目名称。这些文件包含带有输入标题的 ASCII 字符串,你可以修改它们。

4. 如何选择默认启动的系统?

OpenCore 使用 UEFI 首选启动项 来选择默认的启动项。设置的方式随 BIOS 不同而不同,具体请参考 macOS 启动磁盘 或 Windows 启动转换 控制面板。

由于使用 OpenCore 提供的 BOOTx64.efi 作为首选启动项会限制这项功能(可能还会导致一些固件删除不兼容的引导选项),我们强烈建议你启用 RequestBootVarRouting Quirk,这会将你所做的选择保留在 OpenCore 变量空间中。请注意,RequestBootVarRouting 需要单独的 .efi 驱动文件(译者注:即 OpenRuntime.efi)。

5. 安装 macOS 最简单的方法是什么?

在线安装。将 Recovery 镜像(*.dmg*.chunklist 文件)和 OpenCore 一起复制到一个 FAT32 分区中。加载 OpenCore 的启动菜单并选择后缀为 .dmg 的条目。如果你有强迫症,你可以修改 .contentDetails 文件改变条目显示的文字。

你可能会用到 AppleModels 内置的 macrecovery.py 来下载 Recovery 镜像。

如果你需要进行离线安装,请参考 如何创建可引导的 macOS 安装器。除了通过 App Store 或 系统更新,你还可以使用 第三方工具 下载 macOS 镜像文件。

6. 为什么无法加载 Recovery 恢复镜像 进行在线安装?

可能是因为你没带 HFS+ 驱动。目前我们所知道的 Recovery 分区全都是 HFS+ 文件系统。

7. 我可以在 Apple 的硬件、或虚拟机中使用 OpenCore 吗?

可以,没有必要,但请加大力度

OpenCore 支持包括 MacPro 5,1 和虚拟机在内的大部分较新的 Mac 型号。不过,OpenCore 有关在 Mac 硬件上使用的具体细节微乎其微。你可以在 MacRumors.com 查看相关讨论。

8. 为什么 Find 和 Replace 的补丁的长度必须相等?

对于 x86 机器码来说,相对寻址 无法进行大小不同的替换。对于 ACPI 代码来说这是有风险的,而且在技术上这与替换 ACPI 表等价,所以 OpenCore 没有实现。更多详细的解答可以在 AppleLife.ru 上和本文档的 ACPI 章节找到。

9. 我应该如何决定哪些 Booter Quirk 需要被启用?

这些 Quirk 源自 AptioMemoryFix 驱动,为更多的固件提供了广泛支持。如果你正在使用 OpenRuntime,并且想要获得和 AptioMemoryFix 类似的行为,请启用下述 Quirk:

  • ProvideConsoleGop (UEFI Quirk)
  • AvoidRuntimeDefrag
  • DiscardHibernateMap
  • EnableSafeModeSlide
  • EnableWriteUnprotector
  • ForceExitBootServices
  • ProtectMemoryRegions
  • ProvideCustomSlide
  • RebuildAppleMemoryMap
  • SetupVirtualMap

但是,对于大部分现代的设备来说,上述 Quirk 不一定是必需的。比如 DevirtualiseMmioProtectUefiServices 通常是需要启用的,但是 DiscardHibernateMapForceExitBootServices 一般不建议启用。

不幸的是,对于某些 Quirk 来说(RebuildAppleMemoryMap, EnableWriteUnprotector, ProtectMemoryRegions, SetupVirtualMapSyncRuntimePermissions)由于没有明确的参考,因此需要自行尝试最佳组合。详细内容请参考本文档中对这些 Quirk 的描述。

OpenCore安装教程相关推荐

  1. ThinkPad E450 最新macOS BigSur黑苹果安装教程(OpenCore引导)

    前言 本文以ThinkPad E450为例子,对在Windows或WinPE环境下,使用OpenCore引导,来安装macOS BigSur黑苹果系统,进行过程讲解. 本文是精简版安装教程,只讲正常情 ...

  2. 联想拯救者Y7000系列黑苹果MacOS 12.3.1 Monterey详细安装教程记录

    Y7000 2019系列黑苹果MacOS 12.3.1 Monterey详细安装教程 小编的机器是联想拯救者Leigion Y7000 2019 1050,其他同系列的安装方法可在GitHub找对应的 ...

  3. opencore黑苹果教程

    opencore黑苹果教程 最近忽然在朋友圈看到人家装了台式的黑苹果,心里就起了给自己的笔记本装上黑苹果的心思,于是就下了个小决心用一个星期的时间安装属于自己的黑苹果笔记本.一开始淘宝看过卖黑苹果安装 ...

  4. 黑苹果安装教程OC引导

    小白安装指南 1.从零开始,自制EFI,安装黑苹果 2.网络下载EFI(80%可能你根本找不到能用的) 3.修改BIOS 微星主板BIOS修改示例链接 华硕主板BIOS修改示例链接 华硕主板另一个BI ...

  5. 黑苹果安装教程及相关问题处理心得

    简介 通常安装黑苹果一般有这么几个老生常谈的步骤. 首先是对当前计算机设备的一些配置信息有相应的了解,例如,cpu平台,无线网卡,以太网卡,声卡, 至于显卡,这里只驱动核显: 接着就是配置引导,这是至 ...

  6. Monterey安装教程

    安装前准备 以前的安装教程都是只写教程本身的操作,没有往外延伸. 现在都已经是2021年了,全新的Monterey随时都会发布,无论是硬件还是macOS系统本身,已经有了翻天覆地的变化. 硬件准备: ...

  7. Acer 4750 安装黑苹果_NUC8 黑苹果安装教程

    NUC8的黑苹果体验据说是最接近白苹果的,前段时间小编花斥巨资购入了一台NUC8 i5 BEH厚款.经过两天的捣鼓,结果很成功.性能堪比顶配版MacBook Pro 2018版.今天写篇文章纪念一下, ...

  8. 全网最详细黑苹果安装教程,一学就会的方法,赶快学起来吧

    可以说:这是一套目前最全面的黑苹果安装教程,为了能让每个新手,更好的理解和掌握相关方法,教程按操作流程书写,新手请务必按顺序阅读,以便提高学习效率,高手可以随意观看,或者飘过.由于篇幅长度有限,一篇文 ...

  9. 【网站汇总】安装教程系列

    目录 1.Anaconda 2.Pytorch 3.Tensorflow 4.LaTeX 5.博客搭建 1.Anaconda [CV]Anaconda 安装教程_Fannnnf的博客-CSDN博客 2 ...

  10. oracle 11g完全安装教程(CentOS)

    oracle下载链接:http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html oracle ...

最新文章

  1. SQL SERVER的锁机制(三)——概述(锁与事务隔离级别)
  2. 编程十年的十种武学境界
  3. 触摸屏与计算机通讯视频在线,MCGS触摸屏与电脑调试软件modbus通讯
  4. Window对象中的函数confirm方法的简单介绍
  5. Android被逼学习小例子1
  6. 区块链开发公司能做什么?对企业未来市场有何帮助?
  7. Graph Cut and Its Application in Computer Vision
  8. linux信号掩码线程,20.10 信号掩码(阻塞信号传递)
  9. 解决springdatajpa 在解析实体类的字段时候驼峰自动转为下划线问题
  10. Matlab | 空间域水印技术:LSB(Least Significant Bit):计算峰值信噪比PSNR(matlab源代码)
  11. REALM后续:最近邻搜索,MIPS,LSH和ALSH
  12. linuxc线程信号-pthread_cond_wait理解
  13. 使用EXCEL连接PGSQL
  14. potato电脑版连接不上_土豆电脑版-potato chat下载 v2.13.200323 电脑版 - 安下载
  15. 应用树莓派GPIO完成智能红绿灯系统
  16. 折半查找的实现 swustoj
  17. m4a转换成mp3如何操作?
  18. 2021.5.10-2021.5.16周报
  19. JeeSite(JES)
  20. 4417. 神奇的字符串

热门文章

  1. 黑莓8330、8830写号,上网,输入法,汉化
  2. 数学建模之层次分析法
  3. 基于嵌入式linux电子相册代码,基于嵌入式ARM_Linux的电子相册设计方案.docx
  4. 自然语言处理NLP星空智能对话机器人系列:Facebook StarSpace框架案例数据加载
  5. itop4412的安卓驱动移植
  6. Java Web开发的轻便架构Tapestry5---页面渲染一
  7. 电驴让分享继续 服务器不稳定,为什么越来越多的人不再使用eD2k了?回顾电驴的兴与衰...
  8. 2017年十大移动应用开发的测试工具
  9. php源码 辅助发卡_【程序源码】PHP自动化售货发卡网源码
  10. Windows 技术篇-通过注册表查找vc运行库所在位置实战演示,通过ProductCode查看vc++运行库安装位置