mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-19 13:46:05 +10:00
CI: Add sys_patch validation
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -27,3 +27,4 @@ __pycache__/
|
|||||||
/payloads/AutoPkg-Assets.pkg
|
/payloads/AutoPkg-Assets.pkg
|
||||||
/payloads/AutoPkg-Assets.pkg.zip
|
/payloads/AutoPkg-Assets.pkg.zip
|
||||||
/payloads/Universal-Binaries
|
/payloads/Universal-Binaries
|
||||||
|
/payloads/OpenCore-Legacy-Patcher
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
- Removes old patcher files before installing new
|
- Removes old patcher files before installing new
|
||||||
- Add Serial Number Spoofing
|
- Add Serial Number Spoofing
|
||||||
- For recycled machines where MDM was mistakenly left on
|
- For recycled machines where MDM was mistakenly left on
|
||||||
|
- Add sys_patch file validation during CI
|
||||||
|
|
||||||
## 0.4.4
|
## 0.4.4
|
||||||
- Lower SIP requirement for Root Patching
|
- Lower SIP requirement for Root Patching
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ from datetime import datetime
|
|||||||
import plistlib
|
import plistlib
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from resources import constants, generate_smbios, utilities, sys_patch_download, sys_patch_detect, sys_patch_auto
|
from resources import constants, generate_smbios, utilities, sys_patch_download, sys_patch_detect, sys_patch_auto, sys_patch_helpers
|
||||||
from data import os_data
|
from data import os_data
|
||||||
|
|
||||||
|
|
||||||
@@ -166,26 +166,14 @@ class PatchSysVolume:
|
|||||||
utilities.process_status(utilities.elevated(["mkdir", "-p", f"{self.mount_application_support}/SkyLightPlugins/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["mkdir", "-p", f"{self.mount_application_support}/SkyLightPlugins/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
def write_patchset(self, patchset):
|
def write_patchset(self, patchset):
|
||||||
source_path = f"{self.constants.payload_path}"
|
|
||||||
destination_path = f"{self.mount_location}/System/Library/CoreServices"
|
destination_path = f"{self.mount_location}/System/Library/CoreServices"
|
||||||
file_name = "OpenCore-Legacy-Patcher.plist"
|
file_name = "OpenCore-Legacy-Patcher.plist"
|
||||||
source_path_file = f"{source_path}/{file_name}"
|
|
||||||
destination_path_file = f"{destination_path}/{file_name}"
|
destination_path_file = f"{destination_path}/{file_name}"
|
||||||
|
if sys_patch_helpers.sys_patch_helpers(self.constants).generate_patchset_plist(patchset, file_name):
|
||||||
data = {
|
print("- Writing patchset information to Root Volume")
|
||||||
"OpenCore Legacy Patcher": f"v{self.constants.patcher_version}",
|
if Path(destination_path_file).exists():
|
||||||
"PatcherSupportPkg": f"v{self.constants.patcher_support_pkg_version}",
|
utilities.process_status(utilities.elevated(["rm", destination_path_file], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
"Time Patched": f"{datetime.now().strftime('%B %d, %Y @ %H:%M:%S')}",
|
utilities.process_status(utilities.elevated(["cp", f"{self.constants.payload_path}/{file_name}", destination_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
}
|
|
||||||
print("- Writing patchset information to Root Volume")
|
|
||||||
data.update(patchset)
|
|
||||||
if Path(source_path_file).exists():
|
|
||||||
os.remove(source_path_file)
|
|
||||||
# Need to write to a safe location
|
|
||||||
plistlib.dump(data, Path(source_path_file).open("wb"), sort_keys=False)
|
|
||||||
if Path(destination_path_file).exists():
|
|
||||||
utilities.process_status(utilities.elevated(["rm", destination_path_file], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
|
||||||
utilities.process_status(utilities.elevated(["cp", source_path_file, destination_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
|
||||||
|
|
||||||
def patch_root_vol(self):
|
def patch_root_vol(self):
|
||||||
print(f"- Running patches for {self.model}")
|
print(f"- Running patches for {self.model}")
|
||||||
@@ -243,7 +231,7 @@ class PatchSysVolume:
|
|||||||
|
|
||||||
# Make sure SNB kexts are compatible with the host
|
# Make sure SNB kexts are compatible with the host
|
||||||
if "Intel Sandy Bridge" in required_patches:
|
if "Intel Sandy Bridge" in required_patches:
|
||||||
self.snb_board_id_patch(source_files_path)
|
sys_patch_helpers.sys_patch_helpers(self.constants).snb_board_id_patch(source_files_path)
|
||||||
|
|
||||||
for patch in required_patches:
|
for patch in required_patches:
|
||||||
# Check if all files are present
|
# Check if all files are present
|
||||||
@@ -306,35 +294,6 @@ class PatchSysVolume:
|
|||||||
utilities.process_status(utilities.elevated(chown_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(chown_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
|
|
||||||
def snb_board_id_patch(self, source_files_path):
|
|
||||||
# AppleIntelSNBGraphicsFB hard codes the supported Board IDs for Sandy Bridge iGPUs
|
|
||||||
# Because of this, the kext errors out on unsupported systems
|
|
||||||
# This function simply patches in a supported Board ID, using 'determine_best_board_id_for_sandy()'
|
|
||||||
# to supplement the ideal Board ID
|
|
||||||
if self.computer.reported_board_id not in self.constants.sandy_board_id_stock:
|
|
||||||
print(f"- Found unspported Board ID {self.computer.reported_board_id}, performing AppleIntelSNBGraphicsFB bin patching")
|
|
||||||
board_to_patch = generate_smbios.determine_best_board_id_for_sandy(self.computer.reported_board_id, self.computer.gpus)
|
|
||||||
print(f"- Replacing {board_to_patch} with {self.computer.reported_board_id}")
|
|
||||||
|
|
||||||
board_to_patch_hex = bytes.fromhex(board_to_patch.encode('utf-8').hex())
|
|
||||||
reported_board_hex = bytes.fromhex(self.computer.reported_board_id.encode('utf-8').hex())
|
|
||||||
|
|
||||||
if len(board_to_patch_hex) != len(reported_board_hex):
|
|
||||||
print(f"- Error: Board ID {self.computer.reported_board_id} is not the same length as {board_to_patch}")
|
|
||||||
raise Exception("Host's Board ID is not the same length as the kext's Board ID, cannot patch!!!")
|
|
||||||
else:
|
|
||||||
path = source_files_path + "/10.13.6/System/Library/Extensions/AppleIntelSNBGraphicsFB.kext/Contents/MacOS/AppleIntelSNBGraphicsFB"
|
|
||||||
if Path(path).exists():
|
|
||||||
with open(path, 'rb') as f:
|
|
||||||
data = f.read()
|
|
||||||
data = data.replace(board_to_patch_hex, reported_board_hex)
|
|
||||||
with open(path, 'wb') as f:
|
|
||||||
f.write(data)
|
|
||||||
else:
|
|
||||||
print(f"- Error: Could not find {path}")
|
|
||||||
raise Exception("Failed to find AppleIntelSNBGraphicsFB.kext, cannot patch!!!")
|
|
||||||
|
|
||||||
|
|
||||||
def check_files(self):
|
def check_files(self):
|
||||||
if Path(self.constants.payload_local_binaries_root_path).exists():
|
if Path(self.constants.payload_local_binaries_root_path).exists():
|
||||||
print("- Found local Apple Binaries")
|
print("- Found local Apple Binaries")
|
||||||
|
|||||||
63
resources/sys_patch_helpers.py
Normal file
63
resources/sys_patch_helpers.py
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# Additional support functions for sys_patch.py
|
||||||
|
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||||
|
|
||||||
|
from resources import generate_smbios
|
||||||
|
from pathlib import Path
|
||||||
|
from datetime import datetime
|
||||||
|
import plistlib
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class sys_patch_helpers:
|
||||||
|
|
||||||
|
def __init__(self, constants):
|
||||||
|
self.constants = constants
|
||||||
|
|
||||||
|
|
||||||
|
def snb_board_id_patch(self, source_files_path):
|
||||||
|
# AppleIntelSNBGraphicsFB hard codes the supported Board IDs for Sandy Bridge iGPUs
|
||||||
|
# Because of this, the kext errors out on unsupported systems
|
||||||
|
# This function simply patches in a supported Board ID, using 'determine_best_board_id_for_sandy()'
|
||||||
|
# to supplement the ideal Board ID
|
||||||
|
source_files_path = str(source_files_path)
|
||||||
|
if self.constants.computer.reported_board_id not in self.constants.sandy_board_id_stock:
|
||||||
|
print(f"- Found unspported Board ID {self.constants.computer.reported_board_id}, performing AppleIntelSNBGraphicsFB bin patching")
|
||||||
|
board_to_patch = generate_smbios.determine_best_board_id_for_sandy(self.constants.computer.reported_board_id, self.constants.computer.gpus)
|
||||||
|
print(f"- Replacing {board_to_patch} with {self.constants.computer.reported_board_id}")
|
||||||
|
|
||||||
|
board_to_patch_hex = bytes.fromhex(board_to_patch.encode('utf-8').hex())
|
||||||
|
reported_board_hex = bytes.fromhex(self.constants.computer.reported_board_id.encode('utf-8').hex())
|
||||||
|
|
||||||
|
if len(board_to_patch_hex) != len(reported_board_hex):
|
||||||
|
print(f"- Error: Board ID {self.constants.computer.reported_board_id} is not the same length as {board_to_patch}")
|
||||||
|
raise Exception("Host's Board ID is not the same length as the kext's Board ID, cannot patch!!!")
|
||||||
|
else:
|
||||||
|
path = source_files_path + "/10.13.6/System/Library/Extensions/AppleIntelSNBGraphicsFB.kext/Contents/MacOS/AppleIntelSNBGraphicsFB"
|
||||||
|
if Path(path).exists():
|
||||||
|
with open(path, 'rb') as f:
|
||||||
|
data = f.read()
|
||||||
|
data = data.replace(board_to_patch_hex, reported_board_hex)
|
||||||
|
with open(path, 'wb') as f:
|
||||||
|
f.write(data)
|
||||||
|
else:
|
||||||
|
print(f"- Error: Could not find {path}")
|
||||||
|
raise Exception("Failed to find AppleIntelSNBGraphicsFB.kext, cannot patch!!!")
|
||||||
|
|
||||||
|
|
||||||
|
def generate_patchset_plist(self, patchset, file_name):
|
||||||
|
source_path = f"{self.constants.payload_path}"
|
||||||
|
source_path_file = f"{source_path}/{file_name}"
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"OpenCore Legacy Patcher": f"v{self.constants.patcher_version}",
|
||||||
|
"PatcherSupportPkg": f"v{self.constants.patcher_support_pkg_version}",
|
||||||
|
"Time Patched": f"{datetime.now().strftime('%B %d, %Y @ %H:%M:%S')}",
|
||||||
|
}
|
||||||
|
data.update(patchset)
|
||||||
|
if Path(source_path_file).exists():
|
||||||
|
os.remove(source_path_file)
|
||||||
|
# Need to write to a safe location
|
||||||
|
plistlib.dump(data, Path(source_path_file).open("wb"), sort_keys=False)
|
||||||
|
if Path(source_path_file).exists():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
from resources import build
|
from resources import build, sys_patch_helpers
|
||||||
from data import example_data, model_array
|
from data import example_data, model_array, sys_patch_dict, os_data
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
def validate(settings):
|
def validate(settings):
|
||||||
@@ -58,6 +59,43 @@ def validate(settings):
|
|||||||
raise Exception(f"Validation failed for predefined model: {settings.computer.real_model}")
|
raise Exception(f"Validation failed for predefined model: {settings.computer.real_model}")
|
||||||
else:
|
else:
|
||||||
print(f"Validation succeeded for predefined model: {settings.computer.real_model}")
|
print(f"Validation succeeded for predefined model: {settings.computer.real_model}")
|
||||||
|
|
||||||
|
|
||||||
|
def validate_root_patch_files(major_kernel, minor_kernel):
|
||||||
|
patchset = sys_patch_dict.SystemPatchDictionary(major_kernel, minor_kernel, settings.legacy_accel_support)
|
||||||
|
host_os_float = float(f"{major_kernel}.{minor_kernel}")
|
||||||
|
for patch_subject in patchset:
|
||||||
|
for patch_core in patchset[patch_subject]:
|
||||||
|
patch_os_min_float = float(f'{patchset[patch_subject][patch_core]["OS Support"]["Minimum OS Support"]["OS Major"]}.{patchset[patch_subject][patch_core]["OS Support"]["Minimum OS Support"]["OS Minor"]}')
|
||||||
|
patch_os_max_float = float(f'{patchset[patch_subject][patch_core]["OS Support"]["Maximum OS Support"]["OS Major"]}.{patchset[patch_subject][patch_core]["OS Support"]["Maximum OS Support"]["OS Minor"]}')
|
||||||
|
if (host_os_float < patch_os_min_float or host_os_float > patch_os_max_float):
|
||||||
|
continue
|
||||||
|
for install_type in ["Install", "Install Non-Root"]:
|
||||||
|
if install_type in patchset[patch_subject][patch_core]:
|
||||||
|
for install_directory in patchset[patch_subject][patch_core][install_type]:
|
||||||
|
for install_file in patchset[patch_subject][patch_core][install_type][install_directory]:
|
||||||
|
source_file = str(settings.payload_local_binaries_root_path) + "/" + patchset[patch_subject][patch_core][install_type][install_directory][install_file] + install_directory + "/" + install_file
|
||||||
|
if not Path(source_file).exists():
|
||||||
|
raise Exception(f"Failed to find {source_file}")
|
||||||
|
|
||||||
|
print(f"Validating Root Patch Dictionary integrity for Darwin {major_kernel}.{minor_kernel}")
|
||||||
|
if not sys_patch_helpers.sys_patch_helpers(settings).generate_patchset_plist(patchset, "OpenCore-Legacy-Patcher"):
|
||||||
|
raise Exception("Failed to generate patchset plist")
|
||||||
|
|
||||||
|
|
||||||
|
def validate_sys_patch():
|
||||||
|
if Path(settings.payload_local_binaries_root_path_zip).exists():
|
||||||
|
print("Validating Root Patch File integrity")
|
||||||
|
if not Path(settings.payload_local_binaries_root_path).exists():
|
||||||
|
subprocess.run(["ditto", "-V", "-x", "-k", "--sequesterRsrc", "--rsrc", settings.payload_local_binaries_root_path_zip, settings.payload_path])
|
||||||
|
|
||||||
|
for supported_os in [os_data.os_data.big_sur, os_data.os_data.monterey]:
|
||||||
|
validate_root_patch_files(supported_os, 6)
|
||||||
|
print("Validating SNB Board ID patcher")
|
||||||
|
settings.computer.reported_board_id = "Mac-7BA5B2DFE22DDD8C"
|
||||||
|
sys_patch_helpers.sys_patch_helpers(settings).snb_board_id_patch(settings.payload_local_binaries_root_path)
|
||||||
|
else:
|
||||||
|
print("Skipping Root Patch File integrity validation")
|
||||||
|
|
||||||
# First run is with default settings
|
# First run is with default settings
|
||||||
build_prebuilt()
|
build_prebuilt()
|
||||||
@@ -81,3 +119,4 @@ def validate(settings):
|
|||||||
settings.serial_settings = "Minimal"
|
settings.serial_settings = "Minimal"
|
||||||
build_prebuilt()
|
build_prebuilt()
|
||||||
build_dumps()
|
build_dumps()
|
||||||
|
validate_sys_patch()
|
||||||
|
|||||||
Reference in New Issue
Block a user