Add Reboot Prompt in GUI after Root Patching

This commit is contained in:
Mykola Grymalyuk
2022-04-21 15:35:11 -06:00
parent 6537119632
commit 0e3d4244e7
5 changed files with 36 additions and 106 deletions

View File

@@ -38,6 +38,10 @@
- After OS updates, Patcher will detect whether system requires root patches and prompt you
- Implemented via Launch Agent in `/Library/LaunchAgents`
- OpenCore-Patcher.app will be copied to `/Library/Application Support/Dortania` for storage
- Add Reboot Prompt in GUI after Root Patching
- Remove manual root unpatching
- Removed due to reliablity issues
- `bless` based reversion still supported in Big Sur+
## 0.4.3
- Increment Binaries:

View File

@@ -79,6 +79,8 @@ To run the project from source, see here: [Build and run from source](./SOURCE.m
* Catalyst that started OpenCore Legacy Patcher
* [arter97](https://github.com/arter97/)
* [SimpleMSR](https://github.com/arter97/SimpleMSR/) to disable firmware throttling in Nehalem+ MacBooks without batteries
* [Mr.Macintosh](https://mrmacintosh.com)
* Endless hours helping architect and troubleshoot many portions of the project
* MacRumors and Unsupported Mac Communities
* Endless testing, reporting issues
* Apple

View File

@@ -76,6 +76,20 @@ class wx_python_gui:
self.app.ExitMainLoop()
sys.exit()
def reboot_system(self, event=None):
self.popup = wx.MessageDialog(
self.frame,
"Root Patcher finished successfully\n\nWould you like to reboot now?\n\nNote: This will close all open applications, remember to save them or manually reboot once you're ready",
"Reboot?",
wx.YES_NO | wx.ICON_INFORMATION
)
self.popup.SetYesNoLabels("Reboot", "Ignore")
answer = self.popup.ShowModal()
if answer == wx.ID_YES:
# Reboots with Count Down prompt (user can still dismiss if needed)
subprocess.call(['osascript', '-e', 'tell app "loginwindow" to «event aevtrrst»'])
sys.exit(0)
def reset_window(self):
self.frame.DestroyChildren()
self.frame.SetSize(self.WINDOW_WIDTH_MAIN, self.WINDOW_HEIGHT_MAIN)
@@ -130,10 +144,11 @@ class wx_python_gui:
extension = ""
if event:
if event.GetEventObject().GetLabel() == "Start Root Patching":
extension = " --gui_patch"
elif event.GetEventObject().GetLabel() == "Revert Root Patches":
extension = " --gui_unpatch"
if event.GetEventObject() != wx.Menu:
if event.GetEventObject().GetLabel() == "Start Root Patching":
extension = " --gui_patch"
elif event.GetEventObject().GetLabel() == "Revert Root Patches":
extension = " --gui_unpatch"
if self.constants.launcher_script is None:
args_string = f"'{self.constants.launcher_binary}'{extension}"
@@ -905,6 +920,9 @@ class wx_python_gui:
pass
sys.stdout = self.stock_stdout
sys.stderr = self.stock_stderr
if self.constants.root_patcher_succeded is True:
print("- Root Patcher finished successfully")
self.reboot_system()
self.return_to_main_menu.Enable()
wx.GetApp().Yield()
@@ -984,6 +1002,9 @@ class wx_python_gui:
pass
sys.stdout = self.stock_stdout
sys.stderr = self.stock_stderr
if self.constants.root_patcher_succeded is True:
print("- Root Patcher finished successfully")
self.reboot_system()
self.return_to_main_menu.Enable()
wx.GetApp().Yield()

View File

@@ -192,6 +192,7 @@ class Constants:
self.set_content_caching = False # Set Content Caching
self.allow_nvme_fixing = True # Allow NVMe Kernel Space Patches
self.disable_xcpm = False # Disable XCPM (X86PlatformPlugin.kext)
self.root_patcher_succeded = False # Determine if root patcher succeeded
self.legacy_accel_support = [
os_data.os_data.mojave,

View File

@@ -24,6 +24,7 @@ class PatchSysVolume:
self.validate = False
self.added_legacy_kexts = False
self.root_supports_snapshot = utilities.check_if_root_is_apfs_snapshot()
self.constants.root_patcher_succeded = False # Reset Variable each time we start
# GUI will detect hardware patches betfore starting PatchSysVolume()
# However the TUI will not, so allow for data to be passed in manually avoiding multiple calls
@@ -90,10 +91,6 @@ class PatchSysVolume:
if Path(self.mount_extensions).exists():
print("- Root Volume is already mounted")
if patch is True:
# Root Volume unpatching is unreliable due to being a live volume
# Only worth while on Big Sur as '--last-sealed-snapshot' is hit or miss
if self.constants.detected_os == os_data.os_data.big_sur and self.root_supports_snapshot is True and utilities.check_seal() is True:
self.backup_volume()
self.patch_root_vol()
return True
else:
@@ -108,10 +105,6 @@ class PatchSysVolume:
if Path(self.mount_extensions).exists():
print("- Successfully mounted the Root Volume")
if patch is True:
# Root Volume unpatching is unreliable due to being a live volume
# Only worth while on Big Sur as '--last-sealed-snapshot' is hit or miss
if self.constants.detected_os == os_data.os_data.big_sur and self.root_supports_snapshot is True and utilities.check_seal() is True:
self.backup_volume()
self.patch_root_vol()
return True
else:
@@ -127,96 +120,6 @@ class PatchSysVolume:
if self.constants.gui_mode is False:
input("- Press [ENTER] to exit: ")
def backup_volume(self):
for location in sys_patch_data.BackupLocations:
utilities.cls()
print("Backing up root volume before patching (This may take some time)")
print(f"- Attempting to backup {location}")
location_zip = f"{location}-Backup.zip"
location_zip_path = Path(self.mount_location) / Path(location_zip)
if location_zip_path.exists():
print(f"- Found existing {location_zip}, skipping")
else:
print(f"- Backing up {location}")
# cp -r ./Extensions ./Extensions-Backup
# ditto -c -k --sequesterRsrc --keepParent ./Extensions-Backup ./Extensions-Backup.zip
# rm -r ./Extensions-Backup
print("- Creating Backup folder")
utilities.process_status(
utilities.elevated(
["cp", "-r", f"{self.mount_location}/{location}", f"{self.mount_location}/{location}-Backup"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
)
print("- Zipping Backup folder")
utilities.process_status(
utilities.elevated(
["ditto", "-c", "-k", "--sequesterRsrc", "--keepParent", f"{self.mount_location}/{location}-Backup", f"{self.mount_location}/{location_zip}"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
)
print("- Removing Backup folder")
utilities.process_status(
utilities.elevated(
["rm", "-r", f"{self.mount_location}/{location}-Backup"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
)
def manual_root_patch_revert(self):
print("- Attempting to revert patches")
if (Path(self.mount_location) / Path("/System/Library/Extensions-Backup.zip")).exists():
print("- Verified manual unpatching is available")
for location in sys_patch_data.BackupLocations:
utilities.cls()
print("Reverting root volume patches (This may take some time)")
print(f"- Attempting to unpatch {location}")
location_zip = f"/{location}-Backup.zip"
location_zip_path = Path(self.mount_location) / Path(location_zip)
location_old_path = Path(self.mount_location) / Path(location)
if "PrivateFrameworks" in location:
copy_path = Path(self.mount_location) / Path("/System/Library/PrivateFrameworks")
elif "Frameworks" in location:
copy_path = Path(self.mount_location) / Path("/System/Library/Frameworks")
else:
copy_path = Path(self.mount_location) / Path("/System/Library")
if location_zip_path.exists():
print(f"- Found {location_zip}")
print(f"- Unzipping {location_zip}")
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(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(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(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(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")
if self.validate is False:
self.rebuild_snapshot()
else:
print("- Could not find Extensions.zip, cannot manually unpatch root volume")
def unpatch_root_vol(self):
if self.constants.detected_os > os_data.os_data.catalina and self.root_supports_snapshot is True:
print("- Reverting to last signed APFS snapshot")
@@ -225,14 +128,12 @@ class PatchSysVolume:
print("- Unable to revert root volume patches")
print("Reason for unpatch Failure:")
print(result.stdout.decode())
print("- Failed to revert snapshot via bless, falling back on manual restoration")
self.manual_root_patch_revert()
print("- Failed to revert snapshot via Apple's 'bless' command")
else:
self.clean_skylight_plugins()
self.constants.root_patcher_succeded = True
print("- Unpatching complete")
print("\nPlease reboot the machine for patches to take effect")
else:
self.manual_root_patch_revert()
def rebuild_snapshot(self):
print("- Rebuilding Kernel Cache (This may take some time)")
@@ -282,6 +183,7 @@ class PatchSysVolume:
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")
self.constants.root_patcher_succeded = True
if self.constants.gui_mode is False:
input("\nPress [ENTER] to continue")