mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-13 20:28:21 +10:00
sys_patch: Add extra snapshot checks
Avoid issues on snapshot-less installs
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -23,3 +23,4 @@ __pycache__/
|
||||
/payloads/List.txt
|
||||
/payloads/Installer.sh
|
||||
/payloads/Info.plist
|
||||
/payloads/seed.plist
|
||||
|
||||
@@ -24,11 +24,16 @@ class PatchSysVolume:
|
||||
self.root_mount_path = None
|
||||
self.validate = False
|
||||
self.added_legacy_kexts = False
|
||||
self.root_supports_snapshot = utilities.check_if_root_is_apfs_snapshot()
|
||||
|
||||
# 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
|
||||
if hardware_details is None:
|
||||
hardware_details = sys_patch_detect.detect_root_patch(self.computer.real_model, self.constants).detect_patch_set()
|
||||
self.init_hardware_patches(hardware_details)
|
||||
self.init_pathing(custom_root_mount_path=None, custom_data_mount_path=None)
|
||||
|
||||
def init_hardware_patches(self, hardware_details):
|
||||
|
||||
self.amfi_must_disable = hardware_details["Settings: Requires AMFI exemption"]
|
||||
self.check_board_id = hardware_details["Settings: Requires Board ID validation"]
|
||||
@@ -52,7 +57,11 @@ class PatchSysVolume:
|
||||
self.legacy_gmux = hardware_details["Miscellaneous: Legacy GMUX"]
|
||||
self.legacy_keyboard_backlight = hardware_details["Miscellaneous: Legacy Keyboard Backlight"]
|
||||
|
||||
if self.constants.detected_os > os_data.os_data.catalina:
|
||||
def init_pathing(self, custom_root_mount_path=None, custom_data_mount_path=None):
|
||||
if custom_root_mount_path and custom_data_mount_path:
|
||||
self.mount_location = custom_root_mount_path
|
||||
self.data_mount_location = custom_data_mount_path
|
||||
elif self.root_supports_snapshot is True:
|
||||
# Big Sur and newer use APFS snapshots
|
||||
self.mount_location = "/System/Volumes/Update/mnt1"
|
||||
self.mount_location_data = ""
|
||||
@@ -72,8 +81,11 @@ class PatchSysVolume:
|
||||
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 == os_data.os_data.catalina and self.validate is False:
|
||||
print("- Mounting Catalina Root Volume as writable")
|
||||
if (
|
||||
self.constants.detected_os == os_data.os_data.catalina or
|
||||
(self.constants.detected_os > os_data.os_data.catalina and self.root_supports_snapshot is False)
|
||||
):
|
||||
print("- Mounting Dedicated Root Volume as writable")
|
||||
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():
|
||||
@@ -81,7 +93,7 @@ class PatchSysVolume:
|
||||
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 utilities.check_seal() is True:
|
||||
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
|
||||
@@ -89,7 +101,7 @@ class PatchSysVolume:
|
||||
self.unpatch_root_vol()
|
||||
return True
|
||||
else:
|
||||
if self.constants.detected_os > os_data.os_data.catalina:
|
||||
if self.constants.detected_os > os_data.os_data.catalina and self.root_supports_snapshot is True:
|
||||
print("- Mounting APFS Snapshot as writable")
|
||||
result = utilities.elevated(["mount", "-o", "nobrowse", "-t", "apfs", f"/dev/{self.root_mount_path}", self.mount_location], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
if result.returncode == 0:
|
||||
@@ -99,7 +111,7 @@ class PatchSysVolume:
|
||||
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 utilities.check_seal() is True:
|
||||
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
|
||||
@@ -207,7 +219,7 @@ class PatchSysVolume:
|
||||
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:
|
||||
if self.constants.detected_os > os_data.os_data.catalina and self.root_supports_snapshot is True:
|
||||
print("- Reverting to last signed APFS snapshot")
|
||||
result = utilities.elevated(["bless", "--mount", self.mount_location, "--bootefi", "--last-sealed-snapshot"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
if result.returncode != 0:
|
||||
@@ -247,12 +259,7 @@ class PatchSysVolume:
|
||||
else:
|
||||
self.success_status = True
|
||||
print("- Successfully built new kernel cache")
|
||||
# if self.constants.gui_mode is False:
|
||||
# if self.constants.detected_os > os_data.os_data.catalina:
|
||||
# input("Press [ENTER] to continue with snapshotting")
|
||||
# else:
|
||||
# input("Press [ENTER] to continue with kernel and dyld cache merging")
|
||||
if self.constants.detected_os > os_data.os_data.catalina:
|
||||
if self.root_supports_snapshot is True:
|
||||
print("- Creating new APFS snapshot")
|
||||
bless = utilities.elevated(
|
||||
["bless", "--folder", f"{self.mount_location}/System/Library/CoreServices", "--bootefi", "--create-snapshot"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||
@@ -270,8 +277,9 @@ class PatchSysVolume:
|
||||
if self.constants.detected_os == os_data.os_data.catalina:
|
||||
print("- Merging kernel cache")
|
||||
utilities.process_status(utilities.elevated(["kcditto"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||
print("- Merging dyld cache")
|
||||
utilities.process_status(utilities.elevated(["update_dyld_shared_cache", "-root", f"{self.mount_location}/"]))
|
||||
if self.constants.detected_os in [os_data.os_data.mojave, os_data.os_data.catalina]:
|
||||
print("- Merging dyld cache")
|
||||
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.constants.gui_mode is False:
|
||||
|
||||
@@ -84,6 +84,14 @@ def get_disk_path():
|
||||
root_mount_path = root_mount_path[:-2] if root_mount_path.count("s") > 1 else root_mount_path
|
||||
return root_mount_path
|
||||
|
||||
def check_if_root_is_apfs_snapshot():
|
||||
root_partition_info = plistlib.loads(subprocess.run("diskutil info -plist /".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||
try:
|
||||
is_snapshotted = root_partition_info["APFSSnapshot"]
|
||||
except KeyError:
|
||||
is_snapshotted = False
|
||||
return is_snapshotted
|
||||
|
||||
|
||||
def check_seal():
|
||||
# 'Snapshot Sealed' property is only listed on booted snapshots
|
||||
|
||||
Reference in New Issue
Block a user