Restructure into package format

This commit is contained in:
Mykola Grymalyuk
2024-03-31 21:27:36 -06:00
parent d02d89b9c0
commit 463bed4e06
81 changed files with 881 additions and 464 deletions

View File

@@ -0,0 +1,93 @@
"""
bluetooth.py: Class for handling Bluetooth Patches, invocation from build.py
"""
import logging
import binascii
from . import support
from .. import constants
from ..detections import device_probe
from ..datasets import (
smbios_data,
bluetooth_data
)
class BuildBluetooth:
"""
Build Library for Bluetooth Support
Invoke from build.py
"""
def __init__(self, model: str, global_constants: constants.Constants, config: dict) -> None:
self.model: str = model
self.config: dict = config
self.constants: constants.Constants = global_constants
self.computer: device_probe.Computer = self.constants.computer
self._build()
def _build(self) -> None:
"""
Kick off Bluetooth Build Process
"""
if not self.constants.custom_model and self.computer.bluetooth_chipset:
self._on_model()
else:
self._prebuilt_assumption()
def _on_model(self) -> None:
"""
On-Model Hardware Detection Handling
"""
if self.computer.bluetooth_chipset in ["BRCM2070 Hub", "BRCM2046 Hub"]:
logging.info("- Fixing Legacy Bluetooth for macOS Monterey")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("Bluetooth-Spoof.kext", self.constants.btspoof_version, self.constants.btspoof_path)
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -btlfxallowanyaddr"
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["bluetoothInternalControllerInfo"] = binascii.unhexlify("0000000000000000000000000000")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["bluetoothExternalDongleFailed"] = binascii.unhexlify("00")
self.config["NVRAM"]["Delete"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"] += ["bluetoothInternalControllerInfo", "bluetoothExternalDongleFailed"]
elif self.computer.bluetooth_chipset == "BRCM20702 Hub":
# BCM94331 can include either BCM2070 or BRCM20702 v1 Bluetooth chipsets
# Note Monterey only natively supports BRCM20702 v2 (found with BCM94360)
# Due to this, BlueToolFixup is required to resolve Firmware Uploading on legacy chipsets
if self.computer.wifi:
if self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirPortBrcm4360:
logging.info("- Fixing Legacy Bluetooth for macOS Monterey")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
elif self.computer.bluetooth_chipset == "3rd Party Bluetooth 4.0 Hub":
logging.info("- Detected 3rd Party Bluetooth Chipset")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
logging.info("- Enabling Bluetooth FeatureFlags")
self.config["Kernel"]["Quirks"]["ExtendBTFeatureFlags"] = True
def _prebuilt_assumption(self) -> None:
"""
Fall back to pre-built assumptions
"""
if not self.model in smbios_data.smbios_dictionary:
return
if not "Bluetooth Model" in smbios_data.smbios_dictionary[self.model]:
return
if smbios_data.smbios_dictionary[self.model]["Bluetooth Model"] <= bluetooth_data.bluetooth_data.BRCM20702_v1.value:
logging.info("- Fixing Legacy Bluetooth for macOS Monterey")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
if smbios_data.smbios_dictionary[self.model]["Bluetooth Model"] <= bluetooth_data.bluetooth_data.BRCM2070.value:
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -btlfxallowanyaddr"
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["bluetoothInternalControllerInfo"] = binascii.unhexlify("0000000000000000000000000000")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["bluetoothExternalDongleFailed"] = binascii.unhexlify("00")
self.config["NVRAM"]["Delete"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"] += ["bluetoothInternalControllerInfo", "bluetoothExternalDongleFailed"]
support.BuildSupport(self.model, self.constants, self.config).enable_kext("Bluetooth-Spoof.kext", self.constants.btspoof_version, self.constants.btspoof_path)

View File

@@ -0,0 +1,171 @@
"""
build.py: Class for generating OpenCore Configurations tailored for Macs
"""
import copy
import pickle
import shutil
import logging
import zipfile
import plistlib
from pathlib import Path
from datetime import date
from .. import constants
from ..utilities import utilities
from .networking import (
wired,
wireless
)
from . import (
bluetooth,
firmware,
graphics_audio,
support,
storage,
smbios,
security,
misc
)
def rmtree_handler(func, path, exc_info) -> None:
if exc_info[0] == FileNotFoundError:
return
raise # pylint: disable=misplaced-bare-raise
class BuildOpenCore:
"""
Core Build Library for generating and validating OpenCore EFI Configurations
compatible with genuine Macs
"""
def __init__(self, model: str, global_constants: constants.Constants) -> None:
self.model: str = model
self.config: dict = None
self.constants: constants.Constants = global_constants
self._build_opencore()
def _build_efi(self) -> None:
"""
Build EFI folder
"""
utilities.cls()
logging.info(f"Building Configuration {'for external' if self.constants.custom_model else 'on model'}: {self.model}")
self._generate_base()
self._set_revision()
# Set Lilu and co.
support.BuildSupport(self.model, self.constants, self.config).enable_kext("Lilu.kext", self.constants.lilu_version, self.constants.lilu_path)
self.config["Kernel"]["Quirks"]["DisableLinkeditJettison"] = True
# Call support functions
for function in [
firmware.BuildFirmware,
wired.BuildWiredNetworking,
wireless.BuildWirelessNetworking,
graphics_audio.BuildGraphicsAudio,
bluetooth.BuildBluetooth,
storage.BuildStorage,
smbios.BuildSMBIOS,
security.BuildSecurity,
misc.BuildMiscellaneous
]:
function(self.model, self.constants, self.config)
# Work-around ocvalidate
if self.constants.validate is False:
logging.info("- Adding bootmgfw.efi BlessOverride")
self.config["Misc"]["BlessOverride"] += ["\\EFI\\Microsoft\\Boot\\bootmgfw.efi"]
def _generate_base(self) -> None:
"""
Generate OpenCore base folder and config
"""
if not Path(self.constants.build_path).exists():
logging.info("Creating build folder")
Path(self.constants.build_path).mkdir()
else:
logging.info("Build folder already present, skipping")
if Path(self.constants.opencore_zip_copied).exists():
logging.info("Deleting old copy of OpenCore zip")
Path(self.constants.opencore_zip_copied).unlink()
if Path(self.constants.opencore_release_folder).exists():
logging.info("Deleting old copy of OpenCore folder")
shutil.rmtree(self.constants.opencore_release_folder, onerror=rmtree_handler, ignore_errors=True)
logging.info("")
logging.info(f"- Adding OpenCore v{self.constants.opencore_version} {'DEBUG' if self.constants.opencore_debug is True else 'RELEASE'}")
shutil.copy(self.constants.opencore_zip_source, self.constants.build_path)
zipfile.ZipFile(self.constants.opencore_zip_copied).extractall(self.constants.build_path)
# Setup config.plist for editing
logging.info("- Adding config.plist for OpenCore")
shutil.copy(self.constants.plist_template, self.constants.oc_folder)
self.config = plistlib.load(Path(self.constants.plist_path).open("rb"))
def _set_revision(self) -> None:
"""
Set revision information in config.plist
"""
self.config["#Revision"]["Build-Version"] = f"{self.constants.patcher_version} - {date.today()}"
if not self.constants.custom_model:
self.config["#Revision"]["Build-Type"] = "OpenCore Built on Target Machine"
computer_copy = copy.copy(self.constants.computer)
computer_copy.ioregistry = None
self.config["#Revision"]["Hardware-Probe"] = pickle.dumps(computer_copy)
else:
self.config["#Revision"]["Build-Type"] = "OpenCore Built for External Machine"
self.config["#Revision"]["OpenCore-Version"] = f"{self.constants.opencore_version} - {'DEBUG' if self.constants.opencore_debug is True else 'RELEASE'}"
self.config["#Revision"]["Original-Model"] = self.model
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Version"] = f"{self.constants.patcher_version}"
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Model"] = self.model
def _save_config(self) -> None:
"""
Save config.plist to disk
"""
plistlib.dump(self.config, Path(self.constants.plist_path).open("wb"), sort_keys=True)
def _build_opencore(self) -> None:
"""
Kick off the build process
This is the main function:
- Generates the OpenCore configuration
- Cleans working directory
- Signs files
- Validates generated EFI
"""
# Generate OpenCore Configuration
self._build_efi()
if self.constants.allow_oc_everywhere is False or self.constants.allow_native_spoofs is True or (self.constants.custom_serial_number != "" and self.constants.custom_board_serial_number != ""):
smbios.BuildSMBIOS(self.model, self.constants, self.config).set_smbios()
support.BuildSupport(self.model, self.constants, self.config).cleanup()
self._save_config()
# Post-build handling
support.BuildSupport(self.model, self.constants, self.config).sign_files()
support.BuildSupport(self.model, self.constants, self.config).validate_pathing()
logging.info("")
logging.info(f"Your OpenCore EFI for {self.model} has been built at:")
logging.info(f" {self.constants.opencore_release_folder}")
logging.info("")

View File

@@ -0,0 +1,351 @@
"""
firmware.py: Class for handling CPU and Firmware Patches, invocation from build.py
"""
import shutil
import logging
import binascii
from pathlib import Path
from . import support
from .. import constants
from ..utilities import generate_smbios
from ..detections import device_probe
from ..datasets import (
smbios_data,
cpu_data,
os_data
)
class BuildFirmware:
"""
Build Library for CPU and Firmware Support
Invoke from build.py
"""
def __init__(self, model: str, global_constants: constants.Constants, config: dict) -> None:
self.model: str = model
self.config: dict = config
self.constants: constants.Constants = global_constants
self.computer: device_probe.Computer = self.constants.computer
self._build()
def _build(self) -> None:
"""
Kick off CPU and Firmware Build Process
"""
self._cpu_compatibility_handling()
self._power_management_handling()
self._acpi_handling()
self._firmware_driver_handling()
self._firmware_compatibility_handling()
self._apple_logo_handling()
def _apple_logo_handling(self) -> None:
"""
Apple logo Handling
"""
# Macs that natively support Monterey (excluding MacPro6,1 and Macmini7,1) won't have boot.efi draw the Apple logo.
# This causes a cosmetic issue when booting through OpenCore, as the Apple logo will be missing.
if not self.model in smbios_data.smbios_dictionary:
return
if smbios_data.smbios_dictionary[self.model]["Max OS Supported"] >= os_data.os_data.monterey and self.model not in ["MacPro6,1", "Macmini7,1"]:
logging.info("- Enabling Boot Logo patch")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Booter"]["Patch"], "Comment", "Patch SkipLogo")["Enabled"] = True
def _power_management_handling(self) -> None:
"""
Power Management Handling
"""
if not self.model in smbios_data.smbios_dictionary:
return
if not "CPU Generation" in smbios_data.smbios_dictionary[self.model]:
return
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.ivy_bridge.value:
# In macOS Ventura, Apple dropped AppleIntelCPUPowerManagement* kexts as they're unused on Haswell+
# However re-injecting the AICPUPM kexts is not enough, as Ventura changed how 'intel_cpupm_matching' is set:
# macOS 12.5: https://github.com/apple-oss-distributions/xnu/blob/xnu-8020.140.41/osfmk/i386/pal_routines.h#L153-L163
# macOS 13.0: https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.41.9/osfmk/i386/pal_routines.h#L153-L164
#
# Specifically Apple has this logic for power management:
# - 0: Kext Based Power Management
# - 3: Kernel Based Power Management (For Haswell+ and Virtual Machines)
# - 4: Generic Virtual Machine Power Management
#
# Apple determines which to use by verifying whether 'plugin-type' exists in ACPI (with a value of 1 for Haswell, 2 for VMs)
# By default however, the plugin-type is not set, and thus the default value of '0' is used
# https://github.com/apple-oss-distributions/xnu/blob/e7776783b89a353188416a9a346c6cdb4928faad/osfmk/i386/pal_native.h#L62
#
# With Ventura, Apple no longer sets '0' as the default value, and instead sets it to '3'
# This breaks AppleIntelCPUPowerManagement.kext matching as it no longer matches against the correct criteria
#
# To resolve, we patched AICPUPM to attach regardless of the value of 'intel_cpupm_matching'
logging.info("- Enabling legacy power management support")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleIntelCPUPowerManagement.kext", self.constants.aicpupm_version, self.constants.aicpupm_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleIntelCPUPowerManagementClient.kext", self.constants.aicpupm_version, self.constants.aicpupm_client_path)
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.sandy_bridge.value or self.constants.disable_fw_throttle is True:
# With macOS 12.3 Beta 1, Apple dropped the 'plugin-type' check within X86PlatformPlugin
# Because of this, X86PP will match onto the CPU instead of ACPI_SMC_PlatformPlugin
# This causes power management to break on pre-Ivy Bridge CPUs as they don't have correct
# power management tables provided.
# This patch will simply increase ASPP's 'IOProbeScore' to outmatch X86PP
logging.info("- Overriding ACPI SMC matching")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("ASPP-Override.kext", self.constants.aspp_override_version, self.constants.aspp_override_path)
if self.constants.disable_fw_throttle is True:
# Only inject on older OSes if user requests
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Add"], "BundlePath", "ASPP-Override.kext")["MinKernel"] = ""
if self.constants.disable_fw_throttle is True and smbios_data.smbios_dictionary[self.model]["CPU Generation"] >= cpu_data.CPUGen.nehalem.value:
logging.info("- Disabling Firmware Throttling")
# Nehalem and newer systems force firmware throttling via MSR_POWER_CTL
support.BuildSupport(self.model, self.constants, self.config).enable_kext("SimpleMSR.kext", self.constants.simplemsr_version, self.constants.simplemsr_path)
def _acpi_handling(self) -> None:
"""
ACPI Table Handling
"""
if not self.model in smbios_data.smbios_dictionary:
return
if not "CPU Generation" in smbios_data.smbios_dictionary[self.model]:
return
# Resolves Big Sur support for consumer Nehalem
# CPBG device in ACPI is a Co-Processor Bridge Device, which is not actually physically present
# IOPCIFamily will error when enumerating this device, thus we'll power it off via _STA (has no effect in older OSes)
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] == cpu_data.CPUGen.nehalem.value and not (self.model.startswith("MacPro") or self.model.startswith("Xserve")):
logging.info("- Adding SSDT-CPBG.aml")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Add"], "Path", "SSDT-CPBG.aml")["Enabled"] = True
shutil.copy(self.constants.pci_ssdt_path, self.constants.acpi_path)
if cpu_data.CPUGen.sandy_bridge <= smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.ivy_bridge.value and self.model != "MacPro6,1":
# Based on: https://egpu.io/forums/pc-setup/fix-dsdt-override-to-correct-error-12/
# Applicable for Sandy and Ivy Bridge Macs
logging.info("- Enabling Windows 10 UEFI Audio support")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Add"], "Path", "SSDT-PCI.aml")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "BUF0 to BUF1")["Enabled"] = True
shutil.copy(self.constants.windows_ssdt_path, self.constants.acpi_path)
def _cpu_compatibility_handling(self) -> None:
"""
CPU Compatibility Handling
"""
if not self.model in smbios_data.smbios_dictionary:
return
if not "CPU Generation" in smbios_data.smbios_dictionary[self.model]:
return
# SSE4,1 support (ie. Penryn)
# Required for macOS Mojave and newer
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.penryn.value:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AAAMouSSE.kext", self.constants.mousse_version, self.constants.mousse_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("telemetrap.kext", self.constants.telemetrap_version, self.constants.telemetrap_path)
# Force Rosetta Cryptex installation in macOS Ventura
# Restores support for CPUs lacking AVX2.0 support
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.ivy_bridge.value:
logging.info("- Enabling Rosetta Cryptex support in Ventura")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("CryptexFixup.kext", self.constants.cryptexfixup_version, self.constants.cryptexfixup_path)
# i3 Ivy Bridge iMacs don't support RDRAND
# However for prebuilt, assume they do
if (not self.constants.custom_model and "RDRAND" not in self.computer.cpu.flags) or \
(smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.sandy_bridge.value):
# Ref: https://github.com/reenigneorcim/SurPlus
# Enable for all systems missing RDRAND support
logging.info("- Adding SurPlus Patch for Race Condition")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "SurPlus v1 - PART 1 of 2 - Patch read_erandom (inlined in _early_random)")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "SurPlus v1 - PART 2 of 2 - Patch register_and_init_prng")["Enabled"] = True
if self.constants.force_surplus is True:
# Syncretic forces SurPlus to only run on Beta 7 and older by default for saftey reasons
# If users desires, allow forcing in newer OSes
logging.info("- Allowing SurPlus on all newer OSes")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "SurPlus v1 - PART 1 of 2 - Patch read_erandom (inlined in _early_random)")["MaxKernel"] = ""
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "SurPlus v1 - PART 2 of 2 - Patch register_and_init_prng")["MaxKernel"] = ""
# In macOS 12.4 and 12.5 Beta 1, Apple added AVX1.0 usage in AppleFSCompressionTypeZlib
# Pre-Sandy Bridge CPUs don't support AVX1.0, thus we'll downgrade the kext to 12.3.1's
# Currently a (hopefully) temporary workaround for the issue, proper fix needs to be investigated
# Ref:
# https://forums.macrumors.com/threads/macos-12-monterey-on-unsupported-macs-thread.2299557/post-31120235
# https://forums.macrumors.com/threads/monterand-probably-the-start-of-an-ongoing-saga.2320479/post-31123553
# To verify the non-AVX kext is used, check IOService for 'com_apple_AppleFSCompression_NoAVXCompressionTypeZlib'
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] < cpu_data.CPUGen.sandy_bridge.value:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("NoAVXFSCompressionTypeZlib.kext", self.constants.apfs_zlib_version, self.constants.apfs_zlib_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("NoAVXFSCompressionTypeZlib-AVXpel.kext", self.constants.apfs_zlib_v2_version, self.constants.apfs_zlib_v2_path)
# HID patches
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.penryn.value:
logging.info("- Adding IOHIDFamily patch")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Identifier", "com.apple.iokit.IOHIDFamily")["Enabled"] = True
def _firmware_driver_handling(self) -> None:
"""
Firmware Driver Handling (Drivers/*.efi)
"""
if not self.model in smbios_data.smbios_dictionary:
return
if not "CPU Generation" in smbios_data.smbios_dictionary[self.model]:
return
# Exfat check
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] < cpu_data.CPUGen.sandy_bridge.value:
# Sandy Bridge and newer Macs natively support ExFat
logging.info("- Adding ExFatDxeLegacy.efi")
shutil.copy(self.constants.exfat_legacy_driver_path, self.constants.drivers_path)
support.BuildSupport(self.model, self.constants, self.config).get_efi_binary_by_path("ExFatDxeLegacy.efi", "UEFI", "Drivers")["Enabled"] = True
# NVMe check
if self.constants.nvme_boot is True:
logging.info("- Enabling NVMe boot support")
shutil.copy(self.constants.nvme_driver_path, self.constants.drivers_path)
support.BuildSupport(self.model, self.constants, self.config).get_efi_binary_by_path("NvmExpressDxe.efi", "UEFI", "Drivers")["Enabled"] = True
# USB check
if self.constants.xhci_boot is True:
logging.info("- Adding USB 3.0 Controller Patch")
logging.info("- Adding XhciDxe.efi and UsbBusDxe.efi")
shutil.copy(self.constants.xhci_driver_path, self.constants.drivers_path)
shutil.copy(self.constants.usb_bus_driver_path, self.constants.drivers_path)
support.BuildSupport(self.model, self.constants, self.config).get_efi_binary_by_path("XhciDxe.efi", "UEFI", "Drivers")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_efi_binary_by_path("UsbBusDxe.efi", "UEFI", "Drivers")["Enabled"] = True
# PCIe Link Rate check
if self.model == "MacPro3,1":
logging.info("- Adding PCIe Link Rate Patch")
shutil.copy(self.constants.link_rate_driver_path, self.constants.drivers_path)
support.BuildSupport(self.model, self.constants, self.config).get_efi_binary_by_path("FixPCIeLinkRate.efi", "UEFI", "Drivers")["Enabled"] = True
# CSM check
# For model support, check for GUID in firmware and as well as Bootcamp Assistant's Info.plist ('PreUEFIModels' key)
# Ref: https://github.com/acidanthera/OpenCorePkg/blob/0.9.5/Platform/OpenLegacyBoot/OpenLegacyBoot.c#L19
if Path(self.constants.drivers_path / Path("OpenLegacyBoot.efi")).exists():
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.ivy_bridge.value and self.model != "MacPro6,1":
logging.info("- Enabling CSM support")
support.BuildSupport(self.model, self.constants, self.config).get_efi_binary_by_path("OpenLegacyBoot.efi", "UEFI", "Drivers")["Enabled"] = True
else:
# Shipped alongside OpenCorePkg, so remove if unused
(self.constants.drivers_path / Path("OpenLegacyBoot.efi")).unlink()
def _firmware_compatibility_handling(self) -> None:
"""
Firmware Compatibility Handling (Firmware and Kernel)
"""
self._dual_dp_handling()
# Patches IOPCIConfigurator.cpp's IOPCIIsHotplugPort to skip configRead16/32 calls
# Credit to CaseySJ for original discovery:
# - Patch: https://github.com/AMD-OSX/AMD_Vanilla/pull/196
# - Source: https://github.com/apple-oss-distributions/IOPCIFamily/blob/IOPCIFamily-583.40.1/IOPCIConfigurator.cpp#L968-L1022
#
# Currently all pre-Sandy Bridge Macs lacking an iGPU benefit from this patch as well as MacPro6,1
# Otherwise some graphics hardware will fail to wake, macOS will misreport hardware as ExpressCard-based,
# prevents MacPro6,1 from both booting unaccelerated and breaks low power states.
if (
self.model in ["MacPro6,1", "MacBookPro4,1"] or
(
smbios_data.smbios_dictionary[self.model]["CPU Generation"] < cpu_data.CPUGen.sandy_bridge.value and \
not self.model.startswith("MacBook")
)
):
logging.info("- Adding PCI Bus Enumeration Patch")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "CaseySJ - Fix PCI bus enumeration (Ventura)")["Enabled"] = True
# Sonoma slightly adjusted this line specifically
# - https://github.com/apple-oss-distributions/IOPCIFamily/blob/IOPCIFamily-583.40.1/IOPCIConfigurator.cpp#L1009
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Fix PCI bus enumeration (Sonoma)")["Enabled"] = True
if self.constants.set_vmm_cpuid is True:
logging.info("- Enabling VMM patch")
self.config["Kernel"]["Emulate"]["Cpuid1Data"] = binascii.unhexlify("00000000000000000000008000000000")
self.config["Kernel"]["Emulate"]["Cpuid1Mask"] = binascii.unhexlify("00000000000000000000008000000000")
if (
self.model.startswith("MacBook")
and (
smbios_data.smbios_dictionary[self.model]["CPU Generation"] == cpu_data.CPUGen.haswell.value or
smbios_data.smbios_dictionary[self.model]["CPU Generation"] == cpu_data.CPUGen.broadwell.value
)
):
# Fix Virtual Machine support for non-macOS OSes
# Haswell and Broadwell MacBooks lock out the VMX bit if booting UEFI Windows
logging.info("- Enabling VMX Bit for non-macOS OSes")
self.config["UEFI"]["Quirks"]["EnableVmx"] = True
# Works-around Hibernation bug where connecting all firmware drivers breaks the transition from S4
# Mainly applicable for MacBookPro9,1
if self.constants.disable_connectdrivers is True:
logging.info("- Disabling ConnectDrivers")
self.config["UEFI"]["ConnectDrivers"] = False
if self.constants.nvram_write is False:
logging.info("- Disabling Hardware NVRAM Write")
self.config["NVRAM"]["WriteFlash"] = False
if self.constants.serial_settings != "None":
# AppleMCEReporter is very picky about which models attach to the kext
# Commonly it will kernel panic on multi-socket systems, however even on single-socket systems it may cause instability
# To avoid any issues, we'll disable it if the spoof is set to an affected SMBIOS
affected_smbios = ["MacPro6,1", "MacPro7,1", "iMacPro1,1"]
if self.model not in affected_smbios:
# If MacPro6,1 host spoofs, we can safely enable it
if self.constants.override_smbios in affected_smbios or generate_smbios.set_smbios_model_spoof(self.model) in affected_smbios:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleMCEReporterDisabler.kext", self.constants.mce_version, self.constants.mce_path)
def _dual_dp_handling(self) -> None:
"""
Dual DisplayPort Stream Handler (ex. 5k iMac)
Apple has 2 modes for display handling on 5K iMacs and iMac Pro
If at any point in the boot chain an "unsupported" entry is loaded, the firmware will tell the
Display Controller to enter a 4K compatible mode that only uses a single DisplayPort 1.2 stream internally.
This is to prevent situations where the system would boot into an enviroment that cannot handle the custom
dual DisplayPort 1.2 streams the 5k Display uses
To work around this issue, we trick the firmware into loading OpenCore through Apple's Hardware Diagnostic Tests
Specifically hiding as Product.efi under '/System/Library/CoreServices/.diagnostics/Drivers/HardwareDrivers/Product.efi'
The reason chainloading via ./Drivers/HardwareDrivers is possible is thanks to it being loaded via an encrypted file buffer
whereas other drivers like ./qa_logger.efi is invoked via Device Path.
"""
if "Dual DisplayPort Display" not in smbios_data.smbios_dictionary[self.model]:
return
logging.info("- Adding 4K/5K Display Patch")
# Set LauncherPath to '/boot.efi'
# This is to ensure that only the Mac's firmware presents the boot option, but not OpenCore
# https://github.com/acidanthera/OpenCorePkg/blob/0.7.6/Library/OcAppleBootPolicyLib/OcAppleBootPolicyLib.c#L50-L73
self.config["Misc"]["Boot"]["LauncherPath"] = "\\boot.efi"
# Setup diags.efi chainloading
Path(self.constants.opencore_release_folder / Path("System/Library/CoreServices/.diagnostics/Drivers/HardwareDrivers")).mkdir(parents=True, exist_ok=True)
if self.constants.boot_efi is True:
path_oc_loader = self.constants.opencore_release_folder / Path("EFI/BOOT/BOOTx64.efi")
else:
path_oc_loader = self.constants.opencore_release_folder / Path("System/Library/CoreServices/boot.efi")
shutil.move(path_oc_loader, self.constants.opencore_release_folder / Path("System/Library/CoreServices/.diagnostics/Drivers/HardwareDrivers/Product.efi"))
shutil.copy(self.constants.diags_launcher_path, self.constants.opencore_release_folder)
shutil.move(self.constants.opencore_release_folder / Path("diags.efi"), self.constants.opencore_release_folder / Path("boot.efi"))

View File

@@ -0,0 +1,581 @@
"""
graphics_audio.py: Class for handling Graphics and Audio Patches, invocation from build.py
"""
import shutil
import logging
import binascii
from pathlib import Path
from . import support
from .. import constants
from ..utilities import utilities
from ..detections import device_probe
from ..datasets import (
smbios_data,
model_array,
os_data,
cpu_data,
video_bios_data
)
class BuildGraphicsAudio:
"""
Build Library for Graphics and Audio Support
Invoke from build.py
"""
def __init__(self, model: str, global_constants: constants.Constants, config: dict) -> None:
self.model: str = model
self.config: dict = config
self.constants: constants.Constants = global_constants
self.computer: device_probe.Computer = self.constants.computer
self.gfx0_path = None
self._build()
def _build(self) -> None:
"""
Kick off Graphics and Audio Build Process
"""
self._imac_mxm_patching()
self._graphics_handling()
self._audio_handling()
self._firmware_handling()
self._spoof_handling()
self._ioaccel_workaround()
def _graphics_handling(self) -> None:
"""
Graphics Handling
Primarily for Mac Pros and systems with Nvidia Maxwell/Pascal GPUs
"""
if self.constants.allow_oc_everywhere is False and self.constants.serial_settings != "None":
if not support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("WhateverGreen.kext")["Enabled"] is True:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("WhateverGreen.kext", self.constants.whatevergreen_version, self.constants.whatevergreen_path)
# Mac Pro handling
if self.model in model_array.MacPro:
if not self.constants.custom_model:
for i, device in enumerate(self.computer.gpus):
logging.info(f"- Found dGPU ({i + 1}): {utilities.friendly_hex(device.vendor_id)}:{utilities.friendly_hex(device.device_id)}")
self.config["#Revision"][f"Hardware-MacPro-dGPU-{i + 1}"] = f"{utilities.friendly_hex(device.vendor_id)}:{utilities.friendly_hex(device.device_id)}"
if device.pci_path and device.acpi_path:
logging.info(f"- Found dGPU ({i + 1}) at {device.pci_path}")
if isinstance(device, device_probe.AMD):
logging.info("- Adding Mac Pro, Xserve DRM patches")
self.config["DeviceProperties"]["Add"][device.pci_path] = {"shikigva": 128, "unfairgva": 1, "rebuild-device-tree": 1, "agdpmod": "pikera", "enable-gva-support": 1}
elif isinstance(device, device_probe.NVIDIA):
logging.info("- Enabling Nvidia Output Patch")
self.config["DeviceProperties"]["Add"][device.pci_path] = {"rebuild-device-tree": 1, "agdpmod": "vit9696"}
self.config["UEFI"]["Quirks"]["ForgeUefiSupport"] = True
self.config["UEFI"]["Quirks"]["ReloadOptionRoms"] = True
else:
logging.info(f"- Failed to find Device path for dGPU {i + 1}")
if isinstance(device, device_probe.AMD):
logging.info("- Adding Mac Pro, Xserve DRM patches")
if "shikigva=128 unfairgva=1" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"]:
logging.info("- Falling back to boot-args")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " shikigva=128 unfairgva=1 agdpmod=pikera radgva=1" + (
" -wegtree" if "-wegtree" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] else ""
)
elif isinstance(device, device_probe.NVIDIA):
logging.info("- Enabling Nvidia Output Patch")
if "-wegtree agdpmod=vit9696" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"]:
logging.info("- Falling back to boot-args")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -wegtree agdpmod=vit9696"
self.config["UEFI"]["Quirks"]["ForgeUefiSupport"] = True
self.config["UEFI"]["Quirks"]["ReloadOptionRoms"] = True
if not self.computer.gpus:
logging.info("- No socketed dGPU found")
else:
logging.info("- Adding Mac Pro, Xserve DRM patches")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " shikigva=128 unfairgva=1 -wegtree"
if not support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("WhateverGreen.kext")["Enabled"] is True:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("WhateverGreen.kext", self.constants.whatevergreen_version, self.constants.whatevergreen_path)
# Web Driver specific
if not self.constants.custom_model:
for i, device in enumerate(self.computer.gpus):
if isinstance(device, device_probe.NVIDIA):
if (
device.arch in [device_probe.NVIDIA.Archs.Fermi, device_probe.NVIDIA.Archs.Maxwell, device_probe.NVIDIA.Archs.Pascal] or
(self.constants.force_nv_web is True and device.arch in [device_probe.NVIDIA.Archs.Tesla, device_probe.NVIDIA.Archs.Kepler])
):
logging.info(f"- Enabling Web Driver Patches for GPU ({i + 1}): {utilities.friendly_hex(device.vendor_id)}:{utilities.friendly_hex(device.device_id)}")
if device.pci_path and device.acpi_path:
if device.pci_path in self.config["DeviceProperties"]["Add"]:
self.config["DeviceProperties"]["Add"][device.pci_path].update({"disable-metal": 1, "force-compat": 1})
else:
self.config["DeviceProperties"]["Add"][device.pci_path] = {"disable-metal": 1, "force-compat": 1}
support.BuildSupport(self.model, self.constants, self.config).enable_kext("WhateverGreen.kext", self.constants.whatevergreen_version, self.constants.whatevergreen_path)
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"].update({"nvda_drv": binascii.unhexlify("31")})
if "nvda_drv" not in self.config["NVRAM"]["Delete"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]:
self.config["NVRAM"]["Delete"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"] += ["nvda_drv"]
else:
if "ngfxgl=1 ngfxcompat=1" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"]:
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " ngfxgl=1 ngfxcompat=1"
support.BuildSupport(self.model, self.constants, self.config).enable_kext("WhateverGreen.kext", self.constants.whatevergreen_version, self.constants.whatevergreen_path)
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"].update({"nvda_drv": binascii.unhexlify("31")})
if "nvda_drv" not in self.config["NVRAM"]["Delete"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]:
self.config["NVRAM"]["Delete"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"] += ["nvda_drv"]
def _backlight_path_detection(self) -> None:
"""
iMac MXM dGPU Backlight DevicePath Detection
"""
if not self.constants.custom_model and self.computer.dgpu and self.computer.dgpu.pci_path:
for i, device in enumerate(self.computer.gpus):
logging.info(f"- Found dGPU ({i + 1}): {utilities.friendly_hex(device.vendor_id)}:{utilities.friendly_hex(device.device_id)}")
self.config["#Revision"][f"Hardware-iMac-dGPU-{i + 1}"] = f"{utilities.friendly_hex(device.vendor_id)}:{utilities.friendly_hex(device.device_id)}"
if device.pci_path != self.computer.dgpu.pci_path:
logging.info("- device path and GFX0 Device path are different")
self.gfx0_path = device.pci_path
logging.info(f"- Set GFX0 Device Path: {self.gfx0_path}")
self.computer.dgpu.device_id = device.device_id
self.device_id = device.device_id
logging.info(f"- Found GPU Arch: {device.arch}")
if device.arch in [device_probe.AMD.Archs.Navi]:
self.computer.dgpu.arch = device.arch
# self.computer.dgpu.vendor_id = device.vendor_id
# self.vendor_id = device.vendor_id
else:
self.gfx0_path = self.computer.dgpu.pci_path
logging.info(f"- Found GFX0 Device Path: {self.gfx0_path}")
logging.info(f"- Found GPU Arch: {self.computer.dgpu.arch}")
else:
if not self.constants.custom_model:
logging.info("- Failed to find GFX0 Device path, falling back on known logic")
if self.model in ["iMac11,1", "iMac11,3"]:
self.gfx0_path = "PciRoot(0x0)/Pci(0x3,0x0)/Pci(0x0,0x0)"
elif self.model in ["iMac9,1", "iMac10,1"]:
self.gfx0_path = "PciRoot(0x0)/Pci(0xc,0x0)/Pci(0x0,0x0)"
else:
self.gfx0_path = "PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)"
def _nvidia_mxm_patch(self, backlight_path) -> None:
"""
iMac Nvidia Kepler MXM Handler
"""
if not support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("WhateverGreen.kext")["Enabled"] is True:
# Ensure WEG is enabled as we need if for Backlight patching
support.BuildSupport(self.model, self.constants, self.config).enable_kext("WhateverGreen.kext", self.constants.whatevergreen_navi_version, self.constants.whatevergreen_navi_path)
if self.model in ["iMac11,1", "iMac11,2", "iMac11,3", "iMac10,1"]:
logging.info("- Adding Nvidia Brightness Control and DRM patches")
self.config["DeviceProperties"]["Add"][backlight_path] = {
"applbkl": binascii.unhexlify("01000000"),
"@0,backlight-control": binascii.unhexlify("01000000"),
"@0,built-in": binascii.unhexlify("01000000"),
"shikigva": 256,
"agdpmod": "vit9696",
}
if self.constants.custom_model and self.model == "iMac11,2":
# iMac11,2 can have either PciRoot(0x0)/Pci(0x3,0x0)/Pci(0x0,0x0) or PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)
# Set both properties when we cannot run hardware detection
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x3,0x0)/Pci(0x0,0x0)"] = {
"applbkl": binascii.unhexlify("01000000"),
"@0,backlight-control": binascii.unhexlify("01000000"),
"@0,built-in": binascii.unhexlify("01000000"),
"shikigva": 256,
"agdpmod": "vit9696",
}
elif self.model in ["iMac12,1", "iMac12,2"]:
logging.info("- Adding Nvidia Brightness Control and DRM patches")
self.config["DeviceProperties"]["Add"][backlight_path] = {
"applbkl": binascii.unhexlify("01000000"),
"@0,backlight-control": binascii.unhexlify("01000000"),
"@0,built-in": binascii.unhexlify("01000000"),
"shikigva": 256,
"agdpmod": "vit9696",
}
logging.info("- Disabling unsupported iGPU")
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x2,0x0)"] = {
"name": binascii.unhexlify("23646973706C6179"),
"class-code": binascii.unhexlify("FFFFFFFF"),
}
shutil.copy(self.constants.backlight_injector_path, self.constants.kexts_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("BacklightInjector.kext")["Enabled"] = True
self.config["UEFI"]["Quirks"]["ForgeUefiSupport"] = True
self.config["UEFI"]["Quirks"]["ReloadOptionRoms"] = True
def _amd_mxm_patch(self, backlight_path) -> None:
"""
iMac AMD GCN and Navi MXM Handler
"""
logging.info("- Adding AMD DRM patches")
if not support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("WhateverGreen.kext")["Enabled"] is True:
# Ensure WEG is enabled as we need if for Backlight patching
support.BuildSupport(self.model, self.constants, self.config).enable_kext("WhateverGreen.kext", self.constants.whatevergreen_navi_version, self.constants.whatevergreen_navi_path)
if self.model == "iMac9,1":
logging.info("- Adding iMac9,1 Brightness Control and DRM patches")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("BacklightInjector.kext", self.constants.backlight_injectorA_version, self.constants.backlight_injectorA_path)
if not self.constants.custom_model:
if self.computer.dgpu.device_id == 0x7340:
logging.info(f"- Adding AMD RX5500XT vBIOS injection")
self.config["DeviceProperties"]["Add"][backlight_path] = {"shikigva": 128, "unfairgva": 1, "agdpmod": "pikera", "rebuild-device-tree": 1, "enable-gva-support": 1, "ATY,bin_image": binascii.unhexlify(video_bios_data.RX5500XT_64K) }
logging.info(f"- Adding AMD RX5500XT boot-args")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " agdpmod=pikera applbkl=3"
elif self.computer.dgpu.device_id_unspoofed == 0x6981:
logging.info(f"- Adding AMD WX3200 device spoofing")
self.config["DeviceProperties"]["Add"][backlight_path] = {"shikigva": 128, "unfairgva": 1, "agdpmod": "pikera", "rebuild-device-tree": 1, "enable-gva-support": 1, "model": "AMD Radeon Pro WX 3200", "device-id": binascii.unhexlify("FF67")}
else:
self.config["DeviceProperties"]["Add"][backlight_path] = {"shikigva": 128, "unfairgva": 1, "agdpmod": "pikera", "rebuild-device-tree": 1, "enable-gva-support": 1}
else:
self.config["DeviceProperties"]["Add"][backlight_path] = {"shikigva": 128, "unfairgva": 1, "agdpmod": "pikera", "rebuild-device-tree": 1, "enable-gva-support": 1}
if self.constants.custom_model and self.model == "iMac11,2":
# iMac11,2 can have either PciRoot(0x0)/Pci(0x3,0x0)/Pci(0x0,0x0) or PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)
# Set both properties when we cannot run hardware detection
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x3,0x0)/Pci(0x0,0x0)"] = {"shikigva": 128, "unfairgva": 1, "agdpmod": "pikera", "rebuild-device-tree": 1, "enable-gva-support": 1}
if self.model in ["iMac12,1", "iMac12,2"]:
logging.info("- Disabling unsupported iGPU")
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x2,0x0)"] = {
"name": binascii.unhexlify("23646973706C6179"),
"class-code": binascii.unhexlify("FFFFFFFF"),
}
elif self.model in ["iMac9,1", "iMac10,1"]:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AAAMouSSE.kext", self.constants.mousse_version, self.constants.mousse_path)
if self.computer and self.computer.dgpu:
if self.computer.dgpu.arch == device_probe.AMD.Archs.Legacy_GCN_7000:
logging.info("- Adding Legacy GCN Power Gate Patches")
self.config["DeviceProperties"]["Add"][backlight_path].update({
"CAIL,CAIL_DisableDrmdmaPowerGating": 1,
"CAIL,CAIL_DisableGfxCGPowerGating": 1,
"CAIL,CAIL_DisableUVDPowerGating": 1,
"CAIL,CAIL_DisableVCEPowerGating": 1,
})
if self.constants.imac_model == "GCN":
logging.info("- Adding Legacy GCN Power Gate Patches")
self.config["DeviceProperties"]["Add"][backlight_path].update({
"CAIL,CAIL_DisableDrmdmaPowerGating": 1,
"CAIL,CAIL_DisableGfxCGPowerGating": 1,
"CAIL,CAIL_DisableUVDPowerGating": 1,
"CAIL,CAIL_DisableVCEPowerGating": 1,
})
if self.model == "iMac11,2":
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x3,0x0)/Pci(0x0,0x0)"].update({
"CAIL,CAIL_DisableDrmdmaPowerGating": 1,
"CAIL,CAIL_DisableGfxCGPowerGating": 1,
"CAIL,CAIL_DisableUVDPowerGating": 1,
"CAIL,CAIL_DisableVCEPowerGating": 1,
})
elif self.constants.imac_model == "Lexa":
logging.info("- Adding Lexa Spoofing Patches")
self.config["DeviceProperties"]["Add"][backlight_path].update({
"model": "AMD Radeon Pro WX 3200",
"device-id": binascii.unhexlify("FF67"),
})
if self.model == "iMac11,2":
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x3,0x0)/Pci(0x0,0x0)"].update({
"model": "AMD Radeon Pro WX 3200",
"device-id": binascii.unhexlify("FF67"),
})
elif self.constants.imac_model == "Navi":
logging.info("- Adding Navi Spoofing Patches")
navi_backlight_path = backlight_path+"/Pci(0x0,0x0)/Pci(0x0,0x0)"
self.config["DeviceProperties"]["Add"][navi_backlight_path] = {
"ATY,bin_image": binascii.unhexlify(video_bios_data.RX5500XT_64K),
"shikigva": 128,
"unfairgva": 1,
"rebuild-device-tree": 1,
"enable-gva-support": 1
}
logging.info(f"- Adding AMD RX5500XT boot-args")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " agdpmod=pikera applbkl=3"
def _audio_handling(self) -> None:
"""
Audio Handler
"""
if (self.model in model_array.LegacyAudio or self.model in model_array.MacPro) and self.constants.set_alc_usage is True:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleALC.kext", self.constants.applealc_version, self.constants.applealc_path)
# Audio Patch
if self.constants.set_alc_usage is True:
if smbios_data.smbios_dictionary[self.model]["Max OS Supported"] <= os_data.os_data.high_sierra:
# Models dropped in Mojave also lost Audio support
# Xserves and MacPro4,1 are exceptions
# iMac7,1 and iMac8,1 require AppleHDA/IOAudioFamily downgrade
if not (self.model.startswith("Xserve") or self.model in ["MacPro4,1", "iMac7,1", "iMac8,1"]):
if "nForce Chipset" in smbios_data.smbios_dictionary[self.model]:
hdef_path = "PciRoot(0x0)/Pci(0x8,0x0)"
else:
hdef_path = "PciRoot(0x0)/Pci(0x1b,0x0)"
# In AppleALC, MacPro3,1's original layout is already in use, forcing layout 13 instead
if self.model == "MacPro3,1":
self.config["DeviceProperties"]["Add"][hdef_path] = {
"apple-layout-id": 90,
"use-apple-layout-id": 1,
"alc-layout-id": 13,
}
else:
self.config["DeviceProperties"]["Add"][hdef_path] = {
"apple-layout-id": 90,
"use-apple-layout-id": 1,
"use-layout-id": 1,
}
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleALC.kext", self.constants.applealc_version, self.constants.applealc_path)
elif (self.model.startswith("MacPro") and self.model != "MacPro6,1") or self.model.startswith("Xserve"):
# Used to enable Audio support for non-standard dGPUs
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleALC.kext", self.constants.applealc_version, self.constants.applealc_path)
# Due to regression in AppleALC 1.6.4+, temporarily use 1.6.3 and set override
if support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("AppleALC.kext")["Enabled"] is True:
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -lilubetaall"
def _firmware_handling(self) -> None:
"""
Firmware Handler
"""
# Add UGA to GOP layer
if "UGA Graphics" in smbios_data.smbios_dictionary[self.model]:
logging.info("- Adding UGA to GOP Patch")
self.config["UEFI"]["Output"]["GopPassThrough"] = "Apple"
# GMUX handling
if self.constants.software_demux is True and self.model in ["MacBookPro8,2", "MacBookPro8,3"]:
logging.info("- Enabling software demux")
# Add ACPI patches
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Add"], "Path", "SSDT-DGPU.aml")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "_INI to XINI")["Enabled"] = True
shutil.copy(self.constants.demux_ssdt_path, self.constants.acpi_path)
# Disable dGPU
# IOACPIPlane:/_SB/PCI0@0/P0P2@10000/GFX0@0
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)"] = {
"class-code": binascii.unhexlify("FFFFFFFF"),
"device-id": binascii.unhexlify("FFFF0000"),
"IOName": "Dortania Disabled Card",
"name": "Dortania Disabled Card"
}
self.config["DeviceProperties"]["Delete"]["PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)"] = ["class-code", "device-id", "IOName", "name"]
# Add AMDGPUWakeHandler
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AMDGPUWakeHandler.kext", self.constants.gpu_wake_version, self.constants.gpu_wake_path)
if self.constants.dGPU_switch is True and "Switchable GPUs" in smbios_data.smbios_dictionary[self.model]:
logging.info("- Allowing GMUX switching in Windows")
self.config["Booter"]["Quirks"]["SignalAppleOS"] = True
# Force Output support PC VBIOS on Mac Pros
if self.constants.force_output_support is True:
logging.info("- Forcing GOP Support")
self.config["UEFI"]["Quirks"]["ForgeUefiSupport"] = True
self.config["UEFI"]["Quirks"]["ReloadOptionRoms"] = True
# AMD GOP VBIOS injection for AMD GCN 1-4 GPUs
if self.constants.amd_gop_injection is True:
logging.info("- Adding AMDGOP.efi")
shutil.copy(self.constants.amd_gop_driver_path, self.constants.drivers_path)
support.BuildSupport(self.model, self.constants, self.config).get_efi_binary_by_path("AMDGOP.efi", "UEFI", "Drivers")["Enabled"] = True
# Nvidia Kepler GOP VBIOS injection
if self.constants.nvidia_kepler_gop_injection is True:
logging.info("- Adding NVGOP_GK.efi")
shutil.copy(self.constants.nvidia_kepler_gop_driver_path, self.constants.drivers_path)
support.BuildSupport(self.model, self.constants, self.config).get_efi_binary_by_path("NVGOP_GK.efi", "UEFI", "Drivers")["Enabled"] = True
def _spoof_handling(self) -> None:
"""
SMBIOS Spoofing Handler
"""
if self.constants.serial_settings == "None":
return
# AppleMuxControl Override
if self.model == "MacBookPro9,1":
logging.info("- Adding AppleMuxControl Override")
amc_map_path = Path(self.constants.plist_folder_path) / Path("AppleMuxControl/Info.plist")
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)"] = {"agdpmod": "vit9696"}
Path(self.constants.amc_kext_folder).mkdir()
Path(self.constants.amc_contents_folder).mkdir()
shutil.copy(amc_map_path, self.constants.amc_contents_folder)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("AMC-Override.kext")["Enabled"] = True
if self.model not in model_array.NoAGPMSupport:
logging.info("- Adding AppleGraphicsPowerManagement Override")
agpm_map_path = Path(self.constants.plist_folder_path) / Path("AppleGraphicsPowerManagement/Info.plist")
Path(self.constants.agpm_kext_folder).mkdir()
Path(self.constants.agpm_contents_folder).mkdir()
shutil.copy(agpm_map_path, self.constants.agpm_contents_folder)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("AGPM-Override.kext")["Enabled"] = True
if self.model in model_array.AGDPSupport:
logging.info("- Adding AppleGraphicsDevicePolicy Override")
agdp_map_path = Path(self.constants.plist_folder_path) / Path("AppleGraphicsDevicePolicy/Info.plist")
Path(self.constants.agdp_kext_folder).mkdir()
Path(self.constants.agdp_contents_folder).mkdir()
shutil.copy(agdp_map_path, self.constants.agdp_contents_folder)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("AGDP-Override.kext")["Enabled"] = True
# AGPM Patch
if self.model in model_array.DualGPUPatch:
logging.info("- Adding dual GPU patch")
if not self.constants.custom_model and self.computer.dgpu and self.computer.dgpu.pci_path:
self.gfx0_path = self.computer.dgpu.pci_path
logging.info(f"- Found GFX0 Device Path: {self.gfx0_path}")
else:
if not self.constants.custom_model:
logging.info("- Failed to find GFX0 Device path, falling back on known logic")
self.gfx0_path = "PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)"
if self.model in model_array.IntelNvidiaDRM and self.constants.drm_support is True:
logging.info("- Prioritizing DRM support over Intel QuickSync")
self.config["DeviceProperties"]["Add"][self.gfx0_path] = {"agdpmod": "vit9696", "shikigva": 256}
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x2,0x0)"] = {
"name": binascii.unhexlify("23646973706C6179"),
"IOName": "#display",
"class-code": binascii.unhexlify("FFFFFFFF"),
}
elif self.constants.serial_settings != "None":
if self.gfx0_path not in self.config["DeviceProperties"]["Add"] or "agdpmod" not in self.config["DeviceProperties"]["Add"][self.gfx0_path]:
self.config["DeviceProperties"]["Add"][self.gfx0_path] = {"agdpmod": "vit9696"}
if self.model.startswith("iMac14,1"):
# Ensure that agdpmod is applied to iMac14,x with iGPU only
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x2,0x0)"] = {"agdpmod": "vit9696"}
def _imac_mxm_patching(self) -> None:
"""
General iMac MXM Handler
"""
self._backlight_path_detection()
# Check GPU Vendor
if self.constants.metal_build is True:
logging.info("- Adding Metal GPU patches on request")
if self.constants.imac_vendor == "AMD":
self._amd_mxm_patch(self.gfx0_path)
elif self.constants.imac_vendor == "Nvidia":
self._nvidia_mxm_patch(self.gfx0_path)
else:
logging.info("- Failed to find vendor")
elif not self.constants.custom_model and self.model in model_array.LegacyGPU and self.computer.dgpu:
logging.info(f"- Detected dGPU: {utilities.friendly_hex(self.computer.dgpu.vendor_id)}:{utilities.friendly_hex(self.computer.dgpu.device_id)}")
if self.computer.dgpu.arch in [
device_probe.AMD.Archs.Legacy_GCN_7000,
device_probe.AMD.Archs.Legacy_GCN_8000,
device_probe.AMD.Archs.Legacy_GCN_9000,
device_probe.AMD.Archs.Polaris,
device_probe.AMD.Archs.Polaris_Spoof,
device_probe.AMD.Archs.Vega,
device_probe.AMD.Archs.Navi,
]:
self._amd_mxm_patch(self.gfx0_path)
elif self.computer.dgpu.arch == device_probe.NVIDIA.Archs.Kepler:
self._nvidia_mxm_patch(self.gfx0_path)
def _ioaccel_workaround(self) -> None:
"""
Miscellaneous IOAccelerator Handler
When MTL bundles are missing from disk, WindowServer will repeatedly crash
This primarily occurs when installing an RSR update, where root is cleaned but AuxKC is not
"""
gpu_archs = []
if not self.constants.custom_model:
gpu_archs = [gpu.arch for gpu in self.constants.computer.gpus]
else:
if self.model not in smbios_data.smbios_dictionary:
return
gpu_archs = smbios_data.smbios_dictionary[self.model]["Stock GPUs"]
# Check if KDKless and KDK GPUs are present
# We only want KDKless.kext if there are no KDK GPUs
has_kdkless_gpu = False
has_kdk_gpu = False
for arch in gpu_archs:
if arch in [
device_probe.Intel.Archs.Ivy_Bridge,
device_probe.Intel.Archs.Haswell,
device_probe.Intel.Archs.Broadwell,
device_probe.Intel.Archs.Skylake,
device_probe.NVIDIA.Archs.Kepler,
]:
has_kdkless_gpu = True
# Non-Metal KDK
if arch in [
device_probe.NVIDIA.Archs.Tesla,
device_probe.NVIDIA.Archs.Maxwell,
device_probe.NVIDIA.Archs.Pascal,
device_probe.AMD.Archs.TeraScale_1,
device_probe.AMD.Archs.TeraScale_2,
device_probe.Intel.Archs.Iron_Lake,
device_probe.Intel.Archs.Sandy_Bridge,
]:
has_kdk_gpu = True
if arch in [
# Metal KDK (always)
device_probe.AMD.Archs.Legacy_GCN_7000,
device_probe.AMD.Archs.Legacy_GCN_8000,
device_probe.AMD.Archs.Legacy_GCN_9000,
]:
has_kdk_gpu = True
if arch in [
# Metal KDK (pre-AVX2.0)
device_probe.AMD.Archs.Polaris,
device_probe.AMD.Archs.Polaris_Spoof,
device_probe.AMD.Archs.Vega,
device_probe.AMD.Archs.Navi,
]:
if (
self.model == "MacBookPro13,3" or
smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.ivy_bridge.value
):
# MacBookPro13,3 has AVX2.0 however the GPU has an unsupported framebuffer
has_kdk_gpu = True
if has_kdkless_gpu is True and has_kdk_gpu is False:
# KDKlessWorkaround is required for KDKless GPUs
support.BuildSupport(self.model, self.constants, self.config).enable_kext("KDKlessWorkaround.kext", self.constants.kdkless_version, self.constants.kdkless_path)
return
# KDKlessWorkaround supports disabling native AMD stack on Ventura for pre-AVX2.0 CPUs
# Applicable for Polaris, Vega, Navi GPUs
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] > cpu_data.CPUGen.ivy_bridge.value:
return
for arch in gpu_archs:
if arch in [
device_probe.AMD.Archs.Polaris,
device_probe.AMD.Archs.Polaris_Spoof,
device_probe.AMD.Archs.Vega,
device_probe.AMD.Archs.Navi,
]:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("KDKlessWorkaround.kext", self.constants.kdkless_version, self.constants.kdkless_path)
return

View File

@@ -0,0 +1,383 @@
"""
misc.py: Class for handling Misc Patches, invocation from build.py
"""
import shutil
import logging
import binascii
from pathlib import Path
from . import support
from .. import constants
from ..utilities import generate_smbios
from ..detections import device_probe
from ..datasets import (
model_array,
smbios_data,
cpu_data
)
class BuildMiscellaneous:
"""
Build Library for Miscellaneous Hardware and Software Support
xw
Invoke from build.py
"""
def __init__(self, model: str, global_constants: constants.Constants, config: dict) -> None:
self.model: str = model
self.config: dict = config
self.constants: constants.Constants = global_constants
self.computer: device_probe.Computer = self.constants.computer
self._build()
def _build(self) -> None:
"""
Kick off Misc Build Process
"""
self._feature_unlock_handling()
self._restrict_events_handling()
self._firewire_handling()
self._topcase_handling()
self._thunderbolt_handling()
self._webcam_handling()
self._usb_handling()
self._debug_handling()
self._cpu_friend_handling()
self._general_oc_handling()
self._t1_handling()
def _feature_unlock_handling(self) -> None:
"""
FeatureUnlock Handler
"""
if self.constants.fu_status is False:
return
support.BuildSupport(self.model, self.constants, self.config).enable_kext("FeatureUnlock.kext", self.constants.featureunlock_version, self.constants.featureunlock_path)
if self.constants.fu_arguments is not None:
logging.info(f"- Adding additional FeatureUnlock args: {self.constants.fu_arguments}")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += self.constants.fu_arguments
def _restrict_events_handling(self) -> None:
"""
RestrictEvents Handler
"""
block_args = ",".join(self._re_generate_block_arguments())
patch_args = ",".join(self._re_generate_patch_arguments())
if block_args != "":
logging.info(f"- Setting RestrictEvents block arguments: {block_args}")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("RestrictEvents.kext", self.constants.restrictevents_version, self.constants.restrictevents_path)
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["revblock"] = block_args
if block_args != "" and patch_args == "":
# Disable unneeded Userspace patching (cs_validate_page is quite expensive)
patch_args = "none"
if patch_args != "":
logging.info(f"- Setting RestrictEvents patch arguments: {patch_args}")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("RestrictEvents.kext", self.constants.restrictevents_version, self.constants.restrictevents_path)
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["revpatch"] = patch_args
if support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("RestrictEvents.kext")["Enabled"] is False:
# Ensure this is done at the end so all previous RestrictEvents patches are applied
# RestrictEvents and EFICheckDisabler will conflict if both are injected
support.BuildSupport(self.model, self.constants, self.config).enable_kext("EFICheckDisabler.kext", "", self.constants.efi_disabler_path)
def _re_generate_block_arguments(self) -> list:
"""
Generate RestrictEvents block arguments
Returns:
list: RestrictEvents block arguments
"""
re_block_args = []
# Resolve GMUX switching in Big Sur+
if self.model in ["MacBookPro6,1", "MacBookPro6,2", "MacBookPro9,1", "MacBookPro10,1"]:
re_block_args.append("gmux")
# Resolve memory error reporting on MacPro7,1 SMBIOS
if self.model in model_array.MacPro:
logging.info("- Disabling memory error reporting")
re_block_args.append("pcie")
# Resolve mediaanalysisd crashing on 3802 GPUs
# Applicable for systems that are the primary iCloud Photos library host, with large amounts of unprocessed faces
if self.constants.disable_mediaanalysisd is True:
logging.info("- Disabling mediaanalysisd")
re_block_args.append("media")
return re_block_args
def _re_generate_patch_arguments(self) -> list:
"""
Generate RestrictEvents patch arguments
Returns:
list: Patch arguments
"""
re_patch_args = []
# Alternative approach to the kern.hv_vmm_present patch
# Dynamically sets the property to 1 if software update/installer is detected
# Always enabled in installers/recovery environments
if self.constants.allow_oc_everywhere is False and (self.constants.serial_settings == "None" or self.constants.secure_status is False):
re_patch_args.append("sbvmm")
# Resolve CoreGraphics.framework crashing on Ivy Bridge in macOS 13.3+
# Ref: https://github.com/acidanthera/RestrictEvents/pull/12
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] == cpu_data.CPUGen.ivy_bridge.value:
logging.info("- Fixing CoreGraphics support on Ivy Bridge")
re_patch_args.append("f16c")
return re_patch_args
def _cpu_friend_handling(self) -> None:
"""
CPUFriend Handler
"""
if self.constants.allow_oc_everywhere is False and self.model not in ["iMac7,1", "Xserve2,1", "Dortania1,1"] and self.constants.disallow_cpufriend is False and self.constants.serial_settings != "None":
support.BuildSupport(self.model, self.constants, self.config).enable_kext("CPUFriend.kext", self.constants.cpufriend_version, self.constants.cpufriend_path)
# CPUFriendDataProvider handling
pp_map_path = Path(self.constants.platform_plugin_plist_path) / Path(f"{self.model}/Info.plist")
if not pp_map_path.exists():
raise Exception(f"{pp_map_path} does not exist!!! Please file an issue stating file is missing for {self.model}.")
Path(self.constants.pp_kext_folder).mkdir()
Path(self.constants.pp_contents_folder).mkdir()
shutil.copy(pp_map_path, self.constants.pp_contents_folder)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("CPUFriendDataProvider.kext")["Enabled"] = True
def _firewire_handling(self) -> None:
"""
FireWire Handler
"""
if self.constants.firewire_boot is False:
return
if generate_smbios.check_firewire(self.model) is False:
return
# Enable FireWire Boot Support
# Applicable for both native FireWire and Thunderbolt to FireWire adapters
logging.info("- Enabling FireWire Boot Support")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IOFireWireFamily.kext", self.constants.fw_kext, self.constants.fw_family_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IOFireWireSBP2.kext", self.constants.fw_kext, self.constants.fw_sbp2_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IOFireWireSerialBusProtocolTransport.kext", self.constants.fw_kext, self.constants.fw_bus_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("IOFireWireFamily.kext/Contents/PlugIns/AppleFWOHCI.kext")["Enabled"] = True
def _topcase_handling(self) -> None:
"""
USB/SPI Top Case Handler
"""
# macOS 14.4 Beta 1 strips SPI-based top case support for Broadwell through Kaby Lake MacBooks (and MacBookAir6,x)
if self.model.startswith("MacBook") and self.model in smbios_data.smbios_dictionary:
if self.model.startswith("MacBookAir6") or (cpu_data.CPUGen.broadwell <= smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.kaby_lake):
logging.info("- Enabling SPI-based top case support")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleHSSPISupport.kext", self.constants.apple_spi_version, self.constants.apple_spi_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleHSSPIHIDDriver.kext", self.constants.apple_spi_hid_version, self.constants.apple_spi_hid_path)
#On-device probing
if not self.constants.custom_model and self.computer.internal_keyboard_type and self.computer.trackpad_type:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleUSBTopCase.kext", self.constants.topcase_version, self.constants.top_case_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("AppleUSBTopCase.kext/Contents/PlugIns/AppleUSBTCButtons.kext")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("AppleUSBTopCase.kext/Contents/PlugIns/AppleUSBTCKeyboard.kext")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("AppleUSBTopCase.kext/Contents/PlugIns/AppleUSBTCKeyEventDriver.kext")["Enabled"] = True
if self.computer.internal_keyboard_type == "Legacy":
support.BuildSupport(self.model, self.constants, self.config).enable_kext("LegacyKeyboardInjector.kext", self.constants.legacy_keyboard, self.constants.legacy_keyboard_path)
if self.computer.trackpad_type == "Legacy":
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleUSBTrackpad.kext", self.constants.apple_trackpad, self.constants.apple_trackpad_path)
elif self.computer.trackpad_type == "Modern":
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleUSBMultitouch.kext", self.constants.multitouch_version, self.constants.multitouch_path)
#Predefined fallback
else:
# Multi Touch Top Case support for macOS Ventura+
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] < cpu_data.CPUGen.skylake.value:
if self.model.startswith("MacBook"):
# These units got the Force Touch top case, so ignore them
if self.model not in ["MacBookPro11,4", "MacBookPro11,5", "MacBookPro12,1", "MacBook8,1"]:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleUSBTopCase.kext", self.constants.topcase_version, self.constants.top_case_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("AppleUSBTopCase.kext/Contents/PlugIns/AppleUSBTCButtons.kext")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("AppleUSBTopCase.kext/Contents/PlugIns/AppleUSBTCKeyboard.kext")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("AppleUSBTopCase.kext/Contents/PlugIns/AppleUSBTCKeyEventDriver.kext")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleUSBMultitouch.kext", self.constants.multitouch_version, self.constants.multitouch_path)
# Two-finger Top Case support for macOS High Sierra+
if self.model == "MacBook5,2":
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleUSBTrackpad.kext", self.constants.apple_trackpad, self.constants.apple_trackpad_path) # Also requires AppleUSBTopCase.kext
support.BuildSupport(self.model, self.constants, self.config).enable_kext("LegacyKeyboardInjector.kext", self.constants.legacy_keyboard, self.constants.legacy_keyboard_path) # Inject legacy personalities into AppleUSBTCKeyboard and AppleUSBTCKeyEventDriver
def _thunderbolt_handling(self) -> None:
"""
Thunderbolt Handler
"""
if self.constants.disable_tb is True and self.model in ["MacBookPro11,1", "MacBookPro11,2", "MacBookPro11,3", "MacBookPro11,4", "MacBookPro11,5"]:
logging.info("- Disabling 2013-2014 laptop Thunderbolt Controller")
if self.model in ["MacBookPro11,3", "MacBookPro11,5"]:
# 15" dGPU models: IOACPIPlane:/_SB/PCI0@0/PEG1@10001/UPSB@0/DSB0@0/NHI0@0
tb_device_path = "PciRoot(0x0)/Pci(0x1,0x1)/Pci(0x0,0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)"
else:
# 13" and 15" iGPU 2013-2014 models: IOACPIPlane:/_SB/PCI0@0/P0P2@10000/UPSB@0/DSB0@0/NHI0@0
tb_device_path = "PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)"
self.config["DeviceProperties"]["Add"][tb_device_path] = {"class-code": binascii.unhexlify("FFFFFFFF"), "device-id": binascii.unhexlify("FFFF0000")}
def _webcam_handling(self) -> None:
"""
iSight Handler
"""
if self.model in smbios_data.smbios_dictionary:
if "Legacy iSight" in smbios_data.smbios_dictionary[self.model]:
if smbios_data.smbios_dictionary[self.model]["Legacy iSight"] is True:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("LegacyUSBVideoSupport.kext", self.constants.apple_isight_version, self.constants.apple_isight_path)
if not self.constants.custom_model:
if self.constants.computer.pcie_webcam is True:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleCameraInterface.kext", self.constants.apple_camera_version, self.constants.apple_camera_path)
else:
if self.model.startswith("MacBook") and self.model in smbios_data.smbios_dictionary:
if cpu_data.CPUGen.haswell <= smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.kaby_lake:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleCameraInterface.kext", self.constants.apple_camera_version, self.constants.apple_camera_path)
def _usb_handling(self) -> None:
"""
USB Handler
"""
# USB Map
usb_map_path = Path(self.constants.plist_folder_path) / Path("AppleUSBMaps/Info.plist")
if (
usb_map_path.exists()
and (self.constants.allow_oc_everywhere is False or self.constants.allow_native_spoofs is True)
and self.model not in ["Xserve2,1", "Dortania1,1"]
and (
(self.model in model_array.Missing_USB_Map or self.model in model_array.Missing_USB_Map_Ventura)
or self.constants.serial_settings in ["Moderate", "Advanced"])
):
logging.info("- Adding USB-Map.kext")
Path(self.constants.map_kext_folder).mkdir()
Path(self.constants.map_contents_folder).mkdir()
shutil.copy(usb_map_path, self.constants.map_contents_folder)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("USB-Map.kext")["Enabled"] = True
if self.model in model_array.Missing_USB_Map_Ventura and self.constants.serial_settings not in ["Moderate", "Advanced"]:
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("USB-Map.kext")["MinKernel"] = "22.0.0"
# Add UHCI/OHCI drivers
# All Penryn Macs lack an internal USB hub to route USB 1.1 devices to the EHCI controller
# And MacPro4,1, MacPro5,1 and Xserve3,1 are the only post-Penryn Macs that lack an internal USB hub
# - Ref: https://techcommunity.microsoft.com/t5/microsoft-usb-blog/reasons-to-avoid-companion-controllers/ba-p/270710
#
# To be paired for sys_patch_dict.py's 'Legacy USB 1.1' patchset
#
# Note: With macOS 14.1, injection of these kexts causes a panic.
# To avoid this, a MaxKernel is configured with XNU 23.0.0 (macOS 14.0).
# Additionally sys_patch.py stack will now patches the bins onto disk for 14.1+.
# Reason for keeping the dual logic is due to potential conflicts of in-cache vs injection if we start
# patching pre-14.1 hosts.
if (
smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.penryn.value or \
self.model in ["MacPro4,1", "MacPro5,1", "Xserve3,1"]
):
logging.info("- Adding UHCI/OHCI USB support")
shutil.copy(self.constants.apple_usb_11_injector_path, self.constants.kexts_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("USB1.1-Injector.kext/Contents/PlugIns/AppleUSBOHCI.kext")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("USB1.1-Injector.kext/Contents/PlugIns/AppleUSBOHCIPCI.kext")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("USB1.1-Injector.kext/Contents/PlugIns/AppleUSBUHCI.kext")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("USB1.1-Injector.kext/Contents/PlugIns/AppleUSBUHCIPCI.kext")["Enabled"] = True
def _debug_handling(self) -> None:
"""
Debug Handler for OpenCorePkg and Kernel Space
"""
if self.constants.verbose_debug is True:
logging.info("- Enabling Verbose boot")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -v"
if self.constants.kext_debug is True:
logging.info("- Enabling DEBUG Kexts")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -liludbgall liludump=90"
# Disabled due to macOS Monterey crashing shortly after kernel init
# Use DebugEnhancer.kext instead
# self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " msgbuf=1048576"
support.BuildSupport(self.model, self.constants, self.config).enable_kext("DebugEnhancer.kext", self.constants.debugenhancer_version, self.constants.debugenhancer_path)
if self.constants.opencore_debug is True:
logging.info("- Enabling DEBUG OpenCore")
self.config["Misc"]["Debug"]["Target"] = 0x43
self.config["Misc"]["Debug"]["DisplayLevel"] = 0x80000042
def _general_oc_handling(self) -> None:
"""
General OpenCorePkg Handler
"""
logging.info("- Adding OpenCanopy GUI")
shutil.copy(self.constants.gui_path, self.constants.oc_folder)
support.BuildSupport(self.model, self.constants, self.config).get_efi_binary_by_path("OpenCanopy.efi", "UEFI", "Drivers")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_efi_binary_by_path("OpenRuntime.efi", "UEFI", "Drivers")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_efi_binary_by_path("OpenLinuxBoot.efi", "UEFI", "Drivers")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_efi_binary_by_path("ResetNvramEntry.efi", "UEFI", "Drivers")["Enabled"] = True
if self.constants.showpicker is False:
logging.info("- Hiding OpenCore picker")
self.config["Misc"]["Boot"]["ShowPicker"] = False
if self.constants.oc_timeout != 5:
logging.info(f"- Setting custom OpenCore picker timeout to {self.constants.oc_timeout} seconds")
self.config["Misc"]["Boot"]["Timeout"] = self.constants.oc_timeout
if self.constants.vault is True:
logging.info("- Setting Vault configuration")
self.config["Misc"]["Security"]["Vault"] = "Secure"
def _t1_handling(self) -> None:
"""
T1 Security Chip Handler
"""
if self.model not in ["MacBookPro13,2", "MacBookPro13,3", "MacBookPro14,2", "MacBookPro14,3"]:
return
logging.info("- Enabling T1 Security Chip support")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Block"], "Identifier", "com.apple.driver.AppleSSE")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Block"], "Identifier", "com.apple.driver.AppleKeyStore")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Block"], "Identifier", "com.apple.driver.AppleCredentialManager")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).enable_kext("corecrypto_T1.kext", self.constants.t1_corecrypto_version, self.constants.t1_corecrypto_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleSSE.kext", self.constants.t1_sse_version, self.constants.t1_sse_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleKeyStore.kext", self.constants.t1_key_store_version, self.constants.t1_key_store_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleCredentialManager.kext", self.constants.t1_credential_version, self.constants.t1_credential_path)

View File

@@ -0,0 +1,135 @@
"""
wired.py: Class for handling Wired Networking Patches, invocation from build.py
"""
from .. import support
from ... import constants
from ...detections import device_probe
from ...datasets import (
smbios_data,
cpu_data
)
class BuildWiredNetworking:
"""
Build Library for Wired Networking Support
Invoke from build.py
"""
def __init__(self, model: str, global_constants: constants.Constants, config: dict) -> None:
self.model: str = model
self.config: dict = config
self.constants: constants.Constants = global_constants
self.computer: device_probe.Computer = self.constants.computer
self._build()
def _build(self) -> None:
"""
Kick off Wired Build Process
"""
# Check if Ethernet was detected, otherwise fall back to assumptions (mainly for 2011 MacBook Airs and TB Ethernet)
if not self.constants.custom_model and self.constants.computer.ethernet:
self._on_model()
else:
self._prebuilt_assumption()
# Always enable due to chance of hot-plugging
self._usb_ecm_dongles()
self._i210_handling()
def _usb_ecm_dongles(self) -> None:
"""
USB ECM Dongle Handling
"""
# With Sonoma, our WiFi patches require downgrading IOSkywalk
# Unfortunately Apple's DriverKit stack uses IOSkywalk for ECM dongles, so we'll need force load
# the kernel driver to prevent a kernel panic
# - DriverKit: com.apple.DriverKit.AppleUserECM.dext
# - Kext: AppleUSBECM.kext
support.BuildSupport(self.model, self.constants, self.config).enable_kext("ECM-Override.kext", self.constants.ecm_override_version, self.constants.ecm_override_path)
def _i210_handling(self) -> None:
"""
PCIe i210 NIC Handling
"""
# i210 NICs are broke in macOS 14 due to driver kit downgrades
# See ECM logic for why it's always enabled
if not self.model in smbios_data.smbios_dictionary:
return
support.BuildSupport(self.model, self.constants, self.config).enable_kext("CatalinaIntelI210Ethernet.kext", self.constants.i210_version, self.constants.i210_path)
# Ivy Bridge and newer natively support DriverKit, so set MinKernel to 23.0.0
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] >= cpu_data.CPUGen.ivy_bridge.value:
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("CatalinaIntelI210Ethernet.kext")["MinKernel"] = "23.0.0"
def _on_model(self) -> None:
"""
On-Model Hardware Detection Handling
"""
for controller in self.constants.computer.ethernet:
if isinstance(controller, device_probe.BroadcomEthernet) and controller.chipset == device_probe.BroadcomEthernet.Chipsets.AppleBCM5701Ethernet:
if not self.model in smbios_data.smbios_dictionary:
continue
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] < cpu_data.CPUGen.ivy_bridge.value:
# Required due to Big Sur's BCM5701 requiring VT-D support
# Applicable for pre-Ivy Bridge models
support.BuildSupport(self.model, self.constants, self.config).enable_kext("CatalinaBCM5701Ethernet.kext", self.constants.bcm570_version, self.constants.bcm570_path)
elif isinstance(controller, device_probe.IntelEthernet):
if not self.model in smbios_data.smbios_dictionary:
continue
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] < cpu_data.CPUGen.ivy_bridge.value:
# Apple's IOSkywalkFamily in DriverKit requires VT-D support
# Applicable for pre-Ivy Bridge models
if controller.chipset == device_probe.IntelEthernet.Chipsets.AppleIntelI210Ethernet:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("CatalinaIntelI210Ethernet.kext", self.constants.i210_version, self.constants.i210_path)
elif controller.chipset == device_probe.IntelEthernet.Chipsets.AppleIntel8254XEthernet:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleIntel8254XEthernet.kext", self.constants.intel_8254x_version, self.constants.intel_8254x_path)
elif controller.chipset == device_probe.IntelEthernet.Chipsets.Intel82574L:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("Intel82574L.kext", self.constants.intel_82574l_version, self.constants.intel_82574l_path)
elif isinstance(controller, device_probe.NVIDIAEthernet):
support.BuildSupport(self.model, self.constants, self.config).enable_kext("nForceEthernet.kext", self.constants.nforce_version, self.constants.nforce_path)
elif isinstance(controller, device_probe.Marvell) or isinstance(controller, device_probe.SysKonnect):
support.BuildSupport(self.model, self.constants, self.config).enable_kext("MarvelYukonEthernet.kext", self.constants.marvel_version, self.constants.marvel_path)
# Pre-Ivy Bridge Aquantia Ethernet Patch
if isinstance(controller, device_probe.Aquantia) and controller.chipset == device_probe.Aquantia.Chipsets.AppleEthernetAquantiaAqtion:
if not self.model in smbios_data.smbios_dictionary:
continue
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] < cpu_data.CPUGen.ivy_bridge.value:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleEthernetAbuantiaAqtion.kext", self.constants.aquantia_version, self.constants.aquantia_path)
def _prebuilt_assumption(self) -> None:
"""
Fall back to pre-built assumptions
"""
if not self.model in smbios_data.smbios_dictionary:
return
if not "Ethernet Chipset" in smbios_data.smbios_dictionary[self.model]:
return
if smbios_data.smbios_dictionary[self.model]["Ethernet Chipset"] == "Broadcom":
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] < cpu_data.CPUGen.ivy_bridge.value:
# Required due to Big Sur's BCM5701 requiring VT-D support
# Applicable for pre-Ivy Bridge models
support.BuildSupport(self.model, self.constants, self.config).enable_kext("CatalinaBCM5701Ethernet.kext", self.constants.bcm570_version, self.constants.bcm570_path)
elif smbios_data.smbios_dictionary[self.model]["Ethernet Chipset"] == "Nvidia":
support.BuildSupport(self.model, self.constants, self.config).enable_kext("nForceEthernet.kext", self.constants.nforce_version, self.constants.nforce_path)
elif smbios_data.smbios_dictionary[self.model]["Ethernet Chipset"] == "Marvell":
support.BuildSupport(self.model, self.constants, self.config).enable_kext("MarvelYukonEthernet.kext", self.constants.marvel_version, self.constants.marvel_path)
elif smbios_data.smbios_dictionary[self.model]["Ethernet Chipset"] == "Intel 80003ES2LAN":
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleIntel8254XEthernet.kext", self.constants.intel_8254x_version, self.constants.intel_8254x_path)
elif smbios_data.smbios_dictionary[self.model]["Ethernet Chipset"] == "Intel 82574L":
support.BuildSupport(self.model, self.constants, self.config).enable_kext("Intel82574L.kext", self.constants.intel_82574l_version, self.constants.intel_82574l_path)

View File

@@ -0,0 +1,177 @@
"""
wireless.py: Class for handling Wireless Networking Patches, invocation from build.py
"""
import logging
from .. import support
from ... import constants
from ...datasets import smbios_data
from ...utilities import utilities
from ...detections import device_probe
class BuildWirelessNetworking:
"""
Build Library for Wireless Networking Support
Invoke from build.py
"""
def __init__(self, model: str, global_constants: constants.Constants, config: dict) -> None:
self.model: str = model
self.config: dict = config
self.constants: constants.Constants = global_constants
self.computer: device_probe.Computer = self.constants.computer
self._build()
def _build(self) -> None:
"""
Kick off Wireless Build Process
"""
if not self.constants.custom_model and self.constants.computer.wifi:
self._on_model()
else:
self._prebuilt_assumption()
self._wowl_handling()
def _on_model(self) -> None:
"""
On-Model Hardware Detection Handling
"""
logging.info(f"- Found Wireless Device {utilities.friendly_hex(self.computer.wifi.vendor_id)}:{utilities.friendly_hex(self.computer.wifi.device_id)}")
self.config["#Revision"]["Hardware-Wifi"] = f"{utilities.friendly_hex(self.computer.wifi.vendor_id)}:{utilities.friendly_hex(self.computer.wifi.device_id)}"
if isinstance(self.computer.wifi, device_probe.Broadcom):
if self.computer.wifi.chipset in [device_probe.Broadcom.Chipsets.AirportBrcmNIC, device_probe.Broadcom.Chipsets.AirPortBrcm4360]:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IOSkywalkFamily.kext", self.constants.ioskywalk_version, self.constants.ioskywalk_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IO80211FamilyLegacy.kext", self.constants.io80211legacy_version, self.constants.io80211legacy_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211FamilyLegacy.kext/Contents/PlugIns/AirPortBrcmNIC.kext")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Block"], "Identifier", "com.apple.iokit.IOSkywalkFamily")["Enabled"] = True
# This works around OCLP spoofing the Wifi card and therefore unable to actually detect the correct device
if self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirportBrcmNIC and self.constants.validate is False and self.computer.wifi.country_code:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AirportBrcmFixup.kext", self.constants.airportbcrmfixup_version, self.constants.airportbcrmfixup_path)
logging.info(f"- Setting Wireless Card's Country Code: {self.computer.wifi.country_code}")
if self.computer.wifi.pci_path:
arpt_path = self.computer.wifi.pci_path
logging.info(f"- Found ARPT device at {arpt_path}")
self.config["DeviceProperties"]["Add"][arpt_path] = {"brcmfx-country": self.computer.wifi.country_code}
else:
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += f" brcmfx-country={self.computer.wifi.country_code}"
if self.constants.enable_wake_on_wlan is True:
logging.info("- Enabling Wake on WLAN support")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += f" -brcmfxwowl"
elif self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirPortBrcm4360:
self._wifi_fake_id()
elif self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirPortBrcm4331:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AirPortBrcm4331.kext")["Enabled"] = True
elif self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirPortBrcm43224:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AppleAirPortBrcm43224.kext")["Enabled"] = True
elif isinstance(self.computer.wifi, device_probe.Atheros) and self.computer.wifi.chipset == device_probe.Atheros.Chipsets.AirPortAtheros40:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AirPortAtheros40.kext")["Enabled"] = True
def _prebuilt_assumption(self) -> None:
"""
Fall back to pre-built assumptions
"""
if not self.model in smbios_data.smbios_dictionary:
return
if not "Wireless Model" in smbios_data.smbios_dictionary[self.model]:
return
if smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Broadcom.Chipsets.AirPortBrcm4360:
logging.info("- Enabling BCM943224 and BCM94331 Networking Support")
self._wifi_fake_id()
elif smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Broadcom.Chipsets.AirPortBrcm4331:
logging.info("- Enabling BCM94328 Networking Support")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AirPortBrcm4331.kext")["Enabled"] = True
elif smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Broadcom.Chipsets.AirPortBrcm43224:
logging.info("- Enabling BCM94328 Networking Support")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AppleAirPortBrcm43224.kext")["Enabled"] = True
elif smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Atheros.Chipsets.AirPortAtheros40:
logging.info("- Enabling Atheros Networking Support")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AirPortAtheros40.kext")["Enabled"] = True
elif smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Broadcom.Chipsets.AirportBrcmNIC:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AirportBrcmFixup.kext", self.constants.airportbcrmfixup_version, self.constants.airportbcrmfixup_path)
if smbios_data.smbios_dictionary[self.model]["Wireless Model"] in [device_probe.Broadcom.Chipsets.AirportBrcmNIC, device_probe.Broadcom.Chipsets.AirPortBrcm4360]:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IOSkywalkFamily.kext", self.constants.ioskywalk_version, self.constants.ioskywalk_path)
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IO80211FamilyLegacy.kext", self.constants.io80211legacy_version, self.constants.io80211legacy_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211FamilyLegacy.kext/Contents/PlugIns/AirPortBrcmNIC.kext")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Block"], "Identifier", "com.apple.iokit.IOSkywalkFamily")["Enabled"] = True
def _wowl_handling(self) -> None:
"""
Wake on WLAN handling
To avoid reduced networking performance from wake, AirPortBrcmFixup is used to disable wake on WLAN by default.
However some users may want to enable wake on WLAN, so enable if requested.
"""
if self.constants.enable_wake_on_wlan is False:
return
if support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("AirportBrcmFixup.kext")["Enabled"] is False:
return
logging.info("- Enabling Wake on WLAN support")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += f" -brcmfxwowl"
def _wifi_fake_id(self) -> None:
"""
Fake Device ID Handler for BCM943224 and BCM94331 chipsets
BCM94331 and BCM943224 are both partially supported within Big Sur's native AirPortBrcmNIC stack
Simply adding the Device IDs and usage of AirPortBrcmFixup will restore full functionality
"""
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AirportBrcmFixup.kext", self.constants.airportbcrmfixup_version, self.constants.airportbcrmfixup_path)
support.BuildSupport(self.model, self.constants, self.config).get_kext_by_bundle_path("AirportBrcmFixup.kext/Contents/PlugIns/AirPortBrcmNIC_Injector.kext")["Enabled"] = True
if not self.constants.custom_model and self.computer.wifi and self.computer.wifi.pci_path:
arpt_path = self.computer.wifi.pci_path
logging.info(f"- Found ARPT device at {arpt_path}")
else:
if not self.model in smbios_data.smbios_dictionary:
logging.info("No known PCI pathing for this model")
return
if "nForce Chipset" in smbios_data.smbios_dictionary[self.model]:
# Nvidia chipsets all have the same path to ARPT
arpt_path = "PciRoot(0x0)/Pci(0x15,0x0)/Pci(0x0,0x0)"
else:
if self.model in ("iMac7,1", "iMac8,1", "MacPro3,1", "MacBookPro4,1"):
arpt_path = "PciRoot(0x0)/Pci(0x1C,0x4)/Pci(0x0,0x0)"
elif self.model in ("iMac13,1", "iMac13,2"):
arpt_path = "PciRoot(0x0)/Pci(0x1C,0x3)/Pci(0x0,0x0)"
elif self.model in ("MacPro4,1", "MacPro5,1"):
arpt_path = "PciRoot(0x0)/Pci(0x1C,0x5)/Pci(0x0,0x0)"
else:
# Assumes we have a laptop with Intel chipset
# iMac11,x-12,x also apply
arpt_path = "PciRoot(0x0)/Pci(0x1C,0x1)/Pci(0x0,0x0)"
logging.info(f"- Using known ARPT Path: {arpt_path}")
if not self.constants.custom_model and self.computer.wifi and self.constants.validate is False and self.computer.wifi.country_code:
logging.info(f"- Applying fake ID for WiFi, setting Country Code: {self.computer.wifi.country_code}")
self.config["DeviceProperties"]["Add"][arpt_path] = {"brcmfx-country": self.computer.wifi.country_code}

View File

@@ -0,0 +1,87 @@
"""
security.py: Class for handling macOS Security Patches, invocation from build.py
"""
import logging
import binascii
from . import support
from .. import constants
from ..utilities import utilities
from ..detections import device_probe
class BuildSecurity:
"""
Build Library for Security Patch Support
Invoke from build.py
"""
def __init__(self, model: str, global_constants: constants.Constants, config: dict) -> None:
self.model: str = model
self.config: dict = config
self.constants: constants.Constants = global_constants
self.computer: device_probe.Computer = self.constants.computer
self._build()
def _build(self) -> None:
"""
Kick off Security Build Process
"""
if self.constants.sip_status is False or self.constants.custom_sip_value:
# Work-around 12.3 bug where Electron apps no longer launch with SIP lowered
# Unknown whether this is intended behavior or not, revisit with 12.4
logging.info("- Adding ipc_control_port_options=0 to boot-args")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " ipc_control_port_options=0"
# Adds AutoPkgInstaller for Automatic OpenCore-Patcher installation
# Only install if running the GUI (AutoPkg-Assets.pkg requires the GUI)
if self.constants.wxpython_variant is True:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AutoPkgInstaller.kext", self.constants.autopkg_version, self.constants.autopkg_path)
if self.constants.custom_sip_value:
logging.info(f"- Setting SIP value to: {self.constants.custom_sip_value}")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["csr-active-config"] = utilities.string_to_hex(self.constants.custom_sip_value.lstrip("0x"))
elif self.constants.sip_status is False:
logging.info("- Set SIP to allow Root Volume patching")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["csr-active-config"] = binascii.unhexlify("03080000")
# apfs.kext has an undocumented boot-arg that allows FileVault usage on broken APFS seals (-arv_allow_fv)
# This is however hidden behind kern.development, thus we patch _apfs_filevault_allowed to always return true
# Note this function was added in 11.3 (20E232, 20.4), older builds do not support this (ie. 11.2.3)
logging.info("- Allowing FileVault on Root Patched systems")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Force FileVault on Broken Seal")["Enabled"] = True
# Lets us check in sys_patch.py if config supports FileVault
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Settings"] += " -allow_fv"
# Patch KC UUID panics due to RSR installation
# - Ref: https://github.com/dortania/OpenCore-Legacy-Patcher/issues/1019
logging.info("- Enabling KC UUID mismatch patch")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -nokcmismatchpanic"
support.BuildSupport(self.model, self.constants, self.config).enable_kext("RSRHelper.kext", self.constants.rsrhelper_version, self.constants.rsrhelper_path)
if self.constants.disable_cs_lv is True:
# In Ventura, LV patch broke. For now, add AMFI arg
# Before merging into mainline, this needs to be resolved
if self.constants.disable_amfi is True:
logging.info("- Disabling AMFI")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " amfi=0x80"
else:
logging.info("- Disabling Library Validation")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Disable Library Validation Enforcement")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Disable _csr_check() in _vnode_check_signature")["Enabled"] = True
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Settings"] += " -allow_amfi"
# CSLVFixup simply patches out __RESTRICT and __restrict out of the Music.app Binary
# Ref: https://pewpewthespells.com/blog/blocking_code_injection_on_ios_and_os_x.html
support.BuildSupport(self.model, self.constants, self.config).enable_kext("CSLVFixup.kext", self.constants.cslvfixup_version, self.constants.cslvfixup_path)
if self.constants.secure_status is False:
logging.info("- Disabling SecureBootModel")
self.config["Misc"]["Security"]["SecureBootModel"] = "Disabled"
logging.info("- Enabling AMFIPass")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AMFIPass.kext", self.constants.amfipass_version, self.constants.amfipass_path)

View File

@@ -0,0 +1,321 @@
"""
smbios.py: Class for handling SMBIOS Patches, invocation from build.py
"""
import ast
import uuid
import logging
import binascii
import plistlib
import subprocess
from pathlib import Path
from . import support
from .. import constants
from ..utilities import (
utilities,
generate_smbios
)
from ..datasets import (
smbios_data,
cpu_data,
model_array
)
class BuildSMBIOS:
"""
Build Library for SMBIOS Support
Invoke from build.py
"""
def __init__(self, model: str, global_constants: constants.Constants, config: dict) -> None:
self.model: str = model
self.config: dict = config
self.constants: constants.Constants = global_constants
self._build()
def _build(self) -> None:
"""
Kick off SMBIOS Build Process
"""
if self.constants.allow_oc_everywhere is False or self.constants.allow_native_spoofs is True:
if self.constants.serial_settings == "None":
# Credit to Parrotgeek1 for boot.efi and hv_vmm_present patch sets
logging.info("- Enabling Board ID exemption patch")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Booter"]["Patch"], "Comment", "Skip Board ID check")["Enabled"] = True
else:
logging.info("- Enabling SMC exemption patch")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Identifier", "com.apple.driver.AppleSMC")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).enable_kext("SMC-Spoof.kext", self.constants.smcspoof_version, self.constants.smcspoof_path)
if self.constants.serial_settings in ["Moderate", "Advanced"]:
logging.info("- Enabling USB Rename Patches")
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "XHC1 to SHC1")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "EHC1 to EH01")["Enabled"] = True
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "EHC2 to EH02")["Enabled"] = True
if self.model == self.constants.override_smbios:
logging.info("- Adding -no_compat_check")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -no_compat_check"
def set_smbios(self) -> None:
"""
SMBIOS Handler
"""
spoofed_model = self.model
if self.constants.override_smbios == "Default":
if self.constants.serial_settings != "None":
logging.info("- Setting macOS Monterey Supported SMBIOS")
if self.constants.allow_native_spoofs is True:
spoofed_model = self.model
else:
spoofed_model = generate_smbios.set_smbios_model_spoof(self.model)
else:
spoofed_model = self.constants.override_smbios
logging.info(f"- Using Model ID: {spoofed_model}")
spoofed_board = ""
if spoofed_model in smbios_data.smbios_dictionary:
if "Board ID" in smbios_data.smbios_dictionary[spoofed_model]:
spoofed_board = smbios_data.smbios_dictionary[spoofed_model]["Board ID"]
logging.info(f"- Using Board ID: {spoofed_board}")
self.spoofed_model = spoofed_model
self.spoofed_board = spoofed_board
if self.constants.allow_oc_everywhere is False or self.constants.allow_native_spoofs is True:
self.config["#Revision"]["Spoofed-Model"] = f"{self.spoofed_model} - {self.constants.serial_settings}"
if self.constants.serial_settings == "Moderate":
logging.info("- Using Moderate SMBIOS patching")
self._moderate_serial_patch()
elif self.constants.serial_settings == "Advanced":
logging.info("- Using Advanced SMBIOS patching")
self._advanced_serial_patch()
elif self.constants.serial_settings == "Minimal":
logging.info("- Using Minimal SMBIOS patching")
self.spoofed_model = self.model
self._minimal_serial_patch()
else:
# Update DataHub to resolve Lilu Race Condition
# macOS Monterey will sometimes not present the boardIdentifier in the DeviceTree on UEFI 1.2 or older Mac,
# Thus resulting in an infinite loop as Lilu tries to request the Board ID
# To resolve this, set PlatformInfo -> DataHub -> BoardProduct and enable UpdateDataHub
# Note 1: Only apply if system is UEFI 1.2, this is generally Ivy Bridge and older
# Note 2: Flipping 'UEFI -> ProtocolOverrides -> DataHub' will break hibernation
if (smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.ivy_bridge.value and self.model):
logging.info("- Detected UEFI 1.2 or older Mac, updating BoardProduct")
self.config["PlatformInfo"]["DataHub"]["BoardProduct"] = self.spoofed_board
self.config["PlatformInfo"]["UpdateDataHub"] = True
if self.constants.custom_serial_number != "" and self.constants.custom_board_serial_number != "":
logging.info("- Adding custom serial numbers")
self.config["PlatformInfo"]["Automatic"] = True
self.config["PlatformInfo"]["UpdateDataHub"] = True
self.config["PlatformInfo"]["UpdateNVRAM"] = True
self.config["PlatformInfo"]["UpdateSMBIOS"] = True
self.config["UEFI"]["ProtocolOverrides"]["DataHub"] = True
self.config["PlatformInfo"]["Generic"]["SystemSerialNumber"] = self.constants.custom_serial_number
self.config["PlatformInfo"]["Generic"]["MLB"] = self.constants.custom_board_serial_number
self.config["PlatformInfo"]["Generic"]["MaxBIOSVersion"] = False
self.config["PlatformInfo"]["Generic"]["SystemProductName"] = self.spoofed_model
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Spoofed-SN"] = self.constants.custom_serial_number
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Spoofed-MLB"] = self.constants.custom_board_serial_number
# USB Map and CPUFriend Patching
if (
self.constants.allow_oc_everywhere is False
and self.model not in ["Xserve2,1", "Dortania1,1"]
and ((self.model in model_array.Missing_USB_Map or self.model in model_array.Missing_USB_Map_Ventura) or self.constants.serial_settings in ["Moderate", "Advanced"])
):
new_map_ls = Path(self.constants.map_contents_folder) / Path("Info.plist")
map_config = plistlib.load(Path(new_map_ls).open("rb"))
# Strip unused USB maps
for entry in list(map_config["IOKitPersonalities_x86_64"]):
if not entry.startswith(self.model):
map_config["IOKitPersonalities_x86_64"].pop(entry)
else:
try:
map_config["IOKitPersonalities_x86_64"][entry]["model"] = self.spoofed_model
if self.constants.serial_settings in ["Minimal", "None"]:
if map_config["IOKitPersonalities_x86_64"][entry]["IONameMatch"] == "EH01":
map_config["IOKitPersonalities_x86_64"][entry]["IONameMatch"] = "EHC1"
if map_config["IOKitPersonalities_x86_64"][entry]["IONameMatch"] == "EH02":
map_config["IOKitPersonalities_x86_64"][entry]["IONameMatch"] = "EHC2"
if map_config["IOKitPersonalities_x86_64"][entry]["IONameMatch"] == "SHC1":
map_config["IOKitPersonalities_x86_64"][entry]["IONameMatch"] = "XHC1"
except KeyError:
continue
plistlib.dump(map_config, Path(new_map_ls).open("wb"), sort_keys=True)
if self.constants.allow_oc_everywhere is False and self.model not in ["iMac7,1", "Xserve2,1", "Dortania1,1"] and self.constants.disallow_cpufriend is False and self.constants.serial_settings != "None":
# Adjust CPU Friend Data to correct SMBIOS
new_cpu_ls = Path(self.constants.pp_contents_folder) / Path("Info.plist")
cpu_config = plistlib.load(Path(new_cpu_ls).open("rb"))
string_stuff = str(cpu_config["IOKitPersonalities"]["CPUFriendDataProvider"]["cf-frequency-data"])
string_stuff = string_stuff.replace(self.model, self.spoofed_model)
string_stuff = ast.literal_eval(string_stuff)
cpu_config["IOKitPersonalities"]["CPUFriendDataProvider"]["cf-frequency-data"] = string_stuff
plistlib.dump(cpu_config, Path(new_cpu_ls).open("wb"), sort_keys=True)
if self.constants.allow_oc_everywhere is False and self.constants.serial_settings != "None":
if self.model == "MacBookPro9,1":
new_amc_ls = Path(self.constants.amc_contents_folder) / Path("Info.plist")
amc_config = plistlib.load(Path(new_amc_ls).open("rb"))
amc_config["IOKitPersonalities"]["AppleMuxControl"]["ConfigMap"][self.spoofed_board] = amc_config["IOKitPersonalities"]["AppleMuxControl"]["ConfigMap"].pop(self.model)
for entry in list(amc_config["IOKitPersonalities"]["AppleMuxControl"]["ConfigMap"]):
if not entry.startswith(self.spoofed_board):
amc_config["IOKitPersonalities"]["AppleMuxControl"]["ConfigMap"].pop(entry)
plistlib.dump(amc_config, Path(new_amc_ls).open("wb"), sort_keys=True)
if self.model not in model_array.NoAGPMSupport:
new_agpm_ls = Path(self.constants.agpm_contents_folder) / Path("Info.plist")
agpm_config = plistlib.load(Path(new_agpm_ls).open("rb"))
agpm_config["IOKitPersonalities"]["AGPM"]["Machines"][self.spoofed_board] = agpm_config["IOKitPersonalities"]["AGPM"]["Machines"].pop(self.model)
if self.model == "MacBookPro6,2":
# Force G State to not exceed moderate state
# Ref: https://github.com/fabioiop/MBP-2010-GPU-Panic-fix
logging.info("- Patching G State for MacBookPro6,2")
for gpu in ["Vendor10deDevice0a34", "Vendor10deDevice0a29"]:
agpm_config["IOKitPersonalities"]["AGPM"]["Machines"][self.spoofed_board][gpu]["BoostPState"] = [2, 2, 2, 2]
agpm_config["IOKitPersonalities"]["AGPM"]["Machines"][self.spoofed_board][gpu]["BoostTime"] = [2, 2, 2, 2]
for entry in list(agpm_config["IOKitPersonalities"]["AGPM"]["Machines"]):
if not entry.startswith(self.spoofed_board):
agpm_config["IOKitPersonalities"]["AGPM"]["Machines"].pop(entry)
plistlib.dump(agpm_config, Path(new_agpm_ls).open("wb"), sort_keys=True)
if self.model in model_array.AGDPSupport:
new_agdp_ls = Path(self.constants.agdp_contents_folder) / Path("Info.plist")
agdp_config = plistlib.load(Path(new_agdp_ls).open("rb"))
agdp_config["IOKitPersonalities"]["AppleGraphicsDevicePolicy"]["ConfigMap"][self.spoofed_board] = agdp_config["IOKitPersonalities"]["AppleGraphicsDevicePolicy"]["ConfigMap"].pop(
self.model
)
for entry in list(agdp_config["IOKitPersonalities"]["AppleGraphicsDevicePolicy"]["ConfigMap"]):
if not entry.startswith(self.spoofed_board):
agdp_config["IOKitPersonalities"]["AppleGraphicsDevicePolicy"]["ConfigMap"].pop(entry)
plistlib.dump(agdp_config, Path(new_agdp_ls).open("wb"), sort_keys=True)
def _minimal_serial_patch(self) -> None:
"""
Minimal SMBIOS Spoofing Handler
This function will only spoof the following:
- Board ID
- Firmware Features
- BIOS Version
- Serial Numbers (if override requested)
"""
# Generate Firmware Features
fw_feature = generate_smbios.generate_fw_features(self.model, self.constants.custom_model)
# fw_feature = self.patch_firmware_feature()
fw_feature = hex(fw_feature).lstrip("0x").rstrip("L").strip()
logging.info(f"- Setting Firmware Feature: {fw_feature}")
fw_feature = utilities.string_to_hex(fw_feature)
# FirmwareFeatures
self.config["PlatformInfo"]["PlatformNVRAM"]["FirmwareFeatures"] = fw_feature
self.config["PlatformInfo"]["PlatformNVRAM"]["FirmwareFeaturesMask"] = fw_feature
self.config["PlatformInfo"]["SMBIOS"]["FirmwareFeatures"] = fw_feature
self.config["PlatformInfo"]["SMBIOS"]["FirmwareFeaturesMask"] = fw_feature
# Board ID
self.config["PlatformInfo"]["DataHub"]["BoardProduct"] = self.spoofed_board
self.config["PlatformInfo"]["PlatformNVRAM"]["BID"] = self.spoofed_board
self.config["PlatformInfo"]["SMBIOS"]["BoardProduct"] = self.spoofed_board
# Model (ensures tables are not mismatched, even if we're not spoofing)
self.config["PlatformInfo"]["DataHub"]["SystemProductName"] = self.model
self.config["PlatformInfo"]["SMBIOS"]["SystemProductName"] = self.model
self.config["PlatformInfo"]["SMBIOS"]["BoardVersion"] = self.model
# Avoid incorrect Firmware Updates
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["run-efi-updater"] = "No"
self.config["PlatformInfo"]["SMBIOS"]["BIOSVersion"] = "9999.999.999.999.999"
# Update tables
self.config["PlatformInfo"]["UpdateNVRAM"] = True
self.config["PlatformInfo"]["UpdateSMBIOS"] = True
self.config["PlatformInfo"]["UpdateDataHub"] = True
if self.constants.custom_serial_number != "" and self.constants.custom_board_serial_number != "":
logging.info("- Adding custom serial numbers")
sn = self.constants.custom_serial_number
mlb = self.constants.custom_board_serial_number
# Serial Number
self.config["PlatformInfo"]["SMBIOS"]["ChassisSerialNumber"] = sn
self.config["PlatformInfo"]["SMBIOS"]["SystemSerialNumber"] = sn
self.config["PlatformInfo"]["DataHub"]["SystemSerialNumber"] = sn
self.config["PlatformInfo"]["PlatformNVRAM"]["SystemSerialNumber"] = sn
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Spoofed-SN"] = sn
# Board Serial Number
self.config["PlatformInfo"]["SMBIOS"]["BoardSerialNumber"] = mlb
self.config["PlatformInfo"]["PlatformNVRAM"]["BoardSerialNumber"] = mlb
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Spoofed-MLB"] = mlb
def _moderate_serial_patch(self) -> None:
"""
Moderate SMBIOS Spoofing Handler
Implements a full SMBIOS replacement, however retains original serial numbers (unless override requested)
"""
if self.constants.custom_serial_number != "" and self.constants.custom_board_serial_number != "":
logging.info("- Adding custom serial numbers")
self.config["PlatformInfo"]["Generic"]["SystemSerialNumber"] = self.constants.custom_serial_number
self.config["PlatformInfo"]["Generic"]["MLB"] = self.constants.custom_board_serial_number
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Spoofed-SN"] = self.constants.custom_serial_number
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Spoofed-MLB"] = self.constants.custom_board_serial_number
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["run-efi-updater"] = "No"
self.config["PlatformInfo"]["Automatic"] = True
self.config["PlatformInfo"]["UpdateDataHub"] = True
self.config["PlatformInfo"]["UpdateNVRAM"] = True
self.config["PlatformInfo"]["UpdateSMBIOS"] = True
self.config["UEFI"]["ProtocolOverrides"]["DataHub"] = True
self.config["PlatformInfo"]["Generic"]["SystemProductName"] = self.spoofed_model
def _advanced_serial_patch(self) -> None:
"""
Advanced SMBIOS Spoofing Handler
Implements a full SMBIOS replacement, including serial numbers
"""
if self.constants.custom_serial_number == "" or self.constants.custom_board_serial_number == "":
macserial_output = subprocess.run([self.constants.macserial_path, "--generate", "--model", self.spoofed_model, "--num", "1"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
macserial_output = macserial_output.stdout.decode().strip().split(" | ")
sn = macserial_output[0]
mlb = macserial_output[1]
else:
sn = self.constants.custom_serial_number
mlb = self.constants.custom_board_serial_number
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["run-efi-updater"] = "No"
self.config["PlatformInfo"]["Automatic"] = True
self.config["PlatformInfo"]["UpdateDataHub"] = True
self.config["PlatformInfo"]["UpdateNVRAM"] = True
self.config["PlatformInfo"]["UpdateSMBIOS"] = True
self.config["UEFI"]["ProtocolOverrides"]["DataHub"] = True
self.config["PlatformInfo"]["Generic"]["ROM"] = binascii.unhexlify("0016CB445566")
self.config["PlatformInfo"]["Generic"]["SystemProductName"] = self.spoofed_model
self.config["PlatformInfo"]["Generic"]["SystemSerialNumber"] = sn
self.config["PlatformInfo"]["Generic"]["MLB"] = mlb
self.config["PlatformInfo"]["Generic"]["SystemUUID"] = str(uuid.uuid4()).upper()
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Spoofed-SN"] = sn
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Spoofed-MLB"] = mlb

View File

@@ -0,0 +1,196 @@
"""
storage.py: Class for handling Storage Controller Patches, invocation from build.py
"""
import logging
from . import support
from .. import constants
from ..utilities import utilities
from ..detections import device_probe
from ..datasets import (
model_array,
smbios_data,
cpu_data
)
class BuildStorage:
"""
Build Library for System Storage Support
Invoke from build.py
"""
def __init__(self, model: str, global_constants: constants.Constants, config: dict) -> None:
self.model: str = model
self.config: dict = config
self.constants: constants.Constants = global_constants
self.computer: device_probe.Computer = self.constants.computer
self._build()
def _build(self) -> None:
"""
Kick off Storage Build Process
"""
self._ahci_handling()
self._pata_handling()
self._misc_handling()
self._pcie_handling()
self._trim_handling()
def _ahci_handling(self) -> None:
"""
AHCI (SATA) Handler
"""
# MacBookAir6,x ship with an AHCI over PCIe SSD model 'APPLE SSD TS0128F' and 'APPLE SSD TS0256F'
# This controller is not supported properly in macOS Ventura, instead populating itself as 'Media' with no partitions
# To work-around this, use Monterey's AppleAHCI driver to force support
if not self.constants.custom_model:
sata_devices = [i for i in self.computer.storage if isinstance(i, device_probe.SATAController)]
for controller in sata_devices:
# https://linux-hardware.org/?id=pci:1179-010b-1b4b-9183
if controller.vendor_id == 0x1179 and controller.device_id == 0x010b:
logging.info("- Enabling AHCI SSD patch")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("MonteAHCIPort.kext", self.constants.monterey_ahci_version, self.constants.monterey_ahci_path)
break
elif self.model in ["MacBookAir6,1", "MacBookAir6,2"]:
logging.info("- Enabling AHCI SSD patch")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("MonteAHCIPort.kext", self.constants.monterey_ahci_version, self.constants.monterey_ahci_path)
# ThirdPartyDrives Check
if self.constants.allow_3rd_party_drives is True:
for drive in ["SATA 2.5", "SATA 3.5", "mSATA"]:
if not self.model in smbios_data.smbios_dictionary:
break
if not "Stock Storage" in smbios_data.smbios_dictionary[self.model]:
break
if drive in smbios_data.smbios_dictionary[self.model]["Stock Storage"]:
if not self.constants.custom_model:
if self.computer.third_party_sata_ssd is True:
logging.info("- Adding SATA Hibernation Patch")
self.config["Kernel"]["Quirks"]["ThirdPartyDrives"] = True
break
else:
logging.info("- Adding SATA Hibernation Patch")
self.config["Kernel"]["Quirks"]["ThirdPartyDrives"] = True
break
def _pata_handling(self) -> None:
"""
ATA (PATA) Handler
"""
if not self.model in smbios_data.smbios_dictionary:
return
if not "Stock Storage" in smbios_data.smbios_dictionary[self.model]:
return
if not "PATA" in smbios_data.smbios_dictionary[self.model]["Stock Storage"]:
return
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleIntelPIIXATA.kext", self.constants.piixata_version, self.constants.piixata_path)
def _pcie_handling(self) -> None:
"""
PCIe/NVMe Handler
"""
if not self.constants.custom_model and (self.constants.allow_oc_everywhere is True or self.model in model_array.MacPro):
# Use Innie's same logic:
# https://github.com/cdf/Innie/blob/v1.3.0/Innie/Innie.cpp#L90-L97
for i, controller in enumerate(self.computer.storage):
logging.info(f"- Fixing PCIe Storage Controller ({i + 1}) reporting")
if controller.pci_path:
self.config["DeviceProperties"]["Add"][controller.pci_path] = {"built-in": 1}
else:
logging.info(f"- Failed to find Device path for PCIe Storage Controller {i}, falling back to Innie")
support.BuildSupport(self.model, self.constants, self.config).enable_kext("Innie.kext", self.constants.innie_version, self.constants.innie_path)
if not self.constants.custom_model:
nvme_devices = [i for i in self.computer.storage if isinstance(i, device_probe.NVMeController)]
if self.constants.allow_nvme_fixing is True:
for i, controller in enumerate(nvme_devices):
if controller.vendor_id == 0x106b:
continue
logging.info(f"- Found 3rd Party NVMe SSD ({i + 1}): {utilities.friendly_hex(controller.vendor_id)}:{utilities.friendly_hex(controller.device_id)}")
self.config["#Revision"][f"Hardware-NVMe-{i}"] = f"{utilities.friendly_hex(controller.vendor_id)}:{utilities.friendly_hex(controller.device_id)}"
# Disable Bit 0 (L0s), enable Bit 1 (L1)
nvme_aspm = (controller.aspm & (~0b11)) | 0b10
if controller.pci_path:
logging.info(f"- Found NVMe ({i}) at {controller.pci_path}")
self.config["DeviceProperties"]["Add"].setdefault(controller.pci_path, {})["pci-aspm-default"] = nvme_aspm
self.config["DeviceProperties"]["Add"][controller.pci_path.rpartition("/")[0]] = {"pci-aspm-default": nvme_aspm}
else:
if "-nvmefaspm" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"]:
logging.info("- Falling back to -nvmefaspm")
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -nvmefaspm"
if (controller.vendor_id != 0x144D and controller.device_id != 0xA804):
# Avoid injecting NVMeFix when a native Apple NVMe drive is present
# https://github.com/acidanthera/NVMeFix/blob/1.0.9/NVMeFix/NVMeFix.cpp#L220-L225
support.BuildSupport(self.model, self.constants, self.config).enable_kext("NVMeFix.kext", self.constants.nvmefix_version, self.constants.nvmefix_path)
if any((controller.vendor_id == 0x106b and controller.device_id in [0x2001, 0x2003]) for controller in nvme_devices):
# Restore S1X/S3X NVMe support removed in 14.0 Beta 2
# - APPLE SSD AP0128H, AP0256H, etc
# - APPLE SSD AP0128J, AP0256J, etc
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IOS3XeFamily.kext", self.constants.s3x_nvme_version, self.constants.s3x_nvme_path)
# Restore S1X/S3X NVMe support removed in 14.0 Beta 2
# Apple's usage of the S1X and S3X is quite sporadic and inconsistent, so we'll try a catch all for units with NVMe drives
if self.constants.custom_model and self.model in smbios_data.smbios_dictionary:
if "CPU Generation" in smbios_data.smbios_dictionary[self.model]:
if cpu_data.CPUGen.broadwell <= smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.kaby_lake:
support.BuildSupport(self.model, self.constants, self.config).enable_kext("IOS3XeFamily.kext", self.constants.s3x_nvme_version, self.constants.s3x_nvme_path)
# Apple RAID Card check
if not self.constants.custom_model:
if self.computer.storage:
for storage_controller in self.computer.storage:
if storage_controller.vendor_id == 0x106b and storage_controller.device_id == 0x008A:
# AppleRAIDCard.kext only supports pci106b,8a
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleRAIDCard.kext", self.constants.apple_raid_version, self.constants.apple_raid_path)
break
elif self.model.startswith("Xserve"):
# For Xserves, assume RAID is present
# Namely due to Xserve2,1 being limited to 10.7, thus no hardware detection
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AppleRAIDCard.kext", self.constants.apple_raid_version, self.constants.apple_raid_path)
def _misc_handling(self) -> None:
"""
SDXC Handler
"""
if not self.model in smbios_data.smbios_dictionary:
return
if not "CPU Generation" in smbios_data.smbios_dictionary[self.model]:
return
# With macOS Monterey, Apple's SDXC driver requires the system to support VT-D
# However pre-Ivy Bridge don't support this feature
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.CPUGen.sandy_bridge.value:
if (self.constants.computer.sdxc_controller and not self.constants.custom_model) or (self.model.startswith("MacBookPro8") or self.model.startswith("Macmini5")):
support.BuildSupport(self.model, self.constants, self.config).enable_kext("BigSurSDXC.kext", self.constants.bigsursdxc_version, self.constants.bigsursdxc_path)
def _trim_handling(self) -> None:
"""
TRIM Handler
"""
if self.constants.apfs_trim_timeout is False:
logging.info(f"- Disabling APFS TRIM timeout")
self.config["Kernel"]["Quirks"]["SetApfsTrimTimeout"] = 0

View File

@@ -0,0 +1,252 @@
"""
support.py: Utility class for build functions
"""
import shutil
import typing
import logging
import plistlib
import zipfile
import subprocess
from pathlib import Path
from .. import constants
class BuildSupport:
"""
Support Library for build.py and related libraries
"""
def __init__(self, model: str, global_constants: constants.Constants, config: dict) -> None:
self.model: str = model
self.config: dict = config
self.constants: constants.Constants = global_constants
@staticmethod
def get_item_by_kv(iterable: dict, key: str, value: typing.Any) -> dict:
"""
Gets an item from a list of dicts by key and value
Parameters:
iterable (list): List of dicts
key (str): Key to search for
value (any): Value to search for
"""
item = None
for i in iterable:
if i[key] == value:
item = i
break
return item
def get_kext_by_bundle_path(self, bundle_path: str) -> dict:
"""
Gets a kext by bundle path
Parameters:
bundle_path (str): Relative bundle path of the kext in the EFI folder
"""
kext: dict = self.get_item_by_kv(self.config["Kernel"]["Add"], "BundlePath", bundle_path)
if not kext:
logging.info(f"- Could not find kext {bundle_path}!")
raise IndexError
return kext
def get_efi_binary_by_path(self, bundle_name: str, entry_type: str, efi_type: str) -> dict:
"""
Gets an EFI binary by name
Parameters:
bundle_name (str): Name of the EFI binary
entry_type (str): Type of EFI binary (UEFI, Misc)
efi_type (str): Type of EFI binary (Drivers, Tools)
"""
efi_binary: dict = self.get_item_by_kv(self.config[entry_type][efi_type], "Path", bundle_name)
if not efi_binary:
logging.info(f"- Could not find {efi_type}: {bundle_name}!")
raise IndexError
return efi_binary
def enable_kext(self, kext_name: str, kext_version: str, kext_path: Path, check: bool = False) -> None:
"""
Enables a kext in the config.plist
Parameters:
kext_name (str): Name of the kext
kext_version (str): Version of the kext
kext_path (Path): Path to the kext
"""
kext: dict = self.get_kext_by_bundle_path(kext_name)
if callable(check) and not check():
# Check failed
return
if kext["Enabled"] is True:
return
logging.info(f"- Adding {kext_name} {kext_version}")
shutil.copy(kext_path, self.constants.kexts_path)
kext["Enabled"] = True
def sign_files(self) -> None:
"""
Signs files for on OpenCorePkg's Vault system
"""
if self.constants.vault is False:
return
logging.info("- Vaulting EFI\n=========================================")
popen = subprocess.Popen([str(self.constants.vault_path), f"{self.constants.oc_folder}/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
for stdout_line in iter(popen.stdout.readline, ""):
logging.info(stdout_line.strip())
logging.info("=========================================")
def validate_pathing(self) -> None:
"""
Validate whether all files are accounted for on-disk
This ensures that OpenCore won't hit a critical error and fail to boot
"""
logging.info("- Validating generated config")
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/config.plist")):
logging.info("- OpenCore config file missing!!!")
raise Exception("OpenCore config file missing")
config_plist = plistlib.load(Path(self.constants.opencore_release_folder / Path("EFI/OC/config.plist")).open("rb"))
for acpi in config_plist["ACPI"]["Add"]:
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/ACPI") / Path(acpi["Path"])).exists():
logging.info(f"- Missing ACPI Table: {acpi['Path']}")
raise Exception(f"Missing ACPI Table: {acpi['Path']}")
for kext in config_plist["Kernel"]["Add"]:
kext_path = Path(self.constants.opencore_release_folder / Path("EFI/OC/Kexts") / Path(kext["BundlePath"]))
kext_binary_path = Path(kext_path / Path(kext["ExecutablePath"]))
kext_plist_path = Path(kext_path / Path(kext["PlistPath"]))
if not kext_path.exists():
logging.info(f"- Missing kext: {kext_path}")
raise Exception(f"Missing {kext_path}")
if not kext_binary_path.exists():
logging.info(f"- Missing {kext['BundlePath']}'s binary: {kext_binary_path}")
raise Exception(f"Missing {kext_binary_path}")
if not kext_plist_path.exists():
logging.info(f"- Missing {kext['BundlePath']}'s plist: {kext_plist_path}")
raise Exception(f"Missing {kext_plist_path}")
for tool in config_plist["Misc"]["Tools"]:
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/Tools") / Path(tool["Path"])).exists():
logging.info(f"- Missing tool: {tool['Path']}")
raise Exception(f"Missing tool: {tool['Path']}")
for driver in config_plist["UEFI"]["Drivers"]:
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/Drivers") / Path(driver["Path"])).exists():
logging.info(f"- Missing driver: {driver['Path']}")
raise Exception(f"Missing driver: {driver['Path']}")
# Validating local files
# Report if they have no associated config.plist entry (i.e. they're not being used)
for tool_files in Path(self.constants.opencore_release_folder / Path("EFI/OC/Tools")).glob("*"):
if tool_files.name not in [x["Path"] for x in config_plist["Misc"]["Tools"]]:
logging.info(f"- Missing tool from config: {tool_files.name}")
raise Exception(f"Missing tool from config: {tool_files.name}")
for driver_file in Path(self.constants.opencore_release_folder / Path("EFI/OC/Drivers")).glob("*"):
if driver_file.name not in [x["Path"] for x in config_plist["UEFI"]["Drivers"]]:
logging.info(f"- Found extra driver: {driver_file.name}")
raise Exception(f"Found extra driver: {driver_file.name}")
self._validate_malformed_kexts(self.constants.opencore_release_folder / Path("EFI/OC/Kexts"))
def _validate_malformed_kexts(self, directory: str | Path) -> None:
"""
Validate Info.plist and executable pathing for kexts
"""
for kext_folder in Path(directory).glob("*.kext"):
if not Path(kext_folder / Path("Contents/Info.plist")).exists():
continue
kext_data = plistlib.load(Path(kext_folder / Path("Contents/Info.plist")).open("rb"))
if "CFBundleExecutable" in kext_data:
expected_executable = Path(kext_folder / Path("Contents/MacOS") / Path(kext_data["CFBundleExecutable"]))
if not expected_executable.exists():
logging.info(f"- Missing executable for {kext_folder.name}: Contents/MacOS/{expected_executable.name}")
raise Exception(f" - Missing executable for {kext_folder.name}: Contents/MacOS/{expected_executable.name}")
if Path(kext_folder / Path("Contents/PlugIns")).exists():
self._validate_malformed_kexts(kext_folder / Path("Contents/PlugIns"))
def cleanup(self) -> None:
"""
Clean up files and entries
"""
logging.info("- Cleaning up files")
# Remove unused entries
entries_to_clean = {
"ACPI": ["Add", "Delete", "Patch"],
"Booter": ["Patch"],
"Kernel": ["Add", "Block", "Force", "Patch"],
"Misc": ["Tools"],
"UEFI": ["Drivers"],
}
for entry in entries_to_clean:
for sub_entry in entries_to_clean[entry]:
for item in list(self.config[entry][sub_entry]):
if item["Enabled"] is False:
self.config[entry][sub_entry].remove(item)
for kext in self.constants.kexts_path.rglob("*.zip"):
with zipfile.ZipFile(kext) as zip_file:
zip_file.extractall(self.constants.kexts_path)
kext.unlink()
for item in self.constants.oc_folder.rglob("*.zip"):
with zipfile.ZipFile(item) as zip_file:
zip_file.extractall(self.constants.oc_folder)
item.unlink()
if not self.constants.recovery_status:
# Crashes in RecoveryOS for unknown reason
for i in self.constants.build_path.rglob("__MACOSX"):
shutil.rmtree(i)
# Remove unused plugins inside of kexts
# Following plugins are sometimes unused as there's different variants machines need
known_unused_plugins = [
"AirPortBrcm4331.kext",
"AirPortAtheros40.kext",
"AppleAirPortBrcm43224.kext",
"AirPortBrcm4360_Injector.kext",
"AirPortBrcmNIC_Injector.kext"
]
for kext in Path(self.constants.opencore_release_folder / Path("EFI/OC/Kexts")).glob("*.kext"):
for plugin in Path(kext / "Contents/PlugIns/").glob("*.kext"):
should_remove = True
for enabled_kexts in self.config["Kernel"]["Add"]:
if enabled_kexts["BundlePath"].endswith(plugin.name):
should_remove = False
break
if should_remove:
if plugin.name not in known_unused_plugins:
raise Exception(f" - Unknown plugin found: {plugin.name}")
shutil.rmtree(plugin)
Path(self.constants.opencore_zip_copied).unlink()