diff --git a/OpenCore-Patcher.command b/OpenCore-Patcher.command index bf3822aea..efb5493da 100755 --- a/OpenCore-Patcher.command +++ b/OpenCore-Patcher.command @@ -119,11 +119,11 @@ system_profiler SPHardwareDataType | grep 'Model Identifier' menu = Utilities.TUIMenu(title, "Please select an option: ", auto_number=True, top_level=True) options = [ [f"Assume Metal GPU Always:\t\tCurrently {self.constants.imac_vendor}", CliMenu.MenuOptions(self.constants.custom_model or self.current_model, self.constants).change_metal], - [f"Assume Upgraded Wifi Always:\tCurrently {self.constants.wifi_build}", CliMenu.MenuOptions(self.constants.custom_model or self.current_model, self.constants).change_wifi], + #[f"Assume Upgraded Wifi Always:\tCurrently {self.constants.wifi_build}", CliMenu.MenuOptions(self.constants.custom_model or self.current_model, self.constants).change_wifi], [f"Set SMBIOS Mode:\t\t\tCurrently {self.constants.serial_settings}", CliMenu.MenuOptions(self.constants.custom_model or self.current_model, self.constants).change_serial], [f"DRM Preferences:\t\t\tCurrently {self.constants.drm_support}", CliMenu.MenuOptions(self.constants.custom_model or self.current_model, self.constants).drm_setting], [f"Set Generic Bootstrap:\t\tCurrently {self.constants.boot_efi}", CliMenu.MenuOptions(self.constants.custom_model or self.current_model, self.constants).bootstrap_setting], - [f"Assume Legacy GPU:\t\t\tCurrently {self.constants.assume_legacy}", CliMenu.MenuOptions(self.constants.custom_model or self.current_model, self.constants).force_accel_setting], + #[f"Assume Legacy GPU:\t\t\tCurrently {self.constants.assume_legacy}", CliMenu.MenuOptions(self.constants.custom_model or self.current_model, self.constants).force_accel_setting], [f"Disable CPU Friend:\t\t\tCurrently {self.constants.disallow_cpufriend}", CliMenu.MenuOptions(self.constants.custom_model or self.current_model, self.constants).disable_cpufriend], [f"Override SMBIOS Spoof:\t\tCurrently {self.constants.override_smbios}", CliMenu.MenuOptions(self.constants.custom_model or self.current_model, self.constants).set_smbios], [f"Set Custom name {self.constants.custom_cpu_model_value}", CliMenu.MenuOptions(self.constants.custom_model or self.current_model, self.constants).custom_cpu], @@ -150,12 +150,12 @@ system_profiler SPHardwareDataType | grep 'Model Identifier' def PatchVolume(self): Utilities.cls() Utilities.header(["Patching System Volume"]) - print("""Patches Root volume to fix misc issues such as: + big_sur = """Patches Root volume to fix misc issues such as: - Graphics Acceleration for non-Metal GPUs - Nvidia: Tesla - Fermi (8000-500 series) - Intel: Ironlake - Sandy Bridge - - AMD: TeraScale 1 (2000-4000 series) + - AMD: TeraScale 1 and 2 (2000-6000 series) - Audio support for iMac7,1 and iMac8,1 WARNING: Root Volume Patching is still in active development, please @@ -168,7 +168,30 @@ Supported Options: 1. Patch System Volume 2. Unpatch System Volume (Experimental) B. Exit - """) + """ + monterey = """Patches Root volume to fix misc issues such as: + +- Basic Framebuffer and brightness Control (No acceleration) + - Nvidia: Tesla - Fermi (8000-500 series) + - Intel: Ironlake - Sandy Bridge + - AMD: TeraScale 1 and 2 (2000-6000 series) +- Audio support for iMac7,1 and iMac8,1 + +WARNING: Root Volume Patching is still in active development, please +have all important user data backed up. Note when the system volume +is patched, you can no longer have Delta updates or have FileVault +enabled. + +Supported Options: + +1. Patch System Volume +2. Unpatch System Volume (Experimental) +B. Exit + """ + if self.constants.detected_os > self.constants.big_sur: + print(monterey) + else: + print(big_sur) change_menu = input("Patch System Volume?: ") if change_menu == "1": SysPatch.PatchSysVolume(self.constants.custom_model or self.current_model, self.constants).start_patch() @@ -184,7 +207,6 @@ B. Exit title = [ f"OpenCore Legacy Patcher v{self.constants.patcher_version}", f"Selected Model: {self.constants.custom_model or self.current_model}", - f"Target OS: macOS {self.constants.os_support}", ] if (self.constants.custom_model or self.current_model) not in ModelArray.SupportedSMBIOS and self.constants.allow_oc_everywhere is False: diff --git a/Resources/ModelArray.py b/Resources/ModelArray.py index d5a37f1a1..098d3c5ca 100644 --- a/Resources/ModelArray.py +++ b/Resources/ModelArray.py @@ -1244,6 +1244,9 @@ AddIntelGen3Accel = [ "AppleIntelHD4000GraphicsGLDriver.bundle", "AppleIntelHD4000GraphicsMTLDriver.bundle", "AppleIntelHD4000GraphicsVADriver.bundle", + "IOSurface.kext", + "IOGPUFamily.kext", + "IOAcceleratorFamily2.kext", ] AddGeneralAccel = [ diff --git a/Resources/SysPatch.py b/Resources/SysPatch.py index fc60652fd..5ed6a05ce 100644 --- a/Resources/SysPatch.py +++ b/Resources/SysPatch.py @@ -20,17 +20,29 @@ class PatchSysVolume: def __init__(self, model, versions): self.model = model self.constants: Constants.Constants = versions - self.sip_patch_status = True self.root_mount_path = None - self.sip_status = None + self.sip_enabled = True + self.sbm_enabled = True + self.amfi_enabled = True + self.fv_enabled = True + self.nvidia_legacy = False + self.amd_ts1 = False + self.amd_ts2 = False + self.iron_gpu = False + self.sandy_gpu = False + self.ivy_gpu = False + self.nvidia_legacy = False + self.brightness_legacy = False + self.legacy_audio = False + self.added_kexts = False + self.amfi_must_disable = False + self.no_patch = True - # TODO: Put this in a better place - if self.constants.recovery_status is True: - if not Path("/Volumes/mnt1").exists: - self.elevated(["mkdir", "/Volumes/mnt1"], stdout=subprocess.PIPE).stdout.decode().strip().encode() - self.mount_location = "/Volumes/mnt1" - else: + if self.constants.detected_os > self.constants.catalina: + # Big Sur and newer use APFS snapshots self.mount_location = "/System/Volumes/Update/mnt1" + else: + self.mount_location = "/" self.mount_extensions = f"{self.mount_location}/System/Library/Extensions" self.mount_frameworks = f"{self.mount_location}/System/Library/Frameworks" self.mount_lauchd = f"{self.mount_location}/System/Library/LaunchDaemons" @@ -42,130 +54,9 @@ class PatchSysVolume: else: return subprocess.run(["sudo"] + [args[0][0]] + args[0][1:], **kwargs) - def csr_decode(self, print_status): - sip_int = int.from_bytes(self.sip_status, byteorder="little") - i = 0 - for current_sip_bit in self.constants.csr_values: - if sip_int & (1 << i): - temp = True - self.constants.csr_values[current_sip_bit] = True - else: - temp = False - if print_status is True: - print(f"- {current_sip_bit}\t {temp}") - i = i + 1 - - sip_needs_change = all( - self.constants.csr_values[i] - for i in [ - "CSR_ALLOW_UNTRUSTED_KEXTS", - "CSR_ALLOW_UNRESTRICTED_FS", - "CSR_ALLOW_UNRESTRICTED_DTRACE", - "CSR_ALLOW_UNRESTRICTED_NVRAM", - "CSR_ALLOW_DEVICE_CONFIGURATION", - "CSR_ALLOW_UNAPPROVED_KEXTS", - "CSR_ALLOW_EXECUTABLE_POLICY_OVERRIDE", - "CSR_ALLOW_UNAUTHENTICATED_ROOT", - ] - ) - if sip_needs_change is True: - self.sip_patch_status = False - else: - self.sip_patch_status = True - - def recovery_root_mount(self): - def human_fmt(num): - for unit in ["B", "KB", "MB", "GB", "TB", "PB"]: - if abs(num) < 1000.0: - return "%3.1f %s" % (num, unit) - num /= 1000.0 - return "%.1f %s" % (num, "EB") - - print("- Starting Root Volume Picker") - # Planned logic: - # Load "diskutil list -plist" - # Find all APFSVolumes entries where VolumeName is not named Update, VM, Recovery or Preboot - # Omit any VolumeName entries containing "- Data" - # Parse remianing options for macOS 11.x with /Volumes/$disk/System/Library/CoreServices/SystemVersion.plist - # List remaining drives as user options - all_disks = {} - disks = plistlib.loads(subprocess.run("diskutil list -plist".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()) - for disk in disks["AllDisksAndPartitions"]: - disk_info = plistlib.loads(subprocess.run(f"diskutil info -plist {disk['DeviceIdentifier']}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()) - try: - all_disks[disk["DeviceIdentifier"]] = {"identifier": disk_info["DeviceNode"], "name": disk_info["MediaName"], "size": disk_info["TotalSize"], "partitions": {}} - for partition in disk["Partitions"] + disk.get("APFSVolumes", []): - partition_info = plistlib.loads(subprocess.run(f"diskutil info -plist {partition['DeviceIdentifier']}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()) - all_disks[disk["DeviceIdentifier"]]["partitions"][partition["DeviceIdentifier"]] = { - "fs": partition_info.get("FilesystemType", partition_info["Content"]), - "type": partition_info["Content"], - "name": partition_info.get("VolumeName", ""), - "size": partition_info["TotalSize"], - "sealed": partition_info.get("Sealed", "No"), - } - except KeyError: - # Avoid crashing with CDs installed - continue - menu = Utilities.TUIMenu( - ["Select Disk"], - "Please select the disk you would like to patch: ", - in_between=["Missing disks? Ensure they have a macOS Big Sur install present."], - return_number_instead_of_direct_call=True, - loop=True, - ) - for disk in all_disks: - if not any(all_disks[disk]["partitions"][partition]["fs"] == "apfs" for partition in all_disks[disk]["partitions"]): - continue - menu.add_menu_option(f"{disk}: {all_disks[disk]['name']} ({human_fmt(all_disks[disk]['size'])})", key=disk[4:]) - - response = menu.start() - - if response == -1: - return - - disk_identifier = "disk" + response - selected_disk = all_disks[disk_identifier] - - menu = Utilities.TUIMenu( - ["Select Partition"], - "Please select the partition you would like to install OpenCore to: ", - return_number_instead_of_direct_call=True, - loop=True, - in_between=["Missing disks? Ensure they have a macOS Big Sur install present.", "", "* denotes likely candidate."], - ) - # TODO: check if Big Sur, when macOS 12 comes out - for partition in selected_disk["partitions"]: - if selected_disk["partitions"][partition]["fs"] != "apfs": - continue - text = f"{partition}: {selected_disk['partitions'][partition]['name']} ({human_fmt(selected_disk['partitions'][partition]['size'])})" - if selected_disk["partitions"][partition]["sealed"] != "No": - text += " *" - menu.add_menu_option(text, key=partition[len(disk_identifier) + 1 :]) - - response = menu.start() - - if response == -1: - return - else: - return f"{disk_identifier}s{response}" - def find_mount_root_vol(self, patch): - if self.constants.recovery_status is True: - print("- Running RecoveryOS logic") - self.root_mount_path = self.recovery_root_mount() - if not self.root_mount_path: - return - print(f"- Root Mount Path: {self.root_mount_path}") - if not Path(self.constants.payload_mnt1_path).exists(): - print("- Creating mnt1 folder") - Path(self.constants.payload_mnt1_path).mkdir() - else: - root_partition_info = plistlib.loads(subprocess.run("diskutil info -plist /".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()) - self.root_mount_path = root_partition_info["DeviceIdentifier"] - + self.root_mount_path = Utilities.get_disk_path() if self.root_mount_path.startswith("disk"): - if self.constants.recovery_status is False: - self.root_mount_path = self.root_mount_path[:-2] if self.root_mount_path.count("s") > 1 else self.root_mount_path print(f"- Found Root Volume at: {self.root_mount_path}") if Path(self.mount_extensions).exists(): print("- Root Volume is already mounted") @@ -176,16 +67,8 @@ class PatchSysVolume: self.unpatch_root_vol() return True else: - if self.constants.recovery_status is True: - print("- Mounting drive as writable in Recovery") - - umount_drive = plistlib.loads(subprocess.run(f"diskutil info -plist {self.root_mount_path}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()) - umount_drive = umount_drive["VolumeName"] - self.elevated(["umount", f'/Volumes/{umount_drive}'], stdout=subprocess.PIPE).stdout.decode().strip().encode() - self.elevated(["mount", "-t", "apfs", "-rw", f"/dev/{self.root_mount_path}", self.mount_location], stdout=subprocess.PIPE).stdout.decode().strip().encode() - else: - print("- Mounting drive as writable in OS") - self.elevated(["mount", "-o", "nobrowse", "-t", "apfs", f"/dev/{self.root_mount_path}", self.mount_location], stdout=subprocess.PIPE).stdout.decode().strip().encode() + print("- Mounting drive as writable in OS") + self.elevated(["mount", "-o", "nobrowse", "-t", "apfs", f"/dev/{self.root_mount_path}", self.mount_location], stdout=subprocess.PIPE).stdout.decode().strip().encode() if Path(self.mount_extensions).exists(): print("- Successfully mounted the Root Volume") if patch is True: @@ -197,10 +80,46 @@ class PatchSysVolume: else: print("- Failed to mount the Root Volume") print("- Recommend rebooting the machine and trying to patch again") - input("- Press [ENTER] to exit") + input("- Press [ENTER] to exit: ") else: print("- Could not find root volume") - input("- Press [ENTER] to exit") + input("- Press [ENTER] to exit: ") + + def unpatch_root_vol(self): + print("- Reverting to last signed APFS snapshot") + self.elevated(["bless", "--mount", self.mount_location, "--bootefi", "--last-sealed-snapshot"], stdout=subprocess.PIPE).stdout.decode().strip().encode() + + def rebuild_snapshot(self): + if self.constants.gui_mode is False: + input("Press [ENTER] to continue with cache rebuild: ") + print("- Rebuilding Kernel Cache (This may take some time)") + result = self.elevated(["kmutil", "install", "--volume-root", self.mount_location, "--update-all"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + + if result.returncode != 0: + self.success_status = False + print("- Unable to build new kernel cache") + print("\nPlease report this to Github") + print("Reason for Patch Failure:") + print(result.stdout.decode()) + print("") + print("\nPlease reboot the machine to avoid potential issues rerunning the patcher") + input("Press [ENTER] to continue") + else: + self.success_status = True + print("- Successfully built new kernel cache") + if self.constants.gui_mode is False: + input("Press [ENTER] to continue with snapshotting") + print("- Creating new APFS snapshot") + self.elevated(["bless", "--folder", f"{self.mount_location}/System/Library/CoreServices", "--bootefi", "--create-snapshot"], stdout=subprocess.PIPE).stdout.decode().strip().encode() + self.unmount_drive() + print("- Patching complete") + print("\nPlease reboot the machine for patches to take effect") + input("Press [ENTER] to continue") + + + def unmount_drive(self): + print("- Unmounting Root Volume (Don't worry if this fails)") + self.elevated(["diskutil", "unmount", self.root_mount_path], stdout=subprocess.PIPE).stdout.decode().strip().encode() def delete_old_binaries(self, vendor_patch): for delete_current_kext in vendor_patch: @@ -223,201 +142,154 @@ class PatchSysVolume: self.elevated(["chown", "-Rf", "root:wheel", f"{self.mount_extensions}/{add_current_kext}"], stdout=subprocess.PIPE).stdout.decode().strip().encode() def add_brightness_patch(self): - print("- Merging legacy Brightness Control Patches") self.delete_old_binaries(ModelArray.DeleteBrightness) self.add_new_binaries(ModelArray.AddBrightness, self.constants.legacy_brightness) self.elevated(["ditto", self.constants.payload_apple_private_frameworks_path_brightness, self.mount_private_frameworks], stdout=subprocess.PIPE).stdout.decode().strip().encode() self.elevated(["chmod", "-Rf", "755", f"{self.mount_private_frameworks}/DisplayServices.framework"], stdout=subprocess.PIPE).stdout.decode().strip().encode() self.elevated(["chown", "-Rf", "root:wheel", f"{self.mount_private_frameworks}/DisplayServices.framework"], stdout=subprocess.PIPE).stdout.decode().strip().encode() - def gpu_accel_patches_11(self): - igpu_vendor, igpu_device, igpu_acpi = DeviceProbe.pci_probe().gpu_probe("IGPU") - dgpu_vendor, dgpu_device, dgpu_acpi = DeviceProbe.pci_probe().gpu_probe("GFX0") - if dgpu_vendor: - print(f"- Found GFX0: {dgpu_vendor}:{dgpu_device}") - if dgpu_vendor == self.constants.pci_nvidia: - if dgpu_device in PCIIDArray.nvidia_ids().tesla_ids or dgpu_device in PCIIDArray.nvidia_ids().fermi_ids: - print("- Merging legacy Nvidia Tesla and Fermi Kexts and Bundles") - self.delete_old_binaries(ModelArray.DeleteNvidiaAccel11) - self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) - self.add_new_binaries(ModelArray.AddNvidiaAccel11, self.constants.legacy_nvidia_path) - self.added_kexts = True - # TODO: Enable below code if macOS 12 drops support - # elif dgpu_device in PCIIDArray.nvidia_ids().kepler_ids and self.constants.detected_os > self.constants.big_sur: - # print("- Merging legacy Nvidia Kepler Kexts and Bundles") - # self.add_new_binaries(ModelArray.AddNvidiaKeplerAccel11, self.constants.legacy_nvidia_kepler_path) - elif dgpu_vendor == self.constants.pci_amd_ati: - if dgpu_device in PCIIDArray.amd_ids().terascale_1_ids: - print("- Merging legacy AMD Kexts and Bundles") - self.delete_old_binaries(ModelArray.DeleteAMDAccel11) - self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) - self.add_new_binaries(ModelArray.AddAMDAccel11, self.constants.legacy_amd_path) - self.added_kexts = True - if self.model in ["MacBookPro8,2", "MacBookPro8,3"]: - # This is used for MacBookPro8,2/3 where dGPU is disabled via NVRAM and still requires AMD framebuffer - # For reference: - #- deMUX: Don't need the AMD patches - #- dGPUs enabled: Don't install the AMD patches (Infinite login loop otherwise) - #- dGPUs disabled: Do need the AMD patches (Restores Brightness control) - dgpu_status: str = subprocess.run("nvram FA4CE28D-B62F-4C99-9CC3-6815686E30F9:gpu-power-prefs".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode() - if dgpu_status.startswith("FA4CE28D-B62F-4C99-9CC3-6815686E30F9:gpu-power-prefs %01"): - print("- Detected dGPU is disabled via NVRAM") - print("- Merging legacy AMD Kexts and Bundles") - self.delete_old_binaries(ModelArray.DeleteAMDAccel11) - self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) - self.add_new_binaries(ModelArray.AddAMDAccel11, self.constants.legacy_amd_path) - self.added_kexts = True - else: - print("- Cannot install Brightness Control, pleas ensure the dGPU is disabled via NVRAM") - if igpu_vendor: - print(f"- Found IGPU: {igpu_vendor}:{igpu_device}") - if igpu_vendor == self.constants.pci_intel: - if igpu_device in PCIIDArray.intel_ids().iron_ids: - print("- Merging legacy Intel 1st Gen Kexts and Bundles") - self.delete_old_binaries(ModelArray.DeleteNvidiaAccel11) - self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) - self.add_new_binaries(ModelArray.AddIntelGen1Accel, self.constants.legacy_intel_gen1_path) - self.added_kexts = True - elif igpu_device in PCIIDArray.intel_ids().sandy_ids: - print("- Merging legacy Intel 2nd Gen Kexts and Bundles") - self.delete_old_binaries(ModelArray.DeleteNvidiaAccel11) - self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) - self.add_new_binaries(ModelArray.AddIntelGen2Accel, self.constants.legacy_intel_gen2_path) - self.added_kexts = True + def add_audio_patch(self): + self.delete_old_binaries(ModelArray.DeleteVolumeControl) + self.add_new_binaries(ModelArray.AddVolumeControl, self.constants.audio_path) - # TODO: Enable below code if macOS 12 drops support - # elif igpu_device in PCIIDArray.intel_ids().ivy_ids: - # print("- Merging legacy Intel 3rd Gen Kexts and Bundles") - # self.add_new_binaries(ModelArray.AddIntelGen3Accel, self.constants.legacy_intel_gen3_path) - elif igpu_vendor == self.constants.pci_nvidia: - if not dgpu_vendor: - # Avoid patching twice, as Nvidia iGPUs will only have Nvidia dGPUs - print("- Merging legacy Nvidia Kexts and Bundles") - self.delete_old_binaries(ModelArray.DeleteNvidiaAccel11) - self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) - self.add_new_binaries(ModelArray.AddNvidiaAccel11, self.constants.legacy_nvidia_path) - self.added_kexts = True + def gpu_accel_legacy_nvidia(self): + self.delete_old_binaries(ModelArray.DeleteNvidiaAccel11) + self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) + self.add_new_binaries(ModelArray.AddNvidiaAccel11, self.constants.legacy_nvidia_path) - if self.added_kexts == True: - # Frameworks - print("- Merging legacy Frameworks") - self.elevated(["ditto", self.constants.payload_apple_frameworks_path_accel, self.mount_frameworks], stdout=subprocess.PIPE).stdout.decode().strip().encode() + def gpu_framebuffer_legacy_nvidia(self): + self.add_new_binaries(ModelArray.AddNvidiaBrightness, self.constants.legacy_nvidia_path) - if self.model in ModelArray.LegacyBrightness: - self.add_brightness_patch() + def gpu_accel_legacy_ts1(self): + self.delete_old_binaries(ModelArray.DeleteAMDAccel11) + self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) + self.add_new_binaries(ModelArray.AddAMDAccel11, self.constants.legacy_amd_path) - # LaunchDaemons - if Path(self.mount_lauchd / Path("HiddHack.plist")).exists(): - print("- Removing legacy HiddHack") - self.elevated(["rm", f"{self.mount_lauchd}/HiddHack.plist"], stdout=subprocess.PIPE).stdout.decode().strip().encode() - print("- Adding IOHID-Fixup.plist") - self.elevated(["ditto", self.constants.payload_apple_lauchd_path_accel, self.mount_lauchd], stdout=subprocess.PIPE).stdout.decode().strip().encode() - self.elevated(["chmod", "755", f"{self.mount_lauchd}/IOHID-Fixup.plist"], stdout=subprocess.PIPE).stdout.decode().strip().encode() - self.elevated(["chown", "root:wheel", f"{self.mount_lauchd}/IOHID-Fixup.plist"], stdout=subprocess.PIPE).stdout.decode().strip().encode() + def gpu_accel_legacy_ts2(self): + self.delete_old_binaries(ModelArray.DeleteAMDAccel11) + self.delete_old_binaries(ModelArray.DeleteAMDAccel11TS2) + self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) + self.add_new_binaries(ModelArray.AddAMDAccel11, self.constants.legacy_amd_path) - # PrivateFrameworks - print("- Merging legacy PrivateFrameworks") - self.elevated(["ditto", self.constants.payload_apple_private_frameworks_path_accel, self.mount_private_frameworks], stdout=subprocess.PIPE).stdout.decode().strip().encode() - # Sets AppKit to Catalina Window Drawing codepath - # Disabled upon ASentientBot request - # print("- Enabling NSDefenestratorModeEnabled") - # subprocess.run("defaults write -g NSDefenestratorModeEnabled -bool true".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode() - else: - print("- No Acceleration Kexts were installed, skipping remaining acceleration patches") + def gpu_framebuffer_legacy_amd(self): + self.add_new_binaries(ModelArray.AddAMDBrightness, self.constants.legacy_amd_path) + + def gpu_accel_legacy_ironlake(self): + self.delete_old_binaries(ModelArray.DeleteNvidiaAccel11) + self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) + self.add_new_binaries(ModelArray.AddIntelGen1Accel, self.constants.legacy_intel_gen1_path) + + def gpu_framebuffer_legacy_ironlake(self): + self.add_new_binaries(ModelArray.AddIntelGen1Accel, self.constants.legacy_intel_gen1_path) + + def gpu_accel_legacy_sandybridge(self): + self.delete_old_binaries(ModelArray.DeleteNvidiaAccel11) + self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) + self.add_new_binaries(ModelArray.AddIntelGen2Accel, self.constants.legacy_intel_gen2_path) + + def gpu_framebuffer_legacy_sandybridge(self): + self.add_new_binaries(ModelArray.AddIntelGen2Accel, self.constants.legacy_intel_gen1_path) + + def gpu_framebuffer_ivybridge(self): + self.delete_old_binaries(ModelArray.DeleteAMDAccel11) + self.add_new_binaries(ModelArray.AddIntelGen3Accel, self.constants.legacy_intel_gen3_path) + self.elevated(["ditto", self.constants.payload_apple_frameworks_path_accel, self.mount_frameworks], stdout=subprocess.PIPE).stdout.decode().strip().encode() + + def gpu_accel_legacy_extended(self): + print("- Merging general legacy Frameworks") + self.elevated(["ditto", self.constants.payload_apple_frameworks_path_accel, self.mount_frameworks], stdout=subprocess.PIPE).stdout.decode().strip().encode() + if Path(self.mount_lauchd / Path("HiddHack.plist")).exists(): + print("- Removing legacy HiddHack") + self.elevated(["rm", f"{self.mount_lauchd}/HiddHack.plist"], stdout=subprocess.PIPE).stdout.decode().strip().encode() + print("- Adding IOHID-Fixup.plist") + self.elevated(["ditto", self.constants.payload_apple_lauchd_path_accel, self.mount_lauchd], stdout=subprocess.PIPE).stdout.decode().strip().encode() + self.elevated(["chmod", "755", f"{self.mount_lauchd}/IOHID-Fixup.plist"], stdout=subprocess.PIPE).stdout.decode().strip().encode() + self.elevated(["chown", "root:wheel", f"{self.mount_lauchd}/IOHID-Fixup.plist"], stdout=subprocess.PIPE).stdout.decode().strip().encode() + print("- Merging general legacy PrivateFrameworks") + self.elevated(["ditto", self.constants.payload_apple_private_frameworks_path_accel, self.mount_private_frameworks], stdout=subprocess.PIPE).stdout.decode().strip().encode() + + def gpu_accel_legacy_extended_ts2(self): + print("- Merging TeraScale 2 legacy Frameworks") + self.elevated(["ditto", self.constants.payload_apple_frameworks_path_accel_ts2, self.mount_frameworks], stdout=subprocess.PIPE).stdout.decode().strip().encode() + print("- Merging TeraScale 2 PrivateFrameworks") + self.elevated(["ditto", self.constants.payload_apple_private_frameworks_path_accel_ts2, self.mount_private_frameworks], stdout=subprocess.PIPE).stdout.decode().strip().encode() def patch_root_vol(self): - print(f"- Detecting patches for {self.model}") - rebuild_required = False - # TODO: Create Backup of S*/L*/Extensions, Frameworks and PrivateFramework to easily revert changes - # APFS snapshotting seems to ignore System Volume changes inconsistently, would like a backup to avoid total brick - # Perhaps a basic py2 script to run in recovery to restore - # Ensures no .DS_Stores got in - print("- Preparing Files") - self.elevated(["find", self.constants.payload_apple_root_path, "-name", "'.DS_Store'", "-delete"], stdout=subprocess.PIPE).stdout.decode().strip().encode() - - if self.model in ModelArray.LegacyGPU or self.constants.assume_legacy is True: - dgpu_vendor, dgpu_device, dgpu_acpi = DeviceProbe.pci_probe().gpu_probe("GFX0") - if ( - dgpu_vendor - and dgpu_vendor == self.constants.pci_amd_ati - and ( - dgpu_device in PCIIDArray.amd_ids().polaris_ids - or dgpu_device in PCIIDArray.amd_ids().vega_ids - or dgpu_device in PCIIDArray.amd_ids().navi_ids - or dgpu_device in PCIIDArray.amd_ids().legacy_gcn_ids - ) - ): - print("- Detected Metal-based AMD GPU, skipping legacy patches") - elif dgpu_vendor and dgpu_vendor == self.constants.pci_nvidia and dgpu_device in PCIIDArray.nvidia_ids().kepler_ids: - print("- Detected Metal-based Nvidia GPU, skipping legacy patches") + print(f"- Running patches for {self.model}") + # Graphics patches + if self.nvidia_legacy is True: + print("- Installing legacy Nvidia Patches") + if self.constants.detected_os == self.constants.big_sur: + print("- Detected Big Sur, installing Acceleration patches") + self.gpu_accel_legacy_nvidia() + self.added_kexts = True else: - print("- Detected legacy GPU, attempting legacy acceleration patches") - self.gpu_accel_patches_11() - rebuild_required = True + print("- Detected unsupported OS, installing Basic Framebuffer") + self.gpu_framebuffer_legacy_nvidia() - if self.model in ["iMac7,1", "iMac8,1"]: + if self.amd_ts1 is True: + print("- Installing legacy TeraScale 1 Patches") + if self.constants.detected_os == self.constants.big_sur: + print("- Detected Big Sur, installing Acceleration patches") + self.gpu_accel_legacy_ts1() + self.added_kexts = True + else: + print("- Detected unsupported OS, installing Basic Framebuffer") + self.gpu_framebuffer_legacy_amd() + + if self.amd_ts2 is True: + print("- Installing legacy TeraScale 2 Patches") + if self.constants.detected_os == self.constants.big_sur: + print("- Detected Big Sur, installing Acceleration patches") + self.gpu_accel_legacy_ts2() + self.added_kexts = True + else: + print("- Detected unsupported OS, installing Basic Framebuffer") + self.gpu_framebuffer_legacy_amd() + + if self.iron_gpu is True: + print("- Installing legacy Ironlake Patches") + if self.constants.detected_os == self.constants.big_sur: + print("- Detected Big Sur, installing Acceleration patches") + self.gpu_accel_legacy_ironlake() + self.added_kexts = True + else: + print("- Detected unsupported OS, installing Basic Framebuffer") + self.gpu_framebuffer_legacy_ironlake() + + if self.sandy_gpu is True: + print("- Installing legacy Sandy Bridge Patches") + if self.constants.detected_os == self.constants.big_sur: + print("- Detected Big Sur, installing Acceleration patches") + self.gpu_accel_legacy_sandybridge() + self.added_kexts = True + else: + print("- Detected unsupported OS, installing Basic Framebuffer") + self.gpu_framebuffer_legacy_sandybridge() + + if self.ivy_gpu is True: + print("- Installing Ivy Bridge Patches") + self.gpu_framebuffer_ivybridge() + + if self.amd_ts2 is True: + # TeraScale 2 patches must be installed after Intel HD3000 + self.add_new_binaries(ModelArray.AddAMDAccel11TS2, self.constants.legacy_amd_path_ts2) + + if self.added_kexts is True: + self.gpu_accel_legacy_extended() + if self.amd_ts2 is True: + self.gpu_accel_legacy_extended_ts2() + + # Misc patches + if self.brightness_legacy is True: + print("- Installing legacy Brightness Control") + self.add_brightness_patch() + + if self.legacy_audio is True: print("- Fixing Volume Control Support") - self.delete_old_binaries(ModelArray.DeleteVolumeControl) - self.add_new_binaries(ModelArray.AddVolumeControl, self.constants.audio_path) - rebuild_required = True + self.add_audio_patch() - if rebuild_required is True: - self.rebuild_snapshot() - - def unpatch_root_vol(self): - print("- Reverting to last signed APFS snapshot") - self.elevated(["bless", "--mount", self.mount_location, "--bootefi", "--last-sealed-snapshot"], stdout=subprocess.PIPE).stdout.decode().strip().encode() - - def rebuild_snapshot(self): - if self.constants.gui_mode is False: - input("Press [ENTER] to continue with cache rebuild") - print("- Rebuilding Kernel Cache (This may take some time)") - result = self.elevated(["kmutil", "install", "--volume-root", self.mount_location, "--update-all"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - - if result.returncode != 0: - self.success_status = False - print("- Unable to build new kernel cache") - print("\nPlease report this to Github") - print("Reason for Patch Failure:") - print(result.stdout.decode()) - print("") - else: - self.success_status = True - print("- Successfully built new kernel cache") - if self.constants.gui_mode is False: - input("Press [ENTER] to continue with snapshotting") - print("- Creating new APFS snapshot") - self.elevated(["bless", "--folder", f"{self.mount_location}/System/Library/CoreServices", "--bootefi", "--create-snapshot"], stdout=subprocess.PIPE).stdout.decode().strip().encode() - - def unmount_drive(self): - print("- Unmounting Root Volume (Don't worry if this fails)") - self.elevated(["diskutil", "unmount", self.root_mount_path], stdout=subprocess.PIPE).stdout.decode().strip().encode() - - def check_status(self): - nvram_dump = plistlib.loads(subprocess.run("nvram -x -p".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()) - try: - self.sip_status = nvram_dump["csr-active-config"] - except KeyError: - self.sip_status = b"\x00\x00\x00\x00" - - self.smb_model: str = subprocess.run("nvram 94B73556-2197-4702-82A8-3E1337DAFBFB:HardwareModel ".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode() - if not self.smb_model.startswith("nvram: Error getting variable"): - self.smb_model = [line.strip().split(":HardwareModel ", 1)[1] for line in self.smb_model.split("\n") if line.strip().startswith("94B73556-2197-4702-82A8-3E1337DAFBFB:")][0] - if self.smb_model.startswith("j137"): - self.smb_status = True - else: - self.smb_status = False - else: - self.smb_status = False - self.fv_status = True - if self.constants.recovery_status == False: - self.fv_status: str = subprocess.run("fdesetup status".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode() - if self.fv_status.startswith("FileVault is Off"): - self.fv_status = False - else: - # Assume FileVault is off for Recovery purposes - self.fv_status = False - self.csr_decode(False) + self.rebuild_snapshot() def check_files(self): if Path(self.constants.payload_apple_root_path).exists(): @@ -464,79 +336,149 @@ class PatchSysVolume: print("- Download failed, please verify the below link works:") print(f"{self.constants.url_apple_binaries}{self.constants.payload_version}") - def start_patch(self): - # Check SIP - # self.check_files() - if self.constants.custom_model is not None: - print("Root Patching must be done on target machine!") - elif self.model in ModelArray.NoRootPatch11 and self.constants.assume_legacy is False: - print("Root Patching not required for this machine!") - elif self.model not in ModelArray.SupportedSMBIOS11 and self.constants.assume_legacy is False: - print("Cannot run on this machine, model is unsupported!") - elif self.constants.detected_os != self.constants.big_sur: - print("Cannot run on this OS, requires macOS 11!") + + def detect_gpus(self): + igpu_vendor, igpu_device, igpu_acpi = DeviceProbe.pci_probe().gpu_probe("IGPU") + dgpu_vendor, dgpu_device, dgpu_acpi = DeviceProbe.pci_probe().gpu_probe("GFX0") + if dgpu_vendor: + print(f"- Found GFX0: {dgpu_vendor}:{dgpu_device}") + if dgpu_vendor == self.constants.pci_nvidia: + if dgpu_device in PCIIDArray.nvidia_ids().tesla_ids or dgpu_device in PCIIDArray.nvidia_ids().fermi_ids: + if self.constants.detected_os > self.constants.catalina: + self.nvidia_legacy = True + self.amfi_must_disable = True + elif dgpu_vendor == self.constants.pci_amd_ati: + if dgpu_device in PCIIDArray.amd_ids().terascale_1_ids: + if self.constants.detected_os > self.constants.catalina: + self.amd_ts1 = True + self.amfi_must_disable = True + # TODO: Enable TS2 support + elif dgpu_device in PCIIDArray.amd_ids().terascale_2_ids: + if self.constants.detected_os > self.constants.catalina: + self.amd_ts2 = True + self.amfi_must_disable = True + if igpu_vendor: + print(f"- Found IGPU: {igpu_vendor}:{igpu_device}") + if igpu_vendor == self.constants.pci_intel: + if igpu_device in PCIIDArray.intel_ids().iron_ids: + if self.constants.detected_os > self.constants.catalina: + self.iron_gpu = True + self.amfi_must_disable = True + elif igpu_device in PCIIDArray.intel_ids().sandy_ids: + if self.constants.detected_os > self.constants.catalina: + self.sandy_gpu = True + self.amfi_must_disable = True + # TODO: Re-enable when Accel Patches are ready + #elif igpu_device in PCIIDArray.intel_ids().ivy_ids: + # if self.constants.detected_os > self.constants.big_sur: + # self.ivy_gpu = True + elif igpu_vendor == self.constants.pci_nvidia: + if self.constants.detected_os > self.constants.catalina: + self.nvidia_legacy = True + self.amfi_must_disable = True + + def detect_patch_set(self): + self.detect_gpus() + if self.model in ModelArray.LegacyBrightness: + if self.constants.detected_os > self.constants.catalina: + self.brightness_legacy = True + + if self.model in ["iMac7,1", "iMac8,1"]: + if self.constants.detected_os > self.constants.catalina: + self.legacy_audio = True + + Utilities.cls() + print("The following patches will be applied:") + if self.nvidia_legacy is True: + print("- Add Legacy Nvidia Tesla Graphics Patch") + elif self.amd_ts1 is True: + print("- Add Legacy ATI TeraScale 1 Graphics Patch") + elif self.amd_ts2 is True: + print("- Add Legacy ATI TeraScale 2 Graphics Patch") + if self.iron_gpu is True: + print("- Add Legacy Intel IronLake Graphics Patch") + elif self.sandy_gpu is True: + print("- Add Legacy Intel Sandy Bridge Graphics Patch") + elif self.ivy_gpu is True: + print("- Add Legacy Intel Ivy Bridge Graphics Patch") + if self.brightness_legacy is True: + print("- Add Legacy Brightness Control") + if self.legacy_audio is True: + print("- Add legacy Audio Control") + + if self.nvidia_legacy is False and \ + self.amd_ts1 is False and \ + self.amd_ts2 is False and \ + self.iron_gpu is False and \ + self.sandy_gpu is False and \ + self.ivy_gpu is False and \ + self.brightness_legacy is False and \ + self.legacy_audio is False: + self.no_patch = True else: - self.check_status() - Utilities.cls() - if (self.sip_patch_status is False) and (self.smb_status is False): - print("- Detected SIP and SecureBootModel are disabled, continuing") - if self.constants.gui_mode is False: - input("\nPress [ENTER] to continue") + self.no_patch = False + + def verify_patch_allowed(self): + self.sip_enabled, self.sbm_enabled, self.amfi_enabled, self.fv_enabled = Utilities.patching_status() + if self.sip_enabled is True: + print("\nCannot patch!!! Please disable SIP!!!") + print("Disable SIP in Patcher Settings and Rebuild OpenCore") + print("For Hackintoshes, set SIP to EF0F0000") + if self.sbm_enabled is True: + print("\nCannot patch!!! Please disable SecureBootModel!!!") + print("Disable SecureBootModel in Patcher Settings and Rebuild OpenCore") + print("For Hackintoshes, set SecureBootModel to Disabled") + if self.fv_enabled is True: + print("\nCannot patch!!! Please disable FileVault!!!") + print("Go to System Preferences -> Security and disable FileVault") + + if self.amfi_enabled is True and self.amfi_must_disable is True: + print("\nCannot patch!!! Please disable AMFI!!!") + print("For Hackintoshes, please add amfi_getOut_of_my_way=0x1 to boot-args") + + if self.amfi_must_disable is True: + if self.sip_enabled is True or \ + self.sbm_enabled is True or \ + self.amfi_enabled is True or \ + self.fv_enabled is True: + return False + else: + return True + else: + if self.sip_enabled is True or \ + self.sbm_enabled is True or \ + self.fv_enabled is True: + return False + else: + return True + + # Entry Function + def start_patch(self): + print("- Starting Patch Process") + print(f"- Determinging Required Patch set for Darwin {self.constants.detected_os}") + self.detect_patch_set() + if self.no_patch is False: + change_menu = input("Would you like to continue with Root Volume Patching?(y/n): ") + else: + change_menu = None + print("- No Root Patches required for your machine!") + input("\nPress [ENTER] to return to the main menu: ") + if change_menu in ["y", "Y"]: + print("- Continuing with Patching") + print("- Verifying whether Root Patching possible") + if self.verify_patch_allowed() is True: + print("- Patcher is capable of patching") self.check_files() - if self.constants.payload_apple_root_path.exists(): - if not self.find_mount_root_vol(True): - return - self.unmount_drive() - print("- Patching complete") - if self.success_status is True: - print("\nPlease reboot the machine for patches to take effect") - else: - print("\nPlease reboot the machine to avoid potential issues rerunning the patcher") - if self.sip_patch_status is True: - print("SIP set incorrectly, cannot patch on this machine!") - print("Please disable SIP and SecureBootModel in Patcher Settings") - self.csr_decode(True) - print("") - if self.smb_status is True: - print("SecureBootModel set incorrectly, unable to patch!") - print("Please disable SecureBootModel in Patcher Settings") - print("") - if self.fv_status is True: - print("FileVault enabled, unable to patch!") - print("Please disable FileVault in System Preferences") - print("") - if self.constants.gui_mode is False: - input("Press [Enter] to go exit.") + self.find_mount_root_vol(True) + else: + input("\nPress [ENTER] to return to the main menu: ") + + else: + print("- Returning to main menu") def start_unpatch(self): - if self.constants.custom_model is not None: - print("Unpatching must be done on target machine!") - elif self.constants.detected_os != self.constants.big_sur: - print("Cannot run on this OS, requires macOS 11!") - else: - self.check_status() - Utilities.cls() - if (self.sip_patch_status is False) and (self.smb_status is False): - print("- Detected SIP and SecureBootModel are disabled, continuing") - if self.constants.gui_mode is False: - input("\nPress [ENTER] to continue") - if not self.find_mount_root_vol(False): - return - self.unmount_drive() - print("- Unpatching complete") - print("\nPlease reboot the machine for patches to take effect") - if self.sip_patch_status is True: - print("SIP set incorrectly, cannot unpatch on this machine!") - print("Please disable SIP and SecureBootModel in Patcher Settings") - self.csr_decode(True) - print("") - if self.smb_status is True: - print("SecureBootModel set incorrectly, unable to unpatch!") - print("Please disable SecureBootModel in Patcher Settings") - print("") - if self.fv_status is True: - print("FileVault enabled, unable to unpatch!") - print("Please disable FileVault in System Preferences") - print("") - if self.constants.gui_mode is False: - input("Press [Enter] to go exit.") + print("- Starting Unpatch Process") + if self.verify_patch_allowed() is True: + self.find_mount_root_vol(False) + input("\nPress [ENTER] to return to the main menu") + diff --git a/payloads/Config/config.plist b/payloads/Config/config.plist index 08e620f82..c92fb9dc8 100644 --- a/payloads/Config/config.plist +++ b/payloads/Config/config.plist @@ -1218,7 +1218,7 @@ SystemAudioVolume Rg== boot-args - keepsyms=1 debug=0x100 -no_compat_check -lilubetaall + keepsyms=1 debug=0x100 -lilubetaall csr-active-config AAAAAA==