mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-13 20:28:21 +10:00
Add Reboot Prompt in GUI after Root Patching
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user