This is the reasoning behind EFI/OC/config.plist, written so I can answer "why is this set" for any line of it. Everything below is what the published config does. Where the README says something different, this file follows the config and says so.
The laptop has two EFI partitions on the internal NVMe. The first one (200 MiB) belongs to Windows and holds Windows Boot Manager plus a custom shim; OpenCore never touches it. The second is a separate FAT32 partition made for OpenCore, and this repository is its EFI folder.
- The Lenovo firmware starts whatever is first in its boot order.
Misc > Boot > LauncherOption Fullmakes OpenCore add its own firmware boot entry and keep it first, so that is OpenCore (EFI/BOOT/BOOTx64.efithenEFI/OC/OpenCore.efi). - OpenCore loads its drivers from
UEFI > Drivers:OpenRuntime.efi(needed by the Booter quirks and the NVRAM handling),OpenHfsPlus.efi(to read the HFS+ installer and recovery volumes),ResetNvramEntry.efiandToggleSipEntry.efi(two picker entries), andLegionCbmrFix.efi. The last one is from this org: the Lenovo BIOS loads Microsoft's cloud recovery driver (cbmr_driver.efi) at 0x180000000 on every boot and macOS later panics on its pages, so the driver unloads that image and reserves its range before macOS starts. - With
ShowPicker falseandTimeout 0OpenCore boots the default entry (the one Startup Disk sets) straight away. Holding Option or Esc while it starts brings up the text picker (PollAppleHotKeys true,PickerMode Builtin). - boot.efi loads the kernel collection, OpenCore applies the kernel patches and kext injections described below, and ExitBootServices hands the machine to XNU.
Windows is started from the firmware menu (F12, Windows Boot Manager), never through OpenCore, because OpenCore would hand it the Mac SMBIOS.
A USB stick with a known-good copy of the same EFI is the rescue path: F12, pick the stick. The stick's copy differs in two places, LauncherOption Disabled (so booting from it does not register the stick in the firmware boot order) and ShowPicker true (so it always offers a choice).
| Table | What it does | Why |
|---|---|---|
SSDT-PLUG-ALT.aml |
OpenCorePkg's sample, unchanged: 64 Processor objects CP00 to CP3F under \_SB, visible only to Darwin, with plugin-type = 1 on CP00 |
Arrow Lake declares its CPUs as Device (ACPI0007). macOS wants Processor objects, and the plugin type loads the XCPM power management plugin |
SSDT-EC-USBX-LAPTOP.aml |
a device named EC (_HID "ACID0001") under \_SB.PC00.LPCB, plus \_SB.USBX with the four USB sleep and wake power values; both Darwin only |
macOS expects a device called EC. The real controller is EC0 and stays untouched, as Dortania advises for laptops; a fake one with a harmless ID satisfies the check without touching the real embedded controller |
SSDT-RTCAWAC.aml |
an _INI at the root that sets STAS = 1 under Darwin |
The DSDT has both an AWAC clock and a legacy PNP0B00 RTC, gated by STAS. With 1, AWAC turns off and the DSDT's own RTC turns on, which AppleRTC can use. An earlier version added a second RTC device as well, which duplicated the DSDT one and gave wrong years |
APIC-legacy.aml |
a replacement MADT: 24 type-0 Local APIC entries, the IOAPIC and the two interrupt source overrides copied as they are, and one type-4 Local APIC NMI entry for all CPUs | see below |
SSDT-FIXSHUTDOWN.aml |
a new _PTS that calls the firmware one (renamed to ZPTS), then, under Darwin and only for S5, clears PME enable on both xHCI controllers (\_SB.PC02.XHCI and \_SB.PC00.TXHC) |
Without it Apple menu Shut Down came back as a restart: a controller still had PME enabled at S5 and woke the machine straight up. macOS does not clear it, Windows and Linux do. The pattern is RehabMan's FixShutdown from Dortania's post-install guide, extended to both controllers |
SSDT-FIXSHUTDOWN and the _PTS rename only work as a pair. With the rename alone the OS has no _PTS; with the table alone it fails to load because ZPTS does not exist.
This was the first real wall. Every early boot stopped right after EXITBS:START with no kernel output at all, whatever Booter quirk I changed. The cause is in XNU: it counts CPUs only from MADT type-0 (Processor Local APIC) entries (acpi_count_enabled_logical_processors in osfmk/i386/acpi.c). This firmware writes only type-9 (x2APIC) entries, 48 of them, so XNU found zero CPUs and panicked in per-CPU setup before the console existed.
scripts/x2apic_to_lapic.py reads the firmware MADT and writes one type-0 entry for each enabled type-9 entry, in firmware order, with Processor ID = the x2APIC UID and APIC ID = the x2APIC ID (it refuses if an ID does not fit in a byte). The table header keeps the firmware's OEM IDs (LENOVO, CB-01). ACPI > Delete drops the firmware table by signature APIC and OEM table ID CB-01, and ACPI > Add puts the rewritten one in its place. The next boot ran about 10 seconds into the kernel and registered all 24 CPUs. If a BIOS update changes the MADT, the table has to be rebuilt from a new dump.
All of them come from scripts/dsdt_patches.py, which also applies them to a dumped DSDT so the result can be loaded in acpiexec before a boot. The ACPICA to test against is 20160930, the version inside macOS's AppleACPIPlatform. Each find string occurs exactly once, so every entry has Count 1, and each replacement has the same length as the original.
- Two
If (PCHA != Zero)blocks become scopes. The PCH PCIe rootDevice (PC02)and a root-level block withMNVBandScope (_SB.PC02)sit inside module-levelIfstatements. ACPICA 20160930 runs those only after the table has loaded, so every laterScope (_SB.PC02...)failed and macOS rejected the whole DSDT. The symptom was a silent hang after a\_SB.UBTC._CRS AE_NOT_FOUNDerror. The patch turns eachIfinto aScopeof the same length, padded withNoop. Scope (PC02.I2C0)is retargeted toPC00.LPCB.I2C0is defined in an SSDT that loads after the DSDT, so the scope did not resolve. The only thing inside it isTCON, which macOS does not use.- Three
Name+Storepairs become methods. The same old ACPICA never runs a bareStorein aDevicebody, so those names stayed 0 under macOS.SBRG = 0inPC00.SBSCandPC02.SBPCsent every sideband register access, including the xHCI_PS0and_PS3, to low RAM.PU2C = 0inPC02.XHCIskipped everyIf (One <= PU2C) { Device (HSxx) }, so the USB ports had no ACPI nodes. Each patch replaces the name with a method that returns the source value when it is called. - Four
_UPCfixes in Lenovo's USB table (SSDT-22). HS05 (the internal ITE keyboard), HS14 (MT7925 Bluetooth), HS11 (webcam) and HS02 (a USB-A port) returnGUPC (Zero, 0xFF): not connectable. Windows ignores that; macOS turns the port off. The patch changes the first argument toOne. That makes 13 ports onPC02.XHCI, under the 15-port limit, so no port limit patch is needed. _PTStoZPTSfor the shutdown fix above. The find is the name plus the argument count byte (_PTSthen01), so the"_PTS="debug strings in the DSDT are not hit.
ACPI > Quirks are all off except ResetLogoStatus.
| Quirk | Value | Why |
|---|---|---|
ForceExitBootServices |
true | It retries ExitBootServices with a fresh memory map if the firmware changed it in between. It went in during the EXITBS:START hunt and stayed. That hang turned out to be the MADT, so this quirk is a precaution here, not a proven fix |
SetupVirtualMap |
false | Dortania's list for firmware from 2020 on, where it can hang at ExitBootServices |
DevirtualiseMmio |
false | leaves all firmware MMIO regions mapped for runtime services; MmioWhitelist is empty |
ResizeAppleGpuBars |
0 | Resizable BAR stays on in the BIOS and the RTX 5070 comes up with an 8 GB BAR1. 0 makes OpenCore report the BARs to macOS as 1 MB (the value is a power of two in MB); NvGfx resizes BAR1 itself later |
RebuildAppleMemoryMap, SyncRuntimePermissions, ProtectUefiServices, ProvideCustomSlide, EnableSafeModeSlide, AvoidRuntimeDefrag, FixupAppleEfiImages |
true | the usual set for current Intel firmware |
Emulate > Cpuid1Datais55 06 0A 00with maskFF FF FF FFon EAX only. That reports CPUID leaf 1 EAX as0x000A0655: family 6, model 0xA5, stepping 5, a Comet Lake. XNU rejects the real family 6 model 0xC6 (Arrow Lake-HX); the Comet Lake value is the usual spoof for Intel CPUs newer than macOS knows.ProvideCurrentCpuInfomakes OpenCore patch the kernel with the real core and thread count (MSR 0x35, 24 cores and 24 threads here), the TSC frequency and the bus frequency, which XNU cannot work out on a hybrid CPU. OpenCore's documentation requires it for Alder Lake and newer. The README says the boot hangs atEXITBS:STARTwithout it; that hang was the MADT, and the quirk on its own did not change it.AppleXcpmCfgLockpatches XCPM so it does not write MSR 0xE2, which panics when the firmware has CFG lock set.PlatformInfo > Generic > ProcessorTypeis0x0F01. With the Comet Lake spoof, OpenCore's automatic choice was a type that macOS names "Unknown" with 24 cores. 0x0F01 shows as a Xeon W, which RestrictEvents (revpatch=cpuname, NVRAMrevcpuname) then renames to the real name.CpuTscSync(kext) syncs the TSC across cores. The first boot that reached the kernel panicked with "Non-monotonic time" inAppleACPICPU::start; the firmware leaves a non-zeroIA32_TSC_ADJUST.
DisableIoMapperandDisableIoMapperMapping(both true): with AppleVTD active, the NVIDIA driver saw IOMMU-translated addresses in the BARs and refused the card. With VT-d hidden from macOS, the RTX 5070 initialises.DisableLinkeditJettison: Lilu and its plugins need the kernel's__LINKEDITafter boot.PanicNoKextDumpandPowerTimeoutKernelPanic: a panic shows its backtrace instead of a long kext list, and a driver that stalls a power change gets a log line instead of a panic.SetApfsTrimTimeout 0: APFS skips the trim of all free space at mount. After a partition resize that trim took about 20 s of every boot.Scheme:KernelCache Auto,FuzzyMatch true, no custom kernel.Kernel > Patch,BlockandForceare empty.
OpenCore injects the kexts in the order of Kernel > Add, and a kext has to come after everything it links against.
| # | Kext | What it is for |
|---|---|---|
| 0 | Lilu | patching framework; everything with a Lilu dependency comes after it |
| 1 | CpuTscSync | TSC sync, see above |
| 2, 3 | VirtualSMC, SMCBatteryManager | an SMC for macOS; battery through the ACPI battery methods |
| 4 | WhateverGreen | keeps the Intel iGPU usable when the firmware hands the panel to it (see the GPU section) |
| 5 | RestrictEvents | revpatch=sbvmm,cpuname: software updates with a non-Mac model, and the CPU name |
| 6 | ECEnabler | lets SMCBatteryManager read the EC's multi-byte battery fields |
| 7 | NVMeFix | power management for the WD SN7100S |
| 8 | RealtekRTL8111 | Ethernet |
| 9 | MCEReporterDisabler | plist only: keeps Apple's machine-check reporter from attaching; it came in with the first config, following OpCore-Simplify's choice for this kind of CPU |
| 10 | LegionITEKbdFix | plist only: keeps Apple's HID driver off interface 1 of the ITE keyboard (048D:C195, the HID LampArray interface); part of the set that got the internal keyboard typing |
| 11 to 13 | VoodooPS2Controller, its Keyboard plugin, VoodooInput | the PS/2 keyboard device the DSDT declares; VoodooInput is the shared input layer, loaded once from here |
| 14, 15 | VoodooGPIO, VoodooI2CServices | VoodooI2C's own plugins, loaded first because VoodooI2C links against them |
| 16 | VoodooI2C | I2C bus driver for the touchpad (ELAN06FA on PC02.I2C1, 8086:7F4D). Its bundled VoodooInput is not loaded, because two copies would collide |
| 17 | VoodooI2CHID | HID over I2C |
| 18 | LegionI2CArrowLake | plist only: a VoodooI2C personality for the Arrow Lake-HX I2C IDs with the Ice Lake timing values, so it comes after VoodooI2C |
| 19 | MtkWlan | MT7925 Wi-Fi |
| 20 | AMFIPass | lets WindowServer load NvGfx's ad hoc signed Metal plugin |
| 21 | AppleALC | ALC257 audio on Sequoia (alcid=18); it loads on Tahoe too, but Tahoe has no AppleHDA and uses VoodooHDA from /Library/Extensions |
| 22 | LegionCpuProbe | read-only CPU power probe; optional |
| 23 | BlueToolFixup | lets bluetoothd accept a non-Apple controller |
| 24 | LegionBtFix | patches bluetoothd on Tahoe; MinKernel 25.0.0, MaxKernel 25.99.99, so Sequoia never loads it |
| 25 | MtkBt | loads the MT7925 Bluetooth firmware so bluetoothd finds a working controller |
The graphics driver is not here. NvGfx is installed from its own package into the system, not injected by OpenCore.
The README's kext table also lists MtkWlanNative 0.4.14 and LegionCpuPower 0.4.1, and the README's Wi-Fi row names the boot-args mtkfe=native mtknativeif=1. The published config has none of these yet: it is the kext list of 2026-10-17, and the README says it is due a refresh.
boot-args:-v keepsyms=1 debug=0x100(verbose boot, and a panic stays on screen with symbols),-vi2c-force-polling(VoodooGPIO has no Arrow Lake GPIO data, so the touchpad is polled instead of using its interrupt pin),revpatch=sbvmm,cpuname revcpu=1for RestrictEvents, the NvGfx set (nvfb=1 nvaccel=1 nvfbheads=4 -nvkmsnosmooth -nvaccelnoheadless nvrmacpibl=1 nvrmphysctl=1 nvrmnvpcf=1 nvrmtgp=1 nvfbhidpi=1 nvrmdiag=1, documented in NvGfx), the AMFI settings its plugin needs (amfi_get_out_of_my_way=0x1 amfi=0x80 ipc_control_port_options=0), andalcid=18.csr-active-configis0x0A43: untrusted kexts, unrestricted file system, unrestricted NVRAM, unapproved kexts and unauthenticated root. NvGfx and VoodooHDA live in the system, not in OpenCore, and need the kext bits.NVRAM > Deletelists every key thatAddsets, so the config's values replace the stored ones at each boot.WriteFlash falsemeans those values are set for the boot only and not written into the firmware's variable store.UEFI > Quirks > RequestBootVarRoutingkeeps macOS's Startup Disk writes in OpenCore's own GUID, so macOS cannot rearrange the firmware boot order.ReleaseUsbOwnershiptakes the xHCI controllers from the firmware's legacy USB handling.ResizeGpuBars -1leaves the BAR sizes as the firmware set them.Misc > Security:SecureBootModel Disabled(Secure Boot is off in the BIOS; OpenCore and the drivers are unsigned),Vault Optional,ScanPolicy 0,DmgLoading Signed,BlacklistAppleUpdate true(withrun-efi-updater No, macOS updates never try to flash Apple firmware).Misc > Debug:Target 67writes the OpenCore log toopencore-*.txton the EFI partition and shows warnings and errors on screen (DisplayLevel0x80000002). The file is useful with a DEBUG build of OpenCore and harmless with a RELEASE one.PlatformInfo:MacBookPro16,1,UpdateSMBIOSMode Create,SpoofVendor true. The four identity fields carry OpenCore's sample placeholders, written byscripts/sanitize_config.py; generate your own with GenSMBIOS before the first boot.
The BIOS GPU mode decides which GPU drives the internal panel, and the firmware does not always keep the same one between boots. The OpenCore log tells which one it got: Current FB at 0x6000000000 is the RTX 5070, Current FB at 0x70800000 is the Intel iGPU.
- Discrete: the panel is on the RTX 5070 and NvGfx drives it with Metal. This config is set up for that case: the NvGfx boot-args,
ResizeAppleGpuBars 0, the IOMMU quirks and AMFIPass are all there for it. - Hybrid: the panel is on the iGPU (
8086:7D67), and macOS has no accelerated driver for it. This config does not load one; the Intel work is in XeGfx. The config makes sure macOS at least keeps the iGPU: there is no-wegnoigpu, and WhateverGreen is loaded. An early config had-wegnoigpu, and on a Hybrid boot WindowServer found no framebuffer at all and stayed on the verbose console.
Nothing in the config changes between the two modes. The same EFI boots both, and the result depends on the BIOS setting. For a daily system, set Discrete in the BIOS.
- A kext or driver: keep the old bundle next to the new one (renamed, for example
MtkWlan.kext.bak), copy the new one intoEFI/OC/Kexts, and boot. If a new kext needs aKernel > Addentry, add it in its place in the load order and runocvalidatefrom the same OpenCore release. - OpenCore itself: replace
BOOTx64.efi,OpenCore.efiand the four OpenCore drivers from one release together, thenocvalidatethe config against that release's schema. - The stick: only a config that has booted from the internal partition is copied to the stick (rsync of the whole
EFIfolder), and then the stick'sLauncherOptionandShowPickerare set back as described above. - macOS updates: most kexts here do not care. Two do: LegionBtFix patches specific
bluetoothdcode and is limited to Darwin 25, and MtkWlanNative checks the build it runs on. Both were checked on 26.7.2 (25G332) before being released for it. - Rollback: F12 and the stick. It boots the same macOS volume with the last known-good EFI, and from there the internal EFI partition can be mounted (
diskutil mount) and the.bakcopy put back. - ACPI after a BIOS update: the MADT has to be rebuilt with
x2apic_to_lapic.pyfrom a fresh dump, anddsdt_patches.pyrun against the new DSDT and SSDTs. A find that no longer occurs exactly once means the table changed and that patch needs a new look.
MANIFEST.txt has the sha256 of every file on the EFI partition this config was taken from (2026-10-17), apart from config.plist and the logs.