Compare commits

...

132 Commits
1.2.1 ... 1.5.0

Author SHA1 Message Date
Mykola Grymalyuk
a8ecd1c153 Sync CHANGELOG 2024-05-31 10:46:19 -06:00
Mykola Grymalyuk
2dd2569931 PkgBackground: Sync Affinity Design asset file 2024-05-31 10:46:13 -06:00
Mykola Grymalyuk
86e88bf70c Merge pull request #1134 from dortania/sanity-checks
sys_patch: Implement sanity checks
2024-05-31 10:43:03 -06:00
Dhinak G
6daa038705 sys_patch.py: Fix last 2024-05-31 12:21:56 -04:00
Dhinak G
0e6576ac3d sys_patch.py: Run sanity checks before starting patching 2024-05-31 11:46:31 -04:00
Mykola Grymalyuk
074d56eed3 utilities.py: Use full binary path 2024-05-31 08:49:14 -06:00
Mykola Grymalyuk
e086d0aec1 Publish internal installer backup tooling
Published for reference, not intended for end users
2024-05-30 20:07:33 -06:00
Mykola Grymalyuk
61524c764c Set executable bit on tooling 2024-05-30 20:03:02 -06:00
Mykola Grymalyuk
8f0e8d6928 application_entry.py: Add handling for when CWD disappears 2024-05-30 20:02:51 -06:00
Mykola Grymalyuk
b62eb7e684 Tooling: Fetch assets implictly 2024-05-28 18:58:07 -06:00
Mykola Grymalyuk
18d66c66bb gui_entry.py: Add missing import 2024-05-28 18:53:50 -06:00
Mykola Grymalyuk
b27e349952 Add Privileged Helper Tool Documentation 2024-05-28 12:59:49 -06:00
Mykola Grymalyuk
fdfc86e0d6 sys_patch: Avoid relaunching OCLP 2024-05-28 12:23:33 -06:00
Mykola Grymalyuk
3d8d97f400 Merge pull request #1133 from dortania/pkg-support
Implement Package and Privileged Helper Tool support
2024-05-27 17:51:41 -06:00
Mykola Grymalyuk
32e26a10c4 AutoPkg: Fix settings file permission 2024-05-27 17:49:17 -06:00
Mykola Grymalyuk
d613581faa wx_gui: Destroy frame on root patching 2024-05-27 17:27:58 -06:00
Mykola Grymalyuk
c645f57572 Remove legacy _fix_file_permission()
Required for when OCLP would run as root
2024-05-27 17:15:00 -06:00
Mykola Grymalyuk
8fb2ee4b83 Remove stop gap “supports_privileged_helper()” code
Intended to handle transition better, now that it’s complete the code is no longer required
2024-05-27 17:11:28 -06:00
Mykola Grymalyuk
1e650637eb sys_patch: Remove legacy shim code 2024-05-27 15:48:43 -06:00
Mykola Grymalyuk
9be685e358 Shim: update centering logic 2024-05-27 14:58:27 -06:00
Mykola Grymalyuk
3dc0c46986 Packaging: Resolve AutoPkg not setting S-bit 2024-05-27 14:52:51 -06:00
Mykola Grymalyuk
9428040f64 Tooling: Switch AutoPkg generation to macOS-Pkg-Builder 2024-05-27 13:25:51 -06:00
Mykola Grymalyuk
ec9ecbc7a9 Shim: Switch to old spawn logic 2024-05-27 12:13:26 -06:00
Mykola Grymalyuk
303d3de6bd GUI: Remove relaunch logic 2024-05-27 12:13:09 -06:00
Mykola Grymalyuk
e8efa89899 PKG: Add Affinity file
Source for PKG background images
2024-05-27 11:36:28 -06:00
Mykola Grymalyuk
b0def277ea updates.py: Add support for PKG updates 2024-05-27 11:29:04 -06:00
Mykola Grymalyuk
acbeef070f Remove alias creation
Now handled by PKG
2024-05-27 11:04:14 -06:00
Mykola Grymalyuk
e3eb90b7fb Shim: Switch to “/usr/bin/open” 2024-05-27 10:55:02 -06:00
Mykola Grymalyuk
c5dae2c61f Publish CFBundleVersion 2024-05-27 10:54:54 -06:00
Mykola Grymalyuk
fdddb8378c PHT: remove entitlements 2024-05-27 10:48:46 -06:00
Mykola Grymalyuk
8aed4e02a6 Shim: Add entitlements 2024-05-27 10:21:48 -06:00
Mykola Grymalyuk
2a6c3efa99 Build: Sign PHT 2024-05-27 10:19:53 -06:00
Mykola Grymalyuk
b3fe52b02b Shim: Better match original app 2024-05-27 09:51:15 -06:00
Mykola Grymalyuk
41be3ffb55 Build: Set versioning in update shim 2024-05-27 09:34:52 -06:00
Mykola Grymalyuk
9db11c3a8c Tooling: Rename build script 2024-05-27 07:32:57 -06:00
Mykola Grymalyuk
ea96c2c4ad shim: Add setpgid usage 2024-05-26 20:58:20 -06:00
Mykola Grymalyuk
0202f4e1fb Update Shim: Adjust app icon 2024-05-26 20:21:04 -06:00
Mykola Grymalyuk
796c2207a0 CI: Fix missing '--run-as-individual-steps' parameter 2024-05-26 19:52:04 -06:00
Mykola Grymalyuk
1469601570 CI: Modularize steps 2024-05-26 19:45:22 -06:00
Mykola Grymalyuk
7d686a29cf Implement update shim 2024-05-26 19:21:49 -06:00
Mykola Grymalyuk
b6346137f3 PKG Scripts: Add PackageKit parameters 2024-05-22 20:53:25 -06:00
Mykola Grymalyuk
e2dabfcc16 Scripts: Handle output escapes in El Capitan 2024-05-21 21:12:06 -06:00
Mykola Grymalyuk
0ef817566e CI: Add Uninstall PKG 2024-05-21 19:36:33 -06:00
Mykola Grymalyuk
af44dcef8e CI: Add Package Signing support 2024-05-21 13:44:53 -06:00
Mykola Grymalyuk
dd96889f66 CI: Upload PKG 2024-05-21 11:06:42 -06:00
Mykola Grymalyuk
811344261e CI: Adjust formatting 2024-05-21 10:58:52 -06:00
Mykola Grymalyuk
e8233c3691 CI: Add PKG building support 2024-05-21 10:42:11 -06:00
Mykola Grymalyuk
952ac0de8c Privileged Helper: Match directory casing 2024-05-20 18:58:14 -06:00
Mykola Grymalyuk
984eb67596 macos_installer_handler.py: Add support for Privileged Helper 2024-05-20 18:52:49 -06:00
Mykola Grymalyuk
45651a9aec Privileged Helper: Move to CI tooling directory
Moved as otherwise would be bundled in payloads.dmg, adding unnessesary space
2024-05-20 18:50:27 -06:00
Mykola Grymalyuk
e91c76e88e sys_patch_mount.py: Fix mount variable invocation 2024-05-20 13:40:44 -06:00
Mykola Grymalyuk
ef68b43fc3 PrivilegedHelperTool: Publish notarized binary 2024-05-20 13:06:15 -06:00
Mykola Grymalyuk
d6fbb2cf19 PrivilegedHelperTool: Fix Team ID verification 2024-05-20 13:05:50 -06:00
Mykola Grymalyuk
fde7d6f7ec firmware.py: Disable OpenLegacyBoot.efi 2024-05-20 11:38:03 -06:00
Mykola Grymalyuk
bac61f2dfa Sync OpenCorePkg 2024-05-20 11:32:38 -06:00
Mykola Grymalyuk
3906b80a68 PrivilegedHelperTool: Add source
Note: Currently not in use
2024-05-20 11:22:58 -06:00
Mykola Grymalyuk
f7bcb26b10 AutoPkg: Modularize pre/postinstall scripts 2024-05-14 21:16:25 -06:00
Mykola Grymalyuk
23146d731a sys_patch_mount.py: Fix comment and missing return statement 2024-05-13 17:55:37 -06:00
Mykola Grymalyuk
7f7acc4c9a Add backend support for Apple Silicon root patching 2024-05-10 17:44:09 -06:00
Mykola Grymalyuk
b494107d88 sys_patch_helpers.py: Remove unused import 2024-05-10 16:42:03 -06:00
Mykola Grymalyuk
abb18a5ad2 subprocess_wrapper.py: Add unified error handling
Additionally adds backend support for Privileged Helper Tool
2024-05-10 16:06:16 -06:00
Mykola Grymalyuk
84e020f7ea sys_patch.py: Enforce full pathing for subprocess 2024-05-10 14:15:42 -06:00
Mykola Grymalyuk
065b73daab sys_patch_auto.py: Enforce full pathing for subprocess 2024-05-10 14:07:15 -06:00
Mykola Grymalyuk
c456274446 kdk_handler.py: Enforce full pathing for subprocess 2024-05-10 14:04:51 -06:00
Mykola Grymalyuk
2fe8f4f4c8 sys_patch_dict.py: Enforce full pathing for processes 2024-05-10 14:01:33 -06:00
Mykola Grymalyuk
4e8805ddd7 macos_install_handler.py: Add macOS 15 variant support to backend 2024-05-10 08:47:22 -06:00
Mykola Grymalyuk
ddb71e6776 macos_installer_handler.py: Add signature check 2024-04-30 16:58:40 -06:00
Mykola Grymalyuk
a06b1f578e sys_patch.py: Resolve LE cleaning on Web Drivers
Thanks @midi1996 for catching
2024-04-03 15:48:58 -06:00
neon ball
e53ced5b8e Merge pull request #1131 from crystall1nedev/patch-2
Add missing MacBook Pro models to the supported list
2024-04-03 18:06:17 +03:00
Eva Isabella Luna
59b5ccf07e Add missing MacBook Pro x2 2024-04-03 10:56:07 -04:00
Eva Isabella Luna
eddc9e6ffd Add missing MacBook Pro model 2024-04-03 10:52:14 -04:00
neon ball
19c35f05e5 Merge pull request #1130 from crystall1nedev/fix-troubleshooting
Fix root patch troubleshooting docs
2024-04-02 22:16:28 +03:00
Eva Isabella Luna
9adbb5ae09 Note about FV2 2024-04-02 15:06:32 -04:00
Eva Isabella Luna
cf32b7a989 Fix an error deleting /L/E 2024-04-02 14:59:59 -04:00
Mykola Grymalyuk
c19c6aa575 Adjust type hinting 2024-04-01 19:50:28 -06:00
Mykola Grymalyuk
5e2278860d Merge pull request #1129 from dortania/package-restructuring
Restructure Python project into package format
2024-04-01 11:45:30 -06:00
Mykola Grymalyuk
f97096945b Sync CHANGELOG 2024-04-01 11:41:04 -06:00
Mykola Grymalyuk
6caabf9726 Organize Drive Icons 2024-04-01 11:36:25 -06:00
Mykola Grymalyuk
83fec2952e Move utilities directory to support 2024-04-01 11:15:34 -06:00
Mykola Grymalyuk
10da04ca3e Images: Move into docs directory 2024-04-01 09:44:18 -06:00
Mykola Grymalyuk
d464c80305 AutoPkg: Adjust relative path 2024-03-31 21:32:26 -06:00
Mykola Grymalyuk
463bed4e06 Restructure into package format 2024-03-31 21:27:36 -06:00
Mykola Grymalyuk
d02d89b9c0 Increment build 2024-03-31 15:59:50 -06:00
Mykola Grymalyuk
ae8d6923d7 CI: Upgrade actions/setup-node to v4 2024-03-31 15:34:16 -06:00
Mykola Grymalyuk
b7e76c2a4d CI: Upgrade actions/upload-artifact to v4 2024-03-31 15:34:00 -06:00
Mykola Grymalyuk
dd425d2c1e CI: Upgrade actions/checkout to v4 2024-03-31 15:22:49 -06:00
Mykola Grymalyuk
31e4d8d3f1 CI: Use full path for packagesbuild 2024-03-31 15:18:27 -06:00
Eduardo Covas
bbc8902270 Add non-Metal support for macOS 14.4 2024-03-18 09:50:25 -03:00
Dhinak G
520c922429 Fix last 2024-03-15 22:16:35 -04:00
Dhinak G
9c2da4e4fb Update "Stock GPUs" handling
closes #1128
2024-03-15 19:18:33 -04:00
Mykola Grymalyuk
4c4b202bcc Merge pull request #1127 from dortania/fix-apple-logo-oversight
Add SkipLogo patch for Macs natively supporting Monterey or newer
2024-03-13 09:44:58 -06:00
Jazzzny
8509746a49 Add Macmini7,1 to exclude list 2024-03-12 19:20:46 -04:00
Jazzzny
59beb64d17 Remove redundant check 2024-03-12 19:12:04 -04:00
Jazzzny
1713bfe6c3 Add SkipLogo patch 2024-03-12 19:04:54 -04:00
Mykola Grymalyuk
28f7f603b7 Sync OpenCorePkg 2024-03-12 07:50:06 -06:00
Mykola Grymalyuk
5a0c7679f7 Increment build 2024-03-12 07:47:53 -06:00
Mykola Grymalyuk
e494906f22 sys_patch_dict.py: Fix comparison 2024-03-10 17:06:07 -06:00
Mykola Grymalyuk
cdb40d8201 Sync PatcherSupportPkg 2024-03-10 14:14:38 -06:00
neon ball
b42eb6e395 Small fix 2024-03-10 21:10:10 +02:00
neon ball
20bb0cd6d8 Fix typos and stuff 2024-03-10 21:07:51 +02:00
Mykola Grymalyuk
c6688ea922 Increment build 2024-03-10 12:01:23 -06:00
neon ball
0e490e5ae9 Switch kext removal command
Command cleans /Library/Extensions with a one shot instead of having to do it one by one per kext.
2024-03-08 20:18:59 +02:00
Mykola Grymalyuk
e58a671136 bluetooth.py: Fix GUID and delete variables 2024-03-07 17:57:11 -07:00
Mykola Grymalyuk
5d142fd19f bluetooth.py: Publish Controller and Dongle NVRAM variables 2024-03-07 17:28:30 -07:00
Mykola Grymalyuk
f55598dac8 misc.py: Resolve SPI support for MacBookAir6,x 2024-03-07 17:00:52 -07:00
Mykola Grymalyuk
321cc8dd68 Increment build 2024-03-07 14:27:56 -07:00
Jazzzny
9070f5af8d Update implementation for updater (#1126)
* Update implementation for updater

* Update changelog
2024-03-07 16:16:53 -05:00
Mykola Grymalyuk
a8c080042a misc.py: Adjust AppleHSSPI model range 2024-02-20 13:13:21 -07:00
Eduardo Covas
5788e067b3 Resolve 14.4 T1 support 2024-02-13 11:41:23 -03:00
Mykola Grymalyuk
90d7e9715d Sync CHANGELOG 2024-02-11 19:59:03 -07:00
Mykola Grymalyuk
f8a3d5716c Add support for macOS 14.4 2024-02-11 14:23:05 -07:00
Mykola Grymalyuk
82084c84e3 validation.py: Add optional support for checking unused PatcherSupportPkg files 2024-02-11 13:58:37 -07:00
Mykola Grymalyuk
f29c629165 misc.py: Add SPI top case patches 2024-01-30 16:14:09 -07:00
Dhinak G
54b3e17d93 kdk_handler.py: Fix KDK matching
Use sort order from API
2024-01-18 21:22:07 -05:00
Mykola Grymalyuk
2bc843dd2f Adjust copyright label 2024-01-01 11:00:08 -07:00
Dhinak G
55eeec790f Docs: Drop security point on homepage
With Sonoma everything needs patches.
2023-12-31 17:23:28 -05:00
Mykola Grymalyuk
8db6c5607d Sync OpenCorePkg 2023-12-30 19:12:58 -07:00
Mykola Grymalyuk
2df8dc9caf Merge pull request #1121 from dortania/subprocess-cleanup
Refactor subprocess usage
2023-12-30 14:13:39 -07:00
Mykola Grymalyuk
99f48b1e87 Sync CHANGELOG 2023-12-30 14:13:23 -07:00
Mykola Grymalyuk
0dfcf03c0c Use full path and arguments for subprocess 2023-12-30 13:49:59 -07:00
Mykola Grymalyuk
b46e55d3f6 Clean up macserial invocation 2023-12-30 13:14:47 -07:00
Mykola Grymalyuk
62fd543623 Avoid .split() usage for subprocess 2023-12-30 13:14:20 -07:00
Mykola Grymalyuk
ec46221c30 Build-Binary.command: Remove unused import 2023-12-30 12:46:35 -07:00
Mykola Grymalyuk
e57247a233 OpenCore-Patcher-GUI.spec: Add type hinting for PyInstaller classes 2023-12-30 12:44:28 -07:00
Mykola Grymalyuk
6aa0ab2161 Increment build 2023-12-30 12:32:43 -07:00
Mykola Grymalyuk
f1210def89 sys_patch: Expand 32023 patching for 14.2 Beta 2+ 2023-11-26 13:03:18 -07:00
Mykola Grymalyuk
03842d4e77 paylods: Resolve malformed CFBundleExecutable property 2023-11-26 11:11:41 -07:00
Mykola Grymalyuk
34676702f4 Merge pull request #1119 from fricklerhandwerk/fix-typos
fricklerhandwerk: fix typos
2023-11-18 11:00:58 -07:00
fricklerhandwerk
352d917a7d fix typos 2023-11-16 19:21:49 +01:00
Mykola Grymalyuk
f1b47f6a78 Increment build 2023-11-10 18:43:21 -07:00
neon ball
15d58966f6 Update DONATE.md 2023-11-10 22:24:26 +02:00
neon ball
49cb9ccb66 Reword DONATE.md 2023-11-10 19:45:10 +02:00
249 changed files with 17313 additions and 8689 deletions

View File

@@ -13,57 +13,110 @@ jobs:
if: github.repository_owner == 'dortania'
env:
# GitHub Information
branch: ${{ github.ref }}
commiturl: ${{ github.event.head_commit.url }}${{ github.event.release.html_url }}
commitdate: ${{ github.event.head_commit.timestamp }}${{ github.event.release.published_at }}
MAC_CODESIGN_IDENTITY: ${{ secrets.MAC_CODESIGN_IDENTITY }}
MAC_CODESIGN_CERT: ${{ secrets.MAC_CODESIGN_CERT }}
MAC_NOTARIZATION_USERNAME: ${{ secrets.MAC_NOTARIZATION_USERNAME }}
MAC_NOTARIZATION_PASSWORD: ${{ secrets.MAC_NOTARIZATION_PASSWORD }}
MAC_NOTARIZATION_TEAM_ID: ${{ secrets.MAC_NOTARIZATION_TEAM_ID }}
# Analytics
ANALYTICS_KEY: ${{ secrets.ANALYTICS_KEY }}
ANALYTICS_SITE: ${{ secrets.ANALYTICS_SITE }}
# App Signing
ORG_MAC_DEVELOPER_ID_APPLICATION_IDENTITY: ${{ secrets.ORG_MAC_DEVELOPER_ID_APPLICATION_IDENTITY }}
# PKG Signing
ORG_MAC_DEVELOPER_ID_INSTALLER_IDENTITY: ${{ secrets.ORG_MAC_DEVELOPER_ID_INSTALLER_IDENTITY }}
# Notarization
ORG_MAC_NOTARIZATION_TEAM_ID: ${{ secrets.ORG_MAC_NOTARIZATION_TEAM_ID }}
ORG_MAC_NOTARIZATION_APPLE_ID: ${{ secrets.ORG_MAC_NOTARIZATION_APPLE_ID }}
ORG_MAC_NOTARIZATION_PASSWORD: ${{ secrets.ORG_MAC_NOTARIZATION_PASSWORD }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Build Binary
run: /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 Build-Binary.command --reset_binaries --branch "${{ env.branch }}" --commit "${{ env.commiturl }}" --commit_date "${{ env.commitdate }}" --key "${{ env.ANALYTICS_KEY }}" --site "${{ env.ANALYTICS_SITE }}"
# - name: Import Certificate
# if: (!security find-certificate -c "${{ env.MAC_CODESIGN_IDENTITY }}")
# uses: apple-actions/import-codesign-certs@v2
# - name: Import Application Signing Certificate
# uses: dhinakg/import-codesign-certs@master
# with:
# p12-file-base64: ${{ secrets.MAC_CODESIGN_CERT }}
# p12-password: ${{ secrets.MAC_NOTARIZATION_PASSWORD }}
# p12-file-base64: ${{ secrets.ORG_MAC_DEVELOPER_ID_APPLICATION_CERT_P12_BASE64 }}
# p12-password: ${{ secrets.ORG_MAC_DEVELOPER_ID_APPLICATION_CERT_P12_PASSWORD }}
- name: Codesign Binary
run: 'codesign -s "${{ env.MAC_CODESIGN_IDENTITY }}" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"'
# - name: Import Installer Signing Certificate
# uses: dhinakg/import-codesign-certs@master
# with:
# p12-file-base64: ${{ secrets.ORG_MAC_DEVELOPER_ID_INSTALLER_CERT_P12_BASE64 }}
# p12-password: ${{ secrets.ORG_MAC_DEVELOPER_ID_INSTALLER_CERT_P12_PASSWORD }}
- name: Package Binary
run: cd dist; ditto -c -k --sequesterRsrc --keepParent OpenCore-Patcher.app ../OpenCore-Patcher-wxPython.app.zip
# - name: Install Dependencies
# run: /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 -m pip install -r requirements.txt
- name: Notarize Binary
run: xcrun notarytool submit OpenCore-Patcher-wxPython.app.zip --apple-id "${{ env.MAC_NOTARIZATION_USERNAME }}" --password "${{ env.MAC_NOTARIZATION_PASSWORD }}" --team-id "${{ env.MAC_NOTARIZATION_TEAM_ID }}"
# - name: Force Universal2 charset for Python
# run: |
# /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 -m pip uninstall -y charset_normalizer
# /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 -m pip download --platform macosx_10_9_universal2 --only-binary=:all: charset-normalizer
# /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 -m pip install charset_normalizer-*-macosx_10_9_universal2.whl
- name: Generate support package
run: packagesbuild ./payloads/InstallPackage/AutoPkg-Assets-Setup.pkgproj
- name: Prepare Assets (--prepare-assets)
run: >
/Library/Frameworks/Python.framework/Versions/3.11/bin/python3 Build-Project.command
--run-as-individual-steps --reset-dmg-cache
--prepare-assets
- name: Prepare Application (--prepare-application)
run: >
/Library/Frameworks/Python.framework/Versions/3.11/bin/python3 Build-Project.command
--application-signing-identity "${{ env.ORG_MAC_DEVELOPER_ID_APPLICATION_IDENTITY }}"
--notarization-apple-id "${{ env.ORG_MAC_NOTARIZATION_APPLE_ID }}" --notarization-password "${{ env.ORG_MAC_NOTARIZATION_PASSWORD }}" --notarization-team-id "${{ env.ORG_MAC_NOTARIZATION_TEAM_ID }}"
--git-branch "${{ env.branch }}" --git-commit-url "${{ env.commiturl }}" --git-commit-date "${{ env.commitdate }}"
--analytics-key "${{ env.ANALYTICS_KEY }}" --analytics-endpoint "${{ env.ANALYTICS_SITE }}"
--reset-pyinstaller-cache
--run-as-individual-steps
--prepare-application
- name: Prepare Package (--prepare-package)
run: >
/Library/Frameworks/Python.framework/Versions/3.11/bin/python3 Build-Project.command
--installer-signing-identity "${{ env.ORG_MAC_DEVELOPER_ID_INSTALLER_IDENTITY }}"
--notarization-apple-id "${{ env.ORG_MAC_NOTARIZATION_APPLE_ID }}" --notarization-password "${{ env.ORG_MAC_NOTARIZATION_PASSWORD }}" --notarization-team-id "${{ env.ORG_MAC_NOTARIZATION_TEAM_ID }}"
--run-as-individual-steps
--prepare-package
- name: Prepare Update Shim (--prepare-shim)
run: >
/Library/Frameworks/Python.framework/Versions/3.11/bin/python3 Build-Project.command
--application-signing-identity "${{ env.ORG_MAC_DEVELOPER_ID_APPLICATION_IDENTITY }}"
--notarization-apple-id "${{ env.ORG_MAC_NOTARIZATION_APPLE_ID }}" --notarization-password "${{ env.ORG_MAC_NOTARIZATION_PASSWORD }}" --notarization-team-id "${{ env.ORG_MAC_NOTARIZATION_TEAM_ID }}"
--run-as-individual-steps
--prepare-shim
- name: Prepare App for Upload
run: mv ./OpenCore-Patcher-wxPython.app.zip ./OpenCore-Patcher-GUI.app.zip
run: /bin/mv ./dist/OpenCore-Patcher.app.zip ./OpenCore-Patcher-GUI.app.zip
- name: Upload App to Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: OpenCore-Patcher.app (GUI)
path: OpenCore-Patcher-GUI.app.zip
- name: Upload Package to Artifacts
uses: actions/upload-artifact@v3
- name: Upload AutoPkg Package to Artifacts
uses: actions/upload-artifact@v4
with:
name: AutoPkg-Assets.pkg
path: ./dist/AutoPkg-Assets.pkg
- name: Upload Installation Package to Artifacts
uses: actions/upload-artifact@v4
with:
name: OpenCore-Patcher.pkg
path: ./dist/OpenCore-Patcher.pkg
- name: Upload Uninstaller Package to Artifacts
uses: actions/upload-artifact@v4
with:
name: OpenCore-Patcher-Uninstaller.pkg
path: ./dist/OpenCore-Patcher-Uninstaller.pkg
- name: Upload Binary to Release
if: github.event_name == 'release'
uses: svenstaro/upload-release-action@e74ff71f7d8a4c4745b560a485cc5fdb9b5b999d
@@ -73,11 +126,29 @@ jobs:
tag: ${{ github.ref }}
file_glob: true
- name: Upload Package to Release
- name: Upload AutoPkg Package to Release
if: github.event_name == 'release'
uses: svenstaro/upload-release-action@e74ff71f7d8a4c4745b560a485cc5fdb9b5b999d
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./dist/AutoPkg-Assets.pkg
tag: ${{ github.ref }}
file_glob: true
- name: Upload Installation Package to Release
if: github.event_name == 'release'
uses: svenstaro/upload-release-action@e74ff71f7d8a4c4745b560a485cc5fdb9b5b999d
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./dist/OpenCore-Patcher.pkg
tag: ${{ github.ref }}
file_glob: true
- name: Upload Uninstaller Package to Release
if: github.event_name == 'release'
uses: svenstaro/upload-release-action@e74ff71f7d8a4c4745b560a485cc5fdb9b5b999d
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./dist/OpenCore-Patcher-Uninstaller.pkg
tag: ${{ github.ref }}
file_glob: true

View File

@@ -11,11 +11,11 @@ jobs:
runs-on: ubuntu-latest
if: github.repository_owner == 'dortania'
steps:
- uses: actions/setup-node@v3
- uses: actions/setup-node@v4
with:
node-version: '12'
- name: Checkout Repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: '0'
persist-credentials: false

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: macos-latest
if: github.repository_owner != 'dortania'
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Python
uses: actions/setup-python@v2
with:

View File

@@ -12,6 +12,6 @@ jobs:
runs-on: x86_64_monterey
if: github.repository_owner == 'dortania'
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Validate
run: /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 OpenCore-Patcher-GUI.command --validate

1
.gitignore vendored
View File

@@ -39,3 +39,4 @@ __pycache__/
/payloads/update.sh
/payloads/OpenCore-Patcher.app
/.x86_64_venv
*afdesign~lock~

View File

@@ -1,440 +0,0 @@
#!/usr/bin/env python3
# Generate stand alone application for OpenCore-Patcher
# Copyright (C) 2022-2023 - Mykola Grymalyuk
import os
import sys
import time
import argparse
import plistlib
import platform
import subprocess
from pathlib import Path
from resources import constants
class CreateBinary:
"""
Library for creating OpenCore-Patcher application
This script's main purpose is to handle the following:
- Download external dependencies (ex. PatcherSupportPkg)
- Convert payloads directory into DMG
- Build Binary via Pyinstaller
- Patch 'LC_VERSION_MIN_MACOSX' to OS X 10.10
- Add commit data to Info.plist
"""
def __init__(self):
start = time.time()
self._set_cwd()
print("Starting build script")
self.args = self._parse_arguments()
print(f"Current Working Directory:\n- {os.getcwd()}")
self._preflight_processes()
self._build_binary()
self._postflight_processes()
print(f"Build script completed in {str(round(time.time() - start, 2))} seconds")
def _set_cwd(self):
"""
Initialize current working directory to parent of this script
"""
os.chdir(Path(__file__).resolve().parent)
def _parse_arguments(self):
"""
Parse arguments passed to script
"""
parser = argparse.ArgumentParser(description='Builds OpenCore-Patcher binary')
parser.add_argument('--branch', type=str, help='Git branch name')
parser.add_argument('--commit', type=str, help='Git commit URL')
parser.add_argument('--commit_date', type=str, help='Git commit date')
parser.add_argument('--reset_binaries', action='store_true', help='Force redownload and imaging of payloads')
parser.add_argument('--key', type=str, help='Developer key for signing')
parser.add_argument('--site', type=str, help='Path to server')
args = parser.parse_args()
return args
def _setup_pathing(self):
"""
Initialize pathing for pyinstaller
"""
python_path = sys.executable
python_binary = python_path.split("/")[-1]
python_bin_dir = python_path.strip(python_binary)
# macOS (using Python installed by homebrew (e.g. brew))
if f"/usr/local/opt/python@3." in sys.executable:
print(f"\t* NOTE: home(brew) python3 detected; using (sys.exec_prefix, python_path) ==> {sys.exec_prefix, python_path}")
# - under brew, pip3 will install pyinstaller at:
# /usr/local/lib/python3.9/site-packages/pyinstaller
# and /usr/local/bin/pyinstaller stub to load and run.
pyinstaller_path = f"/usr/local/bin/pyinstaller"
else:
pyinstaller_path = f"{python_bin_dir}pyinstaller"
if not Path(pyinstaller_path).exists():
print(f"- pyinstaller not found:\n\t{pyinstaller_path}")
raise Exception("pyinstaller not found")
self.pyinstaller_path = pyinstaller_path
def _preflight_processes(self):
"""
Start preflight processes
"""
print("Starting preflight processes")
self._setup_pathing()
self._delete_extra_binaries()
self._download_resources()
self._generate_payloads_dmg()
def _postflight_processes(self):
"""
Start postflight processes
"""
print("Starting postflight processes")
self._patch_load_command()
self._add_commit_data()
self._post_flight_cleanup()
self._mini_validate()
def _build_binary(self):
"""
Build binary via pyinstaller
"""
if Path(f"./dist/OpenCore-Patcher.app").exists():
print("Found OpenCore-Patcher.app, removing...")
rm_output = subprocess.run(
["rm", "-rf", "./dist/OpenCore-Patcher.app"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
if rm_output.returncode != 0:
print("Remove failed")
print(rm_output.stderr.decode('utf-8'))
raise Exception("Remove failed")
self._embed_key()
print("Building GUI binary...")
build_args = [self.pyinstaller_path, "./OpenCore-Patcher-GUI.spec", "--noconfirm"]
build_result = subprocess.run(build_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self._strip_key()
if build_result.returncode != 0:
print("Build failed")
print(build_result.stderr.decode('utf-8'))
raise Exception("Build failed")
# Next embed support icns into ./Resources
print("Embedding icns...")
for file in Path("payloads/Icon/AppIcons").glob("*.icns"):
subprocess.run(
["cp", str(file), "./dist/OpenCore-Patcher.app/Contents/Resources/"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
def _embed_key(self):
"""
Embed developer key into binary
"""
if not self.args.key:
print("No developer key provided, skipping...")
return
if not self.args.site:
print("No site provided, skipping...")
return
print("Embedding developer key...")
if not Path("./resources/analytics_handler.py").exists():
print("analytics_handler.py not found")
return
lines = []
with open("./resources/analytics_handler.py", "r") as f:
lines = f.readlines()
for i, line in enumerate(lines):
if line.startswith("SITE_KEY: str = "):
lines[i] = f"SITE_KEY: str = \"{self.args.key}\"\n"
elif line.startswith("ANALYTICS_SERVER: str = "):
lines[i] = f"ANALYTICS_SERVER: str = \"{self.args.site}\"\n"
with open("./resources/analytics_handler.py", "w") as f:
f.writelines(lines)
def _strip_key(self):
"""
Strip developer key from binary
"""
if not self.args.key:
print("No developer key provided, skipping...")
return
if not self.args.site:
print("No site provided, skipping...")
return
print("Stripping developer key...")
if not Path("./resources/analytics_handler.py").exists():
print("analytics_handler.py not found")
return
lines = []
with open("./resources/analytics_handler.py", "r") as f:
lines = f.readlines()
for i, line in enumerate(lines):
if line.startswith("SITE_KEY: str = "):
lines[i] = f"SITE_KEY: str = \"\"\n"
elif line.startswith("ANALYTICS_SERVER: str = "):
lines[i] = f"ANALYTICS_SERVER: str = \"\"\n"
with open("./resources/analytics_handler.py", "w") as f:
f.writelines(lines)
def _delete_extra_binaries(self):
"""
Delete extra binaries from payloads directory
"""
whitelist_folders = [
"ACPI",
"Config",
"Drivers",
"Icon",
"InstallPackage",
"Kexts",
"OpenCore",
"Tools",
"Launch Services",
]
whitelist_files = [
"entitlements.plist",
"launcher.sh",
"OC-Patcher-TUI.icns",
"OC-Patcher.icns",
]
print("Deleting extra binaries...")
for file in Path("payloads").glob(pattern="*"):
if file.is_dir():
if file.name in whitelist_folders:
continue
print(f"- Deleting {file.name}")
subprocess.run(["rm", "-rf", file])
else:
if file.name in whitelist_files:
continue
print(f"- Deleting {file.name}")
subprocess.run(["rm", "-f", file])
def _download_resources(self):
"""
Download required dependencies
"""
patcher_support_pkg_version = constants.Constants().patcher_support_pkg_version
required_resources = [
"Universal-Binaries.dmg"
]
print("Downloading required resources...")
for resource in required_resources:
if Path(f"./{resource}").exists():
if self.args.reset_binaries:
print(f" - Removing old {resource}")
# Just to be safe
assert resource, "Resource cannot be empty"
assert resource not in ("/", "."), "Resource cannot be root"
rm_output = subprocess.run(
["rm", "-rf", f"./{resource}"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
if rm_output.returncode != 0:
print("Remove failed")
print(rm_output.stderr.decode('utf-8'))
raise Exception("Remove failed")
else:
print(f"- {resource} already exists, skipping download")
continue
print(f"- Downloading {resource}...")
download_result = subprocess.run(
[
"curl", "-LO",
f"https://github.com/dortania/PatcherSupportPkg/releases/download/{patcher_support_pkg_version}/{resource}"
],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
if download_result.returncode != 0:
print("- Download failed")
print(download_result.stderr.decode('utf-8'))
raise Exception("Download failed")
if not Path(f"./{resource}").exists():
print(f"- {resource} not found")
raise Exception(f"{resource} not found")
def _generate_payloads_dmg(self):
"""
Generate disk image containing all payloads
Disk image will be password protected due to issues with
Apple's notarization system and inclusion of kernel extensions
"""
if Path("./payloads.dmg").exists():
if not self.args.reset_binaries:
print("- payloads.dmg already exists, skipping creation")
return
print("- Removing old payloads.dmg")
rm_output = subprocess.run(
["rm", "-rf", "./payloads.dmg"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
if rm_output.returncode != 0:
print("Remove failed")
print(rm_output.stderr.decode('utf-8'))
raise Exception("Remove failed")
print("- Generating DMG...")
dmg_output = subprocess.run([
'hdiutil', 'create', './payloads.dmg',
'-megabytes', '32000', # Overlays can only be as large as the disk image allows
'-format', 'UDZO', '-ov',
'-volname', 'OpenCore Patcher Resources (Base)',
'-fs', 'HFS+',
'-srcfolder', './payloads',
'-passphrase', 'password', '-encryption'
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if dmg_output.returncode != 0:
print("- DMG generation failed")
print(dmg_output.stderr.decode('utf-8'))
raise Exception("DMG generation failed")
print("- DMG generation complete")
def _add_commit_data(self):
"""
Add commit data to Info.plist
"""
if not self.args.branch and not self.args.commit and not self.args.commit_date:
print("- No commit data provided, adding source info")
branch = "Built from source"
commit_url = ""
commit_date = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
else:
branch = self.args.branch
commit_url = self.args.commit
commit_date = self.args.commit_date
print("- Adding commit data to Info.plist")
plist_path = Path("./dist/OpenCore-Patcher.app/Contents/Info.plist")
plist = plistlib.load(Path(plist_path).open("rb"))
plist["Github"] = {
"Branch": branch,
"Commit URL": commit_url,
"Commit Date": commit_date,
}
plistlib.dump(plist, Path(plist_path).open("wb"), sort_keys=True)
def _patch_load_command(self):
"""
Patch 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, 1)
with open(path, 'wb') as f:
f.write(data)
def _post_flight_cleanup(self):
"""
Post flight cleanup
"""
path = "./dist/OpenCore-Patcher"
print(f"- Removing {path}")
rm_output = subprocess.run(
["rm", "-rf", path],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
if rm_output.returncode != 0:
print(f"- Remove failed: {path}")
print(rm_output.stderr.decode('utf-8'))
raise Exception(f"Remove failed: {path}")
def _mini_validate(self):
"""
Validate generated binary
"""
print("- Validating binary")
validate_output = subprocess.run(
["./dist/OpenCore-Patcher.app/Contents/MacOS/OpenCore-Patcher", "--build", "--model", "MacPro3,1"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
if validate_output.returncode != 0:
print("- Validation failed")
print(validate_output.stderr.decode('utf-8'))
raise Exception("Validation failed")
if __name__ == "__main__":
CreateBinary()

168
Build-Project.command Executable file
View File

@@ -0,0 +1,168 @@
#!/usr/bin/env python3
"""
Build-Project.command: Generate OpenCore-Patcher.app and OpenCore-Patcher.pkg
"""
import os
import sys
import time
import argparse
import plistlib
from pathlib import Path
from ci_tooling.build_modules import (
application,
disk_images,
package,
sign_notarize,
shim
)
from opencore_legacy_patcher import constants
def main() -> None:
"""
Parse Command Line Arguments
"""
parser = argparse.ArgumentParser(description="Build OpenCore Legacy Patcher Suite", add_help=False)
# Signing Parameters
parser.add_argument("--application-signing-identity", type=str, help="Application Signing Identity")
parser.add_argument("--installer-signing-identity", type=str, help="Installer Signing Identity")
# Notarization Parameters
parser.add_argument("--notarization-apple-id", type=str, help="Notarization Apple ID", default=None)
parser.add_argument("--notarization-password", type=str, help="Notarization Password", default=None)
parser.add_argument("--notarization-team-id", type=str, help="Notarization Team ID", default=None)
# GitHub Actions CI/CD Parameters
parser.add_argument("--git-branch", type=str, help="Git Branch", default=None)
parser.add_argument("--git-commit-url", type=str, help="Git Commit URL", default=None)
parser.add_argument("--git-commit-date", type=str, help="Git Commit Date", default=None)
# Local Build Parameters
parser.add_argument("--reset-dmg-cache", action="store_true", help="Redownload PatcherSupportPkg.dmg and regenerate payloads.dmg", default=False)
parser.add_argument("--reset-pyinstaller-cache", action="store_true", help="Clean PyInstaller Cache", default=False)
# CI/CD Parameters for individual steps
# If not specified, will run all steps
parser.add_argument("--run-as-individual-steps", action="store_true", help="CI: Run as individual steps", default=False)
parser.add_argument("--prepare-application", action="store_true", help="CI: Prepare Application", default=False)
parser.add_argument("--prepare-package", action="store_true", help="CI: Prepare Package", default=False)
parser.add_argument("--prepare-assets", action="store_true", help="CI: Prepare Assets", default=False)
# CI/CD Parameters for additional steps
# If not specified, will not run additional steps
parser.add_argument("--prepare-shim", action="store_true", help="CI: Prepare Update Shim", default=False)
# Analytics Parameters
parser.add_argument("--analytics-key", type=str, help="Analytics Key", default=None)
parser.add_argument("--analytics-endpoint", type=str, help="Analytics Endpoint", default=None)
# Help
parser.add_argument("--help", action="store_true", help="Show this help message and exit", default=False)
# Parse Arguments
args = parser.parse_args()
if args.help:
parser.print_help()
print("\n\nIf running outside of CI/CD, simply run the following command:")
print("$ python3 Build-Project.command")
sys.exit(0)
# Set 'Current Working Directory' to script directory
os.chdir(Path(__file__).resolve().parent)
if (args.run_as_individual_steps is False) or (args.run_as_individual_steps and args.prepare_assets):
# Prepare workspace
disk_images.GenerateDiskImages(args.reset_dmg_cache).generate()
if (args.run_as_individual_steps is False) or (args.run_as_individual_steps and args.prepare_application):
# Prepare Privileged Helper Tool
sign_notarize.SignAndNotarize(
path=Path("./ci_tooling/privileged_helper_tool/com.dortania.opencore-legacy-patcher.privileged-helper"),
signing_identity=args.application_signing_identity,
notarization_apple_id=args.notarization_apple_id,
notarization_password=args.notarization_password,
notarization_team_id=args.notarization_team_id,
).sign_and_notarize()
# Build OpenCore-Patcher.app
application.GenerateApplication(
reset_pyinstaller_cache=args.reset_pyinstaller_cache,
git_branch=args.git_branch,
git_commit_url=args.git_commit_url,
git_commit_date=args.git_commit_date,
analytics_key=args.analytics_key,
analytics_endpoint=args.analytics_endpoint,
).generate()
# Sign OpenCore-Patcher.app
sign_notarize.SignAndNotarize(
path=Path("dist/OpenCore-Patcher.app"),
signing_identity=args.application_signing_identity,
notarization_apple_id=args.notarization_apple_id,
notarization_password=args.notarization_password,
notarization_team_id=args.notarization_team_id,
entitlements=Path("./ci_tooling/entitlements/entitlements.plist"),
).sign_and_notarize()
if (args.run_as_individual_steps is False) or (args.run_as_individual_steps and args.prepare_package):
# Build OpenCore-Patcher.pkg and OpenCore-Patcher-Uninstaller.pkg
package.GeneratePackage().generate()
# Sign OpenCore-Patcher.pkg
sign_notarize.SignAndNotarize(
path=Path("dist/OpenCore-Patcher.pkg"),
signing_identity=args.installer_signing_identity,
notarization_apple_id=args.notarization_apple_id,
notarization_password=args.notarization_password,
notarization_team_id=args.notarization_team_id,
).sign_and_notarize()
# Sign OpenCore-Patcher-Uninstaller.pkg
sign_notarize.SignAndNotarize(
path=Path("dist/OpenCore-Patcher-Uninstaller.pkg"),
signing_identity=args.installer_signing_identity,
notarization_apple_id=args.notarization_apple_id,
notarization_password=args.notarization_password,
notarization_team_id=args.notarization_team_id,
).sign_and_notarize()
# Create Update Shim
if args.prepare_shim:
shim.GenerateShim().generate()
if Path("dist/OpenCore-Patcher.app").exists():
if Path("dist/OpenCore-Patcher (Original).app").exists():
Path("dist/OpenCore-Patcher (Original).app").unlink()
Path("dist/OpenCore-Patcher.app").rename("dist/OpenCore-Patcher (Original).app")
Path("dist/OpenCore-Patcher (Shim).app").rename("dist/OpenCore-Patcher.app")
# Update app version in Info.plist
plist_path = Path("dist/OpenCore-Patcher.app/Contents/Info.plist")
contents = plistlib.load(plist_path.open("rb"))
contents["CFBundleVersion"] = constants.Constants().patcher_version
contents["CFBundleShortVersionString"] = constants.Constants().patcher_version
plistlib.dump(contents, plist_path.open("wb"))
sign_notarize.SignAndNotarize(
path=Path("dist/OpenCore-Patcher.app"),
signing_identity=args.application_signing_identity,
notarization_apple_id=args.notarization_apple_id,
notarization_password=args.notarization_password,
notarization_team_id=args.notarization_team_id,
entitlements=Path("./ci_tooling/entitlements/entitlements.plist"),
).sign_and_notarize()
if __name__ == '__main__':
_start = time.time()
main()
print(f"Build script completed in {str(round(time.time() - _start, 2))} seconds")

View File

@@ -1,5 +1,103 @@
# OpenCore Legacy Patcher changelog
## 1.5.0
- Restructure project directories
- Python:
- Move logic into `opencore_legacy_patcher` directory
- Use relative imports for local libraries
- Documentation:
- Move images to `docs/images`
- Payloads:
- Remove redundant/unused files bundled in payloads.dmg
- Resolve unpatching Nvidia Web Drivers failing to clean up `/Library/Extensions`
- Implement preflight code signature checks for macOS installer creation
- Ensures validity of `createinstallmedia` binary before execution
- Modularize AutoPkg's pre/postinstall scripts
- Adjusted to use functions for better readability
- Implements ZSH shebang
- Removes OS logging
- Disable usage of `OpenLegacyBoot.efi`
- Resolves boot issues on certain CSM-based Macs
- Implement new PKG-based installer
- `OpenCore-Patcher.pkg` is now the recommended method for installation
- `OpenCore-Patcher-Uninstaller.pkg` is now available for uninstallation
- Note this only removes the application, not any patches applied
- `OpenCore-Patcher-GUI.app.zip` is deprecated and will be removed in future versions
- Implement new Privileged Helper Tool
- Removes need for password prompts when installing patches, creating installers, etc.
- Installed at `/Library/PrivilegedHelperTools/com.dortania.opencore-legacy-patcher.privileged-helper`
- No launch services required
- For running from source, recompile tool with debug configuration (`make debug`)
- Resolve OpenCore-Patcher.app window not appearing as topmost window on launch
- Reworked CI tooling:
- New build script with reworked parameters: `Build-Project.command`
- Remove reliance on WhiteBox's Packages for AutoPkg creation
- Now implements `pkgbuild` and `productbuild` for package creation through `macOs-Pkg-Builder` Python module
- Implement additional sanity checks before performing root patches
- Checks for mismatched snapshots vs root volume macOS versions
- Increment Binaries:
- OpenCorePkg 1.0.0 - release
## 1.4.3
- Update non-Metal Binaries for macOS Sonoma:
- Resolve TeraScale 2 screen recording kernel panic
- Resolve Dock location after changing screen resolution
- Resolve 14.4 loginwindow crashes
- Patch SkipLogo on Macs that natively support Monterey or newer
- Resolves missing Apple logo on boot screen
- Increment Binaries:
- OpenCorePkg 0.9.9 - release
## 1.4.2
- Resolve Auto-Join support for Modern Wireless on macOS 14.4
- Applicable for BCM94360, 4360, 4350, 4331 and 43224 chipsets
- Resolve WiFi support for Legacy Wireless on macOS 12.7.4 and 13.6.5
- Applicable for BCM94328, BCM94322 and Atheros chipsets
- Resolve USB 1.1 on macOS Ventura regression from OCLP 1.4.0
- Increment Binaries:
- PatcherSupportPkg 1.4.8 - release
## 1.4.1
- Update updater implementation
- Resolve Keyboard/Trackpad support for MacBookAir6,x running macOS 14.4 and newer
- Expands SPI Keyboard and Trackpad patch to include MacBookAir6,x
- Publish Bluetooth NVRAM variables for BCM2046 and BCM2070 chipsets
- Reduces need for NVRAM reset to restore Bluetooth support in newer OSes (Thanks @ausdauersportler)
## 1.4.0
- Refactor subprocess invocations
- Resolve RecoveryOS support (Regression resolved in OpenCorePkg)
- Restore SPI Keyboard and Trackpad support for macOS 14.4 and newer
- Applicable for MacBook8,1, MacBookAir7,x and MacBookPro12,1-14,x
- Restore support for T1 on macOS 14.4 and newer
- Applicable for MacBookPro13,2, MacBookPro13,3, MacBookPro14,2, MacBookPro14,3
- Restore support for legacy Metal GPUs on macOS 14.4 and newer
- Applicable for:
- Intel Ivy Bridge through Skylake
- Nvidia Kepler
- AMD legacy GCN
- Restore support for USB 1.1 on macOS 14.4 and newer
- Applicable for Penryn Macs, Xserve3,1 and MacPro4,1/5,1
- Resolve support for legacy and modern WiFi on macOS 14.4 and newer
- Applicable for all WiFi-equipped Macs
- Note with 14.4: Auto-Join may not work until you forget and rejoin the network
- Increment binaries:
- OpenCorePkg 0.9.7 - release
## 1.3.0
- Resolve mismatched `CFBundleExecutable` and binary name for kexts.
- Resolves ProperTree binary detection (Thanks @CorpNewt).
- Applicable extensions:
- corecrypto_T1.kext
- corecaptureElCap.kext
- IO80211ElCap.kext
- Resolve 3802-GPU support for macOS 14.2 Beta 2 and newer.
- Applicable GPUs:
- Intel Ivy Bridge and Haswell iGPUs
- Nvidia Kepler dGPUs
- Increment Binaries:
- PatcherSupportPkg 1.4.6 - release
## 1.2.1
- Resolve `TeraScale 2 Acceleration` checkbox in Settings not being saved
- Thanks @rtd1250

View File

@@ -1,5 +1,5 @@
Copyright (c) 2020-2023, Dhinak G
Copyright (c) 2020-2023, Mykola Grymalyuk
Copyright (c) 2020-2024, Dhinak G
Copyright (c) 2020-2024, Mykola Grymalyuk
All rights reserved.

View File

@@ -1,6 +1,9 @@
#!/usr/bin/env python3
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
from resources import main
"""
PyInstaller Entry Point
"""
from opencore_legacy_patcher import main
if __name__ == '__main__':
main.OpenCoreLegacyPatcher()
main()

View File

@@ -1,16 +1,28 @@
# -*- mode: python ; coding: utf-8 -*-
import sys, os, time, subprocess, pathlib
import os
import sys
import time
import subprocess
from pathlib import Path
from PyInstaller.building.api import PYZ, EXE, COLLECT
from PyInstaller.building.osx import BUNDLE
from PyInstaller.building.build_main import Analysis
sys.path.append(os.path.abspath(os.getcwd()))
from resources import constants
from opencore_legacy_patcher import constants
block_cipher = None
datas = [
('payloads.dmg', '.'),
('Universal-Binaries.dmg', '.'),
]
if pathlib.Path("DortaniaInternalResources.dmg").exists():
if Path("DortaniaInternalResources.dmg").exists():
datas.append(('DortaniaInternalResources.dmg', '.'))
@@ -27,8 +39,10 @@ a = Analysis(['OpenCore-Patcher-GUI.command'],
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
pyz = PYZ(a.pure,
a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
@@ -43,7 +57,8 @@ exe = EXE(pyz,
disable_windowed_traceback=False,
target_arch="universal2",
codesign_identity=None,
entitlements_file=None )
entitlements_file=None)
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
@@ -52,18 +67,20 @@ coll = COLLECT(exe,
upx=True,
upx_exclude=[],
name='OpenCore-Patcher')
app = BUNDLE(coll,
name='OpenCore-Patcher.app',
icon="payloads/OC-Patcher.icns",
icon="payloads/Icon/AppIcons/OC-Patcher.icns",
bundle_identifier="com.dortania.opencore-legacy-patcher",
info_plist={
"CFBundleName": "OpenCore Legacy Patcher",
"CFBundleVersion": constants.Constants().patcher_version,
"CFBundleShortVersionString": constants.Constants().patcher_version,
"NSHumanReadableCopyright": constants.Constants().copyright_date,
"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(),
"BuildMachineOSBuild": subprocess.run(["/usr/bin/sw_vers", "-buildVersion"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode().strip(),
"NSPrincipalClass": "NSApplication",
})

View File

@@ -1,5 +1,5 @@
<div align="center">
<img src="images/OC-Patcher.png" alt="OpenCore Patcher Logo" width="256" />
<img src="docs/images/OC-Patcher.png" alt="OpenCore Patcher Logo" width="256" />
<h1>OpenCore Legacy Patcher</h1>
</div>

View File

@@ -2,7 +2,7 @@
OpenCore Legacy Patcher at its core is a Python-based GUI/CLI-based application. In turn, to run the project from source, you simply need to invoke the OpenCore-Patcher-GUI.command file via Python.
For developers wishing to validate mainline changes, you may use this link: [GUI (Graphical Based App)](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app-wxpython/main/OpenCore-Patcher.app%20%28GUI%29.zip)
For developers wishing to validate mainline changes, you may use this link: [GUI (Graphical Based App)](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app-wxpython/main/OpenCore-Patcher.pkg.zip)
* **Warning**: Nightly builds (untagged builds built from the latest commit) are actively developed OpenCore Legacy Patcher builds. These builds have not been tested, are not guaranteed to work, and are not guaranteed to be safe. Do not use nightlies without a good reason to do so, and do not use them on your main machine. Additionally, these binaries should not be used without first consulting the [CHANGELOG](./CHANGELOG.md).
@@ -63,9 +63,7 @@ pip3 install pyinstaller
# Move into project directory
cd ~/Developer/OpenCore-Legacy-Patcher/
# Create the pyinstaller based Application
# Optional Arguments
# '--reset_binaries': Redownload and generate support files
python3 Build-Binary.command
python3 Build-Project.command
# Open build folder
open ./dist/
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

103
ci_tooling/autopkg/postinstall.sh Executable file
View File

@@ -0,0 +1,103 @@
#!/bin/zsh --no-rcs
# ------------------------------------------------------
# AutoPkg Assets Postinstall Script
# ------------------------------------------------------
# Create alias for app, start patching and reboot.
# ------------------------------------------------------
# MARK: PackageKit Parameters
# ---------------------------
pathToScript=$0 # ex. /tmp/PKInstallSandbox.*/Scripts/*/preinstall
pathToPackage=$1 # ex. ~/Downloads/Installer.pkg
pathToTargetLocation=$2 # ex. '/', '/Applications', etc (depends on pkgbuild's '--install-location' argument)
pathToTargetVolume=$3 # ex. '/', '/Volumes/MyVolume', etc
pathToStartupDisk=$4 # ex. '/'
# MARK: Variables
# ---------------------------
helperPath="Library/PrivilegedHelperTools/com.dortania.opencore-legacy-patcher.privileged-helper"
mainAppPath="Library/Application Support/Dortania/OpenCore-Patcher.app"
shimAppPath="Applications/OpenCore-Patcher.app"
executablePath="$mainAppPath/Contents/MacOS/OpenCore-Patcher"
# MARK: Functions
# ---------------------------
function _setSUIDBit() {
local binaryPath=$1
echo "Setting SUID bit on: $binaryPath"
# Check if path is a directory
if [[ -d $binaryPath ]]; then
/bin/chmod -R +s $binaryPath
else
/bin/chmod +s $binaryPath
fi
}
function _createAlias() {
local mainPath=$1
local aliasPath=$2
# Check if alias path exists
if [[ -e $aliasPath ]]; then
# Check if alias path is a symbolic link
if [[ -L $aliasPath ]]; then
echo "Removing old symbolic link: $aliasPath"
/bin/rm -f $aliasPath
else
echo "Removing old file: $aliasPath"
/bin/rm -rf $aliasPath
fi
fi
# Create symbolic link
echo "Creating symbolic link: $aliasPath"
/bin/ln -s $mainPath $aliasPath
}
function _startPatching() {
local executable=$1
local logPath=$(_logFile)
# Start patching
"$executable" "--patch_sys_vol" &> $logPath
}
function _logFile() {
echo "/Users/Shared/.OCLP-AutoPatcher-Log-$(/bin/date +"%Y_%m_%d_%I_%M_%p").txt"
}
function _fixSettingsFilePermission() {
local settingsPath="$pathToTargetVolume/Users/Shared/.com.dortania.opencore-legacy-patcher.plist"
if [[ -e $settingsPath ]]; then
echo "Fixing settings file permissions: $settingsPath"
/bin/chmod 666 $settingsPath
fi
}
function _reboot() {
/sbin/reboot
}
function _main() {
_setSUIDBit "$pathToTargetVolume/$helperPath"
_createAlias "$pathToTargetVolume/$mainAppPath" "$pathToTargetVolume/$shimAppPath"
_startPatching "$pathToTargetVolume/$executablePath"
_fixSettingsFilePermission
_reboot
}
# MARK: Main
# ---------------------------
echo "Starting postinstall script..."
_main

View File

@@ -0,0 +1,80 @@
#!/bin/zsh --no-rcs
# ------------------------------------------------------
# AutoPkg Assets Preinstall Script
# ------------------------------------------------------
# Remove old files, and prepare directories.
# ------------------------------------------------------
# MARK: PackageKit Parameters
# ---------------------------
pathToScript=$0 # ex. /tmp/PKInstallSandbox.*/Scripts/*/preinstall
pathToPackage=$1 # ex. ~/Downloads/Installer.pkg
pathToTargetLocation=$2 # ex. '/', '/Applications', etc (depends on pkgbuild's '--install-location' argument)
pathToTargetVolume=$3 # ex. '/', '/Volumes/MyVolume', etc
pathToStartupDisk=$4 # ex. '/'
# MARK: Variables
# ---------------------------
filesToRemove=(
"Applications/OpenCore-Patcher.app"
"Library/Application Support/Dortania/Update.plist"
"Library/Application Support/Dortania/OpenCore-Patcher.app"
"Library/LaunchAgents/com.dortania.opencore-legacy-patcher.auto-patch.plist"
"Library/PrivilegedHelperTools/com.dortania.opencore-legacy-patcher.privileged-helper"
)
# MARK: Functions
# ---------------------------
function _removeFile() {
local file=$1
if [[ ! -e $file ]]; then
# Check if file is a symbolic link
if [[ -L $file ]]; then
echo "Removing symbolic link: $file"
/bin/rm -f $file
fi
return
fi
echo "Removing file: $file"
# Check if file is a directory
if [[ -d $file ]]; then
/bin/rm -rf $file
else
/bin/rm -f $file
fi
}
function _createParentDirectory() {
local file=$1
local parentDirectory="$(/usr/bin/dirname $file)"
# Check if parent directory exists
if [[ ! -d $parentDirectory ]]; then
echo "Creating parent directory: $parentDirectory"
/bin/mkdir -p $parentDirectory
fi
}
function _main() {
for file in $filesToRemove; do
_removeFile $pathToTargetVolume/$file
_createParentDirectory $pathToTargetVolume/$file
done
}
# MARK: Main
# ---------------------------
echo "Starting preinstall script..."
_main

View File

@@ -0,0 +1,176 @@
import sys
import time
import plistlib
import subprocess
from pathlib import Path
from opencore_legacy_patcher import constants
from opencore_legacy_patcher.support import subprocess_wrapper
class GenerateApplication:
"""
Generate OpenCore-Patcher.app
"""
def __init__(self, reset_pyinstaller_cache: bool = False, git_branch: str = None, git_commit_url: str = None, git_commit_date: str = None, analytics_key: str = None, analytics_endpoint: str = None) -> None:
"""
Initialize
"""
self._pyinstaller = [sys.executable, "-m", "PyInstaller"]
self._application_output = Path("./dist/OpenCore-Patcher.app")
self._reset_pyinstaller_cache = reset_pyinstaller_cache
self._git_branch = git_branch
self._git_commit_url = git_commit_url
self._git_commit_date = git_commit_date
self._analytics_key = analytics_key
self._analytics_endpoint = analytics_endpoint
def _generate_application(self) -> None:
"""
Generate PyInstaller Application
"""
if self._application_output.exists():
subprocess_wrapper.run_and_verify(["/bin/rm", "-rf", self._application_output], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print("Generating OpenCore-Patcher.app")
_args = self._pyinstaller + ["./OpenCore-Patcher-GUI.spec", "--noconfirm"]
if self._reset_pyinstaller_cache:
_args.append("--clean")
subprocess_wrapper.run_and_verify(_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def _embed_analytics_key(self) -> None:
"""
Embed analytics key
"""
_file = Path("./opencore_legacy_patcher/support/analytics_handler.py")
if not all([self._analytics_key, self._analytics_endpoint]):
print("Analytics key or endpoint not provided, skipping embedding")
return
print("Embedding analytics data")
if not Path(_file).exists():
raise FileNotFoundError("analytics_handler.py not found")
lines = []
with open(_file, "r") as f:
lines = f.readlines()
for i, line in enumerate(lines):
if line.startswith("SITE_KEY: str = "):
lines[i] = f"SITE_KEY: str = \"{self._analytics_key}\"\n"
elif line.startswith("ANALYTICS_SERVER: str = "):
lines[i] = f"ANALYTICS_SERVER: str = \"{self._analytics_endpoint}\"\n"
with open(_file, "w") as f:
f.writelines(lines)
def _remove_analytics_key(self) -> None:
"""
Remove analytics key
"""
_file = Path("./opencore_legacy_patcher/support/analytics_handler.py")
if not all([self._analytics_key, self._analytics_endpoint]):
return
print("Removing analytics data")
if not _file.exists():
raise FileNotFoundError("analytics_handler.py not found")
lines = []
with open(_file, "r") as f:
lines = f.readlines()
for i, line in enumerate(lines):
if line.startswith("SITE_KEY: str = "):
lines[i] = "SITE_KEY: str = \"\"\n"
elif line.startswith("ANALYTICS_SERVER: str = "):
lines[i] = "ANALYTICS_SERVER: str = \"\"\n"
with open(_file, "w") as f:
f.writelines(lines)
def _patch_load_command(self):
"""
Patch 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
"""
_file = self._application_output / "Contents" / "MacOS" / "OpenCore-Patcher"
_find = b'\x00\x0D\x0A\x00' # 10.13 (0xA0D)
_replace = b'\x00\x0A\x0A\x00' # 10.10 (0xA0A)
print("Patching LC_VERSION_MIN_MACOSX")
with open(_file, "rb") as f:
data = f.read()
data = data.replace(_find, _replace, 1)
with open(_file, "wb") as f:
f.write(data)
def _embed_git_data(self) -> None:
"""
Embed git data
"""
_file = self._application_output / "Contents" / "Info.plist"
_git_branch = self._git_branch or "Built from source"
_git_commit = self._git_commit_url or ""
_git_commit_date = self._git_commit_date or time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print("Embedding git data")
_plist = plistlib.load(_file.open("rb"))
_plist["Github"] = {
"Branch": _git_branch,
"Commit URL": _git_commit,
"Commit Date": _git_commit_date
}
plistlib.dump(_plist, _file.open("wb"), sort_keys=True)
def _embed_resources(self) -> None:
"""
Embed resources
"""
print("Embedding resources")
for file in Path("payloads/Icon/AppIcons").glob("*.icns"):
subprocess_wrapper.run_and_verify(
["/bin/cp", str(file), self._application_output / "Contents" / "Resources/"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
def generate(self) -> None:
"""
Generate OpenCore-Patcher.app
"""
self._embed_analytics_key()
self._generate_application()
self._remove_analytics_key()
self._patch_load_command()
self._embed_git_data()
self._embed_resources()

View File

@@ -0,0 +1,136 @@
"""
disk_images.py: Fetch and generate disk images (Universal-Binaries.dmg, payloads.dmg)
"""
import subprocess
from pathlib import Path
from opencore_legacy_patcher import constants
from opencore_legacy_patcher.support import subprocess_wrapper
class GenerateDiskImages:
def __init__(self, reset_dmg_cache: bool = False) -> None:
"""
Initialize
"""
self.reset_dmg_cache = reset_dmg_cache
def _delete_extra_binaries(self):
"""
Delete extra binaries from payloads directory
"""
whitelist_folders = [
"ACPI",
"Config",
"Drivers",
"Icon",
"Kexts",
"OpenCore",
"Tools",
"Launch Services",
]
whitelist_files = []
print("Deleting extra binaries...")
for file in Path("payloads").glob(pattern="*"):
if file.is_dir():
if file.name in whitelist_folders:
continue
print(f"- Deleting {file.name}")
subprocess_wrapper.run_and_verify(["/bin/rm", "-rf", file])
else:
if file.name in whitelist_files:
continue
print(f"- Deleting {file.name}")
subprocess_wrapper.run_and_verify(["/bin/rm", "-f", file])
def _generate_payloads_dmg(self):
"""
Generate disk image containing all payloads
Disk image will be password protected due to issues with
Apple's notarization system and inclusion of kernel extensions
"""
if Path("./payloads.dmg").exists():
if self.reset_dmg_cache is False:
print("- payloads.dmg already exists, skipping creation")
return
print("- Removing old payloads.dmg")
subprocess_wrapper.run_and_verify(
["/bin/rm", "-rf", "./payloads.dmg"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
print("Generating DMG...")
subprocess_wrapper.run_and_verify([
'/usr/bin/hdiutil', 'create', './payloads.dmg',
'-megabytes', '32000', # Overlays can only be as large as the disk image allows
'-format', 'UDZO', '-ov',
'-volname', 'OpenCore Patcher Resources (Base)',
'-fs', 'HFS+',
'-srcfolder', './payloads',
'-passphrase', 'password', '-encryption'
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print("DMG generation complete")
def _download_resources(self):
"""
Download required dependencies
"""
patcher_support_pkg_version = constants.Constants().patcher_support_pkg_version
required_resources = [
"Universal-Binaries.dmg"
]
print("Downloading required resources...")
for resource in required_resources:
if Path(f"./{resource}").exists():
if self.reset_dmg_cache is True:
print(f" - Removing old {resource}")
# Just to be safe
assert resource, "Resource cannot be empty"
assert resource not in ("/", "."), "Resource cannot be root"
subprocess_wrapper.run_and_verify(
["/bin/rm", "-rf", f"./{resource}"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
else:
print(f"- {resource} already exists, skipping download")
continue
print(f"- Downloading {resource}...")
subprocess_wrapper.run_and_verify(
[
"/usr/bin/curl", "-LO",
f"https://github.com/dortania/PatcherSupportPkg/releases/download/{patcher_support_pkg_version}/{resource}"
],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
if not Path(f"./{resource}").exists():
print(f"- {resource} not found")
raise Exception(f"{resource} not found")
def generate(self) -> None:
"""
Generate disk images
"""
self._delete_extra_binaries()
self._generate_payloads_dmg()
self._download_resources()

View File

@@ -0,0 +1,110 @@
"""
package.py: Generate packages (Installer, Uninstaller, AutoPkg-Assets)
"""
import macos_pkg_builder
from opencore_legacy_patcher import constants
class GeneratePackage:
"""
Generate OpenCore-Patcher.pkg
"""
def __init__(self) -> None:
"""
Initialize
"""
self._files = {
"./dist/OpenCore-Patcher.app": "/Library/Application Support/Dortania/OpenCore-Patcher.app",
"./ci_tooling/privileged_helper_tool/com.dortania.opencore-legacy-patcher.privileged-helper": "/Library/PrivilegedHelperTools/com.dortania.opencore-legacy-patcher.privileged-helper",
}
self._autopkg_files = {
"./payloads/Launch Services/com.dortania.opencore-legacy-patcher.auto-patch.plist": "/Library/LaunchAgents/com.dortania.opencore-legacy-patcher.auto-patch.plist",
}
self._autopkg_files.update(self._files)
def _generate_installer_welcome(self) -> str:
"""
Generate Welcome message for installer PKG
"""
_welcome = ""
_welcome += "# Overview\n"
_welcome += f"This package will install the OpenCore Legacy Patcher application (v{constants.Constants().patcher_version}) on your system."
_welcome += "\n\nAdditionally, a shortcut for OpenCore Legacy Patcher will be added in the '/Applications' folder."
_welcome += "\n\nThis package will not 'Build and Install OpenCore' or install any 'Root Patches' on your machine. If required, you can run OpenCore Legacy Patcher to install any patches you may need."
_welcome += f"\n\nFor more information on OpenCore Legacy Patcher usage, see our [documentation]({constants.Constants().guide_link}) and [GitHub repository]({constants.Constants().repo_link})."
_welcome += "\n\n"
_welcome += "## Files Installed"
_welcome += "\n\nInstallation of this package will add the following files to your system:"
for key, value in self._files.items():
_welcome += f"\n\n- `{value}`"
return _welcome
def _generate_uninstaller_welcome(self) -> str:
"""
Generate Welcome message for uninstaller PKG
"""
_welcome = ""
_welcome += "# Application Uninstaller\n"
_welcome += "This package will uninstall the OpenCore Legacy Patcher application and its Privileged Helper Tool from your system."
_welcome += "\n\n"
_welcome += "This will not remove any root patches or OpenCore configurations that you may have installed using OpenCore Legacy Patcher."
_welcome += "\n\n"
_welcome += f"For more information on OpenCore Legacy Patcher, see our [documentation]({constants.Constants().guide_link}) and [GitHub repository]({constants.Constants().repo_link})."
return _welcome
def generate(self) -> None:
"""
Generate OpenCore-Patcher.pkg
"""
print("Generating OpenCore-Patcher-Uninstaller.pkg")
assert macos_pkg_builder.Packages(
pkg_output="./dist/OpenCore-Patcher-Uninstaller.pkg",
pkg_bundle_id="com.dortania.opencore-legacy-patcher-uninstaller",
pkg_version=constants.Constants().patcher_version,
pkg_background="./ci_tooling/installation_pkg/PkgBackgroundUninstaller.png",
pkg_preinstall_script="./ci_tooling/installation_pkg/uninstall.sh",
pkg_as_distribution=True,
pkg_title="OpenCore Legacy Patcher Uninstaller",
pkg_welcome=self._generate_uninstaller_welcome(),
).build() is True
print("Generating OpenCore-Patcher.pkg")
assert macos_pkg_builder.Packages(
pkg_output="./dist/OpenCore-Patcher.pkg",
pkg_bundle_id="com.dortania.opencore-legacy-patcher",
pkg_version=constants.Constants().patcher_version,
pkg_allow_relocation=False,
pkg_as_distribution=True,
pkg_background="./ci_tooling/installation_pkg/PkgBackground.png",
pkg_preinstall_script="./ci_tooling/installation_pkg/preinstall.sh",
pkg_postinstall_script="./ci_tooling/installation_pkg/postinstall.sh",
pkg_file_structure=self._files,
pkg_title="OpenCore Legacy Patcher",
pkg_welcome=self._generate_installer_welcome(),
).build() is True
print("Generating AutoPkg-Assets.pkg")
assert macos_pkg_builder.Packages(
pkg_output="./dist/AutoPkg-Assets.pkg",
pkg_bundle_id="com.dortania.pkg.AutoPkg-Assets",
pkg_version=constants.Constants().patcher_version,
pkg_allow_relocation=False,
pkg_as_distribution=True,
pkg_background="./ci_tooling/autopkg/PkgBackground.png",
pkg_preinstall_script="./ci_tooling/autopkg/preinstall.sh",
pkg_postinstall_script="./ci_tooling/autopkg/postinstall.sh",
pkg_file_structure=self._autopkg_files,
pkg_title="AutoPkg Assets",
pkg_welcome="# DO NOT RUN AUTOPKG-ASSETS MANUALLY!\n\n## THIS CAN BREAK YOUR SYSTEM'S INSTALL!\n\nThis package should only ever be invoked by the Patcher itself, never downloaded or run by the user. Download the OpenCore-Patcher.pkg on the Github Repository.\n\n[OpenCore Legacy Patcher GitHub Release](https://github.com/dortania/OpenCore-Legacy-Patcher/releases/)",
).build() is True

View File

@@ -0,0 +1,33 @@
"""
shim.py: Generate Update Shim
"""
from pathlib import Path
from opencore_legacy_patcher.support import subprocess_wrapper
class GenerateShim:
def __init__(self) -> None:
self._shim_path = "./ci_tooling/update_shim/OpenCore-Patcher.app"
self._shim_pkg = f"{self._shim_path}/Contents/Resources/OpenCore-Patcher.pkg"
self._build_pkg = "./dist/OpenCore-Patcher.pkg"
self._output_shim = "./dist/OpenCore-Patcher (Shim).app"
def generate(self) -> None:
"""
Generate Update Shim
"""
print("Generating Update Shim")
if Path(self._shim_pkg).exists():
Path(self._shim_pkg).unlink()
subprocess_wrapper.run_and_verify(["/bin/cp", "-R", self._build_pkg, self._shim_pkg])
if Path(self._output_shim).exists():
Path(self._output_shim).unlink()
subprocess_wrapper.run_and_verify(["/bin/cp", "-R", self._shim_path, self._output_shim])

View File

@@ -0,0 +1,54 @@
"""
sign_notarize.py: Sign and Notarize a file
"""
import mac_signing_buddy
import macos_pkg_builder
from pathlib import Path
import macos_pkg_builder.utilities.signing
class SignAndNotarize:
def __init__(self, path: Path, signing_identity: str, notarization_apple_id: str, notarization_password: str, notarization_team_id: str, entitlements: str = None) -> None:
"""
Initialize
"""
self._path = path
self._signing_identity = signing_identity
self._notarization_apple_id = notarization_apple_id
self._notarization_password = notarization_password
self._notarization_team_id = notarization_team_id
self._entitlements = entitlements
def sign_and_notarize(self) -> None:
"""
Sign and Notarize
"""
if not all([self._signing_identity, self._notarization_apple_id, self._notarization_password, self._notarization_team_id]):
print("Signing and Notarization details not provided, skipping")
return
print(f"Signing {self._path.name}")
if self._path.name.endswith(".pkg"):
macos_pkg_builder.utilities.signing.SignPackage(
identity=self._signing_identity,
pkg=self._path,
).sign()
else:
mac_signing_buddy.Sign(
identity=self._signing_identity,
file=self._path,
**({"entitlements": self._entitlements} if self._entitlements else {}),
).sign()
print(f"Notarizing {self._path.name}")
mac_signing_buddy.Notarize(
apple_id=self._notarization_apple_id,
password=self._notarization_password,
team_id=self._notarization_team_id,
file=self._path,
).sign()

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

View File

@@ -0,0 +1,74 @@
#!/bin/zsh --no-rcs
# ------------------------------------------------------
# OpenCore Legacy Patcher PKG Post Install Script
# ------------------------------------------------------
# Set SUID bit on helper tool, and create app alias.
# ------------------------------------------------------
# MARK: PackageKit Parameters
# ---------------------------
pathToScript=$0 # ex. /tmp/PKInstallSandbox.*/Scripts/*/preinstall
pathToPackage=$1 # ex. ~/Downloads/Installer.pkg
pathToTargetLocation=$2 # ex. '/', '/Applications', etc (depends on pkgbuild's '--install-location' argument)
pathToTargetVolume=$3 # ex. '/', '/Volumes/MyVolume', etc
pathToStartupDisk=$4 # ex. '/'
# MARK: Variables
# ---------------------------
helperPath="Library/PrivilegedHelperTools/com.dortania.opencore-legacy-patcher.privileged-helper"
mainAppPath="Library/Application Support/Dortania/OpenCore-Patcher.app"
shimAppPath="Applications/OpenCore-Patcher.app"
# MARK: Functions
# ---------------------------
function _setSUIDBit() {
local binaryPath=$1
echo "Setting SUID bit on: $binaryPath"
# Check if path is a directory
if [[ -d $binaryPath ]]; then
/bin/chmod -R +s $binaryPath
else
/bin/chmod +s $binaryPath
fi
}
function _createAlias() {
local mainPath=$1
local aliasPath=$2
# Check if alias path exists
if [[ -e $aliasPath ]]; then
# Check if alias path is a symbolic link
if [[ -L $aliasPath ]]; then
echo "Removing old symbolic link: $aliasPath"
/bin/rm -f $aliasPath
else
echo "Removing old file: $aliasPath"
/bin/rm -rf $aliasPath
fi
fi
# Create symbolic link
echo "Creating symbolic link: $aliasPath"
/bin/ln -s $mainPath $aliasPath
}
function _main() {
_setSUIDBit "$pathToTargetVolume/$helperPath"
_createAlias "$pathToTargetVolume/$mainAppPath" "$pathToTargetVolume/$shimAppPath"
}
# MARK: Main
# ---------------------------
echo "Starting postinstall script..."
_main

View File

@@ -0,0 +1,79 @@
#!/bin/zsh --no-rcs
# ------------------------------------------------------
# OpenCore Legacy Patcher PKG Preinstall Script
# ------------------------------------------------------
# Remove old files, and prepare directories.
# ------------------------------------------------------
# MARK: PackageKit Parameters
# ---------------------------
pathToScript=$0 # ex. /tmp/PKInstallSandbox.*/Scripts/*/preinstall
pathToPackage=$1 # ex. ~/Downloads/Installer.pkg
pathToTargetLocation=$2 # ex. '/', '/Applications', etc (depends on pkgbuild's '--install-location' argument)
pathToTargetVolume=$3 # ex. '/', '/Volumes/MyVolume', etc
pathToStartupDisk=$4 # ex. '/'
# MARK: Variables
# ---------------------------
filesToRemove=(
"Applications/OpenCore-Patcher.app"
"Library/Application Support/Dortania/Update.plist"
"Library/Application Support/Dortania/OpenCore-Patcher.app"
"Library/PrivilegedHelperTools/com.dortania.opencore-legacy-patcher.privileged-helper"
)
# MARK: Functions
# ---------------------------
function _removeFile() {
local file=$1
if [[ ! -e $file ]]; then
# Check if file is a symbolic link
if [[ -L $file ]]; then
echo "Removing symbolic link: $file"
/bin/rm -f $file
fi
return
fi
echo "Removing file: $file"
# Check if file is a directory
if [[ -d $file ]]; then
/bin/rm -rf $file
else
/bin/rm -f $file
fi
}
function _createParentDirectory() {
local file=$1
local parentDirectory="$(/usr/bin/dirname $file)"
# Check if parent directory exists
if [[ ! -d $parentDirectory ]]; then
echo "Creating parent directory: $parentDirectory"
/bin/mkdir -p $parentDirectory
fi
}
function _main() {
for file in $filesToRemove; do
_removeFile $pathToTargetVolume/$file
_createParentDirectory $pathToTargetVolume/$file
done
}
# MARK: Main
# ---------------------------
echo "Starting preinstall script..."
_main

View File

@@ -0,0 +1,85 @@
#!/bin/zsh --no-rcs
# ------------------------------------------------------
# OpenCore Legacy Patcher PKG Uninstall Script
# ------------------------------------------------------
# MARK: PackageKit Parameters
# ---------------------------
pathToScript=$0 # ex. /tmp/PKInstallSandbox.*/Scripts/*/preinstall
pathToPackage=$1 # ex. ~/Downloads/Installer.pkg
pathToTargetLocation=$2 # ex. '/', '/Applications', etc (depends on pkgbuild's '--install-location' argument)
pathToTargetVolume=$3 # ex. '/', '/Volumes/MyVolume', etc
pathToStartupDisk=$4 # ex. '/'
# MARK: Variables
# ---------------------------
filesToRemove=(
"Applications/OpenCore-Patcher.app"
"Library/Application Support/Dortania/Update.plist"
"Library/Application Support/Dortania/OpenCore-Patcher.app"
"Library/PrivilegedHelperTools/com.dortania.opencore-legacy-patcher.privileged-helper"
)
# MARK: Functions
# ---------------------------
function _removeFile() {
local file=$1
if [[ ! -e $file ]]; then
# Check if file is a symbolic link
if [[ -L $file ]]; then
echo "Removing symbolic link: $file"
/bin/rm -f $file
fi
return
fi
echo "Removing file: $file"
# Check if file is a directory
if [[ -d $file ]]; then
/bin/rm -rf $file
else
/bin/rm -f $file
fi
}
function _cleanLaunchService() {
local domain="com.dortania.opencore-legacy-patcher"
# Iterate over launch agents and daemons
for launchServiceVariant in "$pathToTargetVolume/Library/LaunchAgents" "$pathToTargetVolume/Library/LaunchDaemons"; do
# Check if directory exists
if [[ ! -d $launchServiceVariant ]]; then
continue
fi
# Iterate over launch service files
for launchServiceFile in $(/bin/ls -1 $launchServiceVariant | /usr/bin/grep $domain); do
local launchServicePath="$launchServiceVariant/$launchServiceFile"
# Remove launch service file
_removeFile $launchServicePath
done
done
}
function _main() {
_cleanLaunchService
for file in $filesToRemove; do
_removeFile "$pathToTargetVolume/$file"
done
}
# MARK: Main
# ---------------------------
echo "Starting uninstall script..."
_main

View File

@@ -0,0 +1,374 @@
#!/usr/bin/env python3
"""
--------------------------------
macOS_Installer_Backup.command
--------------------------------
Utility for grabbing macOS Installers from Apple's catalogs and AppleDB,
and saving them to a local directory.
WARNING: Solely for internal usage, not intended for end-users.
"""
import sys
import argparse
import plistlib
import subprocess
from pathlib import Path
from datetime import datetime
# To allow easy importing of OpenCore Legacy Patcher's utilities
sys.path.append(str(Path(__file__).parent.parent.parent))
from opencore_legacy_patcher.support import (
macos_installer_handler,
network_handler,
integrity_verification,
utilities,
)
from opencore_legacy_patcher.datasets import os_data
_DEFAULT_PATH: str = "/Volumes/macOS Installers"
class InstallerBackup:
def __init__(self,
directory: Path = Path(_DEFAULT_PATH),
supported_oses: list = [
os_data.os_data.big_sur,
os_data.os_data.monterey,
os_data.os_data.ventura,
os_data.os_data.sonoma
],
first_run: bool = False
) -> None:
print(f"Starting macOS Installer Backup: {datetime.now()}")
self._directory = directory
self._supported_oses = supported_oses
self._os_table = {
os_data.os_data.big_sur: Path(self._directory, "11 Big Sur"),
os_data.os_data.monterey: Path(self._directory, "12 Monterey"),
os_data.os_data.ventura: Path(self._directory, "13 Ventura"),
os_data.os_data.sonoma: Path(self._directory, "14 Sonoma"),
}
for os_version in self._supported_oses:
if os_version not in self._os_table:
raise ValueError(f"Unsupported OS version: {os_version}")
for dir in self._os_table.values():
if not Path(dir).exists():
if first_run is False:
raise FileNotFoundError(f"Directory does not exist: {dir} (use --first-run to create)")
Path(dir).mkdir(parents=True, exist_ok=True)
self._main()
def _download_installer(self, installer: dict) -> None:
"""
Download installer
"""
installer_name = f"{installer['Version']} ({installer['Build']})"
if Path(installer['Link']).suffix == ".pkg":
installer_name += " InstallAssistant.pkg"
else:
installer_name += " Restore.ipsw"
integrity_name = f"{installer_name}.integrityDataV1"
print(f"Downloading {installer_name}")
# Check if integrity file available
integrity = installer["integrity"]
if integrity is not None:
result = self._downloader(url=integrity, path=Path(self._os_table[installer['OS']], integrity_name), name=integrity_name)
if result is False:
return
# Download installer
result = self._downloader(url=installer["Link"], path=Path(self._os_table[installer['OS']], installer_name), name=installer_name)
if result is False:
return
# Validate against chunklist
if integrity is not None:
result = self._validate_against_chunklist(installer_path=Path(self._os_table[installer['OS']], installer_name), chunklist=Path(self._os_table[installer['OS']], integrity_name))
if result is False:
return
def _validate_against_chunklist(self, installer_path: str, chunklist: str) -> bool:
"""
Validate file against chunklist
"""
name = Path(installer_path).name
if not Path(installer_path).exists():
print("File does not exist")
return False
if not Path(chunklist).exists():
print("Chunklist does not exist")
return False
chunk_obj = integrity_verification.ChunklistVerification(installer_path, chunklist)
if not chunk_obj.chunks:
print("Failed to generate chunklist dict")
return False
print(f"Validating {name} against chunklist: {chunk_obj.total_chunks} chunks", end="\r")
chunk_obj.validate()
while chunk_obj.status == integrity_verification.ChunklistStatus.IN_PROGRESS:
print(f"Validating {name} against chunklist: chunk {chunk_obj.current_chunk} passed", end="\r")
if chunk_obj.status == integrity_verification.ChunklistStatus.FAILURE:
print(chunk_obj.error_msg)
print(f"Validating {name} against chunklist: chunk {chunk_obj.current_chunk} failed")
for file in [installer_path, chunklist]:
result = subprocess.run(["/bin/rm", "-f", file])
if result.returncode != 0:
print(f"Failed to delete {file}")
print(f"Validating {name} against chunklist: chunk {chunk_obj.total_chunks} passed")
return True
def _downloader(self, url, path, name) -> bool:
"""
Download file from URL
"""
dl_obj = network_handler.DownloadObject(url, path)
dl_obj.download(display_progress=False, spawn_thread=True)
percentages_displayed = set()
while dl_obj.is_active():
if dl_obj.get_percent() in percentages_displayed:
continue
percentages_displayed.add(int(dl_obj.get_percent()))
print(f" Downloading: {name}: {dl_obj.get_percent():.2f}% ({utilities.human_fmt(dl_obj.get_speed())})/s", end="\r")
print(f" Downloading: {name}: 100.00% ({utilities.human_fmt(dl_obj.get_speed())})/s")
if not dl_obj.download_complete:
print("Download failed")
subprocess.run(["/bin/rm", "-f", path]) # Retry later
return False
if Path(path).stat().st_size == 0:
print("Downloaded file is empty, considering permanent failure") # Likely dead URL
if not Path(Path(path).parent, "Dead URLs").exists():
Path(Path(path).parent, "Dead URLs").mkdir()
if Path(path).exists():
subprocess.run(["/bin/mv", path, Path(Path(path).parent, "Dead URLs", Path(path).name)])
return True
def _does_file_exist(self, xnu_version: int, build: str, suffix: str) -> bool:
"""
Check if installer already exists in directory
"""
if xnu_version not in self._os_table:
raise ValueError(f"Unsupported OS version: {xnu_version}")
if not Path(self._os_table[xnu_version]).exists():
raise FileNotFoundError(f"Directory does not exist: {self._os_table[xnu_version]}")
# Check failed, as those are generally dead URLs
for path in [Path(self._os_table[xnu_version]), Path(self._os_table[xnu_version], "Dead URLs")]:
if not Path(path).exists():
continue
for file in path.iterdir():
if file.is_dir():
continue
if not file.name.endswith(suffix):
continue
if f"({build})" in file.name:
return True
return False
def _get_remote_installer_catalog(self, os_version: int) -> dict:
"""
Get remote installer catalog from Apple's servers
"""
installers = {}
print(f"SUCATALOG: Getting installers for macOS {os_data.os_conversion.kernel_to_os(os_version)}")
for seed in macos_installer_handler.SeedType:
print(f" Catalog: {seed.name}")
result = macos_installer_handler.RemoteInstallerCatalog(seed_override=seed, os_override=os_version).available_apps
installers.update(result)
return installers
def _get_apple_db_items(self, variant: str = ".ipsw") -> dict:
"""
Get macOS installers from AppleDB
"""
if variant not in ["InstallAssistant.pkg", ".ipsw"]:
raise ValueError(f"Invalid variant: {variant}")
installers = {
# "22F82": {
# url: "https://swcdn.apple.com/content/downloads/36/06/042-01917-A_B57IOY75IU/oocuh8ap7y8l8vhu6ria5aqk7edd262orj/InstallAssistant.pkg",
# version: "13.4.1",
# build: "22F82",
# }
}
print(f"APPLEDB: Getting installers for variant: {variant}")
apple_db = network_handler.NetworkUtilities().get("https://api.appledb.dev/main.json")
if apple_db is None:
return installers
apple_db = apple_db.json()
for group in apple_db:
if group != "ios":
continue
for item in apple_db[group]:
if "osStr" not in item:
continue
if item["osStr"] != "macOS":
continue
if "build" not in item:
continue
if "version" not in item:
continue
if "sources" not in item:
continue
for source in item["sources"]:
if "links" not in source:
continue
for entry in source["links"]:
if "url" not in entry:
continue
if entry["url"].endswith(variant) is False:
continue
models = []
if "devices" in item:
for device in item["devices"]:
_device = device
if "-" in device:
_device = device.split("-")[0]
if _device in models:
continue
models.append(_device)
# Attempt to match macos_installer_handler.py's format
installers[item["build"]] = {
"Version": item["version"],
"Build": item["build"],
"Link": entry["url"],
"Size": -1,
"integrity": None,
"Source": "AppleDB",
"Variant": "Beta" if item["beta"] else "Public",
"OS": os_data.os_conversion.os_to_kernel(item["version"] if " " not in item["version"] else item["version"].split(" ")[0]),
"Models": models,
"Date": item["released"],
}
return installers
def _main(self) -> None:
"""
Main entry point
"""
installers = {}
apple_db_ipsw_installers = {}
apple_db_pkg_installers = {}
for build in self._supported_oses:
installers.update(self._get_remote_installer_catalog(os_version=build))
for installer in [".ipsw", "InstallAssistant.pkg"]:
apple_db_items = self._get_apple_db_items(variant=installer)
if installer == ".ipsw":
apple_db_ipsw_installers = apple_db_items
else:
apple_db_pkg_installers = apple_db_items
installers.update(apple_db_items)
# Sort by name
installers = dict(sorted(installers.items(), key=lambda item: item[1]["Build"]))
print(f"Found {len(installers)} installers, checking which ones are missing")
missing = []
for build in installers:
if self._does_file_exist(xnu_version=installers[build]["OS"], build=installers[build]["Build"], suffix=Path(installers[build]["Link"]).suffix) is True:
continue
missing.append(installers[build])
print(f"Found {len(missing)} missing installers:" if missing else "No missing installers found")
for installer in missing:
print(f" {Path(installer['Link']).suffix}: {installer['Version']} ({installer['Build']})")
self._download_installer(installer)
# Finally, fix names
for apple_db_installers in [apple_db_ipsw_installers, apple_db_pkg_installers]:
for installer in apple_db_installers:
_build = apple_db_installers[installer]["Build"]
_version = apple_db_installers[installer]["Version"]
if _version.lower().endswith(" beta"):
_version += " 1"
elif " " not in _version:
_version += " release"
_base_name = f"{_version} ({_build})"
for os in self._os_table:
for directory in [self._os_table[os], Path(self._os_table[os], "Dead URLs")]:
for file in directory.iterdir():
if file.is_dir():
continue
if f"({_build})" not in file.name and f" {_build} " not in file.name:
continue
_name = _base_name
_current_suffix = Path(file).suffix
if _current_suffix == ".pkg":
_name += " InstallAssistant.pkg"
elif _current_suffix == ".ipsw":
_name += " Restore.ipsw"
elif _current_suffix == ".integrityDataV1":
if Path(file).name.endswith(" Restore.ipsw.integrityDataV1"):
_name += " Restore.ipsw.integrityDataV1"
elif Path(file).name.endswith("InstallAssistant.pkg.integrityDataV1"):
_name += " InstallAssistant.pkg.integrityDataV1"
else:
continue
else:
continue
if Path(file).name == _name:
continue
print(f"Renaming {file.name} to {_name}")
result = subprocess.run(["/bin/mv", file, Path(directory, _name)])
if result.returncode != 0:
print(f"Failed to rename {file} to {Path(directory, _name)}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="macOS Installer Backup")
parser.add_argument("--first-run", action="store_true", help="Create directories if missing")
InstallerBackup(**vars(parser.parse_args()))

View File

@@ -0,0 +1,13 @@
CC=clang
OUTPUT=com.dortania.opencore-legacy-patcher.privileged-helper
all: clean release
release: main.m
$(CC) -framework Foundation -framework Security -arch x86_64 -arch arm64 -mmacosx-version-min=10.9 -o $(OUTPUT) main.m
debug: main.m
$(CC) -framework Foundation -framework Security -arch x86_64 -arch arm64 -mmacosx-version-min=10.9 -o $(OUTPUT) main.m -DDEBUG
clean:
/bin/rm -f $(OUTPUT)

View File

@@ -0,0 +1,34 @@
# OpenCore Legacy Patcher Privileged Helper Tool
`com.dortania.opencore-legacy-patcher.privileged-helper` is OpenCore Legacy Patcher's Privileged Helper Tool.
The architecture is as such:
1. The main application (OpenCore-Patcher.app) will send arguments to the privileged helper tool to execute.
2. The privileged helper tool will check the code signature of the main application to ensure it is signed by Dortania.
3. The privileged helper tool will then execute the command and return the output to the main application.
The helper tool is able to execute code as root by using the "Set UID" bit present on the file.
## Running from source
Since running OpenCore Legacy Patcher from source will lack Dortania's code signature, you will need to disable code signature verification in the privileged helper tool otherwise root commands will fail.
To do so, compile the privileged helper tool with debug:
```
make debug
```
Then when you build OpenCore-Patcher.pkg, the debug version of the helper tool will be used.
### Security Considerations
When using the Privileged Helper Tool from source, you are now adding a security risk to your system. By disabling the code signature checks, any malicious application is given ability to execute code as root.
If possible, we highly recommend creating a developer account with Apple and signing the application with your own ["Developer ID Application" certificate](https://developer.apple.com/help/account/create-certificates/create-developer-id-certificates/). This will allow you to run the application without disabling code signature checks.
* Note that Dortania's Team ID will need to be replaced in main.m with your own Team ID (`S74BDJXQMD` -> `YOUR_TEAM`)
* Additionally you will be required to compile OpenCore-Patcher.app with your own Developer ID Application certificate
If this is not possible, we recommend using [OpenCore Legacy Patcher's prebuilt binaries](../../SOURCE.md) instead.

View File

@@ -0,0 +1,54 @@
#!/bin/zsh --no-rcs
# ------------------------------------------------------
# Privileged Helper Tool Installer
# ------------------------------------------------------
# Moves to expected destination and sets SUID bit.
# ------------------------------------------------------
# Developed for internal testing, end users should be
# using the PKG installer when released.
# ------------------------------------------------------
# MARK: Variables
# ---------------------------
helperName="com.dortania.opencore-legacy-patcher.privileged-helper"
helperPath="/Library/PrivilegedHelperTools/$helperName"
# MARK: Functions
# ---------------------------
function _setSUIDBit() {
local binaryPath=$1
# Check if path is a directory
if [[ -d $binaryPath ]]; then
/bin/chmod -R +s $binaryPath
else
/bin/chmod +s $binaryPath
fi
}
function _copyHelper() {
local sourcePath=$1
local destinationPath=$2
# Check if destination path exists
if [[ -e $destinationPath ]]; then
# Check if destination path is a directory
if [[ -d $destinationPath ]]; then
/bin/rm -rf $destinationPath
else
/bin/rm -f $destinationPath
fi
fi
# Copy source to destination
/bin/cp -R $sourcePath $destinationPath
}
# MARK: Main
# ---------------------------
_copyHelper "./$helperName" $helperPath
_setSUIDBit $helperPath

View File

@@ -0,0 +1,152 @@
/*
------------------------------------------------
OpenCore Legacy Patcher Privileged Helper Tool
------------------------------------------------
Designed as an alternative to an XPC service,
this tool is used to run commands as root.
------------------------------------------------
Server and client must have the same signing
certificate in order to run commands.
------------------------------------------------
*/
#import <Foundation/Foundation.h>
#import <Security/Security.h>
#include <libproc.h>
#define UTILITY_VERSION "1.0.0"
#define VALID_CLIENT_TEAM_ID @"S74BDJXQMD"
#define OCLP_PHT_ERROR_MISSING_ARGUMENTS 160
#define OCLP_PHT_ERROR_SET_UID_MISSING 161
#define OCLP_PHT_ERROR_SET_UID_FAILED 162
#define OCLP_PHT_ERROR_SELF_PATH_MISSING 163
#define OCLP_PHT_ERROR_PARENT_PATH_MISSING 164
#define OCLP_PHT_ERROR_SIGNING_INFORMATION_MISSING 165
#define OCLP_PHT_ERROR_INVALID_TEAM_ID 166
#define OCLP_PHT_ERROR_INVALID_CERTIFICATES 167
#define OCLP_PHT_ERROR_COMMAND_MISSING 168
#define OCLP_PHT_ERROR_COMMAND_FAILED 169
#define OCLP_PHT_ERROR_CATCH_ALL 170
NSDictionary *getSigningInformationFromPath(NSString *path) {
SecStaticCodeRef codeRef;
OSStatus status = SecStaticCodeCreateWithPath((__bridge CFURLRef)[NSURL fileURLWithPath:path], kSecCSDefaultFlags, &codeRef);
if (status != errSecSuccess) {
return nil;
}
CFDictionaryRef codeDict = NULL;
status = SecCodeCopySigningInformation(codeRef, kSecCSSigningInformation, &codeDict);
if (status != errSecSuccess) {
return nil;
}
return (__bridge NSDictionary *)codeDict;
}
NSString *getParentProcessPath() {
char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
if (proc_pidpath(getppid(), pathbuf, sizeof(pathbuf)) <= 0) {
return nil;
}
NSString *path = [NSString stringWithUTF8String:pathbuf];
return path;
}
NSString *getProcessPath() {
NSString *path = [[NSBundle mainBundle] executablePath];
return path;
}
BOOL isSBitSet(NSString *path) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *attributes = [fileManager attributesOfItemAtPath:path error:nil];
if (attributes == nil) {
return NO;
}
return (attributes.filePosixPermissions & S_ISUID) != 0;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
// We simply return if no arguments are passed
if (argc < 2) {
return OCLP_PHT_ERROR_MISSING_ARGUMENTS;
}
if (argc == 2 && (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-v") == 0)) {
printf("%s\n", UTILITY_VERSION);
return 0;
}
// Verify whether we can run as root
NSString *processPath = getProcessPath();
if (processPath == nil) {
return OCLP_PHT_ERROR_SELF_PATH_MISSING;
}
if (!isSBitSet(processPath)) {
return OCLP_PHT_ERROR_SET_UID_MISSING;
}
setuid(0);
if (getuid() != 0) {
return OCLP_PHT_ERROR_SET_UID_FAILED;
}
NSString *parentProcessPath = getParentProcessPath();
if (parentProcessPath == nil) {
return OCLP_PHT_ERROR_PARENT_PATH_MISSING;
}
NSDictionary *processSigningInformation = getSigningInformationFromPath(processPath);
NSDictionary *parentProcessSigningInformation = getSigningInformationFromPath(parentProcessPath);
if (processSigningInformation == nil || parentProcessSigningInformation == nil) {
return OCLP_PHT_ERROR_SIGNING_INFORMATION_MISSING;
}
#ifdef DEBUG
// Skip Team ID check in debug mode
// DO NOT USE IN PRODUCTION
#else
// Check Team ID
if (![processSigningInformation[@"teamid"] isEqualToString:VALID_CLIENT_TEAM_ID] || ![parentProcessSigningInformation[@"teamid"] isEqualToString:VALID_CLIENT_TEAM_ID]) {
return OCLP_PHT_ERROR_INVALID_TEAM_ID;
}
// Check Certificates
if (![processSigningInformation[@"certificates"] isEqualToArray:parentProcessSigningInformation[@"certificates"]]) {
return OCLP_PHT_ERROR_INVALID_CERTIFICATES;
}
#endif
NSString *command = nil;
NSArray *arguments = @[];
if (argc == 2) {
command = [NSString stringWithUTF8String:argv[1]];
} else {
command = [NSString stringWithUTF8String:argv[1]];
for (int i = 2; i < argc; i++) {
arguments = [arguments arrayByAddingObject:[NSString stringWithUTF8String:argv[i]]];
}
}
// Verify command exists
if (![[NSFileManager defaultManager] fileExistsAtPath:command]) {
return OCLP_PHT_ERROR_COMMAND_MISSING;
}
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:command];
[task setArguments:arguments];
[task launch];
[task waitUntilExit];
return [task terminationStatus];
}
return OCLP_PHT_ERROR_CATCH_ALL; // Should never reach here
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>OpenCore-Patcher</string>
<key>CFBundleExecutable</key>
<string>OpenCore-Patcher</string>
<key>CFBundleIconFile</key>
<string>AppIcon.icns</string>
<key>CFBundleIdentifier</key>
<string>com.dortania.opencore-legacy-patcher</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>OpenCore Legacy Patcher</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>LSMinimumSystemVersion</key>
<string>10.10.0</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2020-2024 Dortania</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSRequiresAquaSystemAppearance</key>
<false/>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
# OpenCore-Patcher Update Shim
To handle the new PKG installation method, old versions of OpenCore Legacy Patcher updating to newer versions will still require 'OpenCore-Patcher.app' to be available for download.
Thus the goal of this app is to install an embedded PKG under ./OpenCore-Patcher.app/Contents/Resources/OpenCore-Patcher.pkg to handle the update process.
Source is available at:
* https://github.com/dortania/OCLP-Helper

View File

@@ -1,57 +0,0 @@
# Copyright (C) 2022, Mykola Grymalyuk
# Within AppleMobileFileIntegrity.kext, Apple has a bitmask-based boot-arg (ex. amfi=128)
# Below information is from reversed values in 13.0 Beta 6's AppleMobileFileIntegrity.kext
# Currently only 'amfi=3' has been used by Apple publicly
# - 0x3 used in 11.0.1 dyld source:
# - https://github.com/apple-oss-distributions/dyld/blob/5c9192436bb195e7a8fe61f22a229ee3d30d8222/testing/test-cases/kernel-hello-world.dtest/main.c#L2
import enum
class AppleMobileFileIntegrity(enum.IntEnum):
# Names set are solely for readability
# Internal names are unknown
AMFI_ALLOW_TASK_FOR_PID: int = 0x1 # Allow Task for PID (alt. amfi_unrestrict_task_for_pid=0x1)
AMFI_ALLOW_INVALID_SIGNATURE: int = 0x2 # Reduce sig enforcement (alt. amfi_allow_any_signature=0x1)
AMFI_LV_ENFORCE_THIRD_PARTY: int = 0x4 # Don't mark external binaries as platform binaries
AMFI_UNKNOWN_1: int = 0x8
AMFI_UNKNOWN_2: int = 0x10
AMFI_UNKNOWN_3: int = 0x20
AMFI_UNKNOWN_4: int = 0x40
AMFI_ALLOW_EVERYTHING: int = 0x80 # Disable sig enforcement and Library Validation (alt. amfi_get_out_of_my_way=0x1)
# Internally within AMFI.kext, Apple references 0x2 and 0x80 as both 'Disable signature enforcement'
# However 0x80 is a higher privilege than 0x2, and breaks TCC support in OS (ex. Camera, Microphone, etc prompts)
# Supported boot-args within AMFI.kext, last compared against 13.0 Beta 6
#
# Within _initializeAppleMobileFileIntegrity():
# - amfi_unrestrict_task_for_pid=0x1
# - amfi_dev_mode_policy=0x1
# - amfi_allow_any_signature=0x1
# - amfi_get_out_of_my_way=0x1
# - amfi_unrestricted_local_signing=0x1
# - pmap_cs_unrestricted_local_signing=0x1
# - amfi_ready_to_roll=0x1
# - cs_enforcement_disable=0x1
#
# Within AMFIInitializeLocalSigningPublicKey():
# - -restore
#
# Within macOSPolicyConfigurationInit():
# - amfi_force_policy=0x1
# - amfi_block_unsigned_code=0x1
# - amfi_force_cs_kill=0x1
# - amfi_hsp_disable=0x1
# - amfi_hsp_logging=0x1
# - amfi_allow_bni_as_platform=0x1
# - amfi_allow_non_platform=0x1
# - amfi_prevent_old_entitled_platform_binaries=0x1
# - amfi_allow_only_tc=0x1
# - amfi_allow_only_tc_override=0x1
#
# Within configurationSettingsInit()
# - amfi_enforce_launch_constraints=0x1
# - amfi_allow_3p_launch_constraints=0x1
# - BATS_TESTPLAN_ID="Custom Team ID"

View File

@@ -46,7 +46,7 @@ Metal is Apple's in-house graphics API that acts as a replacement for OpenGL/Ope
By default with the non-Metal acceleration patches, many background blur menus may act distorted when moving a cursor over it. With 0.4.1 and newer, users can enable a new Beta Blur feature to try and resolve the issue:
![](../images/OCLP-GUI-Settings-Beta-Blur.png)
![](./images/OCLP-GUI-Settings-Beta-Blur.png)
Do note that enabling beta blurs can be more demanding on slower hardware
## Downloading older non-Metal Apps
@@ -70,7 +70,7 @@ This issue is fully resolved for 13.2.1 and lower starting from 0.2.5.
::: details Workaround for 0.2.4, Ventura 13.3+
Due to the usage of amfi_get_out_of_my_way=1, macOS will fail to prompt users for special permissions upon application start as well as omit the entires in System Preferences. To work around this, we recommend users install tccplus to manage permissions.
Due to the usage of amfi_get_out_of_my_way=1, macOS will fail to prompt users for special permissions upon application start as well as omit the entries in System Preferences. To work around this, we recommend users install tccplus to manage permissions.
[Download TCCPlus](https://github.com/jslegendre/tccplus)
@@ -190,7 +190,7 @@ A somewhat strange issue on Intel HD3000-based Macs, on 3rd party displays somet
| Default Color Profile | Display/Display P3 Profile |
| :--- | :--- |
| ![](../images/HD3000-Default-Colors.png) | ![](../images/HD3000-Display-Colors.png) |
| ![](./images/HD3000-Default-Colors.png) | ![](./images/HD3000-Display-Colors.png) |
## Cannot Pair Bluetooth Devices

View File

@@ -6,7 +6,7 @@ Reboot the machine while holding `Option` to select the EFI Boot entry with the
* This will be the Mac Boot Picker
![](../images/efi-boot.png)
![](./images/efi-boot.png)
::: details Note for Mac Pros/Xserves/iMacs with unflashed GPUs
@@ -27,7 +27,7 @@ Now you'll want to get a list of drive identifiers. To do so, run the following
diskutil list
```
The command should produce a list of drives installed in your system:
![](../images/Unflashed-Boot-1.png)
![](./images/Unflashed-Boot-1.png)
Keep track of the drive with the OCLP install. You will need the drive identifer for later.
@@ -37,7 +37,7 @@ Run the following command (Replace X with the drive number):
```sh
diskutil mount diskXs1
```
![](../images/Unflashed-Boot-2.png)
![](./images/Unflashed-Boot-2.png)
If everything is correct, the EFI partion should be mounted.
Now you'll want to use the `bless` command to set the default boot device:
@@ -45,7 +45,7 @@ Now you'll want to use the `bless` command to set the default boot device:
bless --mount /Volumes/EFI --setBoot --file /Volumes/EFI/System/Library/CoreServices/boot.efi
```
Once the command is run, it should produce no output.
![](../images/Unflashed-Boot-3.png)
![](./images/Unflashed-Boot-3.png)
If the command produces an output, ensure that you've typed it in correctly.
@@ -56,7 +56,7 @@ Now that you've loaded OpenCore, "select Install macOS":
* This will be the OpenCore Picker
![](../images/oc-boot.png)
![](./images/oc-boot.png)
You will soon reach the installer screen! If you enabled verbose mode when building OCLP, a lot of text will run across the screen. From there, it's just like any normal macOS install. For an example of how the boot process looks, see the following video:
@@ -64,7 +64,7 @@ You will soon reach the installer screen! If you enabled verbose mode when build
If your Mac is looping back into the beginning of the setup after the first reboot, turn it off, start it again and hold `Option`. This time, select the option with a grey hard disk icon, it can say "macOS Installer" or the name you gave the disk during the installer process. Keep repeating this step after every reboot if necessary.
![](../images/oclp-stuck-firstreboot.png)
![](./images/oclp-stuck-firstreboot.png)
::: warning

View File

@@ -8,7 +8,7 @@ If you haven't downloaded OpenCore Patcher yet, do so now:
Next, run the `OpenCore-Patcher.app`:
![](../images/OCLP-GUI-Main-Menu.png)
![](./images/OCLP-GUI-Main-Menu.png)
::: warning
OpenCore configurations are hardware specific.
@@ -19,7 +19,7 @@ Here we'll select Build and Install OpenCore and start building:
| Start Building | Finished Building |
| :--- | :--- |
| ![](../images/OCLP-GUI-Build-Start.png) | ![OCLP GUI Build Finished](../images/OCLP-GUI-Build-Finished.png) |
| ![](./images/OCLP-GUI-Build-Start.png) | ![OCLP GUI Build Finished](./images/OCLP-GUI-Build-Finished.png) |
Once it finishes building, you'll want to select the Install OpenCore button:
@@ -28,6 +28,6 @@ Once it finishes building, you'll want to select the Install OpenCore button:
| Select Drive | Select Partition |
| :--- | :--- |
| ![](../images/OCLP-GUI-EFI-Select-Disk.png) | ![](../images/OCLP-GUI-EFI-Select-Partition.png) |
| ![](./images/OCLP-GUI-EFI-Select-Disk.png) | ![](./images/OCLP-GUI-EFI-Select-Partition.png) |
# Once finished, head to [Booting OpenCore and macOS](./BOOT.md)

View File

@@ -10,7 +10,7 @@ The easiest way to debug yourself is via Patcher Settings. Here there are many d
* "Enable OpenCore DEBUG"
* "Enable Kext DEBUG"
![](../images/ocdebugimage.png)
![](./images/ocdebugimage.png)
When you've enabled these 3 options, rebuild OpenCore and install to your drive. This will provide much greater debug information as well as write logs to the EFI Partition.
@@ -18,11 +18,11 @@ When you've enabled these 3 options, rebuild OpenCore and install to your drive.
With "Enable OpenCore DEBUG" set, on every boot there will be a .txt file generated on the EFI Partition. To grab these logs, [download and run MountEFI](https://github.com/corpnewt/MountEFI):
![](../images/mountefi.png)
![](./images/mountefi.png)
Once you've mounted the EFI Partition of the drive you have macOS on, you should see some nice logs:
![](../images/logs-efi.png)
![](./images/logs-efi.png)
## Obtaining Kernel logs from macOS

View File

@@ -1,18 +1,7 @@
# Supporting the patcher
OpenCore Legacy Patcher is a hobby project for us developers, and while we love helping out the community, it's very difficult for us to troubleshoot issues remotely. The best way for us to get to work on the patcher, fix issues and add enhancements is having the hardware in-hand. As a hobby project, neither of the main developers can afford to buy every legacy Mac to test on.
We have opened OpenCollective in order to manage donations as well as be transparent about where the donated money is going. If you want to support the patcher with money donation, you can do so below.
The best way to support us in all honesty is to donate any old hardware you no longer need, as this allows us to have machines to test locally and push fixes much faster. While we appreciate cash donations, this makes it much more difficult for us to handle as an organization.
[OpenCollective](https://opencollective.com/opencore-legacy-patcher)
Main sections of help we'd appreciate:
* Donating any Mac you own
* Does require SSE4,1 CPU to test on Sierra and newer however
Additionally, hardware info dumps are greatly beneficial for us to determine what patches a machine might need:
* [IORegistryExplorer](https://github.com/khronokernel/IORegistryClone/blob/master/ioreg-210.zip?raw=true)
* `File -> SaveAs` and open an issue on Github
* Note: We want IOReg dumps of hardware not running on OpenCore, instead running a clean, officially supported OS by the machine
If you have any legacy hardware you're willing to donate or want to buy us hardware, please reach out on our Discord server.
If you wish, you can also donate legacy hardware you don't need anymore as long as it makes sense logistically. In this case, reach out on the Discord server.

View File

@@ -6,4 +6,4 @@ OpenCore Legacy Patcher itself is actually quite a "dumb" program. It essentiall
To understand a bit more of how OpenCore is able to revive older Macs in such a native-like way, we need to go over *how* OpenCore works with your Mac:
![](../images/oc-explained.png)
![](./images/oc-explained.png)

View File

@@ -27,12 +27,12 @@ To generate custom OpenCore icons, you'll need the following:
* ResetNVRAM — Reset NVRAM system action or tool (128x128).
* Shell — Entry with UEFI Shell name for e.g. OpenShell (128x128).
* Tool — Any other tool (128x128).
Note, for each image we recommend having one of double the size. This ensures that icons are scaled correctly since .icns support dedicated images depending on HiDPI or not.
Once you have a custom image you want to use(for example, as a background), download the [latest release of OpenCorePkg](https://github.com/acidanthera/OpenCorePkg/releases) and enter the `Utilities/icnspack/` folder:
![](../images/icnspack-folder.png)
![](./images/icnspack-folder.png)
Now `cd` to this folder in terminal and run the following:
@@ -42,7 +42,7 @@ Now `cd` to this folder in terminal and run the following:
Once done, you'll see your custom icon generated in `icnspack`'s folder:
![](../images/icnspack-done.png)
![](./images/icnspack-done.png)
# Custom Mac Boot Picker icons
@@ -59,15 +59,15 @@ To generate legacy icons, you'll need the following:
Head to [developer.apple's More Downloads page](https://developer.apple.com/download/more/) and search for `Graphics Tools` that is supported by your OS(note for 10.6 and older, the app is hidden inside `Developer Tools`):
![](../images/graphics-download.png)
![](./images/graphics-download.png)
Once downloaded, open the disk image and you'll find Icon Composer.app:
![Graphics Open](../images/graphics-open.png)
![Graphics Open](./images/graphics-open.png)
Now run the app and simply drag the images to each section as so:
![](../images/icon-SL.png)
![](./images/icon-SL.png)
Now save and export the new icns file.
@@ -79,7 +79,7 @@ To install, please ensure that Vault was disabled when you built OpenCore. If yo
Now that you've verified that you can edit OpenCore safely, you'll need to mount the drive that OpenCore is stored on. To do this, download [MountEFI](https://github.com/corpnewt/MountEFI) and run it:
![](../images/mountefi.png)
![](./images/mountefi.png)
Select the drive you installed OpenCore to and mount it.
@@ -90,7 +90,7 @@ Select the drive you installed OpenCore to and mount it.
Head to `EFI/OC/Resources/Image/` on your drive and you'll see all the custom icons. For Background.icns, we need to ensure the file matches the theme OpenCore has set so we add the prefix `Modern` to it:
![](../images/background-moved.png)
![](./images/background-moved.png)
Now reboot and you should see your updated icon(s)!
@@ -98,6 +98,6 @@ Now reboot and you should see your updated icon(s)!
Updating the Mac Boot Picker icons is actually quite simple. On the root of your drive, simply drop the icon into the root of the drive with the name `.VolumeIcon.icns`
![](../images/mac-icns-drive.png)
![](./images/mac-icns-drive.png)
Now reboot and you'll see the new icon!

View File

@@ -14,25 +14,25 @@ For this guide, we'll be using the standard OpenCore-Patcher (GUI).
Once downloaded, open the app and you should be greeted by this menu:
![OCLP GUI Main Menu](../images/OCLP-GUI-Main-Menu.png)
![OCLP GUI Main Menu](./images/OCLP-GUI-Main-Menu.png)
First, we'll want to select the "Create macOS Installer" button. This will present you with 2 options:
![](../images/OCLP-GUI-Create-Installer-Menu.png)
![](./images/OCLP-GUI-Create-Installer-Menu.png)
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:
| Downloading | Listed Installers | Unsupported Installer |
| :--- | :--- | :--- |
| ![OCLP GUI Installer Download Catalog](../images/OCLP-GUI-Installer-Download-Catalog.png) | ![OCLP GUI Installer Download Listed Products](../images/OCLP-GUI-Installer-Download-Listed-Products.png) | ![](../images/OCLP-GUI-Installer-Download-Unsupported.png)
| ![OCLP GUI Installer Download Catalog](./images/OCLP-GUI-Installer-Download-Catalog.png) | ![OCLP GUI Installer Download Listed Products](./images/OCLP-GUI-Installer-Download-Listed-Products.png) | ![](./images/OCLP-GUI-Installer-Download-Unsupported.png)
Since the patcher officially supports Big Sur and newer for patching, only those entires will be shown. For ourselves, we'll select macOS 12 as that's the latest public release at the time of writing. This will download and install the macOS installer to your applications folder.
Since the patcher officially supports Big Sur and newer for patching, only those entries will be shown. For ourselves, we'll select macOS 12 as that's the latest public release at the time of writing. This will download and install the macOS installer to your applications folder.
* Note that some machines (namely 2012 and older) may not be currently supported on macOS Ventura. If you see this prompt, you'll need to use an older version of macOS.
| Downloading the Installer | Requesting to install | Finished Installing |
| :--- | :--- | :--- |
| ![OCLP GUI Installer Download Progress](../images/OCLP-GUI-Installer-Download-Progress.png) | ![OCLP GUI Installer Needs Installing](../images/OCLP-GUI-Installer-Needs-Installing.png) | ![OCLP GUI Installer Download Finished](../images/OCLP-GUI-Installer-Download-Finished.png) |
| ![OCLP GUI Installer Download Progress](./images/OCLP-GUI-Installer-Download-Progress.png) | ![OCLP GUI Installer Needs Installing](./images/OCLP-GUI-Installer-Needs-Installing.png) | ![OCLP GUI Installer Download Finished](./images/OCLP-GUI-Installer-Download-Finished.png) |
Once finished, you can proceed to write the installer onto a USB drive.
@@ -40,12 +40,12 @@ Once finished, you can proceed to write the installer onto a USB drive.
| Select Downloaded Installer | Select disk to format |
| :--- | :--- |
| ![](../images/OCLP-GUI-Installer-Select-Local-Installer.png) | ![](../images/OCLP-GUI-Installer-Format-USB.png) |
| ![](./images/OCLP-GUI-Installer-Select-Local-Installer.png) | ![](./images/OCLP-GUI-Installer-Format-USB.png) |
Now the patcher will start the installer flashing!
| Flashing | Success Prompt | Finished Flashing |
| :--- | :--- |
| ![](../images/OCLP-GUI-Installer-Flashing-Process.png) | ![](../images/OCLP-GUI-Installer-Sucess-Prompt.png) | ![](../images/OCLP-GUI-Installer-Finished-Script.png) |
| ![](./images/OCLP-GUI-Installer-Flashing-Process.png) | ![](./images/OCLP-GUI-Installer-Sucess-Prompt.png) | ![](./images/OCLP-GUI-Installer-Finished-Script.png) |
# Once finished, head to [Building and installing OpenCore](./BUILD.md)

View File

@@ -58,9 +58,9 @@ The patcher is designed to target **macOS Big Sur 11.x to macOS Sonoma 14.x**.
| Model Name | Identifier | Tagged Issues |
| :--- | :--- | :--- |
| MacBook Pro (15-inch, Early 2008)<br>MacBook Pro (17-inch, Early 2008) | `MacBookPro4,1` | - [non-Metal GPU (macOS 11+)](https://github.com/dortania/OpenCore-Legacy-Patcher/issues/108)<br>- [USB 1.1 (macOS 13+)](https://github.com/dortania/OpenCore-Legacy-Patcher/issues/1021)|
| MacBook Pro (15-inch, Late 2008) | `MacBookPro5,1` | ^^ |
| MacBook Pro (15-inch, Late 2008)<br>MacBook Pro (15-inch, Early 2009) | `MacBookPro5,1` | ^^ |
| MacBook Pro (17-inch, Early 2009)<br>MacBook Pro (17-inch, Mid 2009) | `MacBookPro5,2` | ^^ |
| MacBook Pro (15-inch, Mid 2009) | `MacBookPro5,3` | ^^ |
| MacBook Pro (15-inch, Mid 2009) | `MacBookPro5,3`<br>`MacBookPro5,4` | ^^ |
| MacBook Pro (13-inch, Mid 2009) | `MacBookPro5,5` | ^^ |
| MacBook Pro (17-inch, Mid 2010) | `MacBookPro6,1` | - [non-Metal GPU (macOS 11+)](https://github.com/dortania/OpenCore-Legacy-Patcher/issues/108) |
| MacBook Pro (15-inch, Mid 2010) | `MacBookPro6,2` | ^^ |

View File

@@ -1,4 +1,4 @@
![](../images/macos-monterey.png)
![](./images/macos-monterey.png)
With OpenCore Legacy Patcher v0.1.7 and newer, we've implemented beta macOS Monterey support for users. Please note that Apple has dropped a lot of hardware with this release as well as broken many of our previous patch sets. This page will be used to inform users regarding current issues and will be updated as new patch sets are developed and added to our patcher.

View File

@@ -20,7 +20,7 @@ And voila! No more USB drive required.
To do this, run the OpenCore Patcher and head to Patcher Settings, then uncheck "Show OpenCore Bootpicker" on the Build tab:
![](../images/OCLP-GUI-Settings-ShowPicker.png)
![](./images/OCLP-GUI-Settings-ShowPicker.png)
Once you've toggled it off, build your OpenCore EFI once again and install to your desired drive. Now to show the OpenCore selector, you can simply hold down the "ESC" key while clicking on EFI boot, and then you can release the "ESC" key when you see the cursor arrow at the top left.
@@ -34,7 +34,7 @@ Going forward with 0.6.6, SIP settings can be accessed from the Security tab sho
| SIP Enabled | SIP Lowered (Root Patching) | SIP Disabled |
| :--- | :--- | :--- |
| ![](../images/OCLP-GUI-Settings-SIP-Enabled.png) | ![](../images/OCLP-GUI-Settings-SIP-Root-Patch.png) | ![](../images/OCLP-GUI-Settings-SIP-Disabled.png) |
| ![](./images/OCLP-GUI-Settings-SIP-Enabled.png) | ![](./images/OCLP-GUI-Settings-SIP-Root-Patch.png) | ![](./images/OCLP-GUI-Settings-SIP-Disabled.png) |
:::warning
@@ -44,9 +44,9 @@ If you're unsure whether you should enable SIP, leave it as-is. Systems where yo
## Applying Post Install Volume Patches
:::warning
:::warning
If you need to use Migration Assistant to bring over data to your new macOS install, it is **highly recommended** to avoid restoring from inside Setup Assistant and waiting to install root patches until after the transfer is complete. If root patches were automatically installed, you can use the options available in the OCLP app to remove them.
If you need to use Migration Assistant to bring over data to your new macOS install, it is **highly recommended** to avoid restoring from inside Setup Assistant and waiting to install root patches until after the transfer is complete. If root patches were automatically installed, you can use the options available in the OCLP app to remove them.
Using Migration Assistant while patches are installed can lead to an unbootable system, requiring a reinstall of macOS.
@@ -60,7 +60,7 @@ Users can also see whether applicable patches have been installed, date and vers
| Automatic install prompt | Status |
| :--- | :--- |
| ![](../images/OCLP-GUI-root-patch-update.png) | ![](../images/OCLP-GUI-Root-Patch-Status.png) |
| ![](./images/OCLP-GUI-root-patch-update.png) | ![](./images/OCLP-GUI-Root-Patch-Status.png) |
@@ -72,7 +72,7 @@ There is also an option to remove root patches, which may be required in some si
| Listing Patches | Patching Finished |
| :--- | :--- |
| ![](../images/OCLP-GUI-Root-Patch.png) | ![](../images/OCLP-GUI-Root-Patch-Finished.png) |
| ![](./images/OCLP-GUI-Root-Patch.png) | ![](./images/OCLP-GUI-Root-Patch-Finished.png) |
:::warning

View File

@@ -10,8 +10,8 @@ meta:
content: Experience macOS just like before
features:
- title: Built with security in mind
details: Supporting System Integrity Protection(SIP), FileVault 2, .im4m Secure Boot and Vaulting. For many machines, you're just as secure as a supported Mac.
# - title: Built with security in mind
# details: Supporting System Integrity Protection(SIP), FileVault 2, .im4m Secure Boot and Vaulting. We make an effort to ensure your system is as secure as possible.
- title: Native OTA updates
details: Install updates the moment they come out, with native System Preferences support, just like a supported Mac.
- title: Zero firmware patching
@@ -22,5 +22,5 @@ features:
details: Unlock Sidecar, AirPlay to Mac, Night Shift, and Universal Control, even on natively supported models!
- title: A helpful community
details: Whether it's getting started or learning the specifics, you can always find answers with our amazing community of tinkerers, developers, and dreamers.
footer: Copyright © Dortania 2020-2022
footer: Copyright © Dortania 2020-2024
---

View File

@@ -1,4 +1,4 @@
![](../images/sonoma.png)
![](./images/sonoma.png)
*Well here we are again, it's always such a pleasure~*
@@ -71,7 +71,7 @@ While USB 1.1 may seem unimportant, it handles many important devices on your sy
With OpenCore Legacy Patcher v0.6.0+, basic support has been implemented via Root Volume patching. However due to this, users will need to use a USB hub for installation and post-OS updates when patches are cleaned:
![](../images/usb11-chart.png)
![](./images/usb11-chart.png)
::: warning The following systems rely on USB 1.1

View File

@@ -40,7 +40,7 @@ However, if the 🚫 Symbol only appears after the boot process has already star
## Cannot boot macOS without the USB
By default, the OpenCore Patcher won't install OpenCore onto the internal drive itself during installs.
By default, the OpenCore Patcher won't install OpenCore onto the internal drive itself during installs.
After installing macOS, OpenCore Legacy Patcher should automatically prompt you to install OpenCore onto the internal drive. However, if it doesn't show the prompt, you'll need to either [manually transfer](https://dortania.github.io/OpenCore-Post-Install/universal/oc2hdd.html) OpenCore to the internal drive's EFI or Build and Install again and select your internal drive.
@@ -66,13 +66,17 @@ Then revert the snapshot
```sh
bless --mount "/Volumes/Macintosh HD" --bootefi --last-sealed-snapshot
```
After that, type the following
```sh
cd "/Volumes/Macintosh HD/Library/Extensions" && ls
```
You should now see bunch of .kexts. If you only see .kexts starting with "HighPoint" and "SoftRAID", you can ignore this and just restart the system. If other kexts are found, continue.
Now we're going to clean the /Library/Extensions folder from offending kexts while keeping needed ones.
Delete everything **except** for the ones that start with HighPoint and SoftRAID, by using `rm -rf "kextname"`
Run the following and **make sure to type it carefully**
::: warning
If you have **FileVault 2 enabled**, you will need to mount the Data volume first. This can be done in Disk Utility by locating your macOS volume name, selecting its Data volume, and selecting the Mount option in the toolbar.
:::
```sh
cd "/Volumes/Macintosh HD - Data/Library/Extensions" && ls | grep -v "HighPoint*\|SoftRAID*" | xargs rm -rf
```
Then restart and now your system should be restored to the unpatched snapshot and should be able to boot again.
@@ -112,7 +116,7 @@ To work-around this, we recommend that users manually connect using the "Other"
## No Graphics Acceleration
In macOS, GPU drivers are often dropped from the OS with each major release of it. With macOS Big Sur, currently, all non-Metal GPUs require additional patches to gain acceleration. In addition, macOS Monterey removed Graphics Drivers for both Intel Ivy Bridge and NVIDIA Kepler graphics processors.
In macOS, GPU drivers are often dropped from the OS with each major release of it. With macOS Big Sur, currently, all non-Metal GPUs require additional patches to gain acceleration. In addition, macOS Monterey removed Graphics Drivers for both Intel Ivy Bridge and NVIDIA Kepler graphics processors.
If you're using OCLP v0.4.4, you should have been prompted to install Root Volume patches after the first boot from installation of macOS. If you need to do this manually, you can do so within the patcher app. Once rebooted, acceleration will be re-enabled as well as brightness control for laptops.
@@ -126,14 +130,14 @@ Due to Apple dropping NVIDIA Kepler support in macOS Monterey, [MacBookPro11,3's
If you're having trouble with DisplayPort output on Mac Pros, try enabling Minimal Spoofing in Settings -> SMBIOS Settings and rebuild/install OpenCore. This will trick macOS drivers into thinking you have a newer MacPro7,1 and resolve the issue.
![](../images/OCLP-GUI-SMBIOS-Minimal.png)
![](./images/OCLP-GUI-SMBIOS-Minimal.png)
## Volume Hash Mismatch Error in macOS Monterey
A semi-common popup some users face is the "Volume Hash Mismatch" error:
<p align="center">
<img src="../images/Hash-Mismatch.png">
<img src="./images/Hash-Mismatch.png">
</p>
What this error signifies is that the OS detects that the boot volume's hash does not match what the OS is expecting, this error is generally cosmetic and can be ignored. However if your system starts to crash spontaneously shortly after, you'll want to reinstall macOS fresh without importing any data at first.
@@ -150,7 +154,7 @@ Head into the GUI, go to Patcher Settings, and toggle the bits you need disabled
| SIP Enabled | SIP Lowered (Root Patching) | SIP Disabled |
| :--- | :--- | :--- |
| ![](../images/OCLP-GUI-Settings-SIP-Enabled.png) | ![](../images/OCLP-GUI-Settings-SIP-Root-Patch.png) | ![](../images/OCLP-GUI-Settings-SIP-Disabled.png) |
| ![](./images/OCLP-GUI-Settings-SIP-Enabled.png) | ![](./images/OCLP-GUI-Settings-SIP-Root-Patch.png) | ![](./images/OCLP-GUI-Settings-SIP-Disabled.png) |
## Intermediate issues with USB 1.1 and Bluetooth on MacPro3,1 - MacPro5,1
@@ -199,4 +203,4 @@ Applicable models include:
| Mac Pro | Mid 2010 and older | MacPro3,1 - MacPro5,1 | |
![](../images/usb11-chart.png)
![](./images/usb11-chart.png)

View File

@@ -13,9 +13,9 @@
:::warning
Note that after you remove OpenCore, your Mac will no longer boot and show the "prohibited" symbol. Be ready to install an natively-supported version of macOS before you uninstall OpenCore.
Note that after you remove OpenCore, your Mac will no longer boot and show the "prohibited" symbol. Be ready to install a natively-supported version of macOS before you uninstall OpenCore.
* This does not apply to native Macs just using OpenCore to achieve features like AirPlay to Mac and Sidecar, but it is still recommended to reinstall macOS after removing OpenCore, if using SMBIOS spoofing to enable Univeral Control.
* This does not apply to native Macs just using OpenCore to achieve features like AirPlay to Mac and Sidecar, but it is still recommended to reinstall macOS after removing OpenCore, if using SMBIOS spoofing to enable Universal Control and other features.
:::
## Uninstalling the application

View File

@@ -12,7 +12,7 @@ If you meet all the requirements, in most cases you can go to Display Preference
| Display Preferences | Universal Control settings |
| :--- | :--- |
| ![](../images/UC-enable-1.png) | ![OCLP GUI Build Finished](../images/UC-enable-2.png) |
| ![](./images/UC-enable-1.png) | ![OCLP GUI Build Finished](./images/UC-enable-2.png) |
Most Mac models from 2011 and above should work out of the box. However, older Macs like the 2008-2011 MacBook Pros require upgrading the Wi-Fi/Bluetooth card to a newer model. More info in the [requirements section.](#requirements-for-universal-control)
@@ -183,7 +183,7 @@ The following models are blacklisted from using Universal Control by Apple:
- Macmini7,x - Mac mini 2014
- MacPro6,x - Mac Pro Late 2013
The hardware in these models are capable of supporting Universal Control, but due to blacklisting, the only solution to use Universal Control on these models is to spoof their SMBIOS. SMBIOS spoofing essentially fools some aspects of macOS to think they are running on a different machine.
The hardware in these models are capable of supporting Universal Control, but due to blacklisting, the only solution to use Universal Control on these models is to spoof their SMBIOS. SMBIOS spoofing essentially fools some aspects of macOS to think they are running on a different machine.
With SMBIOS Spoofing, the Universal Control handshake recognizes a different SMBIOS and thus grants a blacklisted Mac to connect to other Macs and iPads with Universal Control.
@@ -206,7 +206,7 @@ Ventura has dropped more models which includes all of the blacklisted Macs in qu
::: details macOS Sonoma
Firstly run OpenCore Legacy Patcher.
Firstly run OpenCore Legacy Patcher.
Then go to **Settings** and **SMBIOS** tab, set SMBIOS Spoof Level to **Moderate**. Set SMBIOS Spoof Model **one listed next to your native model in the table for spoofed models below.**
@@ -214,7 +214,7 @@ Notice that "Allow native models" and "Allow Native Spoofs" **are NOT** enabled
| Main Settings view | SMBIOS settings |
| :--- | :--- |
| ![](../images/ventura_uc1.png) | ![](../images/ventura_uc2.png) |
| ![](./images/ventura_uc1.png) | ![](./images/ventura_uc2.png) |
@@ -238,7 +238,7 @@ Spoofing to any model with native Sonoma support should work, but these are the
::: details macOS Ventura
Firstly run OpenCore Legacy Patcher.
Firstly run OpenCore Legacy Patcher.
Then go to **Settings** and **SMBIOS** tab, set SMBIOS Spoof Level to **Moderate**. Set SMBIOS Spoof Model **one listed next to your native model in the table for spoofed models below.**
@@ -246,7 +246,7 @@ Notice that "Allow native models" and "Allow Native Spoofs" **are NOT** enabled
| Main Settings view | SMBIOS settings |
| :--- | :--- |
| ![](../images/ventura_uc1.png) | ![](../images/ventura_uc2.png) |
| ![](./images/ventura_uc1.png) | ![](./images/ventura_uc2.png) |
@@ -272,14 +272,14 @@ Spoofing to any model with native Ventura support should work, but these are the
Firstly, run OpenCore Legacy Patcher. Secondly, go to **Settings** then the **App** tab and tick **Allow native models**.
[](../images/OCLP-App-Allow-Native-Models.png)
[](./images/OCLP-App-Allow-Native-Models.png)
Then, go to **SMBIOS** tab, tick **Allow spoofing native Macs**, set SMBIOS Spoof Level to **Moderate**. Set SMBIOS Spoof Model to **one listed next to your native model in the table for spoofed models below.**
| Main Settings view | SMBIOS settings |
| :--- | :--- |
| ![](../images/OCLP-SMBIOS-Allow-Native-Spoof.png) | ![](../images/OCLP-smbios-settings.png) |
| ![](./images/OCLP-SMBIOS-Allow-Native-Spoof.png) | ![](./images/OCLP-smbios-settings.png) |
::: details Table for spoofed models (click to expand)

View File

@@ -1,10 +1,10 @@
# Updating OpenCore and Patches
With OpenCore Legacy Patcher, there's generally very little reason for users to update the OpenCore installation on their machine unless you feel there's a benefit with new versions for your setup, e.g. Bluetooth has stopped working with a new macOS update.
With OpenCore Legacy Patcher, there's generally very little reason for users to update the OpenCore installation on their machine unless you feel there's a benefit with new versions for your setup, e.g. Bluetooth has stopped working with a new macOS update.
For those who do wish to update, simply [download the latest release](https://github.com/dortania/OpenCore-Legacy-Patcher/releases) and rerun the patcher:
![](../images/OCLP-GUI-Main-Menu.png)
![](./images/OCLP-GUI-Main-Menu.png)
Then, rebuild your OpenCore build and install again. OpenCore Will now be updated!
@@ -17,6 +17,6 @@ nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:opencore-version
nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:OCLP-Version
```
![](../images/oclp-version.png)
![](./images/oclp-version.png)
From this, we can see that we're running a RELEASE version of OpenCore 0.8.0 built on April 18th, 2022 with Patcher Version 0.4.5!

View File

@@ -1,4 +1,4 @@
![](../images/ventura.png)
![](./images/ventura.png)
With the release of OpenCore Legacy Patcher v0.5.0 and newer, early support for macOS Ventura has been implemented for most Metal-capable Macs. This page will be used to inform users regarding current issues and will be updated as new patch sets are developed and added to our patcher.
@@ -24,7 +24,7 @@ Ventura's release dropped a large amount of Intel hardware, thus requiring the u
## Current status
<img width="625" alt="" src="../images/OCLP-060-Initial-Support.png">
<img width="625" alt="" src="./images/OCLP-060-Initial-Support.png">
For older hardware, see below sections:
@@ -64,7 +64,7 @@ For Penryn systems and pre-2013 Mac Pros, USB 1.1 support was outright removed i
With OpenCore Legacy Patcher v0.6.0, basic support has been implemented via Root Volume patching. However due to this, users will need to use a USB hub for installation and post-OS updates when patches are cleaned:
![](../images/usb11-chart.png)
![](./images/usb11-chart.png)
::: warning The following systems rely on USB 1.1

View File

@@ -32,13 +32,13 @@ The following is required for installation:
Open Disk Utility in macOS and format the USB Drive as ExFat with the Master Boot Record scheme:
![](../images/windows-mbr-format.png)
![](./images/windows-mbr-format.png)
### Formatting the Target Drive
Next, select the drive you wish to install Windows in Disk Utility on and partition it as ExFat (If formatting the entire drive, ensure it's using the GUID Partition Table scheme):
![](../images/windows-partition-1.png)
![](./images/windows-partition-1.png)
:::warning
@@ -55,7 +55,7 @@ Recommended size is 200MB and the partition format **must** be FAT32 for OpenCor
* Note 2: Having different partitions for OpenCore is not required if the Windows boot files detected by the stock Bootpicker are removed. See "Removing the Windows option from the stock bootpicker" for further information.
* Note 3: We recommend uninstalling OpenCore from the ESP/EFI Partition when you create this new OpenCore partition to avoid confusion when selecting OpenCore builds in the Mac's boot picker.
![](../images/windows-partition-2.png)
![](./images/windows-partition-2.png)
## Creating the Windows Installer
@@ -67,7 +67,7 @@ The latest Windows installation images can be downloaded from Microsoft using th
Once the file is downloaded, mount the .iso image:
![](../images/windows-iso.png)
![](./images/windows-iso.png)
Then open terminal and use the `rsync` command with the disk image set as the source and your USB drive set as the target. (Replace "CCCOMA_X64" with the mounted image's partition name, and replace "InstallWin10" with your USB Drive's name).
@@ -75,11 +75,11 @@ Then open terminal and use the `rsync` command with the disk image set as the so
rsync -r -P /Volumes/CCCOMA_X64/ /Volumes/InstallWin10
```
![](../images/rsync-progess.png)
![](./images/rsync-progess.png)
The `rsync` command will take some time, so get some coffee and sit back. Once finished, the root of the USB drive should look as follows:
![](../images/windows-rsync-done.png)
![](./images/windows-rsync-done.png)
* Ensure that these folders and files are in the root of the USB drive, otherwise the USB will not boot.
@@ -113,31 +113,31 @@ Once booted into the Windows installer, proceed as you normally would until you
When you are prompted to select a drive, select your desired partition and delete it using "Delete". If you want to install Windows to an empty drive, erase every partition currently on the desired drive.
After your drive/partition is erased, press "New" to create the Windows system partitions.
![](../images/DISM-1.png)
![](./images/DISM-1.png)
You will be prompted to confirm the creation of the system partitions, press "OK".
![](../images/DISM-2.png)
![](./images/DISM-2.png)
Once the partitions are created, select the main (largest) partition and press "Format". This will format the partition using the NFTS file system.
![](../images/DISM-3.png)
![](./images/DISM-3.png)
After the installer formats the partition, open up the Command Prompt by pressing SHIFT + F10. Then run the `diskpart` command, and `list vol`. This will produce a list of volumes in your system, make sure to keep track of the drive letters of the main Windows partition (largest, NTFS), the EFI partition (100MB, FAT32), and the Windows installer (Usually Drive D). Run `exit` to close diskpart
![](../images/DISM-4.png)
![](./images/DISM-4.png)
Now, get a list of available Windows editions by running `dism /Get-WimInfo /WimFile:D:\Sources\install.wim` (substituting D with the Installer Drive Letter). This guide will use Option 6 for Windows 10 Pro.
![](../images/DISM-5.png)
![](./images/DISM-5.png)
You can now start the deployment process. Run `dism /Apply-Image /ImageFile:D:\Sources\install.wim /index:6 /ApplyDir:E:`, replacing "D" with the Installer Drive Letter, "6" with the Windows edition option, and "E" with the Windows Partition Drive Letter.
![](../images/DISM-6.png)
![](./images/DISM-6.png)
Once `dism` finishes its thing, run `bcdboot E:\Windows`, substituting "E" for the drive letter of the main Windows partition to create the boot files.
![](../images/DISM-7.png)
![](./images/DISM-7.png)
Windows is now installed. It should be recognized as "EFI Boot" or "Windows" with a Boot Camp icon in the OCLP Bootpicker.
@@ -155,11 +155,11 @@ Start up a command prompt window in the Windows Setup environment by running `cm
Next, enter the EFI Folder by running `C:`, substituting "C" for the EFI Partition Drive Letter. Then run `cd EFI` to enter the EFI Partition. Then, run `rmdir Boot /S /Q` to remove the boot files that can be detected by the stock Bootpicker. The OCLP Picker will still be able to detect and boot Windows.
![](../images/DISM-8.png)
![](./images/DISM-8.png)
You can verify that the `Boot` folder is removed by running the `dir` command:
![](../images/DISM-9.png)
![](./images/DISM-9.png)
If, for whatever reason, you are not able to remove the boot files from the Windows setup, shut down your system, boot into macOS, mount your EFI partition with [MountEFI](https://github.com/corpnewt/MountEFI), and remove the `Boot` folder (it should have a recent file modification date, and contain `Bootx64.efi`).
@@ -176,11 +176,11 @@ Once Brigadier is downloaded, move it to your desktop for easy access.
Open up a command prompt window as a standard user and run `cd desktop`.
![](../images/BOOTCAMP-1.png)
![](./images/BOOTCAMP-1.png)
Then run `.\brigadier.exe --model=MODEL1,1`, replacing "MODEL1,1" with your machine's SMBIOS model.
![](../images/BOOTCAMP-2.png)
![](./images/BOOTCAMP-2.png)
Once the Boot Camp software is downloaded, you can install it by executing `Setup.exe` or `\Drivers\Apple\BootCamp.msi` (`BootCamp64.msi` if present).
@@ -194,11 +194,11 @@ Once Brigadier is downloaded, move it to your desktop for easy access.
Open up a command prompt window as a standard user and run `cd desktop`.
![](../images/BOOTCAMP-1.png)
![](./images/BOOTCAMP-1.png)
Then run `.\brigadier.exe --model=MacPro7,1`. This will download the latest BootCamp 6 package.
![](../images/BOOTCAMP-2.png)
![](./images/BOOTCAMP-2.png)
Once the Boot Camp software is downloaded, you can install Boot Camp 6 by executing `\Drivers\Apple\BootCamp.msi` in an administrator command prompt window.
@@ -210,7 +210,7 @@ If you built OpenCore with Moderate or higher SMBIOS spoofing, you'll get an err
| Setup.exe | BootCamp.msi |
| :--- | :--- |
| ![](../images/windows-bootcamp-error.png) | ![](../images/windows-bootcamp-msi.png) |
| ![](./images/windows-bootcamp-error.png) | ![](./images/windows-bootcamp-msi.png) |
::: details BootCamp.msi quirks

View File

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 178 KiB

View File

Before

Width:  |  Height:  |  Size: 312 KiB

After

Width:  |  Height:  |  Size: 312 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 MiB

After

Width:  |  Height:  |  Size: 2.9 MiB

View File

Before

Width:  |  Height:  |  Size: 3.1 MiB

After

Width:  |  Height:  |  Size: 3.1 MiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 99 KiB

View File

Before

Width:  |  Height:  |  Size: 270 KiB

After

Width:  |  Height:  |  Size: 270 KiB

View File

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 129 KiB

View File

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 141 KiB

View File

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Before

Width:  |  Height:  |  Size: 782 KiB

After

Width:  |  Height:  |  Size: 782 KiB

View File

Before

Width:  |  Height:  |  Size: 984 KiB

After

Width:  |  Height:  |  Size: 984 KiB

View File

Before

Width:  |  Height:  |  Size: 504 KiB

After

Width:  |  Height:  |  Size: 504 KiB

View File

Before

Width:  |  Height:  |  Size: 382 KiB

After

Width:  |  Height:  |  Size: 382 KiB

View File

Before

Width:  |  Height:  |  Size: 446 KiB

After

Width:  |  Height:  |  Size: 446 KiB

View File

Before

Width:  |  Height:  |  Size: 368 KiB

After

Width:  |  Height:  |  Size: 368 KiB

View File

Before

Width:  |  Height:  |  Size: 268 KiB

After

Width:  |  Height:  |  Size: 268 KiB

View File

Before

Width:  |  Height:  |  Size: 246 KiB

After

Width:  |  Height:  |  Size: 246 KiB

View File

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 201 KiB

View File

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 156 KiB

View File

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 116 KiB

View File

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

View File

Before

Width:  |  Height:  |  Size: 221 KiB

After

Width:  |  Height:  |  Size: 221 KiB

View File

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 158 KiB

View File

Before

Width:  |  Height:  |  Size: 359 KiB

After

Width:  |  Height:  |  Size: 359 KiB

View File

Before

Width:  |  Height:  |  Size: 213 KiB

After

Width:  |  Height:  |  Size: 213 KiB

View File

Before

Width:  |  Height:  |  Size: 212 KiB

After

Width:  |  Height:  |  Size: 212 KiB

View File

Before

Width:  |  Height:  |  Size: 196 KiB

After

Width:  |  Height:  |  Size: 196 KiB

View File

Before

Width:  |  Height:  |  Size: 247 KiB

After

Width:  |  Height:  |  Size: 247 KiB

View File

Before

Width:  |  Height:  |  Size: 170 KiB

After

Width:  |  Height:  |  Size: 170 KiB

View File

Before

Width:  |  Height:  |  Size: 194 KiB

After

Width:  |  Height:  |  Size: 194 KiB

View File

Before

Width:  |  Height:  |  Size: 390 KiB

After

Width:  |  Height:  |  Size: 390 KiB

Some files were not shown because too many files have changed in this diff Show More