mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-11 16:27:19 +10:00
Add AMFIPass (#1051)
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -30,6 +30,7 @@ __pycache__/
|
|||||||
/payloads/OpenCore-Legacy-Patcher
|
/payloads/OpenCore-Legacy-Patcher
|
||||||
/payloads/InstallAssistant.pkg.integrityDataV1
|
/payloads/InstallAssistant.pkg.integrityDataV1
|
||||||
/payloads.dmg
|
/payloads.dmg
|
||||||
|
/Universal-Binaries.dmg
|
||||||
/payloads/OpenCore-Legacy-Patcher-*.plist
|
/payloads/OpenCore-Legacy-Patcher-*.plist
|
||||||
/payloads/KDK.dmg
|
/payloads/KDK.dmg
|
||||||
*.log
|
*.log
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class CreateBinary:
|
|||||||
Library for creating OpenCore-Patcher application
|
Library for creating OpenCore-Patcher application
|
||||||
|
|
||||||
This script's main purpose is to handle the following:
|
This script's main purpose is to handle the following:
|
||||||
- Download external dependancies (ex. PatcherSupportPkg)
|
- Download external dependencies (ex. PatcherSupportPkg)
|
||||||
- Convert payloads directory into DMG
|
- Convert payloads directory into DMG
|
||||||
- Build Binary via Pyinstaller
|
- Build Binary via Pyinstaller
|
||||||
- Patch 'LC_VERSION_MIN_MACOSX' to OS X 10.10
|
- Patch 'LC_VERSION_MIN_MACOSX' to OS X 10.10
|
||||||
@@ -275,7 +275,10 @@ class CreateBinary:
|
|||||||
for resource in required_resources:
|
for resource in required_resources:
|
||||||
if Path(f"./{resource}").exists():
|
if Path(f"./{resource}").exists():
|
||||||
if self.args.reset_binaries:
|
if self.args.reset_binaries:
|
||||||
print(f"- Removing old {resource}")
|
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_output = subprocess.run(
|
||||||
["rm", "-rf", f"./{resource}"],
|
["rm", "-rf", f"./{resource}"],
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ This patcher is made of multiple external applications from different people and
|
|||||||
* [telemetrap](https://forums.macrumors.com/threads/mp3-1-others-sse-4-2-emulation-to-enable-amd-metal-driver.2206682/post-28447707) - Syncretic
|
* [telemetrap](https://forums.macrumors.com/threads/mp3-1-others-sse-4-2-emulation-to-enable-amd-metal-driver.2206682/post-28447707) - Syncretic
|
||||||
* [SurPlus](https://github.com/reenigneorcim/SurPlus) - Syncretic
|
* [SurPlus](https://github.com/reenigneorcim/SurPlus) - Syncretic
|
||||||
* [VMM Patch Set](https://github.com/dortania/OpenCore-Legacy-Patcher/blob/4a8f61a01da72b38a4b2250386cc4b497a31a839/payloads/Config/config.plist#L1222-L1281) - parrotgeek1
|
* [VMM Patch Set](https://github.com/dortania/OpenCore-Legacy-Patcher/blob/4a8f61a01da72b38a4b2250386cc4b497a31a839/payloads/Config/config.plist#L1222-L1281) - parrotgeek1
|
||||||
|
* AMFIPass - Dhinak G
|
||||||
* Apple Binaries - Apple Inc.
|
* Apple Binaries - Apple Inc.
|
||||||
* All other patches - respective authors
|
* All other patches - respective authors
|
||||||
|
|
||||||
|
|||||||
@@ -1584,6 +1584,22 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>Arch</key>
|
<key>Arch</key>
|
||||||
<string>x86_64</string>
|
<string>x86_64</string>
|
||||||
|
<key>BundlePath</key>
|
||||||
|
<string>AMFIPass.kext</string>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>AMFIPass</string>
|
||||||
|
<key>Enabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>ExecutablePath</key>
|
||||||
|
<string>Contents/MacOS/AMFIPass</string>
|
||||||
|
<key>MaxKernel</key>
|
||||||
|
<string></string>
|
||||||
|
<key>MinKernel</key>
|
||||||
|
<string>20.0.0</string>
|
||||||
|
<key>PlistPath</key>
|
||||||
|
<string>Contents/Info.plist</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
<key>Comment</key>
|
<key>Comment</key>
|
||||||
<string>Aquantia Ethernet Patch</string>
|
<string>Aquantia Ethernet Patch</string>
|
||||||
<key>Enabled</key>
|
<key>Enabled</key>
|
||||||
|
|||||||
BIN
payloads/Kexts/Acidanthera/AMFIPass-v1.3.1-RELEASE.zip
Normal file
BIN
payloads/Kexts/Acidanthera/AMFIPass-v1.3.1-RELEASE.zip
Normal file
Binary file not shown.
@@ -82,3 +82,6 @@ class BuildSecurity:
|
|||||||
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (1)")["Enabled"] = True
|
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (1)")["Enabled"] = True
|
||||||
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (2) Legacy")["Enabled"] = True
|
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (2) Legacy")["Enabled"] = True
|
||||||
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (2) Ventura")["Enabled"] = True
|
support.BuildSupport(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (2) Ventura")["Enabled"] = True
|
||||||
|
|
||||||
|
logging.info("- Enabling AMFIPass")
|
||||||
|
support.BuildSupport(self.model, self.constants, self.config).enable_kext("AMFIPass.kext", self.constants.amfipass_version, self.constants.amfipass_path)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
from packaging import version
|
||||||
|
|
||||||
from resources import device_probe
|
from resources import device_probe
|
||||||
from data import os_data
|
from data import os_data
|
||||||
@@ -78,13 +79,15 @@ class Constants:
|
|||||||
|
|
||||||
## Dortania
|
## Dortania
|
||||||
## https://github.com/dortania
|
## https://github.com/dortania
|
||||||
self.backlight_injector_version: str = "1.1.0" # BacklightInjector
|
self.backlight_injector_version: str = "1.1.0" # BacklightInjector
|
||||||
self.backlight_injectorA_version: str = "1.0.0" # BacklightInjector (iMac9,1)
|
self.backlight_injectorA_version: str = "1.0.0" # BacklightInjector (iMac9,1)
|
||||||
self.smcspoof_version: str = "1.0.0" # SMC-Spoof
|
self.smcspoof_version: str = "1.0.0" # SMC-Spoof
|
||||||
self.mce_version: str = "1.0.0" # AppleMCEReporterDisabler
|
self.mce_version: str = "1.0.0" # AppleMCEReporterDisabler
|
||||||
self.btspoof_version: str = "1.0.0" # Bluetooth-Spoof
|
self.btspoof_version: str = "1.0.0" # Bluetooth-Spoof
|
||||||
self.aspp_override_version: str = "1.0.1" # ACPI_SMC_PlatformPlugin Override
|
self.aspp_override_version: str = "1.0.1" # ACPI_SMC_PlatformPlugin Override
|
||||||
self.rsrhelper_version: str = "1.0.0" # RSRHelper
|
self.rsrhelper_version: str = "1.0.0" # RSRHelper
|
||||||
|
self.amfipass_version: str = "1.3.1" # AMFIPass
|
||||||
|
self.amfipass_compatibility_version: str = "1.2.1" # Minimum AMFIPass version required
|
||||||
|
|
||||||
## Syncretic
|
## Syncretic
|
||||||
## https://forums.macrumors.com/members/syncretic.1173816/
|
## https://forums.macrumors.com/members/syncretic.1173816/
|
||||||
@@ -232,6 +235,18 @@ class Constants:
|
|||||||
os_data.os_data.ventura,
|
os_data.os_data.ventura,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def special_build(self):
|
||||||
|
"""
|
||||||
|
Special builds are used for testing. They do not get updates through the updater
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
version.parse(self.patcher_version)
|
||||||
|
return False
|
||||||
|
except version.InvalidVersion:
|
||||||
|
return True
|
||||||
|
|
||||||
# Payload Location
|
# Payload Location
|
||||||
|
|
||||||
# Support Disk Images
|
# Support Disk Images
|
||||||
@@ -489,6 +504,11 @@ class Constants:
|
|||||||
def rsrhelper_path(self):
|
def rsrhelper_path(self):
|
||||||
return self.payload_kexts_path / Path(f"Acidanthera/RSRHelper-v{self.rsrhelper_version}-{self.kext_variant}.zip")
|
return self.payload_kexts_path / Path(f"Acidanthera/RSRHelper-v{self.rsrhelper_version}-{self.kext_variant}.zip")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def amfipass_path(self):
|
||||||
|
# AMFIPass is release only
|
||||||
|
return self.payload_kexts_path / Path(f"Acidanthera/AMFIPass-v{self.amfipass_version}-RELEASE.zip")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def innie_path(self):
|
def innie_path(self):
|
||||||
return self.payload_kexts_path / Path(f"Misc/Innie-v{self.innie_version}-{self.kext_variant}.zip")
|
return self.payload_kexts_path / Path(f"Misc/Innie-v{self.innie_version}-{self.kext_variant}.zip")
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class GenerateDefaults:
|
|||||||
self._networking_probe()
|
self._networking_probe()
|
||||||
self._misc_hardwares_probe()
|
self._misc_hardwares_probe()
|
||||||
self._smbios_probe()
|
self._smbios_probe()
|
||||||
|
self._check_amfipass_supported()
|
||||||
|
|
||||||
def _general_probe(self) -> None:
|
def _general_probe(self) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -309,4 +309,32 @@ class GenerateDefaults:
|
|||||||
if is_key_enabled not in ["false", "0"]:
|
if is_key_enabled not in ["false", "0"]:
|
||||||
subprocess.run(["defaults", "write", "-g", key, "-bool", "true"])
|
subprocess.run(["defaults", "write", "-g", key, "-bool", "true"])
|
||||||
|
|
||||||
subprocess.run(["defaults", "write", "-g", "Amy.MenuBar2Beta", "-bool", "false"])
|
subprocess.run(["defaults", "write", "-g", "Amy.MenuBar2Beta", "-bool", "false"])
|
||||||
|
|
||||||
|
def _check_amfipass_supported(self) -> None:
|
||||||
|
"""
|
||||||
|
Check if root volume supports AMFIPass
|
||||||
|
|
||||||
|
The basic requirements of this function are:
|
||||||
|
- The host is the target
|
||||||
|
- Root volume doesn't have adhoc signed binaries
|
||||||
|
|
||||||
|
If all of these conditions are met, it is safe to disable AMFI and CS_LV. Otherwise, for safety, leave it be.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not self.host_is_target:
|
||||||
|
# Unknown whether the host is using old binaries
|
||||||
|
# Rebuild it once you are on the host
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check for adhoc signed binaries
|
||||||
|
if self.constants.computer.oclp_sys_signed is False:
|
||||||
|
# Root patch with new binaries, then reboot
|
||||||
|
return
|
||||||
|
|
||||||
|
# Note: simply checking the authority is not enough, as the authority can be spoofed
|
||||||
|
# (but do we really care? this is just a simple check)
|
||||||
|
# Note: the cert will change
|
||||||
|
|
||||||
|
self.constants.disable_amfi = False
|
||||||
|
self.constants.disable_cs_lv = False
|
||||||
|
|||||||
@@ -604,6 +604,7 @@ class Computer:
|
|||||||
oclp_sys_version: Optional[str] = None
|
oclp_sys_version: Optional[str] = None
|
||||||
oclp_sys_date: Optional[str] = None
|
oclp_sys_date: Optional[str] = None
|
||||||
oclp_sys_url: Optional[str] = None
|
oclp_sys_url: Optional[str] = None
|
||||||
|
oclp_sys_signed: Optional[bool] = False
|
||||||
firmware_vendor: Optional[str] = None
|
firmware_vendor: Optional[str] = None
|
||||||
rosetta_active: Optional[bool] = False
|
rosetta_active: Optional[bool] = False
|
||||||
|
|
||||||
@@ -927,15 +928,19 @@ class Computer:
|
|||||||
|
|
||||||
def oclp_sys_patch_probe(self):
|
def oclp_sys_patch_probe(self):
|
||||||
path = Path("/System/Library/CoreServices/OpenCore-Legacy-Patcher.plist")
|
path = Path("/System/Library/CoreServices/OpenCore-Legacy-Patcher.plist")
|
||||||
if path.exists():
|
if not path.exists():
|
||||||
sys_plist = plistlib.load(path.open("rb"))
|
self.oclp_sys_signed = True # No plist, so assume root is valid
|
||||||
if sys_plist:
|
return
|
||||||
if "OpenCore Legacy Patcher" in sys_plist:
|
sys_plist = plistlib.load(path.open("rb"))
|
||||||
self.oclp_sys_version = sys_plist["OpenCore Legacy Patcher"]
|
if sys_plist:
|
||||||
if "Time Patched" in sys_plist:
|
if "OpenCore Legacy Patcher" in sys_plist:
|
||||||
self.oclp_sys_date = sys_plist["Time Patched"]
|
self.oclp_sys_version = sys_plist["OpenCore Legacy Patcher"]
|
||||||
if "Commit URL" in sys_plist:
|
if "Time Patched" in sys_plist:
|
||||||
self.oclp_sys_url = sys_plist["Commit URL"]
|
self.oclp_sys_date = sys_plist["Time Patched"]
|
||||||
|
if "Commit URL" in sys_plist:
|
||||||
|
self.oclp_sys_url = sys_plist["Commit URL"]
|
||||||
|
if "Custom Signature" in sys_plist:
|
||||||
|
self.oclp_sys_signed = sys_plist["Custom Signature"]
|
||||||
|
|
||||||
def check_rosetta(self):
|
def check_rosetta(self):
|
||||||
result = subprocess.run("sysctl -in sysctl.proc_translated".split(), stdout=subprocess.PIPE).stdout.decode()
|
result = subprocess.run("sysctl -in sysctl.proc_translated".split(), stdout=subprocess.PIPE).stdout.decode()
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from data import os_data
|
|||||||
|
|
||||||
KDK_INSTALL_PATH: str = "/Library/Developer/KDKs"
|
KDK_INSTALL_PATH: str = "/Library/Developer/KDKs"
|
||||||
KDK_INFO_PLIST: str = "KDKInfo.plist"
|
KDK_INFO_PLIST: str = "KDKInfo.plist"
|
||||||
KDK_API_LINK: str = "https://raw.githubusercontent.com/dortania/KdkSupportPkg/gh-pages/manifest.json"
|
KDK_API_LINK: str = "https://dortania.github.io/KdkSupportPkg/manifest.json"
|
||||||
|
|
||||||
KDK_ASSET_LIST: list = None
|
KDK_ASSET_LIST: list = None
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ class PatchSysVolume:
|
|||||||
|
|
||||||
self.skip_root_kmutil_requirement = self.hardware_details["Settings: Supports Auxiliary Cache"]
|
self.skip_root_kmutil_requirement = self.hardware_details["Settings: Supports Auxiliary Cache"]
|
||||||
|
|
||||||
|
|
||||||
def _init_pathing(self, custom_root_mount_path: Path = None, custom_data_mount_path: Path = None) -> None:
|
def _init_pathing(self, custom_root_mount_path: Path = None, custom_data_mount_path: Path = None) -> None:
|
||||||
"""
|
"""
|
||||||
Initializes the pathing for root volume patching
|
Initializes the pathing for root volume patching
|
||||||
@@ -493,7 +492,7 @@ class PatchSysVolume:
|
|||||||
oclp_plist_data = plistlib.load(Path(oclp_path).open("rb"))
|
oclp_plist_data = plistlib.load(Path(oclp_path).open("rb"))
|
||||||
for key in oclp_plist_data:
|
for key in oclp_plist_data:
|
||||||
if isinstance(oclp_plist_data[key], (bool, int)):
|
if isinstance(oclp_plist_data[key], (bool, int)):
|
||||||
continue
|
continue
|
||||||
if "Install" not in oclp_plist_data[key]:
|
if "Install" not in oclp_plist_data[key]:
|
||||||
continue
|
continue
|
||||||
for location in oclp_plist_data[key]["Install"]:
|
for location in oclp_plist_data[key]["Install"]:
|
||||||
|
|||||||
@@ -47,8 +47,7 @@ class AutomaticSysPatch:
|
|||||||
|
|
||||||
dict = updates.CheckBinaryUpdates(self.constants).check_binary_updates()
|
dict = updates.CheckBinaryUpdates(self.constants).check_binary_updates()
|
||||||
if dict:
|
if dict:
|
||||||
for key in dict:
|
version = dict["Version"]
|
||||||
version = dict[key]["Version"]
|
|
||||||
logging.info(f"- Found new version: {version}")
|
logging.info(f"- Found new version: {version}")
|
||||||
|
|
||||||
app = wx.App()
|
app = wx.App()
|
||||||
@@ -64,7 +63,7 @@ class AutomaticSysPatch:
|
|||||||
if response == wx.ID_YES:
|
if response == wx.ID_YES:
|
||||||
gui_entry.EntryPoint(self.constants).start(entry=gui_entry.SupportedEntryPoints.UPDATE_APP)
|
gui_entry.EntryPoint(self.constants).start(entry=gui_entry.SupportedEntryPoints.UPDATE_APP)
|
||||||
elif response == wx.ID_NO:
|
elif response == wx.ID_NO:
|
||||||
webbrowser.open(dict[key]["Github Link"])
|
webbrowser.open(dict["Github Link"])
|
||||||
return
|
return
|
||||||
|
|
||||||
if utilities.check_seal() is True:
|
if utilities.check_seal() is True:
|
||||||
@@ -149,17 +148,21 @@ class AutomaticSysPatch:
|
|||||||
logging.info("- Versions match")
|
logging.info("- Versions match")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
if self.constants.special_build is True:
|
||||||
|
# Version doesn't match and we're on a special build
|
||||||
|
# Special builds don't have good ways to compare versions
|
||||||
|
logging.info("- Special build detected, assuming installed is older")
|
||||||
|
return False
|
||||||
|
|
||||||
# Check if installed version is newer than booted version
|
# Check if installed version is newer than booted version
|
||||||
if updates.CheckBinaryUpdates(self.constants)._check_if_build_newer(
|
if updates.CheckBinaryUpdates(self.constants).check_if_newer(self.constants.computer.oclp_version):
|
||||||
self.constants.computer.oclp_version.split("."), self.constants.patcher_version.split(".")
|
|
||||||
) is True:
|
|
||||||
logging.info("- Installed version is newer than booted version")
|
logging.info("- Installed version is newer than booted version")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
args = [
|
args = [
|
||||||
"osascript",
|
"osascript",
|
||||||
"-e",
|
"-e",
|
||||||
f"""display dialog "OpenCore Legacy Patcher has detected that you are booting an outdated OpenCore build\n- Booted: {self.constants.computer.oclp_version}\n- Installed: {self.constants.patcher_version}\n\nWould you like to update the OpenCore bootloader?" """
|
f"""display dialog "OpenCore Legacy Patcher has detected that you are booting {'a different' if self.constants.special_build else 'an outdated'} OpenCore build\n- Booted: {self.constants.computer.oclp_version}\n- Installed: {self.constants.patcher_version}\n\nWould you like to update the OpenCore bootloader?" """
|
||||||
f'with icon POSIX file "{self.constants.app_icon_path}"',
|
f'with icon POSIX file "{self.constants.app_icon_path}"',
|
||||||
]
|
]
|
||||||
output = subprocess.run(
|
output = subprocess.run(
|
||||||
|
|||||||
@@ -3,26 +3,16 @@
|
|||||||
# Used when supplying data to sys_patch.py
|
# Used when supplying data to sys_patch.py
|
||||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||||
|
|
||||||
import plistlib
|
|
||||||
import logging
|
import logging
|
||||||
import py_sip_xnu
|
import plistlib
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from resources import (
|
import packaging.version
|
||||||
constants,
|
import py_sip_xnu
|
||||||
device_probe,
|
|
||||||
utilities,
|
from data import cpu_data, model_array, os_data, sip_data, smbios_data
|
||||||
amfi_detect,
|
from resources import (amfi_detect, constants, device_probe, kdk_handler,
|
||||||
network_handler,
|
network_handler, utilities)
|
||||||
kdk_handler
|
|
||||||
)
|
|
||||||
from data import (
|
|
||||||
model_array,
|
|
||||||
os_data,
|
|
||||||
sip_data,
|
|
||||||
smbios_data,
|
|
||||||
cpu_data
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class DetectRootPatch:
|
class DetectRootPatch:
|
||||||
@@ -418,7 +408,7 @@ class DetectRootPatch:
|
|||||||
bool: True if loaded, False otherwise
|
bool: True if loaded, False otherwise
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return utilities.check_kext_loaded("WhateverGreen", self.constants.detected_os)
|
return utilities.check_kext_loaded("as.vit9696.WhateverGreen")
|
||||||
|
|
||||||
|
|
||||||
def _check_kdk(self):
|
def _check_kdk(self):
|
||||||
@@ -521,7 +511,7 @@ class DetectRootPatch:
|
|||||||
if self.constants.detected_os > os_data.os_data.catalina:
|
if self.constants.detected_os > os_data.os_data.catalina:
|
||||||
self.brightness_legacy = True
|
self.brightness_legacy = True
|
||||||
|
|
||||||
if self.model in ["iMac7,1", "iMac8,1"] or (self.model in model_array.LegacyAudio and utilities.check_kext_loaded("AppleALC", self.constants.detected_os) is False):
|
if self.model in ["iMac7,1", "iMac8,1"] or (self.model in model_array.LegacyAudio and utilities.check_kext_loaded("as.vit9696.AppleALC") is False):
|
||||||
# Special hack for systems with botched GOPs
|
# Special hack for systems with botched GOPs
|
||||||
# TL;DR: No Boot Screen breaks Lilu, therefore breaking audio
|
# TL;DR: No Boot Screen breaks Lilu, therefore breaking audio
|
||||||
if self.constants.detected_os > os_data.os_data.catalina:
|
if self.constants.detected_os > os_data.os_data.catalina:
|
||||||
@@ -610,6 +600,12 @@ class DetectRootPatch:
|
|||||||
if self.constants.detected_os < os_data.os_data.big_sur:
|
if self.constants.detected_os < os_data.os_data.big_sur:
|
||||||
return amfi_detect.AmfiConfigDetectLevel.NO_CHECK
|
return amfi_detect.AmfiConfigDetectLevel.NO_CHECK
|
||||||
|
|
||||||
|
amfipass_version = utilities.check_kext_loaded("com.dhinakg.AMFIPass")
|
||||||
|
if amfipass_version:
|
||||||
|
if packaging.version.parse(amfipass_version) >= packaging.version.parse(self.constants.amfipass_compatibility_version):
|
||||||
|
# If AMFIPass is loaded, our binaries will work
|
||||||
|
return amfi_detect.AmfiConfigDetectLevel.NO_CHECK
|
||||||
|
|
||||||
if self.constants.detected_os >= os_data.os_data.ventura:
|
if self.constants.detected_os >= os_data.os_data.ventura:
|
||||||
if self.amfi_shim_bins is True:
|
if self.amfi_shim_bins is True:
|
||||||
# Currently we require AMFI outright disabled
|
# Currently we require AMFI outright disabled
|
||||||
|
|||||||
@@ -3,8 +3,11 @@
|
|||||||
# Call check_binary_updates() to determine if any updates are available
|
# Call check_binary_updates() to determine if any updates are available
|
||||||
# Returns dict with Link and Version of the latest binary update if available
|
# Returns dict with Link and Version of the latest binary update if available
|
||||||
import logging
|
import logging
|
||||||
|
from typing import Optional, Union
|
||||||
|
|
||||||
from resources import network_handler, constants
|
from packaging import version
|
||||||
|
|
||||||
|
from resources import constants, network_handler
|
||||||
|
|
||||||
REPO_LATEST_RELEASE_URL: str = "https://api.github.com/repos/dortania/OpenCore-Legacy-Patcher/releases/latest"
|
REPO_LATEST_RELEASE_URL: str = "https://api.github.com/repos/dortania/OpenCore-Legacy-Patcher/releases/latest"
|
||||||
|
|
||||||
@@ -12,48 +15,62 @@ REPO_LATEST_RELEASE_URL: str = "https://api.github.com/repos/dortania/OpenCore-L
|
|||||||
class CheckBinaryUpdates:
|
class CheckBinaryUpdates:
|
||||||
def __init__(self, global_constants: constants.Constants) -> None:
|
def __init__(self, global_constants: constants.Constants) -> None:
|
||||||
self.constants: constants.Constants = global_constants
|
self.constants: constants.Constants = global_constants
|
||||||
|
try:
|
||||||
|
self.binary_version = version.parse(self.constants.patcher_version)
|
||||||
|
except version.InvalidVersion:
|
||||||
|
assert self.constants.special_build is True, "Invalid version number for binary"
|
||||||
|
# Special builds will not have a proper version number
|
||||||
|
self.binary_version = version.parse("0.0.0")
|
||||||
|
|
||||||
self.binary_version = self.constants.patcher_version
|
self.latest_details = None
|
||||||
self.binary_version_array = [int(x) for x in self.binary_version.split(".")]
|
|
||||||
|
|
||||||
|
def check_if_newer(self, version: Union[str, version.Version]) -> bool:
|
||||||
def _check_if_build_newer(self, remote_version: list = None, local_version: list = None) -> bool:
|
|
||||||
"""
|
"""
|
||||||
Check if the remote version is newer than the local version
|
Check if the provided version is newer than the local version
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
remote_version (list): Remote version to compare against
|
version (str): Version to compare against
|
||||||
local_version (list): Local version to compare against
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if remote version is newer, False if not
|
bool: True if the provided version is newer, False if not
|
||||||
|
"""
|
||||||
|
if self.constants.special_build is True:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return self._check_if_build_newer(version, self.binary_version)
|
||||||
|
|
||||||
|
def _check_if_build_newer(self, first_version: Union[str, version.Version], second_version: Union[str, version.Version]) -> bool:
|
||||||
|
"""
|
||||||
|
Check if the first version is newer than the second version
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
first_version_str (str): First version to compare against (generally local)
|
||||||
|
second_version_str (str): Second version to compare against (generally remote)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if first version is newer, False if not
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if remote_version is None:
|
if not isinstance(first_version, version.Version):
|
||||||
remote_version = self.remote_version_array
|
try:
|
||||||
if local_version is None:
|
first_version = version.parse(first_version)
|
||||||
local_version = self.binary_version_array
|
except version.InvalidVersion:
|
||||||
|
# Special build > release build: assume special build is newer
|
||||||
|
return True
|
||||||
|
|
||||||
|
if not isinstance(second_version, version.Version):
|
||||||
|
try:
|
||||||
|
second_version = version.parse(second_version)
|
||||||
|
except version.InvalidVersion:
|
||||||
|
# Release build > special build: assume special build is newer
|
||||||
|
return False
|
||||||
|
|
||||||
if local_version == remote_version:
|
if first_version == second_version:
|
||||||
if not self.constants.commit_info[0].startswith("refs/tags"):
|
if not self.constants.commit_info[0].startswith("refs/tags"):
|
||||||
# Check for nightly builds
|
# Check for nightly builds
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Pad version numbers to match length (ie. 0.1.0 vs 0.1.0.1)
|
return first_version > second_version
|
||||||
while len(remote_version) > len(local_version):
|
|
||||||
local_version.append(0)
|
|
||||||
while len(remote_version) < len(local_version):
|
|
||||||
remote_version.append(0)
|
|
||||||
|
|
||||||
for i in range(0, len(remote_version)):
|
|
||||||
if int(remote_version[i]) < int(local_version[i]):
|
|
||||||
break
|
|
||||||
elif int(remote_version[i]) > int(local_version[i]):
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def _determine_local_build_type(self) -> str:
|
def _determine_local_build_type(self) -> str:
|
||||||
"""
|
"""
|
||||||
@@ -63,11 +80,7 @@ class CheckBinaryUpdates:
|
|||||||
str: "GUI" or "TUI"
|
str: "GUI" or "TUI"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self.constants.wxpython_variant is True:
|
return "GUI" if self.constants.wxpython_variant else "TUI"
|
||||||
return "GUI"
|
|
||||||
else:
|
|
||||||
return "TUI"
|
|
||||||
|
|
||||||
|
|
||||||
def _determine_remote_type(self, remote_name: str) -> str:
|
def _determine_remote_type(self, remote_name: str) -> str:
|
||||||
"""
|
"""
|
||||||
@@ -87,8 +100,7 @@ class CheckBinaryUpdates:
|
|||||||
else:
|
else:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
|
|
||||||
|
def check_binary_updates(self) -> Optional[dict]:
|
||||||
def check_binary_updates(self) -> dict:
|
|
||||||
"""
|
"""
|
||||||
Check if any updates are available for the OpenCore Legacy Patcher binary
|
Check if any updates are available for the OpenCore Legacy Patcher binary
|
||||||
|
|
||||||
@@ -96,7 +108,13 @@ class CheckBinaryUpdates:
|
|||||||
dict: Dictionary with Link and Version of the latest binary update if available
|
dict: Dictionary with Link and Version of the latest binary update if available
|
||||||
"""
|
"""
|
||||||
|
|
||||||
available_binaries: list = {}
|
if self.constants.special_build is True:
|
||||||
|
# Special builds do not get updates through the updater
|
||||||
|
return None
|
||||||
|
|
||||||
|
if self.latest_details:
|
||||||
|
# We already checked
|
||||||
|
return self.latest_details
|
||||||
|
|
||||||
if not network_handler.NetworkUtilities(REPO_LATEST_RELEASE_URL).verify_network_connection():
|
if not network_handler.NetworkUtilities(REPO_LATEST_RELEASE_URL).verify_network_connection():
|
||||||
return None
|
return None
|
||||||
@@ -107,26 +125,26 @@ class CheckBinaryUpdates:
|
|||||||
if "tag_name" not in data_set:
|
if "tag_name" not in data_set:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
self.remote_version = data_set["tag_name"]
|
# The release marked as latest will always be stable, and thus, have a proper version number
|
||||||
|
# But if not, let's not crash the program
|
||||||
|
try:
|
||||||
|
latest_remote_version = version.parse(data_set["tag_name"])
|
||||||
|
except version.InvalidVersion:
|
||||||
|
return None
|
||||||
|
|
||||||
self.remote_version_array = self.remote_version.split(".")
|
if not self._check_if_build_newer(latest_remote_version, self.binary_version):
|
||||||
self.remote_version_array = [int(x) for x in self.remote_version_array]
|
|
||||||
|
|
||||||
if self._check_if_build_newer() is False:
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for asset in data_set["assets"]:
|
for asset in data_set["assets"]:
|
||||||
logging.info(f"Found asset: {asset['name']}")
|
logging.info(f"Found asset: {asset['name']}")
|
||||||
if self._determine_remote_type(asset["name"]) == self._determine_local_build_type():
|
if self._determine_remote_type(asset["name"]) == self._determine_local_build_type():
|
||||||
available_binaries.update({
|
self.latest_details = {
|
||||||
asset['name']: {
|
"Name": asset["name"],
|
||||||
"Name": asset["name"],
|
"Version": latest_remote_version,
|
||||||
"Version": self.remote_version,
|
"Link": asset["browser_download_url"],
|
||||||
"Link": asset["browser_download_url"],
|
"Type": self._determine_remote_type(asset["name"]),
|
||||||
"Type": self._determine_remote_type(asset["name"]),
|
"Github Link": f"https://github.com/dortania/OpenCore-Legacy-Patcher/releases/{latest_remote_version}",
|
||||||
"Github Link": f"https://github.com/dortania/OpenCore-Legacy-Patcher/releases/{self.remote_version}"
|
}
|
||||||
}
|
return self.latest_details
|
||||||
})
|
|
||||||
return available_binaries
|
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk
|
# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import atexit
|
||||||
|
import binascii
|
||||||
|
import logging
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
import plistlib
|
import plistlib
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import os
|
|
||||||
import binascii
|
|
||||||
import argparse
|
|
||||||
import atexit
|
|
||||||
import shutil
|
|
||||||
import py_sip_xnu
|
import py_sip_xnu
|
||||||
|
|
||||||
import logging
|
from data import os_data, sip_data
|
||||||
|
|
||||||
from resources import constants, ioreg
|
from resources import constants, ioreg
|
||||||
from data import sip_data, os_data
|
|
||||||
|
|
||||||
|
|
||||||
def hexswap(input_hex: str):
|
def hexswap(input_hex: str):
|
||||||
@@ -173,15 +172,35 @@ def enable_sleep_after_running():
|
|||||||
sleep_process = None
|
sleep_process = None
|
||||||
|
|
||||||
|
|
||||||
def check_kext_loaded(kext_name, os_version):
|
def check_kext_loaded(bundle_id: str) -> str:
|
||||||
if os_version > os_data.os_data.catalina:
|
"""
|
||||||
kext_loaded = subprocess.run(["kmutil", "showloaded", "--list-only", "--variant-suffix", "release"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
Checks if a kext is loaded
|
||||||
else:
|
|
||||||
kext_loaded = subprocess.run(["kextstat", "-l"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
Parameters:
|
||||||
if kext_name in kext_loaded.stdout.decode():
|
bundle_id (str): The bundle ID of the kext to check
|
||||||
return True
|
|
||||||
else:
|
Returns:
|
||||||
return False
|
str: The version of the kext if it is loaded, or "" if it is not loaded
|
||||||
|
"""
|
||||||
|
# Name (Version) UUID <Linked Against>
|
||||||
|
# no UUID for kextstat
|
||||||
|
pattern = re.compile(re.escape(bundle_id) + r"\s+\((?P<version>.+)\)")
|
||||||
|
|
||||||
|
args = ["kextstat", "-l", "-b", bundle_id]
|
||||||
|
|
||||||
|
if Path("/usr/bin/kmutil").exists():
|
||||||
|
args = ["kmutil", "showloaded", "--list-only", "--variant-suffix", "release", "--optional-identifier", bundle_id]
|
||||||
|
|
||||||
|
kext_loaded = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
if kext_loaded.returncode != 0:
|
||||||
|
return ""
|
||||||
|
output = kext_loaded.stdout.decode()
|
||||||
|
if not output.strip():
|
||||||
|
return ""
|
||||||
|
match = pattern.search(output)
|
||||||
|
if match:
|
||||||
|
return match.group("version")
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def check_oclp_boot():
|
def check_oclp_boot():
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class MainFrame(wx.Frame):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Title label: OpenCore Legacy Patcher v{X.Y.Z}
|
# Title label: OpenCore Legacy Patcher v{X.Y.Z}
|
||||||
title_label = wx.StaticText(self, label=f"OpenCore Legacy Patcher v{self.constants.patcher_version}", pos=(-1,10))
|
title_label = wx.StaticText(self, label=f"OpenCore Legacy Patcher {'' if self.constants.special_build else 'v'}{self.constants.patcher_version}", pos=(-1, 10))
|
||||||
title_label.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
title_label.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
||||||
title_label.Centre(wx.HORIZONTAL)
|
title_label.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
@@ -282,22 +282,21 @@ class MainFrame(wx.Frame):
|
|||||||
if not dict:
|
if not dict:
|
||||||
return
|
return
|
||||||
|
|
||||||
for entry in dict:
|
version = dict["Version"]
|
||||||
version = dict[entry]["Version"]
|
logging.info(f"New version: {version}")
|
||||||
logging.info(f"New version: {version}")
|
dialog = wx.MessageDialog(
|
||||||
dialog = wx.MessageDialog(
|
parent=self,
|
||||||
parent=self,
|
message=f"Current Version: {self.constants.patcher_version}{' (Nightly)' if not self.constants.commit_info[0].startswith('refs/tags') else ''}\nNew version: {version}\nWould you like to update?",
|
||||||
message=f"Current Version: {self.constants.patcher_version}{' (Nightly)' if not self.constants.commit_info[0].startswith('refs/tags') else ''}\nNew version: {version}\nWould you like to update?",
|
caption="Update Available for OpenCore Legacy Patcher!",
|
||||||
caption="Update Available for OpenCore Legacy Patcher!",
|
style=wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION
|
||||||
style=wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION
|
)
|
||||||
)
|
dialog.SetYesNoCancelLabels("Download and install", "Ignore", "View on Github")
|
||||||
dialog.SetYesNoCancelLabels("Download and install", "Ignore", "View on Github")
|
response = dialog.ShowModal()
|
||||||
response = dialog.ShowModal()
|
|
||||||
|
|
||||||
if response == wx.ID_YES:
|
if response == wx.ID_YES:
|
||||||
wx.CallAfter(self.on_update, dict[entry]["Link"], version)
|
wx.CallAfter(self.on_update, dict["Link"], version)
|
||||||
elif response == wx.ID_CANCEL:
|
elif response == wx.ID_CANCEL:
|
||||||
webbrowser.open(dict[entry]["Github Link"])
|
webbrowser.open(dict["Github Link"])
|
||||||
|
|
||||||
|
|
||||||
def on_build_and_install(self, event: wx.Event = None):
|
def on_build_and_install(self, event: wx.Event = None):
|
||||||
|
|||||||
@@ -48,10 +48,8 @@ class UpdateFrame(wx.Frame):
|
|||||||
if url == "" or version_label == "":
|
if url == "" or version_label == "":
|
||||||
dict = updates.CheckBinaryUpdates(self.constants).check_binary_updates()
|
dict = updates.CheckBinaryUpdates(self.constants).check_binary_updates()
|
||||||
if dict:
|
if dict:
|
||||||
for key in dict:
|
version_label = dict["Version"]
|
||||||
version_label = dict[key]["Version"]
|
url = dict["Link"]
|
||||||
url = dict[key]["Link"]
|
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
wx.MessageBox("Failed to get update info", "Critical Error")
|
wx.MessageBox("Failed to get update info", "Critical Error")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|||||||
Reference in New Issue
Block a user