diff --git a/OpenCore-Patcher.command b/OpenCore-Patcher.command index 1b45b61bd..d1c235d6d 100755 --- a/OpenCore-Patcher.command +++ b/OpenCore-Patcher.command @@ -15,7 +15,7 @@ class OpenCoreLegacyPatcher: print("- Loading...") self.constants = constants.Constants() self.generate_base_data() - if arguments.arguments().check_cli() is False: + if utilities.check_cli_args() is None: self.main_menu() def generate_base_data(self): @@ -26,7 +26,7 @@ class OpenCoreLegacyPatcher: self.constants.recovery_status = utilities.check_recovery() self.computer = self.constants.computer defaults.generate_defaults.probe(self.computer.real_model, True, self.constants) - if arguments.arguments().check_cli() is True: + if utilities.check_cli_args() is not None: print("- Detected arguments, switching to CLI mode") self.constants.gui_mode = True # Assumes no user interaction is required self.constants.current_path = Path.cwd() diff --git a/resources/arguments.py b/resources/arguments.py index f5ebbc0c1..c2627f0d1 100644 --- a/resources/arguments.py +++ b/resources/arguments.py @@ -1,53 +1,12 @@ -import argparse import sys import subprocess -from resources import defaults, build +from resources import defaults, build, utilities, validation from data import example_data, model_array # Generic building args class arguments: def __init__(self): - parser = argparse.ArgumentParser() - parser.add_argument("--build", help="Build OpenCore", action="store_true", required=False) - parser.add_argument("--verbose", help="Enable verbose boot", action="store_true", required=False) - parser.add_argument("--debug_oc", help="Enable OpenCore DEBUG", action="store_true", required=False) - parser.add_argument("--debug_kext", help="Enable kext DEBUG", action="store_true", required=False) - parser.add_argument("--hide_picker", help="Hide OpenCore picker", action="store_true", required=False) - parser.add_argument("--disable_sip", help="Disable SIP", action="store_true", required=False) - parser.add_argument("--disable_smb", help="Disable SecureBootModel", action="store_true", required=False) - parser.add_argument("--vault", help="Enable OpenCore Vaulting", action="store_true", required=False) - parser.add_argument("--support_all", help="Allow OpenCore on natively supported Models", action="store_true", required=False) - parser.add_argument("--firewire", help="Enable FireWire Booting", action="store_true", required=False) - parser.add_argument("--nvme", help="Enable NVMe Booting", action="store_true", required=False) - parser.add_argument("--wlan", help="Enable Wake on WLAN support", action="store_true", required=False) - # parser.add_argument("--disable_amfi", help="Disable AMFI", action="store_true", required=False) - parser.add_argument("--moderate_smbios", help="Moderate SMBIOS Patching", action="store_true", required=False) - parser.add_argument("--moj_cat_accel", help="Allow Root Patching on Mojave and Catalina", action="store_true", required=False) - parser.add_argument("--disable_tb", help="Disable Thunderbolt on 2013-2014 MacBook Pros", action="store_true", required=False) - parser.add_argument("--force_surplus", help="Force SurPlus in all newer OSes", action="store_true", required=False) - - # Building args requiring value values (ie. --model iMac12,2) - parser.add_argument("--model", action="store", help="Set custom model", required=False) - parser.add_argument("--disk", action="store", help="Specifies disk to install to", required=False) - parser.add_argument("--smbios_spoof", action="store", help="Set SMBIOS patching mode", required=False) - - # sys_patch args - parser.add_argument("--patch_sys_vol", help="Patches root volume", action="store_true", required=False) - parser.add_argument("--unpatch_sys_vol", help="Unpatches root volume, EXPERIMENTAL", action="store_true", required=False) - - # validation args - parser.add_argument("--validate", help="Runs Validation Tests for CI", action="store_true", required=False) - self.args = parser.parse_args() - - def check_cli(self): - # If no core arguments are present, assume we're running in TUI - # build, patch_sys_vol, unpatch_sys_vol, validate - if not( - self.args.build or self.args.patch_sys_vol or self.args.unpatch_sys_vol or self.args.validate - ): - return False - else: - return True + self.args = utilities.check_cli_args() def parse_arguments(self, settings): if self.args.model: @@ -70,7 +29,7 @@ If you plan to create the USB for another machine, please select the "Change Mod print(f"- Install Disk set: {self.args.disk}") settings.disk = self.args.disk if self.args.validate: - self.validate(settings) + validation.validate(settings) if self.args.verbose: print("- Set verbose configuration") settings.verbose_debug = True @@ -146,74 +105,4 @@ If you plan to create the USB for another machine, please select the "Change Mod self.patch_vol() elif self.args.unpatch_sys_vol: print("- Set System Volume unpatching") - self.unpatch_vol() - - def validate(self, settings): - # Runs through ocvalidate to check for errors - - valid_dumps = [ - example_data.MacBookPro.MacBookPro92_Stock, - # example_data.MacBookPro.MacBookPro171_Stock, - # example_data.Macmini.Macmini91_Stock, - example_data.iMac.iMac81_Stock, - example_data.iMac.iMac112_Stock, - example_data.iMac.iMac122_Upgraded, - example_data.MacPro.MacPro31_Stock, - example_data.MacPro.MacPro31_Upgrade, - example_data.MacPro.MacPro31_Modern_AMD, - example_data.MacPro.MacPro31_Modern_Kepler, - example_data.MacPro.MacPro41_Upgrade, - example_data.MacPro.MacPro41_Modern_AMD, - example_data.MacPro.MacPro41_51__Flashed_Modern_AMD, - ] - settings.validate = True - def build_prebuilt(): - for model in model_array.SupportedSMBIOS: - print(f"Validating predefined model: {model}") - settings.custom_model = model - build.BuildOpenCore(settings.custom_model, settings).build_opencore() - result = subprocess.run([settings.ocvalidate_path, f"{settings.opencore_release_folder}/EFI/OC/config.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - if result.returncode != 0: - print("Error on build!") - print(result.stdout.decode()) - raise Exception(f"Validation failed for predefined model: {model}") - else: - print(f"Validation succeeded for predefined model: {model}") - - def build_dumps(): - for model in valid_dumps: - settings.computer = model - settings.custom_model = "" - print(f"Validating dumped model: {settings.computer.real_model}") - build.BuildOpenCore(settings.computer.real_model, settings).build_opencore() - result = subprocess.run([settings.ocvalidate_path, f"{settings.opencore_release_folder}/EFI/OC/config.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - if result.returncode != 0: - print("Error on build!") - print(result.stdout.decode()) - raise Exception(f"Validation failed for predefined model: {settings.computer.real_model}") - else: - print(f"Validation succeeded for predefined model: {settings.computer.real_model}") - - # First run is with default settings - build_prebuilt() - build_dumps() - # Second run, flip all settings - settings.verbose_debug = True - settings.opencore_debug = True - settings.opencore_build = "DEBUG" - settings.kext_debug = True - settings.showpicker = False - settings.sip_status = False - settings.secure_status = True - settings.firewire_boot = True - settings.nvme_boot = True - settings.enable_wake_on_wlan = True - settings.disable_tb = True - settings.force_surplus = True - build_prebuilt() - build_dumps() - - - - - + self.unpatch_vol() \ No newline at end of file diff --git a/resources/build.py b/resources/build.py index ea4e8664f..6c0f8cf93 100644 --- a/resources/build.py +++ b/resources/build.py @@ -649,7 +649,7 @@ class BuildOpenCore: print("- Enabling ShowPicker") self.config["Misc"]["Boot"]["ShowPicker"] = True else: - print("- Hiding picker and enabling PollAppleHotKeys") + print("- Hiding OpenCore picker") self.config["Misc"]["Boot"]["ShowPicker"] = False if self.constants.vault is True: print("- Setting Vault configuration") diff --git a/resources/mount_root.py b/resources/mount_root.py deleted file mode 100644 index 2759b03fc..000000000 --- a/resources/mount_root.py +++ /dev/null @@ -1,19 +0,0 @@ -# Logic for mounting root volume -from data import os_data -from resources import utilities -import plistlib -import subprocess - -def mount_root_volume(os_version, root_disk): - - if os_version >= os_data.os_data.big_sur: - mount_location = "/System/Volumes/Update/mnt1/" - else: - mount_location = "/" - -def find_root_volume(): - root_partition_info = plistlib.loads(subprocess.run("diskutil info -plist /".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()) - root_mount_path = root_partition_info["DeviceIdentifier"] - root_mount_path = root_mount_path[:-2] if root_mount_path.count("s") > 1 else root_mount_path - return root_mount_path - diff --git a/resources/sys_patch.py b/resources/sys_patch.py index ae130929c..f4c002be7 100644 --- a/resources/sys_patch.py +++ b/resources/sys_patch.py @@ -45,9 +45,6 @@ class PatchSysVolume: self.validate = False self.supports_metal = False - # if (Path.home() / "Desktop/OCLP-Test/").exists: - # self.mount_location = Path.home() / "Desktop/OCLP-Test" - # self.validate = True if self.constants.detected_os > self.constants.catalina: # Big Sur and newer use APFS snapshots self.mount_location = "/System/Volumes/Update/mnt1" @@ -61,18 +58,12 @@ class PatchSysVolume: self.mount_libexec = f"{self.mount_location}/usr/libexec" self.mount_extensions_mux = f"{self.mount_location}/System/Library/Extensions/AppleGraphicsControl.kext/Contents/PlugIns/" - def elevated(self, *args, **kwargs) -> subprocess.CompletedProcess: - if os.getuid() == 0 or self.constants.gui_mode is True: - return subprocess.run(*args, **kwargs) - else: - return subprocess.run(["sudo"] + [args[0][0]] + args[0][1:], **kwargs) - def find_mount_root_vol(self, patch): self.root_mount_path = utilities.get_disk_path() if self.root_mount_path.startswith("disk"): if self.constants.detected_os == self.constants.catalina and self.validate is False: print("- Mounting Catalina Root Volume as writable") - self.elevated(["mount", "-uw", f"{self.mount_location}/"], stdout=subprocess.PIPE).stdout.decode().strip().encode() + utilities.elevated(["mount", "-uw", f"{self.mount_location}/"], stdout=subprocess.PIPE).stdout.decode().strip().encode() print(f"- Found Root Volume at: {self.root_mount_path}") if Path(self.mount_extensions).exists(): print("- Root Volume is already mounted") @@ -87,7 +78,7 @@ class PatchSysVolume: else: if self.constants.detected_os > self.constants.catalina: print("- Mounting APFS Snapshot as writable") - self.elevated(["mount", "-o", "nobrowse", "-t", "apfs", f"/dev/{self.root_mount_path}", self.mount_location], stdout=subprocess.PIPE).stdout.decode().strip().encode() + utilities.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: @@ -175,21 +166,21 @@ class PatchSysVolume: print(f"- Found {location_zip}") print(f"- Unzipping {location_zip}") - utilities.process_status(self.elevated(["unzip", location_zip_path, "-d", copy_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["unzip", location_zip_path, "-d", copy_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) if location_old_path.exists(): print(f"- Renaming {location}") - utilities.process_status(self.elevated(["mv", location_old_path, f"{location_old_path}-Patched"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["mv", location_old_path, f"{location_old_path}-Patched"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) print(f"- Renaming {location}-Backup") - utilities.process_status(self.elevated(["mv", f"{location_old_path}-Backup", location_old_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["mv", f"{location_old_path}-Backup", location_old_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) print(f"- Removing {location_old_path}-Patched") - utilities.process_status(self.elevated(["rm", "-r", f"{location_old_path}-Patched"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["rm", "-r", f"{location_old_path}-Patched"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) # ditto will create a '__MACOSX' folder # print("- Removing __MACOSX folder") - # utilities.process_status(self.elevated(["rm", "-r", f"{copy_path}/__MACOSX"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + # utilities.process_status(utilities.elevated(["rm", "-r", f"{copy_path}/__MACOSX"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) else: print(f"- Failed to find {location_zip}, unable to unpatch") @@ -201,7 +192,7 @@ class PatchSysVolume: def unpatch_root_vol(self): if self.constants.detected_os > self.constants.catalina: print("- Reverting to last signed APFS snapshot") - result = self.elevated(["bless", "--mount", self.mount_location, "--bootefi", "--last-sealed-snapshot"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + result = utilities.elevated(["bless", "--mount", self.mount_location, "--bootefi", "--last-sealed-snapshot"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if result.returncode != 0: print("- Unable to revert root volume patches") print("Reason for unpatch Failure:") @@ -219,9 +210,9 @@ class PatchSysVolume: input("Press [ENTER] to continue with cache rebuild: ") print("- Rebuilding Kernel Cache (This may take some time)") if self.constants.detected_os > self.constants.catalina: - result = self.elevated(["kmutil", "install", "--volume-root", self.mount_location, "--update-all"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + result = utilities.elevated(["kmutil", "install", "--volume-root", self.mount_location, "--update-all"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) else: - result = self.elevated(["kextcache", "-i", f"{self.mount_location}/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + result = utilities.elevated(["kextcache", "-i", f"{self.mount_location}/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # kextcache always returns 0, even if it fails # Check the output for 'KernelCache ID' to see if the cache was successfully rebuilt @@ -245,14 +236,14 @@ class PatchSysVolume: input("Press [ENTER] to continue with kernel and dyld cache merging") if self.constants.detected_os > self.constants.catalina: 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() + utilities.elevated(["bless", "--folder", f"{self.mount_location}/System/Library/CoreServices", "--bootefi", "--create-snapshot"], stdout=subprocess.PIPE).stdout.decode().strip().encode() self.unmount_drive() else: if self.constants.detected_os == self.constants.catalina: print("- Merging kernel cache") - utilities.process_status(self.elevated(["kcditto"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["kcditto"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) print("- Merging dyld cache") - utilities.process_status(self.elevated(["update_dyld_shared_cache", "-root", f"{self.mount_location}/"])) + utilities.process_status(utilities.elevated(["update_dyld_shared_cache", "-root", f"{self.mount_location}/"])) print("- Patching complete") print("\nPlease reboot the machine for patches to take effect") if self.amd_ts2 is True and self.constants.allow_ts2_accel is True: @@ -267,14 +258,14 @@ set million colour before rebooting""" 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() - + utilities.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: delete_path = Path(self.mount_extensions) / Path(delete_current_kext) if Path(delete_path).exists(): print(f"- Deleting {delete_current_kext}") - utilities.process_status(self.elevated(["rm", "-R", delete_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["rm", "-R", delete_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) else: print(f"- Couldn't find {delete_current_kext}, skipping") @@ -283,18 +274,19 @@ set million colour before rebooting""" existing_path = Path(self.mount_extensions) / Path(add_current_kext) if Path(existing_path).exists(): print(f"- Found conflicting kext, Deleting Root Volume's {add_current_kext}") - utilities.process_status(self.elevated(["rm", "-R", existing_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["rm", "-R", existing_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) print(f"- Adding {add_current_kext}") - utilities.process_status(self.elevated(["cp", "-R", f"{vendor_location}/{add_current_kext}", self.mount_extensions], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) - utilities.process_status(self.elevated(["chmod", "-Rf", "755", f"{self.mount_extensions}/{add_current_kext}"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) - utilities.process_status(self.elevated(["chown", "-Rf", "root:wheel", f"{self.mount_extensions}/{add_current_kext}"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["cp", "-R", f"{vendor_location}/{add_current_kext}", self.mount_extensions], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["chmod", "-Rf", "755", f"{self.mount_extensions}/{add_current_kext}"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["chown", "-Rf", "root:wheel", f"{self.mount_extensions}/{add_current_kext}"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + def add_brightness_patch(self): self.delete_old_binaries(sys_patch_data.DeleteBrightness) self.add_new_binaries(sys_patch_data.AddBrightness, self.constants.legacy_brightness) - self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_private_frameworks_path_brightness}/", self.mount_private_frameworks], stdout=subprocess.PIPE) - utilities.process_status(self.elevated(["chmod", "-Rf", "755", f"{self.mount_private_frameworks}/DisplayServices.framework"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) - utilities.process_status(self.elevated(["chown", "-Rf", "root:wheel", f"{self.mount_private_frameworks}/DisplayServices.framework"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_private_frameworks_path_brightness}/", self.mount_private_frameworks], stdout=subprocess.PIPE) + utilities.process_status(utilities.elevated(["chmod", "-Rf", "755", f"{self.mount_private_frameworks}/DisplayServices.framework"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["chown", "-Rf", "root:wheel", f"{self.mount_private_frameworks}/DisplayServices.framework"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) def add_audio_patch(self): if self.model in ["iMac7,1", "iMac8,1"]: @@ -305,18 +297,18 @@ set million colour before rebooting""" def add_wifi_patch(self): print("- Merging Wireless CoreSerices patches") - self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.legacy_wifi_coreservices}/", self.mount_coreservices], stdout=subprocess.PIPE) - utilities.process_status(self.elevated(["chmod", "-Rf", "755", f"{self.mount_coreservices}/WiFiAgent.app"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) - utilities.process_status(self.elevated(["chown", "-Rf", "root:wheel", f"{self.mount_coreservices}/WiFiAgent.app"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.legacy_wifi_coreservices}/", self.mount_coreservices], stdout=subprocess.PIPE) + utilities.process_status(utilities.elevated(["chmod", "-Rf", "755", f"{self.mount_coreservices}/WiFiAgent.app"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["chown", "-Rf", "root:wheel", f"{self.mount_coreservices}/WiFiAgent.app"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) print("- Merging Wireless usr/libexec patches") - self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.legacy_wifi_libexec}/", self.mount_libexec], stdout=subprocess.PIPE) - utilities.process_status(self.elevated(["chmod", "755", f"{self.mount_libexec}/airportd"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) - utilities.process_status(self.elevated(["chown", "root:wheel", f"{self.mount_libexec}/airportd"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.legacy_wifi_libexec}/", self.mount_libexec], stdout=subprocess.PIPE) + utilities.process_status(utilities.elevated(["chmod", "755", f"{self.mount_libexec}/airportd"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["chown", "root:wheel", f"{self.mount_libexec}/airportd"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) def add_legacy_mux_patch(self): self.delete_old_binaries(sys_patch_data.DeleteDemux) print("- Merging Legacy Mux Kext patches") - utilities.process_status(self.elevated(["cp", "-R", f"{self.constants.legacy_mux_path}/AppleMuxControl.kext", self.mount_extensions_mux], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["cp", "-R", f"{self.constants.legacy_mux_path}/AppleMuxControl.kext", self.mount_extensions_mux], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) def gpu_accel_legacy(self): if self.constants.detected_os == self.constants.mojave: @@ -415,9 +407,9 @@ set million colour before rebooting""" print("- Fixing Acceleration in CoreMedia") utilities.process_status(subprocess.run(["defaults", "write", "com.apple.coremedia", "hardwareVideoDecoder", "-string", "enable"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) print("- Merging Ivy Bridge Frameworks") - self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_frameworks_path_accel_ivy}/", self.mount_frameworks], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_frameworks_path_accel_ivy}/", self.mount_frameworks], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) print("- Merging Ivy Bridge PrivateFrameworks") - self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_private_frameworks_path_accel_ivy}/", self.mount_private_frameworks], stdout=subprocess.PIPE) + utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_private_frameworks_path_accel_ivy}/", self.mount_private_frameworks], stdout=subprocess.PIPE) else: print("- Installing basic Ivy Bridge Kext patches for generic OS") self.add_new_binaries(sys_patch_data.AddIntelGen3Accel, self.constants.legacy_intel_gen3_path) @@ -432,24 +424,24 @@ set million colour before rebooting""" def gpu_accel_legacy_extended(self): print("- Merging general legacy Frameworks") - self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_frameworks_path_accel}/", self.mount_frameworks], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_frameworks_path_accel}/", self.mount_frameworks], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if self.constants.detected_os > self.constants.big_sur: print("- Merging Monterey WebKit patch") - self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_frameworks_path_accel_ivy}/", self.mount_frameworks], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_frameworks_path_accel_ivy}/", self.mount_frameworks], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) print("- Merging general legacy PrivateFrameworks") - self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_private_frameworks_path_accel}/", self.mount_private_frameworks], stdout=subprocess.PIPE) + utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_private_frameworks_path_accel}/", self.mount_private_frameworks], stdout=subprocess.PIPE) if self.constants.detected_os > self.constants.catalina: print("- Adding IOHID-Fixup.plist") utilities.process_status( - self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_lauchd_path_accel}/", self.mount_lauchd], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_lauchd_path_accel}/", self.mount_lauchd], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) ) - utilities.process_status(self.elevated(["chmod", "755", f"{self.mount_lauchd}/IOHID-Fixup.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) - utilities.process_status(self.elevated(["chown", "root:wheel", f"{self.mount_lauchd}/IOHID-Fixup.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["chmod", "755", f"{self.mount_lauchd}/IOHID-Fixup.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) + utilities.process_status(utilities.elevated(["chown", "root:wheel", f"{self.mount_lauchd}/IOHID-Fixup.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) else: print("- Disabling Library Validation") utilities.process_status( - self.elevated( + utilities.elevated( ["defaults", "write", "/Library/Preferences/com.apple.security.libraryvalidation.plist", "DisableLibraryValidation", "-bool", "true"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -458,10 +450,10 @@ set million colour before rebooting""" def gpu_accel_legacy_extended_ts2(self): print("- Merging TeraScale 2 legacy Frameworks") - self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_frameworks_path_accel_ts2}/", self.mount_frameworks], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_frameworks_path_accel_ts2}/", self.mount_frameworks], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) print("- Merging TeraScale 2 PrivateFrameworks") - self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_private_frameworks_path_accel_ts2}/", self.mount_private_frameworks], stdout=subprocess.PIPE) + utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_private_frameworks_path_accel_ts2}/", self.mount_private_frameworks], stdout=subprocess.PIPE) if self.validate is False: print("- Fixing Acceleration in CMIO") utilities.process_status(subprocess.run(["defaults", "write", "com.apple.cmio", "CMIO_Unit_Input_ASC.DoNotUseOpenCL", "-bool", "true"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)) diff --git a/resources/utilities.py b/resources/utilities.py index 75cb4e935..15cef94a3 100644 --- a/resources/utilities.py +++ b/resources/utilities.py @@ -7,9 +7,9 @@ import os import plistlib import subprocess from pathlib import Path -import re import os import binascii +import argparse try: import requests @@ -298,9 +298,55 @@ def download_file(link, location): chunk = file.read(1024 * 1024 * 16) return checksum +def elevated(*args, **kwargs) -> subprocess.CompletedProcess: + # When runnign through our GUI, we run as root, however we do not get uid 0 + # Best to assume CLI is running as root + if os.getuid() == 0 or check_cli_args() is not None: + return subprocess.run(*args, **kwargs) + else: + return subprocess.run(["sudo"] + [args[0][0]] + args[0][1:], **kwargs) +def check_cli_args(): + parser = argparse.ArgumentParser() + parser.add_argument("--build", help="Build OpenCore", action="store_true", required=False) + parser.add_argument("--verbose", help="Enable verbose boot", action="store_true", required=False) + parser.add_argument("--debug_oc", help="Enable OpenCore DEBUG", action="store_true", required=False) + parser.add_argument("--debug_kext", help="Enable kext DEBUG", action="store_true", required=False) + parser.add_argument("--hide_picker", help="Hide OpenCore picker", action="store_true", required=False) + parser.add_argument("--disable_sip", help="Disable SIP", action="store_true", required=False) + parser.add_argument("--disable_smb", help="Disable SecureBootModel", action="store_true", required=False) + parser.add_argument("--vault", help="Enable OpenCore Vaulting", action="store_true", required=False) + parser.add_argument("--support_all", help="Allow OpenCore on natively supported Models", action="store_true", required=False) + parser.add_argument("--firewire", help="Enable FireWire Booting", action="store_true", required=False) + parser.add_argument("--nvme", help="Enable NVMe Booting", action="store_true", required=False) + parser.add_argument("--wlan", help="Enable Wake on WLAN support", action="store_true", required=False) + # parser.add_argument("--disable_amfi", help="Disable AMFI", action="store_true", required=False) + parser.add_argument("--moderate_smbios", help="Moderate SMBIOS Patching", action="store_true", required=False) + parser.add_argument("--moj_cat_accel", help="Allow Root Patching on Mojave and Catalina", action="store_true", required=False) + parser.add_argument("--disable_tb", help="Disable Thunderbolt on 2013-2014 MacBook Pros", action="store_true", required=False) + parser.add_argument("--force_surplus", help="Force SurPlus in all newer OSes", action="store_true", required=False) + # Building args requiring value values (ie. --model iMac12,2) + parser.add_argument("--model", action="store", help="Set custom model", required=False) + parser.add_argument("--disk", action="store", help="Specifies disk to install to", required=False) + parser.add_argument("--smbios_spoof", action="store", help="Set SMBIOS patching mode", required=False) + # sys_patch args + parser.add_argument("--patch_sys_vol", help="Patches root volume", action="store_true", required=False) + parser.add_argument("--unpatch_sys_vol", help="Unpatches root volume, EXPERIMENTAL", action="store_true", required=False) + + # validation args + parser.add_argument("--validate", help="Runs Validation Tests for CI", action="store_true", required=False) + args = parser.parse_args() + if not( + args.build or + args.patch_sys_vol or + args.unpatch_sys_vol or + args.validate + ): + return None + else: + return args # def menu(title, prompt, menu_options, add_quit=True, auto_number=False, in_between=[], top_level=False): # return_option = ["Q", "Quit", None] if top_level else ["B", "Back", None] diff --git a/resources/validation.py b/resources/validation.py new file mode 100644 index 000000000..92181041c --- /dev/null +++ b/resources/validation.py @@ -0,0 +1,71 @@ + +import subprocess +from resources import build +from data import example_data, model_array + + +def validate(settings): + # Runs through ocvalidate to check for errors + + valid_dumps = [ + example_data.MacBookPro.MacBookPro92_Stock, + # example_data.MacBookPro.MacBookPro171_Stock, + # example_data.Macmini.Macmini91_Stock, + example_data.iMac.iMac81_Stock, + example_data.iMac.iMac112_Stock, + example_data.iMac.iMac122_Upgraded, + example_data.MacPro.MacPro31_Stock, + example_data.MacPro.MacPro31_Upgrade, + example_data.MacPro.MacPro31_Modern_AMD, + example_data.MacPro.MacPro31_Modern_Kepler, + example_data.MacPro.MacPro41_Upgrade, + example_data.MacPro.MacPro41_Modern_AMD, + example_data.MacPro.MacPro41_51__Flashed_Modern_AMD, + ] + + settings.validate = True + def build_prebuilt(): + for model in model_array.SupportedSMBIOS: + print(f"Validating predefined model: {model}") + settings.custom_model = model + build.BuildOpenCore(settings.custom_model, settings).build_opencore() + result = subprocess.run([settings.ocvalidate_path, f"{settings.opencore_release_folder}/EFI/OC/config.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if result.returncode != 0: + print("Error on build!") + print(result.stdout.decode()) + raise Exception(f"Validation failed for predefined model: {model}") + else: + print(f"Validation succeeded for predefined model: {model}") + + def build_dumps(): + for model in valid_dumps: + settings.computer = model + settings.custom_model = "" + print(f"Validating dumped model: {settings.computer.real_model}") + build.BuildOpenCore(settings.computer.real_model, settings).build_opencore() + result = subprocess.run([settings.ocvalidate_path, f"{settings.opencore_release_folder}/EFI/OC/config.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if result.returncode != 0: + print("Error on build!") + print(result.stdout.decode()) + raise Exception(f"Validation failed for predefined model: {settings.computer.real_model}") + else: + print(f"Validation succeeded for predefined model: {settings.computer.real_model}") + + # First run is with default settings + build_prebuilt() + build_dumps() + # Second run, flip all settings + settings.verbose_debug = True + settings.opencore_debug = True + settings.opencore_build = "DEBUG" + settings.kext_debug = True + settings.showpicker = False + settings.sip_status = False + settings.secure_status = True + settings.firewire_boot = True + settings.nvme_boot = True + settings.enable_wake_on_wlan = True + settings.disable_tb = True + settings.force_surplus = True + build_prebuilt() + build_dumps() \ No newline at end of file