Merge branch 'main' into colorsync-downgrade-toggle

This commit is contained in:
Mykola Grymalyuk
2023-05-04 08:05:06 -07:00
committed by GitHub
12 changed files with 307 additions and 72 deletions

View File

@@ -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:

View File

@@ -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

View File

@@ -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",

View File

@@ -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:

View File

@@ -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

View File

@@ -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 |

View File

@@ -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>

View File

@@ -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):

View File

@@ -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"))

View File

@@ -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,
} }
}) })

View File

@@ -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

View File

@@ -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.