Merge pull request #282 from dortania/syspatch-monterey

Refactor SysPatch for wider OS support
This commit is contained in:
Mykola Grymalyuk
2021-06-09 19:24:34 -06:00
committed by GitHub
4 changed files with 366 additions and 399 deletions

View File

@@ -119,11 +119,11 @@ system_profiler SPHardwareDataType | grep 'Model Identifier'
menu = Utilities.TUIMenu(title, "Please select an option: ", auto_number=True, top_level=True) menu = Utilities.TUIMenu(title, "Please select an option: ", auto_number=True, top_level=True)
options = [ 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 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"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"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"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"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"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], [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): def PatchVolume(self):
Utilities.cls() Utilities.cls()
Utilities.header(["Patching System Volume"]) 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 - Graphics Acceleration for non-Metal GPUs
- Nvidia: Tesla - Fermi (8000-500 series) - Nvidia: Tesla - Fermi (8000-500 series)
- Intel: Ironlake - Sandy Bridge - 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 - Audio support for iMac7,1 and iMac8,1
WARNING: Root Volume Patching is still in active development, please WARNING: Root Volume Patching is still in active development, please
@@ -168,7 +168,30 @@ Supported Options:
1. Patch System Volume 1. Patch System Volume
2. Unpatch System Volume (Experimental) 2. Unpatch System Volume (Experimental)
B. Exit 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?: ") change_menu = input("Patch System Volume?: ")
if change_menu == "1": if change_menu == "1":
SysPatch.PatchSysVolume(self.constants.custom_model or self.current_model, self.constants).start_patch() SysPatch.PatchSysVolume(self.constants.custom_model or self.current_model, self.constants).start_patch()
@@ -184,7 +207,6 @@ B. Exit
title = [ title = [
f"OpenCore Legacy Patcher v{self.constants.patcher_version}", f"OpenCore Legacy Patcher v{self.constants.patcher_version}",
f"Selected Model: {self.constants.custom_model or self.current_model}", 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: if (self.constants.custom_model or self.current_model) not in ModelArray.SupportedSMBIOS and self.constants.allow_oc_everywhere is False:

View File

@@ -1244,6 +1244,9 @@ AddIntelGen3Accel = [
"AppleIntelHD4000GraphicsGLDriver.bundle", "AppleIntelHD4000GraphicsGLDriver.bundle",
"AppleIntelHD4000GraphicsMTLDriver.bundle", "AppleIntelHD4000GraphicsMTLDriver.bundle",
"AppleIntelHD4000GraphicsVADriver.bundle", "AppleIntelHD4000GraphicsVADriver.bundle",
"IOSurface.kext",
"IOGPUFamily.kext",
"IOAcceleratorFamily2.kext",
] ]
AddGeneralAccel = [ AddGeneralAccel = [

View File

@@ -20,17 +20,29 @@ class PatchSysVolume:
def __init__(self, model, versions): def __init__(self, model, versions):
self.model = model self.model = model
self.constants: Constants.Constants = versions self.constants: Constants.Constants = versions
self.sip_patch_status = True
self.root_mount_path = None 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.detected_os > self.constants.catalina:
if self.constants.recovery_status is True: # Big Sur and newer use APFS snapshots
if not Path("/Volumes/mnt1").exists:
self.elevated(["mkdir", "/Volumes/mnt1"], stdout=subprocess.PIPE).stdout.decode().strip().encode()
self.mount_location = "/Volumes/mnt1"
else:
self.mount_location = "/System/Volumes/Update/mnt1" self.mount_location = "/System/Volumes/Update/mnt1"
else:
self.mount_location = "/"
self.mount_extensions = f"{self.mount_location}/System/Library/Extensions" self.mount_extensions = f"{self.mount_location}/System/Library/Extensions"
self.mount_frameworks = f"{self.mount_location}/System/Library/Frameworks" self.mount_frameworks = f"{self.mount_location}/System/Library/Frameworks"
self.mount_lauchd = f"{self.mount_location}/System/Library/LaunchDaemons" self.mount_lauchd = f"{self.mount_location}/System/Library/LaunchDaemons"
@@ -42,130 +54,9 @@ class PatchSysVolume:
else: else:
return subprocess.run(["sudo"] + [args[0][0]] + args[0][1:], **kwargs) 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): def find_mount_root_vol(self, patch):
if self.constants.recovery_status is True: self.root_mount_path = Utilities.get_disk_path()
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"]
if self.root_mount_path.startswith("disk"): 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}") print(f"- Found Root Volume at: {self.root_mount_path}")
if Path(self.mount_extensions).exists(): if Path(self.mount_extensions).exists():
print("- Root Volume is already mounted") print("- Root Volume is already mounted")
@@ -175,14 +66,6 @@ class PatchSysVolume:
else: else:
self.unpatch_root_vol() self.unpatch_root_vol()
return True 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: else:
print("- Mounting drive as writable in OS") 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() self.elevated(["mount", "-o", "nobrowse", "-t", "apfs", f"/dev/{self.root_mount_path}", self.mount_location], stdout=subprocess.PIPE).stdout.decode().strip().encode()
@@ -197,10 +80,46 @@ class PatchSysVolume:
else: else:
print("- Failed to mount the Root Volume") print("- Failed to mount the Root Volume")
print("- Recommend rebooting the machine and trying to patch again") print("- Recommend rebooting the machine and trying to patch again")
input("- Press [ENTER] to exit") input("- Press [ENTER] to exit: ")
else: else:
print("- Could not find root volume") 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): def delete_old_binaries(self, vendor_patch):
for delete_current_kext in vendor_patch: for delete_current_kext in vendor_patch:
@@ -223,90 +142,62 @@ class PatchSysVolume:
self.elevated(["chown", "-Rf", "root:wheel", f"{self.mount_extensions}/{add_current_kext}"], stdout=subprocess.PIPE).stdout.decode().strip().encode() 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): def add_brightness_patch(self):
print("- Merging legacy Brightness Control Patches")
self.delete_old_binaries(ModelArray.DeleteBrightness) self.delete_old_binaries(ModelArray.DeleteBrightness)
self.add_new_binaries(ModelArray.AddBrightness, self.constants.legacy_brightness) 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(["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(["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() 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): def add_audio_patch(self):
igpu_vendor, igpu_device, igpu_acpi = DeviceProbe.pci_probe().gpu_probe("IGPU") self.delete_old_binaries(ModelArray.DeleteVolumeControl)
dgpu_vendor, dgpu_device, dgpu_acpi = DeviceProbe.pci_probe().gpu_probe("GFX0") self.add_new_binaries(ModelArray.AddVolumeControl, self.constants.audio_path)
if dgpu_vendor:
print(f"- Found GFX0: {dgpu_vendor}:{dgpu_device}") def gpu_accel_legacy_nvidia(self):
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.delete_old_binaries(ModelArray.DeleteNvidiaAccel11)
self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path)
self.add_new_binaries(ModelArray.AddNvidiaAccel11, self.constants.legacy_nvidia_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 def gpu_framebuffer_legacy_nvidia(self):
# elif dgpu_device in PCIIDArray.nvidia_ids().kepler_ids and self.constants.detected_os > self.constants.big_sur: self.add_new_binaries(ModelArray.AddNvidiaBrightness, self.constants.legacy_nvidia_path)
# print("- Merging legacy Nvidia Kepler Kexts and Bundles")
# self.add_new_binaries(ModelArray.AddNvidiaKeplerAccel11, self.constants.legacy_nvidia_kepler_path) def gpu_accel_legacy_ts1(self):
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.delete_old_binaries(ModelArray.DeleteAMDAccel11)
self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path)
self.add_new_binaries(ModelArray.AddAMDAccel11, self.constants.legacy_amd_path) self.add_new_binaries(ModelArray.AddAMDAccel11, self.constants.legacy_amd_path)
self.added_kexts = True
if self.model in ["MacBookPro8,2", "MacBookPro8,3"]: def gpu_accel_legacy_ts2(self):
# 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.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.AddGeneralAccel, self.constants.legacy_general_path)
self.add_new_binaries(ModelArray.AddAMDAccel11, self.constants.legacy_amd_path) self.add_new_binaries(ModelArray.AddAMDAccel11, self.constants.legacy_amd_path)
self.added_kexts = True
else: def gpu_framebuffer_legacy_amd(self):
print("- Cannot install Brightness Control, pleas ensure the dGPU is disabled via NVRAM") self.add_new_binaries(ModelArray.AddAMDBrightness, self.constants.legacy_amd_path)
if igpu_vendor:
print(f"- Found IGPU: {igpu_vendor}:{igpu_device}") def gpu_accel_legacy_ironlake(self):
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.delete_old_binaries(ModelArray.DeleteNvidiaAccel11)
self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path)
self.add_new_binaries(ModelArray.AddIntelGen1Accel, self.constants.legacy_intel_gen1_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: def gpu_framebuffer_legacy_ironlake(self):
print("- Merging legacy Intel 2nd Gen Kexts and Bundles") 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.delete_old_binaries(ModelArray.DeleteNvidiaAccel11)
self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path) self.add_new_binaries(ModelArray.AddGeneralAccel, self.constants.legacy_general_path)
self.add_new_binaries(ModelArray.AddIntelGen2Accel, self.constants.legacy_intel_gen2_path) self.add_new_binaries(ModelArray.AddIntelGen2Accel, self.constants.legacy_intel_gen2_path)
self.added_kexts = True
# TODO: Enable below code if macOS 12 drops support def gpu_framebuffer_legacy_sandybridge(self):
# elif igpu_device in PCIIDArray.intel_ids().ivy_ids: self.add_new_binaries(ModelArray.AddIntelGen2Accel, self.constants.legacy_intel_gen1_path)
# 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
if self.added_kexts == True: def gpu_framebuffer_ivybridge(self):
# Frameworks self.delete_old_binaries(ModelArray.DeleteAMDAccel11)
print("- Merging legacy Frameworks") 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() self.elevated(["ditto", self.constants.payload_apple_frameworks_path_accel, self.mount_frameworks], stdout=subprocess.PIPE).stdout.decode().strip().encode()
if self.model in ModelArray.LegacyBrightness: def gpu_accel_legacy_extended(self):
self.add_brightness_patch() 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()
# LaunchDaemons
if Path(self.mount_lauchd / Path("HiddHack.plist")).exists(): if Path(self.mount_lauchd / Path("HiddHack.plist")).exists():
print("- Removing legacy HiddHack") print("- Removing legacy HiddHack")
self.elevated(["rm", f"{self.mount_lauchd}/HiddHack.plist"], stdout=subprocess.PIPE).stdout.decode().strip().encode() self.elevated(["rm", f"{self.mount_lauchd}/HiddHack.plist"], stdout=subprocess.PIPE).stdout.decode().strip().encode()
@@ -314,111 +205,92 @@ class PatchSysVolume:
self.elevated(["ditto", self.constants.payload_apple_lauchd_path_accel, self.mount_lauchd], stdout=subprocess.PIPE).stdout.decode().strip().encode() 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(["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() self.elevated(["chown", "root:wheel", f"{self.mount_lauchd}/IOHID-Fixup.plist"], stdout=subprocess.PIPE).stdout.decode().strip().encode()
print("- Merging general legacy PrivateFrameworks")
# 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() 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 def gpu_accel_legacy_extended_ts2(self):
# print("- Enabling NSDefenestratorModeEnabled") print("- Merging TeraScale 2 legacy Frameworks")
# subprocess.run("defaults write -g NSDefenestratorModeEnabled -bool true".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode() self.elevated(["ditto", self.constants.payload_apple_frameworks_path_accel_ts2, self.mount_frameworks], stdout=subprocess.PIPE).stdout.decode().strip().encode()
else: print("- Merging TeraScale 2 PrivateFrameworks")
print("- No Acceleration Kexts were installed, skipping remaining acceleration patches") 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): def patch_root_vol(self):
print(f"- Detecting patches for {self.model}") print(f"- Running patches for {self.model}")
rebuild_required = False # Graphics patches
# TODO: Create Backup of S*/L*/Extensions, Frameworks and PrivateFramework to easily revert changes if self.nvidia_legacy is True:
# APFS snapshotting seems to ignore System Volume changes inconsistently, would like a backup to avoid total brick print("- Installing legacy Nvidia Patches")
# Perhaps a basic py2 script to run in recovery to restore if self.constants.detected_os == self.constants.big_sur:
# Ensures no .DS_Stores got in print("- Detected Big Sur, installing Acceleration patches")
print("- Preparing Files") self.gpu_accel_legacy_nvidia()
self.elevated(["find", self.constants.payload_apple_root_path, "-name", "'.DS_Store'", "-delete"], stdout=subprocess.PIPE).stdout.decode().strip().encode() self.added_kexts = True
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")
else: else:
print("- Detected legacy GPU, attempting legacy acceleration patches") print("- Detected unsupported OS, installing Basic Framebuffer")
self.gpu_accel_patches_11() self.gpu_framebuffer_legacy_nvidia()
rebuild_required = True
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") print("- Fixing Volume Control Support")
self.delete_old_binaries(ModelArray.DeleteVolumeControl) self.add_audio_patch()
self.add_new_binaries(ModelArray.AddVolumeControl, self.constants.audio_path)
rebuild_required = True
if rebuild_required is True:
self.rebuild_snapshot() 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)
def check_files(self): def check_files(self):
if Path(self.constants.payload_apple_root_path).exists(): if Path(self.constants.payload_apple_root_path).exists():
print("- Found Apple Binaries") print("- Found Apple Binaries")
@@ -464,79 +336,149 @@ class PatchSysVolume:
print("- Download failed, please verify the below link works:") print("- Download failed, please verify the below link works:")
print(f"{self.constants.url_apple_binaries}{self.constants.payload_version}") print(f"{self.constants.url_apple_binaries}{self.constants.payload_version}")
def start_patch(self):
# Check SIP def detect_gpus(self):
# self.check_files() igpu_vendor, igpu_device, igpu_acpi = DeviceProbe.pci_probe().gpu_probe("IGPU")
if self.constants.custom_model is not None: dgpu_vendor, dgpu_device, dgpu_acpi = DeviceProbe.pci_probe().gpu_probe("GFX0")
print("Root Patching must be done on target machine!") if dgpu_vendor:
elif self.model in ModelArray.NoRootPatch11 and self.constants.assume_legacy is False: print(f"- Found GFX0: {dgpu_vendor}:{dgpu_device}")
print("Root Patching not required for this machine!") if dgpu_vendor == self.constants.pci_nvidia:
elif self.model not in ModelArray.SupportedSMBIOS11 and self.constants.assume_legacy is False: if dgpu_device in PCIIDArray.nvidia_ids().tesla_ids or dgpu_device in PCIIDArray.nvidia_ids().fermi_ids:
print("Cannot run on this machine, model is unsupported!") if self.constants.detected_os > self.constants.catalina:
elif self.constants.detected_os != self.constants.big_sur: self.nvidia_legacy = True
print("Cannot run on this OS, requires macOS 11!") self.amfi_must_disable = True
else: elif dgpu_vendor == self.constants.pci_amd_ati:
self.check_status() 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() Utilities.cls()
if (self.sip_patch_status is False) and (self.smb_status is False): print("The following patches will be applied:")
print("- Detected SIP and SecureBootModel are disabled, continuing") if self.nvidia_legacy is True:
if self.constants.gui_mode is False: print("- Add Legacy Nvidia Tesla Graphics Patch")
input("\nPress [ENTER] to continue") elif self.amd_ts1 is True:
self.check_files() print("- Add Legacy ATI TeraScale 1 Graphics Patch")
if self.constants.payload_apple_root_path.exists(): elif self.amd_ts2 is True:
if not self.find_mount_root_vol(True): print("- Add Legacy ATI TeraScale 2 Graphics Patch")
return if self.iron_gpu is True:
self.unmount_drive() print("- Add Legacy Intel IronLake Graphics Patch")
print("- Patching complete") elif self.sandy_gpu is True:
if self.success_status is True: print("- Add Legacy Intel Sandy Bridge Graphics Patch")
print("\nPlease reboot the machine for patches to take effect") 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: else:
print("\nPlease reboot the machine to avoid potential issues rerunning the patcher") self.no_patch = False
if self.sip_patch_status is True:
print("SIP set incorrectly, cannot patch on this machine!") def verify_patch_allowed(self):
print("Please disable SIP and SecureBootModel in Patcher Settings") self.sip_enabled, self.sbm_enabled, self.amfi_enabled, self.fv_enabled = Utilities.patching_status()
self.csr_decode(True) if self.sip_enabled is True:
print("") print("\nCannot patch!!! Please disable SIP!!!")
if self.smb_status is True: print("Disable SIP in Patcher Settings and Rebuild OpenCore")
print("SecureBootModel set incorrectly, unable to patch!") print("For Hackintoshes, set SIP to EF0F0000")
print("Please disable SecureBootModel in Patcher Settings") if self.sbm_enabled is True:
print("") print("\nCannot patch!!! Please disable SecureBootModel!!!")
if self.fv_status is True: print("Disable SecureBootModel in Patcher Settings and Rebuild OpenCore")
print("FileVault enabled, unable to patch!") print("For Hackintoshes, set SecureBootModel to Disabled")
print("Please disable FileVault in System Preferences") if self.fv_enabled is True:
print("") print("\nCannot patch!!! Please disable FileVault!!!")
if self.constants.gui_mode is False: print("Go to System Preferences -> Security and disable FileVault")
input("Press [Enter] to go exit.")
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()
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): def start_unpatch(self):
if self.constants.custom_model is not None: print("- Starting Unpatch Process")
print("Unpatching must be done on target machine!") if self.verify_patch_allowed() is True:
elif self.constants.detected_os != self.constants.big_sur: self.find_mount_root_vol(False)
print("Cannot run on this OS, requires macOS 11!") input("\nPress [ENTER] to return to the main menu")
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.")

View File

@@ -1218,7 +1218,7 @@
<key>SystemAudioVolume</key> <key>SystemAudioVolume</key>
<data>Rg==</data> <data>Rg==</data>
<key>boot-args</key> <key>boot-args</key>
<string>keepsyms=1 debug=0x100 -no_compat_check -lilubetaall</string> <string>keepsyms=1 debug=0x100 -lilubetaall</string>
<key>csr-active-config</key> <key>csr-active-config</key>
<data>AAAAAA==</data> <data>AAAAAA==</data>
</dict> </dict>