diff --git a/.gitignore b/.gitignore index 05a0832a9..231976573 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ __pycache__/ /payloads/seed.plist /payloads/AutoPkg-Assets.pkg /payloads/AutoPkg-Assets.pkg.zip +/payloads/Universal-Binaries diff --git a/CHANGELOG.md b/CHANGELOG.md index 786feba32..b6eb2f7e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ - Add Macmini8,1 FeatureUnlock support - Drops CPU check, supports all machines - Refactor Root Patching System + - Adds preflight checks validating patch set data and presence + - Adds dynamic Sandy Bridge Board ID patching + - Allows for unrestricted SMBIOS usage with `AppleIntelSNBGraphicsFB` + - Adds OpenCL downgrade for TeraScale 2 + - Resolves VNC support (credit IronApple#2711) - Add `OpenCore-Legacy-Patcher.plist` for applied patch info - Located under `/System/Library/CoreServices` - Lists patch sets applied including files installed and removed diff --git a/data/os_data.py b/data/os_data.py index bb9145959..cdeb761fc 100644 --- a/data/os_data.py +++ b/data/os_data.py @@ -34,4 +34,14 @@ class os_conversion: if kernel >= os_data.big_sur: return str((kernel - 9)) else: - return str((f"10.{kernel - 4}")) \ No newline at end of file + return str((f"10.{kernel - 4}")) + + def is_os_newer(source_major, source_minor, target_major, target_minor): + # Check if OS version 1 is newer than OS version 2 + if source_major < target_major: + return True + elif source_major == target_major: + if source_minor < target_minor: + return True + else: + return False \ No newline at end of file diff --git a/data/sys_patch_dict.py b/data/sys_patch_dict.py index 86647af1f..d178d633b 100644 --- a/data/sys_patch_dict.py +++ b/data/sys_patch_dict.py @@ -13,10 +13,14 @@ from data import os_data -def SystemPatchDictionary(os_major): +def SystemPatchDictionary(os_major, os_minor): sys_patch_dict = { "Graphics": { "Non-Metal Common": { + "OS Support": { + "OS Major": os_data.os_data.big_sur, + "OS Minor": 0 + }, "Install": { "/System/Library/Extensions": { "IOSurface.kext": "10.15.7", @@ -68,6 +72,10 @@ def SystemPatchDictionary(os_major): }, }, "Metal Common": { + "OS Support": { + "OS Major": os_data.os_data.monterey, + "OS Minor": 0 + }, "Install": { "/System/Library/Frameworks": { "OpenCL.framework": "11.6", @@ -81,6 +89,10 @@ def SystemPatchDictionary(os_major): }, "Legacy GVA": { + "OS Support": { + "OS Major": os_data.os_data.big_sur, + "OS Minor": 0 + }, "Install": { "/System/Library/PrivateFrameworks": { "AppleGVA.framework": "10.13.6", @@ -90,6 +102,10 @@ def SystemPatchDictionary(os_major): }, "Nvidia Tesla": { + "OS Support": { + "OS Major": os_data.os_data.mojave, + "OS Minor": 0 + }, "Install": { "/System/Library/Extensions": { "GeForceGA.bundle": "10.13.6", @@ -98,11 +114,17 @@ def SystemPatchDictionary(os_major): "GeForceTeslaVADriver.bundle": "10.13.6", "NVDANV50HalTesla.kext": "10.13.6", "NVDAResmanTesla.kext": "10.13.6", - **({ "NVDAStartup.kext": "12.0 Beta 6" } if os_major >= os_data.os_data.monterey else {}) + # Apple dropped NVDAStartup in 12.0 Beta 7 (XNU 21.1) + **({ "NVDAStartup.kext": "12.0 Beta 6" } if os_data.os_conversion.is_os_newer(os_data.os_data.monterey, 1, os_major, os_minor) else {}) }, }, }, "Nvidia Kepler": { + "OS Support": { + # 12.0 beta 7 (XNU 21.1) + "OS Major": os_data.os_data.monterey, + "OS Minor": 1 + }, "Install": { "/System/Library/Extensions": { "GeForceAIRPlugin.bundle": "11.0 Beta 3", @@ -118,6 +140,10 @@ def SystemPatchDictionary(os_major): }, }, "Nvidia Web Drivers": { + "OS Support": { + "OS Major": os_data.os_data.mojave, + "OS Minor": 0 + }, "Install": { "/System/Library/Extensions": { "NVDAStartupWeb.kext": "10.13.6", @@ -141,6 +167,10 @@ def SystemPatchDictionary(os_major): }, }, "AMD Non-Metal Common": { + "OS Support": { + "OS Major": os_data.os_data.mojave, + "OS Minor": 0 + }, "Install": { "/System/Library/Extensions": { "AMDFramebuffer.kext": "10.13.6", @@ -162,6 +192,10 @@ def SystemPatchDictionary(os_major): }, "AMD TeraScale 1": { + "OS Support": { + "OS Major": os_data.os_data.mojave, + "OS Minor": 0 + }, "Install": { "/System/Library/Extensions": { "AMD2400Controller.kext": "10.13.6", @@ -175,8 +209,25 @@ def SystemPatchDictionary(os_major): "ATIRadeonX2000VADriver.bundle": "10.13.6", }, }, + "Remove": { + "/System/Library/Extensions": [ + # Following removals are a work around for 0.4.3 and older root patches + # Previously TS1 and TS2 patch sets were shared, now they're split off + # Due to this, updating to 0.4.4 or newer can break kmutil linking + "AMD5000Controller.kext", + "AMD6000Controller.kext", + "AMDRadeonVADriver.bundle", + "AMDRadeonVADriver2.bundle", + "AMDRadeonX3000.kext", + "AMDRadeonX3000GLDriver.bundle", + ], + }, }, "AMD TeraScale 2": { + "OS Support": { + "OS Major": os_data.os_data.mojave, + "OS Minor": 0 + }, "Install": { "/System/Library/Extensions": { "AMD5000Controller.kext": "10.13.6", @@ -204,6 +255,10 @@ def SystemPatchDictionary(os_major): }, }, "Intel Ironlake": { + "OS Support": { + "OS Major": os_data.os_data.mojave, + "OS Minor": 0 + }, "Install": { "/System/Library/Extensions": { "AppleIntelHDGraphics.kext": "10.13.6", @@ -215,6 +270,10 @@ def SystemPatchDictionary(os_major): }, }, "Intel Sandy Bridge": { + "OS Support": { + "OS Major": os_data.os_data.mojave, + "OS Minor": 0 + }, "Install": { "/System/Library/Extensions": { "AppleIntelHD3000Graphics.kext": "10.13.6", @@ -227,6 +286,10 @@ def SystemPatchDictionary(os_major): }, }, "Intel Ivy Bridge": { + "OS Support": { + "OS Major": os_data.os_data.monterey, + "OS Minor": 0 + }, "Processes": { "defaults write com.apple.coremedia hardwareVideoDecoder -string enable": False, }, @@ -245,6 +308,10 @@ def SystemPatchDictionary(os_major): }, "Audio": { "Legacy Realtek": { + "OS Support": { + "OS Major": os_data.os_data.sierra, + "OS Minor": 0 + }, # For iMac7,1 and iMac8,1 units with legacy Realtek HD Audio "Install": { "/System/Library/Extensions": { @@ -264,6 +331,10 @@ def SystemPatchDictionary(os_major): }, # For Mac Pros with non-UGA/GOP GPUs "Legacy Non-GOP": { + "OS Support": { + "OS Major": os_data.os_data.mojave, + "OS Minor": 0 + }, "Install": { "/System/Library/Extensions": { "AppleHDA.kext": "10.13.6", @@ -273,6 +344,10 @@ def SystemPatchDictionary(os_major): }, "Networking": { "Legacy WiFi": { + "OS Support": { + "OS Major": os_data.os_data.monterey, + "OS Minor": 0 + }, "Install": { "/usr/libexec": { "airportd": "11.5.2", @@ -291,6 +366,10 @@ def SystemPatchDictionary(os_major): }, "Brightness": { "Legacy Brightness": { + "OS Support": { + "OS Major": os_data.os_data.high_sierra, + "OS Minor": 0 + }, "Install": { "/System/Library/Extensions": { "AppleBacklight.kext": "10.12.6", @@ -309,6 +388,10 @@ def SystemPatchDictionary(os_major): }, "Miscellaneous": { "Legacy GMUX": { + "OS Support": { + "OS Major": os_data.os_data.high_sierra, + "OS Minor": 0 + }, "Install": { "/System/Library/Extensions/AppleGraphicsControl.kext/Contents/PlugIns": { "AppleMuxControl.kext": "10.12.6", @@ -325,6 +408,10 @@ def SystemPatchDictionary(os_major): }, }, "Legacy Keyboard Backlight": { + "OS Support": { + "OS Major": os_data.os_data.big_sur, + "OS Minor": 0 + }, "Processes": { "defaults write /Library/Preferences/.GlobalPreferences.plist Moraea_BacklightHack -bool true": True, }, diff --git a/resources/sys_patch.py b/resources/sys_patch.py index 29f17b886..bf1ef92ec 100644 --- a/resources/sys_patch.py +++ b/resources/sys_patch.py @@ -49,6 +49,11 @@ class PatchSysVolume: hardware_details = sys_patch_detect.detect_root_patch(self.computer.real_model, self.constants).detect_patch_set() self.hardware_details = hardware_details self.init_pathing(custom_root_mount_path=None, custom_data_mount_path=None) + + def __del__(self): + # Ensures that each time we're patching, we're using a clean repository + if Path(self.constants.payload_local_binaries_root_path).exists(): + shutil.rmtree(self.constants.payload_local_binaries_root_path) def init_pathing(self, custom_root_mount_path=None, custom_data_mount_path=None): if custom_root_mount_path and custom_data_mount_path: @@ -63,42 +68,32 @@ class PatchSysVolume: self.mount_location_data = "" self.mount_extensions = f"{self.mount_location}/System/Library/Extensions" self.mount_application_support = f"{self.mount_location_data}/Library/Application Support" + - def find_mount_root_vol(self, patch): + def mount_root_vol(self): + # Returns boolean if Root Volume is available self.root_mount_path = utilities.get_disk_path() if self.root_mount_path.startswith("disk"): print(f"- Found Root Volume at: {self.root_mount_path}") if Path(self.mount_extensions).exists(): print("- Root Volume is already mounted") - if patch is True: - self.patch_root_vol() - return True - else: - self.unpatch_root_vol() - return True + return True else: - if self.constants.detected_os > os_data.os_data.catalina and self.root_supports_snapshot is True: + if self.root_supports_snapshot is True: print("- Mounting APFS Snapshot as writable") result = utilities.elevated(["mount", "-o", "nobrowse", "-t", "apfs", f"/dev/{self.root_mount_path}", self.mount_location], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if result.returncode == 0: print(f"- Mounted APFS Snapshot as writable at: {self.mount_location}") - if Path(self.mount_extensions).exists(): - print("- Successfully mounted the Root Volume") - if patch is True: - self.patch_root_vol() - return True + if Path(self.mount_extensions).exists(): + print("- Successfully mounted the Root Volume") + return True + else: + print("- Root Volume appears to have unmounted unexpectedly") else: - self.unpatch_root_vol() - return True - else: - print("- Failed to mount the Root Volume") - print("- Recommend rebooting the machine and trying to patch again") - if self.constants.gui_mode is False: - input("- Press [ENTER] to exit: ") - else: - print("- Could not find root volume") - if self.constants.gui_mode is False: - input("- Press [ENTER] to exit: ") + print("- Unable to mount APFS Snapshot as writable") + print("Reason for mount failure:") + print(result.stdout.decode().strip()) + return False def unpatch_root_vol(self): if self.constants.detected_os > os_data.os_data.catalina and self.root_supports_snapshot is True: @@ -248,30 +243,18 @@ class PatchSysVolume: # Make sure SNB kexts are compatible with the host if "Intel Sandy Bridge" in required_patches: - if self.computer.reported_board_id not in self.constants.sandy_board_id_stock: - print(f"- Found unspported Board ID {self.computer.reported_board_id}, performing AppleIntelSNBGraphicsFB bin patching") - board_to_patch = generate_smbios.determine_best_board_id_for_sandy(self.computer.reported_board_id, self.computer.gpus) - print(f"- Replacing {board_to_patch} with {self.computer.reported_board_id}") - - board_to_patch_hex = bytes.fromhex(board_to_patch.encode('utf-8').hex()) - reported_board_hex = bytes.fromhex(self.computer.reported_board_id.encode('utf-8').hex()) - - if len(board_to_patch_hex) != len(reported_board_hex): - print(f"- Error: Board ID {self.computer.reported_board_id} is not the same length as {board_to_patch}") - raise Exception("Host's Board ID is not the same length as the kext's Board ID, cannot patch!!!") - else: - path = source_files_path + "10.13.6/System/Library/Extensions/AppleIntelSNBGraphicsFB.kext/Contents/MacOS/AppleIntelSNBGraphicsFB" - if Path(path).exists(): - with open(path, 'rb') as f: - data = f.read() - data = data.replace(board_to_patch_hex, reported_board_hex) - with open(path, 'wb') as f: - f.write(data) - else: - raise Exception("Failed to find AppleIntelSNBGraphicsFB.kext, cannot patch!!!") + self.snb_board_id_patch(source_files_path) - # Check all the files are present for patch in required_patches: + # Check if the patch sets support the current OS + if required_patches[patch]["OS Support"]["OS Major"] > self.constants.detected_os: + print(f"Patch set OS Major check: {required_patches[patch]['OS Support']['OS Major']} < {self.constants.detected_os}") + raise Exception("This patchset is not supported on this version of macOS!") + elif required_patches[patch]["OS Support"]["OS Minor"] > self.constants.detected_os_minor: + print(f"Patch set OS Minor check: {required_patches[patch]['OS Support']['OS Minor']} < {self.constants.detected_os_minor}") + raise Exception("This patchset is not supported on this version of macOS!") + + # Check if all files are present for method_type in ["Install", "Install Non-Root"]: if method_type in required_patches[patch]: for install_patch_directory in required_patches[patch][method_type]: @@ -331,6 +314,35 @@ class PatchSysVolume: utilities.process_status(utilities.elevated(chown_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + def snb_board_id_patch(self, source_files_path): + # AppleIntelSNBGraphicsFB hard codes the supported Board IDs for Sandy Bridge iGPUs + # Because of this, the kext errors out on unsupported systems + # This function simply patches in a supported Board ID, using 'determine_best_board_id_for_sandy()' + # to supplement the ideal Board ID + if self.computer.reported_board_id not in self.constants.sandy_board_id_stock: + print(f"- Found unspported Board ID {self.computer.reported_board_id}, performing AppleIntelSNBGraphicsFB bin patching") + board_to_patch = generate_smbios.determine_best_board_id_for_sandy(self.computer.reported_board_id, self.computer.gpus) + print(f"- Replacing {board_to_patch} with {self.computer.reported_board_id}") + + board_to_patch_hex = bytes.fromhex(board_to_patch.encode('utf-8').hex()) + reported_board_hex = bytes.fromhex(self.computer.reported_board_id.encode('utf-8').hex()) + + if len(board_to_patch_hex) != len(reported_board_hex): + print(f"- Error: Board ID {self.computer.reported_board_id} is not the same length as {board_to_patch}") + raise Exception("Host's Board ID is not the same length as the kext's Board ID, cannot patch!!!") + else: + path = source_files_path + "/10.13.6/System/Library/Extensions/AppleIntelSNBGraphicsFB.kext/Contents/MacOS/AppleIntelSNBGraphicsFB" + if Path(path).exists(): + with open(path, 'rb') as f: + data = f.read() + data = data.replace(board_to_patch_hex, reported_board_hex) + with open(path, 'wb') as f: + f.write(data) + else: + print(f"- Error: Could not find {path}") + raise Exception("Failed to find AppleIntelSNBGraphicsFB.kext, cannot patch!!!") + + def check_files(self): if Path(self.constants.payload_local_binaries_root_path).exists(): print("- Found local Apple Binaries") @@ -389,7 +401,14 @@ class PatchSysVolume: if sys_patch_detect.detect_root_patch(self.computer.real_model, self.constants).verify_patch_allowed(print_errors=not self.constants.wxpython_variant) is True: print("- Patcher is capable of patching") if self.check_files(): - self.find_mount_root_vol(True) + if self.mount_root_vol() is True: + self.patch_root_vol() + if self.constants.gui_mode is False: + input("\nPress [ENTER] to return to the main menu") + else: + print("- Recommend rebooting the machine and trying to patch again") + if self.constants.gui_mode is False: + input("- Press [ENTER] to exit: ") elif self.constants.gui_mode is False: input("\nPress [ENTER] to return to the main menu: ") @@ -399,8 +418,13 @@ class PatchSysVolume: def start_unpatch(self): print("- Starting Unpatch Process") if sys_patch_detect.detect_root_patch(self.computer.real_model, self.constants).verify_patch_allowed(print_errors=True) is True: - self.find_mount_root_vol(False) - if self.constants.gui_mode is False: - input("\nPress [ENTER] to return to the main menu") + if self.mount_root_vol() is True: + self.unpatch_root_vol() + if self.constants.gui_mode is False: + input("\nPress [ENTER] to return to the main menu") + else: + print("- Recommend rebooting the machine and trying to patch again") + if self.constants.gui_mode is False: + input("- Press [ENTER] to exit: ") elif self.constants.gui_mode is False: input("\nPress [ENTER] to return to the main menu") diff --git a/resources/sys_patch_detect.py b/resources/sys_patch_detect.py index 54499e8f1..04546e509 100644 --- a/resources/sys_patch_detect.py +++ b/resources/sys_patch_detect.py @@ -220,7 +220,7 @@ class detect_root_patch: return True def generate_patchset(self, hardware_details): - all_hardware_patchset = sys_patch_dict.SystemPatchDictionary(self.constants.detected_os) + all_hardware_patchset = sys_patch_dict.SystemPatchDictionary(self.constants.detected_os, self.constants.detected_os_minor) required_patches = {} utilities.cls() print("- The following patches will be applied:")