mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-06-21 06:30:52 +10:00
Add basic CLI support
This commit is contained in:
@@ -43,3 +43,23 @@ jobs:
|
|||||||
file: OpenCore-Patcher.app.zip
|
file: OpenCore-Patcher.app.zip
|
||||||
tag: ${{ github.ref }}
|
tag: ${{ github.ref }}
|
||||||
file_glob: true
|
file_glob: true
|
||||||
|
build:
|
||||||
|
name: Build CLI
|
||||||
|
runs-on: self-hosted
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: pyinstaller OCLP-GUI.spec
|
||||||
|
- run: cd dist; zip ../OCLP-GUI.zip OCLP-GUI
|
||||||
|
- name: Upload Binary to Artifacts
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: OCLP-GUI
|
||||||
|
path: OCLP-GUI.zip
|
||||||
|
- name: Upload to Release
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
uses: svenstaro/upload-release-action@e74ff71f7d8a4c4745b560a485cc5fdb9b5b999d
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: OCLP-GUI.zip
|
||||||
|
tag: ${{ github.ref }}
|
||||||
|
file_glob: true
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
- Enhance HDMI audio support on Mac Pros and Xserves
|
- Enhance HDMI audio support on Mac Pros and Xserves
|
||||||
- Strip unused kext entries during build
|
- Strip unused kext entries during build
|
||||||
- Add gfxutil support for better DeviceProperty path detection
|
- Add gfxutil support for better DeviceProperty path detection
|
||||||
|
- Add basic CLI support
|
||||||
|
|
||||||
## 0.0.22
|
## 0.0.22
|
||||||
- Add ExFat support for models missing driver
|
- Add ExFat support for models missing driver
|
||||||
|
|||||||
Executable
+155
@@ -0,0 +1,155 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright (C) 2020-2021 Mykola Grymalyuk
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import platform
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from Resources import Build, ModelArray, Constants, SysPatch, Utilities, CliMenu
|
||||||
|
|
||||||
|
|
||||||
|
class OpenCoreLegacyPatcher():
|
||||||
|
def __init__(self):
|
||||||
|
self.constants = Constants.Constants()
|
||||||
|
self.current_model: str = None
|
||||||
|
opencore_model: str = subprocess.run("nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-product".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode()
|
||||||
|
if not opencore_model.startswith("nvram: Error getting variable"):
|
||||||
|
opencore_model = [line.strip().split(":oem-product ", 1)[1] for line in opencore_model.split("\n") if line.strip().startswith("4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:")][0]
|
||||||
|
self.current_model = opencore_model
|
||||||
|
else:
|
||||||
|
self.current_model = subprocess.run("system_profiler SPHardwareDataType".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
self.current_model = [line.strip().split(": ", 1)[1] for line in self.current_model.stdout.decode().split("\n") if line.strip().startswith("Model Identifier")][0]
|
||||||
|
self.constants.detected_os = int(platform.uname().release.partition(".")[0])
|
||||||
|
if self.current_model in ModelArray.NoAPFSsupport:
|
||||||
|
self.constants.serial_settings = "Moderate"
|
||||||
|
|
||||||
|
# Logic for when user runs custom OpenCore build and do not expose it
|
||||||
|
# Note: This logic currently only applies for iMacPro1,1 users, see below threads on the culprits:
|
||||||
|
# - https://forums.macrumors.com/threads/2011-imac-graphics-card-upgrade.1596614/post-17425857
|
||||||
|
# - https://forums.macrumors.com/threads/opencore-on-the-mac-pro.2207814/
|
||||||
|
# PLEASE FOR THE LOVE OF GOD JUST SET ExposeSensitiveData CORRECTLY!!!
|
||||||
|
if self.current_model == "iMacPro1,1":
|
||||||
|
serial: str = subprocess.run("system_profiler SPHardwareDataType | grep Serial".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode()
|
||||||
|
serial = [line.strip().split("Number (system): ", 1)[1] for line in serial.split("\n") if line.strip().startswith("Serial")][0]
|
||||||
|
true_model = subprocess.run([str(self.constants.macserial_path), "--info", str(serial)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
true_model = [i.partition(" - ")[2] for i in true_model.stdout.decode().split("\n") if "Model: " in i][0]
|
||||||
|
print(f"True Model: {true_model}")
|
||||||
|
if not true_model.startswith("Unknown"):
|
||||||
|
self.current_model = true_model
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
|
# Generic building args
|
||||||
|
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('--skip_wifi', help='Skip wifi patches', 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)
|
||||||
|
|
||||||
|
# Building args requiring value values
|
||||||
|
parser.add_argument('--model', action='store', help='Set custom model', required=False)
|
||||||
|
parser.add_argument('--metal_gpu', action='store', help='Set Metal GPU Vendor', required=False)
|
||||||
|
parser.add_argument('--smbios_spoof', action='store', help='Set SMBIOS patching mode', required=False)
|
||||||
|
|
||||||
|
# SysPatch 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)
|
||||||
|
parser.add_argument('--custom_repo', action='store', help='Set SMBIOS patching mode', required=False)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
self.constants.gui_mode = True
|
||||||
|
self.constants.current_path = Path.cwd()
|
||||||
|
|
||||||
|
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
|
||||||
|
print("- Rerouting payloads location")
|
||||||
|
self.constants.payload_path = sys._MEIPASS / Path("payloads")
|
||||||
|
else:
|
||||||
|
print("- Using default payloads location")
|
||||||
|
|
||||||
|
if args.verbose:
|
||||||
|
print("- Set verbose configuration")
|
||||||
|
self.constants.verbose_debug = True
|
||||||
|
if args.debug_oc:
|
||||||
|
print("- Set OpenCore DEBUG configuration")
|
||||||
|
self.constants.opencore_debug = True
|
||||||
|
self.constants.opencore_build = "DEBUG"
|
||||||
|
if args.debug_kext:
|
||||||
|
print("- Set kext DEBUG configuration")
|
||||||
|
self.constants.kext_debug = True
|
||||||
|
if args.skip_wifi:
|
||||||
|
print("- Set wifi skip configuration")
|
||||||
|
self.constants.wifi_build = True
|
||||||
|
if args.hide_picker:
|
||||||
|
print("- Set HidePicker configuration")
|
||||||
|
self.constants.showpicker = False
|
||||||
|
if args.disable_sip:
|
||||||
|
print("- Set Disable SIP configuration")
|
||||||
|
self.constants.sip_status = False
|
||||||
|
if args.disable_smb:
|
||||||
|
print("- Set Disable SecureBootModel configuration")
|
||||||
|
self.constants.secure_status = False
|
||||||
|
if args.vault:
|
||||||
|
print("- Set Vault configuration")
|
||||||
|
self.constants.vault = True
|
||||||
|
if args.metal_gpu:
|
||||||
|
if args.metal_gpu == "Nvidia":
|
||||||
|
print("- Set Metal GPU patches to Nvidia")
|
||||||
|
self.constants.metal_build = True
|
||||||
|
self.constants.imac_vendor = "Nvidia"
|
||||||
|
elif args.metal_gpu == "AMD":
|
||||||
|
print("- Set Metal GPU patches to AMD")
|
||||||
|
self.constants.metal_build = True
|
||||||
|
self.constants.imac_vendor = "AMD"
|
||||||
|
else:
|
||||||
|
print(f"- Unknown GPU arg passed: {args.metal_gpu}")
|
||||||
|
self.constants.metal_build = False
|
||||||
|
self.constants.imac_vendor = "None"
|
||||||
|
if args.smbios_spoof:
|
||||||
|
if args.smbios_spoof == "Minimal":
|
||||||
|
self.constants.serial_settings = "Minimal"
|
||||||
|
elif args.smbios_spoof == "Moderate":
|
||||||
|
self.constants.serial_settings = "Moderate"
|
||||||
|
elif args.smbios_spoof == "Advanced":
|
||||||
|
self.constants.serial_settings = "Advanced"
|
||||||
|
else:
|
||||||
|
print(f"- Unknown SMBIOS arg passed: {args.smbios_spoof}")
|
||||||
|
|
||||||
|
if args.build:
|
||||||
|
if args.model:
|
||||||
|
print(f"- Using custom model: {args.model}")
|
||||||
|
self.constants.custom_model = args.model
|
||||||
|
self.build_opencore()
|
||||||
|
else:
|
||||||
|
print(f"- Using detected model: {self.current_model}")
|
||||||
|
self.build_opencore()
|
||||||
|
if args.patch_sys_vol:
|
||||||
|
print("- Set System Volume patching")
|
||||||
|
if args.custom_repo:
|
||||||
|
self.constants.url_apple_binaries = args.custom_repo
|
||||||
|
print(f"- Custom set repo to: {self.constants.url_apple_binaries}")
|
||||||
|
SysPatch.PatchSysVolume(self.constants.custom_model or self.current_model, self.constants).start_patch()
|
||||||
|
elif args.unpatch_sys_vol:
|
||||||
|
print("- Set System Volume unpatching")
|
||||||
|
SysPatch.PatchSysVolume(self.constants.custom_model or self.current_model, self.constants).start_unpatch()
|
||||||
|
|
||||||
|
|
||||||
|
def build_opencore(self):
|
||||||
|
Build.BuildOpenCore(self.constants.custom_model or self.current_model, self.constants).build_opencore()
|
||||||
|
|
||||||
|
def install_opencore(self):
|
||||||
|
Build.BuildOpenCore(self.constants.custom_model or self.current_model, self.constants).copy_efi()
|
||||||
|
|
||||||
|
OpenCoreLegacyPatcher()
|
||||||
|
|
||||||
|
# Example arg for OCLP command line
|
||||||
|
# ./OCLP --build --verbose --debug_oc --debug_kext --model iMac11,2
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# -*- mode: python ; coding: utf-8 -*-
|
||||||
|
import sys, os
|
||||||
|
sys.path.append(os.path.abspath(os.getcwd()))
|
||||||
|
from Resources import Constants
|
||||||
|
block_cipher = None
|
||||||
|
|
||||||
|
|
||||||
|
a = Analysis(['OCLP-CLI.command'],
|
||||||
|
binaries=[],
|
||||||
|
datas=[('payloads', 'payloads'), ('Resources', 'Resources')],
|
||||||
|
hiddenimports=[],
|
||||||
|
hookspath=[],
|
||||||
|
runtime_hooks=[],
|
||||||
|
excludes=[],
|
||||||
|
win_no_prefer_redirects=False,
|
||||||
|
win_private_assemblies=False,
|
||||||
|
cipher=block_cipher,
|
||||||
|
noarchive=False)
|
||||||
|
pyz = PYZ(a.pure, a.zipped_data,
|
||||||
|
cipher=block_cipher)
|
||||||
|
exe = EXE(pyz,
|
||||||
|
a.scripts,
|
||||||
|
a.binaries,
|
||||||
|
a.zipfiles,
|
||||||
|
a.datas,
|
||||||
|
[],
|
||||||
|
name='OCLP-CLI',
|
||||||
|
debug=False,
|
||||||
|
bootloader_ignore_signals=False,
|
||||||
|
strip=False,
|
||||||
|
upx=True,
|
||||||
|
upx_exclude=[],
|
||||||
|
runtime_tmpdir=None,
|
||||||
|
console=True )
|
||||||
+20
-10
@@ -256,10 +256,12 @@ class PatchSysVolume:
|
|||||||
subprocess.run(f"sudo bless --mount {self.mount_location} --bootefi --last-sealed-snapshot".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
subprocess.run(f"sudo bless --mount {self.mount_location} --bootefi --last-sealed-snapshot".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
||||||
|
|
||||||
def rebuild_snapshot(self):
|
def rebuild_snapshot(self):
|
||||||
input("Press [ENTER] to continue with cache rebuild")
|
if self.constants.gui_mode is False:
|
||||||
|
input("Press [ENTER] to continue with cache rebuild")
|
||||||
print("- Rebuilding Kernel Cache (This may take some time)")
|
print("- Rebuilding Kernel Cache (This may take some time)")
|
||||||
subprocess.run(f"sudo kmutil install --volume-root {self.mount_location} --update-all".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
subprocess.run(f"sudo kmutil install --volume-root {self.mount_location} --update-all".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
||||||
input("Press [ENTER] to continue with snapshotting")
|
if self.constants.gui_mode is False:
|
||||||
|
input("Press [ENTER] to continue with snapshotting")
|
||||||
print("- Creating new APFS snapshot")
|
print("- Creating new APFS snapshot")
|
||||||
subprocess.run(f"sudo bless --folder {self.mount_location}/System/Library/CoreServices --bootefi --create-snapshot".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
subprocess.run(f"sudo bless --folder {self.mount_location}/System/Library/CoreServices --bootefi --create-snapshot".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
||||||
|
|
||||||
@@ -295,9 +297,12 @@ class PatchSysVolume:
|
|||||||
def check_files(self):
|
def check_files(self):
|
||||||
if Path(self.constants.payload_apple_root_path).exists():
|
if Path(self.constants.payload_apple_root_path).exists():
|
||||||
print("- Found Apple Binaries")
|
print("- Found Apple Binaries")
|
||||||
patch_input = input("Would you like to redownload?(y/n): ")
|
if self.constants.gui_mode is False:
|
||||||
if patch_input in {"y", "Y", "yes", "Yes"}:
|
patch_input = input("Would you like to redownload?(y/n): ")
|
||||||
shutil.rmtree(Path(self.constants.payload_apple_root_path))
|
if patch_input in {"y", "Y", "yes", "Yes"}:
|
||||||
|
shutil.rmtree(Path(self.constants.payload_apple_root_path))
|
||||||
|
self.download_files()
|
||||||
|
else:
|
||||||
self.download_files()
|
self.download_files()
|
||||||
else:
|
else:
|
||||||
print("- Apple binaries missing")
|
print("- Apple binaries missing")
|
||||||
@@ -319,7 +324,8 @@ class PatchSysVolume:
|
|||||||
os.rename(self.constants.payload_apple_root_path_unzip, self.constants.payload_apple_root_path)
|
os.rename(self.constants.payload_apple_root_path_unzip, self.constants.payload_apple_root_path)
|
||||||
print("- Binaries downloaded to:")
|
print("- Binaries downloaded to:")
|
||||||
print(self.constants.payload_path)
|
print(self.constants.payload_path)
|
||||||
input("Press [ENTER] to continue")
|
if self.constants.gui_mode is False:
|
||||||
|
input("Press [ENTER] to continue")
|
||||||
except zipfile.BadZipFile:
|
except zipfile.BadZipFile:
|
||||||
print("- Couldn't unzip")
|
print("- Couldn't unzip")
|
||||||
os.remove(self.constants.payload_apple_root_path_zip)
|
os.remove(self.constants.payload_apple_root_path_zip)
|
||||||
@@ -342,7 +348,8 @@ class PatchSysVolume:
|
|||||||
Utilities.cls()
|
Utilities.cls()
|
||||||
if (self.sip_patch_status is False) and (self.smb_status is False):
|
if (self.sip_patch_status is False) and (self.smb_status is False):
|
||||||
print("- Detected SIP and SecureBootModel are disabled, continuing")
|
print("- Detected SIP and SecureBootModel are disabled, continuing")
|
||||||
input("\nPress [ENTER] to continue")
|
if self.constants.gui_mode is False:
|
||||||
|
input("\nPress [ENTER] to continue")
|
||||||
self.check_files()
|
self.check_files()
|
||||||
if self.constants.payload_apple_root_path.exists():
|
if self.constants.payload_apple_root_path.exists():
|
||||||
self.find_mount_root_vol(True)
|
self.find_mount_root_vol(True)
|
||||||
@@ -362,7 +369,8 @@ class PatchSysVolume:
|
|||||||
print("FileVault enabled, unable to patch!")
|
print("FileVault enabled, unable to patch!")
|
||||||
print("Please disable FileVault in System Preferences")
|
print("Please disable FileVault in System Preferences")
|
||||||
print("")
|
print("")
|
||||||
input("Press [Enter] to go exit.")
|
if self.constants.gui_mode is False:
|
||||||
|
input("Press [Enter] to go exit.")
|
||||||
|
|
||||||
def start_unpatch(self):
|
def start_unpatch(self):
|
||||||
if self.constants.custom_model is not None:
|
if self.constants.custom_model is not None:
|
||||||
@@ -374,7 +382,8 @@ class PatchSysVolume:
|
|||||||
Utilities.cls()
|
Utilities.cls()
|
||||||
if (self.sip_patch_status is False) and (self.smb_status is False):
|
if (self.sip_patch_status is False) and (self.smb_status is False):
|
||||||
print("- Detected SIP and SecureBootModel are disabled, continuing")
|
print("- Detected SIP and SecureBootModel are disabled, continuing")
|
||||||
input("\nPress [ENTER] to continue")
|
if self.constants.gui_mode is False:
|
||||||
|
input("\nPress [ENTER] to continue")
|
||||||
self.find_mount_root_vol(False)
|
self.find_mount_root_vol(False)
|
||||||
self.unmount_drive()
|
self.unmount_drive()
|
||||||
print("- Unpatching complete")
|
print("- Unpatching complete")
|
||||||
@@ -392,4 +401,5 @@ class PatchSysVolume:
|
|||||||
print("FileVault enabled, unable to unpatch!")
|
print("FileVault enabled, unable to unpatch!")
|
||||||
print("Please disable FileVault in System Preferences")
|
print("Please disable FileVault in System Preferences")
|
||||||
print("")
|
print("")
|
||||||
input("Press [Enter] to go exit.")
|
if self.constants.gui_mode is False:
|
||||||
|
input("Press [Enter] to go exit.")
|
||||||
|
|||||||
Reference in New Issue
Block a user