Compare commits
117 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8683e4e27 | ||
|
|
7bb4aea2c0 | ||
|
|
30375b869b | ||
|
|
5c207e0a2b | ||
|
|
92324ede72 | ||
|
|
158dac6ab4 | ||
|
|
dfc4a7b2fc | ||
|
|
b205f7943a | ||
|
|
1163aaa4bd | ||
|
|
3dcf20f0c2 | ||
|
|
8502ec5f78 | ||
|
|
54616ea385 | ||
|
|
d1f9170390 | ||
|
|
d4d16c3e56 | ||
|
|
751bdceafd | ||
|
|
80dcea163f | ||
|
|
c2eef22f2d | ||
|
|
299fed997d | ||
|
|
711c512258 | ||
|
|
07b9a1a2c6 | ||
|
|
c78506501f | ||
|
|
5612837492 | ||
|
|
80644bfbd4 | ||
|
|
b924e427e2 | ||
|
|
0cbd1422fe | ||
|
|
461f9ddb9b | ||
|
|
b2e5037c2e | ||
|
|
be3e7da342 | ||
|
|
b4830dfd0b | ||
|
|
b8bdab3576 | ||
|
|
a56f3af99c | ||
|
|
0e969ee6cd | ||
|
|
0bd3ce595d | ||
|
|
ea05912b6b | ||
|
|
a756058006 | ||
|
|
bd3985ce6c | ||
|
|
1e80691c67 | ||
|
|
023fec03aa | ||
|
|
64b9e7ada6 | ||
|
|
efda41fb3a | ||
|
|
77fccad046 | ||
|
|
cc914aadc1 | ||
|
|
5ea1b5075b | ||
|
|
41295e4cb2 | ||
|
|
7d5eea977d | ||
|
|
65fc232a25 | ||
|
|
43a708d3ae | ||
|
|
c8bb3a3e93 | ||
|
|
7e236f06e5 | ||
|
|
cc1b8781ab | ||
|
|
6553562e53 | ||
|
|
31812f0485 | ||
|
|
7ecf9ff151 | ||
|
|
54b4c27d4a | ||
|
|
7ed691993c | ||
|
|
14de472b6a | ||
|
|
fd67032afe | ||
|
|
cb808dc7ca | ||
|
|
3a65f005fe | ||
|
|
a0978dfd20 | ||
|
|
e701b5b851 | ||
|
|
4cc2dab964 | ||
|
|
ca44ba775a | ||
|
|
b2bb32f988 | ||
|
|
0956ad0d3d | ||
|
|
bf7b63c1be | ||
|
|
c34781bb3c | ||
|
|
e962f2bb8f | ||
|
|
a381f1d3bb | ||
|
|
4b6125d583 | ||
|
|
dfa396f385 | ||
|
|
3fc7424086 | ||
|
|
c37e035b6d | ||
|
|
0b21472ccb | ||
|
|
f66f16441b | ||
|
|
f512b7336a | ||
|
|
e35b115b81 | ||
|
|
dfe64e95b2 | ||
|
|
e626c79c81 | ||
|
|
98b08432fa | ||
|
|
7a7f1ce090 | ||
|
|
78f191dd5b | ||
|
|
e9e72d9641 | ||
|
|
a2500e50c2 | ||
|
|
6d917fbc29 | ||
|
|
c9cb6db0e4 | ||
|
|
0d72f46cb4 | ||
|
|
3884ca77d5 | ||
|
|
66a2d67ed9 | ||
|
|
5ed5f3aa15 | ||
|
|
86af9e96f4 | ||
|
|
5b97685274 | ||
|
|
3c929edd4b | ||
|
|
dfec8f2d72 | ||
|
|
5ff1110e90 | ||
|
|
9b5d25b2be | ||
|
|
0e25f2f3cf | ||
|
|
ee0b04f05b | ||
|
|
3c08127013 | ||
|
|
a17ca2c330 | ||
|
|
0cb2c84968 | ||
|
|
aa8643f247 | ||
|
|
554925d311 | ||
|
|
fbd7150c00 | ||
|
|
8233e15e42 | ||
|
|
7c21628ea2 | ||
|
|
118853cd46 | ||
|
|
7e29758fea | ||
|
|
a8f56c1ec8 | ||
|
|
79cd9c76f8 | ||
|
|
fc7656bb25 | ||
|
|
e3ec7f7137 | ||
|
|
1f2ee627f4 | ||
|
|
91f5d9778c | ||
|
|
fbcf958ead | ||
|
|
0d402c4dba | ||
|
|
b51beb8707 |
11
.github/workflows/build-app-offline.yml
vendored
@@ -10,17 +10,24 @@ jobs:
|
||||
build:
|
||||
name: Build Offline TUI
|
||||
runs-on: x86_64_mojave
|
||||
env:
|
||||
branch: ${{ github.event.ref }}
|
||||
commiturl: ${{ github.event.head_commit.url }}
|
||||
commitdate: ${{ github.event.head_commit.timestamp }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: python3 create_offline_build.py
|
||||
- run: /Library/Frameworks/Python.framework/Versions/3.9/bin/pyinstaller OpenCore-Patcher.spec
|
||||
- run: python3 ./payloads/binary.py $branch $commiturl $commitdate
|
||||
- run: ./after_pyinstaller.sh
|
||||
- run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"'
|
||||
- run: cd dist; zip -r ../OpenCore-Patcher-TUI-Offline.app.zip OpenCore-Patcher.app
|
||||
- run: cd dist; zip -r ../OpenCore-Patcher-TUI.app.zip OpenCore-Patcher.app
|
||||
- run: ./../sign-tui.sh
|
||||
- run: mv ./OpenCore-Patcher-TUI.app.zip ./OpenCore-Patcher-TUI-Offline.app.zip
|
||||
- name: Upload App to Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: OpenCore-Patcher-TUI-Offline.app
|
||||
name: OpenCore-Patcher-TUI.app (Offline)
|
||||
path: OpenCore-Patcher-TUI-Offline.app.zip
|
||||
|
||||
- name: Upload to Release
|
||||
|
||||
40
.github/workflows/build-app-wxpython-offline.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
name: CI - Build wxPython Offline
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build wxPython Offline
|
||||
runs-on: x86_64_mojave
|
||||
env:
|
||||
branch: ${{ github.event.ref }}
|
||||
commiturl: ${{ github.event.head_commit.url }}
|
||||
commitdate: ${{ github.event.head_commit.timestamp }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: python3 create_offline_build.py
|
||||
- run: /Library/Frameworks/Python.framework/Versions/3.9/bin/pyinstaller OpenCore-Patcher-GUI.spec
|
||||
- run: python3 ./payloads/binary.py $branch $commiturl $commitdate
|
||||
- run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"'
|
||||
- run: cd dist; zip -r ../OpenCore-Patcher-wxPython.app.zip OpenCore-Patcher.app
|
||||
- run: ./../sign-wxpython.sh
|
||||
- run: mv ./OpenCore-Patcher-wxPython.app.zip ./OpenCore-Patcher-GUI-Offline.app.zip
|
||||
- name: Upload App to Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: OpenCore-Patcher.app (GUI Offline)
|
||||
path: OpenCore-Patcher-GUI-Offline.app.zip
|
||||
- name: Upload to Release
|
||||
if: github.event_name == 'release'
|
||||
uses: svenstaro/upload-release-action@e74ff71f7d8a4c4745b560a485cc5fdb9b5b999d
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: OpenCore-Patcher-GUI-Offline.app.zip
|
||||
tag: ${{ github.ref }}
|
||||
file_glob: true
|
||||
- name: Validate OpenCore
|
||||
run: ./dist/OpenCore-Patcher.app/Contents/MacOS/OpenCore-Patcher --validate
|
||||
37
.github/workflows/build-app-wxpython.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: CI - Build wxPython
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build wxPython
|
||||
runs-on: x86_64_mojave
|
||||
env:
|
||||
branch: ${{ github.event.ref }}
|
||||
commiturl: ${{ github.event.head_commit.url }}
|
||||
commitdate: ${{ github.event.head_commit.timestamp }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: /Library/Frameworks/Python.framework/Versions/3.9/bin/pyinstaller OpenCore-Patcher-GUI.spec
|
||||
- run: python3 ./payloads/binary.py $branch $commiturl $commitdate
|
||||
- run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"'
|
||||
- run: cd dist; zip -r ../OpenCore-Patcher-wxPython.app.zip OpenCore-Patcher.app
|
||||
- run: ./../sign-wxpython.sh
|
||||
- run: mv ./OpenCore-Patcher-wxPython.app.zip ./OpenCore-Patcher-GUI.app.zip
|
||||
- name: Upload App to Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: OpenCore-Patcher.app (GUI)
|
||||
path: OpenCore-Patcher-GUI.app.zip
|
||||
- name: Upload to Release
|
||||
if: github.event_name == 'release'
|
||||
uses: svenstaro/upload-release-action@e74ff71f7d8a4c4745b560a485cc5fdb9b5b999d
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: OpenCore-Patcher-GUI.app.zip
|
||||
tag: ${{ github.ref }}
|
||||
file_glob: true
|
||||
5
.github/workflows/build-app.yml
vendored
@@ -10,9 +10,14 @@ jobs:
|
||||
build:
|
||||
name: Build TUI
|
||||
runs-on: x86_64_mojave
|
||||
env:
|
||||
branch: ${{ github.event.ref }}
|
||||
commiturl: ${{ github.event.head_commit.url }}
|
||||
commitdate: ${{ github.event.head_commit.timestamp }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: /Library/Frameworks/Python.framework/Versions/3.9/bin/pyinstaller OpenCore-Patcher.spec
|
||||
- run: python3 ./payloads/binary.py $branch $commiturl $commitdate
|
||||
- run: ./after_pyinstaller.sh
|
||||
- run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"'
|
||||
- run: cd dist; zip -r ../OpenCore-Patcher-TUI.app.zip OpenCore-Patcher.app
|
||||
|
||||
52
.github/workflows/build-gui.yml
vendored
@@ -1,52 +0,0 @@
|
||||
name: CI - Build GUI
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build GUI
|
||||
runs-on: x86_64_mojave
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- run: /Library/Frameworks/Python.framework/Versions/3.9/bin/pyinstaller OpenCore-Patcher.spec
|
||||
- run: cd dist; cp OpenCore-Patcher ../; cd ..; mv OpenCore-Patcher OCLP-CLI
|
||||
- name: Download latest nightly OCLP-GUI
|
||||
run: curl -S -L https://nightly.link/dortania/OCLP-GUI/workflows/build-app/master/OpenCore-Patcher-GUI.app.zip --output ./OpenCore-Patcher-GUI.app.zip --insecure
|
||||
- run: unzip -o OpenCore-Patcher-GUI.app.zip
|
||||
- run: unzip OpenCore-Patcher-GUI.app.zip; rm OpenCore-Patcher-GUI.app.zip
|
||||
- name: Merge new GUI
|
||||
run: cp OCLP-CLI OpenCore\ Patcher.app/Contents/Resources/
|
||||
- run: python3 merge_gui.py
|
||||
- name: Code Sign Binaries
|
||||
run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "OpenCore Patcher.app/Contents/Resources/OCLP-CLI"'
|
||||
- run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "OpenCore Patcher.app/Contents/Resources/oclpd"'
|
||||
- run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "OpenCore Patcher.app"'
|
||||
- run: ditto -c -k --sequesterRsrc --keepParent OpenCore\ Patcher.app OpenCore-Patcher-GUI.app.zip
|
||||
- name: Notarize Binaries for release
|
||||
if: github.event_name == 'release'
|
||||
run: ./../sign-gui.sh
|
||||
- name: Upload GUI to Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: OpenCore-Patcher-GUI.app
|
||||
path: OpenCore-Patcher-GUI.app.zip
|
||||
- name: Upload CLI to Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: OCLP-CLI
|
||||
path: OCLP-CLI
|
||||
- name: Upload to Release
|
||||
if: github.event_name == 'release'
|
||||
uses: svenstaro/upload-release-action@e74ff71f7d8a4c4745b560a485cc5fdb9b5b999d
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: OpenCore-Patcher-GUI.app.zip
|
||||
tag: ${{ github.ref }}
|
||||
file_glob: true
|
||||
- name: Validate OpenCore
|
||||
run: ./OCLP-CLI --validate
|
||||
1
.gitignore
vendored
@@ -21,3 +21,4 @@ __pycache__/
|
||||
/docs/yarn-error.log
|
||||
/docs/node_modules/
|
||||
/payloads/List.txt
|
||||
/payloads/Installer.sh
|
||||
|
||||
39
CHANGELOG.md
@@ -1,5 +1,44 @@
|
||||
# OpenCore Legacy Patcher changelog
|
||||
|
||||
## 0.4.1
|
||||
- Add XHCI Boot Support to pre-UEFI 2.0 Macs
|
||||
- Applicable to pre-Ivy Macs with upgraded USB 3.0 controllers, allows USB 3.0 boot
|
||||
- Credit to Jazzzny for research and testing
|
||||
- Drivers stripped from MacPro6,1 firmware
|
||||
- Resolve OCLP-Helper dyld crash
|
||||
|
||||
## 0.4.0
|
||||
- Resolves Install USB Creation using incorrect installer
|
||||
- Resolves `installer` failing to extract InstallAssistant in older OSes
|
||||
- Resolves certain Samsung NVMe drives appearing as external on Mac Pros
|
||||
- Add FeatureUnlock configurability
|
||||
- Add NVRAM WriteFlash configurability for degarded/fragile systems
|
||||
- Add `ThirdPartyDrives` quirk configurability
|
||||
- Resolve Skylight dylib injection issue
|
||||
- Increment Binaries:
|
||||
- OpenCore 0.7.7 - release
|
||||
- RestrictEvents 1.0.6 - release
|
||||
- FeatureUnlock 1.0.6 - rolling (1d0bc7b)
|
||||
- WhateverGreen 1.5.6 - release
|
||||
- Lilu 1.5.9 - release
|
||||
- gfxutil 1.8.2b - release
|
||||
- PatcherSupportPkg 0.2.9 - release
|
||||
- Re-add Content Caching support for VMM-spoofed systems
|
||||
- Add wxPython Based GUI
|
||||
- Superceeds Obj-C Based GUI
|
||||
- Both standard and offline builds provided
|
||||
- Allow optional spoofing on native Models
|
||||
- Recommended for systems that cannot update their firmware natively (ie. dead internal drive)
|
||||
- Add Dropbox fix for non-Metal on Monterey
|
||||
- Add App Update checks to GUI
|
||||
- If new version available, app will prompt on launch.
|
||||
- Configurable in Developer Settings
|
||||
- Resolved OS crashing on slow Macs with FeatureUnlock
|
||||
- Disable Windows GMUX support by default
|
||||
- Resolves brightness control issues on MacBookPro11,3 in Windows
|
||||
- Configurable in Developer Settings
|
||||
- Add Commit Data to Info.plist
|
||||
|
||||
## 0.3.3
|
||||
- Disable Asset Caching support with spoofless approach
|
||||
- Switch to Minimal or higher if required
|
||||
|
||||
6
OpenCore-Patcher-GUI.command
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||
from resources import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
main.OpenCoreLegacyPatcher(True)
|
||||
55
OpenCore-Patcher-GUI.spec
Normal file
@@ -0,0 +1,55 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
import sys, os, time, subprocess
|
||||
sys.path.append(os.path.abspath(os.getcwd()))
|
||||
from resources import constants
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['OpenCore-Patcher-GUI.command'],
|
||||
pathex=['resources', 'data', 'gui'],
|
||||
binaries=[],
|
||||
datas=[('payloads', 'payloads')],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
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='OpenCore-Patcher',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=False,
|
||||
disable_windowed_traceback=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None )
|
||||
app = BUNDLE(exe,
|
||||
name='OpenCore-Patcher.app',
|
||||
icon="payloads/OC-Patcher.icns",
|
||||
bundle_identifier="com.dortania.opencore-legacy-patcher-wxpython",
|
||||
info_plist={
|
||||
"CFBundleShortVersionString": constants.Constants().patcher_version,
|
||||
"NSHumanReadableCopyright": "Copyright 2020-2022 Dortania",
|
||||
"LSMinimumSystemVersion": "10.10.0",
|
||||
"NSRequiresAquaSystemAppearance": False,
|
||||
"NSHighResolutionCapable": True,
|
||||
"Build Date": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
|
||||
"BuildMachineOSBuild": subprocess.run("sw_vers -buildVersion".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode().strip(),
|
||||
})
|
||||
@@ -1,92 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (C) 2020-2021, Dhinak G, Mykola Grymalyuk
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from resources import build, cli_menu, constants, utilities, device_probe, os_probe, defaults, arguments, install
|
||||
from data import model_array
|
||||
|
||||
|
||||
class OpenCoreLegacyPatcher:
|
||||
def __init__(self):
|
||||
print("- Loading...")
|
||||
self.constants = constants.Constants()
|
||||
self.generate_base_data()
|
||||
if utilities.check_cli_args() is None:
|
||||
self.main_menu()
|
||||
|
||||
def generate_base_data(self):
|
||||
self.constants.detected_os = os_probe.detect_kernel_major()
|
||||
self.constants.detected_os_minor = os_probe.detect_kernel_minor()
|
||||
self.constants.detected_os_build = os_probe.detect_kernel_build()
|
||||
self.constants.computer = device_probe.Computer.probe()
|
||||
self.constants.recovery_status = utilities.check_recovery()
|
||||
self.computer = self.constants.computer
|
||||
defaults.generate_defaults.probe(self.computer.real_model, True, self.constants)
|
||||
if utilities.check_cli_args() is not None:
|
||||
print("- Detected arguments, switching to CLI mode")
|
||||
self.constants.gui_mode = True # Assumes no user interaction is required
|
||||
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")
|
||||
arguments.arguments().parse_arguments(self.constants)
|
||||
else:
|
||||
print("- No arguments present, loading TUI")
|
||||
|
||||
def main_menu(self):
|
||||
response = None
|
||||
while not (response and response == -1):
|
||||
title = [
|
||||
f"OpenCore Legacy Patcher v{self.constants.patcher_version}",
|
||||
f"Selected Model: {self.constants.custom_model or self.computer.real_model}",
|
||||
]
|
||||
|
||||
if (self.constants.custom_model or self.computer.real_model) not in model_array.SupportedSMBIOS and self.constants.allow_oc_everywhere is False:
|
||||
in_between = [
|
||||
"Your model is not supported by this patcher for running unsupported OSes!",
|
||||
"",
|
||||
'If you plan to create the USB for another machine, please select the \n"Change Model" option in the menu.',
|
||||
"",
|
||||
'If you want to run OCLP on a native Mac, please toggle \n"Allow OpenCore on native Models" in settings',
|
||||
]
|
||||
elif not self.constants.custom_model and self.computer.real_model == "iMac7,1" and "SSE4.1" not in self.computer.cpu.flags:
|
||||
in_between = [
|
||||
"Your model requires a CPU upgrade to a CPU supporting SSE4.1+ to be supported by this patcher!",
|
||||
"",
|
||||
f'If you plan to create the USB for another {self.computer.real_model} with SSE4.1+, please select the "Change Model" option in the menu.',
|
||||
]
|
||||
elif self.constants.custom_model == "iMac7,1":
|
||||
in_between = ["This model is supported", "However please ensure the CPU has been upgraded to support SSE4.1+"]
|
||||
else:
|
||||
in_between = ["This model is supported"]
|
||||
|
||||
menu = utilities.TUIMenu(title, "Please select an option: ", in_between=in_between, auto_number=True, top_level=True)
|
||||
|
||||
options = (
|
||||
[["Build OpenCore", build.BuildOpenCore(self.constants.custom_model or self.constants.computer.real_model, self.constants).build_opencore]]
|
||||
if ((self.constants.custom_model or self.computer.real_model) in model_array.SupportedSMBIOS) or self.constants.allow_oc_everywhere is True
|
||||
else []
|
||||
) + [
|
||||
["Install OpenCore to USB/internal drive", install.tui_disk_installation(self.constants).copy_efi],
|
||||
["Post-Install Volume Patch", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).PatchVolume],
|
||||
["Change Model", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).change_model],
|
||||
["Patcher Settings", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).patcher_settings],
|
||||
["Installer Creation", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).download_macOS],
|
||||
["Credits", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).credits],
|
||||
]
|
||||
|
||||
for option in options:
|
||||
menu.add_menu_option(option[0], function=option[1])
|
||||
|
||||
response = menu.start()
|
||||
|
||||
if getattr(sys, "frozen", False) and self.constants.recovery_status is False:
|
||||
subprocess.run("""osascript -e 'tell application "Terminal" to close first window' & exit""", shell=True)
|
||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||
from resources import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
OpenCoreLegacyPatcher()
|
||||
main.OpenCoreLegacyPatcher()
|
||||
@@ -12,7 +12,7 @@ a = Analysis(['OpenCore-Patcher.command'],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
excludes=['wxPython', 'wxpython'],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
@@ -40,5 +40,5 @@ app = BUNDLE(exe,
|
||||
info_plist={
|
||||
"CFBundleShortVersionString": constants.Constants().patcher_version,
|
||||
"CFBundleExecutable": "MacOS/Launcher",
|
||||
"NSHumanReadableCopyright": "Copyright 2020-2021 Dortania"
|
||||
"NSHumanReadableCopyright": "Copyright 2020-2022 Dortania"
|
||||
})
|
||||
@@ -3,7 +3,7 @@
|
||||
<h1>OpenCore Legacy Patcher</h1>
|
||||
</div>
|
||||
|
||||
A python program with an [Objective-C GUI](https://github.com/dortania/OCLP-GUI) for building and booting [OpenCore](https://github.com/acidanthera/OpenCorePkg) on both legacy and modern Macs, see our in-depth [Guide](https://dortania.github.io/OpenCore-Legacy-Patcher/) for more information.
|
||||
A python program for building and booting [OpenCore](https://github.com/acidanthera/OpenCorePkg) on both legacy and modern Macs, see our in-depth [Guide](https://dortania.github.io/OpenCore-Legacy-Patcher/) for more information.
|
||||
|
||||
Supported features:
|
||||
|
||||
|
||||
41
SOURCE.md
@@ -4,9 +4,10 @@ OpenCore Legacy Patcher at its core is a python-based TUI/CLI based application.
|
||||
|
||||
For developers wishing to validate mainline changes, you may use these nightly links:
|
||||
|
||||
* [GUI (Graphical Based App)](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-gui/main/OpenCore-Patcher-GUI.app.zip)
|
||||
* [GUI (Graphical Based App)](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app-wxpython/main/OpenCore-Patcher.app%20%28GUI%29.zip)
|
||||
* [GUI (Graphical Based App) - Offline Variant](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app-wxpython-offline/main/OpenCore-Patcher.app%20%28GUI%20Offline%29.zip)
|
||||
* [TUI (Text Based App)](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app/main/OpenCore-Patcher-TUI.app.zip)
|
||||
* [TUI (Text Based App) - Offline Variant](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app/main/OpenCore-Patcher-TUI-Offline.app.zip)
|
||||
* [TUI (Text Based App) - Offline Variant](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app-offline/main/OpenCore-Patcher-TUI.app%20%28Offline%29.zip)
|
||||
|
||||
**Warning**: These binaries should not be used without first consulting the [CHANGELOG](./CHANGELOG.md). Do not distribute these links in forums, instead direct to this file.
|
||||
|
||||
@@ -36,12 +37,19 @@ pip3 install -r requirements.txt
|
||||
To run the project from source, simply invoke via python3:
|
||||
|
||||
```sh
|
||||
# Launch TUI
|
||||
python3 OpenCore-Patcher.command
|
||||
```
|
||||
|
||||
```sh
|
||||
# Launch GUI
|
||||
python3 OpenCore-Patcher-GUI.command
|
||||
```
|
||||
|
||||
Note that the OpenCore-Patcher.command file can be run as both a TUI and a CLI utility for other programs to call. If no core arguments are passed, the TUI is initialized. Otherwise the CLI will start:
|
||||
|
||||
```sh
|
||||
# Launch CLI
|
||||
python3 OpenCore-Patcher.command --build --model iMac12,2 --verbose
|
||||
```
|
||||
|
||||
@@ -49,7 +57,7 @@ See `-h`/`--help` for more information on supported CLI arguments.
|
||||
|
||||
## Generating prebuilt binaries
|
||||
|
||||
The main goal of generating prebuilt binaries is to strip the requirement of a local python installation for users. For developers, there's very little benefit besides for usage with the project's GUI ([Generating the GUI](#generating-the-gui)). For development, simply use the OpenCore-Patcher.command file with a python3 installation.
|
||||
The main goal of generating prebuilt binaries is to strip the requirement of a local python installation for users. For developers, there's very little benefit besides enabling dark mode support in the GUI. For development, simply use the OpenCore-Patcher.command file with a python3 installation.
|
||||
|
||||
* Note that due to PyInstaller's linking mechanism, binaries generated on Catalina and newer are not compatible with High Sierra and older
|
||||
* To ensure the largest compatibility, generate binaries on macOS Mojave. These binaries will be compatible with macOS 10.9 to macOS 12.
|
||||
@@ -60,9 +68,9 @@ The main goal of generating prebuilt binaries is to strip the requirement of a l
|
||||
pip3 install pyinstaller
|
||||
# Move into project directory
|
||||
cd ~/Developer/OpenCore-Legacy-Patcher/
|
||||
# Create the pyinstaller based Application
|
||||
# Create the pyinstaller based Application (replace OpenCore-Patcher.spec with OpenCore-Patcher-GUI.spec for GUI binary)
|
||||
pyinstaller OpenCore-Patcher.spec
|
||||
# Post PyInstaller clean up
|
||||
# Post PyInstaller clean up (only for the TUI)
|
||||
./after_pyinstaller.sh
|
||||
# Open build folder
|
||||
open ./dist/
|
||||
@@ -70,25 +78,4 @@ open ./dist/
|
||||
|
||||
Once done, you'll find the application generated at `./dist/OpenCore-Patcher.app`:
|
||||
|
||||

|
||||
|
||||
## Generating the GUI
|
||||
|
||||
To generate a GUI, you will have need a core `OpenCore-Patcher` binary generated during the above stage([Generating prebuilt binaries](#generating-prebuilt-binaries)).
|
||||
|
||||
Once conditions are met, you'll be able to work with the GUI portion. The source of which is found at [dortania/OCLP-GUI](https://github.com/dortania/OCLP-GUI).
|
||||
|
||||
```sh
|
||||
# Move into a directory to store the project
|
||||
cd ~/Developer
|
||||
# Clone project
|
||||
git clone https://github.com/dortania/OCLP-GUI
|
||||
# Update the OpenCore-Patcher binary from the core project
|
||||
cp ./OpenCore-Legacy-Patcher/dist/OpenCore-Patcher ./OCLP-GUI/OpenCore\ Patcher/OpenCore\ Patcher/
|
||||
# Rename binary to OCLP-CLI
|
||||
mv ./OCLP-GUI/OpenCore\ Patcher/OpenCore\ Patcher/OCLP-GUI/OpenCore-Patcher ./OCLP-GUI/OpenCore\ Patcher/OpenCore\ Patcher/OCLP-GUI/OCLP-CLI
|
||||
# Build project
|
||||
cd ./OCLP-GUI/OpenCore\ Patcher; xcodebuild; cd ../../
|
||||
# Open build folder
|
||||
open ./OCLP-GUI/OpenCore\ Patcher/build/Release/
|
||||
```
|
||||

|
||||
@@ -1,8 +1,8 @@
|
||||
# Data for SkyLightShim Plugin systems
|
||||
class shim_list:
|
||||
shim_pathing = {
|
||||
"CoreWLAN.dylib": "/Systen/Library/CoreServices/WiFiAgent.app/Contents/MacOS/WiFiAgent",
|
||||
"BacklightFixup.dylib": "/System/Library/CoreServices/loginwindow.app/Contents/Mac0S/loginwindow",
|
||||
"CoreWLAN.dylib": "/System/Library/CoreServices/WiFiAgent.app/Contents/MacOS/WiFiAgent",
|
||||
"BacklightFixup.dylib": "/System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow",
|
||||
}
|
||||
|
||||
shim_legacy_accel = [
|
||||
|
||||
@@ -179,6 +179,31 @@ class iMac:
|
||||
opencore_version=None,
|
||||
)
|
||||
|
||||
iMac151_Stock = device_probe.Computer(
|
||||
real_model='iMac15,1',
|
||||
real_board_id='Mac-42FD25EABCABB274',
|
||||
reported_model='iMac15,1', reported_board_id='Mac-42FD25EABCABB274',
|
||||
gpus=[
|
||||
device_probe.Intel(vendor_id=32902, device_id=1042, class_code=196608, name='IGPU', model='Intel Iris Pro', acpi_path=None, pci_path='PciRoot(0x0)/Pci(0x2,0x0)'),
|
||||
device_probe.AMD(vendor_id=4098, device_id=26640, class_code=196608, name='GFX0', model='AMD Radeon R9 M290X', acpi_path=None, pci_path='PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)')
|
||||
],
|
||||
igpu=device_probe.Intel(vendor_id=32902, device_id=1042, class_code=196608, name='IGPU', model='Intel Iris Pro', acpi_path=None, pci_path='PciRoot(0x0)/Pci(0x2,0x0)'),
|
||||
dgpu=device_probe.AMD(vendor_id=4098, device_id=26640, class_code=196608, name='GFX0', model='AMD Radeon R9 M290X', acpi_path=None, pci_path='PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)'),
|
||||
storage=[
|
||||
device_probe.SATAController(vendor_id=32902, device_id=35842, class_code=67073, name='SATA', model=None, acpi_path=None, pci_path='PciRoot(0x0)/Pci(0x1f,0x2)'),
|
||||
device_probe.SATAController(vendor_id=6987, device_id=37251, class_code=67073, name='SSD0', model=None, acpi_path=None, pci_path='PciRoot(0x0)/Pci(0x1c,0x0)/Pci(0x0,0x0)')
|
||||
],
|
||||
wifi=device_probe.Broadcom(vendor_id=5348, device_id=17312, class_code=163840, name='ARPT', model=None, acpi_path=None, pci_path='PciRoot(0x0)/Pci(0x1c,0x2)/Pci(0x0,0x0)'),
|
||||
cpu=device_probe.CPU(
|
||||
name='Intel(R) Core(TM) i5-4690 CPU @ 3.50GHz',
|
||||
flags=['FPU', 'VME', 'DE', 'PSE', 'TSC', 'MSR', 'PAE', 'MCE', 'CX8', 'APIC', 'SEP', 'MTRR', 'PGE', 'MCA', 'CMOV', 'PAT', 'PSE36', 'CLFSH', 'DS', 'ACPI', 'MMX', 'FXSR', 'SSE', 'SSE2', 'SS', 'HTT', 'TM', 'PBE', 'SSE3', 'PCLMULQDQ', 'DTES64', 'MON', 'DSCPL', 'VMX', 'SMX', 'EST', 'TM2', 'SSSE3', 'FMA', 'CX16', 'TPR', 'PDCM', 'SSE4.1', 'SSE4.2', 'x2APIC', 'MOVBE', 'POPCNT', 'AES', 'PCID', 'XSAVE', 'OSXSAVE', 'SEGLIM64', 'TSCTMR', 'AVX1.0', 'RDRAND', 'F16C']
|
||||
),
|
||||
oclp_version=None,
|
||||
opencore_version=None,
|
||||
bluetooth_chipset='BRCM20702 Hub',
|
||||
third_party_sata_ssd=False
|
||||
)
|
||||
|
||||
class MacPro:
|
||||
|
||||
MacPro31_Stock = device_probe.Computer(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Lists all models and required patches
|
||||
# Copyright (C) 2020-2021, Dhinak G, Mykola Grymalyuk
|
||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||
SupportedSMBIOS = [
|
||||
# MacBook
|
||||
"MacBook4,1",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from data import os_data
|
||||
class system_integrity_protection:
|
||||
csr_values = {
|
||||
# Source: macOS 11.4 (XNU's csr.h)
|
||||
@@ -17,6 +18,101 @@ class system_integrity_protection:
|
||||
"CSR_ALLOW_UNAUTHENTICATED_ROOT": False, # 0x800 - Allow Root Volume Mounting - Introduced in Big Sur # noqa: E241
|
||||
}
|
||||
|
||||
csr_values_extended = {
|
||||
"CSR_ALLOW_UNTRUSTED_KEXTS": {
|
||||
"name": "CSR_ALLOW_UNTRUSTED_KEXTS",
|
||||
"description": "Allows Unsigned Kexts",
|
||||
"introduced": os_data.os_data.el_capitan.value,
|
||||
"introduced_friendly": "El Capitan",
|
||||
"value": 0x1,
|
||||
},
|
||||
"CSR_ALLOW_UNRESTRICTED_FS": {
|
||||
"name": "CSR_ALLOW_UNRESTRICTED_FS",
|
||||
"description": "File System Access",
|
||||
"introduced": os_data.os_data.el_capitan.value,
|
||||
"introduced_friendly": "El Capitan",
|
||||
"value": 0x2,
|
||||
},
|
||||
"CSR_ALLOW_TASK_FOR_PID": {
|
||||
"name": "CSR_ALLOW_TASK_FOR_PID",
|
||||
"description": "Unrestricted task_for_pid()",
|
||||
"introduced": os_data.os_data.el_capitan.value,
|
||||
"introduced_friendly": "El Capitan",
|
||||
"value": 0x4,
|
||||
},
|
||||
"CSR_ALLOW_KERNEL_DEBUGGER": {
|
||||
"name": "CSR_ALLOW_KERNEL_DEBUGGER",
|
||||
"description": "Allow Kernel Debugger",
|
||||
"introduced": os_data.os_data.el_capitan.value,
|
||||
"introduced_friendly": "El Capitan",
|
||||
"value": 0x8,
|
||||
},
|
||||
"CSR_ALLOW_APPLE_INTERNAL": {
|
||||
"name": "CSR_ALLOW_APPLE_INTERNAL",
|
||||
"description": "Set AppleInternal Features",
|
||||
"introduced": os_data.os_data.el_capitan.value,
|
||||
"introduced_friendly": "El Capitan",
|
||||
"value": 0x10,
|
||||
},
|
||||
# "CSR_ALLOW_DESTRUCTIVE_DTRACE": {
|
||||
# "name": "CSR_ALLOW_DESTRUCTIVE_DTRACE",
|
||||
# "description": "Allow destructive DTrace",
|
||||
# "deprecated": True,
|
||||
# "introduced": os_data.os_data.el_capitan.value,
|
||||
# "introduced_friendly": "El Capitan",
|
||||
# "value": 0x20,
|
||||
# },
|
||||
"CSR_ALLOW_UNRESTRICTED_DTRACE": {
|
||||
"name": "CSR_ALLOW_UNRESTRICTED_DTRACE",
|
||||
"description": "Unrestricted DTrace usage",
|
||||
"introduced": os_data.os_data.el_capitan.value,
|
||||
"introduced_friendly": "El Capitan",
|
||||
"value": 0x20,
|
||||
},
|
||||
"CSR_ALLOW_UNRESTRICTED_NVRAM": {
|
||||
"name": "CSR_ALLOW_UNRESTRICTED_NVRAM",
|
||||
"description": "Unrestricted NVRAM write",
|
||||
"introduced": os_data.os_data.el_capitan.value,
|
||||
"introduced_friendly": "El Capitan",
|
||||
"value": 0x40,
|
||||
},
|
||||
"CSR_ALLOW_DEVICE_CONFIGURATION": {
|
||||
"name": "CSR_ALLOW_DEVICE_CONFIGURATION",
|
||||
"description": "Allow custom DeviceTree (iOS)",
|
||||
"introduced": os_data.os_data.el_capitan.value,
|
||||
"introduced_friendly": "El Capitan",
|
||||
"value": 0x80,
|
||||
},
|
||||
"CSR_ALLOW_ANY_RECOVERY_OS": {
|
||||
"name": "CSR_ALLOW_ANY_RECOVERY_OS",
|
||||
"description": "Skip BaseSystem Verification",
|
||||
"introduced": os_data.os_data.sierra.value,
|
||||
"introduced_friendly": "Sierra",
|
||||
"value": 0x100,
|
||||
},
|
||||
"CSR_ALLOW_UNAPPROVED_KEXTS": {
|
||||
"name": "CSR_ALLOW_UNAPPROVED_KEXTS",
|
||||
"description": "Allow Unnotarized Kexts",
|
||||
"introduced": os_data.os_data.high_sierra.value,
|
||||
"introduced_friendly": "High Sierra",
|
||||
"value": 0x200,
|
||||
},
|
||||
"CSR_ALLOW_EXECUTABLE_POLICY_OVERRIDE": {
|
||||
"name": "CSR_ALLOW_EXECUTABLE_POLICY_OVERRIDE",
|
||||
"description": "Override Executable Policy",
|
||||
"introduced": os_data.os_data.mojave.value,
|
||||
"introduced_friendly": "Mojave",
|
||||
"value": 0x400,
|
||||
},
|
||||
"CSR_ALLOW_UNAUTHENTICATED_ROOT": {
|
||||
"name": "CSR_ALLOW_UNAUTHENTICATED_ROOT",
|
||||
"description": "Allow Root Volume Mounting",
|
||||
"introduced": os_data.os_data.big_sur.value,
|
||||
"introduced_friendly": "Big Sur",
|
||||
"value": 0x800,
|
||||
},
|
||||
}
|
||||
|
||||
root_patch_sip_mojave = [
|
||||
# Variables required to root patch in Mojave and Catalina
|
||||
"CSR_ALLOW_UNTRUSTED_KEXTS", # 0x1
|
||||
|
||||
@@ -2803,6 +2803,28 @@ smbios_dictionary = {
|
||||
"Stock GPUs": [],
|
||||
"Stock Storage": [],
|
||||
},
|
||||
"VMware7,1": {
|
||||
# VMware Virtual Machine
|
||||
"Board ID": "440BX Desktop Reference Platform",
|
||||
"FirmwareFeatures": None,
|
||||
"CPU Generation": cpu_data.cpu_data.penryn.value,
|
||||
"Max OS Supported": os_data.os_data.max_os,
|
||||
"Wireless Model": None,
|
||||
"Bluetooth Model": bluetooth_data.bluetooth_data.NonApplicable,
|
||||
"Stock GPUs": [],
|
||||
"Stock Storage": [],
|
||||
},
|
||||
"Parallels17,1": {
|
||||
# Parallels Virtual Machine
|
||||
"Board ID": "Parallels Virtual Platform",
|
||||
"FirmwareFeatures": None,
|
||||
"CPU Generation": cpu_data.cpu_data.penryn.value,
|
||||
"Max OS Supported": os_data.os_data.max_os,
|
||||
"Wireless Model": None,
|
||||
"Bluetooth Model": bluetooth_data.bluetooth_data.NonApplicable,
|
||||
"Stock GPUs": [],
|
||||
"Stock Storage": [],
|
||||
},
|
||||
"iBridge2,11": {
|
||||
# Unknown ID, Intel based, present in Monterey
|
||||
"Board ID": None,
|
||||
|
||||
@@ -18,4 +18,8 @@ After plenty of verbose booting, you will reach the installer screen! From there
|
||||
|
||||
* [OpenCore Legacy Patcher Boot Process](https://www.youtube.com/watch?v=AN3zsbQV_n4)
|
||||
|
||||
**MacBookPro11,3 Note**: When booting macOS Monterey, you'll need to boot into safe mode if acceleration patches are not installed yet. [Otherwise you'll hit a black screen due to missing Nvidia drivers.](https://github.com/dortania/OpenCore-Legacy-Patcher/issues/522)
|
||||
|
||||
* Safe Mode can be started by holding Shift+Enter when selecting macOS Monterey in OCLP's Boot Menu.
|
||||
|
||||
# Once installed and booting, head to [Post-Installation](./POST-INSTALL.md)
|
||||
|
||||
@@ -2,35 +2,27 @@
|
||||
|
||||
Now that we have a macOS installer, lets now build our OpenCore configuration!
|
||||
|
||||
First Download the latest release:
|
||||
If you haven't downloaded OpenCore Patcher yet, do so now:
|
||||
|
||||
* [OpenCore Legacy Patcher Releases](https://github.com/dortania/Opencore-Legacy-Patcher/releases)
|
||||
|
||||
Next, run the `OpenCore-Patcher.app`:
|
||||
|
||||

|
||||

|
||||
|
||||
From here you have a couple important options:
|
||||
Here we'll select Build and Install OpenCore and start building:
|
||||
|
||||
* Build OpenCore
|
||||
* Install OpenCore to USB/internal drive
|
||||
* Change Model
|
||||
* Patcher Settings
|
||||
|
||||
If you're patching for a different machine than you're running, please select "Change Model" and enter the updated SMBIOS. For more advanced users, you may also tweak the patcher's build settings via "Patcher Settings"
|
||||
|
||||
Now lets enter "Build OpenCore":
|
||||
|
||||

|
||||
|
||||
The process should be quite quick to build, once finished you'll be plopped back to the main menu.
|
||||
|
||||
Next lets run `Install OpenCore to USB/internal drive`:
|
||||
|
||||
| Select Drive | Select EFI/FAT32 Partition |
|
||||
| Start Building | Finished Building |
|
||||
| :--- | :--- |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|
||||
Once it finishes building, you'll want to select the Install OpenCore button:
|
||||
|
||||
* If you created a macOS USB manually and don't see it listed, make sure it's either formatted as GUID/GPT or has a FAT32 partition for OpenCore to sit on
|
||||
|
||||
|
||||
| Select Drive | Select Partition |
|
||||
| :--- | :--- |
|
||||
|  |  |
|
||||
|
||||
* If you have issues, please ensure you install OpenCore onto a FAT32 partition to ensure your Mac is able to boot it. You will need to format your drive as GUID/GPT in Disk Utility
|
||||
|
||||
# Once finished, head to [Booting OpenCore and macOS](./BOOT.md)
|
||||
|
||||
@@ -7,53 +7,46 @@ This doc is centered around downloading and writing the macOS installer to a USB
|
||||
|
||||
* Note: 16GB+ USB will be required for the installer
|
||||
|
||||
## Downloading
|
||||
## Creating the installer
|
||||
|
||||
The simplest way to download macOS installs would be to use installinstallmacos:
|
||||
With OpenCore Legacy Patcher, our new GUI includes a download menu for macOS installers. So to start off, you'll want to grab our app:
|
||||
|
||||
```sh
|
||||
[ ! -d ~/macOS-installer/ ] && mkdir ~/macOS-installer; cd ~/macOS-installer; [ ! -f ~/macOS-installer/installinstallmacos.py ] && curl -O https://raw.githubusercontent.com/munki/macadmin-scripts/main/installinstallmacos.py ; sudo python installinstallmacos.py
|
||||
```
|
||||
* [OpenCore Legacy Patcher Release Apps](https://github.com/dortania/OpenCore-Legacy-Patcher/releases)
|
||||
|
||||
* Note: On El Capitan (10.11) and older, you'll need to specify a catalog at the end of the command:
|
||||
For this guide, we'll be using the standard OpenCore-Patcher (GUI).
|
||||
|
||||
```
|
||||
--catalogurl https://swscan.apple.com/content/catalogs/others/index-11-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog
|
||||
```
|
||||
Once downloaded, open the app and you should be greeted with this menu:
|
||||
|
||||

|
||||

|
||||
|
||||
As you can see, we get a nice list of macOS installers. If you need a particular versions of macOS, you can select it by typing the number next to it. For this example we'll choose 10:
|
||||
First we'll want to select the "Create macOS Installer" button. This will present you with 2 options:
|
||||
|
||||

|
||||

|
||||
|
||||
This is going to take a while as we're downloading the entire 12GB+ macOS installer.
|
||||
For this example, we'll assume you'll need an installer. Selecting this option will download Apple's Installer Catalogs and build a list for you to choose:
|
||||
|
||||
Once finished, you'll find in your `~/macOS-Installer/` folder a DMG containing the macOS Installer, called `Install_macOS_11.1-20C69.dmg` for example. Mount it and you'll find the installer application.
|
||||
|
||||
* Note: We recommend to move the Install macOS.app into the `/Applications` folder, as we'll be executing commands from there.
|
||||
* Note 2: Running Cmd+Shift+G in Finder will allow you to easily jump to `~/macOS-installer`
|
||||
| Downloading | Listed Installers |
|
||||
| :--- | :--- |
|
||||
|  |  |
|
||||
|
||||

|
||||
Since the patcher officially supports Big Sur and newer for patching, only those entires will be showen. For ourselves, we'll select 12.1 as that's the latest public release at the time of writing. This will download and install the macOS installer to your applications folder.
|
||||
|
||||

|
||||
| Downloading the Installer | Requesting to install | Finished Installing |
|
||||
| :--- | :--- | :--- |
|
||||
|  |  |  |
|
||||
|
||||
## Building
|
||||
Once finished, you can proceed to write the installer onto a USB drive.
|
||||
|
||||
Now we'll be formatting the USB to prep for both the macOS installer and OpenCore. We'll want to use macOS Extended (HFS+) with a GUID partition map(Using GUID is important for the patcher). This will create two partitions: the main `MyVolume` and a second called `EFI` which is used as a boot partition where your Mac's firmware will check for boot files. `EFI` partitions will be hidden by default, so don't worry if you don't immediately see them.
|
||||
* Note: The entire USB drive will be formatted
|
||||
|
||||
* Note: By default, Disk Utility only shows partitions – press Cmd/Win+2 to show all devices (alternatively you can press the View button)
|
||||
| Select Downloaded Installer | Select disk to format |
|
||||
| :--- | :--- |
|
||||
|  |  |
|
||||
|
||||

|
||||
|
||||
Next run the `createinstallmedia` command provided by [Apple](https://support.apple.com/en-us/HT201372). Note that the command is made for USB's formatted with the name `MyVolume`:
|
||||
|
||||
```sh
|
||||
sudo /Applications/Install\ macOS\ Big\ Sur.app/Contents/Resources/createinstallmedia --volume /Volumes/MyVolume
|
||||
```
|
||||
|
||||
* Note: You can also replace the `createinstallmedia` path with that of where your installer's located (same idea with the drive name).
|
||||
|
||||

|
||||
Now the patcher will start the installer flashing!
|
||||
|
||||
| Flashing | Success Prompt | Finished Flashing |
|
||||
| :--- | :--- |
|
||||
|  |  |  |
|
||||
# Once finished, head to [Building and installing OpenCore](./BUILD.md)
|
||||
|
||||
@@ -20,4 +20,4 @@ This patcher is made of multiple external applications from different people and
|
||||
* [VMM Patch Set](https://github.com/dortania/OpenCore-Legacy-Patcher/blob/4a8f61a01da72b38a4b2250386cc4b497a31a839/payloads/Config/config.plist#L1222-L1281) - parrotgeek1
|
||||
* Apple Binaries - Apple Inc.
|
||||
|
||||
Remaining files within OpenCore Legacy Patcher are copyrighted 2020-2021 Mykola Grymalyuk & Dhinak G. For integration into other projects, please request written permission.
|
||||
Remaining files within OpenCore Legacy Patcher are copyrighted 2020-2022 Mykola Grymalyuk & Dhinak G. For integration into other projects, please request written permission.
|
||||
|
||||
@@ -15,10 +15,19 @@ With Monterey, Apple continues their their somewhat ruthless march of dropping I
|
||||
* MacBookPro11,2
|
||||
* MacBookPro11,3
|
||||
|
||||
All of these models now have support in OpenCore Legacy Patcher. Note iMac15,1 does have [an unfortunate firmware bug preventing resolutions above 4k](https://github.com/dortania/OpenCore-Legacy-Patcher/issues/359) with OpenCore Legacy Patcher
|
||||
All of these models now have support in OpenCore Legacy Patcher.
|
||||
|
||||
## Previously Broken Hardware
|
||||
|
||||
::: details iMac15,1 5K Display Output Issue (Resolved in 0.3.2 and newer)
|
||||
|
||||
* Documentation:
|
||||
* [5K iMac and UEFI: Fixing the dreaded output limitation](https://khronokernel.github.io/macos/2021/12/08/5K-UEFI.html)
|
||||
* Associated Github Issue:
|
||||
* [5k Output issues on iMac15,1 (27" 5k iMac - 2014) #359](https://github.com/dortania/OpenCore-Legacy-Patcher/issues/359)
|
||||
|
||||
:::
|
||||
|
||||
::: details macOS 12.0 Beta 4 issue on 2012 to early 2013 machines (Resolved in 0.2.5 and newer)
|
||||
|
||||
Currently in macOS 12.0 Beta 4, many Ivy Bridge Macs have experienced Bluetooth issues relating to their BCM20702 chipset. Currently the exact issue is unknown however is assumed to be a bug on Apple's end. Recommend downgrading to macOS 12.0 Beta 3 till resolved:
|
||||
|
||||
@@ -16,5 +16,5 @@ features:
|
||||
details: Install updates the moment they come out just like on a supported Mac, and no more 12GB+ updates.
|
||||
- title: Zero firmware patching
|
||||
details: No need to patch APFS ROM support, all protocol upgrades are done in memory and never permanent.
|
||||
footer: Copyright © Dortania 2020-2021
|
||||
footer: Copyright © Dortania 2020-2022
|
||||
---
|
||||
@@ -12,6 +12,7 @@ Here are some common errors users may experience while using this patcher:
|
||||
* [No Brightness Control](#no-brightness-control)
|
||||
* [Cannot connect Wi-Fi on Monterey with legacy cards](#cannot-connect-Wi-Fi-on-Monterey-with-legacy-cards)
|
||||
* [No Graphics Acceleration on Intel Ivy Bridge and Nvidia Kepler GPUs](#no-graphics-acceleration-on-intel-ivy-bridge-and-nvidia-kepler-gpus)
|
||||
* [Black Screen on MacBookPro11,3 in macOS Monterey](#black-screen-on-macbookpro113-in-macos-monterey)
|
||||
|
||||
## Stuck on `This version of Mac OS X is not supported on this platform`
|
||||
|
||||
@@ -81,4 +82,10 @@ To work-around, we recommend users to manually connect using the "other" option
|
||||
|
||||
With macOS Monterey, Apple removed Graphics Drivers for both Intel Ivy Bride and Nvidia Kepler. To re-enable acceleration, simply run the Post Install Root Volume patches.
|
||||
|
||||
Once rebooted, acceleration will be re-enabled as well as brightness control for laptops.
|
||||
Once rebooted, acceleration will be re-enabled as well as brightness control for laptops.
|
||||
|
||||
## Black Screen on MacBookPro11,3 in macOS Monterey
|
||||
|
||||
Due to Apple dropping Nvidia Kepler support in macOS Monterey, [MacBookPro11,3's GMUX has difficulties switching back to the iGPU to display macOS correctly.](https://github.com/dortania/OpenCore-Legacy-Patcher/issues/522) To work-around this issue, boot the MacBookPro11,3 in Safe Mode and once macOS is installed, run OCLP's Post Install Root Patches to enable GPU Acceleration for the Nvidia dGPU.
|
||||
|
||||
* Safe Mode can be started by holding Shift+Enter when selecting macOS Monterey in OCLP's Boot Menu.
|
||||
@@ -6,15 +6,19 @@ To install UEFI is actually super simple! All it requires is to boot Windows' In
|
||||
|
||||
* Note: UEFI Windows is generally quite usable for Arrendale and newer models, however machines with Penryn CPUs may experience issues
|
||||
* Recommended Models:
|
||||
* MacBookAir4,x and newer
|
||||
* MacBookPro8,x and newer
|
||||
* Macmini5,x and newer
|
||||
* iMac11,x and newer
|
||||
* MacPro4,1 and newer
|
||||
* Xserve3,1 and newer
|
||||
* MacBookAir4,x - 5,x
|
||||
* MacBookPro8,x - 10,x
|
||||
* Macmini5,x - 6,x
|
||||
* iMac11,x - 13,x
|
||||
|
||||
Once you know your model is supported, you're good to go with the rest of this guide
|
||||
|
||||
* Newer models than listed here will already natively support UEFI Windows through Boot Camp
|
||||
|
||||
For MacPro4,1/5,1 and Xserve3,1 users, please be aware that Windows has troubles with automatic installation, so please refer to cdf's guide on manual installation:
|
||||
|
||||
* [cdf's Mac Pro Thread](https://forums.macrumors.com/threads/opencore-on-the-mac-pro.2207814/)
|
||||
|
||||
## Disk Formatting
|
||||
|
||||
To start off, we'll need the following:
|
||||
|
||||
2498
gui/gui_main.py
Normal file
43
gui/menu_redirect.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import wx
|
||||
import time
|
||||
|
||||
class RedirectText(object):
|
||||
def __init__(self,aWxTextCtrl, sleep):
|
||||
self.out=aWxTextCtrl
|
||||
self.sleep = sleep
|
||||
|
||||
def write(self,string):
|
||||
self.out.WriteText(string)
|
||||
wx.GetApp().Yield()
|
||||
if self.sleep:
|
||||
time.sleep(0.01)
|
||||
|
||||
def fileno(self):
|
||||
return 1
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
class RedirectLabel(object):
|
||||
def __init__(self,aWxTextCtrl):
|
||||
self.out=aWxTextCtrl
|
||||
|
||||
def write(self,string):
|
||||
if string.endswith("MB/s"):
|
||||
self.out.SetLabel(string)
|
||||
self.out.Centre(wx.HORIZONTAL)
|
||||
wx.GetApp().Yield()
|
||||
time.sleep(0.01)
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
class RedirectLabelAll(object):
|
||||
def __init__(self,aWxTextCtrl):
|
||||
self.out=aWxTextCtrl
|
||||
|
||||
def write(self,string):
|
||||
self.out.SetLabel(string)
|
||||
self.out.Centre(wx.HORIZONTAL)
|
||||
wx.GetApp().Yield()
|
||||
time.sleep(0.01)
|
||||
BIN
images/OCLP-GUI-Build-Finished.png
Normal file
|
After Width: | Height: | Size: 427 KiB |
BIN
images/OCLP-GUI-Build-Start.png
Normal file
|
After Width: | Height: | Size: 307 KiB |
BIN
images/OCLP-GUI-Create-Installer-Menu.png
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
images/OCLP-GUI-EFI-Finished-Install.png
Normal file
|
After Width: | Height: | Size: 206 KiB |
BIN
images/OCLP-GUI-EFI-Needs-Permission.png
Normal file
|
After Width: | Height: | Size: 246 KiB |
BIN
images/OCLP-GUI-EFI-Select-Disk.png
Normal file
|
After Width: | Height: | Size: 240 KiB |
BIN
images/OCLP-GUI-EFI-Select-Partition.png
Normal file
|
After Width: | Height: | Size: 153 KiB |
BIN
images/OCLP-GUI-Installer-Download-Catalog.png
Normal file
|
After Width: | Height: | Size: 150 KiB |
BIN
images/OCLP-GUI-Installer-Download-Finished.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
images/OCLP-GUI-Installer-Download-Listed-Products.png
Normal file
|
After Width: | Height: | Size: 265 KiB |
BIN
images/OCLP-GUI-Installer-Download-Progress.png
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
images/OCLP-GUI-Installer-Finished-Script.png
Normal file
|
After Width: | Height: | Size: 213 KiB |
BIN
images/OCLP-GUI-Installer-Flashing-Process.png
Normal file
|
After Width: | Height: | Size: 212 KiB |
BIN
images/OCLP-GUI-Installer-Format-USB.png
Normal file
|
After Width: | Height: | Size: 196 KiB |
BIN
images/OCLP-GUI-Installer-Needs-Installing.png
Normal file
|
After Width: | Height: | Size: 247 KiB |
BIN
images/OCLP-GUI-Installer-Select-Local-Installer.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
images/OCLP-GUI-Installer-Sucess-Prompt.png
Normal file
|
After Width: | Height: | Size: 194 KiB |
BIN
images/OCLP-GUI-Main-Menu.png
Normal file
|
After Width: | Height: | Size: 213 KiB |
10
merge_gui.py
@@ -1,10 +0,0 @@
|
||||
# Updates build version in OCLP-GUI during CI builds
|
||||
# Copyright (C) 2021 Mykola Grymalyuk
|
||||
import plistlib
|
||||
from pathlib import Path
|
||||
from resources import constants
|
||||
|
||||
app_path = Path.cwd() / Path ("OpenCore Patcher.app/Contents/Info.plist")
|
||||
info = plistlib.load(Path(app_path).open("rb"))
|
||||
info["CFBundleShortVersionString"] = constants.Constants().patcher_version
|
||||
plistlib.dump(info, Path(app_path).open("wb"), sort_keys=True)
|
||||
@@ -433,7 +433,7 @@
|
||||
<key>Arch</key>
|
||||
<string>x86_64</string>
|
||||
<key>Comment</key>
|
||||
<string>4331 Wifi Patch</string>
|
||||
<string>Broadcom Wifi Patch</string>
|
||||
<key>Enabled</key>
|
||||
<false/>
|
||||
<key>MaxKernel</key>
|
||||
@@ -921,7 +921,7 @@
|
||||
<key>BundlePath</key>
|
||||
<string>IOFireWireFamily.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<string>Enable FireWire Rooting #1</string>
|
||||
<key>Enabled</key>
|
||||
<false/>
|
||||
<key>ExecutablePath</key>
|
||||
@@ -939,7 +939,7 @@
|
||||
<key>BundlePath</key>
|
||||
<string>IOFireWireFamily.kext/Contents/PlugIns/AppleFWOHCI.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<string>Enable FireWire Rooting #2</string>
|
||||
<key>Enabled</key>
|
||||
<false/>
|
||||
<key>ExecutablePath</key>
|
||||
@@ -957,7 +957,7 @@
|
||||
<key>BundlePath</key>
|
||||
<string>IOFireWireSBP2.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<string>Enable FireWire Rooting #3</string>
|
||||
<key>Enabled</key>
|
||||
<false/>
|
||||
<key>ExecutablePath</key>
|
||||
@@ -975,7 +975,7 @@
|
||||
<key>BundlePath</key>
|
||||
<string>IOFireWireSerialBusProtocolTransport.kext</string>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<string>Enable FireWire Rooting #4</string>
|
||||
<key>Enabled</key>
|
||||
<false/>
|
||||
<key>ExecutablePath</key>
|
||||
@@ -1854,6 +1854,12 @@
|
||||
<integer>0</integer>
|
||||
<key>KeySubsequentDelay</key>
|
||||
<integer>5</integer>
|
||||
<key>PointerPollMask</key>
|
||||
<integer>-1</integer>
|
||||
<key>PointerPollMax</key>
|
||||
<integer>2</integer>
|
||||
<key>PointerPollMin</key>
|
||||
<integer>2</integer>
|
||||
<key>GraphicsInputMirroring</key>
|
||||
<false/>
|
||||
<key>PointerSpeedDiv</key>
|
||||
@@ -1867,20 +1873,24 @@
|
||||
<integer>0</integer>
|
||||
<key>AudioDevice</key>
|
||||
<string></string>
|
||||
<key>AudioOut</key>
|
||||
<integer>0</integer>
|
||||
<key>AudioOutMask</key>
|
||||
<integer>1</integer>
|
||||
<key>AudioSupport</key>
|
||||
<false/>
|
||||
<key>MinimumVolume</key>
|
||||
<integer>20</integer>
|
||||
<key>DisconnectHda</key>
|
||||
<false/>
|
||||
<key>MaximumGain</key>
|
||||
<integer>-15</integer>
|
||||
<key>MinimumAssistGain</key>
|
||||
<integer>-30</integer>
|
||||
<key>MinimumAudibleGain</key>
|
||||
<integer>-55</integer>
|
||||
<key>PlayChime</key>
|
||||
<string>Disabled</string>
|
||||
<key>ResetTrafficClass</key>
|
||||
<false/>
|
||||
<key>SetupDelay</key>
|
||||
<integer>0</integer>
|
||||
<key>VolumeAmplifier</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>ConnectDrivers</key>
|
||||
<true/>
|
||||
@@ -1936,6 +1946,16 @@
|
||||
<key>Arguments</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
<key>Path</key>
|
||||
<string>UsbBusDxe.efi</string>
|
||||
<key>Enabled</key>
|
||||
<false/>
|
||||
<key>Arguments</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Comment</key>
|
||||
<string></string>
|
||||
|
||||
BIN
payloads/Drivers/UsbBusDxe.efi
Normal file
BIN
payloads/Kexts/Acidanthera/FeatureUnlock-v1.0.6-DEBUG.zip
Normal file
BIN
payloads/Kexts/Acidanthera/FeatureUnlock-v1.0.6-RELEASE.zip
Normal file
BIN
payloads/Kexts/Acidanthera/Lilu-v1.5.9-DEBUG.zip
Normal file
BIN
payloads/Kexts/Acidanthera/Lilu-v1.5.9-RELEASE.zip
Normal file
BIN
payloads/Kexts/Acidanthera/RestrictEvents-MBP91-v1.0.6-DEBUG.zip
Normal file
BIN
payloads/Kexts/Acidanthera/RestrictEvents-v1.0.6-DEBUG.zip
Normal file
BIN
payloads/Kexts/Acidanthera/RestrictEvents-v1.0.6-RELEASE.zip
Normal file
BIN
payloads/Kexts/Acidanthera/WhateverGreen-v1.5.6-DEBUG.zip
Normal file
BIN
payloads/Kexts/Acidanthera/WhateverGreen-v1.5.6-RELEASE.zip
Normal file
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>AppleGraphicsDevicePolicy</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>6.2.9, Copyright 2008-2021 Apple Inc. All rights reserved.</string>
|
||||
<string>6.2.9, Copyright 2008-2022 Apple Inc. All rights reserved.</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.apple.driver.AppleGraphicsDevicePolicy</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
@@ -190,7 +190,7 @@
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>11.3</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>6.2.9, Copyright © 2008-2021 Apple Inc. All rights reserved.</string>
|
||||
<string>6.2.9, Copyright © 2008-2022 Apple Inc. All rights reserved.</string>
|
||||
<key>OSBundleLibraries</key>
|
||||
<dict>
|
||||
<key>com.apple.AppleGraphicsDeviceControl</key>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>AppleMuxControl</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>6.2.9, Copyright 2008-2021 Apple Inc. All rights reserved.</string>
|
||||
<string>6.2.9, Copyright 2008-2022 Apple Inc. All rights reserved.</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.apple.driver.AppleMuxControl</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
@@ -390,7 +390,7 @@
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>11.3</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>6.2.9, Copyright © 2008-2021 Apple Inc. All rights reserved.</string>
|
||||
<string>6.2.9, Copyright © 2008-2022 Apple Inc. All rights reserved.</string>
|
||||
<key>OSBundleLibraries</key>
|
||||
<dict>
|
||||
<key>com.apple.AppleGraphicsDeviceControl</key>
|
||||
|
||||
BIN
payloads/Tools/OCLP-Helper
Executable file
BIN
payloads/Tools/ocvalidate-0.7.7
Executable file
54
payloads/binary.py
Normal file
@@ -0,0 +1,54 @@
|
||||
# Handle Misc patching for binaries during commit
|
||||
# This includes Load Command Patching as well as Info.plist patching
|
||||
# Copyright (C) 2022 - Mykola Grymalyuk
|
||||
import sys
|
||||
import plistlib
|
||||
from pathlib import Path
|
||||
|
||||
def main():
|
||||
patch_load_command()
|
||||
patch_info_plist()
|
||||
|
||||
def patch_load_command():
|
||||
# Patches LC_VERSION_MIN_MACOSX in Load Command to report 10.10
|
||||
#
|
||||
# By default Pyinstaller will create binaries supporting 10.13+
|
||||
# However this limitation is entirely arbitrary for our libraries
|
||||
# and instead we're able to support 10.10 without issues.
|
||||
#
|
||||
# To verify set version:
|
||||
# otool -l ./dist/OpenCore-Patcher.app/Contents/MacOS/OpenCore-Patcher
|
||||
#
|
||||
# cmd LC_VERSION_MIN_MACOSX
|
||||
# cmdsize 16
|
||||
# version 10.13
|
||||
# sdk 10.9
|
||||
print("- Patching LC_VERSION_MIN_MACOSX")
|
||||
path = './dist/OpenCore-Patcher.app/Contents/MacOS/OpenCore-Patcher'
|
||||
find = b'\x00\x0D\x0A\x00' # 10.13 (0xA0D)
|
||||
replace = b'\x00\x0A\x0A\x00' # 10.10 (0xA0A)
|
||||
with open(path, 'rb') as f:
|
||||
data = f.read()
|
||||
data = data.replace(find, replace)
|
||||
with open(path, 'wb') as f:
|
||||
f.write(data)
|
||||
|
||||
def patch_info_plist():
|
||||
# Add Commit Data to Info.plist
|
||||
print("- Updating Info.plist")
|
||||
argsv = sys.argv
|
||||
argsv.pop(0)
|
||||
if argsv:
|
||||
plist_path = './dist/OpenCore-Patcher.app/Contents/Info.plist'
|
||||
plist = plistlib.load(Path(plist_path).open("rb"))
|
||||
print("- Adding Github Dictionary")
|
||||
plist["Github"] = {
|
||||
"Branch": argsv[0],
|
||||
"Commit URL": argsv[1],
|
||||
"Commit Date": argsv[2],
|
||||
}
|
||||
print("- Writing Plist")
|
||||
plistlib.dump(plist, Path(plist_path).open("wb"), sort_keys=True)
|
||||
else:
|
||||
print("- No commit data supplied, skipping")
|
||||
main()
|
||||
@@ -1,2 +1,3 @@
|
||||
requests
|
||||
pyobjc
|
||||
pyobjc
|
||||
wxpython
|
||||
@@ -1,5 +1,5 @@
|
||||
# Commands for building the EFI and SMBIOS
|
||||
# Copyright (C) 2020-2021, Dhinak G, Mykola Grymalyuk
|
||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||
from __future__ import print_function
|
||||
|
||||
import binascii
|
||||
@@ -139,18 +139,12 @@ class BuildOpenCore:
|
||||
# IDE patch
|
||||
("AppleIntelPIIXATA.kext", self.constants.piixata_version, self.constants.piixata_path, lambda: "PATA" in smbios_data.smbios_dictionary[self.model]["Stock Storage"]),
|
||||
# Misc
|
||||
(
|
||||
"FeatureUnlock.kext",
|
||||
self.constants.featureunlock_version,
|
||||
self.constants.featureunlock_path,
|
||||
lambda: smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.kaby_lake.value,
|
||||
),
|
||||
("DebugEnhancer.kext", self.constants.debugenhancer_version, self.constants.debugenhancer_path, lambda: self.constants.kext_debug is True),
|
||||
("AppleUSBTrackpad.kext", self.constants.apple_trackpad, self.constants.apple_trackpad_path, lambda: self.model in ["MacBook4,1", "MacBook5,2"]),
|
||||
]:
|
||||
self.enable_kext(name, version, path, check)
|
||||
|
||||
if self.constants.allow_oc_everywhere is False:
|
||||
if self.constants.allow_oc_everywhere is False or self.constants.allow_native_spoofs is True:
|
||||
if self.constants.serial_settings == "None":
|
||||
# Credit to Parrotgeek1 for boot.efi and hv_vmm_present patch sets
|
||||
# print("- Enabling Board ID exemption patch")
|
||||
@@ -175,6 +169,14 @@ class BuildOpenCore:
|
||||
# Required for Lilu in 11.0+
|
||||
self.config["Kernel"]["Quirks"]["DisableLinkeditJettison"] = True
|
||||
|
||||
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.kaby_lake.value:
|
||||
if self.constants.fu_status is True:
|
||||
# Enable FeatureUnlock.kext
|
||||
self.enable_kext("FeatureUnlock.kext", self.constants.featureunlock_version, self.constants.featureunlock_path)
|
||||
if self.constants.fu_arguments is not None:
|
||||
print(f"- Adding additional FeatureUnlock args: {self.constants.fu_arguments}")
|
||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += self.constants.fu_arguments
|
||||
|
||||
if self.model in ["MacBookPro6,1", "MacBookPro6,2", "MacBookPro9,1", "MacBookPro10,1"]:
|
||||
# Modded RestrictEvents with displaypolicyd blocked to fix dGPU switching
|
||||
self.enable_kext("RestrictEvents.kext", self.constants.restrictevents_mbp_version, self.constants.restrictevents_mbp_path)
|
||||
@@ -234,8 +236,14 @@ class BuildOpenCore:
|
||||
print("- Falling back to -nvmefaspm")
|
||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -nvmefaspm"
|
||||
|
||||
if self.get_kext_by_bundle_path("NVMeFix.kext")["Enabled"] is False:
|
||||
self.enable_kext("NVMeFix.kext", self.constants.nvmefix_version, self.constants.nvmefix_path)
|
||||
if (controller.vendor_id != 0x144D and controller.device_id != 0xA804 and self.model not in ["MacBookPro13,3", "MacBookPro14,3"]):
|
||||
# Avoid injecting NVMeFix when a native Apple NVMe drive is present
|
||||
# Note on 2016-2017 MacBook Pros, 15" devices used a stock Samsung SSD with IONVMeController
|
||||
# Technically this should be patched based on NVMeFix.kext logic,
|
||||
# however Apple deemed the SSD unsupported for enhanced performance
|
||||
# https://github.com/acidanthera/NVMeFix/blob/1.0.9/NVMeFix/NVMeFix.cpp#L220-L225
|
||||
if self.get_kext_by_bundle_path("NVMeFix.kext")["Enabled"] is False:
|
||||
self.enable_kext("NVMeFix.kext", self.constants.nvmefix_version, self.constants.nvmefix_path)
|
||||
|
||||
if not nvme_devices:
|
||||
print("- No 3rd Party NVMe drives found")
|
||||
@@ -376,7 +384,7 @@ class BuildOpenCore:
|
||||
usb_map_path = Path(self.constants.plist_folder_path) / Path("AppleUSBMaps/Info.plist")
|
||||
if (
|
||||
usb_map_path.exists()
|
||||
and self.constants.allow_oc_everywhere is False
|
||||
and (self.constants.allow_oc_everywhere is False or self.constants.allow_native_spoofs is True)
|
||||
and self.model not in ["Xserve2,1", "Dortania1,1"]
|
||||
and (self.model in model_array.Missing_USB_Map or self.constants.serial_settings in ["Moderate", "Advanced"])
|
||||
):
|
||||
@@ -387,7 +395,7 @@ class BuildOpenCore:
|
||||
self.get_kext_by_bundle_path("USB-Map.kext")["Enabled"] = True
|
||||
|
||||
if self.constants.allow_oc_everywhere is False:
|
||||
if self.constants.serial_settings != "None":
|
||||
if self.constants.serial_settings != "None":
|
||||
if self.model == "MacBookPro9,1":
|
||||
print("- Adding AppleMuxControl Override")
|
||||
amc_map_path = Path(self.constants.plist_folder_path) / Path("AppleMuxControl/Info.plist")
|
||||
@@ -470,18 +478,8 @@ class BuildOpenCore:
|
||||
# Used to enable Audio support for non-standard dGPUs
|
||||
self.enable_kext("AppleALC.kext", self.constants.applealc_version, self.constants.applealc_path)
|
||||
|
||||
def check_firewire(model):
|
||||
# MacBooks never supported FireWire
|
||||
# Pre-Thunderbolt MacBook Airs as well
|
||||
if model.startswith("MacBook"):
|
||||
return False
|
||||
elif model.startswith("MacBookAir"):
|
||||
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] < cpu_data.cpu_data.sandy_bridge.value:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
if self.constants.firewire_boot is True and check_firewire(self.model) is True:
|
||||
if self.constants.firewire_boot is True and generate_smbios.check_firewire(self.model) is True:
|
||||
# Enable FireWire Boot Support
|
||||
# Applicable for both native FireWire and Thunderbolt to FireWire adapters
|
||||
print("- Enabling FireWire Boot Support")
|
||||
@@ -579,7 +577,7 @@ class BuildOpenCore:
|
||||
"CAIL,CAIL_DisableVCEPowerGating": 1,
|
||||
"agdpmod": "pikera",
|
||||
})
|
||||
elif self.constants.imac_model == "Legacy GCN":
|
||||
if self.constants.imac_model == "Legacy GCN":
|
||||
print("- Adding Legacy GCN Power Gate Patches")
|
||||
self.config["DeviceProperties"]["Add"][backlight_path].update({
|
||||
"rebuild-device-tree": 1,
|
||||
@@ -703,6 +701,9 @@ class BuildOpenCore:
|
||||
if self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirPortBrcm4360:
|
||||
print("- Fixing Legacy Bluetooth for macOS Monterey")
|
||||
self.enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
|
||||
elif self.computer.bluetooth_chipset == "3rd Party Bluetooth 4.0 Hub":
|
||||
print("- Detected 3rd Party Chipset")
|
||||
self.enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
|
||||
elif smbios_data.smbios_dictionary[self.model]["Bluetooth Model"] <= bluetooth_data.bluetooth_data.BRCM20702_v1.value:
|
||||
print("- Fixing Legacy Bluetooth for macOS Monterey")
|
||||
self.enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
|
||||
@@ -760,18 +761,27 @@ class BuildOpenCore:
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if self.constants.xhci_boot is True:
|
||||
print("- Adding USB 3.0 Controller Patch")
|
||||
print("- Adding XhciDxe.efi and UsbBusDxe.efi")
|
||||
shutil.copy(self.constants.xhci_driver_path, self.constants.drivers_path)
|
||||
shutil.copy(self.constants.usb_bus_driver_path, self.constants.drivers_path)
|
||||
self.get_efi_binary_by_path("XhciDxe.efi", "UEFI", "Drivers")["Enabled"] = True
|
||||
self.get_efi_binary_by_path("UsbBusDxe.efi", "UEFI", "Drivers")["Enabled"] = True
|
||||
|
||||
# ThirdPartDrives Check
|
||||
for drive in ["SATA 2.5", "SATA 3.5", "mSATA"]:
|
||||
if drive in smbios_data.smbios_dictionary[self.model]["Stock Storage"]:
|
||||
if not self.constants.custom_model:
|
||||
if self.computer.third_party_sata_ssd is True:
|
||||
if self.constants.allow_3rd_party_drives is True:
|
||||
for drive in ["SATA 2.5", "SATA 3.5", "mSATA"]:
|
||||
if drive in smbios_data.smbios_dictionary[self.model]["Stock Storage"]:
|
||||
if not self.constants.custom_model:
|
||||
if self.computer.third_party_sata_ssd is True:
|
||||
print("- Adding SATA Hibernation Patch")
|
||||
self.config["Kernel"]["Quirks"]["ThirdPartyDrives"] = True
|
||||
break
|
||||
else:
|
||||
print("- Adding SATA Hibernation Patch")
|
||||
self.config["Kernel"]["Quirks"]["ThirdPartyDrives"] = True
|
||||
break
|
||||
else:
|
||||
print("- Adding SATA Hibernation Patch")
|
||||
self.config["Kernel"]["Quirks"]["ThirdPartyDrives"] = True
|
||||
break
|
||||
|
||||
# Apple RAID Card check
|
||||
if not self.constants.custom_model:
|
||||
@@ -792,7 +802,7 @@ class BuildOpenCore:
|
||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -v"
|
||||
if self.constants.kext_debug is True:
|
||||
print("- Enabling DEBUG Kexts")
|
||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -liludbgall"
|
||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -liludbgall liludump=90"
|
||||
# Disabled due to macOS Monterey crashing shortly after kernel init
|
||||
# Use DebugEnhancer.kext instead
|
||||
# self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " msgbuf=1048576"
|
||||
@@ -889,10 +899,15 @@ class BuildOpenCore:
|
||||
if self.constants.disable_connectdrivers is True:
|
||||
print("- Disabling ConnectDrivers")
|
||||
self.config["UEFI"]["ConnectDrivers"] = False
|
||||
# if self.get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (1)")["Enabled"] is True:
|
||||
# # Add Content Caching patch
|
||||
# print("- Fixing Content Caching support")
|
||||
# self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -allow_assetcache"
|
||||
if self.constants.nvram_write is False:
|
||||
print("- Disabling Hardware NVRAM Write")
|
||||
self.config["NVRAM"]["WriteFlash"] = False
|
||||
if self.get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (1)")["Enabled"] is True:
|
||||
# Add Content Caching patch
|
||||
print("- Fixing Content Caching support")
|
||||
if self.get_kext_by_bundle_path("RestrictEvents.kext")["Enabled"] is False:
|
||||
self.enable_kext("RestrictEvents.kext", self.constants.restrictevents_version, self.constants.restrictevents_path)
|
||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -revasset"
|
||||
if self.get_kext_by_bundle_path("RestrictEvents.kext")["Enabled"] is False:
|
||||
# Ensure this is done at the end so all previous RestrictEvents patches are applied
|
||||
# RestrictEvents and EFICheckDisabler will confilict if both are injected
|
||||
@@ -903,7 +918,10 @@ class BuildOpenCore:
|
||||
if self.constants.override_smbios == "Default":
|
||||
if self.constants.serial_settings != "None":
|
||||
print("- Setting macOS Monterey Supported SMBIOS")
|
||||
spoofed_model = generate_smbios.set_smbios_model_spoof(self.model)
|
||||
if self.constants.allow_native_spoofs is True:
|
||||
spoofed_model = self.model
|
||||
else:
|
||||
spoofed_model = generate_smbios.set_smbios_model_spoof(self.model)
|
||||
else:
|
||||
spoofed_model = self.constants.override_smbios
|
||||
print(f"- Using Model ID: {spoofed_model}")
|
||||
@@ -914,7 +932,7 @@ class BuildOpenCore:
|
||||
spoofed_board = ""
|
||||
self.spoofed_model = spoofed_model
|
||||
self.spoofed_board = spoofed_board
|
||||
if self.constants.allow_oc_everywhere is False:
|
||||
if self.constants.allow_oc_everywhere is False or self.constants.allow_native_spoofs is True:
|
||||
self.config["#Revision"]["Spoofed-Model"] = f"{self.spoofed_model} - {self.constants.serial_settings}"
|
||||
|
||||
# Setup menu
|
||||
@@ -953,10 +971,7 @@ class BuildOpenCore:
|
||||
# Update tables
|
||||
self.config["PlatformInfo"]["UpdateNVRAM"] = True
|
||||
self.config["PlatformInfo"]["UpdateSMBIOS"] = True
|
||||
|
||||
# Updating DataHub breaks hibernation, disabling for time being
|
||||
# self.config["PlatformInfo"]["UpdateDataHub"] = True
|
||||
# self.config["UEFI"]["ProtocolOverrides"]["DataHub"] = True
|
||||
self.config["PlatformInfo"]["UpdateDataHub"] = True
|
||||
|
||||
def moderate_serial_patch(self):
|
||||
if self.constants.custom_cpu_model == 0 or self.constants.custom_cpu_model == 1:
|
||||
@@ -997,6 +1012,18 @@ class BuildOpenCore:
|
||||
print("- Using Minimal SMBIOS patching")
|
||||
self.spoofed_model = self.model
|
||||
minimal_serial_patch(self)
|
||||
else:
|
||||
# Update DataHub to resolve Lilu Race Condition
|
||||
# macOS Monterey will somtimes not present the boardIdentifier in the DeviceTree on UEFI 1.2 or older Mac,
|
||||
# Thus resulting in an infitinte loop as Lilu tries to request the Board ID
|
||||
# To resolve this, set PlatformInfo -> DataHub -> BoardProduct and enable UpdateDataHub
|
||||
|
||||
# Note 1: Only apply if system is UEFI 1.2, this is generally Ivy Bridge and older, excluding MacPro6,1
|
||||
# Note 2: Flipping 'UEFI -> ProtocolOverrides -> DataHub' will break hibernation
|
||||
if (smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.ivy_bridge.value and self.model != "MacPro6,1"):
|
||||
print("- Detected UEFI 1.2 or older Mac, updating BoardProduct")
|
||||
self.config["PlatformInfo"]["DataHub"]["BoardProduct"] = self.spoofed_board
|
||||
self.config["PlatformInfo"]["UpdateDataHub"] = True
|
||||
|
||||
# USB Map and CPUFriend Patching
|
||||
if (
|
||||
@@ -1162,7 +1189,7 @@ class BuildOpenCore:
|
||||
|
||||
def build_opencore(self):
|
||||
self.build_efi()
|
||||
if self.constants.allow_oc_everywhere is False:
|
||||
if self.constants.allow_oc_everywhere is False or self.constants.allow_native_spoofs is True:
|
||||
self.set_smbios()
|
||||
self.cleanup()
|
||||
self.sign_files()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Handle misc CLI menu options
|
||||
# Copyright (C) 2020-2021, Dhinak G, Mykola Grymalyuk
|
||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
|
||||
@@ -101,17 +101,16 @@ option is for those patching on a different machine or OCLP cannot detect.
|
||||
utilities.header(["Set SMBIOS Spoof Level"])
|
||||
print(
|
||||
"""This section is for setting how OpenCore generates the SMBIOS
|
||||
Recommended for adanced users who want control how serials are handled
|
||||
Recommended for advanced users who want control how serials are handled
|
||||
|
||||
Valid options:
|
||||
|
||||
0. None:\tOnly update FirmwareFeatures
|
||||
0. None:\tUse stock SMBIOS (VMM Masking)
|
||||
1. Minimal:\tUse original serials and minimally update SMBIOS
|
||||
2. Moderate:\tReplace entire SMBIOS but keep original serials
|
||||
3. Advanced:\tReplace entire SMBIOS and generate new serials
|
||||
Q. Return to previous menu
|
||||
|
||||
Note: For new users we recommend leaving as default(1. Minimal)
|
||||
"""
|
||||
)
|
||||
change_menu = input("Set SMBIOS Spoof Level(ie. 1): ")
|
||||
@@ -467,6 +466,33 @@ OpenCore will enable NVMe support in it's picker
|
||||
print("Returning to previous menu")
|
||||
else:
|
||||
self.allow_nvme()
|
||||
|
||||
def allow_xhci(self):
|
||||
utilities.cls()
|
||||
utilities.header(["Allow NVMe UEFI Support"])
|
||||
print(
|
||||
"""
|
||||
For machines not natively supporting XHCI/USB 3.o,
|
||||
this option allows you to see and boot XHCI
|
||||
drive in OpenCore's picker
|
||||
|
||||
Not required if your machine natively supports USB 3.0
|
||||
|
||||
Note: You must have OpenCore on a bootable volume
|
||||
first, ie. USB 2.0 or SATA drive. Once loaded,
|
||||
OpenCore will enable XHCI support in it's picker
|
||||
"""
|
||||
)
|
||||
|
||||
change_menu = input("Enable XHCI Boot support?(y/n/q): ")
|
||||
if change_menu in {"y", "Y", "yes", "Yes"}:
|
||||
self.constants.xhci_boot = True
|
||||
elif change_menu in {"n", "N", "no", "No"}:
|
||||
self.constants.xhci_boot = False
|
||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||
print("Returning to previous menu")
|
||||
else:
|
||||
self.allow_xhci()
|
||||
|
||||
def allow_wowl(self):
|
||||
utilities.cls()
|
||||
@@ -697,6 +723,29 @@ for Windows may prefer to only work with the dGPU and eGPU active.
|
||||
else:
|
||||
self.dGPU_switch_support()
|
||||
|
||||
def set_3rd_party_drices(self):
|
||||
utilities.cls()
|
||||
utilities.header(["Set enhanced 3rd Party SSD Support"])
|
||||
print(
|
||||
"""
|
||||
On SATA-based Macs, Apple restricts enhanced OS support to native
|
||||
drives. Namely hibernation and TRIM.
|
||||
|
||||
This option allows you to disable enhanced support in situations where
|
||||
TRIM is not ideal.
|
||||
"""
|
||||
)
|
||||
|
||||
change_menu = input("Set enhanced 3rd Party SSD Support?(y/n/q): ")
|
||||
if change_menu in {"y", "Y", "yes", "Yes"}:
|
||||
self.constants.allow_3rd_party_drives = True
|
||||
elif change_menu in {"n", "N", "no", "No"}:
|
||||
self.constants.allow_3rd_party_drives = False
|
||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||
print("Returning to previous menu")
|
||||
else:
|
||||
self.set_3rd_party_drices()
|
||||
|
||||
def set_software_demux(self):
|
||||
utilities.cls()
|
||||
utilities.header(["Set Software Demux"])
|
||||
@@ -832,7 +881,90 @@ To disable SIP outright, set it to 0xFEF
|
||||
except ValueError:
|
||||
print("Invalid input, returning to previous menu")
|
||||
self.set_custom_sip_value()
|
||||
|
||||
def set_fu_settings(self):
|
||||
utilities.cls()
|
||||
utilities.header(["Set FeatureUnlock Settings"])
|
||||
print(
|
||||
"""
|
||||
By default OCLP will add a kext called FeatureUnlock to enable
|
||||
features locked out from older models. Including:
|
||||
|
||||
- AirPlay to Mac
|
||||
- SideCar
|
||||
- Night Shift
|
||||
|
||||
However for systems experiencing memory instability, disabling this
|
||||
kext can help.
|
||||
|
||||
Supported Options:
|
||||
|
||||
1. Enable FeatureUnlock and all patches
|
||||
2. Enable FeatureUnlock and disable AirPlay to Mac and SideCar
|
||||
3. Disable FeatureUnlock
|
||||
"""
|
||||
)
|
||||
change_menu = input("Set FeatreUnlock (ie. 1): ")
|
||||
if change_menu == "1":
|
||||
self.constants.fu_status = True
|
||||
self.constants.fu_arguments = None
|
||||
elif change_menu == "2":
|
||||
self.constants.fu_status = True
|
||||
self.constants.fu_arguments = " -disable_sidecar_mac"
|
||||
elif change_menu == "3":
|
||||
self.constants.fu_status = False
|
||||
self.constants.fu_arguments = None
|
||||
else:
|
||||
print("Invalid input, returning to previous menu")
|
||||
self.set_fu_settings()
|
||||
|
||||
def set_allow_native_spoofs(self):
|
||||
utilities.cls()
|
||||
utilities.header(["Allow Native Spoofs"])
|
||||
print(
|
||||
"""
|
||||
By default OCLP will not touch the SMBIOS of native models
|
||||
to ensure a "stock-like" environment. However for systems that
|
||||
cannot update their firmware, this option will allow OCLP to
|
||||
spoof the SMBIOS.
|
||||
|
||||
By default VMM is used to spoof the SMBIOS. Minimal and higher are
|
||||
available however not officially supported.
|
||||
"""
|
||||
)
|
||||
change_menu = input("Allow Native Spoofs?(y/n/q): ")
|
||||
if change_menu in {"y", "Y", "yes", "Yes"}:
|
||||
self.constants.allow_native_spoofs = True
|
||||
elif change_menu in {"n", "N", "no", "No"}:
|
||||
self.constants.allow_native_spoofs = False
|
||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||
print("Returning to previous menu")
|
||||
else:
|
||||
self.set_allow_native_spoofs()
|
||||
|
||||
def set_nvram_write(self):
|
||||
utilities.cls()
|
||||
utilities.header(["Set NVRAM Write"])
|
||||
print(
|
||||
"""
|
||||
By default, OpenCore will write NVRAM variables to flash. This is
|
||||
recommended for majority of systems however for extremely degraded
|
||||
or fragile systems, you may wish to disable this.
|
||||
|
||||
Supported Options:
|
||||
|
||||
1. Enable NVRAM Write
|
||||
2. Disable NVRAM Write
|
||||
"""
|
||||
)
|
||||
change_menu = input("Set NVRAM Write (ie. 1): ")
|
||||
if change_menu == "1":
|
||||
self.constants.nvram_write = True
|
||||
elif change_menu == "2":
|
||||
self.constants.nvram_write = False
|
||||
else:
|
||||
print("Invalid input, returning to previous menu")
|
||||
self.set_nvram_write()
|
||||
|
||||
def credits(self):
|
||||
utilities.TUIOnlyPrint(
|
||||
@@ -1007,6 +1139,7 @@ system_profiler SPHardwareDataType | grep 'Model Identifier'
|
||||
options = [
|
||||
[f"Set SMBIOS Spoof Level:\tCurrently {self.constants.serial_settings}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).change_serial],
|
||||
[f"Set SMBIOS Spoof Model:\tCurrently {self.constants.override_smbios}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).set_smbios],
|
||||
[f"Allow Native Spoofs:\tCurrently {self.constants.allow_native_spoofs}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).set_allow_native_spoofs],
|
||||
[f"Set Custom name {self.constants.custom_cpu_model_value}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).custom_cpu],
|
||||
]
|
||||
|
||||
@@ -1023,6 +1156,7 @@ system_profiler SPHardwareDataType | grep 'Model Identifier'
|
||||
options = [
|
||||
[f"Set FireWire Boot:\tCurrently {self.constants.firewire_boot}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).allow_firewire],
|
||||
[f"Set NVMe Boot:\tCurrently {self.constants.nvme_boot}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).allow_nvme],
|
||||
[f"Set XHCI Boot:\tCurrently {self.constants.xhci_boot}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).allow_xhci],
|
||||
]
|
||||
|
||||
for option in options:
|
||||
@@ -1055,7 +1189,9 @@ system_profiler SPHardwareDataType | grep 'Model Identifier'
|
||||
[f"Set Hibernation Workaround:\tCurrently {self.constants.disable_connectdrivers}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).set_hibernation_workaround],
|
||||
[f"Disable Battery Throttling:\tCurrently {self.constants.disable_msr_power_ctl}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).set_battery_throttle],
|
||||
[f"Set Software Demux:\tCurrently {self.constants.software_demux}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).set_software_demux],
|
||||
|
||||
[f"Set 3rd Party SSD Support:\tCurrently {self.constants.allow_3rd_party_drives}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).set_3rd_party_drices],
|
||||
[f"Set FeatureUnlock: \tCurrently {self.constants.fu_status}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).set_fu_settings],
|
||||
[f"Set NVRAM Write:\t\tCurrently {self.constants.nvram_write}", MenuOptions(self.constants.custom_model or self.constants.computer.real_model, self.constants).set_nvram_write],
|
||||
]
|
||||
|
||||
for option in options:
|
||||
@@ -1107,9 +1243,14 @@ B. Exit
|
||||
self.download_macOS()
|
||||
|
||||
def download_install_assistant(self, link):
|
||||
installer.download_install_assistant(self.constants.payload_path, link)
|
||||
# To avoid selecting the wrong installer by mistake, let user select the correct one
|
||||
self.find_local_installer()
|
||||
if installer.download_install_assistant(self.constants.payload_path, link):
|
||||
installer.install_macOS_installer(self.constants.payload_path)
|
||||
input("Press any key to continue...")
|
||||
# To avoid selecting the wrong installer by mistake, let user select the correct one
|
||||
self.find_local_installer()
|
||||
else:
|
||||
print("Failed to start download")
|
||||
input("Press any key to continue...")
|
||||
|
||||
|
||||
def download_macOS_installer(self):
|
||||
@@ -1137,7 +1278,7 @@ B. Exit
|
||||
avalible_installers = installer.list_local_macOS_installers()
|
||||
if avalible_installers:
|
||||
for app in avalible_installers:
|
||||
options.append([f"{avalible_installers[app]['Short Name']}: {avalible_installers[app]['Version']} ({avalible_installers[app]['Build']})", lambda: self.list_disks(avalible_installers[app]['Path'])])
|
||||
options.append([f"{avalible_installers[app]['Short Name']}: {avalible_installers[app]['Version']} ({avalible_installers[app]['Build']})", lambda x=app: self.list_disks(avalible_installers[x]['Path'])])
|
||||
for option in options:
|
||||
menu.add_menu_option(option[0], function=option[1])
|
||||
response = menu.start()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# pylint: disable=multiple-statements
|
||||
# Define Files
|
||||
# Copyright (C) 2020-2021, Dhinak G, Mykola Grymalyuk
|
||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
@@ -14,27 +14,31 @@ from data import os_data
|
||||
class Constants:
|
||||
def __init__(self):
|
||||
# Patcher Versioning
|
||||
self.patcher_version = "0.3.3" # OpenCore-Legacy-Patcher
|
||||
self.patcher_support_pkg_version = "0.2.8" # PatcherSupportPkg
|
||||
self.patcher_version = "0.4.1" # OpenCore-Legacy-Patcher
|
||||
self.patcher_support_pkg_version = "0.2.9" # PatcherSupportPkg
|
||||
self.url_patcher_support_pkg = "https://github.com/dortania/PatcherSupportPkg/releases/download/"
|
||||
self.nightly_url_patcher_support_pkg = "https://nightly.link/dortania/PatcherSupportPkg/workflows/build/master/"
|
||||
self.discord_link = "https://discord.gg/rqdPgH8xSN"
|
||||
self.guide_link = "https://dortania.github.io/OpenCore-Legacy-Patcher/"
|
||||
self.repo_link = "https://github.com/dortania/OpenCore-Legacy-Patcher"
|
||||
self.repo_link_latest = f"{self.repo_link}/releases/tag/{self.patcher_version}"
|
||||
|
||||
# OpenCore Versioning
|
||||
# https://github.com/acidanthera/OpenCorePkg
|
||||
self.opencore_commit = "7266ec9 - 12-06-2021"
|
||||
self.opencore_version = "0.7.6"
|
||||
self.opencore_commit = "b530a29 - 01-11-2022"
|
||||
self.opencore_version = "0.7.7"
|
||||
|
||||
# Kext Versioning
|
||||
## Acidanthera
|
||||
## https://github.com/acidanthera
|
||||
self.lilu_version = "1.5.8" # Lilu
|
||||
self.whatevergreen_version = "1.5.5" # WhateverGreen
|
||||
self.lilu_version = "1.5.9" # Lilu
|
||||
self.whatevergreen_version = "1.5.6" # WhateverGreen
|
||||
self.airportbcrmfixup_version = "2.1.3" # AirPortBrcmFixup
|
||||
self.nvmefix_version = "1.0.9" # NVMeFix
|
||||
self.applealc_version = "1.6.3" # AppleALC
|
||||
self.restrictevents_version = "1.0.5" # RestrictEvents
|
||||
self.restrictevents_mbp_version = "1.0.5" # RestrictEvents blocking displaypolicyd (see RestrictEvents-MBP91.patch)
|
||||
self.featureunlock_version = "1.0.5" # FeatureUnlock
|
||||
self.restrictevents_version = "1.0.6" # RestrictEvents
|
||||
self.restrictevents_mbp_version = "1.0.6" # RestrictEvents blocking displaypolicyd (see RestrictEvents-MBP91.patch)
|
||||
self.featureunlock_version = "1.0.6" # FeatureUnlock
|
||||
self.debugenhancer_version = "1.0.4" # DebugEnhancer
|
||||
self.cpufriend_version = "1.2.4" # CPUFriend
|
||||
self.bluetool_version = "2.6.1" # BlueToolFixup (BrcmPatchRAM)
|
||||
@@ -94,6 +98,9 @@ class Constants:
|
||||
self.patch_disk = "" # Set Root Volume to patch
|
||||
self.validate = False # Enable validation testing for CI
|
||||
self.recovery_status = False # Detect if booted into RecoveryOS
|
||||
self.launcher_binary = None # Determine launch binary (ie. Python vs PyInstaller)
|
||||
self.launcher_script = None # Determine launch file (if run via Python)
|
||||
self.ignore_updates = False # Ignore OCLP updates
|
||||
|
||||
## Hardware
|
||||
self.computer: device_probe.Computer = None # type: ignore
|
||||
@@ -102,8 +109,9 @@ class Constants:
|
||||
## OpenCore Settings
|
||||
self.opencore_debug = False
|
||||
self.opencore_build = "RELEASE"
|
||||
self.showpicker = True # Show or Hide OpenCore's Boot Picker
|
||||
self.boot_efi = False # Use EFI/BOOT/BOOTx64.efi bootstrap
|
||||
self.showpicker = True # Show or Hide OpenCore's Boot Picker
|
||||
self.boot_efi = False # Use EFI/BOOT/BOOTx64.efi bootstrap
|
||||
self.nvram_write = True # Write to hardware NVRAM
|
||||
|
||||
## Kext Settings
|
||||
self.kext_debug = False # Enables Lilu debug and DebugEnhancer
|
||||
@@ -117,6 +125,11 @@ class Constants:
|
||||
self.custom_cpu_model_value = "" # New CPU name within About This Mac
|
||||
self.serial_settings = "None" # Set SMBIOS level used
|
||||
self.override_smbios = "Default" # Set SMBIOS model used
|
||||
self.allow_native_spoofs = False # Allow native models to recieve spoofs
|
||||
|
||||
## FeatureUnlock Settings
|
||||
self.fu_status = True # Enable FeatureUnlock
|
||||
self.fu_arguments = None # Set FeatureUnlock arguments
|
||||
|
||||
## Latebloom Settings
|
||||
self.latebloom_status = False # Latebloom Enabled
|
||||
@@ -142,6 +155,7 @@ class Constants:
|
||||
## Boot Volume Settings
|
||||
self.firewire_boot = False # Allow macOS FireWire Boot
|
||||
self.nvme_boot = False # Allow UEFI NVMe Boot
|
||||
self.xhci_boot = False
|
||||
|
||||
## Graphics Settings
|
||||
self.metal_build = False # Set MXM Build support
|
||||
@@ -157,7 +171,7 @@ class Constants:
|
||||
self.enable_wake_on_wlan = False # Allow Wake on WLAN for modern Broadcom
|
||||
self.disable_tb = False # Disable Thunderbolt Controller
|
||||
self.set_alc_usage = True # Set AppleALC usage
|
||||
self.dGPU_switch = True # Set Display GPU Switching for Windows
|
||||
self.dGPU_switch = False # Set Display GPU Switching for Windows
|
||||
self.force_surplus = False # Force SurPlus patch in newer OSes
|
||||
self.force_latest_psp = False # Force latest PatcherSupportPkg
|
||||
self.disable_msr_power_ctl = False # Disable MSR Power Control (missing battery throttling)
|
||||
@@ -166,6 +180,7 @@ class Constants:
|
||||
self.custom_sip_value = None # Set custom SIP value
|
||||
self.walkthrough = False # Enable Walkthrough
|
||||
self.disable_connectdrivers = False # Disable ConnectDrivers (hibernation)
|
||||
self.allow_3rd_party_drives = True # Allow ThridPartyDrives quirk
|
||||
|
||||
self.legacy_accel_support = [
|
||||
os_data.os_data.mojave,
|
||||
@@ -214,6 +229,10 @@ class Constants:
|
||||
@property
|
||||
def xhci_driver_path(self):
|
||||
return self.payload_path / Path("Drivers/XhciDxe.efi")
|
||||
|
||||
@property
|
||||
def usb_bus_driver_path(self):
|
||||
return self.payload_path / Path("Drivers/UsbBusDxe.efi")
|
||||
|
||||
@property
|
||||
def diags_launcher_path(self):
|
||||
@@ -222,6 +241,10 @@ class Constants:
|
||||
@property
|
||||
def list_txt_path(self):
|
||||
return self.payload_path / Path("List.txt")
|
||||
|
||||
@property
|
||||
def installer_sh_path(self):
|
||||
return self.payload_path / Path("Installer.sh")
|
||||
|
||||
# Kexts
|
||||
@property
|
||||
@@ -477,6 +500,10 @@ class Constants:
|
||||
@property
|
||||
def ocvalidate_path(self):
|
||||
return self.payload_path / Path(f"Tools/ocvalidate-{self.opencore_version}")
|
||||
|
||||
@property
|
||||
def oclp_helper_path(self):
|
||||
return self.payload_path / Path("Tools/OCLP-Helper")
|
||||
|
||||
# Icons
|
||||
@property
|
||||
@@ -529,6 +556,10 @@ class Constants:
|
||||
def payload_apple_libexec_path(self):
|
||||
return self.payload_apple_usr_path / Path("libexec")
|
||||
|
||||
@property
|
||||
def payload_apple_application_support(self):
|
||||
return self.payload_apple_root_path / Path("Application Support")
|
||||
|
||||
@property
|
||||
def payload_apple_private_path(self):
|
||||
return self.payload_apple_root_path / Path("private")
|
||||
@@ -651,12 +682,16 @@ class Constants:
|
||||
return self.payload_apple_libexec_path / Path("Legacy-Wifi")
|
||||
|
||||
@property
|
||||
def legacy_wifi_etc(self):
|
||||
return self.payload_apple_etc_path / Path("Legacy-Wifi")
|
||||
def legacy_wifi_support(self):
|
||||
return self.payload_apple_application_support / Path("Legacy-Wifi")
|
||||
|
||||
@property
|
||||
def legacy_keyboard_backlight_etc(self):
|
||||
return self.payload_apple_etc_path / Path("Keyboard-Backlight")
|
||||
def legacy_keyboard_backlight_support(self):
|
||||
return self.payload_apple_application_support / Path("Keyboard-Backlight")
|
||||
|
||||
@property
|
||||
def legacy_dropbox_support(self):
|
||||
return self.payload_apple_application_support / Path("Dropbox")
|
||||
|
||||
sbm_values = [
|
||||
"j137ap", # iMacPro1,1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Generate Default Data
|
||||
from resources import utilities, device_probe, generate_smbios
|
||||
from data import model_array, smbios_data
|
||||
from data import model_array, smbios_data, cpu_data
|
||||
|
||||
|
||||
class generate_defaults:
|
||||
@@ -12,6 +12,12 @@ class generate_defaults:
|
||||
settings.amfi_status = True
|
||||
|
||||
if host_is_target:
|
||||
if settings.computer.usb_controllers and smbios_data.smbios_dictionary[model]["CPU Generation"] < cpu_data.cpu_data.ivy_bridge.value:
|
||||
# Pre-Ivy do not natively support XHCI boot support
|
||||
# If we detect XHCI on older model, enable
|
||||
for controller in settings.computer.usb_controllers:
|
||||
if isinstance(controller, device_probe.XHCIController):
|
||||
settings.xhci_boot = True
|
||||
if utilities.check_metal_support(device_probe, settings.computer) is False:
|
||||
settings.disable_cs_lv = True
|
||||
if settings.computer.gpus:
|
||||
@@ -90,6 +96,13 @@ class generate_defaults:
|
||||
# Users disabling TS2 most likely have a faulty dGPU
|
||||
# users can override this in settings
|
||||
settings.allow_ts2_accel = False
|
||||
|
||||
if smbios_data.smbios_dictionary[model]["CPU Generation"] < cpu_data.cpu_data.ivy_bridge.value and model != "MacPro5,1":
|
||||
# Sidecar and AirPlay to Mac only blacklist Ivy and newer (as well as MacPro5,1)
|
||||
# Avoid extra patching without benefit
|
||||
settings.fu_arguments = " -disable_sidecar_mac"
|
||||
else:
|
||||
settings.fu_arguments = None
|
||||
|
||||
# Check if running in RecoveryOS
|
||||
settings.recovery_status = utilities.check_recovery()
|
||||
@@ -103,12 +116,15 @@ class generate_defaults:
|
||||
# Native Macs (mainly M1s) will error out as they don't know what SMBIOS to spoof to
|
||||
# As we don't spoof on native models, we can safely ignore this
|
||||
spoof_model = model
|
||||
if smbios_data.smbios_dictionary[spoof_model]["SecureBootModel"] is not None:
|
||||
if settings.sip_status is False:
|
||||
# Force VMM as root patching breaks .im4m signature
|
||||
settings.secure_status = False
|
||||
settings.force_vmm = True
|
||||
else:
|
||||
# Allow SecureBootModel
|
||||
settings.secure_status = True
|
||||
settings.force_vmm = False
|
||||
try:
|
||||
if smbios_data.smbios_dictionary[spoof_model]["SecureBootModel"] is not None:
|
||||
if settings.sip_status is False:
|
||||
# Force VMM as root patching breaks .im4m signature
|
||||
settings.secure_status = False
|
||||
settings.force_vmm = True
|
||||
else:
|
||||
# Allow SecureBootModel
|
||||
settings.secure_status = True
|
||||
settings.force_vmm = False
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Hardware probing
|
||||
# Copyright (C) 2020-2021, Dhinak G, Mykola Grymalyuk
|
||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -158,6 +158,17 @@ class SATAController(PCIDevice):
|
||||
class SASController(PCIDevice):
|
||||
CLASS_CODE: ClassVar[int] = 0x010400
|
||||
|
||||
@dataclass
|
||||
class XHCIController(PCIDevice):
|
||||
CLASS_CODE: ClassVar[int] = 0x0c0330
|
||||
|
||||
@dataclass
|
||||
class EHCIController(PCIDevice):
|
||||
CLASS_CODE: ClassVar[int] = 0x0c0320
|
||||
|
||||
@dataclass
|
||||
class OHCIController(PCIDevice):
|
||||
CLASS_CODE: ClassVar[int] = 0x0c0310
|
||||
|
||||
@dataclass
|
||||
class NVIDIA(GPU):
|
||||
@@ -339,6 +350,7 @@ class Computer:
|
||||
igpu: Optional[GPU] = None # Shortcut for IGPU
|
||||
dgpu: Optional[GPU] = None # Shortcut for GFX0
|
||||
storage: list[PCIDevice] = field(default_factory=list)
|
||||
usb_controllers: list[PCIDevice] = field(default_factory=list)
|
||||
wifi: Optional[WirelessCard] = None
|
||||
cpu: Optional[CPU] = None
|
||||
oclp_version: Optional[str] = None
|
||||
@@ -354,6 +366,7 @@ class Computer:
|
||||
computer.igpu_probe()
|
||||
computer.wifi_probe()
|
||||
computer.storage_probe()
|
||||
computer.usb_controller_probe()
|
||||
computer.smbios_probe()
|
||||
computer.cpu_probe()
|
||||
computer.bluetooth_probe()
|
||||
@@ -412,6 +425,39 @@ class Computer:
|
||||
self.wifi = vendor.from_ioregistry(device, anti_spoof=True) # type: ignore
|
||||
break
|
||||
ioreg.IOObjectRelease(device)
|
||||
|
||||
def usb_controller_probe(self):
|
||||
xhci_controllers = ioreg.ioiterator_to_list(
|
||||
ioreg.IOServiceGetMatchingServices(
|
||||
ioreg.kIOMasterPortDefault,
|
||||
{"IOProviderClass": "IOPCIDevice", "IOPropertyMatch": [{"class-code": binascii.a2b_hex(utilities.hexswap(hex(XHCIController.CLASS_CODE)[2:].zfill(8)))}]},
|
||||
None,
|
||||
)[1]
|
||||
)
|
||||
ehci_controllers = ioreg.ioiterator_to_list(
|
||||
ioreg.IOServiceGetMatchingServices(
|
||||
ioreg.kIOMasterPortDefault,
|
||||
{"IOProviderClass": "IOPCIDevice", "IOPropertyMatch": [{"class-code": binascii.a2b_hex(utilities.hexswap(hex(EHCIController.CLASS_CODE)[2:].zfill(8)))}]},
|
||||
None,
|
||||
)[1]
|
||||
)
|
||||
ohci_controllers = ioreg.ioiterator_to_list(
|
||||
ioreg.IOServiceGetMatchingServices(
|
||||
ioreg.kIOMasterPortDefault,
|
||||
{"IOProviderClass": "IOPCIDevice", "IOPropertyMatch": [{"class-code": binascii.a2b_hex(utilities.hexswap(hex(OHCIController.CLASS_CODE)[2:].zfill(8)))}]},
|
||||
None,
|
||||
)[1]
|
||||
)
|
||||
for device in xhci_controllers:
|
||||
self.usb_controllers.append(XHCIController.from_ioregistry(device))
|
||||
ioreg.IOObjectRelease(device)
|
||||
for device in ehci_controllers:
|
||||
self.usb_controllers.append(EHCIController.from_ioregistry(device))
|
||||
ioreg.IOObjectRelease(device)
|
||||
for device in ohci_controllers:
|
||||
self.usb_controllers.append(OHCIController.from_ioregistry(device))
|
||||
ioreg.IOObjectRelease(device)
|
||||
|
||||
|
||||
def storage_probe(self):
|
||||
sata_controllers = ioreg.ioiterator_to_list(
|
||||
@@ -453,19 +499,8 @@ class Computer:
|
||||
controller = NVMeController.from_ioregistry(parent)
|
||||
controller.aspm = aspm
|
||||
|
||||
if (
|
||||
if controller.vendor_id != 0x106B:
|
||||
# Handle Apple Vendor ID
|
||||
controller.vendor_id != 0x106B
|
||||
and (
|
||||
# Handle soldered Samsung SSDs
|
||||
controller.vendor_id != 0x144D and controller.device_id != 0xA804
|
||||
)
|
||||
):
|
||||
# Avoid patching when a native Apple NVMe drive is present
|
||||
# Note on 2016-2017 MacBook Pros, 15" devices used a stock Samsung SSD with IONVMeController
|
||||
# Technically this should be patched based on NVMeFix.kext logic,
|
||||
# however Apple deemed the SSD unsupported for usage with AppleNVMeController class
|
||||
# https://github.com/acidanthera/NVMeFix/blob/1.0.9/NVMeFix/NVMeFix.cpp#L220-L225
|
||||
self.storage.append(controller)
|
||||
|
||||
ioreg.IOObjectRelease(parent)
|
||||
@@ -499,13 +534,15 @@ class Computer:
|
||||
|
||||
def bluetooth_probe(self):
|
||||
usb_data: str = subprocess.run("system_profiler SPUSBDataType".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode()
|
||||
if "BRCM2070 Hub" in usb_data:
|
||||
if "BRCM20702 Hub" in usb_data:
|
||||
self.bluetooth_chipset = "BRCM20702 Hub"
|
||||
elif "BCM20702A0" in usb_data or "BCM2045A0" in usb_data:
|
||||
self.bluetooth_chipset = "3rd Party Bluetooth 4.0 Hub"
|
||||
elif "BRCM2070 Hub" in usb_data:
|
||||
self.bluetooth_chipset = "BRCM2070 Hub"
|
||||
elif "BRCM2046 Hub" in usb_data:
|
||||
self.bluetooth_chipset = "BRCM2046 Hub"
|
||||
elif "BRCM20702 Hub" in usb_data:
|
||||
self.bluetooth_chipset = "BRCM20702 Hub"
|
||||
elif "Bluetooth":
|
||||
elif "Bluetooth" in usb_data:
|
||||
self.bluetooth_chipset = "Generic"
|
||||
|
||||
def sata_disk_probe(self):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from data import smbios_data, os_data
|
||||
from data import smbios_data, os_data, cpu_data
|
||||
from resources import utilities
|
||||
|
||||
|
||||
@@ -71,9 +71,15 @@ def generate_fw_features(model, custom):
|
||||
firmwarefeature = utilities.get_rom("firmware-features")
|
||||
if not firmwarefeature:
|
||||
print("- Failed to find FirmwareFeatures, falling back on defaults")
|
||||
firmwarefeature = int(smbios_data.smbios_dictionary[model]["FirmwareFeatures"], 16)
|
||||
if smbios_data.smbios_dictionary[model]["FirmwareFeatures"] is None:
|
||||
firmwarefeature = 0
|
||||
else:
|
||||
firmwarefeature = int(smbios_data.smbios_dictionary[model]["FirmwareFeatures"], 16)
|
||||
else:
|
||||
firmwarefeature = int(smbios_data.smbios_dictionary[model]["FirmwareFeatures"], 16)
|
||||
if smbios_data.smbios_dictionary[model]["FirmwareFeatures"] is None:
|
||||
firmwarefeature = 0
|
||||
else:
|
||||
firmwarefeature = int(smbios_data.smbios_dictionary[model]["FirmwareFeatures"], 16)
|
||||
firmwarefeature = update_firmware_features(firmwarefeature)
|
||||
return firmwarefeature
|
||||
|
||||
@@ -98,3 +104,16 @@ def find_model_off_board(board):
|
||||
key = "MacPro5,1"
|
||||
return key
|
||||
return None
|
||||
|
||||
def check_firewire(model):
|
||||
# MacBooks never supported FireWire
|
||||
# Pre-Thunderbolt MacBook Airs as well
|
||||
if model.startswith("MacBookPro"):
|
||||
return True
|
||||
elif model.startswith("MacBookAir"):
|
||||
if smbios_data.smbios_dictionary[model]["CPU Generation"] < cpu_data.cpu_data.sandy_bridge.value:
|
||||
return False
|
||||
elif model.startswith("MacBook"):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
@@ -1,6 +1,6 @@
|
||||
# Installation of OpenCore files to ESP
|
||||
# Usage soley for TUI
|
||||
# Copyright (C) 2020-2021, Dhinak G, Mykola Grymalyuk
|
||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||
|
||||
import plistlib
|
||||
import subprocess
|
||||
@@ -14,23 +14,7 @@ class tui_disk_installation:
|
||||
def __init__(self, versions):
|
||||
self.constants: constants.Constants = versions
|
||||
|
||||
def copy_efi(self):
|
||||
utilities.cls()
|
||||
utilities.header(["Installing OpenCore to Drive"])
|
||||
|
||||
if not self.constants.opencore_release_folder.exists():
|
||||
utilities.TUIOnlyPrint(
|
||||
["Installing OpenCore to Drive"],
|
||||
"Press [Enter] to go back.\n",
|
||||
[
|
||||
"""OpenCore folder missing!
|
||||
Please build OpenCore first!"""
|
||||
],
|
||||
).start()
|
||||
return
|
||||
|
||||
print("\nDisk picker is loading...")
|
||||
|
||||
def list_disks(self):
|
||||
all_disks = {}
|
||||
# TODO: AllDisksAndPartitions is not supported in Snow Leopard and older
|
||||
try:
|
||||
@@ -54,7 +38,60 @@ Please build OpenCore first!"""
|
||||
except KeyError:
|
||||
# Avoid crashing with CDs installed
|
||||
continue
|
||||
# TODO: Advanced mode
|
||||
|
||||
supported_disks = {}
|
||||
for disk in all_disks:
|
||||
if not any(all_disks[disk]["partitions"][partition]["fs"] in ("msdos", "EFI") for partition in all_disks[disk]["partitions"]):
|
||||
continue
|
||||
supported_disks.update({
|
||||
disk: {
|
||||
"disk": disk,
|
||||
"name": all_disks[disk]["name"],
|
||||
"size": utilities.human_fmt(all_disks[disk]['size']),
|
||||
"partitions": all_disks[disk]["partitions"]
|
||||
}
|
||||
})
|
||||
return supported_disks
|
||||
|
||||
def list_partitions(self, disk_response, supported_disks):
|
||||
# Takes disk UUID as well as diskutil dataset generated by list_disks
|
||||
# Returns list of FAT32 partitions
|
||||
disk_identifier = disk_response
|
||||
selected_disk = supported_disks[disk_identifier]
|
||||
|
||||
supported_partitions = {}
|
||||
|
||||
for partition in selected_disk["partitions"]:
|
||||
if selected_disk["partitions"][partition]["fs"] not in ("msdos", "EFI"):
|
||||
continue
|
||||
supported_partitions.update({
|
||||
partition: {
|
||||
"partition": partition,
|
||||
"name": selected_disk["partitions"][partition]["name"],
|
||||
"size": utilities.human_fmt(selected_disk["partitions"][partition]["size"])
|
||||
}
|
||||
})
|
||||
return supported_partitions
|
||||
|
||||
|
||||
def copy_efi(self):
|
||||
utilities.cls()
|
||||
utilities.header(["Installing OpenCore to Drive"])
|
||||
|
||||
if not self.constants.opencore_release_folder.exists():
|
||||
utilities.TUIOnlyPrint(
|
||||
["Installing OpenCore to Drive"],
|
||||
"Press [Enter] to go back.\n",
|
||||
[
|
||||
"""OpenCore folder missing!
|
||||
Please build OpenCore first!"""
|
||||
],
|
||||
).start()
|
||||
return
|
||||
|
||||
print("\nDisk picker is loading...")
|
||||
|
||||
all_disks = self.list_disks()
|
||||
menu = utilities.TUIMenu(
|
||||
["Select Disk"],
|
||||
"Please select the disk you would like to install OpenCore to: ",
|
||||
@@ -63,9 +100,7 @@ Please build OpenCore first!"""
|
||||
loop=True,
|
||||
)
|
||||
for disk in all_disks:
|
||||
if not any(all_disks[disk]["partitions"][partition]["fs"] in ("msdos", "EFI") for partition in all_disks[disk]["partitions"]):
|
||||
continue
|
||||
menu.add_menu_option(f"{disk}: {all_disks[disk]['name']} ({utilities.human_fmt(all_disks[disk]['size'])})", key=disk[4:])
|
||||
menu.add_menu_option(f"{disk}: {all_disks[disk]['name']} ({all_disks[disk]['size']})", key=disk[4:])
|
||||
|
||||
response = menu.start()
|
||||
|
||||
@@ -96,9 +131,9 @@ Please build OpenCore first!"""
|
||||
|
||||
if response == -1:
|
||||
return
|
||||
self.install_opencore(disk_identifier, response)
|
||||
self.install_opencore(f"{disk_identifier}s{response}")
|
||||
|
||||
def install_opencore(self, disk_identifier, response):
|
||||
def install_opencore(self, full_disk_identifier):
|
||||
def determine_sd_card(media_name):
|
||||
# Array filled with common SD Card names
|
||||
# Note most USB-based SD Card readers generally report as "Storage Device"
|
||||
@@ -117,7 +152,7 @@ Please build OpenCore first!"""
|
||||
args = [
|
||||
"osascript",
|
||||
"-e",
|
||||
f'''do shell script "diskutil mount {disk_identifier}s{response}"'''
|
||||
f'''do shell script "diskutil mount {full_disk_identifier}"'''
|
||||
' with prompt "OpenCore Legacy Patcher needs administrator privileges to mount your EFI."'
|
||||
" with administrator privileges"
|
||||
" without altering line endings",
|
||||
@@ -126,7 +161,7 @@ Please build OpenCore first!"""
|
||||
if self.constants.detected_os >= os_data.os_data.el_capitan and not self.constants.recovery_status:
|
||||
result = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
else:
|
||||
result = subprocess.run(f"diskutil mount {disk_identifier}s{response}".split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(f"diskutil mount {full_disk_identifier}".split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
if result.returncode != 0:
|
||||
if "execution error" in result.stderr.decode() and result.stderr.decode().strip()[-5:-1] == "-128":
|
||||
@@ -137,8 +172,9 @@ Please build OpenCore first!"""
|
||||
["Copying OpenCore"], "Press [Enter] to go back.\n", ["An error occurred!"] + result.stderr.decode().split("\n") + ["", "Please report this to the devs at GitHub."]
|
||||
).start()
|
||||
return
|
||||
drive_host_info = plistlib.loads(subprocess.run(f"diskutil info -plist {disk_identifier}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||
partition_info = plistlib.loads(subprocess.run(f"diskutil info -plist {disk_identifier}s{response}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||
partition_info = plistlib.loads(subprocess.run(f"diskutil info -plist {full_disk_identifier}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||
parent_disk = partition_info["ParentWholeDisk"]
|
||||
drive_host_info = plistlib.loads(subprocess.run(f"diskutil info -plist {parent_disk}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||
sd_type = drive_host_info["MediaName"]
|
||||
try:
|
||||
ssd_type = drive_host_info["SolidState"]
|
||||
@@ -150,7 +186,7 @@ Please build OpenCore first!"""
|
||||
utilities.header(["Copying OpenCore"])
|
||||
|
||||
if mount_path.exists():
|
||||
if (mount_path / Path("EFI/Microsoft")).exists():
|
||||
if (mount_path / Path("EFI/Microsoft")).exists() and self.constants.gui_mode is False:
|
||||
print("- Found Windows Boot Loader")
|
||||
print("\nWould you like to continue installing OpenCore?")
|
||||
print("Installing OpenCore onto this drive may make Windows unbootable until OpenCore")
|
||||
@@ -202,8 +238,9 @@ Please build OpenCore first!"""
|
||||
print("- Unmounting EFI partition")
|
||||
subprocess.run(["diskutil", "umount", mount_path], stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
||||
print("- OpenCore transfer complete")
|
||||
print("\nPress [Enter] to continue.\n")
|
||||
input()
|
||||
if self.constants.gui_mode is False:
|
||||
print("\nPress [Enter] to continue.\n")
|
||||
input()
|
||||
else:
|
||||
utilities.TUIOnlyPrint(["Copying OpenCore"], "Press [Enter] to go back.\n", ["EFI failed to mount!", "Please report this to the devs at GitHub."]).start()
|
||||
|
||||
|
||||
@@ -53,11 +53,29 @@ def create_installer(installer_path, volume_name):
|
||||
return False
|
||||
|
||||
def download_install_assistant(download_path, ia_link):
|
||||
# Downloads and unpackages InstallAssistant.pkg into /Applications
|
||||
utilities.download_file(ia_link, (Path(download_path) / Path("InstallAssistant.pkg")))
|
||||
print("- Installing InstallAssistant.pkg to /Applications/")
|
||||
utilities.elevated(["installer", "-pkg", (Path(download_path) / Path("InstallAssistant.pkg")), "-target", "/Applications"])
|
||||
input("- Press ENTER to continue: ")
|
||||
# Downloads InstallAssistant.pkg
|
||||
if utilities.download_file(ia_link, (Path(download_path) / Path("InstallAssistant.pkg"))):
|
||||
return True
|
||||
return False
|
||||
|
||||
def install_macOS_installer(download_path):
|
||||
args = [
|
||||
"osascript",
|
||||
"-e",
|
||||
f'''do shell script "installer -pkg {Path(download_path)}/InstallAssistant.pkg -target /"'''
|
||||
' with prompt "OpenCore Legacy Patcher needs administrator privileges to add InstallAssistant."'
|
||||
" with administrator privileges"
|
||||
" without altering line endings",
|
||||
]
|
||||
|
||||
result = subprocess.run(args,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
if result.returncode == 0:
|
||||
print("- InstallAssistant installed")
|
||||
return True
|
||||
else:
|
||||
print("- Failed to install InstallAssistant")
|
||||
print(f" Error Code: {result.returncode}")
|
||||
return False
|
||||
|
||||
def list_downloadable_macOS_installers(download_path, catalog):
|
||||
avalible_apps = {}
|
||||
@@ -69,41 +87,41 @@ def list_downloadable_macOS_installers(download_path, catalog):
|
||||
link = "https://swscan.apple.com/content/catalogs/others/index-12customerseed-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz"
|
||||
|
||||
# Download and unzip the catalog
|
||||
utilities.download_file(link, (Path(download_path) / Path("seed.sucatalog.gz")))
|
||||
subprocess.run(["gunzip", "-d", "-f", Path(download_path) / Path("seed.sucatalog.gz")])
|
||||
catalog_plist = plistlib.load((Path(download_path) / Path("seed.sucatalog")).open("rb"))
|
||||
if utilities.download_file(link, (Path(download_path) / Path("seed.sucatalog.gz"))):
|
||||
subprocess.run(["gunzip", "-d", "-f", Path(download_path) / Path("seed.sucatalog.gz")])
|
||||
catalog_plist = plistlib.load((Path(download_path) / Path("seed.sucatalog")).open("rb"))
|
||||
|
||||
for item in catalog_plist["Products"]:
|
||||
try:
|
||||
# Check if entry has SharedSupport and BuildManifest
|
||||
# Ensures only Big Sur and newer Installers are listed
|
||||
catalog_plist["Products"][item]["ExtendedMetaInfo"]["InstallAssistantPackageIdentifiers"]["SharedSupport"]
|
||||
catalog_plist["Products"][item]["ExtendedMetaInfo"]["InstallAssistantPackageIdentifiers"]["BuildManifest"]
|
||||
for item in catalog_plist["Products"]:
|
||||
try:
|
||||
# Check if entry has SharedSupport and BuildManifest
|
||||
# Ensures only Big Sur and newer Installers are listed
|
||||
catalog_plist["Products"][item]["ExtendedMetaInfo"]["InstallAssistantPackageIdentifiers"]["SharedSupport"]
|
||||
catalog_plist["Products"][item]["ExtendedMetaInfo"]["InstallAssistantPackageIdentifiers"]["BuildManifest"]
|
||||
|
||||
for bm_package in catalog_plist["Products"][item]["Packages"]:
|
||||
if "BuildManifest.plist" in bm_package["URL"]:
|
||||
utilities.download_file(bm_package["URL"], (Path(download_path) / Path("BuildManifest.plist")))
|
||||
build_plist = plistlib.load((Path(download_path) / Path("BuildManifest.plist")).open("rb"))
|
||||
version = build_plist["ProductVersion"]
|
||||
build = build_plist["ProductBuildVersion"]
|
||||
for ia_package in catalog_plist["Products"][item]["Packages"]:
|
||||
if "InstallAssistant.pkg" in ia_package["URL"]:
|
||||
download_link = ia_package["URL"]
|
||||
size = ia_package["Size"]
|
||||
integrity = ia_package["IntegrityDataURL"]
|
||||
for bm_package in catalog_plist["Products"][item]["Packages"]:
|
||||
if "BuildManifest.plist" in bm_package["URL"]:
|
||||
utilities.download_file(bm_package["URL"], (Path(download_path) / Path("BuildManifest.plist")))
|
||||
build_plist = plistlib.load((Path(download_path) / Path("BuildManifest.plist")).open("rb"))
|
||||
version = build_plist["ProductVersion"]
|
||||
build = build_plist["ProductBuildVersion"]
|
||||
for ia_package in catalog_plist["Products"][item]["Packages"]:
|
||||
if "InstallAssistant.pkg" in ia_package["URL"]:
|
||||
download_link = ia_package["URL"]
|
||||
size = ia_package["Size"]
|
||||
integrity = ia_package["IntegrityDataURL"]
|
||||
|
||||
avalible_apps.update({
|
||||
item: {
|
||||
"Version": version,
|
||||
"Build": build,
|
||||
"Link": download_link,
|
||||
"Size": size,
|
||||
"integrity": integrity,
|
||||
"Source": "Apple Inc.",
|
||||
}
|
||||
})
|
||||
except KeyError:
|
||||
pass
|
||||
avalible_apps.update({
|
||||
item: {
|
||||
"Version": version,
|
||||
"Build": build,
|
||||
"Link": download_link,
|
||||
"Size": size,
|
||||
"integrity": integrity,
|
||||
"Source": "Apple Inc.",
|
||||
}
|
||||
})
|
||||
except KeyError:
|
||||
pass
|
||||
return avalible_apps
|
||||
|
||||
def format_drive(disk_id):
|
||||
@@ -172,4 +190,66 @@ def select_disk_to_format():
|
||||
if response == -1:
|
||||
return None
|
||||
|
||||
return response
|
||||
return response
|
||||
|
||||
|
||||
|
||||
def list_disk_to_format():
|
||||
all_disks = {}
|
||||
list_disks = {}
|
||||
# TODO: AllDisksAndPartitions is not supported in Snow Leopard and older
|
||||
try:
|
||||
# High Sierra and newer
|
||||
disks = plistlib.loads(subprocess.run("diskutil list -plist physical".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||
except ValueError:
|
||||
# Sierra and older
|
||||
disks = plistlib.loads(subprocess.run("diskutil list -plist".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||
for disk in disks["AllDisksAndPartitions"]:
|
||||
disk_info = plistlib.loads(subprocess.run(f"diskutil info -plist {disk['DeviceIdentifier']}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||
try:
|
||||
all_disks[disk["DeviceIdentifier"]] = {"identifier": disk_info["DeviceNode"], "name": disk_info["MediaName"], "size": disk_info["TotalSize"], "removable": disk_info["Internal"], "partitions": {}}
|
||||
except KeyError:
|
||||
# Avoid crashing with CDs installed
|
||||
continue
|
||||
for disk in all_disks:
|
||||
# Strip disks that are under 14GB (15,032,385,536 bytes)
|
||||
# createinstallmedia isn't great at detecting if a disk has enough space
|
||||
if not any(all_disks[disk]['size'] > 15032385536 for partition in all_disks[disk]):
|
||||
continue
|
||||
# Strip internal disks as well (avoid user formatting their SSD/HDD)
|
||||
# Ensure user doesn't format their boot drive
|
||||
if not any(all_disks[disk]['removable'] is False for partition in all_disks[disk]):
|
||||
continue
|
||||
print(f"disk {disk}: {all_disks[disk]['name']} ({utilities.human_fmt(all_disks[disk]['size'])})")
|
||||
list_disks.update({
|
||||
disk: {
|
||||
"identifier": all_disks[disk]["identifier"],
|
||||
"name": all_disks[disk]["name"],
|
||||
"size": all_disks[disk]["size"],
|
||||
}
|
||||
})
|
||||
return list_disks
|
||||
|
||||
|
||||
def generate_installer_creation_script(script_location, installer_path, disk):
|
||||
# Creates installer.sh to be piped to OCLP-Helper and run as admin
|
||||
# Goals:
|
||||
# - Format provided disk as HFS+ GPT
|
||||
# - Run createinstallmedia on provided disk
|
||||
# Implemnting this into a single installer.sh script allows us to only call
|
||||
# OCLP-Helper once to avoid nagging the user about permissions
|
||||
|
||||
createinstallmedia_path = str(Path(installer_path) / Path("Contents/Resources/createinstallmedia"))
|
||||
|
||||
if script_location.exists():
|
||||
script_location.unlink()
|
||||
script_location.touch()
|
||||
|
||||
with script_location.open("w") as script:
|
||||
script.write(f'''#!/bin/bash
|
||||
earse_disk='diskutil eraseDisk HFS+ OCLP-Installer {disk}'
|
||||
if $earse_disk; then
|
||||
"{createinstallmedia_path}" --volume /Volumes/OCLP-Installer --nointeraction
|
||||
fi
|
||||
''')
|
||||
return True
|
||||
@@ -1,5 +1,5 @@
|
||||
# Handle misc CLI menu options
|
||||
# Copyright (C) 2020-2021, Dhinak G
|
||||
# Copyright (C) 2020-2022, Dhinak G
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
100
resources/main.py
Normal file
@@ -0,0 +1,100 @@
|
||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from resources import build, cli_menu, constants, utilities, device_probe, os_probe, defaults, arguments, install
|
||||
from data import model_array
|
||||
|
||||
class OpenCoreLegacyPatcher:
|
||||
def __init__(self, launch_gui=False):
|
||||
print("- Loading...")
|
||||
self.constants = constants.Constants()
|
||||
self.generate_base_data()
|
||||
if utilities.check_cli_args() is None:
|
||||
if launch_gui is True:
|
||||
from gui import gui_main
|
||||
gui_main.wx_python_gui(self.constants)
|
||||
else:
|
||||
self.main_menu()
|
||||
|
||||
def generate_base_data(self):
|
||||
self.constants.detected_os = os_probe.detect_kernel_major()
|
||||
self.constants.detected_os_minor = os_probe.detect_kernel_minor()
|
||||
self.constants.detected_os_build = os_probe.detect_kernel_build()
|
||||
self.constants.computer = device_probe.Computer.probe()
|
||||
self.constants.recovery_status = utilities.check_recovery()
|
||||
self.computer = self.constants.computer
|
||||
launcher_script = None
|
||||
launcher_binary = sys.executable
|
||||
if "python" in launcher_binary:
|
||||
# We're running from source
|
||||
launcher_script = __file__
|
||||
if "main.py" in launcher_script:
|
||||
launcher_script = launcher_script.replace("/resources/main.py", "/OpenCore-Patcher-GUI.command")
|
||||
self.constants.launcher_binary = launcher_binary
|
||||
self.constants.launcher_script = launcher_script
|
||||
defaults.generate_defaults.probe(self.computer.real_model, True, self.constants)
|
||||
if utilities.check_cli_args() is not None:
|
||||
print("- Detected arguments, switching to CLI mode")
|
||||
self.constants.gui_mode = True # Assumes no user interaction is required
|
||||
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")
|
||||
arguments.arguments().parse_arguments(self.constants)
|
||||
else:
|
||||
print("- No arguments present, loading TUI")
|
||||
|
||||
def main_menu(self):
|
||||
response = None
|
||||
while not (response and response == -1):
|
||||
title = [
|
||||
f"OpenCore Legacy Patcher v{self.constants.patcher_version}",
|
||||
f"Selected Model: {self.constants.custom_model or self.computer.real_model}",
|
||||
]
|
||||
|
||||
if (self.constants.custom_model or self.computer.real_model) not in model_array.SupportedSMBIOS and self.constants.allow_oc_everywhere is False:
|
||||
in_between = [
|
||||
"Your model is not supported by this patcher for running unsupported OSes!",
|
||||
"",
|
||||
'If you plan to create the USB for another machine, please select the \n"Change Model" option in the menu.',
|
||||
"",
|
||||
'If you want to run OCLP on a native Mac, please toggle \n"Allow OpenCore on native Models" in settings',
|
||||
]
|
||||
elif not self.constants.custom_model and self.computer.real_model == "iMac7,1" and "SSE4.1" not in self.computer.cpu.flags:
|
||||
in_between = [
|
||||
"Your model requires a CPU upgrade to a CPU supporting SSE4.1+ to be supported by this patcher!",
|
||||
"",
|
||||
f'If you plan to create the USB for another {self.computer.real_model} with SSE4.1+, please select the "Change Model" option in the menu.',
|
||||
]
|
||||
elif self.constants.custom_model == "iMac7,1":
|
||||
in_between = ["This model is supported", "However please ensure the CPU has been upgraded to support SSE4.1+"]
|
||||
else:
|
||||
in_between = ["This model is supported"]
|
||||
|
||||
menu = utilities.TUIMenu(title, "Please select an option: ", in_between=in_between, auto_number=True, top_level=True)
|
||||
|
||||
options = (
|
||||
[["Build OpenCore", build.BuildOpenCore(self.constants.custom_model or self.constants.computer.real_model, self.constants).build_opencore]]
|
||||
if ((self.constants.custom_model or self.computer.real_model) in model_array.SupportedSMBIOS) or self.constants.allow_oc_everywhere is True
|
||||
else []
|
||||
) + [
|
||||
["Install OpenCore to USB/internal drive", install.tui_disk_installation(self.constants).copy_efi],
|
||||
["Post-Install Volume Patch", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).PatchVolume],
|
||||
["Change Model", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).change_model],
|
||||
["Patcher Settings", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).patcher_settings],
|
||||
["Installer Creation", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).download_macOS],
|
||||
["Credits", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).credits],
|
||||
]
|
||||
|
||||
for option in options:
|
||||
menu.add_menu_option(option[0], function=option[1])
|
||||
|
||||
response = menu.start()
|
||||
|
||||
if getattr(sys, "frozen", False) and self.constants.recovery_status is False:
|
||||
subprocess.run("""osascript -e 'tell application "Terminal" to close first window' & exit""", shell=True)
|
||||
155
resources/run.py
Normal file
@@ -0,0 +1,155 @@
|
||||
# Module for running processes with real time output
|
||||
# Written by CorpNewt
|
||||
# Source: https://github.com/corpnewt/pymodules/blob/884c3de15b6a2570afde52fe8a14a3e946ffb18a/run.py
|
||||
|
||||
import sys, subprocess, time, threading, shlex
|
||||
try:
|
||||
from Queue import Queue, Empty
|
||||
except:
|
||||
from queue import Queue, Empty
|
||||
|
||||
ON_POSIX = 'posix' in sys.builtin_module_names
|
||||
|
||||
class Run:
|
||||
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
def _read_output(self, pipe, q):
|
||||
try:
|
||||
for line in iter(lambda: pipe.read(1), b''):
|
||||
q.put(line)
|
||||
except ValueError:
|
||||
pass
|
||||
pipe.close()
|
||||
|
||||
def _create_thread(self, output):
|
||||
# Creates a new queue and thread object to watch based on the output pipe sent
|
||||
q = Queue()
|
||||
t = threading.Thread(target=self._read_output, args=(output, q))
|
||||
t.daemon = True
|
||||
return (q,t)
|
||||
|
||||
def _stream_output(self, comm, shell = False):
|
||||
output = error = ""
|
||||
p = None
|
||||
try:
|
||||
if shell and type(comm) is list:
|
||||
comm = " ".join(shlex.quote(x) for x in comm)
|
||||
if not shell and type(comm) is str:
|
||||
comm = shlex.split(comm)
|
||||
p = subprocess.Popen(comm, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0, universal_newlines=True, close_fds=ON_POSIX)
|
||||
# Setup the stdout thread/queue
|
||||
q,t = self._create_thread(p.stdout)
|
||||
qe,te = self._create_thread(p.stderr)
|
||||
# Start both threads
|
||||
t.start()
|
||||
te.start()
|
||||
|
||||
while True:
|
||||
c = z = ""
|
||||
try: c = q.get_nowait()
|
||||
except Empty: pass
|
||||
else:
|
||||
sys.stdout.write(c)
|
||||
output += c
|
||||
sys.stdout.flush()
|
||||
try: z = qe.get_nowait()
|
||||
except Empty: pass
|
||||
else:
|
||||
sys.stderr.write(z)
|
||||
error += z
|
||||
sys.stderr.flush()
|
||||
if not c==z=="": continue # Keep going until empty
|
||||
# No output - see if still running
|
||||
p.poll()
|
||||
if p.returncode != None:
|
||||
# Subprocess ended
|
||||
break
|
||||
# No output, but subprocess still running - stall for 20ms
|
||||
time.sleep(0.02)
|
||||
|
||||
o, e = p.communicate()
|
||||
return (output+o, error+e, p.returncode)
|
||||
except:
|
||||
if p:
|
||||
try: o, e = p.communicate()
|
||||
except: o = e = ""
|
||||
return (output+o, error+e, p.returncode)
|
||||
return ("", "Command not found!", 1)
|
||||
|
||||
def _decode(self, value, encoding="utf-8", errors="ignore"):
|
||||
# Helper method to only decode if bytes type
|
||||
if sys.version_info >= (3,0) and isinstance(value, bytes):
|
||||
return value.decode(encoding,errors)
|
||||
return value
|
||||
|
||||
def _run_command(self, comm, shell = False):
|
||||
c = None
|
||||
try:
|
||||
if shell and type(comm) is list:
|
||||
comm = " ".join(shlex.quote(x) for x in comm)
|
||||
if not shell and type(comm) is str:
|
||||
comm = shlex.split(comm)
|
||||
p = subprocess.Popen(comm, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
c = p.communicate()
|
||||
except:
|
||||
if c == None:
|
||||
return ("", "Command not found!", 1)
|
||||
return (self._decode(c[0]), self._decode(c[1]), p.returncode)
|
||||
|
||||
def run(self, command_list, leave_on_fail = False):
|
||||
# Command list should be an array of dicts
|
||||
if type(command_list) is dict:
|
||||
# We only have one command
|
||||
command_list = [command_list]
|
||||
output_list = []
|
||||
for comm in command_list:
|
||||
args = comm.get("args", [])
|
||||
shell = comm.get("shell", False)
|
||||
stream = comm.get("stream", False)
|
||||
sudo = comm.get("sudo", False)
|
||||
stdout = comm.get("stdout", False)
|
||||
stderr = comm.get("stderr", False)
|
||||
mess = comm.get("message", None)
|
||||
show = comm.get("show", False)
|
||||
|
||||
if not mess == None:
|
||||
print(mess)
|
||||
|
||||
if not len(args):
|
||||
# nothing to process
|
||||
continue
|
||||
if sudo:
|
||||
# Check if we have sudo
|
||||
out = self._run_command(["which", "sudo"])
|
||||
if "sudo" in out[0]:
|
||||
# Can sudo
|
||||
if type(args) is list:
|
||||
args.insert(0, out[0].replace("\n", "")) # add to start of list
|
||||
elif type(args) is str:
|
||||
args = out[0].replace("\n", "") + " " + args # add to start of string
|
||||
|
||||
if show:
|
||||
print(" ".join(args))
|
||||
|
||||
if stream:
|
||||
# Stream it!
|
||||
out = self._stream_output(args, shell)
|
||||
else:
|
||||
# Just run and gather output
|
||||
out = self._run_command(args, shell)
|
||||
if stdout and len(out[0]):
|
||||
print(out[0])
|
||||
if stderr and len(out[1]):
|
||||
print(out[1])
|
||||
# Append output
|
||||
output_list.append(out)
|
||||
# Check for errors
|
||||
if leave_on_fail and out[2] != 0:
|
||||
# Got an error - leave
|
||||
break
|
||||
if len(output_list) == 1:
|
||||
# We only ran one command - just return that output
|
||||
return output_list[0]
|
||||
return output_list
|
||||
@@ -1,5 +1,5 @@
|
||||
# Framework for mounting and patching macOS root volume
|
||||
# Copyright (C) 2020-2021, Dhinak G, Mykola Grymalyuk
|
||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||
# Missing Features:
|
||||
# - Full System/Library Snapshotting (need to research how Apple achieves this)
|
||||
# - Temporary Work-around: sudo bless --mount /System/Volumes/Update/mnt1 --bootefi --last-sealed-snapshot
|
||||
@@ -12,8 +12,8 @@ import zipfile
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
from resources import constants, device_probe, utilities, generate_smbios
|
||||
from data import sip_data, sys_patch_data, model_array, os_data, smbios_data, cpu_data, dylib_data
|
||||
from resources import constants, device_probe, utilities, generate_smbios, sys_patch_download
|
||||
from data import sip_data, sys_patch_data, model_array, os_data, smbios_data, cpu_data
|
||||
|
||||
|
||||
class PatchSysVolume:
|
||||
@@ -62,6 +62,7 @@ class PatchSysVolume:
|
||||
self.mount_libexec = f"{self.mount_location}/usr/libexec"
|
||||
self.mount_extensions_mux = f"{self.mount_location}/System/Library/Extensions/AppleGraphicsControl.kext/Contents/PlugIns/"
|
||||
self.mount_private_etc = f"{self.mount_location_data}/private/etc"
|
||||
self.mount_application_support = f"{self.mount_location_data}/Library/Application Support"
|
||||
|
||||
def find_mount_root_vol(self, patch):
|
||||
self.root_mount_path = utilities.get_disk_path()
|
||||
@@ -85,7 +86,9 @@ class PatchSysVolume:
|
||||
else:
|
||||
if self.constants.detected_os > os_data.os_data.catalina:
|
||||
print("- Mounting APFS Snapshot as writable")
|
||||
utilities.elevated(["mount", "-o", "nobrowse", "-t", "apfs", f"/dev/{self.root_mount_path}", self.mount_location], stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
||||
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:
|
||||
print(f"- Mounted APFS Snapshot as writable at: {self.mount_location}")
|
||||
if Path(self.mount_extensions).exists():
|
||||
print("- Successfully mounted the Root Volume")
|
||||
if patch is True:
|
||||
@@ -215,26 +218,6 @@ class PatchSysVolume:
|
||||
self.manual_root_patch_revert()
|
||||
|
||||
def rebuild_snapshot(self):
|
||||
# Grab List.txt if appropriate
|
||||
dylib_list = self.build_skylight_plugin_list()
|
||||
if dylib_list is not None:
|
||||
print("- Updating SkyLightPlugins List.txt")
|
||||
if (Path(self.mount_private_etc) / Path("SkyLightPlugins/List.txt")).exists():
|
||||
print("- Removing existing List.txt")
|
||||
utilities.process_status(
|
||||
utilities.elevated(
|
||||
["rm", "-f", f"{self.mount_private_etc}/SkyLightPlugins/List.txt"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
)
|
||||
utilities.process_status(
|
||||
utilities.elevated(
|
||||
["cp", dylib_list, f"{self.mount_private_etc}/SkyLightPlugins/"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
)
|
||||
print("- Rebuilding Kernel Cache (This may take some time)")
|
||||
if self.constants.detected_os > os_data.os_data.catalina:
|
||||
result = utilities.elevated(["kmutil", "install", "--volume-root", self.mount_location, "--update-all"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
@@ -272,7 +255,7 @@ class PatchSysVolume:
|
||||
print(bless.stdout.decode())
|
||||
if "Can't use last-sealed-snapshot or create-snapshot on non system volume" in bless.stdout.decode():
|
||||
print("- This is an APFS bug with Monterey! Perform a clean installation to ensure your APFS volume is built correctly")
|
||||
sys.exit(1)
|
||||
return
|
||||
else:
|
||||
self.unmount_drive()
|
||||
else:
|
||||
@@ -316,35 +299,7 @@ set million colour before rebooting"""
|
||||
utilities.process_status(utilities.elevated(["cp", "-R", f"{vendor_location}/{add_current_kext}", self.mount_extensions], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||
utilities.process_status(utilities.elevated(["chmod", "-Rf", "755", f"{self.mount_extensions}/{add_current_kext}"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||
utilities.process_status(utilities.elevated(["chown", "-Rf", "root:wheel", f"{self.mount_extensions}/{add_current_kext}"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||
|
||||
def build_skylight_plugin_list(self):
|
||||
# ASentientBot's Skylight system support injecting additional dylibs into macOS
|
||||
# To do so, it parses the List.txt file in '/private/etc/SkyLightPlugins/'
|
||||
# The format of this file is:
|
||||
# <plugin path> : <plugin name>
|
||||
# Parse all dylibs in /private/etc/SkyLightPlugins/, generate an appropriate List.txt
|
||||
|
||||
skylight_plugins = []
|
||||
if self.constants.list_txt_path.exists():
|
||||
self.constants.list_txt_path.unlink()
|
||||
|
||||
if (Path(self.mount_private_etc) / Path("SkyLightPlugins")).exists():
|
||||
for file in (Path(self.mount_private_etc) / Path("SkyLightPlugins")).glob("*.dylib"):
|
||||
skylight_plugins.append(file.name)
|
||||
if len(skylight_plugins) > 0:
|
||||
with open(self.constants.list_txt_path, "w") as f:
|
||||
for plugin in skylight_plugins:
|
||||
try:
|
||||
path = dylib_data.shim_list.shim_pathing[plugin]
|
||||
print(f"- Adding {plugin} to list.txt")
|
||||
f.write(f"{path} : {plugin}\n")
|
||||
except KeyError:
|
||||
print(f"- Skipping {plugin}, unknown pathing")
|
||||
continue
|
||||
return self.constants.list_txt_path
|
||||
return None
|
||||
|
||||
|
||||
def add_brightness_patch(self):
|
||||
self.delete_old_binaries(sys_patch_data.DeleteBrightness)
|
||||
self.add_new_binaries(sys_patch_data.AddBrightness, self.constants.legacy_brightness)
|
||||
@@ -372,8 +327,8 @@ set million colour before rebooting"""
|
||||
# dylib patch to resolve password crash prompt
|
||||
# Note requires ASentientBot's SkyLight to function
|
||||
# Thus Metal machines do not benefit from this patch, however install anyways as harmless
|
||||
print("- Merging Wireless private/etc")
|
||||
utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.legacy_wifi_etc}/", self.mount_private_etc], stdout=subprocess.PIPE)
|
||||
print("- Merging Wireless SkyLightPlugins")
|
||||
utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.legacy_wifi_support}/", self.mount_application_support], stdout=subprocess.PIPE)
|
||||
|
||||
def add_legacy_mux_patch(self):
|
||||
self.delete_old_binaries(sys_patch_data.DeleteDemux)
|
||||
@@ -383,8 +338,12 @@ set million colour before rebooting"""
|
||||
)
|
||||
|
||||
def add_legacy_keyboard_backlight_patch(self):
|
||||
print("- Merging Backlight private/etc")
|
||||
utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.legacy_keyboard_backlight_etc}/", self.mount_private_etc], stdout=subprocess.PIPE)
|
||||
print("- Merging Keyboard Backlight SkyLightPlugins")
|
||||
utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.legacy_keyboard_backlight_support}/", self.mount_application_support], stdout=subprocess.PIPE)
|
||||
|
||||
def add_legacy_dropbox_patch(self):
|
||||
print("- Merging DropboxHack SkyLightPlugins")
|
||||
utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.legacy_dropbox_support}/", self.mount_application_support], stdout=subprocess.PIPE)
|
||||
|
||||
def gpu_accel_legacy(self):
|
||||
if self.constants.detected_os == os_data.os_data.mojave:
|
||||
@@ -543,6 +502,9 @@ set million colour before rebooting"""
|
||||
utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_private_frameworks_path_legacy_drm}/", self.mount_private_frameworks], stdout=subprocess.PIPE)
|
||||
|
||||
def gpu_accel_legacy_extended(self):
|
||||
if self.constants.detected_os == os_data.os_data.monterey:
|
||||
self.add_legacy_dropbox_patch()
|
||||
|
||||
print("- Merging general legacy Frameworks")
|
||||
utilities.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.payload_apple_frameworks_path_accel}/", self.mount_frameworks], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
if self.constants.detected_os > os_data.os_data.big_sur:
|
||||
@@ -677,47 +639,26 @@ set million colour before rebooting"""
|
||||
|
||||
def check_files(self):
|
||||
if Path(self.constants.payload_apple_root_path).exists():
|
||||
print("- Found Apple Binaries")
|
||||
print("- Found local Apple Binaries")
|
||||
if self.constants.gui_mode is False:
|
||||
patch_input = input("Would you like to redownload?(y/n): ")
|
||||
if patch_input in {"y", "Y", "yes", "Yes"}:
|
||||
shutil.rmtree(Path(self.constants.payload_apple_root_path))
|
||||
self.download_files()
|
||||
output = self.download_files()
|
||||
else:
|
||||
self.download_files()
|
||||
output = self.download_files()
|
||||
else:
|
||||
print("- Apple binaries missing")
|
||||
self.download_files()
|
||||
output = self.download_files()
|
||||
return output
|
||||
|
||||
def download_files(self):
|
||||
if self.constants.detected_os == os_data.os_data.monterey:
|
||||
os_ver = "12-Monterey"
|
||||
elif self.constants.detected_os == os_data.os_data.big_sur:
|
||||
os_ver = "11-Big-Sur"
|
||||
elif self.constants.detected_os == os_data.os_data.catalina:
|
||||
os_ver = "10.15-Catalina"
|
||||
elif self.constants.detected_os == os_data.os_data.mojave:
|
||||
os_ver = "10.14-Mojave"
|
||||
if self.constants.gui_mode is False:
|
||||
download_result, os_ver, link = sys_patch_download.grab_patcher_support_pkg(self.constants).download_files()
|
||||
else:
|
||||
raise Exception(f"Unsupported OS: {self.constants.detected_os}")
|
||||
link = f"{self.constants.url_patcher_support_pkg}{self.constants.patcher_support_pkg_version}/{os_ver}.zip"
|
||||
download_result = True
|
||||
os_ver, link = sys_patch_download.grab_patcher_support_pkg(self.constants).generate_pkg_link()
|
||||
|
||||
if Path(self.constants.payload_apple_root_path).exists():
|
||||
print("- Removing old Apple Binaries folder")
|
||||
Path(self.constants.payload_apple_root_path).unlink()
|
||||
if Path(self.constants.payload_apple_root_path_zip).exists():
|
||||
print("- Removing old Apple Binaries zip")
|
||||
Path(self.constants.payload_apple_root_path_zip).unlink()
|
||||
|
||||
local_zip = Path(self.constants.payload_path) / f"{os_ver}.zip"
|
||||
if Path(local_zip).exists():
|
||||
print(f"- Found local {os_ver} zip, skipping download")
|
||||
print(f"- Duplicating into Apple.zip")
|
||||
shutil.copy(local_zip, self.constants.payload_apple_root_path_zip)
|
||||
else:
|
||||
utilities.download_file(link, self.constants.payload_apple_root_path_zip)
|
||||
|
||||
if self.constants.payload_apple_root_path_zip.exists():
|
||||
if download_result and self.constants.payload_apple_root_path_zip.exists():
|
||||
print("- Download completed")
|
||||
print("- Unzipping download...")
|
||||
try:
|
||||
@@ -727,15 +668,19 @@ set million colour before rebooting"""
|
||||
Path(self.constants.payload_apple_root_path_zip).unlink()
|
||||
print("- Binaries downloaded to:")
|
||||
print(self.constants.payload_path)
|
||||
# if self.constants.gui_mode is False:
|
||||
# input("Press [ENTER] to continue")
|
||||
return self.constants.payload_apple_root_path
|
||||
except zipfile.BadZipFile:
|
||||
print("- Couldn't unzip")
|
||||
return
|
||||
return None
|
||||
else:
|
||||
print("- Download failed, please verify the below link works:")
|
||||
print(link)
|
||||
input("Press [ENTER] to continue")
|
||||
if self.constants.gui_mode is True:
|
||||
print("- Download failed, please verify the below link works:")
|
||||
print(link)
|
||||
print("\nIf you continue to have issues, try using the Offline builds")
|
||||
print("located on Github next to the other builds")
|
||||
else:
|
||||
input("\nPress enter to continue")
|
||||
return None
|
||||
|
||||
def detect_gpus(self):
|
||||
gpus = self.constants.computer.gpus
|
||||
@@ -952,7 +897,7 @@ set million colour before rebooting"""
|
||||
# Entry Function
|
||||
def start_patch(self):
|
||||
print("- Starting Patch Process")
|
||||
print(f"- Determinging Required Patch set for Darwin {self.constants.detected_os}")
|
||||
print(f"- Determining Required Patch set for Darwin {self.constants.detected_os}")
|
||||
self.detect_patch_set()
|
||||
if self.no_patch is True:
|
||||
change_menu = None
|
||||
@@ -963,14 +908,14 @@ set million colour before rebooting"""
|
||||
change_menu = input("Would you like to continue with Root Volume Patching?(y/n): ")
|
||||
else:
|
||||
change_menu = "y"
|
||||
print("Continuing root patching")
|
||||
print("- Continuing root patching")
|
||||
if change_menu in ["y", "Y"]:
|
||||
print("- Continuing with Patching")
|
||||
print("- Verifying whether Root Patching possible")
|
||||
if self.verify_patch_allowed() is True:
|
||||
print("- Patcher is capable of patching")
|
||||
self.check_files()
|
||||
self.find_mount_root_vol(True)
|
||||
if self.check_files():
|
||||
self.find_mount_root_vol(True)
|
||||
elif self.constants.gui_mode is False:
|
||||
input("\nPress [ENTER] to return to the main menu: ")
|
||||
|
||||
|
||||
196
resources/sys_patch_detect.py
Normal file
@@ -0,0 +1,196 @@
|
||||
from resources import constants, device_probe, utilities, generate_smbios
|
||||
from data import model_array, os_data, smbios_data, cpu_data, sip_data
|
||||
|
||||
class detect_root_patch:
|
||||
def __init__(self, model, versions):
|
||||
self.model = model
|
||||
self.constants: constants.Constants() = versions
|
||||
self.computer = self.constants.computer
|
||||
|
||||
# GPU Patch Detection
|
||||
self.nvidia_legacy= False
|
||||
self.kepler_gpu= False
|
||||
self.amd_ts1= False
|
||||
self.amd_ts2= False
|
||||
self.iron_gpu= False
|
||||
self.sandy_gpu= False
|
||||
self.ivy_gpu= False
|
||||
|
||||
# Misc Patch Detection
|
||||
self.brightness_legacy= False
|
||||
self.legacy_audio= False
|
||||
self.legacy_wifi= False
|
||||
self.legacy_gmux= False
|
||||
self.legacy_keyboard_backlight= False
|
||||
|
||||
# Patch Requirements
|
||||
self.amfi_must_disable= False
|
||||
self.check_board_id= False
|
||||
self.supports_metal= False
|
||||
|
||||
# Validation Checks
|
||||
self.sip_enabled = False
|
||||
self.sbm_enabled = False
|
||||
self.amfi_enabled = False
|
||||
self.fv_enabled = False
|
||||
self.dosdude_patched = False
|
||||
self.bad_board_id = False
|
||||
|
||||
|
||||
def detect_gpus(self):
|
||||
gpus = self.constants.computer.gpus
|
||||
if self.constants.moj_cat_accel is True:
|
||||
non_metal_os = os_data.os_data.high_sierra
|
||||
else:
|
||||
non_metal_os = os_data.os_data.catalina
|
||||
for i, gpu in enumerate(gpus):
|
||||
if gpu.class_code and gpu.class_code != 0xFFFFFFFF:
|
||||
print(f"- Found GPU ({i}): {utilities.friendly_hex(gpu.vendor_id)}:{utilities.friendly_hex(gpu.device_id)}")
|
||||
if gpu.arch in [device_probe.NVIDIA.Archs.Tesla, device_probe.NVIDIA.Archs.Fermi]:
|
||||
if self.constants.detected_os > non_metal_os:
|
||||
self.nvidia_legacy = True
|
||||
self.amfi_must_disable = True
|
||||
# self.legacy_keyboard_backlight = self.check_legacy_keyboard_backlight()
|
||||
elif gpu.arch == device_probe.NVIDIA.Archs.Kepler:
|
||||
if self.constants.detected_os > os_data.os_data.big_sur:
|
||||
# Kepler drivers were dropped with Beta 7
|
||||
# 12.0 Beta 5: 21.0.0 - 21A5304g
|
||||
# 12.0 Beta 6: 21.1.0 - 21A5506j
|
||||
# 12.0 Beta 7: 21.1.0 - 21A5522h
|
||||
if self.constants.detected_os == os_data.os_data.monterey and self.constants.detected_os_minor > 0:
|
||||
if "21A5506j" not in self.constants.detected_os_build:
|
||||
self.kepler_gpu = True
|
||||
self.supports_metal = True
|
||||
elif gpu.arch == device_probe.AMD.Archs.TeraScale_1:
|
||||
if self.constants.detected_os > non_metal_os:
|
||||
self.amd_ts1 = True
|
||||
self.amfi_must_disable = True
|
||||
elif gpu.arch == device_probe.AMD.Archs.TeraScale_2:
|
||||
if self.constants.detected_os > non_metal_os:
|
||||
self.amd_ts2 = True
|
||||
self.amfi_must_disable = True
|
||||
elif gpu.arch == device_probe.Intel.Archs.Iron_Lake:
|
||||
if self.constants.detected_os > non_metal_os:
|
||||
self.iron_gpu = True
|
||||
self.amfi_must_disable = True
|
||||
elif gpu.arch == device_probe.Intel.Archs.Sandy_Bridge:
|
||||
if self.constants.detected_os > non_metal_os:
|
||||
self.sandy_gpu = True
|
||||
self.amfi_must_disable = True
|
||||
self.check_board_id = True
|
||||
elif gpu.arch == device_probe.Intel.Archs.Ivy_Bridge:
|
||||
if self.constants.detected_os > os_data.os_data.big_sur:
|
||||
self.ivy_gpu = True
|
||||
self.supports_metal = True
|
||||
if self.supports_metal is True:
|
||||
# Avoid patching Metal and non-Metal GPUs if both present, prioritize Metal GPU
|
||||
# Main concerns are for iMac12,x with Sandy iGPU and Kepler dGPU
|
||||
self.nvidia_legacy = False
|
||||
self.amd_ts1 = False
|
||||
self.amd_ts2 = False
|
||||
self.iron_gpu = False
|
||||
self.sandy_gpu = False
|
||||
|
||||
def check_dgpu_status(self):
|
||||
dgpu = self.constants.computer.dgpu
|
||||
if dgpu:
|
||||
if dgpu.class_code and dgpu.class_code == 0xFFFFFFFF:
|
||||
# If dGPU is disabled via class-codes, assume demuxed
|
||||
return False
|
||||
return True
|
||||
return False
|
||||
|
||||
def detect_demux(self):
|
||||
# If GFX0 is missing, assume machine was demuxed
|
||||
# -wegnoegpu would also trigger this, so ensure arg is not present
|
||||
if not "-wegnoegpu" in (utilities.get_nvram("boot-args") or ""):
|
||||
igpu = self.constants.computer.igpu
|
||||
dgpu = self.check_dgpu_status()
|
||||
if igpu and not dgpu:
|
||||
return True
|
||||
return False
|
||||
|
||||
def check_legacy_keyboard_backlight(self):
|
||||
# With Big Sur and newer, Skylight patch set unfortunately breaks native keyboard backlight
|
||||
# Penryn Macs are able to re-enable the keyboard backlight by simply running '/usr/libexec/TouchBarServer'
|
||||
# For Arrendale and newer, this has no effect.
|
||||
if self.model.startswith("MacBookPro") or self.model.startswith("MacBookAir"):
|
||||
# non-Metal MacBooks never had keyboard backlight
|
||||
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.penryn.value:
|
||||
if self.constants.detected_os > os_data.os_data.catalina:
|
||||
return True
|
||||
return False
|
||||
|
||||
def detect_patch_set(self):
|
||||
self.detect_gpus()
|
||||
if self.model in model_array.LegacyBrightness:
|
||||
if self.constants.detected_os > os_data.os_data.catalina:
|
||||
self.brightness_legacy = True
|
||||
|
||||
if self.model in ["iMac7,1", "iMac8,1"] or (self.model in model_array.LegacyAudio and utilities.check_kext_loaded("AppleALC", self.constants.detected_os) is False):
|
||||
# Special hack for systems with botched GOPs
|
||||
# TL;DR: No Boot Screen breaks Lilu, therefore breaking audio
|
||||
if self.constants.detected_os > os_data.os_data.catalina:
|
||||
self.legacy_audio = True
|
||||
|
||||
if (
|
||||
isinstance(self.constants.computer.wifi, device_probe.Broadcom)
|
||||
and self.constants.computer.wifi.chipset in [device_probe.Broadcom.Chipsets.AirPortBrcm4331, device_probe.Broadcom.Chipsets.AirPortBrcm43224]
|
||||
) or (isinstance(self.constants.computer.wifi, device_probe.Atheros) and self.constants.computer.wifi.chipset == device_probe.Atheros.Chipsets.AirPortAtheros40):
|
||||
if self.constants.detected_os > os_data.os_data.big_sur:
|
||||
self.legacy_wifi = True
|
||||
|
||||
# if self.model in ["MacBookPro5,1", "MacBookPro5,2", "MacBookPro5,3", "MacBookPro8,2", "MacBookPro8,3"]:
|
||||
if self.model in ["MacBookPro8,2", "MacBookPro8,3"]:
|
||||
# Sierra uses a legacy GMUX control method needed for dGPU switching on MacBookPro5,x
|
||||
# Same method is also used for demuxed machines
|
||||
# Note that MacBookPro5,x machines are extremely unstable with this patch set, so disabled until investigated further
|
||||
# Ref: https://github.com/dortania/OpenCore-Legacy-Patcher/files/7360909/KP-b10-030.txt
|
||||
if self.constants.detected_os > os_data.os_data.high_sierra:
|
||||
if self.model in ["MacBookPro8,2", "MacBookPro8,3"]:
|
||||
# Ref: https://doslabelectronics.com/Demux.html
|
||||
if self.detect_demux() is True:
|
||||
self.legacy_gmux = True
|
||||
else:
|
||||
self.legacy_gmux = True
|
||||
|
||||
self.root_patch_dict = {
|
||||
"Graphics: Nvidia Tesla": self.nvidia_legacy,
|
||||
"Graphics: Nvidia Kepler": self.kepler_gpu,
|
||||
"Graphics: AMD TeraScale 1": self.amd_ts1,
|
||||
"Graphics: AMD TeraScale 2": self.amd_ts2,
|
||||
"Graphics: Intel Ironlake": self.iron_gpu,
|
||||
"Graphics: Intel Sandy Bridge": self.sandy_gpu,
|
||||
"Graphics: Intel Ivy Bridge": self.ivy_gpu,
|
||||
# "Graphics: Intel Ivy Bridge": True,
|
||||
"Brightness: Legacy Backlight Control": self.brightness_legacy,
|
||||
"Audio: Legacy Realtek": self.legacy_audio,
|
||||
"Networking: Legacy Wireless": self.legacy_wifi,
|
||||
"Miscellaneous: Legacy GMUX": self.legacy_gmux,
|
||||
"Miscellaneous: Legacy Keyboard Backlight": self.legacy_keyboard_backlight,
|
||||
"Settings: Requires AMFI exemption": self.amfi_must_disable,
|
||||
"Settings: Requires Board ID validation": self.check_board_id,
|
||||
"Validation: Patching Possible": self.verify_patch_allowed(),
|
||||
"Validation: SIP is enabled": self.sip_enabled,
|
||||
"Validation: SBM is enabled": self.sbm_enabled,
|
||||
"Validation: AMFI is enabled": self.amfi_enabled,
|
||||
"Validation: FileVault is enabled": self.fv_enabled,
|
||||
"Validation: System is dosdude1 patched": self.dosdude_patched,
|
||||
"Validation: Board ID is unsupported": self.bad_board_id,
|
||||
}
|
||||
|
||||
return self.root_patch_dict
|
||||
|
||||
def verify_patch_allowed(self):
|
||||
sip = sip_data.system_integrity_protection.root_patch_sip_big_sur if self.constants.detected_os > os_data.os_data.catalina else sip_data.system_integrity_protection.root_patch_sip_mojave
|
||||
self.sip_enabled, self.sbm_enabled, self.amfi_enabled, self.fv_enabled, self.dosdude_patched = utilities.patching_status(sip, self.constants.detected_os)
|
||||
|
||||
if self.check_board_id is True and (self.computer.reported_board_id not in self.constants.sandy_board_id and self.computer.reported_board_id not in self.constants.sandy_board_id_stock):
|
||||
self.bad_board_id = True
|
||||
|
||||
if any(
|
||||
[self.sip_enabled, self.sbm_enabled, self.fv_enabled, self.dosdude_patched, self.amfi_enabled if self.amfi_must_disable else False, self.bad_board_id if self.check_board_id else False]
|
||||
):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
48
resources/sys_patch_download.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# Download PatcherSupportPkg for usage with Root Patching
|
||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||
|
||||
from data import os_data
|
||||
from resources import utilities
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
|
||||
class grab_patcher_support_pkg:
|
||||
|
||||
def __init__(self, constants):
|
||||
self.constants = constants
|
||||
|
||||
def generate_pkg_link(self):
|
||||
if self.constants.detected_os == os_data.os_data.monterey:
|
||||
os_ver = "12-Monterey"
|
||||
elif self.constants.detected_os == os_data.os_data.big_sur:
|
||||
os_ver = "11-Big-Sur"
|
||||
elif self.constants.detected_os == os_data.os_data.catalina:
|
||||
os_ver = "10.15-Catalina"
|
||||
elif self.constants.detected_os == os_data.os_data.mojave:
|
||||
os_ver = "10.14-Mojave"
|
||||
else:
|
||||
raise Exception(f"Unsupported OS: {self.constants.detected_os}")
|
||||
link = f"{self.constants.url_patcher_support_pkg}{self.constants.patcher_support_pkg_version}/{os_ver}.zip"
|
||||
return os_ver, link
|
||||
|
||||
def download_files(self):
|
||||
os_ver, link = self.generate_pkg_link()
|
||||
if Path(self.constants.payload_apple_root_path).exists():
|
||||
print("- Removing old Apple Binaries folder")
|
||||
# Delete folder
|
||||
shutil.rmtree(self.constants.payload_apple_root_path)
|
||||
if Path(self.constants.payload_apple_root_path_zip).exists():
|
||||
print("- Removing old Apple Binaries zip")
|
||||
Path(self.constants.payload_apple_root_path_zip).unlink()
|
||||
|
||||
download_result = None
|
||||
local_zip = Path(self.constants.payload_path) / f"{os_ver}.zip"
|
||||
if Path(local_zip).exists():
|
||||
print(f"- Found local {os_ver} zip, skipping download")
|
||||
print(f"- Duplicating into Apple.zip")
|
||||
shutil.copy(local_zip, self.constants.payload_apple_root_path_zip)
|
||||
download_result = True
|
||||
else:
|
||||
download_result = utilities.download_file(link, self.constants.payload_apple_root_path_zip)
|
||||
|
||||
return download_result, os_ver, link
|
||||
120
resources/updates.py
Normal file
@@ -0,0 +1,120 @@
|
||||
# Copyright (C) 2022, Mykola Grymalyuk
|
||||
# Check whether new updates are available for OpenCore Legacy Patcher binary
|
||||
# Call check_binary_updates() to determine if any updates are available
|
||||
# Returns dict with Link and Version of the latest binary update if available
|
||||
import requests
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class check_binary_updates:
|
||||
def __init__(self, constants):
|
||||
self.constants = constants
|
||||
self.binary_version = self.constants.patcher_version
|
||||
self.binary_version_array = self.binary_version.split(".")
|
||||
self.binary_version_array = [int(x) for x in self.binary_version_array]
|
||||
self.binary_url = "https://api.github.com/repos/dortania/OpenCore-Legacy-Patcher/releases/latest"
|
||||
|
||||
self.available_binaries = {}
|
||||
|
||||
def verify_network_connection(self, url):
|
||||
try:
|
||||
response = requests.head(url, timeout=5)
|
||||
if response:
|
||||
return True
|
||||
except (requests.exceptions.Timeout,
|
||||
requests.exceptions.TooManyRedirects,
|
||||
requests.exceptions.ConnectionError,
|
||||
requests.exceptions.HTTPError):
|
||||
return False
|
||||
return False
|
||||
|
||||
def check_if_build_newer(self):
|
||||
if self.remote_version_array[0] > self.binary_version_array[0]:
|
||||
return True
|
||||
elif self.remote_version_array[0] == self.binary_version_array[0]:
|
||||
if self.remote_version_array[1] > self.binary_version_array[1]:
|
||||
return True
|
||||
elif self.remote_version_array[1] == self.binary_version_array[1]:
|
||||
if self.remote_version_array[2] > self.binary_version_array[2]:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
return False
|
||||
|
||||
def determine_local_build_type(self):
|
||||
if self.constants.gui_mode is True:
|
||||
return "GUI"
|
||||
else:
|
||||
return "TUI"
|
||||
|
||||
def determine_local_build_type_offline(self):
|
||||
if (Path(self.constants.payload_path) / f"12-Monterey.zip").exists():
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def determine_remote_type(self, remote_name):
|
||||
if "TUI" in remote_name:
|
||||
return "TUI"
|
||||
elif "GUI" in remote_name:
|
||||
return "GUI"
|
||||
else:
|
||||
return "Unknown"
|
||||
|
||||
def determine_remote_offline_type(self, remote_name):
|
||||
if "Offline" in remote_name:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def check_binary_updates(self):
|
||||
# print("- Checking for updates...")
|
||||
if self.verify_network_connection(self.binary_url):
|
||||
# print("- Network connection functional")
|
||||
response = requests.get(self.binary_url)
|
||||
data_set = response.json()
|
||||
# print("- Retrived latest version data")
|
||||
self.remote_version = data_set["tag_name"]
|
||||
# print(f"- Latest version: {self.remote_version}")
|
||||
self.remote_version_array = self.remote_version.split(".")
|
||||
self.remote_version_array = [
|
||||
int(x) for x in self.remote_version_array
|
||||
]
|
||||
if self.check_if_build_newer() is True:
|
||||
# print("- Remote version is newer")
|
||||
for asset in data_set["assets"]:
|
||||
print(f"- Found asset: {asset['name']}")
|
||||
if self.determine_remote_type(
|
||||
asset["name"]) == self.determine_local_build_type(
|
||||
) and self.determine_remote_offline_type(
|
||||
asset["name"]
|
||||
) == self.determine_local_build_type_offline():
|
||||
# print(f"- Found matching asset: {asset['name']}")
|
||||
self.available_binaries.update({
|
||||
asset['name']: {
|
||||
"Name":
|
||||
asset["name"],
|
||||
"Version":
|
||||
self.remote_version,
|
||||
"Link":
|
||||
asset["browser_download_url"],
|
||||
"Type":
|
||||
self.determine_remote_type(asset["name"]),
|
||||
"Offline":
|
||||
self.determine_remote_offline_type(
|
||||
asset["name"]),
|
||||
"Github Link":
|
||||
f"https://github.com/dortania/OpenCore-Legacy-Patcher/releases/{self.remote_version}"
|
||||
}
|
||||
})
|
||||
break
|
||||
if self.available_binaries:
|
||||
return self.available_binaries
|
||||
else:
|
||||
# print("- No matching binaries available")
|
||||
return None
|
||||
# else:
|
||||
# print("- Failed to connect to GitHub API")
|
||||
return None
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2020-2021, Dhinak G
|
||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymaluk
|
||||
from __future__ import print_function
|
||||
|
||||
import hashlib
|
||||
@@ -312,22 +312,31 @@ def verify_network_connection(url):
|
||||
except (requests.exceptions.Timeout, requests.exceptions.TooManyRedirects, requests.exceptions.ConnectionError, requests.exceptions.HTTPError):
|
||||
return False
|
||||
|
||||
def download_file(link, location):
|
||||
def download_file(link, location, is_gui=None):
|
||||
if verify_network_connection(link):
|
||||
short_link = os.path.basename(link)
|
||||
if Path(location).exists():
|
||||
Path(location).unlink()
|
||||
header = requests.head(link).headers
|
||||
try:
|
||||
# Try to get true file
|
||||
# ex. Github's release links provides a "fake" header
|
||||
# Thus need to resolve to the real link
|
||||
link = requests.head(link).headers["location"]
|
||||
header = requests.head(link).headers
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
# Handle cases where Content-Length has garbage or is missing
|
||||
total_file_size = int(requests.head(link).headers['Content-Length'])
|
||||
except KeyError:
|
||||
total_file_size = 0
|
||||
if total_file_size != 0:
|
||||
if total_file_size > 1024:
|
||||
file_size_rounded = round(total_file_size / 1024 / 1024, 2)
|
||||
file_size_string = f" of {file_size_rounded}MB"
|
||||
else:
|
||||
file_size_string = ""
|
||||
response = requests.get(link, stream=True)
|
||||
short_link = os.path.basename(link)
|
||||
# SU Catalog's link is quite long, strip to make it bearable
|
||||
if "sucatalog.gz" in short_link:
|
||||
short_link = "sucatalog.gz"
|
||||
@@ -343,15 +352,15 @@ def download_file(link, location):
|
||||
dl += len(chunk)
|
||||
file.write(chunk)
|
||||
count += len(chunk)
|
||||
cls()
|
||||
print(box_string)
|
||||
print(header)
|
||||
print(box_string)
|
||||
print("")
|
||||
if total_file_size != 0:
|
||||
if is_gui is None:
|
||||
cls()
|
||||
print(box_string)
|
||||
print(header)
|
||||
print(box_string)
|
||||
print("")
|
||||
if total_file_size > 1024:
|
||||
total_downloaded_string = f" ({round(float(dl / total_file_size * 100), 2)}%)"
|
||||
print(f"{round(count / 1024 / 1024, 2)}MB Downloaded{file_size_string}{total_downloaded_string}")
|
||||
print(f"Average Download Speed: {round(dl//(time.perf_counter() - start) / 100000 / 8, 2)} MB/s")
|
||||
print(f"{round(count / 1024 / 1024, 2)}MB Downloaded{file_size_string}{total_downloaded_string}\nAverage Download Speed: {round(dl//(time.perf_counter() - start) / 100000 / 8, 2)} MB/s")
|
||||
checksum = hashlib.sha256()
|
||||
with location.open("rb") as file:
|
||||
chunk = file.read(1024 * 1024 * 16)
|
||||
@@ -373,7 +382,16 @@ def download_file(link, location):
|
||||
print(f"https://github.com/dortania/OpenCore-Legacy-Patcher/releases/download/{constants.Constants().patcher_version}/OpenCore-Patcher-TUI-Offline.app.zip")
|
||||
else:
|
||||
print(link)
|
||||
sys.exit()
|
||||
return None
|
||||
|
||||
def monitor_disk_output(disk):
|
||||
# Returns MB written on drive
|
||||
output = subprocess.check_output(["iostat", "-Id", disk])
|
||||
output = output.decode("utf-8")
|
||||
# Grab second last entry (last is \n)
|
||||
output = output.split(" ")
|
||||
output = output[-2]
|
||||
return output
|
||||
|
||||
def elevated(*args, **kwargs) -> subprocess.CompletedProcess:
|
||||
# When runnign through our GUI, we run as root, however we do not get uid 0
|
||||
|
||||
@@ -13,6 +13,7 @@ def validate(settings):
|
||||
example_data.iMac.iMac81_Stock,
|
||||
example_data.iMac.iMac112_Stock,
|
||||
example_data.iMac.iMac122_Upgraded,
|
||||
example_data.iMac.iMac151_Stock,
|
||||
example_data.MacPro.MacPro31_Stock,
|
||||
example_data.MacPro.MacPro31_Upgrade,
|
||||
example_data.MacPro.MacPro31_Modern_AMD,
|
||||
|
||||