mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-18 05:34:42 +10:00
Merge branch 'main' into colorsync-downgrade-toggle
This commit is contained in:
37
.github/workflows/build-app-wxpython.yml
vendored
37
.github/workflows/build-app-wxpython.yml
vendored
@@ -9,26 +9,49 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build wxPython
|
name: Build wxPython
|
||||||
runs-on: x86_64_mojave
|
runs-on: x86_64_monterey
|
||||||
if: github.repository_owner == 'dortania'
|
if: github.repository_owner == 'dortania'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
branch: ${{ github.ref }}
|
branch: ${{ github.ref }}
|
||||||
commiturl: ${{ github.event.head_commit.url }}${{ github.event.release.html_url }}
|
commiturl: ${{ github.event.head_commit.url }}${{ github.event.release.html_url }}
|
||||||
commitdate: ${{ github.event.head_commit.timestamp }}${{ github.event.release.published_at }}
|
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_USERNAME: ${{ secrets.MAC_NOTARIZATION_USERNAME }}
|
||||||
MAC_NOTARIZATION_PASSWORD: ${{ secrets.MAC_NOTARIZATION_PASSWORD }}
|
MAC_NOTARIZATION_PASSWORD: ${{ secrets.MAC_NOTARIZATION_PASSWORD }}
|
||||||
|
MAC_NOTARIZATION_TEAM_ID: ${{ secrets.MAC_NOTARIZATION_TEAM_ID }}
|
||||||
ANALYTICS_KEY: ${{ secrets.ANALYTICS_KEY }}
|
ANALYTICS_KEY: ${{ secrets.ANALYTICS_KEY }}
|
||||||
ANALYTICS_SITE: ${{ secrets.ANALYTICS_SITE }}
|
ANALYTICS_SITE: ${{ secrets.ANALYTICS_SITE }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: /Library/Frameworks/Python.framework/Versions/3.10/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 }}"
|
|
||||||
- run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements ./payloads/entitlements.plist -o runtime "dist/OpenCore-Patcher.app"'
|
- name: Build Binary
|
||||||
- run: cd dist; ditto -c -k --sequesterRsrc --keepParent OpenCore-Patcher.app ../OpenCore-Patcher-wxPython.app.zip
|
run: /Library/Frameworks/Python.framework/Versions/3.10/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 }}"
|
||||||
- run: xcrun altool --notarize-app --primary-bundle-id "com.dortania.opencore-legacy-patcher" --username "${{ env.MAC_NOTARIZATION_USERNAME }}" --password "${{ env.MAC_NOTARIZATION_PASSWORD }}" --file OpenCore-Patcher-wxPython.app.zip
|
|
||||||
- run: packagesbuild ./payloads/InstallPackage/AutoPkg-Assets-Setup.pkgproj
|
# Uncomment when using Github Runners or first run on self-hosted
|
||||||
- run: mv ./OpenCore-Patcher-wxPython.app.zip ./OpenCore-Patcher-GUI.app.zip
|
# - name: Import Certificate
|
||||||
|
# uses: apple-actions/import-codesign-certs@v1
|
||||||
|
# with:
|
||||||
|
# p12-file-base64: ${{ secrets.MAC_CODESIGN_CERT }}
|
||||||
|
# p12-password: ${{ secrets.MAC_NOTARIZATION_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: Package Binary
|
||||||
|
run: cd dist; ditto -c -k --sequesterRsrc --keepParent OpenCore-Patcher.app ../OpenCore-Patcher-wxPython.app.zip
|
||||||
|
|
||||||
|
- 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: Generate support package
|
||||||
|
run: packagesbuild ./payloads/InstallPackage/AutoPkg-Assets-Setup.pkgproj
|
||||||
|
|
||||||
|
- name: Prepare App for Upload
|
||||||
|
run: mv ./OpenCore-Patcher-wxPython.app.zip ./OpenCore-Patcher-GUI.app.zip
|
||||||
|
|
||||||
- name: Upload App to Artifacts
|
- name: Upload App to Artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
|
|||||||
5
.github/workflows/validate.yml
vendored
5
.github/workflows/validate.yml
vendored
@@ -9,7 +9,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Validate
|
name: Validate
|
||||||
runs-on: x86_64_mojave
|
runs-on: x86_64_monterey
|
||||||
if: github.repository_owner == 'dortania'
|
if: github.repository_owner == 'dortania'
|
||||||
env:
|
env:
|
||||||
branch: ${{ github.ref }}
|
branch: ${{ github.ref }}
|
||||||
@@ -17,4 +17,5 @@ jobs:
|
|||||||
commitdate: ${{ github.event.head_commit.timestamp }}${{ github.event.release.published_at }}
|
commitdate: ${{ github.event.head_commit.timestamp }}${{ github.event.release.published_at }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3 OpenCore-Patcher-GUI.command --validate
|
- name: Validate
|
||||||
|
run: /Library/Frameworks/Python.framework/Versions/3.10/bin/python3 OpenCore-Patcher-GUI.command --validate
|
||||||
|
|||||||
@@ -231,6 +231,7 @@ class CreateBinary:
|
|||||||
|
|
||||||
whitelist_files = [
|
whitelist_files = [
|
||||||
"com.dortania.opencore-legacy-patcher.auto-patch.plist",
|
"com.dortania.opencore-legacy-patcher.auto-patch.plist",
|
||||||
|
"com.dortania.opencore-legacy-patcher.rsr-monitor.plist",
|
||||||
"entitlements.plist",
|
"entitlements.plist",
|
||||||
"launcher.sh",
|
"launcher.sh",
|
||||||
"OC-Patcher-TUI.icns",
|
"OC-Patcher-TUI.icns",
|
||||||
|
|||||||
27
CHANGELOG.md
27
CHANGELOG.md
@@ -1,5 +1,11 @@
|
|||||||
# OpenCore Legacy Patcher changelog
|
# OpenCore Legacy Patcher changelog
|
||||||
|
|
||||||
|
## 0.6.6
|
||||||
|
- Implement option to disable ColorSync downgrade on HD 3000 Macs
|
||||||
|
- Allows for Display Profiles support on some units
|
||||||
|
- Note: black box rendering issues will likely appear
|
||||||
|
- Thanks [@jazzzny](https://github.com/Jazzzny)
|
||||||
|
|
||||||
## 0.6.5
|
## 0.6.5
|
||||||
- Update 3802 Patchset Binaries:
|
- Update 3802 Patchset Binaries:
|
||||||
- Resolves additional 3rd party app crashes on Metal with macOS 13.3+
|
- Resolves additional 3rd party app crashes on Metal with macOS 13.3+
|
||||||
@@ -11,10 +17,25 @@
|
|||||||
- Restores USB 3.0 expansion card support on USB 1.1 machines such as MacPro5,1
|
- Restores USB 3.0 expansion card support on USB 1.1 machines such as MacPro5,1
|
||||||
- Resolve OpenCL rendering on Nvidia Web Drivers
|
- Resolve OpenCL rendering on Nvidia Web Drivers
|
||||||
- thanks [@jazzzny](https://github.com/Jazzzny)
|
- thanks [@jazzzny](https://github.com/Jazzzny)
|
||||||
- Implement option to disable ColorSync downgrade on HD 3000 Macs
|
- Resolve UI unable to download macOS installers on unknown models
|
||||||
- Allows for Display Profiles support
|
- ex. M2 Macs and Hackintoshes
|
||||||
|
- Implement minimum OS check for installer creation
|
||||||
|
- Prevents vague errors when creating Ventura installers on Yosemite
|
||||||
|
- Resolve WindowServer crashing with Rapid Security Response (RSR) installation
|
||||||
|
- Primarily applicable for Haswell iGPUs on 13.3.1 (a)
|
||||||
|
- Update legacy Wireless binaries
|
||||||
|
- Resolve wifi crashing on 13.4 with BCM94322, BCM943224 and Atheros chipsets
|
||||||
|
- Backend changes:
|
||||||
|
- macos_installer_handler.py:
|
||||||
|
- Expand OS support for IA parsing in SUCatalog
|
||||||
|
- gui_main.py:
|
||||||
|
- Fix spacing regression introduced with `.AppleSystemUIFont` implementation
|
||||||
- Increment Binaries:
|
- Increment Binaries:
|
||||||
- PatcherSupportPkg 0.9.6 - release
|
- PatcherSupportPkg 0.9.7 - release
|
||||||
|
- Build Server Changes:
|
||||||
|
- Upgrade CI Host to macOS Monterey
|
||||||
|
- Upgrade Xcode to 14.2
|
||||||
|
- Switch from `altool` to `notarytool` for notarization
|
||||||
|
|
||||||
## 0.6.4
|
## 0.6.4
|
||||||
- Backend changes:
|
- Backend changes:
|
||||||
|
|||||||
@@ -28,22 +28,51 @@ class os_data(enum.IntEnum):
|
|||||||
|
|
||||||
class os_conversion:
|
class os_conversion:
|
||||||
|
|
||||||
def os_to_kernel(os):
|
def os_to_kernel(os: str) -> int:
|
||||||
# Convert OS version to major XNU version
|
"""
|
||||||
|
Convert OS version to major XNU version
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
os (str): OS version
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Major XNU version
|
||||||
|
"""
|
||||||
if os.startswith("10."):
|
if os.startswith("10."):
|
||||||
return (int(os.split(".")[1]) + 4)
|
return (int(os.split(".")[1]) + 4)
|
||||||
else:
|
else:
|
||||||
return (int(os.split(".")[0]) + 9)
|
return (int(os.split(".")[0]) + 9)
|
||||||
|
|
||||||
def kernel_to_os(kernel):
|
|
||||||
# Convert major XNU version to OS version
|
def kernel_to_os(kernel: int) -> str:
|
||||||
|
"""
|
||||||
|
Convert major XNU version to OS version
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
kernel (int): Major XNU version
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: OS version
|
||||||
|
"""
|
||||||
if kernel >= os_data.big_sur:
|
if kernel >= os_data.big_sur:
|
||||||
return str((kernel - 9))
|
return str((kernel - 9))
|
||||||
else:
|
else:
|
||||||
return str((f"10.{kernel - 4}"))
|
return str((f"10.{kernel - 4}"))
|
||||||
|
|
||||||
def is_os_newer(source_major, source_minor, target_major, target_minor):
|
|
||||||
# Check if OS version 1 is newer than OS version 2
|
def is_os_newer(source_major: int, source_minor: int, target_major: int, target_minor: int) -> bool:
|
||||||
|
"""
|
||||||
|
Check if OS version 1 is newer than OS version 2
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
source_major (int): Major XNU version of OS version 1
|
||||||
|
source_minor (int): Minor XNU version of OS version 1
|
||||||
|
target_major (int): Major XNU version of OS version 2
|
||||||
|
target_minor (int): Minor XNU version of OS version 2
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if OS version 1 is newer than OS version 2
|
||||||
|
"""
|
||||||
if source_major < target_major:
|
if source_major < target_major:
|
||||||
return True
|
return True
|
||||||
elif source_major == target_major:
|
elif source_major == target_major:
|
||||||
@@ -52,8 +81,17 @@ class os_conversion:
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def convert_kernel_to_marketing_name(kernel):
|
|
||||||
# Convert major XNU version to Marketing Name
|
def convert_kernel_to_marketing_name(kernel: int) -> str:
|
||||||
|
"""
|
||||||
|
Convert major XNU version to Marketing name
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
kernel (int): Major XNU version
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Marketing name of OS
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
# Find os_data enum name
|
# Find os_data enum name
|
||||||
os_name = os_data(kernel).name
|
os_name = os_data(kernel).name
|
||||||
@@ -70,8 +108,17 @@ class os_conversion:
|
|||||||
|
|
||||||
return os_name
|
return os_name
|
||||||
|
|
||||||
def convert_marketing_name_to_kernel(marketing_name):
|
|
||||||
# Convert Marketing Name to major XNU version
|
def convert_marketing_name_to_kernel(marketing_name: str) -> int:
|
||||||
|
"""
|
||||||
|
Convert Marketing Name to major XNU version
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
marketing_name (str): Marketing Name of OS
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Major XNU version
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
# Find os_data enum value
|
# Find os_data enum value
|
||||||
os_kernel = os_data[marketing_name.lower().replace(" ", "_")]
|
os_kernel = os_data[marketing_name.lower().replace(" ", "_")]
|
||||||
@@ -81,16 +128,18 @@ class os_conversion:
|
|||||||
return int(os_kernel)
|
return int(os_kernel)
|
||||||
|
|
||||||
|
|
||||||
def find_largest_build(build_array):
|
def find_largest_build(build_array: list) -> str:
|
||||||
# Find the newest version within an array of versions
|
"""
|
||||||
# These builds will have both numbers and letters in the version
|
Find the newest version within an array of versions
|
||||||
# ex:
|
These builds will have both numbers and letters in the version
|
||||||
# [
|
ex:
|
||||||
# "22A5295i",
|
[
|
||||||
# "22A5266r",
|
"22A5295i",
|
||||||
# "22A5286j",
|
"22A5266r",
|
||||||
# "22A5295h",
|
"22A5286j",
|
||||||
# ]
|
"22A5295h",
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
|
||||||
max_length = 0 # Length of the longest build
|
max_length = 0 # Length of the longest build
|
||||||
build_array_split = [] # 'build_array', converted into individual array of elements
|
build_array_split = [] # 'build_array', converted into individual array of elements
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ The below table will list all supported and unsupported functions of the patcher
|
|||||||
|
|
||||||
Regarding OS support, see below:
|
Regarding OS support, see below:
|
||||||
|
|
||||||
* Machines listing `YES - Ventura and older` means they cannot run macOS Ventura at this time. Machines with only `YES` can run all of the supported macOS versions offered by OpenCore Legacy Patcher.
|
|
||||||
|
|
||||||
| Support Entry | Supported OSes | Description | Comment |
|
| Support Entry | Supported OSes | Description | Comment |
|
||||||
| :--- | :--- | :--- | :--- |
|
| :--- | :--- | :--- | :--- |
|
||||||
| HostOS | macOS 10.9 - macOS 13 | Refers to OSes where running OpenCore-Patcher.app are supported | Supports 10.7+ if [Python 3.9 or higher](https://www.python.org/downloads/) is manually installed, simply run the `OpenCore-Patcher-GUI.command` located in the repo |
|
| HostOS | macOS 10.10 - macOS 13 | Refers to OSes where running OpenCore-Patcher.app are supported | Supports 10.7+ if [Python 3.9 or higher](https://www.python.org/downloads/) is manually installed, simply run the `OpenCore-Patcher-GUI.command` located in the repo |
|
||||||
| TargetOS | macOS 11 - macOS 13 | Refers to OSes that can be patched to run with OpenCore | May support 10.4 and newer (in a potentially broken state). No support provided. |
|
| TargetOS | macOS 11 - macOS 13 | Refers to OSes that can be patched to run with OpenCore | May support 10.4 and newer (in a potentially broken state). No support provided. |
|
||||||
|
|
||||||
|
* macOS Ventura installer creation requires 10.11 or later
|
||||||
|
|
||||||
### MacBook
|
### MacBook
|
||||||
|
|
||||||
| SMBIOS | Year | Supported | Comment |
|
| SMBIOS | Year | Supported | Comment |
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?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>AssociatedBundleIdentifiers</key>
|
||||||
|
<string>com.dortania.opencore-legacy-patcher</string>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>com.dortania.opencore-legacy-patcher.rsr-monitor</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>rm</string>
|
||||||
|
<string>-rf</string>
|
||||||
|
<string>/Library/Extensions/example.kext</string> <!-- Update kext to correct name -->
|
||||||
|
</array>
|
||||||
|
<key>WatchPaths</key>
|
||||||
|
<array>
|
||||||
|
<string>/System/Volumes/Preboot/UUID/cryptex1/OS.dmg</string> <!-- Update UUID to host's booted Preboot folder -->
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -12,8 +12,8 @@ from data import os_data
|
|||||||
class Constants:
|
class Constants:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
# Patcher Versioning
|
# Patcher Versioning
|
||||||
self.patcher_version: str = "0.6.5" # OpenCore-Legacy-Patcher
|
self.patcher_version: str = "0.6.6" # OpenCore-Legacy-Patcher
|
||||||
self.patcher_support_pkg_version: str = "0.9.6" # PatcherSupportPkg
|
self.patcher_support_pkg_version: str = "0.9.7" # PatcherSupportPkg
|
||||||
self.copyright_date: str = "Copyright © 2020-2023 Dortania"
|
self.copyright_date: str = "Copyright © 2020-2023 Dortania"
|
||||||
|
|
||||||
# URLs
|
# URLs
|
||||||
@@ -239,6 +239,10 @@ class Constants:
|
|||||||
def auto_patch_launch_agent_path(self):
|
def auto_patch_launch_agent_path(self):
|
||||||
return self.payload_path / Path("com.dortania.opencore-legacy-patcher.auto-patch.plist")
|
return self.payload_path / Path("com.dortania.opencore-legacy-patcher.auto-patch.plist")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rsr_monitor_launch_daemon_path(self):
|
||||||
|
return self.payload_path / Path("com.dortania.opencore-legacy-patcher.rsr-monitor.plist")
|
||||||
|
|
||||||
# ACPI
|
# ACPI
|
||||||
@property
|
@property
|
||||||
def pci_ssdt_path(self):
|
def pci_ssdt_path(self):
|
||||||
|
|||||||
@@ -1782,7 +1782,7 @@ class wx_python_gui:
|
|||||||
if model in ["MacPro3,1", "MacPro4,1", "MacPro5,1"]:
|
if model in ["MacPro3,1", "MacPro4,1", "MacPro5,1"]:
|
||||||
has_legacy_usb = True
|
has_legacy_usb = True
|
||||||
issues_list = "- Lack of Keyboard/Mouse in macOS installer without a USB hub\n"
|
issues_list = "- Lack of Keyboard/Mouse in macOS installer without a USB hub\n"
|
||||||
elif model in smbios_data.smbios_dictionary[model]:
|
elif model in smbios_data.smbios_dictionary:
|
||||||
if "CPU Generation" in smbios_data.smbios_dictionary[model]:
|
if "CPU Generation" in smbios_data.smbios_dictionary[model]:
|
||||||
if smbios_data.smbios_dictionary[model]["CPU Generation"] <= cpu_data.cpu_data.penryn:
|
if smbios_data.smbios_dictionary[model]["CPU Generation"] <= cpu_data.cpu_data.penryn:
|
||||||
has_legacy_usb = True
|
has_legacy_usb = True
|
||||||
@@ -2060,7 +2060,17 @@ class wx_python_gui:
|
|||||||
logging.info("Installer(s) found:")
|
logging.info("Installer(s) found:")
|
||||||
for app in available_installers:
|
for app in available_installers:
|
||||||
logging.info(f"- {available_installers[app]['Short Name']}: {available_installers[app]['Version']} ({available_installers[app]['Build']})")
|
logging.info(f"- {available_installers[app]['Short Name']}: {available_installers[app]['Version']} ({available_installers[app]['Build']})")
|
||||||
self.install_selection = wx.Button(self.frame, label=f"{available_installers[app]['Short Name']}: {available_installers[app]['Version']} ({available_installers[app]['Build']})", size=(320, 30))
|
|
||||||
|
app_str = f"{available_installers[app]['Short Name']}"
|
||||||
|
unsupported: bool = available_installers[app]['Minimum Host OS'] > self.constants.detected_os
|
||||||
|
|
||||||
|
if unsupported:
|
||||||
|
min_str = os_data.os_conversion.convert_kernel_to_marketing_name(available_installers[app]['Minimum Host OS'])
|
||||||
|
app_str += f" (Requires {min_str})"
|
||||||
|
else:
|
||||||
|
app_str += f": {available_installers[app]['Version']} ({available_installers[app]['Build']})"
|
||||||
|
|
||||||
|
self.install_selection = wx.Button(self.frame, label=app_str, size=(320, 30))
|
||||||
i = i + 25
|
i = i + 25
|
||||||
self.install_selection.SetPosition(
|
self.install_selection.SetPosition(
|
||||||
wx.Point(
|
wx.Point(
|
||||||
@@ -2070,6 +2080,9 @@ class wx_python_gui:
|
|||||||
)
|
)
|
||||||
self.install_selection.Bind(wx.EVT_BUTTON, lambda event, temp=app: self.format_usb_menu(available_installers[temp]['Short Name'], available_installers[temp]['Path']))
|
self.install_selection.Bind(wx.EVT_BUTTON, lambda event, temp=app: self.format_usb_menu(available_installers[temp]['Short Name'], available_installers[temp]['Path']))
|
||||||
self.install_selection.Centre(wx.HORIZONTAL)
|
self.install_selection.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
if unsupported:
|
||||||
|
self.install_selection.Disable()
|
||||||
else:
|
else:
|
||||||
logging.info("No installers found")
|
logging.info("No installers found")
|
||||||
# Label: No Installers Found
|
# Label: No Installers Found
|
||||||
@@ -2099,6 +2112,7 @@ class wx_python_gui:
|
|||||||
def format_usb_menu(self, installer_name, installer_path):
|
def format_usb_menu(self, installer_name, installer_path):
|
||||||
self.frame.DestroyChildren()
|
self.frame.DestroyChildren()
|
||||||
logging.info(installer_path)
|
logging.info(installer_path)
|
||||||
|
self.frame.SetSize(370, -1)
|
||||||
|
|
||||||
# Header
|
# Header
|
||||||
self.header = wx.StaticText(self.frame, label="Format USB")
|
self.header = wx.StaticText(self.frame, label="Format USB")
|
||||||
@@ -2171,7 +2185,7 @@ class wx_python_gui:
|
|||||||
|
|
||||||
def format_usb_progress(self, disk, installer_name, installer_path):
|
def format_usb_progress(self, disk, installer_name, installer_path):
|
||||||
self.frame.DestroyChildren()
|
self.frame.DestroyChildren()
|
||||||
self.frame.SetSize(500, -1)
|
self.frame.SetSize(520, -1)
|
||||||
# Header
|
# Header
|
||||||
self.header = wx.StaticText(self.frame, label=f"Creating Installer: {installer_name}")
|
self.header = wx.StaticText(self.frame, label=f"Creating Installer: {installer_name}")
|
||||||
self.header.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
self.header.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
||||||
|
|||||||
@@ -13,10 +13,24 @@ from resources import network_handler, utilities
|
|||||||
|
|
||||||
APPLICATION_SEARCH_PATH: str = "/Applications"
|
APPLICATION_SEARCH_PATH: str = "/Applications"
|
||||||
SFR_SOFTWARE_UPDATE_PATH: str = "SFR/com_apple_MobileAsset_SFRSoftwareUpdate/com_apple_MobileAsset_SFRSoftwareUpdate.xml"
|
SFR_SOFTWARE_UPDATE_PATH: str = "SFR/com_apple_MobileAsset_SFRSoftwareUpdate/com_apple_MobileAsset_SFRSoftwareUpdate.xml"
|
||||||
|
CATALOG_URL_BASE: str = "https://swscan.apple.com/content/catalogs/others/index"
|
||||||
CATALOG_URL_BASE: str = "https://swscan.apple.com/content/catalogs/others/index"
|
CATALOG_URL_EXTENSION: str = ".merged-1.sucatalog"
|
||||||
CATALOG_URL_EXTENSION: str = "13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog"
|
CATALOG_URL_VARIANTS: list = [
|
||||||
CATALOG_URL_VERSION: str = "13"
|
"13",
|
||||||
|
"12",
|
||||||
|
"10.16",
|
||||||
|
"10.15",
|
||||||
|
"10.14",
|
||||||
|
"10.13",
|
||||||
|
"10.12",
|
||||||
|
"10.11",
|
||||||
|
"10.10",
|
||||||
|
"10.9",
|
||||||
|
"mountainlion",
|
||||||
|
"lion",
|
||||||
|
"snowleopard",
|
||||||
|
"leopard",
|
||||||
|
]
|
||||||
|
|
||||||
tmp_dir = tempfile.TemporaryDirectory()
|
tmp_dir = tempfile.TemporaryDirectory()
|
||||||
|
|
||||||
@@ -222,15 +236,15 @@ class RemoteInstallerCatalog:
|
|||||||
Parses Apple's Software Update catalog and finds all macOS installers.
|
Parses Apple's Software Update catalog and finds all macOS installers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, seed_override: SeedType = SeedType.PublicRelease) -> None:
|
def __init__(self, seed_override: SeedType = SeedType.PublicRelease, os_override: int = os_data.os_data.ventura) -> None:
|
||||||
|
|
||||||
self.catalog_url: str = self._construct_catalog_url(seed_override)
|
self.catalog_url: str = self._construct_catalog_url(seed_override, os_override)
|
||||||
|
|
||||||
self.available_apps: dict = self._parse_catalog()
|
self.available_apps: dict = self._parse_catalog()
|
||||||
self.available_apps_latest: dict = self._list_newest_installers_only()
|
self.available_apps_latest: dict = self._list_newest_installers_only()
|
||||||
|
|
||||||
|
|
||||||
def _construct_catalog_url(self, seed_type: SeedType) -> str:
|
def _construct_catalog_url(self, seed_type: SeedType, os_kernel: int) -> str:
|
||||||
"""
|
"""
|
||||||
Constructs the catalog URL based on the seed type
|
Constructs the catalog URL based on the seed type
|
||||||
|
|
||||||
@@ -241,17 +255,30 @@ class RemoteInstallerCatalog:
|
|||||||
str: The catalog URL
|
str: The catalog URL
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
url: str = CATALOG_URL_BASE
|
||||||
|
|
||||||
url: str = ""
|
os_version: str = os_data.os_conversion.kernel_to_os(os_kernel)
|
||||||
|
os_version = "10.16" if os_version == "11" else os_version
|
||||||
|
if os_version not in CATALOG_URL_VARIANTS:
|
||||||
|
logging.error(f"OS version {os_version} is not supported, defaulting to latest")
|
||||||
|
os_version = CATALOG_URL_VARIANTS[0]
|
||||||
|
|
||||||
|
url += f"-{os_version}"
|
||||||
if seed_type == SeedType.DeveloperSeed:
|
if seed_type == SeedType.DeveloperSeed:
|
||||||
url = f"{CATALOG_URL_BASE}-{CATALOG_URL_VERSION}seed-{CATALOG_URL_EXTENSION}"
|
url += f"seed"
|
||||||
elif seed_type == SeedType.PublicSeed:
|
elif seed_type == SeedType.PublicSeed:
|
||||||
url = f"{CATALOG_URL_BASE}-{CATALOG_URL_VERSION}beta-{CATALOG_URL_EXTENSION}"
|
url += f"beta"
|
||||||
elif seed_type == SeedType.CustomerSeed:
|
elif seed_type == SeedType.CustomerSeed:
|
||||||
url = f"{CATALOG_URL_BASE}-{CATALOG_URL_VERSION}customerseed-{CATALOG_URL_EXTENSION}"
|
url += f"customerseed"
|
||||||
else:
|
|
||||||
url = f"{CATALOG_URL_BASE}-{CATALOG_URL_EXTENSION}"
|
did_find_variant: bool = False
|
||||||
|
for variant in CATALOG_URL_VARIANTS:
|
||||||
|
if variant in url:
|
||||||
|
did_find_variant = True
|
||||||
|
if did_find_variant:
|
||||||
|
url += f"-{variant}"
|
||||||
|
|
||||||
|
url += f"{CATALOG_URL_EXTENSION}"
|
||||||
|
|
||||||
return url
|
return url
|
||||||
|
|
||||||
@@ -356,13 +383,10 @@ class RemoteInstallerCatalog:
|
|||||||
continue
|
continue
|
||||||
if "IntegrityDataURL" not in ia_package:
|
if "IntegrityDataURL" not in ia_package:
|
||||||
continue
|
continue
|
||||||
if "Size" not in ia_package:
|
|
||||||
size = 0
|
|
||||||
|
|
||||||
download_link = ia_package["URL"]
|
download_link = ia_package["URL"]
|
||||||
integrity = ia_package["IntegrityDataURL"]
|
integrity = ia_package["IntegrityDataURL"]
|
||||||
size = ia_package["Size"]
|
size = ia_package["Size"] if ia_package["Size"] else 0
|
||||||
|
|
||||||
|
|
||||||
if any([version, build, download_link, size, integrity]) is None:
|
if any([version, build, download_link, size, integrity]) is None:
|
||||||
continue
|
continue
|
||||||
@@ -518,28 +542,34 @@ class LocalInstallerCatalog:
|
|||||||
if "CFBundleDisplayName" not in application_info_plist:
|
if "CFBundleDisplayName" not in application_info_plist:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
app_version = application_info_plist["DTPlatformVersion"]
|
app_version: str = application_info_plist["DTPlatformVersion"]
|
||||||
clean_name = application_info_plist["CFBundleDisplayName"]
|
clean_name: str = application_info_plist["CFBundleDisplayName"]
|
||||||
|
app_sdk: str = application_info_plist["DTSDKBuild"] if "DTSDKBuild" in application_info_plist else "Unknown"
|
||||||
|
min_required: str = application_info_plist["LSMinimumSystemVersion"] if "LSMinimumSystemVersion" in application_info_plist else "Unknown"
|
||||||
|
|
||||||
if "DTSDKBuild" in application_info_plist:
|
kernel: int = 0
|
||||||
app_sdk = application_info_plist["DTSDKBuild"]
|
try:
|
||||||
else:
|
kernel = int(app_sdk[:2])
|
||||||
app_sdk = "Unknown"
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
min_required = os_data.os_conversion.os_to_kernel(min_required) if min_required != "Unknown" else 0
|
||||||
|
|
||||||
|
if min_required == os_data.os_data.sierra and kernel == os_data.os_data.ventura:
|
||||||
|
# Ventura's installer requires El Capitan minimum
|
||||||
|
# Ref: https://github.com/dortania/OpenCore-Legacy-Patcher/discussions/1038
|
||||||
|
min_required = os_data.os_data.el_capitan
|
||||||
|
|
||||||
# app_version can sometimes report GM instead of the actual version
|
# app_version can sometimes report GM instead of the actual version
|
||||||
# This is a workaround to get the actual version
|
# This is a workaround to get the actual version
|
||||||
if app_version.startswith("GM"):
|
if app_version.startswith("GM"):
|
||||||
try:
|
if kernel == 0:
|
||||||
app_version = int(app_sdk[:2])
|
|
||||||
if app_version < 20:
|
|
||||||
app_version = f"10.{app_version - 4}"
|
|
||||||
else:
|
|
||||||
app_version = f"{app_version - 9}.0"
|
|
||||||
except ValueError:
|
|
||||||
app_version = "Unknown"
|
app_version = "Unknown"
|
||||||
|
else:
|
||||||
|
app_version = os_data.os_conversion.kernel_to_os(kernel)
|
||||||
|
|
||||||
# Check if App Version is High Sierra or newer
|
# Check if App Version is High Sierra or newer
|
||||||
if os_data.os_conversion.os_to_kernel(app_version) < os_data.os_data.high_sierra:
|
if kernel < os_data.os_data.high_sierra:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
results = self._parse_sharedsupport_version(Path(APPLICATION_SEARCH_PATH) / Path(application)/ Path("Contents/SharedSupport/SharedSupport.dmg"))
|
results = self._parse_sharedsupport_version(Path(APPLICATION_SEARCH_PATH) / Path(application)/ Path("Contents/SharedSupport/SharedSupport.dmg"))
|
||||||
@@ -554,6 +584,7 @@ class LocalInstallerCatalog:
|
|||||||
"Version": app_version,
|
"Version": app_version,
|
||||||
"Build": app_sdk,
|
"Build": app_sdk,
|
||||||
"Path": application,
|
"Path": application,
|
||||||
|
"Minimum Host OS": min_required,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -312,9 +312,71 @@ class AutomaticSysPatch:
|
|||||||
utilities.process_status(utilities.elevated(["chmod", "644", "/Library/LaunchAgents/com.dortania.opencore-legacy-patcher.auto-patch.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["chmod", "644", "/Library/LaunchAgents/com.dortania.opencore-legacy-patcher.auto-patch.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
utilities.process_status(utilities.elevated(["chown", "root:wheel", "/Library/LaunchAgents/com.dortania.opencore-legacy-patcher.auto-patch.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["chown", "root:wheel", "/Library/LaunchAgents/com.dortania.opencore-legacy-patcher.auto-patch.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
|
# Copy over our launch daemon
|
||||||
|
if self._create_rsr_monitor_daemon() is True:
|
||||||
|
logging.info("- Copying rsr-monitor.plist Launch Daemon to /Library/LaunchDaemons/")
|
||||||
|
if Path("/Library/LaunchDaemons/com.dortania.opencore-legacy-patcher.rsr-monitor.plist").exists():
|
||||||
|
logging.info("- Deleting existing rsr-monitor.plist")
|
||||||
|
utilities.process_status(utilities.elevated(["rm", "/Library/LaunchDaemons/com.dortania.opencore-legacy-patcher.rsr-monitor.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
if not Path("/Library/LaunchDaemons/").exists():
|
||||||
|
logging.info("- Creating /Library/LaunchDaemons/")
|
||||||
|
utilities.process_status(utilities.elevated(["mkdir", "-p", "/Library/LaunchDaemons/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
utilities.process_status(utilities.elevated(["cp", self.constants.rsr_monitor_launch_daemon_path, "/Library/LaunchDaemons/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
|
# Set the permissions on the com.dortania.opencore-legacy-patcher.rsr-monitor.plist
|
||||||
|
logging.info("- Setting permissions on rsr-monitor.plist")
|
||||||
|
utilities.process_status(utilities.elevated(["chmod", "644", "/Library/LaunchDaemons/com.dortania.opencore-legacy-patcher.rsr-monitor.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
utilities.process_status(utilities.elevated(["chown", "root:wheel", "/Library/LaunchDaemons/com.dortania.opencore-legacy-patcher.rsr-monitor.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
# Making app alias
|
# Making app alias
|
||||||
# Simply an easy way for users to notice the app
|
# Simply an easy way for users to notice the app
|
||||||
# If there's already an alias or exiting app, skip
|
# If there's already an alias or exiting app, skip
|
||||||
if not Path("/Applications/OpenCore-Patcher.app").exists():
|
if not Path("/Applications/OpenCore-Patcher.app").exists():
|
||||||
logging.info("- Making app alias")
|
logging.info("- Making app alias")
|
||||||
utilities.process_status(utilities.elevated(["ln", "-s", "/Library/Application Support/Dortania/OpenCore-Patcher.app", "/Applications/OpenCore-Patcher.app"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["ln", "-s", "/Library/Application Support/Dortania/OpenCore-Patcher.app", "/Applications/OpenCore-Patcher.app"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
|
|
||||||
|
def _create_rsr_monitor_daemon(self) -> bool:
|
||||||
|
# Get kext list in /Library/Extensions that have the 'GPUCompanionBundles' property
|
||||||
|
# This is used to determine if we need to run the RSRMonitor
|
||||||
|
logging.info("- Checking if RSRMonitor is needed")
|
||||||
|
|
||||||
|
cryptex_path = f"/System/Volumes/Preboot/{utilities.get_preboot_uuid()}/cryptex1/current/OS.dmg"
|
||||||
|
if not Path(cryptex_path).exists():
|
||||||
|
logging.info("- No OS.dmg, skipping RSRMonitor")
|
||||||
|
return False
|
||||||
|
|
||||||
|
kexts = []
|
||||||
|
for kext in Path("/Library/Extensions").glob("*.kext"):
|
||||||
|
if not Path(f"{kext}/Contents/Info.plist").exists():
|
||||||
|
continue
|
||||||
|
kext_plist = plistlib.load(open(f"{kext}/Contents/Info.plist", "rb"))
|
||||||
|
if "GPUCompanionBundles" not in kext_plist:
|
||||||
|
continue
|
||||||
|
logging.info(f" - Found kext with GPUCompanionBundles: {kext.name}")
|
||||||
|
kexts.append(kext.name)
|
||||||
|
|
||||||
|
# If we have no kexts, we don't need to run the RSRMonitor
|
||||||
|
if not kexts:
|
||||||
|
logging.info("- No kexts found with GPUCompanionBundles, skipping RSRMonitor")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Load the RSRMonitor plist
|
||||||
|
rsr_monitor_plist = plistlib.load(open(self.constants.rsr_monitor_launch_daemon_path, "rb"))
|
||||||
|
|
||||||
|
arguments = ["rm", "-Rfv"]
|
||||||
|
arguments += [f"/Library/Extensions/{kext}" for kext in kexts]
|
||||||
|
|
||||||
|
# Add the arguments to the RSRMonitor plist
|
||||||
|
rsr_monitor_plist["ProgramArguments"] = arguments
|
||||||
|
|
||||||
|
# Next add monitoring for '/System/Volumes/Preboot/{UUID}/cryptex1/OS.dmg'
|
||||||
|
logging.info(f" - Adding monitor: {cryptex_path}")
|
||||||
|
rsr_monitor_plist["WatchPaths"] = [
|
||||||
|
cryptex_path,
|
||||||
|
]
|
||||||
|
|
||||||
|
# Write the RSRMonitor plist
|
||||||
|
plistlib.dump(rsr_monitor_plist, Path(self.constants.rsr_monitor_launch_daemon_path).open("wb"))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|||||||
@@ -451,6 +451,15 @@ def monitor_disk_output(disk):
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
def get_preboot_uuid() -> str:
|
||||||
|
"""
|
||||||
|
Get the UUID of the Preboot volume
|
||||||
|
"""
|
||||||
|
args = ["ioreg", "-a", "-n", "chosen", "-p", "IODeviceTree", "-r"]
|
||||||
|
output = plistlib.loads(subprocess.run(args, stdout=subprocess.PIPE).stdout)
|
||||||
|
return output[0]["apfs-preboot-uuid"].strip(b"\0").decode()
|
||||||
|
|
||||||
|
|
||||||
def block_os_updaters():
|
def block_os_updaters():
|
||||||
# Disables any processes that would be likely to mess with
|
# Disables any processes that would be likely to mess with
|
||||||
# the root volume while we're working with it.
|
# the root volume while we're working with it.
|
||||||
|
|||||||
Reference in New Issue
Block a user