mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-06-19 05:40:01 +10:00
@@ -32,3 +32,4 @@ __pycache__/
|
|||||||
/payloads.dmg
|
/payloads.dmg
|
||||||
/payloads/OpenCore-Legacy-Patcher-*.plist
|
/payloads/OpenCore-Legacy-Patcher-*.plist
|
||||||
/payloads/KDK.dmg
|
/payloads/KDK.dmg
|
||||||
|
*.log
|
||||||
|
|||||||
+13
-2
@@ -7,8 +7,19 @@
|
|||||||
- Ensure `Moraea_BlurBeta` is set on non-Metal systems
|
- Ensure `Moraea_BlurBeta` is set on non-Metal systems
|
||||||
- Implement proper Root Unpatching verification in GUI
|
- Implement proper Root Unpatching verification in GUI
|
||||||
- Removes arbitrary patch requirements used against unpatching (ex. network connection)
|
- Removes arbitrary patch requirements used against unpatching (ex. network connection)
|
||||||
- Prioritize KdkSupportPkg repository for downloads
|
- Backend Changes:
|
||||||
- Skips calls to Apple's now defunct Developer Portal API
|
- Refactored kdk_handler.py
|
||||||
|
- Prioritizes KdkSupportPkg repository for downloads
|
||||||
|
- Skips calls to Apple's now defunct Developer Portal API
|
||||||
|
- Support local loose matching when no network connection is available
|
||||||
|
- Implemented logging framework usage for more reliable logging
|
||||||
|
- Logs are stored under `~/OpenCore-Patcher.log`
|
||||||
|
- Subsequent runs are appended to the log, allowing for easy debugging
|
||||||
|
- Implemented new network_handler.py module
|
||||||
|
- Allows for more reliable network calls and downloads
|
||||||
|
- Better supports network timeouts and disconnects
|
||||||
|
- Dramatically less noise in console during downloads
|
||||||
|
- Remove unused sys_patch_downloader.py module
|
||||||
- Increment Binaries:
|
- Increment Binaries:
|
||||||
- PatcherSupportPkg 0.8.3 - release
|
- PatcherSupportPkg 0.8.3 - release
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Our project's main goal is to breath new life to Macs no longer supported by App
|
|||||||
|
|
||||||
Noteworthy features of OpenCore Legacy Patcher:
|
Noteworthy features of OpenCore Legacy Patcher:
|
||||||
|
|
||||||
* Support for macOS Big Sur and Monterey
|
* Support for macOS Big Sur, Monterey and Ventura
|
||||||
* Native Over the Air(OTA) System Updates
|
* Native Over the Air(OTA) System Updates
|
||||||
* Supports Penryn and newer Macs
|
* Supports Penryn and newer Macs
|
||||||
* Full support for WPA Wifi and Personal Hotspot on BCM943224 and newer chipsets
|
* Full support for WPA Wifi and Personal Hotspot on BCM943224 and newer chipsets
|
||||||
@@ -32,7 +32,7 @@ Note: Only clean-installs and upgrades are supported, macOS Big Sur installs alr
|
|||||||
|
|
||||||
* You can however reinstall macOS with this patcher and retain your original data
|
* You can however reinstall macOS with this patcher and retain your original data
|
||||||
|
|
||||||
Note 2: Currently OpenCore Legacy Patcher officially supports patching to run macOS Big Sur and Monterey installs. For older OSes, OpenCore may function however support is currently not provided from Dortania.
|
Note 2: Currently OpenCore Legacy Patcher officially supports patching to run macOS Big Sur through Ventura installs. For older OSes, OpenCore may function however support is currently not provided from Dortania.
|
||||||
|
|
||||||
* For macOS Mojave and Catalina support, we recommend the use of [dosdude1's patchers](http://dosdude1.com)
|
* For macOS Mojave and Catalina support, we recommend the use of [dosdude1's patchers](http://dosdude1.com)
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -15,7 +15,7 @@
|
|||||||
* [Black Boxes on HD3000 iGPUs](#black-boxes-on-hd3000-igpus)
|
* [Black Boxes on HD3000 iGPUs](#black-boxes-on-hd3000-igpus)
|
||||||
* [Cannot Pair Bluetooth Devices](#cannot-pair-bluetooth-devices)
|
* [Cannot Pair Bluetooth Devices](#cannot-pair-bluetooth-devices)
|
||||||
|
|
||||||
The below page is for users experiencing issues with their overall usage of macOS Big Sur / macOS Monterey and the Legacy Graphics Acceleration patches. Note that the following GPUs currently do not have acceleration support in Big Sur / Monterey:
|
The below page is for users experiencing issues with their overall usage of macOS Big Sur / Monterey / Ventura and the Legacy Graphics Acceleration patches. Note that the following GPUs currently do not have acceleration support in Big Sur / Monterey / Ventura:
|
||||||
|
|
||||||
* Intel 3rd and 4th Gen - GMA series
|
* Intel 3rd and 4th Gen - GMA series
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ For those unfamiliar with what is considered a non-Metal GPU, see the chart belo
|
|||||||
|
|
||||||
::: details macOS GPU Chart
|
::: details macOS GPU Chart
|
||||||
|
|
||||||
Metal is Apple's in-house graphics API that acts as a replacement for OpenGL/OpenCL, introduced in 2015. With the release of macOS Mojave, every system without a Metal-capable GPU was dropped.
|
Metal is Apple's in-house graphics API that acts as a replacement for OpenGL/OpenCL, introduced in 2015. With the release of macOS Mojave, every system without a Metal-capable GPU was dropped.
|
||||||
|
|
||||||
| Graphics Vendor | Architecture | Series | Supports Metal |
|
| Graphics Vendor | Architecture | Series | Supports Metal |
|
||||||
| :--- | :--- | :--- | :--- |
|
| :--- | :--- | :--- | :--- |
|
||||||
@@ -31,7 +31,7 @@ Metal is Apple's in-house graphics API that acts as a replacement for OpenGL/Ope
|
|||||||
| ^^ | TeraScale 2 | HD5000 - HD6000 | ^^ |
|
| ^^ | TeraScale 2 | HD5000 - HD6000 | ^^ |
|
||||||
| AMD | GCN (and newer) | HD7000+ | <span style="color:green">Yes</span> |
|
| AMD | GCN (and newer) | HD7000+ | <span style="color:green">Yes</span> |
|
||||||
| NVIDIA | Tesla | 8000GT - GT300 | <span style="color:red">No</span> |
|
| NVIDIA | Tesla | 8000GT - GT300 | <span style="color:red">No</span> |
|
||||||
| ^^ | Fermi | GT400 - GT500 | ^^ |
|
| ^^ | Fermi | GT400 - GT500 | ^^ |
|
||||||
| ^^ | Kepler | GT600 - GT700 | <span style="color:green">Yes</span> |
|
| ^^ | Kepler | GT600 - GT700 | <span style="color:green">Yes</span> |
|
||||||
| Intel | GMA | GMA900 - GMA3000 | <span style="color:red">No</span> |
|
| Intel | GMA | GMA900 - GMA3000 | <span style="color:red">No</span> |
|
||||||
| ^^ | Iron Lake | HD series | ^^ |
|
| ^^ | Iron Lake | HD series | ^^ |
|
||||||
@@ -102,7 +102,7 @@ Due to the Metal Backend, the enhanced color output of these apps seems to heavi
|
|||||||
|
|
||||||
## Cannot press "Done" when editing a Sidebar Widget
|
## Cannot press "Done" when editing a Sidebar Widget
|
||||||
|
|
||||||
Workaround: Press some combination of Tab, or Tab and then Shift-Tab, or just Shift-Tab until the "Done" button is highlighted. Then press spacebar to activate the button, the same as in any other dialog with a highlighted button halo.
|
Workaround: Press some combination of Tab, or Tab and then Shift-Tab, or just Shift-Tab until the "Done" button is highlighted. Then press spacebar to activate the button, the same as in any other dialog with a highlighted button halo.
|
||||||
|
|
||||||
## Wake from sleep heavily distorted on AMD/ATI in macOS 11.3 and newer
|
## Wake from sleep heavily distorted on AMD/ATI in macOS 11.3 and newer
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ 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 - Monterey 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.
|
* 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 |
|
||||||
| :--- | :--- | :--- | :--- |
|
| :--- | :--- | :--- | :--- |
|
||||||
|
|||||||
+24
-23
@@ -5,6 +5,7 @@ from resources.build import build
|
|||||||
from data import model_array
|
from data import model_array
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import logging
|
||||||
|
|
||||||
# Generic building args
|
# Generic building args
|
||||||
class arguments:
|
class arguments:
|
||||||
@@ -17,68 +18,68 @@ class arguments:
|
|||||||
elif self.args.build:
|
elif self.args.build:
|
||||||
if self.args.model:
|
if self.args.model:
|
||||||
if self.args.model:
|
if self.args.model:
|
||||||
print(f"- Using custom model: {self.args.model}")
|
logging.info(f"- Using custom model: {self.args.model}")
|
||||||
settings.custom_model = self.args.model
|
settings.custom_model = self.args.model
|
||||||
defaults.generate_defaults(settings.custom_model, False, settings)
|
defaults.generate_defaults(settings.custom_model, False, settings)
|
||||||
elif settings.computer.real_model not in model_array.SupportedSMBIOS and settings.allow_oc_everywhere is False:
|
elif settings.computer.real_model not in model_array.SupportedSMBIOS and settings.allow_oc_everywhere is False:
|
||||||
print(
|
logging.info(
|
||||||
"""Your model is not supported by this patcher for running unsupported OSes!"
|
"""Your model is not supported by this patcher for running unsupported OSes!"
|
||||||
|
|
||||||
If you plan to create the USB for another machine, please select the "Change Model" option in the menu."""
|
If you plan to create the USB for another machine, please select the "Change Model" option in the menu."""
|
||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
print(f"- Using detected model: {settings.computer.real_model}")
|
logging.info(f"- Using detected model: {settings.computer.real_model}")
|
||||||
defaults.generate_defaults(settings.custom_model, True, settings)
|
defaults.generate_defaults(settings.custom_model, True, settings)
|
||||||
|
|
||||||
if self.args.disk:
|
if self.args.disk:
|
||||||
print(f"- Install Disk set: {self.args.disk}")
|
logging.info(f"- Install Disk set: {self.args.disk}")
|
||||||
settings.disk = self.args.disk
|
settings.disk = self.args.disk
|
||||||
if self.args.verbose:
|
if self.args.verbose:
|
||||||
print("- Set verbose configuration")
|
logging.info("- Set verbose configuration")
|
||||||
settings.verbose_debug = True
|
settings.verbose_debug = True
|
||||||
else:
|
else:
|
||||||
settings.verbose_debug = False # Override Defaults detected
|
settings.verbose_debug = False # Override Defaults detected
|
||||||
if self.args.debug_oc:
|
if self.args.debug_oc:
|
||||||
print("- Set OpenCore DEBUG configuration")
|
logging.info("- Set OpenCore DEBUG configuration")
|
||||||
settings.opencore_debug = True
|
settings.opencore_debug = True
|
||||||
settings.opencore_build = "DEBUG"
|
settings.opencore_build = "DEBUG"
|
||||||
if self.args.debug_kext:
|
if self.args.debug_kext:
|
||||||
print("- Set kext DEBUG configuration")
|
logging.info("- Set kext DEBUG configuration")
|
||||||
settings.kext_debug = True
|
settings.kext_debug = True
|
||||||
if self.args.hide_picker:
|
if self.args.hide_picker:
|
||||||
print("- Set HidePicker configuration")
|
logging.info("- Set HidePicker configuration")
|
||||||
settings.showpicker = False
|
settings.showpicker = False
|
||||||
if self.args.disable_sip:
|
if self.args.disable_sip:
|
||||||
print("- Set Disable SIP configuration")
|
logging.info("- Set Disable SIP configuration")
|
||||||
settings.sip_status = False
|
settings.sip_status = False
|
||||||
else:
|
else:
|
||||||
settings.sip_status = True # Override Defaults detected
|
settings.sip_status = True # Override Defaults detected
|
||||||
if self.args.disable_smb:
|
if self.args.disable_smb:
|
||||||
print("- Set Disable SecureBootModel configuration")
|
logging.info("- Set Disable SecureBootModel configuration")
|
||||||
settings.secure_status = False
|
settings.secure_status = False
|
||||||
else:
|
else:
|
||||||
settings.secure_status = True # Override Defaults detected
|
settings.secure_status = True # Override Defaults detected
|
||||||
if self.args.vault:
|
if self.args.vault:
|
||||||
print("- Set Vault configuration")
|
logging.info("- Set Vault configuration")
|
||||||
settings.vault = True
|
settings.vault = True
|
||||||
if self.args.firewire:
|
if self.args.firewire:
|
||||||
print("- Set FireWire Boot configuration")
|
logging.info("- Set FireWire Boot configuration")
|
||||||
settings.firewire_boot = True
|
settings.firewire_boot = True
|
||||||
if self.args.nvme:
|
if self.args.nvme:
|
||||||
print("- Set NVMe Boot configuration")
|
logging.info("- Set NVMe Boot configuration")
|
||||||
settings.nvme_boot = True
|
settings.nvme_boot = True
|
||||||
if self.args.wlan:
|
if self.args.wlan:
|
||||||
print("- Set Wake on WLAN configuration")
|
logging.info("- Set Wake on WLAN configuration")
|
||||||
settings.enable_wake_on_wlan = True
|
settings.enable_wake_on_wlan = True
|
||||||
if self.args.disable_tb:
|
if self.args.disable_tb:
|
||||||
print("- Set Disable Thunderbolt configuration")
|
logging.info("- Set Disable Thunderbolt configuration")
|
||||||
settings.disable_tb = True
|
settings.disable_tb = True
|
||||||
if self.args.force_surplus:
|
if self.args.force_surplus:
|
||||||
print("- Forcing SurPlus override configuration")
|
logging.info("- Forcing SurPlus override configuration")
|
||||||
settings.force_surplus = True
|
settings.force_surplus = True
|
||||||
if self.args.moderate_smbios:
|
if self.args.moderate_smbios:
|
||||||
print("- Set Moderate SMBIOS Patching configuration")
|
logging.info("- Set Moderate SMBIOS Patching configuration")
|
||||||
settings.serial_settings = "Moderate"
|
settings.serial_settings = "Moderate"
|
||||||
if self.args.smbios_spoof:
|
if self.args.smbios_spoof:
|
||||||
if self.args.smbios_spoof == "Minimal":
|
if self.args.smbios_spoof == "Minimal":
|
||||||
@@ -88,18 +89,18 @@ class arguments:
|
|||||||
elif self.args.smbios_spoof == "Advanced":
|
elif self.args.smbios_spoof == "Advanced":
|
||||||
settings.serial_settings = "Advanced"
|
settings.serial_settings = "Advanced"
|
||||||
else:
|
else:
|
||||||
print(f"- Unknown SMBIOS arg passed: {self.args.smbios_spoof}")
|
logging.info(f"- Unknown SMBIOS arg passed: {self.args.smbios_spoof}")
|
||||||
|
|
||||||
if self.args.support_all:
|
if self.args.support_all:
|
||||||
print("- Building for natively supported model")
|
logging.info("- Building for natively supported model")
|
||||||
settings.allow_oc_everywhere = True
|
settings.allow_oc_everywhere = True
|
||||||
settings.serial_settings = "None"
|
settings.serial_settings = "None"
|
||||||
build.build_opencore(settings.custom_model or settings.computer.real_model, settings).build_opencore()
|
build.build_opencore(settings.custom_model or settings.computer.real_model, settings).build_opencore()
|
||||||
elif self.args.patch_sys_vol:
|
elif self.args.patch_sys_vol:
|
||||||
print("- Set System Volume patching")
|
logging.info("- Set System Volume patching")
|
||||||
|
|
||||||
if "Library/InstallerSandboxes/" in str(settings.payload_path):
|
if "Library/InstallerSandboxes/" in str(settings.payload_path):
|
||||||
print("- Running from Installer Sandbox")
|
logging.info("- Running from Installer Sandbox")
|
||||||
thread = threading.Thread(target=sys_patch.PatchSysVolume(settings.custom_model or settings.computer.real_model, settings, None).start_patch)
|
thread = threading.Thread(target=sys_patch.PatchSysVolume(settings.custom_model or settings.computer.real_model, settings, None).start_patch)
|
||||||
thread.start()
|
thread.start()
|
||||||
while thread.is_alive():
|
while thread.is_alive():
|
||||||
@@ -108,8 +109,8 @@ class arguments:
|
|||||||
else:
|
else:
|
||||||
sys_patch.PatchSysVolume(settings.custom_model or settings.computer.real_model, settings, None).start_patch()
|
sys_patch.PatchSysVolume(settings.custom_model or settings.computer.real_model, settings, None).start_patch()
|
||||||
elif self.args.unpatch_sys_vol:
|
elif self.args.unpatch_sys_vol:
|
||||||
print("- Set System Volume unpatching")
|
logging.info("- Set System Volume unpatching")
|
||||||
sys_patch.PatchSysVolume(settings.custom_model or settings.computer.real_model, settings, None).start_unpatch()
|
sys_patch.PatchSysVolume(settings.custom_model or settings.computer.real_model, settings, None).start_unpatch()
|
||||||
elif self.args.auto_patch:
|
elif self.args.auto_patch:
|
||||||
print("- Set Auto patching")
|
logging.info("- Set Auto patching")
|
||||||
sys_patch_auto.AutomaticSysPatch(settings).start_auto_patch()
|
sys_patch_auto.AutomaticSysPatch(settings).start_auto_patch()
|
||||||
@@ -5,6 +5,8 @@ from resources import constants, device_probe
|
|||||||
from resources.build import support
|
from resources.build import support
|
||||||
from data import smbios_data, bluetooth_data
|
from data import smbios_data, bluetooth_data
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
class build_bluetooth:
|
class build_bluetooth:
|
||||||
|
|
||||||
def __init__(self, model, versions, config):
|
def __init__(self, model, versions, config):
|
||||||
@@ -24,7 +26,7 @@ class build_bluetooth:
|
|||||||
|
|
||||||
def on_model(self):
|
def on_model(self):
|
||||||
if self.computer.bluetooth_chipset in ["BRCM2070 Hub", "BRCM2046 Hub"]:
|
if self.computer.bluetooth_chipset in ["BRCM2070 Hub", "BRCM2046 Hub"]:
|
||||||
print("- Fixing Legacy Bluetooth for macOS Monterey")
|
logging.info("- Fixing Legacy Bluetooth for macOS Monterey")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("Bluetooth-Spoof.kext", self.constants.btspoof_version, self.constants.btspoof_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("Bluetooth-Spoof.kext", self.constants.btspoof_version, self.constants.btspoof_path)
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -btlfxallowanyaddr"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -btlfxallowanyaddr"
|
||||||
@@ -34,12 +36,12 @@ class build_bluetooth:
|
|||||||
# Due to this, BlueToolFixup is required to resolve Firmware Uploading on legacy chipsets
|
# Due to this, BlueToolFixup is required to resolve Firmware Uploading on legacy chipsets
|
||||||
if self.computer.wifi:
|
if self.computer.wifi:
|
||||||
if self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirPortBrcm4360:
|
if self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirPortBrcm4360:
|
||||||
print("- Fixing Legacy Bluetooth for macOS Monterey")
|
logging.info("- Fixing Legacy Bluetooth for macOS Monterey")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
|
||||||
elif self.computer.bluetooth_chipset == "3rd Party Bluetooth 4.0 Hub":
|
elif self.computer.bluetooth_chipset == "3rd Party Bluetooth 4.0 Hub":
|
||||||
print("- Detected 3rd Party Bluetooth Chipset")
|
logging.info("- Detected 3rd Party Bluetooth Chipset")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
|
||||||
print("- Enabling Bluetooth FeatureFlags")
|
logging.info("- Enabling Bluetooth FeatureFlags")
|
||||||
self.config["Kernel"]["Quirks"]["ExtendBTFeatureFlags"] = True
|
self.config["Kernel"]["Quirks"]["ExtendBTFeatureFlags"] = True
|
||||||
|
|
||||||
|
|
||||||
@@ -50,7 +52,7 @@ class build_bluetooth:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if smbios_data.smbios_dictionary[self.model]["Bluetooth Model"] <= bluetooth_data.bluetooth_data.BRCM20702_v1.value:
|
if smbios_data.smbios_dictionary[self.model]["Bluetooth Model"] <= bluetooth_data.bluetooth_data.BRCM20702_v1.value:
|
||||||
print("- Fixing Legacy Bluetooth for macOS Monterey")
|
logging.info("- Fixing Legacy Bluetooth for macOS Monterey")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
|
||||||
if smbios_data.smbios_dictionary[self.model]["Bluetooth Model"] <= bluetooth_data.bluetooth_data.BRCM2070.value:
|
if smbios_data.smbios_dictionary[self.model]["Bluetooth Model"] <= bluetooth_data.bluetooth_data.BRCM2070.value:
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -btlfxallowanyaddr"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -btlfxallowanyaddr"
|
||||||
|
|||||||
+15
-13
@@ -8,6 +8,7 @@ import shutil
|
|||||||
import zipfile
|
import zipfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
import logging
|
||||||
|
|
||||||
from resources import constants, utilities
|
from resources import constants, utilities
|
||||||
from resources.build import bluetooth, firmware, graphics_audio, support, storage, smbios, security, misc
|
from resources.build import bluetooth, firmware, graphics_audio, support, storage, smbios, security, misc
|
||||||
@@ -30,9 +31,9 @@ class build_opencore:
|
|||||||
def build_efi(self):
|
def build_efi(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
if not self.constants.custom_model:
|
if not self.constants.custom_model:
|
||||||
print(f"Building Configuration on model: {self.model}")
|
logging.info(f"Building Configuration on model: {self.model}")
|
||||||
else:
|
else:
|
||||||
print(f"Building Configuration for external model: {self.model}")
|
logging.info(f"Building Configuration for external model: {self.model}")
|
||||||
|
|
||||||
self.generate_base()
|
self.generate_base()
|
||||||
self.set_revision()
|
self.set_revision()
|
||||||
@@ -54,31 +55,32 @@ class build_opencore:
|
|||||||
|
|
||||||
# Work-around ocvalidate
|
# Work-around ocvalidate
|
||||||
if self.constants.validate is False:
|
if self.constants.validate is False:
|
||||||
print("- Adding bootmgfw.efi BlessOverride")
|
logging.info("- Adding bootmgfw.efi BlessOverride")
|
||||||
self.config["Misc"]["BlessOverride"] += ["\\EFI\\Microsoft\\Boot\\bootmgfw.efi"]
|
self.config["Misc"]["BlessOverride"] += ["\\EFI\\Microsoft\\Boot\\bootmgfw.efi"]
|
||||||
|
|
||||||
|
|
||||||
def generate_base(self):
|
def generate_base(self):
|
||||||
# Generate OpenCore base folder and config
|
# Generate OpenCore base folder and config
|
||||||
if not Path(self.constants.build_path).exists():
|
if not Path(self.constants.build_path).exists():
|
||||||
print("Creating build folder")
|
logging.info("Creating build folder")
|
||||||
Path(self.constants.build_path).mkdir()
|
Path(self.constants.build_path).mkdir()
|
||||||
else:
|
else:
|
||||||
print("Build folder already present, skipping")
|
logging.info("Build folder already present, skipping")
|
||||||
|
|
||||||
if Path(self.constants.opencore_zip_copied).exists():
|
if Path(self.constants.opencore_zip_copied).exists():
|
||||||
print("Deleting old copy of OpenCore zip")
|
logging.info("Deleting old copy of OpenCore zip")
|
||||||
Path(self.constants.opencore_zip_copied).unlink()
|
Path(self.constants.opencore_zip_copied).unlink()
|
||||||
if Path(self.constants.opencore_release_folder).exists():
|
if Path(self.constants.opencore_release_folder).exists():
|
||||||
print("Deleting old copy of OpenCore folder")
|
logging.info("Deleting old copy of OpenCore folder")
|
||||||
shutil.rmtree(self.constants.opencore_release_folder, onerror=rmtree_handler, ignore_errors=True)
|
shutil.rmtree(self.constants.opencore_release_folder, onerror=rmtree_handler, ignore_errors=True)
|
||||||
|
|
||||||
print(f"\n- Adding OpenCore v{self.constants.opencore_version} {self.constants.opencore_build}")
|
logging.info("")
|
||||||
|
logging.info(f"- Adding OpenCore v{self.constants.opencore_version} {self.constants.opencore_build}")
|
||||||
shutil.copy(self.constants.opencore_zip_source, self.constants.build_path)
|
shutil.copy(self.constants.opencore_zip_source, self.constants.build_path)
|
||||||
zipfile.ZipFile(self.constants.opencore_zip_copied).extractall(self.constants.build_path)
|
zipfile.ZipFile(self.constants.opencore_zip_copied).extractall(self.constants.build_path)
|
||||||
|
|
||||||
# Setup config.plist for editing
|
# Setup config.plist for editing
|
||||||
print("- Adding config.plist for OpenCore")
|
logging.info("- Adding config.plist for OpenCore")
|
||||||
shutil.copy(self.constants.plist_template, self.constants.oc_folder)
|
shutil.copy(self.constants.plist_template, self.constants.oc_folder)
|
||||||
self.config = plistlib.load(Path(self.constants.plist_path).open("rb"))
|
self.config = plistlib.load(Path(self.constants.plist_path).open("rb"))
|
||||||
|
|
||||||
@@ -115,9 +117,9 @@ class build_opencore:
|
|||||||
support.build_support(self.model, self.constants, self.config).sign_files()
|
support.build_support(self.model, self.constants, self.config).sign_files()
|
||||||
support.build_support(self.model, self.constants, self.config).validate_pathing()
|
support.build_support(self.model, self.constants, self.config).validate_pathing()
|
||||||
|
|
||||||
print("")
|
logging.info("")
|
||||||
print(f"Your OpenCore EFI for {self.model} has been built at:")
|
logging.info(f"Your OpenCore EFI for {self.model} has been built at:")
|
||||||
print(f" {self.constants.opencore_release_folder}")
|
logging.info(f" {self.constants.opencore_release_folder}")
|
||||||
print("")
|
logging.info("")
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
input("Press [Enter] to continue\n")
|
input("Press [Enter] to continue\n")
|
||||||
|
|||||||
+20
-20
@@ -5,7 +5,7 @@ from resources import constants, generate_smbios
|
|||||||
from resources.build import support
|
from resources.build import support
|
||||||
from data import smbios_data, cpu_data
|
from data import smbios_data, cpu_data
|
||||||
|
|
||||||
import binascii, shutil
|
import binascii, shutil, logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
class build_firmware:
|
class build_firmware:
|
||||||
@@ -50,7 +50,7 @@ class build_firmware:
|
|||||||
# This breaks AppleIntelCPUPowerManagement.kext matching as it no longer matches against the correct criteria
|
# This breaks AppleIntelCPUPowerManagement.kext matching as it no longer matches against the correct criteria
|
||||||
#
|
#
|
||||||
# To resolve, we patched AICPUPM to attach regardless of the value of 'intel_cpupm_matching'
|
# To resolve, we patched AICPUPM to attach regardless of the value of 'intel_cpupm_matching'
|
||||||
print("- Enabling legacy power management support")
|
logging.info("- Enabling legacy power management support")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("AppleIntelCPUPowerManagement.kext", self.constants.aicpupm_version, self.constants.aicpupm_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("AppleIntelCPUPowerManagement.kext", self.constants.aicpupm_version, self.constants.aicpupm_path)
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("AppleIntelCPUPowerManagementClient.kext", self.constants.aicpupm_version, self.constants.aicpupm_client_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("AppleIntelCPUPowerManagementClient.kext", self.constants.aicpupm_version, self.constants.aicpupm_client_path)
|
||||||
|
|
||||||
@@ -60,14 +60,14 @@ class build_firmware:
|
|||||||
# This causes power management to break on pre-Ivy Bridge CPUs as they don't have correct
|
# This causes power management to break on pre-Ivy Bridge CPUs as they don't have correct
|
||||||
# power management tables provided.
|
# power management tables provided.
|
||||||
# This patch will simply increase ASPP's 'IOProbeScore' to outmatch X86PP
|
# This patch will simply increase ASPP's 'IOProbeScore' to outmatch X86PP
|
||||||
print("- Overriding ACPI SMC matching")
|
logging.info("- Overriding ACPI SMC matching")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("ASPP-Override.kext", self.constants.aspp_override_version, self.constants.aspp_override_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("ASPP-Override.kext", self.constants.aspp_override_version, self.constants.aspp_override_path)
|
||||||
if self.constants.disable_xcpm is True:
|
if self.constants.disable_xcpm is True:
|
||||||
# Only inject on older OSes if user requests
|
# Only inject on older OSes if user requests
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Add"], "BundlePath", "ASPP-Override.kext")["MinKernel"] = ""
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Add"], "BundlePath", "ASPP-Override.kext")["MinKernel"] = ""
|
||||||
|
|
||||||
if self.constants.disable_msr_power_ctl is True and smbios_data.smbios_dictionary[self.model]["CPU Generation"] >= cpu_data.cpu_data.nehalem.value:
|
if self.constants.disable_msr_power_ctl is True and smbios_data.smbios_dictionary[self.model]["CPU Generation"] >= cpu_data.cpu_data.nehalem.value:
|
||||||
print("- Disabling Firmware Throttling")
|
logging.info("- Disabling Firmware Throttling")
|
||||||
# Nehalem and newer systems force firmware throttling via MSR_POWER_CTL
|
# Nehalem and newer systems force firmware throttling via MSR_POWER_CTL
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("SimpleMSR.kext", self.constants.simplemsr_version, self.constants.simplemsr_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("SimpleMSR.kext", self.constants.simplemsr_version, self.constants.simplemsr_path)
|
||||||
|
|
||||||
@@ -82,14 +82,14 @@ class build_firmware:
|
|||||||
# CPBG device in ACPI is a Co-Processor Bridge Device, which is not actually physically present
|
# CPBG device in ACPI is a Co-Processor Bridge Device, which is not actually physically present
|
||||||
# IOPCIFamily will error when enumerating this device, thus we'll power it off via _STA (has no effect in older OSes)
|
# IOPCIFamily will error when enumerating this device, thus we'll power it off via _STA (has no effect in older OSes)
|
||||||
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] == cpu_data.cpu_data.nehalem.value and not (self.model.startswith("MacPro") or self.model.startswith("Xserve")):
|
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] == cpu_data.cpu_data.nehalem.value and not (self.model.startswith("MacPro") or self.model.startswith("Xserve")):
|
||||||
print("- Adding SSDT-CPBG.aml")
|
logging.info("- Adding SSDT-CPBG.aml")
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Add"], "Path", "SSDT-CPBG.aml")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Add"], "Path", "SSDT-CPBG.aml")["Enabled"] = True
|
||||||
shutil.copy(self.constants.pci_ssdt_path, self.constants.acpi_path)
|
shutil.copy(self.constants.pci_ssdt_path, self.constants.acpi_path)
|
||||||
|
|
||||||
if cpu_data.cpu_data.sandy_bridge <= smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.ivy_bridge.value and self.model != "MacPro6,1":
|
if cpu_data.cpu_data.sandy_bridge <= smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.ivy_bridge.value and self.model != "MacPro6,1":
|
||||||
# Based on: https://egpu.io/forums/pc-setup/fix-dsdt-override-to-correct-error-12/
|
# Based on: https://egpu.io/forums/pc-setup/fix-dsdt-override-to-correct-error-12/
|
||||||
# Applicable for Sandy and Ivy Bridge Macs
|
# Applicable for Sandy and Ivy Bridge Macs
|
||||||
print("- Enabling Windows 10 UEFI Audio support")
|
logging.info("- Enabling Windows 10 UEFI Audio support")
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Add"], "Path", "SSDT-PCI.aml")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Add"], "Path", "SSDT-PCI.aml")["Enabled"] = True
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "BUF0 to BUF1")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "BUF0 to BUF1")["Enabled"] = True
|
||||||
shutil.copy(self.constants.windows_ssdt_path, self.constants.acpi_path)
|
shutil.copy(self.constants.windows_ssdt_path, self.constants.acpi_path)
|
||||||
@@ -110,7 +110,7 @@ class build_firmware:
|
|||||||
# Force Rosetta Cryptex installation in macOS Ventura
|
# Force Rosetta Cryptex installation in macOS Ventura
|
||||||
# Restores support for CPUs lacking AVX2.0 support
|
# Restores support for CPUs lacking AVX2.0 support
|
||||||
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.ivy_bridge.value:
|
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.ivy_bridge.value:
|
||||||
print("- Enabling Rosetta Cryptex support in Ventura")
|
logging.info("- Enabling Rosetta Cryptex support in Ventura")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("CryptexFixup.kext", self.constants.cryptexfixup_version, self.constants.cryptexfixup_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("CryptexFixup.kext", self.constants.cryptexfixup_version, self.constants.cryptexfixup_path)
|
||||||
|
|
||||||
# i3 Ivy Bridge iMacs don't support RDRAND
|
# i3 Ivy Bridge iMacs don't support RDRAND
|
||||||
@@ -119,13 +119,13 @@ class build_firmware:
|
|||||||
(smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.sandy_bridge.value):
|
(smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.sandy_bridge.value):
|
||||||
# Ref: https://github.com/reenigneorcim/SurPlus
|
# Ref: https://github.com/reenigneorcim/SurPlus
|
||||||
# Enable for all systems missing RDRAND support
|
# Enable for all systems missing RDRAND support
|
||||||
print("- Adding SurPlus Patch for Race Condition")
|
logging.info("- Adding SurPlus Patch for Race Condition")
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "SurPlus v1 - PART 1 of 2 - Patch read_erandom (inlined in _early_random)")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "SurPlus v1 - PART 1 of 2 - Patch read_erandom (inlined in _early_random)")["Enabled"] = True
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "SurPlus v1 - PART 2 of 2 - Patch register_and_init_prng")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "SurPlus v1 - PART 2 of 2 - Patch register_and_init_prng")["Enabled"] = True
|
||||||
if self.constants.force_surplus is True:
|
if self.constants.force_surplus is True:
|
||||||
# Syncretic forces SurPlus to only run on Beta 7 and older by default for saftey reasons
|
# Syncretic forces SurPlus to only run on Beta 7 and older by default for saftey reasons
|
||||||
# If users desires, allow forcing in newer OSes
|
# If users desires, allow forcing in newer OSes
|
||||||
print("- Allowing SurPlus on all newer OSes")
|
logging.info("- Allowing SurPlus on all newer OSes")
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "SurPlus v1 - PART 1 of 2 - Patch read_erandom (inlined in _early_random)")["MaxKernel"] = ""
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "SurPlus v1 - PART 1 of 2 - Patch read_erandom (inlined in _early_random)")["MaxKernel"] = ""
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "SurPlus v1 - PART 2 of 2 - Patch register_and_init_prng")["MaxKernel"] = ""
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "SurPlus v1 - PART 2 of 2 - Patch register_and_init_prng")["MaxKernel"] = ""
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ class build_firmware:
|
|||||||
|
|
||||||
# HID patches
|
# HID patches
|
||||||
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.penryn.value:
|
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.penryn.value:
|
||||||
print("- Adding IOHIDFamily patch")
|
logging.info("- Adding IOHIDFamily patch")
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Identifier", "com.apple.iokit.IOHIDFamily")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Identifier", "com.apple.iokit.IOHIDFamily")["Enabled"] = True
|
||||||
|
|
||||||
|
|
||||||
@@ -157,20 +157,20 @@ class build_firmware:
|
|||||||
# Exfat check
|
# Exfat check
|
||||||
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] < cpu_data.cpu_data.sandy_bridge.value:
|
if smbios_data.smbios_dictionary[self.model]["CPU Generation"] < cpu_data.cpu_data.sandy_bridge.value:
|
||||||
# Sandy Bridge and newer Macs natively support ExFat
|
# Sandy Bridge and newer Macs natively support ExFat
|
||||||
print("- Adding ExFatDxeLegacy.efi")
|
logging.info("- Adding ExFatDxeLegacy.efi")
|
||||||
shutil.copy(self.constants.exfat_legacy_driver_path, self.constants.drivers_path)
|
shutil.copy(self.constants.exfat_legacy_driver_path, self.constants.drivers_path)
|
||||||
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("ExFatDxeLegacy.efi", "UEFI", "Drivers")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("ExFatDxeLegacy.efi", "UEFI", "Drivers")["Enabled"] = True
|
||||||
|
|
||||||
# NVMe check
|
# NVMe check
|
||||||
if self.constants.nvme_boot is True:
|
if self.constants.nvme_boot is True:
|
||||||
print("- Enabling NVMe boot support")
|
logging.info("- Enabling NVMe boot support")
|
||||||
shutil.copy(self.constants.nvme_driver_path, self.constants.drivers_path)
|
shutil.copy(self.constants.nvme_driver_path, self.constants.drivers_path)
|
||||||
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("NvmExpressDxe.efi", "UEFI", "Drivers")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("NvmExpressDxe.efi", "UEFI", "Drivers")["Enabled"] = True
|
||||||
|
|
||||||
# USB check
|
# USB check
|
||||||
if self.constants.xhci_boot is True:
|
if self.constants.xhci_boot is True:
|
||||||
print("- Adding USB 3.0 Controller Patch")
|
logging.info("- Adding USB 3.0 Controller Patch")
|
||||||
print("- Adding XhciDxe.efi and UsbBusDxe.efi")
|
logging.info("- Adding XhciDxe.efi and UsbBusDxe.efi")
|
||||||
shutil.copy(self.constants.xhci_driver_path, self.constants.drivers_path)
|
shutil.copy(self.constants.xhci_driver_path, self.constants.drivers_path)
|
||||||
shutil.copy(self.constants.usb_bus_driver_path, self.constants.drivers_path)
|
shutil.copy(self.constants.usb_bus_driver_path, self.constants.drivers_path)
|
||||||
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("XhciDxe.efi", "UEFI", "Drivers")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("XhciDxe.efi", "UEFI", "Drivers")["Enabled"] = True
|
||||||
@@ -178,7 +178,7 @@ class build_firmware:
|
|||||||
|
|
||||||
# PCIe Link Rate check
|
# PCIe Link Rate check
|
||||||
if self.model == "MacPro3,1":
|
if self.model == "MacPro3,1":
|
||||||
print("- Adding PCIe Link Rate Patch")
|
logging.info("- Adding PCIe Link Rate Patch")
|
||||||
shutil.copy(self.constants.link_rate_driver_path, self.constants.drivers_path)
|
shutil.copy(self.constants.link_rate_driver_path, self.constants.drivers_path)
|
||||||
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("FixPCIeLinkRate.efi", "UEFI", "Drivers")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("FixPCIeLinkRate.efi", "UEFI", "Drivers")["Enabled"] = True
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ class build_firmware:
|
|||||||
# Waiting for XNU source to be released to fix this properly
|
# Waiting for XNU source to be released to fix this properly
|
||||||
# Ref: https://forums.macrumors.com/threads/opencore-on-the-mac-pro.2207814/
|
# Ref: https://forums.macrumors.com/threads/opencore-on-the-mac-pro.2207814/
|
||||||
if self.model in ["MacPro6,1", "iMac7,1", "iMac8,1", "MacBookPro4,1"] or self.constants.set_vmm_cpuid is True:
|
if self.model in ["MacPro6,1", "iMac7,1", "iMac8,1", "MacBookPro4,1"] or self.constants.set_vmm_cpuid is True:
|
||||||
print("- Enabling VMM patch")
|
logging.info("- Enabling VMM patch")
|
||||||
self.config["Kernel"]["Emulate"]["Cpuid1Data"] = binascii.unhexlify("00000000000000000000008000000000")
|
self.config["Kernel"]["Emulate"]["Cpuid1Data"] = binascii.unhexlify("00000000000000000000008000000000")
|
||||||
self.config["Kernel"]["Emulate"]["Cpuid1Mask"] = binascii.unhexlify("00000000000000000000008000000000")
|
self.config["Kernel"]["Emulate"]["Cpuid1Mask"] = binascii.unhexlify("00000000000000000000008000000000")
|
||||||
self.config["Kernel"]["Emulate"]["MinKernel"] = "22.0.0"
|
self.config["Kernel"]["Emulate"]["MinKernel"] = "22.0.0"
|
||||||
@@ -207,17 +207,17 @@ class build_firmware:
|
|||||||
):
|
):
|
||||||
# Fix Virtual Machine support for non-macOS OSes
|
# Fix Virtual Machine support for non-macOS OSes
|
||||||
# Haswell and Broadwell MacBooks lock out the VMX bit if booting UEFI Windows
|
# Haswell and Broadwell MacBooks lock out the VMX bit if booting UEFI Windows
|
||||||
print("- Enabling VMX Bit for non-macOS OSes")
|
logging.info("- Enabling VMX Bit for non-macOS OSes")
|
||||||
self.config["UEFI"]["Quirks"]["EnableVmx"] = True
|
self.config["UEFI"]["Quirks"]["EnableVmx"] = True
|
||||||
|
|
||||||
# Works-around Hibernation bug where connecting all firmware drivers breaks the transition from S4
|
# Works-around Hibernation bug where connecting all firmware drivers breaks the transition from S4
|
||||||
# Mainly applicable for MacBookPro9,1
|
# Mainly applicable for MacBookPro9,1
|
||||||
if self.constants.disable_connectdrivers is True:
|
if self.constants.disable_connectdrivers is True:
|
||||||
print("- Disabling ConnectDrivers")
|
logging.info("- Disabling ConnectDrivers")
|
||||||
self.config["UEFI"]["ConnectDrivers"] = False
|
self.config["UEFI"]["ConnectDrivers"] = False
|
||||||
|
|
||||||
if self.constants.nvram_write is False:
|
if self.constants.nvram_write is False:
|
||||||
print("- Disabling Hardware NVRAM Write")
|
logging.info("- Disabling Hardware NVRAM Write")
|
||||||
self.config["NVRAM"]["WriteFlash"] = False
|
self.config["NVRAM"]["WriteFlash"] = False
|
||||||
|
|
||||||
if self.constants.serial_settings != "None":
|
if self.constants.serial_settings != "None":
|
||||||
@@ -247,7 +247,7 @@ class build_firmware:
|
|||||||
if "5K Display" not in smbios_data.smbios_dictionary[self.model]:
|
if "5K Display" not in smbios_data.smbios_dictionary[self.model]:
|
||||||
return
|
return
|
||||||
|
|
||||||
print("- Adding 5K Display Patch")
|
logging.info("- Adding 5K Display Patch")
|
||||||
# Set LauncherPath to '/boot.efi'
|
# Set LauncherPath to '/boot.efi'
|
||||||
# This is to ensure that only the Mac's firmware presents the boot option, but not OpenCore
|
# This is to ensure that only the Mac's firmware presents the boot option, but not OpenCore
|
||||||
# https://github.com/acidanthera/OpenCorePkg/blob/0.7.6/Library/OcAppleBootPolicyLib/OcAppleBootPolicyLib.c#L50-L73
|
# https://github.com/acidanthera/OpenCorePkg/blob/0.7.6/Library/OcAppleBootPolicyLib/OcAppleBootPolicyLib.c#L50-L73
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from data import smbios_data, model_array, os_data, cpu_data
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import shutil, binascii
|
import shutil, binascii, logging
|
||||||
|
|
||||||
class build_graphics_audio:
|
class build_graphics_audio:
|
||||||
|
|
||||||
@@ -37,42 +37,42 @@ class build_graphics_audio:
|
|||||||
if self.model in model_array.MacPro:
|
if self.model in model_array.MacPro:
|
||||||
if not self.constants.custom_model:
|
if not self.constants.custom_model:
|
||||||
for i, device in enumerate(self.computer.gpus):
|
for i, device in enumerate(self.computer.gpus):
|
||||||
print(f"- Found dGPU ({i + 1}): {utilities.friendly_hex(device.vendor_id)}:{utilities.friendly_hex(device.device_id)}")
|
logging.info(f"- Found dGPU ({i + 1}): {utilities.friendly_hex(device.vendor_id)}:{utilities.friendly_hex(device.device_id)}")
|
||||||
self.config["#Revision"][f"Hardware-MacPro-dGPU-{i + 1}"] = f"{utilities.friendly_hex(device.vendor_id)}:{utilities.friendly_hex(device.device_id)}"
|
self.config["#Revision"][f"Hardware-MacPro-dGPU-{i + 1}"] = f"{utilities.friendly_hex(device.vendor_id)}:{utilities.friendly_hex(device.device_id)}"
|
||||||
|
|
||||||
if device.pci_path and device.acpi_path:
|
if device.pci_path and device.acpi_path:
|
||||||
print(f"- Found dGPU ({i + 1}) at {device.pci_path}")
|
logging.info(f"- Found dGPU ({i + 1}) at {device.pci_path}")
|
||||||
if isinstance(device, device_probe.AMD):
|
if isinstance(device, device_probe.AMD):
|
||||||
print("- Adding Mac Pro, Xserve DRM patches")
|
logging.info("- Adding Mac Pro, Xserve DRM patches")
|
||||||
self.config["DeviceProperties"]["Add"][device.pci_path] = {"shikigva": 128, "unfairgva": 1, "rebuild-device-tree": 1, "agdpmod": "pikera", "enable-gva-support": 1}
|
self.config["DeviceProperties"]["Add"][device.pci_path] = {"shikigva": 128, "unfairgva": 1, "rebuild-device-tree": 1, "agdpmod": "pikera", "enable-gva-support": 1}
|
||||||
elif isinstance(device, device_probe.NVIDIA):
|
elif isinstance(device, device_probe.NVIDIA):
|
||||||
print("- Enabling Nvidia Output Patch")
|
logging.info("- Enabling Nvidia Output Patch")
|
||||||
self.config["DeviceProperties"]["Add"][device.pci_path] = {"rebuild-device-tree": 1, "agdpmod": "vit9696"}
|
self.config["DeviceProperties"]["Add"][device.pci_path] = {"rebuild-device-tree": 1, "agdpmod": "vit9696"}
|
||||||
self.config["UEFI"]["Quirks"]["ForgeUefiSupport"] = True
|
self.config["UEFI"]["Quirks"]["ForgeUefiSupport"] = True
|
||||||
self.config["UEFI"]["Quirks"]["ReloadOptionRoms"] = True
|
self.config["UEFI"]["Quirks"]["ReloadOptionRoms"] = True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(f"- Failed to find Device path for dGPU {i + 1}")
|
logging.info(f"- Failed to find Device path for dGPU {i + 1}")
|
||||||
if isinstance(device, device_probe.AMD):
|
if isinstance(device, device_probe.AMD):
|
||||||
print("- Adding Mac Pro, Xserve DRM patches")
|
logging.info("- Adding Mac Pro, Xserve DRM patches")
|
||||||
if "shikigva=128 unfairgva=1" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"]:
|
if "shikigva=128 unfairgva=1" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"]:
|
||||||
print("- Falling back to boot-args")
|
logging.info("- Falling back to boot-args")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " shikigva=128 unfairgva=1 agdpmod=pikera radgva=1" + (
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " shikigva=128 unfairgva=1 agdpmod=pikera radgva=1" + (
|
||||||
" -wegtree" if "-wegtree" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] else ""
|
" -wegtree" if "-wegtree" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] else ""
|
||||||
)
|
)
|
||||||
elif isinstance(device, device_probe.NVIDIA):
|
elif isinstance(device, device_probe.NVIDIA):
|
||||||
print("- Enabling Nvidia Output Patch")
|
logging.info("- Enabling Nvidia Output Patch")
|
||||||
if "-wegtree agdpmod=vit9696" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"]:
|
if "-wegtree agdpmod=vit9696" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"]:
|
||||||
print("- Falling back to boot-args")
|
logging.info("- Falling back to boot-args")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -wegtree agdpmod=vit9696"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -wegtree agdpmod=vit9696"
|
||||||
self.config["UEFI"]["Quirks"]["ForgeUefiSupport"] = True
|
self.config["UEFI"]["Quirks"]["ForgeUefiSupport"] = True
|
||||||
self.config["UEFI"]["Quirks"]["ReloadOptionRoms"] = True
|
self.config["UEFI"]["Quirks"]["ReloadOptionRoms"] = True
|
||||||
|
|
||||||
if not self.computer.gpus:
|
if not self.computer.gpus:
|
||||||
print("- No socketed dGPU found")
|
logging.info("- No socketed dGPU found")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print("- Adding Mac Pro, Xserve DRM patches")
|
logging.info("- Adding Mac Pro, Xserve DRM patches")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " shikigva=128 unfairgva=1 -wegtree"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " shikigva=128 unfairgva=1 -wegtree"
|
||||||
|
|
||||||
if not support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("WhateverGreen.kext")["Enabled"] is True:
|
if not support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("WhateverGreen.kext")["Enabled"] is True:
|
||||||
@@ -86,7 +86,7 @@ class build_graphics_audio:
|
|||||||
device.arch in [device_probe.NVIDIA.Archs.Fermi, device_probe.NVIDIA.Archs.Maxwell, device_probe.NVIDIA.Archs.Pascal] or
|
device.arch in [device_probe.NVIDIA.Archs.Fermi, device_probe.NVIDIA.Archs.Maxwell, device_probe.NVIDIA.Archs.Pascal] or
|
||||||
(self.constants.force_nv_web is True and device.arch in [device_probe.NVIDIA.Archs.Tesla, device_probe.NVIDIA.Archs.Kepler])
|
(self.constants.force_nv_web is True and device.arch in [device_probe.NVIDIA.Archs.Tesla, device_probe.NVIDIA.Archs.Kepler])
|
||||||
):
|
):
|
||||||
print(f"- Enabling Web Driver Patches for GPU ({i + 1}): {utilities.friendly_hex(device.vendor_id)}:{utilities.friendly_hex(device.device_id)}")
|
logging.info(f"- Enabling Web Driver Patches for GPU ({i + 1}): {utilities.friendly_hex(device.vendor_id)}:{utilities.friendly_hex(device.device_id)}")
|
||||||
if device.pci_path and device.acpi_path:
|
if device.pci_path and device.acpi_path:
|
||||||
if device.pci_path in self.config["DeviceProperties"]["Add"]:
|
if device.pci_path in self.config["DeviceProperties"]["Add"]:
|
||||||
self.config["DeviceProperties"]["Add"][device.pci_path].update({"disable-metal": 1, "force-compat": 1})
|
self.config["DeviceProperties"]["Add"][device.pci_path].update({"disable-metal": 1, "force-compat": 1})
|
||||||
@@ -108,10 +108,10 @@ class build_graphics_audio:
|
|||||||
def backlight_path_detection(self):
|
def backlight_path_detection(self):
|
||||||
if not self.constants.custom_model and self.computer.dgpu and self.computer.dgpu.pci_path:
|
if not self.constants.custom_model and self.computer.dgpu and self.computer.dgpu.pci_path:
|
||||||
self.gfx0_path = self.computer.dgpu.pci_path
|
self.gfx0_path = self.computer.dgpu.pci_path
|
||||||
print(f"- Found GFX0 Device Path: {self.gfx0_path}")
|
logging.info(f"- Found GFX0 Device Path: {self.gfx0_path}")
|
||||||
else:
|
else:
|
||||||
if not self.constants.custom_model:
|
if not self.constants.custom_model:
|
||||||
print("- Failed to find GFX0 Device path, falling back on known logic")
|
logging.info("- Failed to find GFX0 Device path, falling back on known logic")
|
||||||
if self.model in ["iMac11,1", "iMac11,3"]:
|
if self.model in ["iMac11,1", "iMac11,3"]:
|
||||||
self.gfx0_path = "PciRoot(0x0)/Pci(0x3,0x0)/Pci(0x0,0x0)"
|
self.gfx0_path = "PciRoot(0x0)/Pci(0x3,0x0)/Pci(0x0,0x0)"
|
||||||
elif self.model == "iMac10,1":
|
elif self.model == "iMac10,1":
|
||||||
@@ -125,7 +125,7 @@ class build_graphics_audio:
|
|||||||
# Ensure WEG is enabled as we need if for Backlight patching
|
# Ensure WEG is enabled as we need if for Backlight patching
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("WhateverGreen.kext", self.constants.whatevergreen_version, self.constants.whatevergreen_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("WhateverGreen.kext", self.constants.whatevergreen_version, self.constants.whatevergreen_path)
|
||||||
if self.model in ["iMac11,1", "iMac11,2", "iMac11,3", "iMac10,1"]:
|
if self.model in ["iMac11,1", "iMac11,2", "iMac11,3", "iMac10,1"]:
|
||||||
print("- Adding Nvidia Brightness Control and DRM patches")
|
logging.info("- Adding Nvidia Brightness Control and DRM patches")
|
||||||
self.config["DeviceProperties"]["Add"][backlight_path] = {
|
self.config["DeviceProperties"]["Add"][backlight_path] = {
|
||||||
"applbkl": binascii.unhexlify("01000000"),
|
"applbkl": binascii.unhexlify("01000000"),
|
||||||
"@0,backlight-control": binascii.unhexlify("01000000"),
|
"@0,backlight-control": binascii.unhexlify("01000000"),
|
||||||
@@ -144,7 +144,7 @@ class build_graphics_audio:
|
|||||||
"agdpmod": "vit9696",
|
"agdpmod": "vit9696",
|
||||||
}
|
}
|
||||||
elif self.model in ["iMac12,1", "iMac12,2"]:
|
elif self.model in ["iMac12,1", "iMac12,2"]:
|
||||||
print("- Adding Nvidia Brightness Control and DRM patches")
|
logging.info("- Adding Nvidia Brightness Control and DRM patches")
|
||||||
self.config["DeviceProperties"]["Add"][backlight_path] = {
|
self.config["DeviceProperties"]["Add"][backlight_path] = {
|
||||||
"applbkl": binascii.unhexlify("01000000"),
|
"applbkl": binascii.unhexlify("01000000"),
|
||||||
"@0,backlight-control": binascii.unhexlify("01000000"),
|
"@0,backlight-control": binascii.unhexlify("01000000"),
|
||||||
@@ -152,7 +152,7 @@ class build_graphics_audio:
|
|||||||
"shikigva": 256,
|
"shikigva": 256,
|
||||||
"agdpmod": "vit9696",
|
"agdpmod": "vit9696",
|
||||||
}
|
}
|
||||||
print("- Disabling unsupported iGPU")
|
logging.info("- Disabling unsupported iGPU")
|
||||||
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x2,0x0)"] = {
|
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x2,0x0)"] = {
|
||||||
"name": binascii.unhexlify("23646973706C6179"),
|
"name": binascii.unhexlify("23646973706C6179"),
|
||||||
"IOName": "#display",
|
"IOName": "#display",
|
||||||
@@ -165,7 +165,7 @@ class build_graphics_audio:
|
|||||||
|
|
||||||
|
|
||||||
def amd_mxm_patch(self, backlight_path):
|
def amd_mxm_patch(self, backlight_path):
|
||||||
print("- Adding AMD DRM patches")
|
logging.info("- Adding AMD DRM patches")
|
||||||
if not support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("WhateverGreen.kext")["Enabled"] is True:
|
if not support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("WhateverGreen.kext")["Enabled"] is True:
|
||||||
# Ensure WEG is enabled as we need if for Backlight patching
|
# Ensure WEG is enabled as we need if for Backlight patching
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("WhateverGreen.kext", self.constants.whatevergreen_version, self.constants.whatevergreen_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("WhateverGreen.kext", self.constants.whatevergreen_version, self.constants.whatevergreen_path)
|
||||||
@@ -175,7 +175,7 @@ class build_graphics_audio:
|
|||||||
# Set both properties when we cannot run hardware detection
|
# Set both properties when we cannot run hardware detection
|
||||||
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x3,0x0)/Pci(0x0,0x0)"] = {"shikigva": 128, "unfairgva": 1, "agdpmod": "pikera", "rebuild-device-tree": 1, "enable-gva-support": 1}
|
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x3,0x0)/Pci(0x0,0x0)"] = {"shikigva": 128, "unfairgva": 1, "agdpmod": "pikera", "rebuild-device-tree": 1, "enable-gva-support": 1}
|
||||||
if self.model in ["iMac12,1", "iMac12,2"]:
|
if self.model in ["iMac12,1", "iMac12,2"]:
|
||||||
print("- Disabling unsupported iGPU")
|
logging.info("- Disabling unsupported iGPU")
|
||||||
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x2,0x0)"] = {
|
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x2,0x0)"] = {
|
||||||
"name": binascii.unhexlify("23646973706C6179"),
|
"name": binascii.unhexlify("23646973706C6179"),
|
||||||
"IOName": "#display",
|
"IOName": "#display",
|
||||||
@@ -185,7 +185,7 @@ class build_graphics_audio:
|
|||||||
support.build_support(self.model, self.constants, self.config).enable_kext("AAAMouSSE.kext", self.constants.mousse_version, self.constants.mousse_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("AAAMouSSE.kext", self.constants.mousse_version, self.constants.mousse_path)
|
||||||
if self.computer and self.computer.dgpu:
|
if self.computer and self.computer.dgpu:
|
||||||
if self.computer.dgpu.arch == device_probe.AMD.Archs.Legacy_GCN_7000:
|
if self.computer.dgpu.arch == device_probe.AMD.Archs.Legacy_GCN_7000:
|
||||||
print("- Adding Legacy GCN Power Gate Patches")
|
logging.info("- Adding Legacy GCN Power Gate Patches")
|
||||||
self.config["DeviceProperties"]["Add"][backlight_path].update({
|
self.config["DeviceProperties"]["Add"][backlight_path].update({
|
||||||
"CAIL,CAIL_DisableDrmdmaPowerGating": 1,
|
"CAIL,CAIL_DisableDrmdmaPowerGating": 1,
|
||||||
"CAIL,CAIL_DisableGfxCGPowerGating": 1,
|
"CAIL,CAIL_DisableGfxCGPowerGating": 1,
|
||||||
@@ -193,7 +193,7 @@ class build_graphics_audio:
|
|||||||
"CAIL,CAIL_DisableVCEPowerGating": 1,
|
"CAIL,CAIL_DisableVCEPowerGating": 1,
|
||||||
})
|
})
|
||||||
if self.constants.imac_model == "Legacy GCN":
|
if self.constants.imac_model == "Legacy GCN":
|
||||||
print("- Adding Legacy GCN Power Gate Patches")
|
logging.info("- Adding Legacy GCN Power Gate Patches")
|
||||||
self.config["DeviceProperties"]["Add"][backlight_path].update({
|
self.config["DeviceProperties"]["Add"][backlight_path].update({
|
||||||
"CAIL,CAIL_DisableDrmdmaPowerGating": 1,
|
"CAIL,CAIL_DisableDrmdmaPowerGating": 1,
|
||||||
"CAIL,CAIL_DisableGfxCGPowerGating": 1,
|
"CAIL,CAIL_DisableGfxCGPowerGating": 1,
|
||||||
@@ -249,12 +249,12 @@ class build_graphics_audio:
|
|||||||
def firmware_handling(self):
|
def firmware_handling(self):
|
||||||
# Add UGA to GOP layer
|
# Add UGA to GOP layer
|
||||||
if "UGA Graphics" in smbios_data.smbios_dictionary[self.model]:
|
if "UGA Graphics" in smbios_data.smbios_dictionary[self.model]:
|
||||||
print("- Adding UGA to GOP Patch")
|
logging.info("- Adding UGA to GOP Patch")
|
||||||
self.config["UEFI"]["Output"]["GopPassThrough"] = "Apple"
|
self.config["UEFI"]["Output"]["GopPassThrough"] = "Apple"
|
||||||
|
|
||||||
# GMUX handling
|
# GMUX handling
|
||||||
if self.constants.software_demux is True and self.model in ["MacBookPro8,2", "MacBookPro8,3"]:
|
if self.constants.software_demux is True and self.model in ["MacBookPro8,2", "MacBookPro8,3"]:
|
||||||
print("- Enabling software demux")
|
logging.info("- Enabling software demux")
|
||||||
# Add ACPI patches
|
# Add ACPI patches
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Add"], "Path", "SSDT-DGPU.aml")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Add"], "Path", "SSDT-DGPU.aml")["Enabled"] = True
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "_INI to XINI")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "_INI to XINI")["Enabled"] = True
|
||||||
@@ -272,24 +272,24 @@ class build_graphics_audio:
|
|||||||
support.build_support(self.model, self.constants, self.config).enable_kext("AMDGPUWakeHandler.kext", self.constants.gpu_wake_version, self.constants.gpu_wake_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("AMDGPUWakeHandler.kext", self.constants.gpu_wake_version, self.constants.gpu_wake_path)
|
||||||
|
|
||||||
if self.constants.dGPU_switch is True and "Switchable GPUs" in smbios_data.smbios_dictionary[self.model]:
|
if self.constants.dGPU_switch is True and "Switchable GPUs" in smbios_data.smbios_dictionary[self.model]:
|
||||||
print("- Allowing GMUX switching in Windows")
|
logging.info("- Allowing GMUX switching in Windows")
|
||||||
self.config["Booter"]["Quirks"]["SignalAppleOS"] = True
|
self.config["Booter"]["Quirks"]["SignalAppleOS"] = True
|
||||||
|
|
||||||
# Force Output support PC VBIOS on Mac Pros
|
# Force Output support PC VBIOS on Mac Pros
|
||||||
if self.constants.force_output_support is True:
|
if self.constants.force_output_support is True:
|
||||||
print("- Forcing GOP Support")
|
logging.info("- Forcing GOP Support")
|
||||||
self.config["UEFI"]["Quirks"]["ForgeUefiSupport"] = True
|
self.config["UEFI"]["Quirks"]["ForgeUefiSupport"] = True
|
||||||
self.config["UEFI"]["Quirks"]["ReloadOptionRoms"] = True
|
self.config["UEFI"]["Quirks"]["ReloadOptionRoms"] = True
|
||||||
|
|
||||||
# AMD GOP VBIOS injection for AMD GCN 1-4 GPUs
|
# AMD GOP VBIOS injection for AMD GCN 1-4 GPUs
|
||||||
if self.constants.amd_gop_injection is True:
|
if self.constants.amd_gop_injection is True:
|
||||||
print("- Adding AMDGOP.efi")
|
logging.info("- Adding AMDGOP.efi")
|
||||||
shutil.copy(self.constants.amd_gop_driver_path, self.constants.drivers_path)
|
shutil.copy(self.constants.amd_gop_driver_path, self.constants.drivers_path)
|
||||||
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("AMDGOP.efi", "UEFI", "Drivers")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("AMDGOP.efi", "UEFI", "Drivers")["Enabled"] = True
|
||||||
|
|
||||||
# Nvidia Kepler GOP VBIOS injection
|
# Nvidia Kepler GOP VBIOS injection
|
||||||
if self.constants.nvidia_kepler_gop_injection is True:
|
if self.constants.nvidia_kepler_gop_injection is True:
|
||||||
print("- Adding NVGOP_GK.efi")
|
logging.info("- Adding NVGOP_GK.efi")
|
||||||
shutil.copy(self.constants.nvidia_kepler_gop_driver_path, self.constants.drivers_path)
|
shutil.copy(self.constants.nvidia_kepler_gop_driver_path, self.constants.drivers_path)
|
||||||
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("NVGOP_GK.efi", "UEFI", "Drivers")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("NVGOP_GK.efi", "UEFI", "Drivers")["Enabled"] = True
|
||||||
|
|
||||||
@@ -300,7 +300,7 @@ class build_graphics_audio:
|
|||||||
|
|
||||||
# AppleMuxControl Override
|
# AppleMuxControl Override
|
||||||
if self.model == "MacBookPro9,1":
|
if self.model == "MacBookPro9,1":
|
||||||
print("- Adding AppleMuxControl Override")
|
logging.info("- Adding AppleMuxControl Override")
|
||||||
amc_map_path = Path(self.constants.plist_folder_path) / Path("AppleMuxControl/Info.plist")
|
amc_map_path = Path(self.constants.plist_folder_path) / Path("AppleMuxControl/Info.plist")
|
||||||
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)"] = {"agdpmod": "vit9696"}
|
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)"] = {"agdpmod": "vit9696"}
|
||||||
Path(self.constants.amc_kext_folder).mkdir()
|
Path(self.constants.amc_kext_folder).mkdir()
|
||||||
@@ -309,7 +309,7 @@ class build_graphics_audio:
|
|||||||
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("AMC-Override.kext")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("AMC-Override.kext")["Enabled"] = True
|
||||||
|
|
||||||
if self.model not in model_array.NoAGPMSupport:
|
if self.model not in model_array.NoAGPMSupport:
|
||||||
print("- Adding AppleGraphicsPowerManagement Override")
|
logging.info("- Adding AppleGraphicsPowerManagement Override")
|
||||||
agpm_map_path = Path(self.constants.plist_folder_path) / Path("AppleGraphicsPowerManagement/Info.plist")
|
agpm_map_path = Path(self.constants.plist_folder_path) / Path("AppleGraphicsPowerManagement/Info.plist")
|
||||||
Path(self.constants.agpm_kext_folder).mkdir()
|
Path(self.constants.agpm_kext_folder).mkdir()
|
||||||
Path(self.constants.agpm_contents_folder).mkdir()
|
Path(self.constants.agpm_contents_folder).mkdir()
|
||||||
@@ -317,7 +317,7 @@ class build_graphics_audio:
|
|||||||
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("AGPM-Override.kext")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("AGPM-Override.kext")["Enabled"] = True
|
||||||
|
|
||||||
if self.model in model_array.AGDPSupport:
|
if self.model in model_array.AGDPSupport:
|
||||||
print("- Adding AppleGraphicsDevicePolicy Override")
|
logging.info("- Adding AppleGraphicsDevicePolicy Override")
|
||||||
agdp_map_path = Path(self.constants.plist_folder_path) / Path("AppleGraphicsDevicePolicy/Info.plist")
|
agdp_map_path = Path(self.constants.plist_folder_path) / Path("AppleGraphicsDevicePolicy/Info.plist")
|
||||||
Path(self.constants.agdp_kext_folder).mkdir()
|
Path(self.constants.agdp_kext_folder).mkdir()
|
||||||
Path(self.constants.agdp_contents_folder).mkdir()
|
Path(self.constants.agdp_contents_folder).mkdir()
|
||||||
@@ -326,17 +326,17 @@ class build_graphics_audio:
|
|||||||
|
|
||||||
# AGPM Patch
|
# AGPM Patch
|
||||||
if self.model in model_array.DualGPUPatch:
|
if self.model in model_array.DualGPUPatch:
|
||||||
print("- Adding dual GPU patch")
|
logging.info("- Adding dual GPU patch")
|
||||||
if not self.constants.custom_model and self.computer.dgpu and self.computer.dgpu.pci_path:
|
if not self.constants.custom_model and self.computer.dgpu and self.computer.dgpu.pci_path:
|
||||||
self.gfx0_path = self.computer.dgpu.pci_path
|
self.gfx0_path = self.computer.dgpu.pci_path
|
||||||
print(f"- Found GFX0 Device Path: {self.gfx0_path}")
|
logging.info(f"- Found GFX0 Device Path: {self.gfx0_path}")
|
||||||
else:
|
else:
|
||||||
if not self.constants.custom_model:
|
if not self.constants.custom_model:
|
||||||
print("- Failed to find GFX0 Device path, falling back on known logic")
|
logging.info("- Failed to find GFX0 Device path, falling back on known logic")
|
||||||
self.gfx0_path = "PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)"
|
self.gfx0_path = "PciRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)"
|
||||||
|
|
||||||
if self.model in model_array.IntelNvidiaDRM and self.constants.drm_support is True:
|
if self.model in model_array.IntelNvidiaDRM and self.constants.drm_support is True:
|
||||||
print("- Prioritizing DRM support over Intel QuickSync")
|
logging.info("- Prioritizing DRM support over Intel QuickSync")
|
||||||
self.config["DeviceProperties"]["Add"][self.gfx0_path] = {"agdpmod": "vit9696", "shikigva": 256}
|
self.config["DeviceProperties"]["Add"][self.gfx0_path] = {"agdpmod": "vit9696", "shikigva": 256}
|
||||||
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x2,0x0)"] = {
|
self.config["DeviceProperties"]["Add"]["PciRoot(0x0)/Pci(0x2,0x0)"] = {
|
||||||
"name": binascii.unhexlify("23646973706C6179"),
|
"name": binascii.unhexlify("23646973706C6179"),
|
||||||
@@ -355,15 +355,15 @@ class build_graphics_audio:
|
|||||||
# Check GPU Vendor
|
# Check GPU Vendor
|
||||||
if self.constants.metal_build is True:
|
if self.constants.metal_build is True:
|
||||||
self.backlight_path_detection()
|
self.backlight_path_detection()
|
||||||
print("- Adding Metal GPU patches on request")
|
logging.info("- Adding Metal GPU patches on request")
|
||||||
if self.constants.imac_vendor == "AMD":
|
if self.constants.imac_vendor == "AMD":
|
||||||
self.amd_mxm_patch(self.gfx0_path)
|
self.amd_mxm_patch(self.gfx0_path)
|
||||||
elif self.constants.imac_vendor == "Nvidia":
|
elif self.constants.imac_vendor == "Nvidia":
|
||||||
self.nvidia_mxm_patch(self.gfx0_path)
|
self.nvidia_mxm_patch(self.gfx0_path)
|
||||||
else:
|
else:
|
||||||
print("- Failed to find vendor")
|
logging.info("- Failed to find vendor")
|
||||||
elif not self.constants.custom_model and self.model in model_array.LegacyGPU and self.computer.dgpu:
|
elif not self.constants.custom_model and self.model in model_array.LegacyGPU and self.computer.dgpu:
|
||||||
print(f"- Detected dGPU: {utilities.friendly_hex(self.computer.dgpu.vendor_id)}:{utilities.friendly_hex(self.computer.dgpu.device_id)}")
|
logging.info(f"- Detected dGPU: {utilities.friendly_hex(self.computer.dgpu.vendor_id)}:{utilities.friendly_hex(self.computer.dgpu.device_id)}")
|
||||||
if self.computer.dgpu.arch in [
|
if self.computer.dgpu.arch in [
|
||||||
device_probe.AMD.Archs.Legacy_GCN_7000,
|
device_probe.AMD.Archs.Legacy_GCN_7000,
|
||||||
device_probe.AMD.Archs.Legacy_GCN_8000,
|
device_probe.AMD.Archs.Legacy_GCN_8000,
|
||||||
|
|||||||
+20
-20
@@ -5,7 +5,7 @@ from resources import constants, device_probe, generate_smbios, utilities
|
|||||||
from resources.build import support
|
from resources.build import support
|
||||||
from data import model_array, smbios_data, cpu_data
|
from data import model_array, smbios_data, cpu_data
|
||||||
|
|
||||||
import binascii, shutil
|
import binascii, shutil, logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ class build_misc:
|
|||||||
if self.constants.fu_status is True:
|
if self.constants.fu_status is True:
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("FeatureUnlock.kext", self.constants.featureunlock_version, self.constants.featureunlock_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("FeatureUnlock.kext", self.constants.featureunlock_version, self.constants.featureunlock_path)
|
||||||
if self.constants.fu_arguments is not None:
|
if self.constants.fu_arguments is not None:
|
||||||
print(f"- Adding additional FeatureUnlock args: {self.constants.fu_arguments}")
|
logging.info(f"- Adding additional FeatureUnlock args: {self.constants.fu_arguments}")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += self.constants.fu_arguments
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += self.constants.fu_arguments
|
||||||
|
|
||||||
def restrict_events_handling(self):
|
def restrict_events_handling(self):
|
||||||
@@ -49,7 +49,7 @@ class build_misc:
|
|||||||
if self.model in ["MacBookPro6,1", "MacBookPro6,2", "MacBookPro9,1", "MacBookPro10,1"]:
|
if self.model in ["MacBookPro6,1", "MacBookPro6,2", "MacBookPro9,1", "MacBookPro10,1"]:
|
||||||
block_args += "gmux,"
|
block_args += "gmux,"
|
||||||
if self.model in model_array.MacPro:
|
if self.model in model_array.MacPro:
|
||||||
print("- Disabling memory error reporting")
|
logging.info("- Disabling memory error reporting")
|
||||||
block_args += "pcie,"
|
block_args += "pcie,"
|
||||||
gpu_dict = []
|
gpu_dict = []
|
||||||
if not self.constants.custom_model:
|
if not self.constants.custom_model:
|
||||||
@@ -65,20 +65,20 @@ class build_misc:
|
|||||||
device_probe.Intel.Archs.Haswell,
|
device_probe.Intel.Archs.Haswell,
|
||||||
device_probe.NVIDIA.Archs.Kepler,
|
device_probe.NVIDIA.Archs.Kepler,
|
||||||
]:
|
]:
|
||||||
print("- Disabling mediaanalysisd")
|
logging.info("- Disabling mediaanalysisd")
|
||||||
block_args += "media,"
|
block_args += "media,"
|
||||||
break
|
break
|
||||||
if block_args.endswith(","):
|
if block_args.endswith(","):
|
||||||
block_args = block_args[:-1]
|
block_args = block_args[:-1]
|
||||||
|
|
||||||
if block_args != "":
|
if block_args != "":
|
||||||
print(f"- Setting RestrictEvents block arguments: {block_args}")
|
logging.info(f"- Setting RestrictEvents block arguments: {block_args}")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("RestrictEvents.kext", self.constants.restrictevents_version, self.constants.restrictevents_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("RestrictEvents.kext", self.constants.restrictevents_version, self.constants.restrictevents_path)
|
||||||
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["revblock"] = block_args
|
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["revblock"] = block_args
|
||||||
|
|
||||||
patch_args = ""
|
patch_args = ""
|
||||||
if support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (1)")["Enabled"] is True and self.constants.set_content_caching is True:
|
if support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Reroute kern.hv_vmm_present patch (1)")["Enabled"] is True and self.constants.set_content_caching is True:
|
||||||
print("- Fixing Content Caching support")
|
logging.info("- Fixing Content Caching support")
|
||||||
patch_args += "asset,"
|
patch_args += "asset,"
|
||||||
|
|
||||||
if patch_args.endswith(","):
|
if patch_args.endswith(","):
|
||||||
@@ -89,17 +89,17 @@ class build_misc:
|
|||||||
patch_args = "none"
|
patch_args = "none"
|
||||||
|
|
||||||
if patch_args != "":
|
if patch_args != "":
|
||||||
print(f"- Setting RestrictEvents patch arguments: {patch_args}")
|
logging.info(f"- Setting RestrictEvents patch arguments: {patch_args}")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("RestrictEvents.kext", self.constants.restrictevents_version, self.constants.restrictevents_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("RestrictEvents.kext", self.constants.restrictevents_version, self.constants.restrictevents_path)
|
||||||
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["revpatch"] = patch_args
|
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["revpatch"] = patch_args
|
||||||
|
|
||||||
if self.constants.custom_cpu_model == 0 or self.constants.custom_cpu_model == 1:
|
if self.constants.custom_cpu_model == 0 or self.constants.custom_cpu_model == 1:
|
||||||
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["revcpu"] = self.constants.custom_cpu_model
|
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["revcpu"] = self.constants.custom_cpu_model
|
||||||
if self.constants.custom_cpu_model_value != "":
|
if self.constants.custom_cpu_model_value != "":
|
||||||
print(f"- Adding custom CPU Name: {self.constants.custom_cpu_model_value}")
|
logging.info(f"- Adding custom CPU Name: {self.constants.custom_cpu_model_value}")
|
||||||
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["revcpuname"] = self.constants.custom_cpu_model_value
|
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["revcpuname"] = self.constants.custom_cpu_model_value
|
||||||
else:
|
else:
|
||||||
print("- Adding CPU Name Patch")
|
logging.info("- Adding CPU Name Patch")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("RestrictEvents.kext", self.constants.restrictevents_version, self.constants.restrictevents_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("RestrictEvents.kext", self.constants.restrictevents_version, self.constants.restrictevents_path)
|
||||||
|
|
||||||
if support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("RestrictEvents.kext")["Enabled"] is False:
|
if support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("RestrictEvents.kext")["Enabled"] is False:
|
||||||
@@ -125,7 +125,7 @@ class build_misc:
|
|||||||
if self.constants.firewire_boot is True and generate_smbios.check_firewire(self.model) is True:
|
if self.constants.firewire_boot is True and generate_smbios.check_firewire(self.model) is True:
|
||||||
# Enable FireWire Boot Support
|
# Enable FireWire Boot Support
|
||||||
# Applicable for both native FireWire and Thunderbolt to FireWire adapters
|
# Applicable for both native FireWire and Thunderbolt to FireWire adapters
|
||||||
print("- Enabling FireWire Boot Support")
|
logging.info("- Enabling FireWire Boot Support")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("IOFireWireFamily.kext", self.constants.fw_kext, self.constants.fw_family_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("IOFireWireFamily.kext", self.constants.fw_kext, self.constants.fw_family_path)
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("IOFireWireSBP2.kext", self.constants.fw_kext, self.constants.fw_sbp2_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("IOFireWireSBP2.kext", self.constants.fw_kext, self.constants.fw_sbp2_path)
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("IOFireWireSerialBusProtocolTransport.kext", self.constants.fw_kext, self.constants.fw_bus_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("IOFireWireSerialBusProtocolTransport.kext", self.constants.fw_kext, self.constants.fw_bus_path)
|
||||||
@@ -148,7 +148,7 @@ class build_misc:
|
|||||||
|
|
||||||
def thunderbolt_handling(self):
|
def thunderbolt_handling(self):
|
||||||
if self.constants.disable_tb is True and self.model in ["MacBookPro11,1", "MacBookPro11,2", "MacBookPro11,3", "MacBookPro11,4", "MacBookPro11,5"]:
|
if self.constants.disable_tb is True and self.model in ["MacBookPro11,1", "MacBookPro11,2", "MacBookPro11,3", "MacBookPro11,4", "MacBookPro11,5"]:
|
||||||
print("- Disabling 2013-2014 laptop Thunderbolt Controller")
|
logging.info("- Disabling 2013-2014 laptop Thunderbolt Controller")
|
||||||
if self.model in ["MacBookPro11,3", "MacBookPro11,5"]:
|
if self.model in ["MacBookPro11,3", "MacBookPro11,5"]:
|
||||||
# 15" dGPU models: IOACPIPlane:/_SB/PCI0@0/PEG1@10001/UPSB@0/DSB0@0/NHI0@0
|
# 15" dGPU models: IOACPIPlane:/_SB/PCI0@0/PEG1@10001/UPSB@0/DSB0@0/NHI0@0
|
||||||
tb_device_path = "PciRoot(0x0)/Pci(0x1,0x1)/Pci(0x0,0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)"
|
tb_device_path = "PciRoot(0x0)/Pci(0x1,0x1)/Pci(0x0,0x0)/Pci(0x0,0x0)/Pci(0x0,0x0)"
|
||||||
@@ -175,7 +175,7 @@ class build_misc:
|
|||||||
(self.model in model_array.Missing_USB_Map or self.model in model_array.Missing_USB_Map_Ventura)
|
(self.model in model_array.Missing_USB_Map or self.model in model_array.Missing_USB_Map_Ventura)
|
||||||
or self.constants.serial_settings in ["Moderate", "Advanced"])
|
or self.constants.serial_settings in ["Moderate", "Advanced"])
|
||||||
):
|
):
|
||||||
print("- Adding USB-Map.kext")
|
logging.info("- Adding USB-Map.kext")
|
||||||
Path(self.constants.map_kext_folder).mkdir()
|
Path(self.constants.map_kext_folder).mkdir()
|
||||||
Path(self.constants.map_contents_folder).mkdir()
|
Path(self.constants.map_contents_folder).mkdir()
|
||||||
shutil.copy(usb_map_path, self.constants.map_contents_folder)
|
shutil.copy(usb_map_path, self.constants.map_contents_folder)
|
||||||
@@ -196,7 +196,7 @@ class build_misc:
|
|||||||
smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.penryn.value or \
|
smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.penryn.value or \
|
||||||
self.model in ["MacPro4,1", "MacPro5,1"]
|
self.model in ["MacPro4,1", "MacPro5,1"]
|
||||||
):
|
):
|
||||||
print("- Adding UHCI/OHCI USB support")
|
logging.info("- Adding UHCI/OHCI USB support")
|
||||||
shutil.copy(self.constants.apple_usb_11_injector_path, self.constants.kexts_path)
|
shutil.copy(self.constants.apple_usb_11_injector_path, self.constants.kexts_path)
|
||||||
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("USB1.1-Injector.kext/Contents/PlugIns/AppleUSBOHCI.kext")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("USB1.1-Injector.kext/Contents/PlugIns/AppleUSBOHCI.kext")["Enabled"] = True
|
||||||
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("USB1.1-Injector.kext/Contents/PlugIns/AppleUSBOHCIPCI.kext")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("USB1.1-Injector.kext/Contents/PlugIns/AppleUSBOHCIPCI.kext")["Enabled"] = True
|
||||||
@@ -207,11 +207,11 @@ class build_misc:
|
|||||||
# DEBUG Settings (OpenCorePkg and Kernel Space)
|
# DEBUG Settings (OpenCorePkg and Kernel Space)
|
||||||
|
|
||||||
if self.constants.verbose_debug is True:
|
if self.constants.verbose_debug is True:
|
||||||
print("- Enabling Verbose boot")
|
logging.info("- Enabling Verbose boot")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -v"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -v"
|
||||||
|
|
||||||
if self.constants.kext_debug is True:
|
if self.constants.kext_debug is True:
|
||||||
print("- Enabling DEBUG Kexts")
|
logging.info("- Enabling DEBUG Kexts")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -liludbgall liludump=90"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -liludbgall liludump=90"
|
||||||
# Disabled due to macOS Monterey crashing shortly after kernel init
|
# Disabled due to macOS Monterey crashing shortly after kernel init
|
||||||
# Use DebugEnhancer.kext instead
|
# Use DebugEnhancer.kext instead
|
||||||
@@ -219,7 +219,7 @@ class build_misc:
|
|||||||
support.build_support(self.model, self.constants, self.config).enable_kext("DebugEnhancer.kext", self.constants.debugenhancer_version, self.constants.debugenhancer_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("DebugEnhancer.kext", self.constants.debugenhancer_version, self.constants.debugenhancer_path)
|
||||||
|
|
||||||
if self.constants.opencore_debug is True:
|
if self.constants.opencore_debug is True:
|
||||||
print("- Enabling DEBUG OpenCore")
|
logging.info("- Enabling DEBUG OpenCore")
|
||||||
self.config["Misc"]["Debug"]["Target"] = 0x43
|
self.config["Misc"]["Debug"]["Target"] = 0x43
|
||||||
self.config["Misc"]["Debug"]["DisplayLevel"] = 0x80000042
|
self.config["Misc"]["Debug"]["DisplayLevel"] = 0x80000042
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ class build_misc:
|
|||||||
# OpenCorePkg Settings
|
# OpenCorePkg Settings
|
||||||
|
|
||||||
# OpenCanopy Settings (GUI)
|
# OpenCanopy Settings (GUI)
|
||||||
print("- Adding OpenCanopy GUI")
|
logging.info("- Adding OpenCanopy GUI")
|
||||||
shutil.rmtree(self.constants.resources_path, onerror=self.rmtree_handler)
|
shutil.rmtree(self.constants.resources_path, onerror=self.rmtree_handler)
|
||||||
shutil.copy(self.constants.gui_path, self.constants.oc_folder)
|
shutil.copy(self.constants.gui_path, self.constants.oc_folder)
|
||||||
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("OpenCanopy.efi", "UEFI", "Drivers")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("OpenCanopy.efi", "UEFI", "Drivers")["Enabled"] = True
|
||||||
@@ -236,14 +236,14 @@ class build_misc:
|
|||||||
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("ResetNvramEntry.efi", "UEFI", "Drivers")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("ResetNvramEntry.efi", "UEFI", "Drivers")["Enabled"] = True
|
||||||
|
|
||||||
if self.constants.showpicker is False:
|
if self.constants.showpicker is False:
|
||||||
print("- Hiding OpenCore picker")
|
logging.info("- Hiding OpenCore picker")
|
||||||
self.config["Misc"]["Boot"]["ShowPicker"] = False
|
self.config["Misc"]["Boot"]["ShowPicker"] = False
|
||||||
|
|
||||||
if self.constants.oc_timeout != 5:
|
if self.constants.oc_timeout != 5:
|
||||||
print(f"- Setting custom OpenCore picker timeout to {self.constants.oc_timeout} seconds")
|
logging.info(f"- Setting custom OpenCore picker timeout to {self.constants.oc_timeout} seconds")
|
||||||
self.config["Misc"]["Boot"]["Timeout"] = self.constants.oc_timeout
|
self.config["Misc"]["Boot"]["Timeout"] = self.constants.oc_timeout
|
||||||
|
|
||||||
if self.constants.vault is True and utilities.check_command_line_tools() is True:
|
if self.constants.vault is True and utilities.check_command_line_tools() is True:
|
||||||
print("- Setting Vault configuration")
|
logging.info("- Setting Vault configuration")
|
||||||
self.config["Misc"]["Security"]["Vault"] = "Secure"
|
self.config["Misc"]["Security"]["Vault"] = "Secure"
|
||||||
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("OpenShell.efi", "Misc", "Tools")["Enabled"] = False
|
support.build_support(self.model, self.constants, self.config).get_efi_binary_by_path("OpenShell.efi", "Misc", "Tools")["Enabled"] = False
|
||||||
@@ -5,6 +5,8 @@ from resources import constants, device_probe, utilities
|
|||||||
from resources.build import support
|
from resources.build import support
|
||||||
from data import smbios_data
|
from data import smbios_data
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
class build_wireless:
|
class build_wireless:
|
||||||
|
|
||||||
def __init__(self, model, versions, config):
|
def __init__(self, model, versions, config):
|
||||||
@@ -24,22 +26,22 @@ class build_wireless:
|
|||||||
|
|
||||||
|
|
||||||
def on_model(self):
|
def on_model(self):
|
||||||
print(f"- Found Wireless Device {utilities.friendly_hex(self.computer.wifi.vendor_id)}:{utilities.friendly_hex(self.computer.wifi.device_id)}")
|
logging.info(f"- Found Wireless Device {utilities.friendly_hex(self.computer.wifi.vendor_id)}:{utilities.friendly_hex(self.computer.wifi.device_id)}")
|
||||||
self.config["#Revision"]["Hardware-Wifi"] = f"{utilities.friendly_hex(self.computer.wifi.vendor_id)}:{utilities.friendly_hex(self.computer.wifi.device_id)}"
|
self.config["#Revision"]["Hardware-Wifi"] = f"{utilities.friendly_hex(self.computer.wifi.vendor_id)}:{utilities.friendly_hex(self.computer.wifi.device_id)}"
|
||||||
|
|
||||||
if isinstance(self.computer.wifi, device_probe.Broadcom):
|
if isinstance(self.computer.wifi, device_probe.Broadcom):
|
||||||
# This works around OCLP spoofing the Wifi card and therefore unable to actually detect the correct device
|
# This works around OCLP spoofing the Wifi card and therefore unable to actually detect the correct device
|
||||||
if self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirportBrcmNIC and self.constants.validate is False and self.computer.wifi.country_code:
|
if self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirportBrcmNIC and self.constants.validate is False and self.computer.wifi.country_code:
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("AirportBrcmFixup.kext", self.constants.airportbcrmfixup_version, self.constants.airportbcrmfixup_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("AirportBrcmFixup.kext", self.constants.airportbcrmfixup_version, self.constants.airportbcrmfixup_path)
|
||||||
print(f"- Setting Wireless Card's Country Code: {self.computer.wifi.country_code}")
|
logging.info(f"- Setting Wireless Card's Country Code: {self.computer.wifi.country_code}")
|
||||||
if self.computer.wifi.pci_path:
|
if self.computer.wifi.pci_path:
|
||||||
arpt_path = self.computer.wifi.pci_path
|
arpt_path = self.computer.wifi.pci_path
|
||||||
print(f"- Found ARPT device at {arpt_path}")
|
logging.info(f"- Found ARPT device at {arpt_path}")
|
||||||
self.config["DeviceProperties"]["Add"][arpt_path] = {"brcmfx-country": self.computer.wifi.country_code}
|
self.config["DeviceProperties"]["Add"][arpt_path] = {"brcmfx-country": self.computer.wifi.country_code}
|
||||||
else:
|
else:
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += f" brcmfx-country={self.computer.wifi.country_code}"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += f" brcmfx-country={self.computer.wifi.country_code}"
|
||||||
if self.constants.enable_wake_on_wlan is True:
|
if self.constants.enable_wake_on_wlan is True:
|
||||||
print("- Enabling Wake on WLAN support")
|
logging.info("- Enabling Wake on WLAN support")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += f" -brcmfxwowl"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += f" -brcmfxwowl"
|
||||||
elif self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirPortBrcm4360:
|
elif self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirPortBrcm4360:
|
||||||
self.wifi_fake_id()
|
self.wifi_fake_id()
|
||||||
@@ -63,20 +65,20 @@ class build_wireless:
|
|||||||
if not "Wireless Model" in smbios_data.smbios_dictionary[self.model]:
|
if not "Wireless Model" in smbios_data.smbios_dictionary[self.model]:
|
||||||
return
|
return
|
||||||
if smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Broadcom.Chipsets.AirPortBrcm4360:
|
if smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Broadcom.Chipsets.AirPortBrcm4360:
|
||||||
print("- Enabling BCM943224 and BCM94331 Networking Support")
|
logging.info("- Enabling BCM943224 and BCM94331 Networking Support")
|
||||||
self.wifi_fake_id()
|
self.wifi_fake_id()
|
||||||
elif smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Broadcom.Chipsets.AirPortBrcm4331:
|
elif smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Broadcom.Chipsets.AirPortBrcm4331:
|
||||||
print("- Enabling BCM94328 Networking Support")
|
logging.info("- Enabling BCM94328 Networking Support")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path)
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path)
|
||||||
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AirPortBrcm4331.kext")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AirPortBrcm4331.kext")["Enabled"] = True
|
||||||
elif smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Broadcom.Chipsets.AirPortBrcm43224:
|
elif smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Broadcom.Chipsets.AirPortBrcm43224:
|
||||||
print("- Enabling BCM94328 Networking Support")
|
logging.info("- Enabling BCM94328 Networking Support")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path)
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path)
|
||||||
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AppleAirPortBrcm43224.kext")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AppleAirPortBrcm43224.kext")["Enabled"] = True
|
||||||
elif smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Atheros.Chipsets.AirPortAtheros40:
|
elif smbios_data.smbios_dictionary[self.model]["Wireless Model"] == device_probe.Atheros.Chipsets.AirPortAtheros40:
|
||||||
print("- Enabling Atheros Networking Support")
|
logging.info("- Enabling Atheros Networking Support")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path)
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path)
|
||||||
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AirPortAtheros40.kext")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AirPortAtheros40.kext")["Enabled"] = True
|
||||||
@@ -92,7 +94,7 @@ class build_wireless:
|
|||||||
if support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("AirportBrcmFixup.kext")["Enabled"] is False:
|
if support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("AirportBrcmFixup.kext")["Enabled"] is False:
|
||||||
return
|
return
|
||||||
|
|
||||||
print("- Enabling Wake on WLAN support")
|
logging.info("- Enabling Wake on WLAN support")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += f" -brcmfxwowl"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += f" -brcmfxwowl"
|
||||||
|
|
||||||
|
|
||||||
@@ -103,10 +105,10 @@ class build_wireless:
|
|||||||
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("AirportBrcmFixup.kext/Contents/PlugIns/AirPortBrcmNIC_Injector.kext")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_kext_by_bundle_path("AirportBrcmFixup.kext/Contents/PlugIns/AirPortBrcmNIC_Injector.kext")["Enabled"] = True
|
||||||
if not self.constants.custom_model and self.computer.wifi and self.computer.wifi.pci_path:
|
if not self.constants.custom_model and self.computer.wifi and self.computer.wifi.pci_path:
|
||||||
arpt_path = self.computer.wifi.pci_path
|
arpt_path = self.computer.wifi.pci_path
|
||||||
print(f"- Found ARPT device at {arpt_path}")
|
logging.info(f"- Found ARPT device at {arpt_path}")
|
||||||
else:
|
else:
|
||||||
if not self.model in smbios_data.smbios_dictionary:
|
if not self.model in smbios_data.smbios_dictionary:
|
||||||
print("No known PCI pathing for this model")
|
logging.info("No known PCI pathing for this model")
|
||||||
return
|
return
|
||||||
if "nForce Chipset" in smbios_data.smbios_dictionary[self.model]:
|
if "nForce Chipset" in smbios_data.smbios_dictionary[self.model]:
|
||||||
# Nvidia chipsets all have the same path to ARPT
|
# Nvidia chipsets all have the same path to ARPT
|
||||||
@@ -122,8 +124,8 @@ class build_wireless:
|
|||||||
# Assumes we have a laptop with Intel chipset
|
# Assumes we have a laptop with Intel chipset
|
||||||
# iMac11,x-12,x also apply
|
# iMac11,x-12,x also apply
|
||||||
arpt_path = "PciRoot(0x0)/Pci(0x1C,0x1)/Pci(0x0,0x0)"
|
arpt_path = "PciRoot(0x0)/Pci(0x1C,0x1)/Pci(0x0,0x0)"
|
||||||
print(f"- Using known ARPT Path: {arpt_path}")
|
logging.info(f"- Using known ARPT Path: {arpt_path}")
|
||||||
|
|
||||||
if not self.constants.custom_model and self.computer.wifi and self.constants.validate is False and self.computer.wifi.country_code:
|
if not self.constants.custom_model and self.computer.wifi and self.constants.validate is False and self.computer.wifi.country_code:
|
||||||
print(f"- Applying fake ID for WiFi, setting Country Code: {self.computer.wifi.country_code}")
|
logging.info(f"- Applying fake ID for WiFi, setting Country Code: {self.computer.wifi.country_code}")
|
||||||
self.config["DeviceProperties"]["Add"][arpt_path] = {"brcmfx-country": self.computer.wifi.country_code}
|
self.config["DeviceProperties"]["Add"][arpt_path] = {"brcmfx-country": self.computer.wifi.country_code}
|
||||||
@@ -5,6 +5,7 @@ from resources import constants, utilities
|
|||||||
from resources.build import support
|
from resources.build import support
|
||||||
|
|
||||||
import binascii
|
import binascii
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
class build_security:
|
class build_security:
|
||||||
@@ -20,35 +21,35 @@ class build_security:
|
|||||||
if self.constants.sip_status is False or self.constants.custom_sip_value:
|
if self.constants.sip_status is False or self.constants.custom_sip_value:
|
||||||
# Work-around 12.3 bug where Electron apps no longer launch with SIP lowered
|
# Work-around 12.3 bug where Electron apps no longer launch with SIP lowered
|
||||||
# Unknown whether this is intended behavior or not, revisit with 12.4
|
# Unknown whether this is intended behavior or not, revisit with 12.4
|
||||||
print("- Adding ipc_control_port_options=0 to boot-args")
|
logging.info("- Adding ipc_control_port_options=0 to boot-args")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " ipc_control_port_options=0"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " ipc_control_port_options=0"
|
||||||
# Adds AutoPkgInstaller for Automatic OpenCore-Patcher installation
|
# Adds AutoPkgInstaller for Automatic OpenCore-Patcher installation
|
||||||
# Only install if running the GUI (AutoPkg-Assets.pkg requires the GUI)
|
# Only install if running the GUI (AutoPkg-Assets.pkg requires the GUI)
|
||||||
if self.constants.wxpython_variant is True:
|
if self.constants.wxpython_variant is True:
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("AutoPkgInstaller.kext", self.constants.autopkg_version, self.constants.autopkg_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("AutoPkgInstaller.kext", self.constants.autopkg_version, self.constants.autopkg_path)
|
||||||
if self.constants.custom_sip_value:
|
if self.constants.custom_sip_value:
|
||||||
print(f"- Setting SIP value to: {self.constants.custom_sip_value}")
|
logging.info(f"- Setting SIP value to: {self.constants.custom_sip_value}")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["csr-active-config"] = utilities.string_to_hex(self.constants.custom_sip_value.lstrip("0x"))
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["csr-active-config"] = utilities.string_to_hex(self.constants.custom_sip_value.lstrip("0x"))
|
||||||
elif self.constants.sip_status is False:
|
elif self.constants.sip_status is False:
|
||||||
print("- Set SIP to allow Root Volume patching")
|
logging.info("- Set SIP to allow Root Volume patching")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["csr-active-config"] = binascii.unhexlify("03080000")
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["csr-active-config"] = binascii.unhexlify("03080000")
|
||||||
|
|
||||||
# apfs.kext has an undocumented boot-arg that allows FileVault usage on broken APFS seals (-arv_allow_fv)
|
# apfs.kext has an undocumented boot-arg that allows FileVault usage on broken APFS seals (-arv_allow_fv)
|
||||||
# This is however hidden behind kern.development, thus we patch _apfs_filevault_allowed to always return true
|
# This is however hidden behind kern.development, thus we patch _apfs_filevault_allowed to always return true
|
||||||
# Note this function was added in 11.3 (20E232, 20.4), older builds do not support this (ie. 11.2.3)
|
# Note this function was added in 11.3 (20E232, 20.4), older builds do not support this (ie. 11.2.3)
|
||||||
print("- Allowing FileVault on Root Patched systems")
|
logging.info("- Allowing FileVault on Root Patched systems")
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Force FileVault on Broken Seal")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Force FileVault on Broken Seal")["Enabled"] = True
|
||||||
# Lets us check in sys_patch.py if config supports FileVault
|
# Lets us check in sys_patch.py if config supports FileVault
|
||||||
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Settings"] += " -allow_fv"
|
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Settings"] += " -allow_fv"
|
||||||
|
|
||||||
# Patch KC UUID panics due to RSR installation
|
# Patch KC UUID panics due to RSR installation
|
||||||
# - Ref: https://github.com/dortania/OpenCore-Legacy-Patcher/issues/1019
|
# - Ref: https://github.com/dortania/OpenCore-Legacy-Patcher/issues/1019
|
||||||
print("- Enabling KC UUID mismatch patch")
|
logging.info("- Enabling KC UUID mismatch patch")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -nokcmismatchpanic"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -nokcmismatchpanic"
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("RSRHelper.kext", self.constants.rsrhelper_version, self.constants.rsrhelper_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("RSRHelper.kext", self.constants.rsrhelper_version, self.constants.rsrhelper_path)
|
||||||
|
|
||||||
if self.constants.disable_cs_lv is True:
|
if self.constants.disable_cs_lv is True:
|
||||||
print("- Disabling Library Validation")
|
logging.info("- Disabling Library Validation")
|
||||||
# In Ventura, LV patch broke. For now, add AMFI arg
|
# In Ventura, LV patch broke. For now, add AMFI arg
|
||||||
# Before merging into mainline, this needs to be resolved
|
# Before merging into mainline, this needs to be resolved
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Disable Library Validation Enforcement")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Comment", "Disable Library Validation Enforcement")["Enabled"] = True
|
||||||
@@ -61,10 +62,10 @@ class build_security:
|
|||||||
support.build_support(self.model, self.constants, self.config).enable_kext("CSLVFixup.kext", self.constants.cslvfixup_version, self.constants.cslvfixup_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("CSLVFixup.kext", self.constants.cslvfixup_version, self.constants.cslvfixup_path)
|
||||||
|
|
||||||
if self.constants.secure_status is False:
|
if self.constants.secure_status is False:
|
||||||
print("- Disabling SecureBootModel")
|
logging.info("- Disabling SecureBootModel")
|
||||||
self.config["Misc"]["Security"]["SecureBootModel"] = "Disabled"
|
self.config["Misc"]["Security"]["SecureBootModel"] = "Disabled"
|
||||||
if self.constants.force_vmm is True:
|
if self.constants.force_vmm is True:
|
||||||
print("- Forcing VMM patchset to support OTA updates")
|
logging.info("- Forcing VMM patchset to support OTA updates")
|
||||||
support.build_support(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.build_support(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.build_support(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.build_support(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.build_support(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.build_support(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
|
||||||
|
|||||||
+18
-18
@@ -5,7 +5,7 @@ from resources import constants, utilities, generate_smbios
|
|||||||
from resources.build import support
|
from resources.build import support
|
||||||
from data import smbios_data, cpu_data, model_array
|
from data import smbios_data, cpu_data, model_array
|
||||||
|
|
||||||
import subprocess, plistlib, binascii, uuid, ast
|
import subprocess, plistlib, binascii, uuid, ast, logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
class build_smbios:
|
class build_smbios:
|
||||||
@@ -19,26 +19,26 @@ class build_smbios:
|
|||||||
if self.constants.allow_oc_everywhere is False or self.constants.allow_native_spoofs is True:
|
if self.constants.allow_oc_everywhere is False or self.constants.allow_native_spoofs is True:
|
||||||
if self.constants.serial_settings == "None":
|
if self.constants.serial_settings == "None":
|
||||||
# Credit to Parrotgeek1 for boot.efi and hv_vmm_present patch sets
|
# Credit to Parrotgeek1 for boot.efi and hv_vmm_present patch sets
|
||||||
print("- Enabling Board ID exemption patch")
|
logging.info("- Enabling Board ID exemption patch")
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Booter"]["Patch"], "Comment", "Skip Board ID check")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Booter"]["Patch"], "Comment", "Skip Board ID check")["Enabled"] = True
|
||||||
|
|
||||||
print("- Enabling VMM exemption patch")
|
logging.info("- Enabling VMM exemption patch")
|
||||||
support.build_support(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.build_support(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.build_support(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.build_support(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.build_support(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.build_support(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
|
||||||
else:
|
else:
|
||||||
print("- Enabling SMC exemption patch")
|
logging.info("- Enabling SMC exemption patch")
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Identifier", "com.apple.driver.AppleSMC")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["Kernel"]["Patch"], "Identifier", "com.apple.driver.AppleSMC")["Enabled"] = True
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("SMC-Spoof.kext", self.constants.smcspoof_version, self.constants.smcspoof_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("SMC-Spoof.kext", self.constants.smcspoof_version, self.constants.smcspoof_path)
|
||||||
|
|
||||||
if self.constants.serial_settings in ["Moderate", "Advanced"]:
|
if self.constants.serial_settings in ["Moderate", "Advanced"]:
|
||||||
print("- Enabling USB Rename Patches")
|
logging.info("- Enabling USB Rename Patches")
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "XHC1 to SHC1")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "XHC1 to SHC1")["Enabled"] = True
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "EHC1 to EH01")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "EHC1 to EH01")["Enabled"] = True
|
||||||
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "EHC2 to EH02")["Enabled"] = True
|
support.build_support(self.model, self.constants, self.config).get_item_by_kv(self.config["ACPI"]["Patch"], "Comment", "EHC2 to EH02")["Enabled"] = True
|
||||||
|
|
||||||
if self.model == self.constants.override_smbios:
|
if self.model == self.constants.override_smbios:
|
||||||
print("- Adding -no_compat_check")
|
logging.info("- Adding -no_compat_check")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -no_compat_check"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -no_compat_check"
|
||||||
|
|
||||||
|
|
||||||
@@ -47,20 +47,20 @@ class build_smbios:
|
|||||||
|
|
||||||
if self.constants.override_smbios == "Default":
|
if self.constants.override_smbios == "Default":
|
||||||
if self.constants.serial_settings != "None":
|
if self.constants.serial_settings != "None":
|
||||||
print("- Setting macOS Monterey Supported SMBIOS")
|
logging.info("- Setting macOS Monterey Supported SMBIOS")
|
||||||
if self.constants.allow_native_spoofs is True:
|
if self.constants.allow_native_spoofs is True:
|
||||||
spoofed_model = self.model
|
spoofed_model = self.model
|
||||||
else:
|
else:
|
||||||
spoofed_model = generate_smbios.set_smbios_model_spoof(self.model)
|
spoofed_model = generate_smbios.set_smbios_model_spoof(self.model)
|
||||||
else:
|
else:
|
||||||
spoofed_model = self.constants.override_smbios
|
spoofed_model = self.constants.override_smbios
|
||||||
print(f"- Using Model ID: {spoofed_model}")
|
logging.info(f"- Using Model ID: {spoofed_model}")
|
||||||
|
|
||||||
spoofed_board = ""
|
spoofed_board = ""
|
||||||
if spoofed_model in smbios_data.smbios_dictionary:
|
if spoofed_model in smbios_data.smbios_dictionary:
|
||||||
if "Board ID" in smbios_data.smbios_dictionary[spoofed_model]:
|
if "Board ID" in smbios_data.smbios_dictionary[spoofed_model]:
|
||||||
spoofed_board = smbios_data.smbios_dictionary[spoofed_model]["Board ID"]
|
spoofed_board = smbios_data.smbios_dictionary[spoofed_model]["Board ID"]
|
||||||
print(f"- Using Board ID: {spoofed_board}")
|
logging.info(f"- Using Board ID: {spoofed_board}")
|
||||||
|
|
||||||
self.spoofed_model = spoofed_model
|
self.spoofed_model = spoofed_model
|
||||||
self.spoofed_board = spoofed_board
|
self.spoofed_board = spoofed_board
|
||||||
@@ -69,13 +69,13 @@ class build_smbios:
|
|||||||
self.config["#Revision"]["Spoofed-Model"] = f"{self.spoofed_model} - {self.constants.serial_settings}"
|
self.config["#Revision"]["Spoofed-Model"] = f"{self.spoofed_model} - {self.constants.serial_settings}"
|
||||||
|
|
||||||
if self.constants.serial_settings == "Moderate":
|
if self.constants.serial_settings == "Moderate":
|
||||||
print("- Using Moderate SMBIOS patching")
|
logging.info("- Using Moderate SMBIOS patching")
|
||||||
self.moderate_serial_patch()
|
self.moderate_serial_patch()
|
||||||
elif self.constants.serial_settings == "Advanced":
|
elif self.constants.serial_settings == "Advanced":
|
||||||
print("- Using Advanced SMBIOS patching")
|
logging.info("- Using Advanced SMBIOS patching")
|
||||||
self.advanced_serial_patch()
|
self.advanced_serial_patch()
|
||||||
elif self.constants.serial_settings == "Minimal":
|
elif self.constants.serial_settings == "Minimal":
|
||||||
print("- Using Minimal SMBIOS patching")
|
logging.info("- Using Minimal SMBIOS patching")
|
||||||
self.spoofed_model = self.model
|
self.spoofed_model = self.model
|
||||||
self.minimal_serial_patch()
|
self.minimal_serial_patch()
|
||||||
else:
|
else:
|
||||||
@@ -87,12 +87,12 @@ class build_smbios:
|
|||||||
# Note 1: Only apply if system is UEFI 1.2, this is generally Ivy Bridge and older
|
# Note 1: Only apply if system is UEFI 1.2, this is generally Ivy Bridge and older
|
||||||
# Note 2: Flipping 'UEFI -> ProtocolOverrides -> DataHub' will break hibernation
|
# Note 2: Flipping 'UEFI -> ProtocolOverrides -> DataHub' will break hibernation
|
||||||
if (smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.ivy_bridge.value and self.model):
|
if (smbios_data.smbios_dictionary[self.model]["CPU Generation"] <= cpu_data.cpu_data.ivy_bridge.value and self.model):
|
||||||
print("- Detected UEFI 1.2 or older Mac, updating BoardProduct")
|
logging.info("- Detected UEFI 1.2 or older Mac, updating BoardProduct")
|
||||||
self.config["PlatformInfo"]["DataHub"]["BoardProduct"] = self.spoofed_board
|
self.config["PlatformInfo"]["DataHub"]["BoardProduct"] = self.spoofed_board
|
||||||
self.config["PlatformInfo"]["UpdateDataHub"] = True
|
self.config["PlatformInfo"]["UpdateDataHub"] = True
|
||||||
|
|
||||||
if self.constants.custom_serial_number != "" and self.constants.custom_board_serial_number != "":
|
if self.constants.custom_serial_number != "" and self.constants.custom_board_serial_number != "":
|
||||||
print("- Adding custom serial numbers")
|
logging.info("- Adding custom serial numbers")
|
||||||
self.config["PlatformInfo"]["Automatic"] = True
|
self.config["PlatformInfo"]["Automatic"] = True
|
||||||
self.config["PlatformInfo"]["UpdateDataHub"] = True
|
self.config["PlatformInfo"]["UpdateDataHub"] = True
|
||||||
self.config["PlatformInfo"]["UpdateNVRAM"] = True
|
self.config["PlatformInfo"]["UpdateNVRAM"] = True
|
||||||
@@ -156,7 +156,7 @@ class build_smbios:
|
|||||||
if self.model == "MacBookPro6,2":
|
if self.model == "MacBookPro6,2":
|
||||||
# Force G State to not exceed moderate state
|
# Force G State to not exceed moderate state
|
||||||
# Ref: https://github.com/fabioiop/MBP-2010-GPU-Panic-fix
|
# Ref: https://github.com/fabioiop/MBP-2010-GPU-Panic-fix
|
||||||
print("- Patching G State for MacBookPro6,2")
|
logging.info("- Patching G State for MacBookPro6,2")
|
||||||
for gpu in ["Vendor10deDevice0a34", "Vendor10deDevice0a29"]:
|
for gpu in ["Vendor10deDevice0a34", "Vendor10deDevice0a29"]:
|
||||||
agpm_config["IOKitPersonalities"]["AGPM"]["Machines"][self.spoofed_board][gpu]["BoostPState"] = [2, 2, 2, 2]
|
agpm_config["IOKitPersonalities"]["AGPM"]["Machines"][self.spoofed_board][gpu]["BoostPState"] = [2, 2, 2, 2]
|
||||||
agpm_config["IOKitPersonalities"]["AGPM"]["Machines"][self.spoofed_board][gpu]["BoostTime"] = [2, 2, 2, 2]
|
agpm_config["IOKitPersonalities"]["AGPM"]["Machines"][self.spoofed_board][gpu]["BoostTime"] = [2, 2, 2, 2]
|
||||||
@@ -183,7 +183,7 @@ class build_smbios:
|
|||||||
fw_feature = generate_smbios.generate_fw_features(self.model, self.constants.custom_model)
|
fw_feature = generate_smbios.generate_fw_features(self.model, self.constants.custom_model)
|
||||||
# fw_feature = self.patch_firmware_feature()
|
# fw_feature = self.patch_firmware_feature()
|
||||||
fw_feature = hex(fw_feature).lstrip("0x").rstrip("L").strip()
|
fw_feature = hex(fw_feature).lstrip("0x").rstrip("L").strip()
|
||||||
print(f"- Setting Firmware Feature: {fw_feature}")
|
logging.info(f"- Setting Firmware Feature: {fw_feature}")
|
||||||
fw_feature = utilities.string_to_hex(fw_feature)
|
fw_feature = utilities.string_to_hex(fw_feature)
|
||||||
|
|
||||||
# FirmwareFeatures
|
# FirmwareFeatures
|
||||||
@@ -216,7 +216,7 @@ class build_smbios:
|
|||||||
self.config["PlatformInfo"]["UpdateDataHub"] = True
|
self.config["PlatformInfo"]["UpdateDataHub"] = True
|
||||||
|
|
||||||
if self.constants.custom_serial_number != "" and self.constants.custom_board_serial_number != "":
|
if self.constants.custom_serial_number != "" and self.constants.custom_board_serial_number != "":
|
||||||
print("- Adding custom serial numbers")
|
logging.info("- Adding custom serial numbers")
|
||||||
sn = self.constants.custom_serial_number
|
sn = self.constants.custom_serial_number
|
||||||
mlb = self.constants.custom_board_serial_number
|
mlb = self.constants.custom_board_serial_number
|
||||||
|
|
||||||
@@ -237,7 +237,7 @@ class build_smbios:
|
|||||||
if self.constants.custom_cpu_model == 0 or self.constants.custom_cpu_model == 1:
|
if self.constants.custom_cpu_model == 0 or self.constants.custom_cpu_model == 1:
|
||||||
self.config["PlatformInfo"]["Generic"]["ProcessorType"] = 1537
|
self.config["PlatformInfo"]["Generic"]["ProcessorType"] = 1537
|
||||||
if self.constants.custom_serial_number != "" and self.constants.custom_board_serial_number != "":
|
if self.constants.custom_serial_number != "" and self.constants.custom_board_serial_number != "":
|
||||||
print("- Adding custom serial numbers")
|
logging.info("- Adding custom serial numbers")
|
||||||
self.config["PlatformInfo"]["Generic"]["SystemSerialNumber"] = self.constants.custom_serial_number
|
self.config["PlatformInfo"]["Generic"]["SystemSerialNumber"] = self.constants.custom_serial_number
|
||||||
self.config["PlatformInfo"]["Generic"]["MLB"] = self.constants.custom_board_serial_number
|
self.config["PlatformInfo"]["Generic"]["MLB"] = self.constants.custom_board_serial_number
|
||||||
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Spoofed-SN"] = self.constants.custom_serial_number
|
self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Spoofed-SN"] = self.constants.custom_serial_number
|
||||||
|
|||||||
+11
-10
@@ -5,6 +5,7 @@ from resources import constants, device_probe, utilities
|
|||||||
from resources.build import support
|
from resources.build import support
|
||||||
from data import model_array, smbios_data, cpu_data
|
from data import model_array, smbios_data, cpu_data
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
class build_storage:
|
class build_storage:
|
||||||
|
|
||||||
@@ -31,11 +32,11 @@ class build_storage:
|
|||||||
for controller in sata_devices:
|
for controller in sata_devices:
|
||||||
# https://linux-hardware.org/?id=pci:1179-010b-1b4b-9183
|
# https://linux-hardware.org/?id=pci:1179-010b-1b4b-9183
|
||||||
if controller.vendor_id == 0x1179 and controller.device_id == 0x010b:
|
if controller.vendor_id == 0x1179 and controller.device_id == 0x010b:
|
||||||
print("- Enabling AHCI SSD patch")
|
logging.info("- Enabling AHCI SSD patch")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("MonteAHCIPort.kext", self.constants.monterey_ahci_version, self.constants.monterey_ahci_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("MonteAHCIPort.kext", self.constants.monterey_ahci_version, self.constants.monterey_ahci_path)
|
||||||
break
|
break
|
||||||
elif self.model in ["MacBookAir6,1", "MacBookAir6,2"]:
|
elif self.model in ["MacBookAir6,1", "MacBookAir6,2"]:
|
||||||
print("- Enabling AHCI SSD patch")
|
logging.info("- Enabling AHCI SSD patch")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("MonteAHCIPort.kext", self.constants.monterey_ahci_version, self.constants.monterey_ahci_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("MonteAHCIPort.kext", self.constants.monterey_ahci_version, self.constants.monterey_ahci_path)
|
||||||
|
|
||||||
# ThirdPartyDrives Check
|
# ThirdPartyDrives Check
|
||||||
@@ -48,11 +49,11 @@ class build_storage:
|
|||||||
if drive in smbios_data.smbios_dictionary[self.model]["Stock Storage"]:
|
if drive in smbios_data.smbios_dictionary[self.model]["Stock Storage"]:
|
||||||
if not self.constants.custom_model:
|
if not self.constants.custom_model:
|
||||||
if self.computer.third_party_sata_ssd is True:
|
if self.computer.third_party_sata_ssd is True:
|
||||||
print("- Adding SATA Hibernation Patch")
|
logging.info("- Adding SATA Hibernation Patch")
|
||||||
self.config["Kernel"]["Quirks"]["ThirdPartyDrives"] = True
|
self.config["Kernel"]["Quirks"]["ThirdPartyDrives"] = True
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
print("- Adding SATA Hibernation Patch")
|
logging.info("- Adding SATA Hibernation Patch")
|
||||||
self.config["Kernel"]["Quirks"]["ThirdPartyDrives"] = True
|
self.config["Kernel"]["Quirks"]["ThirdPartyDrives"] = True
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -73,29 +74,29 @@ class build_storage:
|
|||||||
# Use Innie's same logic:
|
# Use Innie's same logic:
|
||||||
# https://github.com/cdf/Innie/blob/v1.3.0/Innie/Innie.cpp#L90-L97
|
# https://github.com/cdf/Innie/blob/v1.3.0/Innie/Innie.cpp#L90-L97
|
||||||
for i, controller in enumerate(self.computer.storage):
|
for i, controller in enumerate(self.computer.storage):
|
||||||
print(f"- Fixing PCIe Storage Controller ({i + 1}) reporting")
|
logging.info(f"- Fixing PCIe Storage Controller ({i + 1}) reporting")
|
||||||
if controller.pci_path:
|
if controller.pci_path:
|
||||||
self.config["DeviceProperties"]["Add"][controller.pci_path] = {"built-in": 1}
|
self.config["DeviceProperties"]["Add"][controller.pci_path] = {"built-in": 1}
|
||||||
else:
|
else:
|
||||||
print(f"- Failed to find Device path for PCIe Storage Controller {i}, falling back to Innie")
|
logging.info(f"- Failed to find Device path for PCIe Storage Controller {i}, falling back to Innie")
|
||||||
support.build_support(self.model, self.constants, self.config).enable_kext("Innie.kext", self.constants.innie_version, self.constants.innie_path)
|
support.build_support(self.model, self.constants, self.config).enable_kext("Innie.kext", self.constants.innie_version, self.constants.innie_path)
|
||||||
|
|
||||||
if not self.constants.custom_model and self.constants.allow_nvme_fixing is True:
|
if not self.constants.custom_model and self.constants.allow_nvme_fixing is True:
|
||||||
nvme_devices = [i for i in self.computer.storage if isinstance(i, device_probe.NVMeController)]
|
nvme_devices = [i for i in self.computer.storage if isinstance(i, device_probe.NVMeController)]
|
||||||
for i, controller in enumerate(nvme_devices):
|
for i, controller in enumerate(nvme_devices):
|
||||||
print(f"- Found 3rd Party NVMe SSD ({i + 1}): {utilities.friendly_hex(controller.vendor_id)}:{utilities.friendly_hex(controller.device_id)}")
|
logging.info(f"- Found 3rd Party NVMe SSD ({i + 1}): {utilities.friendly_hex(controller.vendor_id)}:{utilities.friendly_hex(controller.device_id)}")
|
||||||
self.config["#Revision"][f"Hardware-NVMe-{i}"] = f"{utilities.friendly_hex(controller.vendor_id)}:{utilities.friendly_hex(controller.device_id)}"
|
self.config["#Revision"][f"Hardware-NVMe-{i}"] = f"{utilities.friendly_hex(controller.vendor_id)}:{utilities.friendly_hex(controller.device_id)}"
|
||||||
|
|
||||||
# Disable Bit 0 (L0s), enable Bit 1 (L1)
|
# Disable Bit 0 (L0s), enable Bit 1 (L1)
|
||||||
nvme_aspm = (controller.aspm & (~0b11)) | 0b10
|
nvme_aspm = (controller.aspm & (~0b11)) | 0b10
|
||||||
|
|
||||||
if controller.pci_path:
|
if controller.pci_path:
|
||||||
print(f"- Found NVMe ({i}) at {controller.pci_path}")
|
logging.info(f"- Found NVMe ({i}) at {controller.pci_path}")
|
||||||
self.config["DeviceProperties"]["Add"].setdefault(controller.pci_path, {})["pci-aspm-default"] = nvme_aspm
|
self.config["DeviceProperties"]["Add"].setdefault(controller.pci_path, {})["pci-aspm-default"] = nvme_aspm
|
||||||
self.config["DeviceProperties"]["Add"][controller.pci_path.rpartition("/")[0]] = {"pci-aspm-default": nvme_aspm}
|
self.config["DeviceProperties"]["Add"][controller.pci_path.rpartition("/")[0]] = {"pci-aspm-default": nvme_aspm}
|
||||||
else:
|
else:
|
||||||
if "-nvmefaspm" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"]:
|
if "-nvmefaspm" not in self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"]:
|
||||||
print("- Falling back to -nvmefaspm")
|
logging.info("- Falling back to -nvmefaspm")
|
||||||
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -nvmefaspm"
|
self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -nvmefaspm"
|
||||||
|
|
||||||
if (controller.vendor_id != 0x144D and controller.device_id != 0xA804):
|
if (controller.vendor_id != 0x144D and controller.device_id != 0xA804):
|
||||||
@@ -132,5 +133,5 @@ class build_storage:
|
|||||||
|
|
||||||
def trim_handling(self):
|
def trim_handling(self):
|
||||||
if self.constants.apfs_trim_timeout is False:
|
if self.constants.apfs_trim_timeout is False:
|
||||||
print(f"- Disabling APFS TRIM timeout")
|
logging.info(f"- Disabling APFS TRIM timeout")
|
||||||
self.config["Kernel"]["Quirks"]["SetApfsTrimTimeout"] = 0
|
self.config["Kernel"]["Quirks"]["SetApfsTrimTimeout"] = 0
|
||||||
+18
-17
@@ -5,6 +5,7 @@ from resources import constants, utilities
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import shutil, plistlib, subprocess, zipfile
|
import shutil, plistlib, subprocess, zipfile
|
||||||
|
import logging
|
||||||
|
|
||||||
class build_support:
|
class build_support:
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ class build_support:
|
|||||||
def get_kext_by_bundle_path(self, bundle_path):
|
def get_kext_by_bundle_path(self, bundle_path):
|
||||||
kext = self.get_item_by_kv(self.config["Kernel"]["Add"], "BundlePath", bundle_path)
|
kext = self.get_item_by_kv(self.config["Kernel"]["Add"], "BundlePath", bundle_path)
|
||||||
if not kext:
|
if not kext:
|
||||||
print(f"- Could not find kext {bundle_path}!")
|
logging.info(f"- Could not find kext {bundle_path}!")
|
||||||
raise IndexError
|
raise IndexError
|
||||||
return kext
|
return kext
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ class build_support:
|
|||||||
def get_efi_binary_by_path(self, bundle_path, entry_location, efi_type):
|
def get_efi_binary_by_path(self, bundle_path, entry_location, efi_type):
|
||||||
efi_binary = self.get_item_by_kv(self.config[entry_location][efi_type], "Path", bundle_path)
|
efi_binary = self.get_item_by_kv(self.config[entry_location][efi_type], "Path", bundle_path)
|
||||||
if not efi_binary:
|
if not efi_binary:
|
||||||
print(f"- Could not find {efi_type}: {bundle_path}!")
|
logging.info(f"- Could not find {efi_type}: {bundle_path}!")
|
||||||
raise IndexError
|
raise IndexError
|
||||||
return efi_binary
|
return efi_binary
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ class build_support:
|
|||||||
if kext["Enabled"] is True:
|
if kext["Enabled"] is True:
|
||||||
return
|
return
|
||||||
|
|
||||||
print(f"- Adding {kext_name} {kext_version}")
|
logging.info(f"- Adding {kext_name} {kext_version}")
|
||||||
shutil.copy(kext_path, self.constants.kexts_path)
|
shutil.copy(kext_path, self.constants.kexts_path)
|
||||||
kext["Enabled"] = True
|
kext["Enabled"] = True
|
||||||
|
|
||||||
@@ -63,27 +64,27 @@ class build_support:
|
|||||||
# sign.command checks for the existence of '/usr/bin/strings' however does not verify whether it's executable
|
# sign.command checks for the existence of '/usr/bin/strings' however does not verify whether it's executable
|
||||||
# sign.command will continue to run and create an unbootable OpenCore.efi due to the missing strings binary
|
# sign.command will continue to run and create an unbootable OpenCore.efi due to the missing strings binary
|
||||||
# macOS has dummy binaries that just reroute to the actual binaries after you install Xcode's Command Line Tools
|
# macOS has dummy binaries that just reroute to the actual binaries after you install Xcode's Command Line Tools
|
||||||
print("- Missing Command Line tools, skipping Vault for saftey reasons")
|
logging.info("- Missing Command Line tools, skipping Vault for saftey reasons")
|
||||||
print("- Install via 'xcode-select --install' and rerun OCLP if you wish to vault this config")
|
logging.info("- Install via 'xcode-select --install' and rerun OCLP if you wish to vault this config")
|
||||||
return
|
return
|
||||||
|
|
||||||
print("- Vaulting EFI")
|
logging.info("- Vaulting EFI")
|
||||||
subprocess.run([str(self.constants.vault_path), f"{self.constants.oc_folder}/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
subprocess.run([str(self.constants.vault_path), f"{self.constants.oc_folder}/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
|
||||||
|
|
||||||
def validate_pathing(self):
|
def validate_pathing(self):
|
||||||
# Verify whether all files are accounted for on-disk
|
# Verify whether all files are accounted for on-disk
|
||||||
# This ensures that OpenCore won't hit a critical error and fail to boot
|
# This ensures that OpenCore won't hit a critical error and fail to boot
|
||||||
print("- Validating generated config")
|
logging.info("- Validating generated config")
|
||||||
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/config.plist")):
|
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/config.plist")):
|
||||||
print("- OpenCore config file missing!!!")
|
logging.info("- OpenCore config file missing!!!")
|
||||||
raise Exception("OpenCore config file missing")
|
raise Exception("OpenCore config file missing")
|
||||||
|
|
||||||
config_plist = plistlib.load(Path(self.constants.opencore_release_folder / Path("EFI/OC/config.plist")).open("rb"))
|
config_plist = plistlib.load(Path(self.constants.opencore_release_folder / Path("EFI/OC/config.plist")).open("rb"))
|
||||||
|
|
||||||
for acpi in config_plist["ACPI"]["Add"]:
|
for acpi in config_plist["ACPI"]["Add"]:
|
||||||
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/ACPI") / Path(acpi["Path"])).exists():
|
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/ACPI") / Path(acpi["Path"])).exists():
|
||||||
print(f" - Missing ACPI Table: {acpi['Path']}")
|
logging.info(f" - Missing ACPI Table: {acpi['Path']}")
|
||||||
raise Exception(f"Missing ACPI Table: {acpi['Path']}")
|
raise Exception(f"Missing ACPI Table: {acpi['Path']}")
|
||||||
|
|
||||||
for kext in config_plist["Kernel"]["Add"]:
|
for kext in config_plist["Kernel"]["Add"]:
|
||||||
@@ -91,40 +92,40 @@ class build_support:
|
|||||||
kext_binary_path = Path(kext_path / Path(kext["ExecutablePath"]))
|
kext_binary_path = Path(kext_path / Path(kext["ExecutablePath"]))
|
||||||
kext_plist_path = Path(kext_path / Path(kext["PlistPath"]))
|
kext_plist_path = Path(kext_path / Path(kext["PlistPath"]))
|
||||||
if not kext_path.exists():
|
if not kext_path.exists():
|
||||||
print(f"- Missing kext: {kext_path}")
|
logging.info(f"- Missing kext: {kext_path}")
|
||||||
raise Exception(f"Missing {kext_path}")
|
raise Exception(f"Missing {kext_path}")
|
||||||
if not kext_binary_path.exists():
|
if not kext_binary_path.exists():
|
||||||
print(f"- Missing {kext['BundlePath']}'s binary: {kext_binary_path}")
|
logging.info(f"- Missing {kext['BundlePath']}'s binary: {kext_binary_path}")
|
||||||
raise Exception(f"Missing {kext_binary_path}")
|
raise Exception(f"Missing {kext_binary_path}")
|
||||||
if not kext_plist_path.exists():
|
if not kext_plist_path.exists():
|
||||||
print(f"- Missing {kext['BundlePath']}'s plist: {kext_plist_path}")
|
logging.info(f"- Missing {kext['BundlePath']}'s plist: {kext_plist_path}")
|
||||||
raise Exception(f"Missing {kext_plist_path}")
|
raise Exception(f"Missing {kext_plist_path}")
|
||||||
|
|
||||||
for tool in config_plist["Misc"]["Tools"]:
|
for tool in config_plist["Misc"]["Tools"]:
|
||||||
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/Tools") / Path(tool["Path"])).exists():
|
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/Tools") / Path(tool["Path"])).exists():
|
||||||
print(f" - Missing tool: {tool['Path']}")
|
logging.info(f" - Missing tool: {tool['Path']}")
|
||||||
raise Exception(f"Missing tool: {tool['Path']}")
|
raise Exception(f"Missing tool: {tool['Path']}")
|
||||||
|
|
||||||
for driver in config_plist["UEFI"]["Drivers"]:
|
for driver in config_plist["UEFI"]["Drivers"]:
|
||||||
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/Drivers") / Path(driver["Path"])).exists():
|
if not Path(self.constants.opencore_release_folder / Path("EFI/OC/Drivers") / Path(driver["Path"])).exists():
|
||||||
print(f" - Missing driver: {driver['Path']}")
|
logging.info(f" - Missing driver: {driver['Path']}")
|
||||||
raise Exception(f"Missing driver: {driver['Path']}")
|
raise Exception(f"Missing driver: {driver['Path']}")
|
||||||
|
|
||||||
# Validating local files
|
# Validating local files
|
||||||
# Report if they have no associated config.plist entry (i.e. they're not being used)
|
# Report if they have no associated config.plist entry (i.e. they're not being used)
|
||||||
for tool_files in Path(self.constants.opencore_release_folder / Path("EFI/OC/Tools")).glob("*"):
|
for tool_files in Path(self.constants.opencore_release_folder / Path("EFI/OC/Tools")).glob("*"):
|
||||||
if tool_files.name not in [x["Path"] for x in config_plist["Misc"]["Tools"]]:
|
if tool_files.name not in [x["Path"] for x in config_plist["Misc"]["Tools"]]:
|
||||||
print(f" - Missing tool from config: {tool_files.name}")
|
logging.info(f" - Missing tool from config: {tool_files.name}")
|
||||||
raise Exception(f"Missing tool from config: {tool_files.name}")
|
raise Exception(f"Missing tool from config: {tool_files.name}")
|
||||||
|
|
||||||
for driver_file in Path(self.constants.opencore_release_folder / Path("EFI/OC/Drivers")).glob("*"):
|
for driver_file in Path(self.constants.opencore_release_folder / Path("EFI/OC/Drivers")).glob("*"):
|
||||||
if driver_file.name not in [x["Path"] for x in config_plist["UEFI"]["Drivers"]]:
|
if driver_file.name not in [x["Path"] for x in config_plist["UEFI"]["Drivers"]]:
|
||||||
print(f"- Found extra driver: {driver_file.name}")
|
logging.info(f"- Found extra driver: {driver_file.name}")
|
||||||
raise Exception(f"Found extra driver: {driver_file.name}")
|
raise Exception(f"Found extra driver: {driver_file.name}")
|
||||||
|
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
print("- Cleaning up files")
|
logging.info("- Cleaning up files")
|
||||||
# Remove unused entries
|
# Remove unused entries
|
||||||
entries_to_clean = {
|
entries_to_clean = {
|
||||||
"ACPI": ["Add", "Delete", "Patch"],
|
"ACPI": ["Add", "Delete", "Patch"],
|
||||||
|
|||||||
+97
-96
@@ -1,6 +1,7 @@
|
|||||||
# Handle misc CLI menu options
|
# Handle misc CLI menu options
|
||||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||||
import sys
|
import sys
|
||||||
|
import logging
|
||||||
|
|
||||||
from resources import constants, install, utilities, defaults, installer, tui_helpers, global_settings
|
from resources import constants, install, utilities, defaults, installer, tui_helpers, global_settings
|
||||||
from resources.sys_patch import sys_patch
|
from resources.sys_patch import sys_patch
|
||||||
@@ -21,7 +22,7 @@ class MenuOptions:
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.verbose_debug = False
|
self.constants.verbose_debug = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.change_verbose()
|
self.change_verbose()
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ class MenuOptions:
|
|||||||
self.constants.opencore_debug = False
|
self.constants.opencore_debug = False
|
||||||
self.constants.opencore_build = "RELEASE"
|
self.constants.opencore_build = "RELEASE"
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.change_oc()
|
self.change_oc()
|
||||||
|
|
||||||
@@ -51,14 +52,14 @@ class MenuOptions:
|
|||||||
self.constants.kext_debug = False
|
self.constants.kext_debug = False
|
||||||
self.constants.kext_variant = "RELEASE"
|
self.constants.kext_variant = "RELEASE"
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.change_kext()
|
self.change_kext()
|
||||||
|
|
||||||
def change_metal(self):
|
def change_metal(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Assume Metal GPU Always in iMac"])
|
utilities.header(["Assume Metal GPU Always in iMac"])
|
||||||
print(
|
logging.info(
|
||||||
"""This is for iMacs that have upgraded Metal GPUs, otherwise
|
"""This is for iMacs that have upgraded Metal GPUs, otherwise
|
||||||
Patcher assumes based on stock configuration (ie. iMac10,x-12,x)
|
Patcher assumes based on stock configuration (ie. iMac10,x-12,x)
|
||||||
|
|
||||||
@@ -92,14 +93,14 @@ option is for those patching on a different machine or OCLP cannot detect.
|
|||||||
self.constants.imac_vendor = "AMD"
|
self.constants.imac_vendor = "AMD"
|
||||||
self.constants.imac_model = "Legacy GCN"
|
self.constants.imac_model = "Legacy GCN"
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.change_metal()
|
self.change_metal()
|
||||||
|
|
||||||
def change_serial(self):
|
def change_serial(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set SMBIOS Spoof Level"])
|
utilities.header(["Set SMBIOS Spoof Level"])
|
||||||
print(
|
logging.info(
|
||||||
"""This section is for setting how OpenCore generates the SMBIOS
|
"""This section is for setting how OpenCore generates the SMBIOS
|
||||||
Recommended for advanced users who want control how serials are handled
|
Recommended for advanced users who want control how serials are handled
|
||||||
|
|
||||||
@@ -123,14 +124,14 @@ Q. Return to previous menu
|
|||||||
elif change_menu == "3":
|
elif change_menu == "3":
|
||||||
self.constants.serial_settings = "Advanced"
|
self.constants.serial_settings = "Advanced"
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.change_serial()
|
self.change_serial()
|
||||||
|
|
||||||
def change_showpicker(self):
|
def change_showpicker(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set OpenCore Picker mode"])
|
utilities.header(["Set OpenCore Picker mode"])
|
||||||
print(
|
logging.info(
|
||||||
"""By default, OpenCore will show its boot picker each time on boot up,
|
"""By default, OpenCore will show its boot picker each time on boot up,
|
||||||
however this can be disabled by default and be shown on command by repeatedly
|
however this can be disabled by default and be shown on command by repeatedly
|
||||||
pressing the "Esc" key
|
pressing the "Esc" key
|
||||||
@@ -142,14 +143,14 @@ pressing the "Esc" key
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.showpicker = False
|
self.constants.showpicker = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.change_showpicker()
|
self.change_showpicker()
|
||||||
|
|
||||||
def change_vault(self):
|
def change_vault(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set OpenCore Vaulting"])
|
utilities.header(["Set OpenCore Vaulting"])
|
||||||
print(
|
logging.info(
|
||||||
"""By default, this patcher will sign all your files and ensure none of the
|
"""By default, this patcher will sign all your files and ensure none of the
|
||||||
contents can be tampered with. However for more advanced users, you may
|
contents can be tampered with. However for more advanced users, you may
|
||||||
want to be able to freely edit the config.plist and files.
|
want to be able to freely edit the config.plist and files.
|
||||||
@@ -164,14 +165,14 @@ Note: For security reasons, OpenShell will be disabled when Vault is set.
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.vault = False
|
self.constants.vault = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.change_vault()
|
self.change_vault()
|
||||||
|
|
||||||
def change_sip(self):
|
def change_sip(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set System Integrity protection"])
|
utilities.header(["Set System Integrity protection"])
|
||||||
print(
|
logging.info(
|
||||||
f"""SIP is used to ensure proper security measures are set,
|
f"""SIP is used to ensure proper security measures are set,
|
||||||
however to patch the root volume this must be lowered partially.
|
however to patch the root volume this must be lowered partially.
|
||||||
Only disable is absolutely necessary. SIP value = 0x803
|
Only disable is absolutely necessary. SIP value = 0x803
|
||||||
@@ -193,14 +194,14 @@ Q. Return to previous menu
|
|||||||
elif change_menu == "3":
|
elif change_menu == "3":
|
||||||
self.set_custom_sip_value()
|
self.set_custom_sip_value()
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.change_sip()
|
self.change_sip()
|
||||||
|
|
||||||
def change_sbm(self):
|
def change_sbm(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set SecureBootModel"])
|
utilities.header(["Set SecureBootModel"])
|
||||||
print(
|
logging.info(
|
||||||
"""SecureBootModel is used to ensure best firmware security,
|
"""SecureBootModel is used to ensure best firmware security,
|
||||||
however to patch the root volume this must be disabled.
|
however to patch the root volume this must be disabled.
|
||||||
Only recommended to enable for users with T2 SMBIOS spoofs.
|
Only recommended to enable for users with T2 SMBIOS spoofs.
|
||||||
@@ -219,7 +220,7 @@ Q. Return to previous menu
|
|||||||
elif change_menu == "2":
|
elif change_menu == "2":
|
||||||
self.constants.secure_status = False
|
self.constants.secure_status = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.change_sbm()
|
self.change_sbm()
|
||||||
|
|
||||||
@@ -227,7 +228,7 @@ Q. Return to previous menu
|
|||||||
def bootstrap_setting(self):
|
def bootstrap_setting(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set Bootstrap method"])
|
utilities.header(["Set Bootstrap method"])
|
||||||
print(
|
logging.info(
|
||||||
"""Sets OpenCore's bootstrap method, currently the patcher supports the
|
"""Sets OpenCore's bootstrap method, currently the patcher supports the
|
||||||
following options.
|
following options.
|
||||||
|
|
||||||
@@ -251,14 +252,14 @@ see the EFI Boot entry in the boot picker.
|
|||||||
elif change_menu == "2":
|
elif change_menu == "2":
|
||||||
self.constants.boot_efi = True
|
self.constants.boot_efi = True
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.bootstrap_setting()
|
self.bootstrap_setting()
|
||||||
|
|
||||||
def drm_setting(self):
|
def drm_setting(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set DRM preferences"])
|
utilities.header(["Set DRM preferences"])
|
||||||
print(
|
logging.info(
|
||||||
"""Sets OpenCore's DRM preferences for iMac13,x and iMac14,x.
|
"""Sets OpenCore's DRM preferences for iMac13,x and iMac14,x.
|
||||||
In Big Sur, some DRM based content may be broken by
|
In Big Sur, some DRM based content may be broken by
|
||||||
default in AppleTV, Photobooth, etc.
|
default in AppleTV, Photobooth, etc.
|
||||||
@@ -277,14 +278,14 @@ Recommend only disabling if absolutely required.
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.drm_support = False
|
self.constants.drm_support = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.drm_setting()
|
self.drm_setting()
|
||||||
|
|
||||||
def allow_native_models(self):
|
def allow_native_models(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Allow OpenCore on native Models"])
|
utilities.header(["Allow OpenCore on native Models"])
|
||||||
print(
|
logging.info(
|
||||||
"""Allows natively supported Macs to use OpenCore. Recommended
|
"""Allows natively supported Macs to use OpenCore. Recommended
|
||||||
for users with 3rd Party NVMe SSDs to achieve improved overall
|
for users with 3rd Party NVMe SSDs to achieve improved overall
|
||||||
power usage.
|
power usage.
|
||||||
@@ -299,14 +300,14 @@ power usage.
|
|||||||
self.constants.allow_oc_everywhere = False
|
self.constants.allow_oc_everywhere = False
|
||||||
self.constants.serial_settings = "Minimal"
|
self.constants.serial_settings = "Minimal"
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.allow_native_models()
|
self.allow_native_models()
|
||||||
|
|
||||||
def custom_cpu(self):
|
def custom_cpu(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set custom CPU Model Name"])
|
utilities.header(["Set custom CPU Model Name"])
|
||||||
print(
|
logging.info(
|
||||||
"""Change reported CPU Model name in About This Mac
|
"""Change reported CPU Model name in About This Mac
|
||||||
Custom names will report as follows:
|
Custom names will report as follows:
|
||||||
|
|
||||||
@@ -318,11 +319,11 @@ Q. Return to previous menu
|
|||||||
)
|
)
|
||||||
if self.constants.custom_cpu_model_value == "":
|
if self.constants.custom_cpu_model_value == "":
|
||||||
if self.constants.custom_cpu_model == 0:
|
if self.constants.custom_cpu_model == 0:
|
||||||
print("Currently using original name")
|
logging.info("Currently using original name")
|
||||||
else:
|
else:
|
||||||
print("Currently using CPU name")
|
logging.info("Currently using CPU name")
|
||||||
else:
|
else:
|
||||||
print(f"Custom CPU name currently: {self.constants.custom_cpu_model_value}")
|
logging.info(f"Custom CPU name currently: {self.constants.custom_cpu_model_value}")
|
||||||
change_menu = input("Set custom CPU Name(1,2,3): ")
|
change_menu = input("Set custom CPU Name(1,2,3): ")
|
||||||
if change_menu == "1":
|
if change_menu == "1":
|
||||||
self.constants.custom_cpu_model = 2
|
self.constants.custom_cpu_model = 2
|
||||||
@@ -334,14 +335,14 @@ Q. Return to previous menu
|
|||||||
self.constants.custom_cpu_model = 1
|
self.constants.custom_cpu_model = 1
|
||||||
self.constants.custom_cpu_model_value = input("Enter new CPU Name: ")
|
self.constants.custom_cpu_model_value = input("Enter new CPU Name: ")
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.custom_cpu()
|
self.custom_cpu()
|
||||||
|
|
||||||
def disable_cpufriend(self):
|
def disable_cpufriend(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Disable CPU Friend?"])
|
utilities.header(["Disable CPU Friend?"])
|
||||||
print(
|
logging.info(
|
||||||
"""Only recommended for advanced users
|
"""Only recommended for advanced users
|
||||||
Disabling CPUFriend forces macOS into using a different
|
Disabling CPUFriend forces macOS into using a different
|
||||||
Mac's power profile for CPUs and GPUs, which can harm the
|
Mac's power profile for CPUs and GPUs, which can harm the
|
||||||
@@ -354,14 +355,14 @@ hardware
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.disallow_cpufriend = False
|
self.constants.disallow_cpufriend = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.disable_cpufriend()
|
self.disable_cpufriend()
|
||||||
|
|
||||||
def set_smbios(self):
|
def set_smbios(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set SMBIOS Spoof Model"])
|
utilities.header(["Set SMBIOS Spoof Model"])
|
||||||
print(
|
logging.info(
|
||||||
"""Change model OpenCore spoofs Mac too
|
"""Change model OpenCore spoofs Mac too
|
||||||
|
|
||||||
Valid options:
|
Valid options:
|
||||||
@@ -374,7 +375,7 @@ Q. Return to previous menu
|
|||||||
|
|
||||||
change_menu = input("Set SMBIOS Spoof Model: ")
|
change_menu = input("Set SMBIOS Spoof Model: ")
|
||||||
if change_menu == "1":
|
if change_menu == "1":
|
||||||
print("Setting SMBIOS spoof to default mode")
|
logging.info("Setting SMBIOS spoof to default mode")
|
||||||
self.constants.override_smbios = "Default"
|
self.constants.override_smbios = "Default"
|
||||||
elif change_menu == "2":
|
elif change_menu == "2":
|
||||||
custom_smbios = input("Set new SMBIOS mode: ")
|
custom_smbios = input("Set new SMBIOS mode: ")
|
||||||
@@ -382,23 +383,23 @@ Q. Return to previous menu
|
|||||||
if smbios_data.smbios_dictionary[custom_smbios]["Board ID"] != None:
|
if smbios_data.smbios_dictionary[custom_smbios]["Board ID"] != None:
|
||||||
self.constants.override_smbios = custom_smbios
|
self.constants.override_smbios = custom_smbios
|
||||||
else:
|
else:
|
||||||
print("Non-Intel SMBIOS, reverting to Default setting")
|
logging.info("Non-Intel SMBIOS, reverting to Default setting")
|
||||||
self.constants.override_smbios = "Default"
|
self.constants.override_smbios = "Default"
|
||||||
except KeyError:
|
except KeyError:
|
||||||
print("Unsupported SMBIOS, reverting to Default setting")
|
logging.info("Unsupported SMBIOS, reverting to Default setting")
|
||||||
self.constants.override_smbios = "Default"
|
self.constants.override_smbios = "Default"
|
||||||
elif change_menu == "3":
|
elif change_menu == "3":
|
||||||
print("Disabling SMBIOS spoof")
|
logging.info("Disabling SMBIOS spoof")
|
||||||
self.constants.override_smbios = self.model
|
self.constants.override_smbios = self.model
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.set_smbios()
|
self.set_smbios()
|
||||||
|
|
||||||
def allow_firewire(self):
|
def allow_firewire(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Allow FireWire Boot Support"])
|
utilities.header(["Allow FireWire Boot Support"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
In macOS Catalina and newer, Apple restricted
|
In macOS Catalina and newer, Apple restricted
|
||||||
usage of FireWire devices to boot macOS for
|
usage of FireWire devices to boot macOS for
|
||||||
@@ -418,14 +419,14 @@ Note: MacBook5,x-7,1 don't support FireWire boot
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.firewire_boot = False
|
self.constants.firewire_boot = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.allow_firewire()
|
self.allow_firewire()
|
||||||
|
|
||||||
def allow_nvme(self):
|
def allow_nvme(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Allow NVMe UEFI Support"])
|
utilities.header(["Allow NVMe UEFI Support"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
For machines not natively supporting NVMe,
|
For machines not natively supporting NVMe,
|
||||||
this option allows you to see and boot NVMe
|
this option allows you to see and boot NVMe
|
||||||
@@ -445,14 +446,14 @@ OpenCore will enable NVMe support in it's picker
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.nvme_boot = False
|
self.constants.nvme_boot = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.allow_nvme()
|
self.allow_nvme()
|
||||||
|
|
||||||
def allow_nvme_pwr_mgmt(self):
|
def allow_nvme_pwr_mgmt(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Allow NVMe Power Management Adjustments"])
|
utilities.header(["Allow NVMe Power Management Adjustments"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
For machines with upgraded NVMe drives, this
|
For machines with upgraded NVMe drives, this
|
||||||
option allows for better power management support
|
option allows for better power management support
|
||||||
@@ -472,14 +473,14 @@ Skylake and newer Macs.
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.allow_nvme_fixing = False
|
self.constants.allow_nvme_fixing = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.allow_nvme()
|
self.allow_nvme()
|
||||||
|
|
||||||
def allow_xhci(self):
|
def allow_xhci(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Allow NVMe UEFI Support"])
|
utilities.header(["Allow NVMe UEFI Support"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
For machines not natively supporting XHCI/USB 3.o,
|
For machines not natively supporting XHCI/USB 3.o,
|
||||||
this option allows you to see and boot XHCI
|
this option allows you to see and boot XHCI
|
||||||
@@ -499,14 +500,14 @@ OpenCore will enable XHCI support in it's picker
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.xhci_boot = False
|
self.constants.xhci_boot = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.allow_xhci()
|
self.allow_xhci()
|
||||||
|
|
||||||
def allow_wowl(self):
|
def allow_wowl(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Allow Wake on WLAN"])
|
utilities.header(["Allow Wake on WLAN"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
Due to an unfortunate bug in macOS Big Sur+, Wake on WLAN is
|
Due to an unfortunate bug in macOS Big Sur+, Wake on WLAN is
|
||||||
disabled by default for BCM943224, BCM94331 and BCM94360/2 chipsets.
|
disabled by default for BCM943224, BCM94331 and BCM94360/2 chipsets.
|
||||||
@@ -523,7 +524,7 @@ be prepared if enabling.
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.enable_wake_on_wlan = False
|
self.constants.enable_wake_on_wlan = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.allow_wowl()
|
self.allow_wowl()
|
||||||
|
|
||||||
@@ -531,7 +532,7 @@ be prepared if enabling.
|
|||||||
def disable_tb(self):
|
def disable_tb(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Disable Thunderbolt on 2013-14 MacBook Pros"])
|
utilities.header(["Disable Thunderbolt on 2013-14 MacBook Pros"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
Some 2013-14 MacBook Pro's have issues with the built-in thunderbolt,
|
Some 2013-14 MacBook Pro's have issues with the built-in thunderbolt,
|
||||||
resulting in kernel panics and random shutdowns.
|
resulting in kernel panics and random shutdowns.
|
||||||
@@ -550,14 +551,14 @@ other devices that benefit from this fix.
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.disable_tb = False
|
self.constants.disable_tb = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.disable_tb()
|
self.disable_tb()
|
||||||
|
|
||||||
def terascale_2_accel(self):
|
def terascale_2_accel(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set TeraScale 2 Acceleration"])
|
utilities.header(["Set TeraScale 2 Acceleration"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
By default this patcher will install TeraScale 2 acceleration, however
|
By default this patcher will install TeraScale 2 acceleration, however
|
||||||
for some laptops this may be undesired due to how degraded their dGPU
|
for some laptops this may be undesired due to how degraded their dGPU
|
||||||
@@ -577,21 +578,21 @@ handle acceleration tasks.
|
|||||||
global_settings.global_settings().write_property("MacBookPro_TeraScale_2_Accel", False)
|
global_settings.global_settings().write_property("MacBookPro_TeraScale_2_Accel", False)
|
||||||
self.constants.allow_ts2_accel = False
|
self.constants.allow_ts2_accel = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.terascale_2_accel()
|
self.terascale_2_accel()
|
||||||
|
|
||||||
def dump_hardware(self):
|
def dump_hardware(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Dumping detected hardware"])
|
utilities.header(["Dumping detected hardware"])
|
||||||
print("")
|
logging.info("")
|
||||||
print(self.constants.computer)
|
logging.info(self.constants.computer)
|
||||||
input("\nPress [ENTER] to exit: ")
|
input("\nPress [ENTER] to exit: ")
|
||||||
|
|
||||||
def applealc_support(self):
|
def applealc_support(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set AppleALC usage"])
|
utilities.header(["Set AppleALC usage"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
By default this patcher will install audio patches in-memory via
|
By default this patcher will install audio patches in-memory via
|
||||||
AppleALC. However for systems that cannot achieve boot screen support,
|
AppleALC. However for systems that cannot achieve boot screen support,
|
||||||
@@ -608,14 +609,14 @@ If AppleALC is detected, the Patcher will not install AppleHDA.
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.set_alc_usage = False
|
self.constants.set_alc_usage = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.applealc_support()
|
self.applealc_support()
|
||||||
|
|
||||||
def dGPU_switch_support(self):
|
def dGPU_switch_support(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set Windows GMUX support"])
|
utilities.header(["Set Windows GMUX support"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
With OCLP, we're able to restore iGPU functionality on iGPU+dGPU
|
With OCLP, we're able to restore iGPU functionality on iGPU+dGPU
|
||||||
MacBook Pros. However for some this may not be desires, ie. eGPUs
|
MacBook Pros. However for some this may not be desires, ie. eGPUs
|
||||||
@@ -629,14 +630,14 @@ for Windows may prefer to only work with the dGPU and eGPU active.
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.dGPU_switch = False
|
self.constants.dGPU_switch = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.dGPU_switch_support()
|
self.dGPU_switch_support()
|
||||||
|
|
||||||
def set_3rd_party_drives(self):
|
def set_3rd_party_drives(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set enhanced 3rd Party SSD Support"])
|
utilities.header(["Set enhanced 3rd Party SSD Support"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
On SATA-based Macs, Apple restricts enhanced OS support to native
|
On SATA-based Macs, Apple restricts enhanced OS support to native
|
||||||
drives. Namely hibernation and TRIM.
|
drives. Namely hibernation and TRIM.
|
||||||
@@ -652,14 +653,14 @@ TRIM is not ideal.
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.allow_3rd_party_drives = False
|
self.constants.allow_3rd_party_drives = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.set_3rd_party_drives()
|
self.set_3rd_party_drives()
|
||||||
|
|
||||||
def set_software_demux(self):
|
def set_software_demux(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set Software Demux"])
|
utilities.header(["Set Software Demux"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
For MacBookPro8,2/3 users, it's very common for the dGPU to fail and
|
For MacBookPro8,2/3 users, it's very common for the dGPU to fail and
|
||||||
thus require the user to disable them via the 'gpu-power-prefs'
|
thus require the user to disable them via the 'gpu-power-prefs'
|
||||||
@@ -680,14 +681,14 @@ https://dortania.github.io/OpenCore-Legacy-Patcher/ACCEL.html#unable-to-switch-g
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.software_demux = False
|
self.constants.software_demux = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.set_software_demux()
|
self.set_software_demux()
|
||||||
|
|
||||||
def set_battery_throttle(self):
|
def set_battery_throttle(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Disable Firmware Throttling"])
|
utilities.header(["Disable Firmware Throttling"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
By default on Nehalem and newer Macs, the firmware will throttle if
|
By default on Nehalem and newer Macs, the firmware will throttle if
|
||||||
the battery or Display is either dead or missing. The firmware will set
|
the battery or Display is either dead or missing. The firmware will set
|
||||||
@@ -709,14 +710,14 @@ Note: Only supported on Nehalem and newer Macs (2010+)
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.disable_msr_power_ctl = False
|
self.constants.disable_msr_power_ctl = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.set_battery_throttle()
|
self.set_battery_throttle()
|
||||||
|
|
||||||
def set_xcpm(self):
|
def set_xcpm(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Disable XCPM"])
|
utilities.header(["Disable XCPM"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
By default on Ivy Bridge EP and newer Macs, the system will throttle if
|
By default on Ivy Bridge EP and newer Macs, the system will throttle if
|
||||||
the battery or Display is either dead or missing. Apple's XCPM will set
|
the battery or Display is either dead or missing. Apple's XCPM will set
|
||||||
@@ -735,14 +736,14 @@ Note: Only supported on Ivy Bridge EP and newer Macs (2013+)
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.disable_xcpm = False
|
self.constants.disable_xcpm = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.set_xcpm()
|
self.set_xcpm()
|
||||||
|
|
||||||
def set_surplus(self):
|
def set_surplus(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Override SurPlus MaxKernel"])
|
utilities.header(["Override SurPlus MaxKernel"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
By default OCLP will only allow SurPlus to be used on Big Sur and Monterey.
|
By default OCLP will only allow SurPlus to be used on Big Sur and Monterey.
|
||||||
This is for safety reasons in the event newer OSes may break compatibility
|
This is for safety reasons in the event newer OSes may break compatibility
|
||||||
@@ -761,14 +762,14 @@ the event there's issues.
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.force_surplus = False
|
self.constants.force_surplus = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.set_surplus()
|
self.set_surplus()
|
||||||
|
|
||||||
def set_hibernation_workaround(self):
|
def set_hibernation_workaround(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set Hibernation Workaround"])
|
utilities.header(["Set Hibernation Workaround"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
For users with Hibernation issues, you can flip this option to disable certain
|
For users with Hibernation issues, you can flip this option to disable certain
|
||||||
OpenCore settings that may affect the stability of Hibernation. Namely
|
OpenCore settings that may affect the stability of Hibernation. Namely
|
||||||
@@ -792,14 +793,14 @@ Note: This option should only be flipped under the following circumstances:
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.disable_connectdrivers = False
|
self.constants.disable_connectdrivers = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.set_hibernation_workaround()
|
self.set_hibernation_workaround()
|
||||||
|
|
||||||
def set_custom_sip_value(self):
|
def set_custom_sip_value(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set Custom SIP Value"])
|
utilities.header(["Set Custom SIP Value"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
By default OCLP will use the SIP value of 0x00 as the enabled and
|
By default OCLP will use the SIP value of 0x00 as the enabled and
|
||||||
0x803 for machines that require root patching. For users who wish
|
0x803 for machines that require root patching. For users who wish
|
||||||
@@ -815,13 +816,13 @@ To disable SIP outright, set it to 0xFEF
|
|||||||
# Convert to binary hex
|
# Convert to binary hex
|
||||||
self.constants.custom_sip_value = change_menu
|
self.constants.custom_sip_value = change_menu
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("Invalid input, returning to previous menu")
|
logging.info("Invalid input, returning to previous menu")
|
||||||
self.set_custom_sip_value()
|
self.set_custom_sip_value()
|
||||||
|
|
||||||
def set_fu_settings(self):
|
def set_fu_settings(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set FeatureUnlock Settings"])
|
utilities.header(["Set FeatureUnlock Settings"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
By default OCLP will add a kext called FeatureUnlock to enable
|
By default OCLP will add a kext called FeatureUnlock to enable
|
||||||
features locked out from older models. Including:
|
features locked out from older models. Including:
|
||||||
@@ -851,13 +852,13 @@ Supported Options:
|
|||||||
self.constants.fu_status = False
|
self.constants.fu_status = False
|
||||||
self.constants.fu_arguments = None
|
self.constants.fu_arguments = None
|
||||||
else:
|
else:
|
||||||
print("Invalid input, returning to previous menu")
|
logging.info("Invalid input, returning to previous menu")
|
||||||
self.set_fu_settings()
|
self.set_fu_settings()
|
||||||
|
|
||||||
def set_allow_native_spoofs(self):
|
def set_allow_native_spoofs(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Allow Native Spoofs"])
|
utilities.header(["Allow Native Spoofs"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
By default OCLP will not touch the SMBIOS of native models
|
By default OCLP will not touch the SMBIOS of native models
|
||||||
to ensure a "stock-like" environment. However for systems that
|
to ensure a "stock-like" environment. However for systems that
|
||||||
@@ -874,14 +875,14 @@ available however not officially supported.
|
|||||||
elif change_menu in {"n", "N", "no", "No"}:
|
elif change_menu in {"n", "N", "no", "No"}:
|
||||||
self.constants.allow_native_spoofs = False
|
self.constants.allow_native_spoofs = False
|
||||||
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
elif change_menu in {"q", "Q", "Quit", "quit"}:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.set_allow_native_spoofs()
|
self.set_allow_native_spoofs()
|
||||||
|
|
||||||
def set_nvram_write(self):
|
def set_nvram_write(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set NVRAM Write"])
|
utilities.header(["Set NVRAM Write"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
By default, OpenCore will write NVRAM variables to flash. This is
|
By default, OpenCore will write NVRAM variables to flash. This is
|
||||||
recommended for majority of systems however for extremely degraded
|
recommended for majority of systems however for extremely degraded
|
||||||
@@ -899,13 +900,13 @@ Supported Options:
|
|||||||
elif change_menu == "2":
|
elif change_menu == "2":
|
||||||
self.constants.nvram_write = False
|
self.constants.nvram_write = False
|
||||||
else:
|
else:
|
||||||
print("Invalid input, returning to previous menu")
|
logging.info("Invalid input, returning to previous menu")
|
||||||
self.set_nvram_write()
|
self.set_nvram_write()
|
||||||
|
|
||||||
def set_cc_support(self):
|
def set_cc_support(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Set Content Caching Support"])
|
utilities.header(["Set Content Caching Support"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
On systems spoofing via VMM, Content Caching is disabled by
|
On systems spoofing via VMM, Content Caching is disabled by
|
||||||
default by Apple. This option allows you to mask VMM from
|
default by Apple. This option allows you to mask VMM from
|
||||||
@@ -918,12 +919,12 @@ AssetCache.
|
|||||||
elif change_menu in ["n", "N", "no", "No"]:
|
elif change_menu in ["n", "N", "no", "No"]:
|
||||||
self.constants.set_content_caching = False
|
self.constants.set_content_caching = False
|
||||||
elif change_menu in ["q", "Q", "Quit", "quit"]:
|
elif change_menu in ["q", "Q", "Quit", "quit"]:
|
||||||
print("Returning to previous menu")
|
logging.info("Returning to previous menu")
|
||||||
else:
|
else:
|
||||||
self.set_cc_support()
|
self.set_cc_support()
|
||||||
|
|
||||||
def credits(self):
|
def credits(self):
|
||||||
tui_helpers.TUIOnlyPrint(
|
tui_helpers.TUIOnlyLogging.info(
|
||||||
["Credits"],
|
["Credits"],
|
||||||
"Press [Enter] to go back.\n",
|
"Press [Enter] to go back.\n",
|
||||||
[
|
[
|
||||||
@@ -947,7 +948,7 @@ https://github.com/dortania/OpenCore-Legacy-Patcher
|
|||||||
def change_model(self):
|
def change_model(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Select Different Model"])
|
utilities.header(["Select Different Model"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
Tip: Run the following command on the target machine to find the model identifier:
|
Tip: Run the following command on the target machine to find the model identifier:
|
||||||
|
|
||||||
@@ -956,14 +957,14 @@ system_profiler SPHardwareDataType | grep 'Model Identifier'
|
|||||||
)
|
)
|
||||||
self.constants.custom_model = input("Please enter the model identifier of the target machine: ").strip()
|
self.constants.custom_model = input("Please enter the model identifier of the target machine: ").strip()
|
||||||
if self.constants.custom_model not in model_array.SupportedSMBIOS:
|
if self.constants.custom_model not in model_array.SupportedSMBIOS:
|
||||||
print(
|
logging.info(
|
||||||
f"""
|
f"""
|
||||||
{self.constants.custom_model} is not a valid SMBIOS Identifier for macOS {self.constants.os_support}!
|
{self.constants.custom_model} is not a valid SMBIOS Identifier for macOS {self.constants.os_support}!
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
print_models = input(f"Print list of valid options for macOS {self.constants.os_support}? (y/n)")
|
logging.info_models = input(f"Logging.info list of valid options for macOS {self.constants.os_support}? (y/n)")
|
||||||
if print_models.lower() in {"y", "yes"}:
|
if logging.info_models.lower() in {"y", "yes"}:
|
||||||
print("\n".join(model_array.SupportedSMBIOS))
|
logging.info("\n".join(model_array.SupportedSMBIOS))
|
||||||
input("\nPress [ENTER] to continue")
|
input("\nPress [ENTER] to continue")
|
||||||
else:
|
else:
|
||||||
defaults.generate_defaults(self.constants.custom_model, False, self.constants)
|
defaults.generate_defaults(self.constants.custom_model, False, self.constants)
|
||||||
@@ -975,11 +976,11 @@ system_profiler SPHardwareDataType | grep 'Model Identifier'
|
|||||||
no_patch = False
|
no_patch = False
|
||||||
no_unpatch = False
|
no_unpatch = False
|
||||||
if self.constants.detected_os == os_data.os_data.monterey:
|
if self.constants.detected_os == os_data.os_data.monterey:
|
||||||
print(MenuOptions.monterey)
|
logging.info(MenuOptions.monterey)
|
||||||
elif self.constants.detected_os == os_data.os_data.big_sur:
|
elif self.constants.detected_os == os_data.os_data.big_sur:
|
||||||
print(MenuOptions.big_sur)
|
logging.info(MenuOptions.big_sur)
|
||||||
else:
|
else:
|
||||||
print(MenuOptions.default)
|
logging.info(MenuOptions.default)
|
||||||
no_patch = True
|
no_patch = True
|
||||||
no_unpatch = True
|
no_unpatch = True
|
||||||
change_menu = input("Patch System Volume?: ")
|
change_menu = input("Patch System Volume?: ")
|
||||||
@@ -988,7 +989,7 @@ system_profiler SPHardwareDataType | grep 'Model Identifier'
|
|||||||
elif no_unpatch is not True and change_menu == "2":
|
elif no_unpatch is not True and change_menu == "2":
|
||||||
sys_patch.PatchSysVolume(self.constants.custom_model or self.constants.computer.real_model, self.constants, None).start_unpatch()
|
sys_patch.PatchSysVolume(self.constants.custom_model or self.constants.computer.real_model, self.constants, None).start_unpatch()
|
||||||
else:
|
else:
|
||||||
print("Returning to main menu")
|
logging.info("Returning to main menu")
|
||||||
|
|
||||||
def advanced_patcher_settings(self):
|
def advanced_patcher_settings(self):
|
||||||
response = None
|
response = None
|
||||||
@@ -1169,7 +1170,7 @@ system_profiler SPHardwareDataType | grep 'Model Identifier'
|
|||||||
def download_macOS(self):
|
def download_macOS(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Create macOS installer"])
|
utilities.header(["Create macOS installer"])
|
||||||
print(
|
logging.info(
|
||||||
"""
|
"""
|
||||||
This option allows you to download and flash a macOS installer
|
This option allows you to download and flash a macOS installer
|
||||||
to your USB drive.
|
to your USB drive.
|
||||||
@@ -1196,7 +1197,7 @@ B. Exit
|
|||||||
# To avoid selecting the wrong installer by mistake, let user select the correct one
|
# To avoid selecting the wrong installer by mistake, let user select the correct one
|
||||||
self.find_local_installer()
|
self.find_local_installer()
|
||||||
else:
|
else:
|
||||||
print("Failed to start download")
|
logging.info("Failed to start download")
|
||||||
input("Press any key to continue...")
|
input("Press any key to continue...")
|
||||||
|
|
||||||
|
|
||||||
@@ -1246,14 +1247,14 @@ B. Exit
|
|||||||
if installer.create_installer(installer_path, "OCLP-Installer") is True:
|
if installer.create_installer(installer_path, "OCLP-Installer") is True:
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Create macOS installer"])
|
utilities.header(["Create macOS installer"])
|
||||||
print("Installer created successfully.")
|
logging.info("Installer created successfully.")
|
||||||
input("Press enter to exit.")
|
input("Press enter to exit.")
|
||||||
if self.constants.walkthrough is True:
|
if self.constants.walkthrough is True:
|
||||||
self.closing_message()
|
self.closing_message()
|
||||||
else:
|
else:
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Create macOS installer"])
|
utilities.header(["Create macOS installer"])
|
||||||
print("Installer creation failed.")
|
logging.info("Installer creation failed.")
|
||||||
input("Press enter to return to the previous.")
|
input("Press enter to return to the previous.")
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
@@ -1263,12 +1264,12 @@ B. Exit
|
|||||||
def closing_message(self):
|
def closing_message(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Create macOS installer"])
|
utilities.header(["Create macOS installer"])
|
||||||
print("Thank you for using OpenCore Legacy Patcher!")
|
logging.info("Thank you for using OpenCore Legacy Patcher!")
|
||||||
print("Reboot your machine and select EFI Boot to load OpenCore")
|
logging.info("Reboot your machine and select EFI Boot to load OpenCore")
|
||||||
print("")
|
logging.info("")
|
||||||
print("If you have any issues, remember to check the guide as well as\nour Discord server:")
|
logging.info("If you have any issues, remember to check the guide as well as\nour Discord server:")
|
||||||
print("\n\tGuide: https://dortania.github.io/OpenCore-Legacy-Patcher/")
|
logging.info("\n\tGuide: https://dortania.github.io/OpenCore-Legacy-Patcher/")
|
||||||
print("\tDiscord: https://discord.gg/rqdPgH8xSN")
|
logging.info("\tDiscord: https://discord.gg/rqdPgH8xSN")
|
||||||
input("\nPress enter to exit: ")
|
input("\nPress enter to exit: ")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ class commit_info:
|
|||||||
|
|
||||||
def generate_commit_info(self):
|
def generate_commit_info(self):
|
||||||
if self.plist_path:
|
if self.plist_path:
|
||||||
# print(self.plist_path)
|
|
||||||
plist_info = plistlib.load(Path(self.plist_path).open("rb"))
|
plist_info = plistlib.load(Path(self.plist_path).open("rb"))
|
||||||
if "Github" in plist_info:
|
if "Github" in plist_info:
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from data import smbios_data, os_data, cpu_data
|
from data import smbios_data, os_data, cpu_data
|
||||||
from resources import utilities
|
from resources import utilities
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
def set_smbios_model_spoof(model):
|
def set_smbios_model_spoof(model):
|
||||||
try:
|
try:
|
||||||
@@ -60,7 +61,7 @@ def generate_fw_features(model, custom):
|
|||||||
if not custom:
|
if not custom:
|
||||||
firmwarefeature = utilities.get_rom("firmware-features")
|
firmwarefeature = utilities.get_rom("firmware-features")
|
||||||
if not firmwarefeature:
|
if not firmwarefeature:
|
||||||
print("- Failed to find FirmwareFeatures, falling back on defaults")
|
logging.info("- Failed to find FirmwareFeatures, falling back on defaults")
|
||||||
if smbios_data.smbios_dictionary[model]["FirmwareFeatures"] is None:
|
if smbios_data.smbios_dictionary[model]["FirmwareFeatures"] is None:
|
||||||
firmwarefeature = 0
|
firmwarefeature = 0
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import plistlib
|
import plistlib
|
||||||
|
import logging
|
||||||
|
|
||||||
class global_settings:
|
class global_settings:
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ class global_settings:
|
|||||||
try:
|
try:
|
||||||
plistlib.dump({"Developed by Dortania": True,}, Path(self.global_settings_plist).open("wb"))
|
plistlib.dump({"Developed by Dortania": True,}, Path(self.global_settings_plist).open("wb"))
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
print("- Permission error: Unable to write to global settings file")
|
logging.info("- Permission error: Unable to write to global settings file")
|
||||||
|
|
||||||
def read_property(self, property_name):
|
def read_property(self, property_name):
|
||||||
if Path(self.global_settings_plist).exists():
|
if Path(self.global_settings_plist).exists():
|
||||||
@@ -37,7 +38,7 @@ class global_settings:
|
|||||||
try:
|
try:
|
||||||
plistlib.dump(plist, Path(self.global_settings_plist).open("wb"))
|
plistlib.dump(plist, Path(self.global_settings_plist).open("wb"))
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
print("- Failed to write to global settings file")
|
logging.info("- Failed to write to global settings file")
|
||||||
|
|
||||||
|
|
||||||
def convert_defaults_to_global_settings(self):
|
def convert_defaults_to_global_settings(self):
|
||||||
@@ -52,11 +53,11 @@ class global_settings:
|
|||||||
try:
|
try:
|
||||||
plistlib.dump(global_settings_plist, Path(self.global_settings_plist).open("wb"))
|
plistlib.dump(global_settings_plist, Path(self.global_settings_plist).open("wb"))
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
print("- Permission error: Unable to write to global settings file")
|
logging.info("- Permission error: Unable to write to global settings file")
|
||||||
return
|
return
|
||||||
|
|
||||||
# delete defaults plist
|
# delete defaults plist
|
||||||
try:
|
try:
|
||||||
Path(defaults_path).unlink()
|
Path(defaults_path).unlink()
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
print("- Permission error: Unable to delete defaults plist")
|
logging.info("- Permission error: Unable to delete defaults plist")
|
||||||
+240
-176
@@ -17,9 +17,10 @@ import binascii
|
|||||||
import hashlib
|
import hashlib
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import py_sip_xnu
|
import py_sip_xnu
|
||||||
|
import logging
|
||||||
|
|
||||||
from resources import constants, defaults, install, installer, utilities, run, generate_smbios, updates, integrity_verification, global_settings, kdk_handler
|
from resources import constants, defaults, install, installer, utilities, run, generate_smbios, updates, integrity_verification, global_settings, kdk_handler, network_handler
|
||||||
from resources.sys_patch import sys_patch_download, sys_patch_detect, sys_patch, sys_patch_auto
|
from resources.sys_patch import sys_patch_detect, sys_patch
|
||||||
from resources.build import build
|
from resources.build import build
|
||||||
from data import model_array, os_data, smbios_data, sip_data, cpu_data
|
from data import model_array, os_data, smbios_data, sip_data, cpu_data
|
||||||
from resources.gui import menu_redirect, gui_help
|
from resources.gui import menu_redirect, gui_help
|
||||||
@@ -40,8 +41,7 @@ class wx_python_gui:
|
|||||||
self.hyperlink_colour = (25, 179, 231)
|
self.hyperlink_colour = (25, 179, 231)
|
||||||
|
|
||||||
# Backup stdout for usage with wxPython
|
# Backup stdout for usage with wxPython
|
||||||
self.stock_stdout = sys.stdout
|
self.stock_stream = logging.getLogger().handlers[0].stream
|
||||||
self.stock_stderr = sys.stderr
|
|
||||||
|
|
||||||
current_uid = os.getuid()
|
current_uid = os.getuid()
|
||||||
|
|
||||||
@@ -108,8 +108,7 @@ class wx_python_gui:
|
|||||||
def reset_window(self):
|
def reset_window(self):
|
||||||
self.frame.DestroyChildren()
|
self.frame.DestroyChildren()
|
||||||
self.frame.SetSize(self.WINDOW_WIDTH_MAIN, self.WINDOW_HEIGHT_MAIN)
|
self.frame.SetSize(self.WINDOW_WIDTH_MAIN, self.WINDOW_HEIGHT_MAIN)
|
||||||
sys.stdout = self.stock_stdout
|
logging.getLogger().handlers[0].stream = self.stock_stream
|
||||||
sys.stderr = self.stock_stderr
|
|
||||||
self.reset_frame_modal()
|
self.reset_frame_modal()
|
||||||
|
|
||||||
# Re-enable sleep if we failed to do so before returning to the main menu
|
# Re-enable sleep if we failed to do so before returning to the main menu
|
||||||
@@ -261,7 +260,7 @@ class wx_python_gui:
|
|||||||
|
|
||||||
result = subprocess.run(args,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
result = subprocess.run(args,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
print("- Failed to move application into /Library/Application Support/Dortania/OpenCore-Patcher.app")
|
logging.info("- Failed to move application into /Library/Application Support/Dortania/OpenCore-Patcher.app")
|
||||||
# Notify user we failed to move the application
|
# Notify user we failed to move the application
|
||||||
self.popup = wx.MessageDialog(
|
self.popup = wx.MessageDialog(
|
||||||
self.frame,
|
self.frame,
|
||||||
@@ -293,7 +292,7 @@ class wx_python_gui:
|
|||||||
for entry in dict:
|
for entry in dict:
|
||||||
version = dict[entry]["Version"]
|
version = dict[entry]["Version"]
|
||||||
github_link = dict[entry]["Github Link"]
|
github_link = dict[entry]["Github Link"]
|
||||||
print(f"New version: {version}")
|
logging.info(f"New version: {version}")
|
||||||
self.dialog = wx.MessageDialog(
|
self.dialog = wx.MessageDialog(
|
||||||
parent=self.frame,
|
parent=self.frame,
|
||||||
message=f"Current Version: {self.constants.patcher_version}\nNew version: {version}\nWould you like to view?",
|
message=f"Current Version: {self.constants.patcher_version}\nNew version: {version}\nWould you like to view?",
|
||||||
@@ -306,12 +305,12 @@ class wx_python_gui:
|
|||||||
if response == wx.ID_YES:
|
if response == wx.ID_YES:
|
||||||
webbrowser.open(github_link)
|
webbrowser.open(github_link)
|
||||||
elif response == wx.ID_NO:
|
elif response == wx.ID_NO:
|
||||||
print("- Setting IgnoreAppUpdates to True")
|
logging.info("- Setting IgnoreAppUpdates to True")
|
||||||
self.constants.ignore_updates = True
|
self.constants.ignore_updates = True
|
||||||
global_settings.global_settings().write_property("IgnoreAppUpdates", True)
|
global_settings.global_settings().write_property("IgnoreAppUpdates", True)
|
||||||
else:
|
else:
|
||||||
self.constants.ignore_updates = True
|
self.constants.ignore_updates = True
|
||||||
print("- Ignoring App Updates due to defaults")
|
logging.info("- Ignoring App Updates due to defaults")
|
||||||
|
|
||||||
# if did_find_update is False:
|
# if did_find_update is False:
|
||||||
# self.check_for_local_installs()
|
# self.check_for_local_installs()
|
||||||
@@ -332,7 +331,7 @@ class wx_python_gui:
|
|||||||
|
|
||||||
# Show Dialog Box
|
# Show Dialog Box
|
||||||
if self.dialog.ShowModal() == wx.ID_YES:
|
if self.dialog.ShowModal() == wx.ID_YES:
|
||||||
print("Relaunching as root")
|
logging.info("Relaunching as root")
|
||||||
|
|
||||||
timer_val = 5
|
timer_val = 5
|
||||||
extension = ""
|
extension = ""
|
||||||
@@ -706,8 +705,9 @@ class wx_python_gui:
|
|||||||
# Centre the text box to top of window
|
# Centre the text box to top of window
|
||||||
self.stdout_text.Centre(wx.HORIZONTAL)
|
self.stdout_text.Centre(wx.HORIZONTAL)
|
||||||
self.stdout_text.SetValue("")
|
self.stdout_text.SetValue("")
|
||||||
sys.stdout=menu_redirect.RedirectText(self.stdout_text, False)
|
|
||||||
sys.stderr=menu_redirect.RedirectText(self.stdout_text, False)
|
# Set StreamHandler to redirect stdout to textbox
|
||||||
|
logging.getLogger().handlers[0].stream = menu_redirect.RedirectText(self.stdout_text, False)
|
||||||
|
|
||||||
self.return_to_main_menu = wx.Button(self.frame_modal, label="Return to Main Menu")
|
self.return_to_main_menu = wx.Button(self.frame_modal, label="Return to Main Menu")
|
||||||
self.return_to_main_menu.SetPosition(
|
self.return_to_main_menu.SetPosition(
|
||||||
@@ -735,8 +735,7 @@ class wx_python_gui:
|
|||||||
self.build_opencore.Bind(wx.EVT_BUTTON, self.install_menu)
|
self.build_opencore.Bind(wx.EVT_BUTTON, self.install_menu)
|
||||||
|
|
||||||
# Reset stdout
|
# Reset stdout
|
||||||
sys.stdout = self.stock_stdout
|
logging.getLogger().handlers[0].stream = self.stock_stream
|
||||||
sys.stderr = self.stock_stderr
|
|
||||||
|
|
||||||
# Throw popup asking to install OpenCore
|
# Throw popup asking to install OpenCore
|
||||||
self.dialog = wx.MessageDialog(
|
self.dialog = wx.MessageDialog(
|
||||||
@@ -838,7 +837,7 @@ class wx_python_gui:
|
|||||||
|
|
||||||
for disk in list_disks:
|
for disk in list_disks:
|
||||||
# Create a button for each disk
|
# Create a button for each disk
|
||||||
print(f"{list_disks[disk]['disk']} - {list_disks[disk]['name']} - {list_disks[disk]['size']}")
|
logging.info(f"{list_disks[disk]['disk']} - {list_disks[disk]['name']} - {list_disks[disk]['size']}")
|
||||||
self.install_button = wx.Button(self.frame, label=disk, size=(300,30))
|
self.install_button = wx.Button(self.frame, label=disk, size=(300,30))
|
||||||
self.install_button.SetLabel(f"{list_disks[disk]['disk']} - {list_disks[disk]['name']} - {list_disks[disk]['size']}")
|
self.install_button.SetLabel(f"{list_disks[disk]['disk']} - {list_disks[disk]['name']} - {list_disks[disk]['size']}")
|
||||||
self.install_button.SetPosition(
|
self.install_button.SetPosition(
|
||||||
@@ -913,7 +912,7 @@ class wx_python_gui:
|
|||||||
|
|
||||||
list_partitions = install.tui_disk_installation(self.constants).list_partitions(disk, disk_data)
|
list_partitions = install.tui_disk_installation(self.constants).list_partitions(disk, disk_data)
|
||||||
for partition in list_partitions:
|
for partition in list_partitions:
|
||||||
print(f"{list_partitions[partition]['partition']} - {list_partitions[partition]['name']} - {list_partitions[partition]['size']}")
|
logging.info(f"{list_partitions[partition]['partition']} - {list_partitions[partition]['name']} - {list_partitions[partition]['size']}")
|
||||||
self.install_button = wx.Button(self.frame_modal, label=partition, size=(300,30))
|
self.install_button = wx.Button(self.frame_modal, label=partition, size=(300,30))
|
||||||
self.install_button.SetLabel(f"{list_partitions[partition]['partition']} - {list_partitions[partition]['name']} - {list_partitions[partition]['size']}")
|
self.install_button.SetLabel(f"{list_partitions[partition]['partition']} - {list_partitions[partition]['name']} - {list_partitions[partition]['size']}")
|
||||||
self.install_button.SetPosition(
|
self.install_button.SetPosition(
|
||||||
@@ -943,7 +942,7 @@ class wx_python_gui:
|
|||||||
self.frame_modal.ShowWindowModal()
|
self.frame_modal.ShowWindowModal()
|
||||||
|
|
||||||
def install_oc_process(self, partition):
|
def install_oc_process(self, partition):
|
||||||
print(f"Installing OpenCore to {partition}")
|
logging.info(f"Installing OpenCore to {partition}")
|
||||||
self.reset_frame_modal()
|
self.reset_frame_modal()
|
||||||
self.frame_modal.SetSize(self.WINDOW_WIDTH_BUILD - 20, self.WINDOW_HEIGHT_BUILD)
|
self.frame_modal.SetSize(self.WINDOW_WIDTH_BUILD - 20, self.WINDOW_HEIGHT_BUILD)
|
||||||
|
|
||||||
@@ -967,11 +966,9 @@ class wx_python_gui:
|
|||||||
self.frame_modal.SetSize(-1, self.stdout_text.GetPosition().y + self.stdout_text.GetSize().height + 40)
|
self.frame_modal.SetSize(-1, self.stdout_text.GetPosition().y + self.stdout_text.GetSize().height + 40)
|
||||||
self.frame_modal.ShowWindowModal()
|
self.frame_modal.ShowWindowModal()
|
||||||
|
|
||||||
sys.stdout=menu_redirect.RedirectText(self.stdout_text, False)
|
logging.getLogger().handlers[0].stream = menu_redirect.RedirectText(self.stdout_text, False)
|
||||||
sys.stderr=menu_redirect.RedirectText(self.stdout_text, False)
|
|
||||||
result = install.tui_disk_installation(self.constants).install_opencore(partition)
|
result = install.tui_disk_installation(self.constants).install_opencore(partition)
|
||||||
sys.stdout=sys.__stdout__
|
logging.getLogger().handlers[0].stream = self.stock_stream
|
||||||
sys.stderr=sys.__stderr__
|
|
||||||
|
|
||||||
self.return_to_main_menu = wx.Button(self.frame_modal, label="Return to Main Menu")
|
self.return_to_main_menu = wx.Button(self.frame_modal, label="Return to Main Menu")
|
||||||
self.return_to_main_menu.SetPosition(
|
self.return_to_main_menu.SetPosition(
|
||||||
@@ -1024,10 +1021,10 @@ class wx_python_gui:
|
|||||||
break
|
break
|
||||||
|
|
||||||
if patch_installed is False:
|
if patch_installed is False:
|
||||||
print(f"- Patch {patch} not installed")
|
logging.info(f"- Patch {patch} not installed")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
print("- No new patches detected for system")
|
logging.info("- No new patches detected for system")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@@ -1062,7 +1059,7 @@ class wx_python_gui:
|
|||||||
self.patches = patches
|
self.patches = patches
|
||||||
can_unpatch = patches["Validation: Unpatching Possible"]
|
can_unpatch = patches["Validation: Unpatching Possible"]
|
||||||
if not any(not patch.startswith("Settings") and not patch.startswith("Validation") and patches[patch] is True for patch in patches):
|
if not any(not patch.startswith("Settings") and not patch.startswith("Validation") and patches[patch] is True for patch in patches):
|
||||||
print("- No applicable patches available")
|
logging.info("- No applicable patches available")
|
||||||
patches = []
|
patches = []
|
||||||
|
|
||||||
# Check if OCLP has already applied the same patches
|
# Check if OCLP has already applied the same patches
|
||||||
@@ -1076,7 +1073,7 @@ class wx_python_gui:
|
|||||||
for patch in patches:
|
for patch in patches:
|
||||||
# Add Label for each patch
|
# Add Label for each patch
|
||||||
if (not patch.startswith("Settings") and not patch.startswith("Validation") and patches[patch] is True):
|
if (not patch.startswith("Settings") and not patch.startswith("Validation") and patches[patch] is True):
|
||||||
print(f"- Adding patch: {patch} - {patches[patch]}")
|
logging.info(f"- Adding patch: {patch} - {patches[patch]}")
|
||||||
self.patch_label = wx.StaticText(self.frame_modal, label=f"- {patch}")
|
self.patch_label = wx.StaticText(self.frame_modal, label=f"- {patch}")
|
||||||
self.patch_label.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
self.patch_label.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||||
self.patch_label.SetPosition(
|
self.patch_label.SetPosition(
|
||||||
@@ -1112,7 +1109,7 @@ class wx_python_gui:
|
|||||||
if patch == "Validation: Unpatching Possible":
|
if patch == "Validation: Unpatching Possible":
|
||||||
continue
|
continue
|
||||||
if patch.startswith("Validation") and patches[patch] is True:
|
if patch.startswith("Validation") and patches[patch] is True:
|
||||||
print(f"- Adding check: {patch} - {patches[patch]}")
|
logging.info(f"- Adding check: {patch} - {patches[patch]}")
|
||||||
self.patch_label = wx.StaticText(self.frame_modal, label=f"- {patch[12:]}")
|
self.patch_label = wx.StaticText(self.frame_modal, label=f"- {patch[12:]}")
|
||||||
self.patch_label.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
self.patch_label.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||||
self.patch_label.SetPosition(
|
self.patch_label.SetPosition(
|
||||||
@@ -1268,34 +1265,61 @@ class wx_python_gui:
|
|||||||
|
|
||||||
self.progress_bar.Hide()
|
self.progress_bar.Hide()
|
||||||
|
|
||||||
# Download resources
|
|
||||||
sys.stdout=menu_redirect.RedirectLabel(self.developer_note)
|
|
||||||
download_result, link = sys_patch_download.grab_patcher_support_pkg(self.constants).download_files()
|
|
||||||
sys.stdout=sys.__stdout__
|
|
||||||
|
|
||||||
if download_result is None:
|
|
||||||
# Create popup window to inform user of error
|
|
||||||
self.popup = wx.MessageDialog(
|
|
||||||
self.frame_modal,
|
|
||||||
"A problem occurred trying to download PatcherSupportPkg binaries\n\nIf you continue to have this error, download an Offline build from Github\nThese builds don't require a network connection to root patch",
|
|
||||||
"Network Error",
|
|
||||||
wx.YES_NO | wx.ICON_ERROR
|
|
||||||
)
|
|
||||||
self.popup.SetYesNoLabels("View on Github", "Ignore")
|
|
||||||
answer = self.popup.ShowModal()
|
|
||||||
if answer == wx.ID_YES:
|
|
||||||
webbrowser.open(self.constants.repo_link_latest)
|
|
||||||
self.main_menu()
|
|
||||||
|
|
||||||
if self.patches["Settings: Kernel Debug Kit missing"] is True:
|
if self.patches["Settings: Kernel Debug Kit missing"] is True:
|
||||||
# Download KDK (if needed)
|
# Download KDK (if needed)
|
||||||
self.subheader.SetLabel("Downloading Kernel Debug Kit")
|
self.subheader.SetLabel("Downloading Kernel Debug Kit")
|
||||||
self.subheader.Centre(wx.HORIZONTAL)
|
self.subheader.Centre(wx.HORIZONTAL)
|
||||||
self.developer_note.SetLabel("Starting shortly")
|
self.developer_note.SetLabel("Starting shortly")
|
||||||
|
|
||||||
sys.stdout=menu_redirect.RedirectLabel(self.developer_note)
|
kdk_result = False
|
||||||
kdk_result, error_msg, detected_build = kdk_handler.kernel_debug_kit_handler(self.constants).download_kdk(self.constants.detected_os_version, self.constants.detected_os_build)
|
kdk_obj = kdk_handler.KernelDebugKitObject(self.constants, self.constants.detected_os_build, self.constants.detected_os_version)
|
||||||
sys.stdout=sys.__stdout__
|
if kdk_obj.success is True:
|
||||||
|
kdk_download_obj = kdk_obj.retrieve_download()
|
||||||
|
if not kdk_download_obj:
|
||||||
|
kdk_result = True
|
||||||
|
else:
|
||||||
|
kdk_download_obj.download()
|
||||||
|
|
||||||
|
self.header.SetLabel(f"Downloading KDK Build: {kdk_obj.kdk_url_build}")
|
||||||
|
self.header.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
self.progress_bar.SetValue(0)
|
||||||
|
# Set below developer note
|
||||||
|
self.progress_bar.SetPosition(
|
||||||
|
wx.Point(
|
||||||
|
self.developer_note.GetPosition().x,
|
||||||
|
self.developer_note.GetPosition().y + self.developer_note.GetSize().height + 10
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.progress_bar.Centre(wx.HORIZONTAL)
|
||||||
|
self.progress_bar.Show()
|
||||||
|
|
||||||
|
self.frame.SetSize(-1, self.progress_bar.GetPosition().y + self.progress_bar.GetSize().height + 60)
|
||||||
|
|
||||||
|
while kdk_download_obj.is_active():
|
||||||
|
self.subheader.SetLabel(f"{utilities.human_fmt(kdk_download_obj.downloaded_file_size)} downloaded of {utilities.human_fmt(kdk_download_obj.total_file_size)} ({kdk_download_obj.get_percent():.2f}%)")
|
||||||
|
self.subheader.Centre(wx.HORIZONTAL)
|
||||||
|
self.developer_note.SetLabel(
|
||||||
|
f"Average download speed: {utilities.human_fmt(kdk_download_obj.get_speed())}/s"
|
||||||
|
)
|
||||||
|
self.developer_note.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
self.progress_bar.SetValue(kdk_download_obj.get_percent())
|
||||||
|
|
||||||
|
wx.GetApp().Yield()
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
if kdk_download_obj.download_complete is False:
|
||||||
|
logging.error("Failed to download KDK")
|
||||||
|
logging.error(kdk_download_obj.error_msg)
|
||||||
|
error_msg = kdk_download_obj.error_msg
|
||||||
|
else:
|
||||||
|
kdk_result = kdk_obj.validate_kdk_checksum()
|
||||||
|
error_msg = kdk_obj.error_msg
|
||||||
|
else:
|
||||||
|
logging.error("Failed to download KDK")
|
||||||
|
logging.error(kdk_obj.error_msg)
|
||||||
|
error_msg = kdk_obj.error_msg
|
||||||
|
|
||||||
if kdk_result is False:
|
if kdk_result is False:
|
||||||
# Create popup window to inform user of error
|
# Create popup window to inform user of error
|
||||||
@@ -1368,8 +1392,7 @@ class wx_python_gui:
|
|||||||
|
|
||||||
self.frame_modal.SetSize(self.WINDOW_WIDTH_BUILD, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40)
|
self.frame_modal.SetSize(self.WINDOW_WIDTH_BUILD, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40)
|
||||||
|
|
||||||
sys.stdout = menu_redirect.RedirectText(self.text_box, True)
|
logging.getLogger().handlers[0].stream = menu_redirect.RedirectText(self.text_box, True)
|
||||||
sys.stderr = menu_redirect.RedirectText(self.text_box, True)
|
|
||||||
self.frame_modal.ShowWindowModal()
|
self.frame_modal.ShowWindowModal()
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
try:
|
try:
|
||||||
@@ -1377,10 +1400,9 @@ class wx_python_gui:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.text_box.AppendText(f"- An internal error occurred while running the Root Patcher:\n{str(e)}")
|
self.text_box.AppendText(f"- An internal error occurred while running the Root Patcher:\n{str(e)}")
|
||||||
pass
|
pass
|
||||||
sys.stdout = self.stock_stdout
|
logging.getLogger().handlers[0].stream = self.stock_stream
|
||||||
sys.stderr = self.stock_stderr
|
|
||||||
if self.constants.root_patcher_succeeded is True:
|
if self.constants.root_patcher_succeeded is True:
|
||||||
print("- Root Patcher finished successfully")
|
logging.info("- Root Patcher finished successfully")
|
||||||
if self.constants.needs_to_open_preferences is True:
|
if self.constants.needs_to_open_preferences is True:
|
||||||
if self.constants.detected_os >= os_data.os_data.ventura:
|
if self.constants.detected_os >= os_data.os_data.ventura:
|
||||||
self.reboot_system(message="Root Patcher finished successfully!\nIf you were prompted to open System Settings to authorize new kexts, this can be ignored. Your system is ready once restarted.\n\nWould you like to reboot now?")
|
self.reboot_system(message="Root Patcher finished successfully!\nIf you were prompted to open System Settings to authorize new kexts, this can be ignored. Your system is ready once restarted.\n\nWould you like to reboot now?")
|
||||||
@@ -1479,8 +1501,7 @@ class wx_python_gui:
|
|||||||
self.frame_modal.SetSize(-1, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40)
|
self.frame_modal.SetSize(-1, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40)
|
||||||
|
|
||||||
# Start reverting root patches
|
# Start reverting root patches
|
||||||
sys.stdout = menu_redirect.RedirectText(self.text_box, True)
|
logging.getLogger().handlers[0].stream = menu_redirect.RedirectText(self.text_box, True)
|
||||||
sys.stderr = menu_redirect.RedirectText(self.text_box, True)
|
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
self.frame_modal.ShowWindowModal()
|
self.frame_modal.ShowWindowModal()
|
||||||
while self.is_unpack_finished() is False:
|
while self.is_unpack_finished() is False:
|
||||||
@@ -1490,10 +1511,9 @@ class wx_python_gui:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.text_box.AppendText(f"- An internal error occurred while running the Root Patcher:\n{str(e)}")
|
self.text_box.AppendText(f"- An internal error occurred while running the Root Patcher:\n{str(e)}")
|
||||||
pass
|
pass
|
||||||
sys.stdout = self.stock_stdout
|
logging.getLogger().handlers[0].stream = self.stock_stream
|
||||||
sys.stderr = self.stock_stderr
|
|
||||||
if self.constants.root_patcher_succeeded is True:
|
if self.constants.root_patcher_succeeded is True:
|
||||||
print("- Root Patcher finished successfully")
|
logging.info("- Root Patcher finished successfully")
|
||||||
self.reboot_system(message="Root Patcher finished successfully\nWould you like to reboot now?")
|
self.reboot_system(message="Root Patcher finished successfully\nWould you like to reboot now?")
|
||||||
self.return_to_main_menu.Enable()
|
self.return_to_main_menu.Enable()
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
@@ -1599,7 +1619,7 @@ class wx_python_gui:
|
|||||||
def ia():
|
def ia():
|
||||||
self.available_installers = installer.list_downloadable_macOS_installers(self.constants.payload_path, "DeveloperSeed")
|
self.available_installers = installer.list_downloadable_macOS_installers(self.constants.payload_path, "DeveloperSeed")
|
||||||
|
|
||||||
print("- Downloading installer catalog...")
|
logging.info("- Downloading installer catalog...")
|
||||||
thread_ia = threading.Thread(target=ia)
|
thread_ia = threading.Thread(target=ia)
|
||||||
thread_ia.start()
|
thread_ia.start()
|
||||||
|
|
||||||
@@ -1608,7 +1628,7 @@ class wx_python_gui:
|
|||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
available_installers = self.available_installers
|
available_installers = self.available_installers
|
||||||
else:
|
else:
|
||||||
print("- Using existing installer catalog...")
|
logging.info("- Using existing installer catalog...")
|
||||||
available_installers = ias
|
available_installers = ias
|
||||||
|
|
||||||
self.reset_frame_modal()
|
self.reset_frame_modal()
|
||||||
@@ -1637,7 +1657,7 @@ class wx_python_gui:
|
|||||||
if ias is None:
|
if ias is None:
|
||||||
available_installers = installer.only_list_newest_installers(available_installers)
|
available_installers = installer.only_list_newest_installers(available_installers)
|
||||||
for app in available_installers:
|
for app in available_installers:
|
||||||
print(f"macOS {available_installers[app]['Version']} ({available_installers[app]['Build']}):\n - Size: {utilities.human_fmt(available_installers[app]['Size'])}\n - Source: {available_installers[app]['Source']}\n - Variant: {available_installers[app]['Variant']}\n - Link: {available_installers[app]['Link']}\n")
|
logging.info(f"macOS {available_installers[app]['Version']} ({available_installers[app]['Build']}):\n - Size: {utilities.human_fmt(available_installers[app]['Size'])}\n - Source: {available_installers[app]['Source']}\n - Variant: {available_installers[app]['Variant']}\n - Link: {available_installers[app]['Link']}\n")
|
||||||
if available_installers[app]['Variant'] in ["DeveloperSeed" , "PublicSeed"]:
|
if available_installers[app]['Variant'] in ["DeveloperSeed" , "PublicSeed"]:
|
||||||
extra = " Beta"
|
extra = " Beta"
|
||||||
else:
|
else:
|
||||||
@@ -1757,14 +1777,32 @@ class wx_python_gui:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.download_label.Centre(wx.HORIZONTAL)
|
self.download_label.Centre(wx.HORIZONTAL)
|
||||||
# Redirect stdout to label
|
|
||||||
sys.stdout=menu_redirect.RedirectLabel(self.download_label)
|
self.download_label_2 = wx.StaticText(self.frame, label="")
|
||||||
|
self.download_label_2.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
|
||||||
|
self.download_label_2.SetPosition(
|
||||||
|
wx.Point(
|
||||||
|
self.download_label.GetPosition().x,
|
||||||
|
self.download_label.GetPosition().y + self.download_label.GetSize().height + 5
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.download_label_2.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Progress Bar
|
||||||
|
self.download_progress = wx.Gauge(self.frame, range=100, size=(self.frame.GetSize().width - 100, 20))
|
||||||
|
self.download_progress.SetPosition(
|
||||||
|
wx.Point(
|
||||||
|
self.download_label_2.GetPosition().x,
|
||||||
|
self.download_label_2.GetPosition().y + self.download_label_2.GetSize().height + 5
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.download_progress.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
self.return_to_main_menu = wx.Button(self.frame, label="Return to Main Menu")
|
self.return_to_main_menu = wx.Button(self.frame, label="Return to Main Menu")
|
||||||
self.return_to_main_menu.SetPosition(
|
self.return_to_main_menu.SetPosition(
|
||||||
wx.Point(
|
wx.Point(
|
||||||
self.download_label.GetPosition().x,
|
self.download_progress.GetPosition().x,
|
||||||
self.download_label.GetPosition().y + self.download_label.GetSize().height + 30
|
self.download_progress.GetPosition().y + self.download_progress.GetSize().height + 15
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.return_to_main_menu.Bind(wx.EVT_BUTTON, self.main_menu)
|
self.return_to_main_menu.Bind(wx.EVT_BUTTON, self.main_menu)
|
||||||
@@ -1772,16 +1810,32 @@ class wx_python_gui:
|
|||||||
self.frame.SetSize(-1, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40)
|
self.frame.SetSize(-1, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40)
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
|
|
||||||
|
|
||||||
|
ia_download = network_handler.DownloadObject(app_dict['Link'], self.constants.payload_path / "InstallAssistant.pkg")
|
||||||
|
ia_download.download()
|
||||||
|
|
||||||
|
while ia_download.is_active():
|
||||||
|
wx.GetApp().Yield()
|
||||||
|
self.download_label.SetLabel(f"{utilities.human_fmt(ia_download.downloaded_file_size)} downloaded of {utilities.human_fmt(ia_download.total_file_size)} ({ia_download.get_percent():.2f}%)")
|
||||||
|
self.download_label.Centre(wx.HORIZONTAL)
|
||||||
|
self.download_label_2.SetLabel(
|
||||||
|
f"Average download speed: {utilities.human_fmt(ia_download.get_speed())}/s"
|
||||||
|
)
|
||||||
|
self.download_label_2.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
self.download_progress.SetValue(ia_download.get_percent())
|
||||||
|
|
||||||
|
wx.GetApp().Yield()
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
|
||||||
# Download macOS install data
|
# Download macOS install data
|
||||||
if installer.download_install_assistant(self.constants.payload_path, app_dict['Link']):
|
if ia_download.download_complete is True:
|
||||||
# Fix stdout
|
|
||||||
sys.stdout = self.stock_stdout
|
|
||||||
self.download_label.SetLabel(f"Finished Downloading {installer_name}")
|
self.download_label.SetLabel(f"Finished Downloading {installer_name}")
|
||||||
self.download_label.Centre(wx.HORIZONTAL)
|
self.download_label.Centre(wx.HORIZONTAL)
|
||||||
wx.App.Get().Yield()
|
wx.App.Get().Yield()
|
||||||
self.installer_validation(apple_integrity_file_link= app_dict['integrity'])
|
self.installer_validation(apple_integrity_file_link=app_dict['integrity'])
|
||||||
else:
|
else:
|
||||||
sys.stdout = self.stock_stdout
|
|
||||||
self.download_label.SetLabel(f"Failed to download {installer_name}")
|
self.download_label.SetLabel(f"Failed to download {installer_name}")
|
||||||
self.download_label.Centre(wx.HORIZONTAL)
|
self.download_label.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
@@ -1822,7 +1876,7 @@ class wx_python_gui:
|
|||||||
self.return_to_main_menu.SetPosition(
|
self.return_to_main_menu.SetPosition(
|
||||||
wx.Point(
|
wx.Point(
|
||||||
self.progress_bar.GetPosition().x,
|
self.progress_bar.GetPosition().x,
|
||||||
self.progress_bar.GetPosition().y + self.progress_bar.GetSize().height + 40
|
self.progress_bar.GetPosition().y + self.progress_bar.GetSize().height + 10
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.return_to_main_menu.Bind(wx.EVT_BUTTON, self.main_menu)
|
self.return_to_main_menu.Bind(wx.EVT_BUTTON, self.main_menu)
|
||||||
@@ -1832,7 +1886,8 @@ class wx_python_gui:
|
|||||||
|
|
||||||
wx.App.Get().Yield()
|
wx.App.Get().Yield()
|
||||||
integrity_path = Path(Path(self.constants.payload_path) / Path(apple_integrity_file_link.split("/")[-1]))
|
integrity_path = Path(Path(self.constants.payload_path) / Path(apple_integrity_file_link.split("/")[-1]))
|
||||||
if utilities.download_file(apple_integrity_file_link, integrity_path, verify_checksum=False):
|
|
||||||
|
if network_handler.DownloadObject(apple_integrity_file_link, integrity_path).download_simple(verify_checksum=False):
|
||||||
# If we're unable to download the integrity file immediately after downloading the IA, there's a legitimate issue
|
# If we're unable to download the integrity file immediately after downloading the IA, there's a legitimate issue
|
||||||
# on Apple's end.
|
# on Apple's end.
|
||||||
# Fail gracefully and just head to installing the IA.
|
# Fail gracefully and just head to installing the IA.
|
||||||
@@ -1850,7 +1905,7 @@ class wx_python_gui:
|
|||||||
for chunk in chunks:
|
for chunk in chunks:
|
||||||
status = hashlib.sha256(f.read(chunk["length"])).digest()
|
status = hashlib.sha256(f.read(chunk["length"])).digest()
|
||||||
if not status == chunk["checksum"]:
|
if not status == chunk["checksum"]:
|
||||||
print(f"Chunk {chunks.index(chunk) + 1} checksum status FAIL: chunk sum {binascii.hexlify(chunk['checksum']).decode()}, calculated sum {binascii.hexlify(status).decode()}")
|
logging.info(f"Chunk {chunks.index(chunk) + 1} checksum status FAIL: chunk sum {binascii.hexlify(chunk['checksum']).decode()}, calculated sum {binascii.hexlify(status).decode()}")
|
||||||
self.popup = wx.MessageDialog(
|
self.popup = wx.MessageDialog(
|
||||||
self.frame,
|
self.frame,
|
||||||
f"We've found that Chunk {chunks.index(chunk) + 1} of {len(chunks)} has failed the integrity check.\n\nThis generally happens when downloading on unstable connections such as WiFi or cellular.\n\nPlease try redownloading again on a stable connection (ie. Ethernet)",
|
f"We've found that Chunk {chunks.index(chunk) + 1} of {len(chunks)} has failed the integrity check.\n\nThis generally happens when downloading on unstable connections such as WiFi or cellular.\n\nPlease try redownloading again on a stable connection (ie. Ethernet)",
|
||||||
@@ -1865,9 +1920,9 @@ class wx_python_gui:
|
|||||||
self.verifying_chunk_label.SetLabel(f"Verifying Chunk {self.progress_bar.GetValue()} of {max_progress}")
|
self.verifying_chunk_label.SetLabel(f"Verifying Chunk {self.progress_bar.GetValue()} of {max_progress}")
|
||||||
wx.App.Get().Yield()
|
wx.App.Get().Yield()
|
||||||
else:
|
else:
|
||||||
print("Invalid integrity file provided")
|
logging.info("Invalid integrity file provided")
|
||||||
else:
|
else:
|
||||||
print("Failed to download integrity file, skipping integrity check.")
|
logging.info("Failed to download integrity file, skipping integrity check.")
|
||||||
|
|
||||||
wx.App.Get().Yield()
|
wx.App.Get().Yield()
|
||||||
self.header.SetLabel("Installing InstallAssistant.pkg")
|
self.header.SetLabel("Installing InstallAssistant.pkg")
|
||||||
@@ -1944,9 +1999,9 @@ class wx_python_gui:
|
|||||||
|
|
||||||
i = -7
|
i = -7
|
||||||
if available_installers:
|
if available_installers:
|
||||||
print("Installer(s) found:")
|
logging.info("Installer(s) found:")
|
||||||
for app in available_installers:
|
for app in available_installers:
|
||||||
print(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))
|
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))
|
||||||
i = i + 25
|
i = i + 25
|
||||||
self.install_selection.SetPosition(
|
self.install_selection.SetPosition(
|
||||||
@@ -1958,7 +2013,7 @@ 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)
|
||||||
else:
|
else:
|
||||||
print("No installers found")
|
logging.info("No installers found")
|
||||||
# Label: No Installers Found
|
# Label: No Installers Found
|
||||||
self.install_selection = wx.StaticText(self.frame, label="No Installers Found in Applications folder")
|
self.install_selection = wx.StaticText(self.frame, label="No Installers Found in Applications folder")
|
||||||
self.install_selection.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD))
|
self.install_selection.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD))
|
||||||
@@ -1985,7 +2040,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()
|
||||||
print(installer_path)
|
logging.info(installer_path)
|
||||||
|
|
||||||
# Header
|
# Header
|
||||||
self.header = wx.StaticText(self.frame, label="Format USB")
|
self.header = wx.StaticText(self.frame, label="Format USB")
|
||||||
@@ -2017,9 +2072,9 @@ class wx_python_gui:
|
|||||||
i = -15
|
i = -15
|
||||||
available_disks = installer.list_disk_to_format()
|
available_disks = installer.list_disk_to_format()
|
||||||
if available_disks:
|
if available_disks:
|
||||||
print("Disks found")
|
logging.info("Disks found")
|
||||||
for disk in available_disks:
|
for disk in available_disks:
|
||||||
print(f"{disk}: {available_disks[disk]['name']} - {available_disks[disk]['size']}")
|
logging.info(f"{disk}: {available_disks[disk]['name']} - {available_disks[disk]['size']}")
|
||||||
self.usb_selection = wx.Button(self.frame, label=f"{disk} - {available_disks[disk]['name']} - {utilities.human_fmt(available_disks[disk]['size'])}", size=(300, 30))
|
self.usb_selection = wx.Button(self.frame, label=f"{disk} - {available_disks[disk]['name']} - {utilities.human_fmt(available_disks[disk]['size'])}", size=(300, 30))
|
||||||
i = i + 25
|
i = i + 25
|
||||||
self.usb_selection.SetPosition(
|
self.usb_selection.SetPosition(
|
||||||
@@ -2031,7 +2086,7 @@ class wx_python_gui:
|
|||||||
self.usb_selection.Bind(wx.EVT_BUTTON, lambda event, temp=disk: self.format_usb_progress(available_disks[temp]['identifier'], installer_name, installer_path))
|
self.usb_selection.Bind(wx.EVT_BUTTON, lambda event, temp=disk: self.format_usb_progress(available_disks[temp]['identifier'], installer_name, installer_path))
|
||||||
self.usb_selection.Centre(wx.HORIZONTAL)
|
self.usb_selection.Centre(wx.HORIZONTAL)
|
||||||
else:
|
else:
|
||||||
print("No disks found")
|
logging.info("No disks found")
|
||||||
# Label: No Disks Found
|
# Label: No Disks Found
|
||||||
self.usb_selection = wx.StaticText(self.frame, label="No Disks Found")
|
self.usb_selection = wx.StaticText(self.frame, label="No Disks Found")
|
||||||
self.usb_selection.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD))
|
self.usb_selection.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD))
|
||||||
@@ -2137,9 +2192,9 @@ class wx_python_gui:
|
|||||||
self.frame.SetSize(-1, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40)
|
self.frame.SetSize(-1, self.return_to_main_menu.GetPosition().y + self.return_to_main_menu.GetSize().height + 40)
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
# Create installer.sh script
|
# Create installer.sh script
|
||||||
print("- Creating installer.sh script")
|
logging.info("- Creating installer.sh script")
|
||||||
print(f"- Disk: {disk}")
|
logging.info(f"- Disk: {disk}")
|
||||||
print(f"- Installer: {installer_path}")
|
logging.info(f"- Installer: {installer_path}")
|
||||||
|
|
||||||
self.prepare_script_thread = threading.Thread(target=self.prepare_script, args=(installer_path,disk))
|
self.prepare_script_thread = threading.Thread(target=self.prepare_script, args=(installer_path,disk))
|
||||||
self.prepare_script_thread.start()
|
self.prepare_script_thread.start()
|
||||||
@@ -2152,8 +2207,8 @@ class wx_python_gui:
|
|||||||
if self.prepare_result is True:
|
if self.prepare_result is True:
|
||||||
self.progress_label.SetLabel("Bytes Written: 0")
|
self.progress_label.SetLabel("Bytes Written: 0")
|
||||||
self.progress_label.Centre(wx.HORIZONTAL)
|
self.progress_label.Centre(wx.HORIZONTAL)
|
||||||
print("- Successfully generated creation script")
|
logging.info("- Successfully generated creation script")
|
||||||
print("- Starting creation script as admin")
|
logging.info("- Starting creation script as admin")
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
disk = disk[5:]
|
disk = disk[5:]
|
||||||
@@ -2206,7 +2261,7 @@ class wx_python_gui:
|
|||||||
self.constants.start_build_install = True
|
self.constants.start_build_install = True
|
||||||
self.build_install_menu()
|
self.build_install_menu()
|
||||||
else:
|
else:
|
||||||
print("- Failed to create installer script")
|
logging.info("- Failed to create installer script")
|
||||||
self.progress_label.SetLabel("Failed to copy files to tmp directory")
|
self.progress_label.SetLabel("Failed to copy files to tmp directory")
|
||||||
self.progress_label.Centre(wx.HORIZONTAL)
|
self.progress_label.Centre(wx.HORIZONTAL)
|
||||||
popup_message = wx.MessageDialog(self.frame, "Failed to prepare the base files for installer creation.\n\nPlease ensure you have 20GB~ free on-disk before starting to ensure the installer has enough room to work.", "Error", wx.OK)
|
popup_message = wx.MessageDialog(self.frame, "Failed to prepare the base files for installer creation.\n\nPlease ensure you have 20GB~ free on-disk before starting to ensure the installer has enough room to work.", "Error", wx.OK)
|
||||||
@@ -2221,16 +2276,16 @@ class wx_python_gui:
|
|||||||
args = [self.constants.oclp_helper_path, "/bin/sh", self.constants.installer_sh_path]
|
args = [self.constants.oclp_helper_path, "/bin/sh", self.constants.installer_sh_path]
|
||||||
output, error, returncode = run.Run()._stream_output(comm=args)
|
output, error, returncode = run.Run()._stream_output(comm=args)
|
||||||
if "Install media now available at" in output:
|
if "Install media now available at" in output:
|
||||||
print("- Successfully created macOS installer")
|
logging.info("- Successfully created macOS installer")
|
||||||
while self.download_thread.is_alive():
|
while self.download_thread.is_alive():
|
||||||
# wait for download_thread to finish
|
# wait for download_thread to finish
|
||||||
# though highly unlikely this thread is still alive (flashing an Installer will take a while)
|
# though highly unlikely this thread is still alive (flashing an Installer will take a while)
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print("- Installing Root Patcher to drive")
|
logging.info("- Installing Root Patcher to drive")
|
||||||
self.install_installer_pkg(self.target_disk)
|
self.install_installer_pkg(self.target_disk)
|
||||||
self.finished_cim_process = True
|
self.finished_cim_process = True
|
||||||
else:
|
else:
|
||||||
print("- Failed to create macOS installer")
|
logging.info("- Failed to create macOS installer")
|
||||||
popup = wx.MessageDialog(self.frame, f"Failed to create macOS installer\n\nOutput: {output}\n\nError: {error}", "Error", wx.OK | wx.ICON_ERROR)
|
popup = wx.MessageDialog(self.frame, f"Failed to create macOS installer\n\nOutput: {output}\n\nError: {error}", "Error", wx.OK | wx.ICON_ERROR)
|
||||||
popup.ShowModal()
|
popup.ShowModal()
|
||||||
utilities.enable_sleep_after_running()
|
utilities.enable_sleep_after_running()
|
||||||
@@ -2243,8 +2298,8 @@ class wx_python_gui:
|
|||||||
# - When running from source/unable to find on Github, use the nightly.link variant
|
# - When running from source/unable to find on Github, use the nightly.link variant
|
||||||
# - If nightly also fails, fall back to the manually uploaded variant
|
# - If nightly also fails, fall back to the manually uploaded variant
|
||||||
link = self.constants.installer_pkg_url
|
link = self.constants.installer_pkg_url
|
||||||
if utilities.validate_link(link) is False:
|
if network_handler.NetworkUtilities(link).validate_link() is False:
|
||||||
print("- Stock Install.pkg is missing on Github, falling back to Nightly")
|
logging.info("- Stock Install.pkg is missing on Github, falling back to Nightly")
|
||||||
link = self.constants.installer_pkg_url_nightly
|
link = self.constants.installer_pkg_url_nightly
|
||||||
|
|
||||||
if link.endswith(".zip"):
|
if link.endswith(".zip"):
|
||||||
@@ -2252,13 +2307,22 @@ class wx_python_gui:
|
|||||||
else:
|
else:
|
||||||
path = self.constants.installer_pkg_path
|
path = self.constants.installer_pkg_path
|
||||||
|
|
||||||
if utilities.download_file(link, path):
|
autopkg_download = network_handler.DownloadObject(link, path)
|
||||||
# Download thread will re-enable Idle Sleep after downloading
|
autopkg_download.download(spawn_thread=False)
|
||||||
utilities.disable_sleep_while_running()
|
|
||||||
if str(path).endswith(".zip"):
|
if autopkg_download.download_complete is False:
|
||||||
if Path(self.constants.installer_pkg_path).exists():
|
logging.warning("- Failed to download Install.pkg")
|
||||||
subprocess.run(["rm", self.constants.installer_pkg_path])
|
logging.warning(autopkg_download.error_msg)
|
||||||
subprocess.run(["ditto", "-V", "-x", "-k", "--sequesterRsrc", "--rsrc", self.constants.installer_pkg_zip_path, self.constants.payload_path])
|
return
|
||||||
|
|
||||||
|
# Download thread will re-enable Idle Sleep after downloading
|
||||||
|
utilities.disable_sleep_while_running()
|
||||||
|
if not str(path).endswith(".zip"):
|
||||||
|
return
|
||||||
|
if Path(self.constants.installer_pkg_path).exists():
|
||||||
|
subprocess.run(["rm", self.constants.installer_pkg_path])
|
||||||
|
subprocess.run(["ditto", "-V", "-x", "-k", "--sequesterRsrc", "--rsrc", self.constants.installer_pkg_zip_path, self.constants.payload_path])
|
||||||
|
|
||||||
|
|
||||||
def install_installer_pkg(self, disk):
|
def install_installer_pkg(self, disk):
|
||||||
disk = disk + "s2" # ESP sits at 1, and we know macOS will have created the main partition at 2
|
disk = disk + "s2" # ESP sits at 1, and we know macOS will have created the main partition at 2
|
||||||
@@ -2271,7 +2335,7 @@ class wx_python_gui:
|
|||||||
subprocess.run(["mkdir", "-p", f"{path}/Library/Packages/"])
|
subprocess.run(["mkdir", "-p", f"{path}/Library/Packages/"])
|
||||||
subprocess.run(["cp", "-r", self.constants.installer_pkg_path, f"{path}/Library/Packages/"])
|
subprocess.run(["cp", "-r", self.constants.installer_pkg_path, f"{path}/Library/Packages/"])
|
||||||
else:
|
else:
|
||||||
print("- Installer unsupported, requires Big Sur or newer")
|
logging.info("- Installer unsupported, requires Big Sur or newer")
|
||||||
|
|
||||||
|
|
||||||
def settings_menu(self, event=None):
|
def settings_menu(self, event=None):
|
||||||
@@ -2456,11 +2520,11 @@ class wx_python_gui:
|
|||||||
def model_choice_click(self, event=None):
|
def model_choice_click(self, event=None):
|
||||||
user_choice = self.dropdown_model.GetStringSelection()
|
user_choice = self.dropdown_model.GetStringSelection()
|
||||||
if user_choice == self.computer.real_model:
|
if user_choice == self.computer.real_model:
|
||||||
print(f"Using Real Model: {user_choice}")
|
logging.info(f"Using Real Model: {user_choice}")
|
||||||
self.constants.custom_model = None
|
self.constants.custom_model = None
|
||||||
defaults.generate_defaults(self.computer.real_model, True, self.constants)
|
defaults.generate_defaults(self.computer.real_model, True, self.constants)
|
||||||
else:
|
else:
|
||||||
print(f"Using Custom Model: {user_choice}")
|
logging.info(f"Using Custom Model: {user_choice}")
|
||||||
self.constants.custom_model = user_choice
|
self.constants.custom_model = user_choice
|
||||||
defaults.generate_defaults(self.constants.custom_model, False, self.constants)
|
defaults.generate_defaults(self.constants.custom_model, False, self.constants)
|
||||||
# Reload Settings
|
# Reload Settings
|
||||||
@@ -2483,64 +2547,64 @@ class wx_python_gui:
|
|||||||
if dlg.ShowModal() == wx.ID_NO:
|
if dlg.ShowModal() == wx.ID_NO:
|
||||||
self.checkbox_allow_native_models.SetValue(False)
|
self.checkbox_allow_native_models.SetValue(False)
|
||||||
return
|
return
|
||||||
print("Allow Native Models")
|
logging.info("Allow Native Models")
|
||||||
self.constants.allow_oc_everywhere = True
|
self.constants.allow_oc_everywhere = True
|
||||||
self.constants.serial_settings = "None"
|
self.constants.serial_settings = "None"
|
||||||
else:
|
else:
|
||||||
print("Disallow Native Models")
|
logging.info("Disallow Native Models")
|
||||||
self.constants.allow_oc_everywhere = False
|
self.constants.allow_oc_everywhere = False
|
||||||
self.constants.serial_settings = "Minimal"
|
self.constants.serial_settings = "Minimal"
|
||||||
|
|
||||||
def verbose_checkbox_click(self, event=None):
|
def verbose_checkbox_click(self, event=None):
|
||||||
if self.verbose_checkbox.GetValue():
|
if self.verbose_checkbox.GetValue():
|
||||||
print("Verbose mode enabled")
|
logging.info("Verbose mode enabled")
|
||||||
self.constants.verbose_debug = True
|
self.constants.verbose_debug = True
|
||||||
else:
|
else:
|
||||||
print("Verbose mode disabled")
|
logging.info("Verbose mode disabled")
|
||||||
self.constants.verbose_debug = False
|
self.constants.verbose_debug = False
|
||||||
|
|
||||||
def kext_checkbox_click(self, event=None):
|
def kext_checkbox_click(self, event=None):
|
||||||
if self.kext_checkbox.GetValue():
|
if self.kext_checkbox.GetValue():
|
||||||
print("Kext mode enabled")
|
logging.info("Kext mode enabled")
|
||||||
self.constants.kext_debug = True
|
self.constants.kext_debug = True
|
||||||
self.constants.kext_variant = "DEBUG"
|
self.constants.kext_variant = "DEBUG"
|
||||||
else:
|
else:
|
||||||
print("Kext mode disabled")
|
logging.info("Kext mode disabled")
|
||||||
self.constants.kext_debug = False
|
self.constants.kext_debug = False
|
||||||
self.constants.kext_variant = "RELEASE"
|
self.constants.kext_variant = "RELEASE"
|
||||||
|
|
||||||
def oc_checkbox_click(self, event=None):
|
def oc_checkbox_click(self, event=None):
|
||||||
if self.opencore_checkbox.GetValue():
|
if self.opencore_checkbox.GetValue():
|
||||||
print("OC mode enabled")
|
logging.info("OC mode enabled")
|
||||||
self.constants.opencore_debug = True
|
self.constants.opencore_debug = True
|
||||||
self.constants.opencore_build = "DEBUG"
|
self.constants.opencore_build = "DEBUG"
|
||||||
else:
|
else:
|
||||||
print("OC mode disabled")
|
logging.info("OC mode disabled")
|
||||||
self.constants.opencore_debug = False
|
self.constants.opencore_debug = False
|
||||||
self.constants.opencore_build = "RELEASE"
|
self.constants.opencore_build = "RELEASE"
|
||||||
|
|
||||||
def sip_checkbox_click(self, event=None):
|
def sip_checkbox_click(self, event=None):
|
||||||
if self.sip_checkbox.GetValue():
|
if self.sip_checkbox.GetValue():
|
||||||
print("SIP mode enabled")
|
logging.info("SIP mode enabled")
|
||||||
self.constants.sip_status = True
|
self.constants.sip_status = True
|
||||||
else:
|
else:
|
||||||
print("SIP mode disabled")
|
logging.info("SIP mode disabled")
|
||||||
self.constants.sip_status = False
|
self.constants.sip_status = False
|
||||||
|
|
||||||
def secureboot_checkbox_click(self, event=None):
|
def secureboot_checkbox_click(self, event=None):
|
||||||
if self.secureboot_checkbox.GetValue():
|
if self.secureboot_checkbox.GetValue():
|
||||||
print("SecureBoot mode enabled")
|
logging.info("SecureBoot mode enabled")
|
||||||
self.constants.secure_status = True
|
self.constants.secure_status = True
|
||||||
else:
|
else:
|
||||||
print("SecureBoot mode disabled")
|
logging.info("SecureBoot mode disabled")
|
||||||
self.constants.secure_status = False
|
self.constants.secure_status = False
|
||||||
|
|
||||||
def show_picker_checkbox_click(self, event=None):
|
def show_picker_checkbox_click(self, event=None):
|
||||||
if self.bootpicker_checkbox.GetValue():
|
if self.bootpicker_checkbox.GetValue():
|
||||||
print("Show Picker mode enabled")
|
logging.info("Show Picker mode enabled")
|
||||||
self.constants.showpicker = True
|
self.constants.showpicker = True
|
||||||
else:
|
else:
|
||||||
print("Show Picker mode disabled")
|
logging.info("Show Picker mode disabled")
|
||||||
self.constants.showpicker = False
|
self.constants.showpicker = False
|
||||||
|
|
||||||
def dev_settings_menu(self, event=None):
|
def dev_settings_menu(self, event=None):
|
||||||
@@ -2794,29 +2858,29 @@ class wx_python_gui:
|
|||||||
|
|
||||||
def delete_unused_kdks_click(self, event):
|
def delete_unused_kdks_click(self, event):
|
||||||
if self.delete_unused_kdks_checkbox.GetValue() is True:
|
if self.delete_unused_kdks_checkbox.GetValue() is True:
|
||||||
print("Nuke KDKs enabled")
|
logging.info("Nuke KDKs enabled")
|
||||||
self.constants.should_nuke_kdks = True
|
self.constants.should_nuke_kdks = True
|
||||||
else:
|
else:
|
||||||
print("Nuke KDKs disabled")
|
logging.info("Nuke KDKs disabled")
|
||||||
self.constants.should_nuke_kdks = False
|
self.constants.should_nuke_kdks = False
|
||||||
global_settings.global_settings().write_property("ShouldNukeKDKs", self.constants.should_nuke_kdks)
|
global_settings.global_settings().write_property("ShouldNukeKDKs", self.constants.should_nuke_kdks)
|
||||||
|
|
||||||
def disable_library_validation_click(self, event):
|
def disable_library_validation_click(self, event):
|
||||||
if self.disable_library_validation_checkbox.GetValue():
|
if self.disable_library_validation_checkbox.GetValue():
|
||||||
print("Disable Library Validation")
|
logging.info("Disable Library Validation")
|
||||||
self.disable_amfi_checkbox.Enable()
|
self.disable_amfi_checkbox.Enable()
|
||||||
self.constants.disable_cs_lv = True
|
self.constants.disable_cs_lv = True
|
||||||
else:
|
else:
|
||||||
print("Enable Library Validation")
|
logging.info("Enable Library Validation")
|
||||||
self.disable_amfi_checkbox.Disable()
|
self.disable_amfi_checkbox.Disable()
|
||||||
self.constants.disable_cs_lv = False
|
self.constants.disable_cs_lv = False
|
||||||
|
|
||||||
def disable_amfi_click(self, event):
|
def disable_amfi_click(self, event):
|
||||||
if self.disable_amfi_checkbox.GetValue():
|
if self.disable_amfi_checkbox.GetValue():
|
||||||
print("Disable AMFI")
|
logging.info("Disable AMFI")
|
||||||
self.constants.disable_amfi = True
|
self.constants.disable_amfi = True
|
||||||
else:
|
else:
|
||||||
print("Enable AMFI")
|
logging.info("Enable AMFI")
|
||||||
self.constants.disable_amfi = False
|
self.constants.disable_amfi = False
|
||||||
|
|
||||||
def set_ignore_app_updates_click(self, event):
|
def set_ignore_app_updates_click(self, event):
|
||||||
@@ -2828,171 +2892,171 @@ class wx_python_gui:
|
|||||||
|
|
||||||
def firewire_click(self, event=None):
|
def firewire_click(self, event=None):
|
||||||
if self.firewire_boot_checkbox.GetValue():
|
if self.firewire_boot_checkbox.GetValue():
|
||||||
print("Firewire Enabled")
|
logging.info("Firewire Enabled")
|
||||||
self.constants.firewire_boot = True
|
self.constants.firewire_boot = True
|
||||||
else:
|
else:
|
||||||
print("Firewire Disabled")
|
logging.info("Firewire Disabled")
|
||||||
self.constants.firewire_boot = False
|
self.constants.firewire_boot = False
|
||||||
|
|
||||||
def nvme_click(self, event=None):
|
def nvme_click(self, event=None):
|
||||||
if self.nvme_boot_checkbox.GetValue():
|
if self.nvme_boot_checkbox.GetValue():
|
||||||
print("NVMe Enabled")
|
logging.info("NVMe Enabled")
|
||||||
self.constants.nvme_boot = True
|
self.constants.nvme_boot = True
|
||||||
else:
|
else:
|
||||||
print("NVMe Disabled")
|
logging.info("NVMe Disabled")
|
||||||
self.constants.nvme_boot = False
|
self.constants.nvme_boot = False
|
||||||
|
|
||||||
def nvme_power_management_click(self, event=None):
|
def nvme_power_management_click(self, event=None):
|
||||||
if self.nvme_power_management_checkbox.GetValue():
|
if self.nvme_power_management_checkbox.GetValue():
|
||||||
print("NVMe Power Management Enabled")
|
logging.info("NVMe Power Management Enabled")
|
||||||
self.constants.allow_nvme_fixing = True
|
self.constants.allow_nvme_fixing = True
|
||||||
else:
|
else:
|
||||||
print("NVMe Power Management Disabled")
|
logging.info("NVMe Power Management Disabled")
|
||||||
self.constants.allow_nvme_fixing = False
|
self.constants.allow_nvme_fixing = False
|
||||||
|
|
||||||
def xhci_click(self, event=None):
|
def xhci_click(self, event=None):
|
||||||
if self.xhci_boot_checkbox.GetValue():
|
if self.xhci_boot_checkbox.GetValue():
|
||||||
print("XHCI Enabled")
|
logging.info("XHCI Enabled")
|
||||||
self.constants.xhci_boot = True
|
self.constants.xhci_boot = True
|
||||||
else:
|
else:
|
||||||
print("XHCI Disabled")
|
logging.info("XHCI Disabled")
|
||||||
self.constants.xhci_boot = False
|
self.constants.xhci_boot = False
|
||||||
|
|
||||||
def wake_on_wlan_click(self, event=None):
|
def wake_on_wlan_click(self, event=None):
|
||||||
if self.wake_on_wlan_checkbox.GetValue():
|
if self.wake_on_wlan_checkbox.GetValue():
|
||||||
print("Wake on WLAN Enabled")
|
logging.info("Wake on WLAN Enabled")
|
||||||
self.constants.enable_wake_on_wlan = True
|
self.constants.enable_wake_on_wlan = True
|
||||||
else:
|
else:
|
||||||
print("Wake on WLAN Disabled")
|
logging.info("Wake on WLAN Disabled")
|
||||||
self.constants.enable_wake_on_wlan = False
|
self.constants.enable_wake_on_wlan = False
|
||||||
|
|
||||||
def apfs_trim_click(self, event=None):
|
def apfs_trim_click(self, event=None):
|
||||||
if self.apfs_trim_checkbox.GetValue():
|
if self.apfs_trim_checkbox.GetValue():
|
||||||
print("APFS Trim Enabled")
|
logging.info("APFS Trim Enabled")
|
||||||
self.constants.apfs_trim_timeout = True
|
self.constants.apfs_trim_timeout = True
|
||||||
else:
|
else:
|
||||||
print("APFS Trim Disabled")
|
logging.info("APFS Trim Disabled")
|
||||||
self.constants.apfs_trim_timeout = False
|
self.constants.apfs_trim_timeout = False
|
||||||
|
|
||||||
def content_caching_click(self, event=None):
|
def content_caching_click(self, event=None):
|
||||||
if self.content_caching_checkbox.GetValue():
|
if self.content_caching_checkbox.GetValue():
|
||||||
print("Content Caching Enabled")
|
logging.info("Content Caching Enabled")
|
||||||
self.constants.set_content_caching = True
|
self.constants.set_content_caching = True
|
||||||
else:
|
else:
|
||||||
print("Content Caching Disabled")
|
logging.info("Content Caching Disabled")
|
||||||
self.constants.set_content_caching = False
|
self.constants.set_content_caching = False
|
||||||
|
|
||||||
def amd_gop_injection_checkbox_click(self, event=None):
|
def amd_gop_injection_checkbox_click(self, event=None):
|
||||||
if self.set_amd_gop_injection.GetValue():
|
if self.set_amd_gop_injection.GetValue():
|
||||||
print("AMD GOP Injection Enabled")
|
logging.info("AMD GOP Injection Enabled")
|
||||||
self.constants.amd_gop_injection = True
|
self.constants.amd_gop_injection = True
|
||||||
else:
|
else:
|
||||||
print("AMD GOP Injection Disabled")
|
logging.info("AMD GOP Injection Disabled")
|
||||||
self.constants.amd_gop_injection = False
|
self.constants.amd_gop_injection = False
|
||||||
|
|
||||||
def nvidia_kepler_gop_injection_checkbox_click(self, event=None):
|
def nvidia_kepler_gop_injection_checkbox_click(self, event=None):
|
||||||
if self.set_nvidia_kepler_gop_injection.GetValue():
|
if self.set_nvidia_kepler_gop_injection.GetValue():
|
||||||
print("Nvidia Kepler GOP Injection Enabled")
|
logging.info("Nvidia Kepler GOP Injection Enabled")
|
||||||
self.constants.nvidia_kepler_gop_injection = True
|
self.constants.nvidia_kepler_gop_injection = True
|
||||||
else:
|
else:
|
||||||
print("Nvidia Kepler GOP Injection Disabled")
|
logging.info("Nvidia Kepler GOP Injection Disabled")
|
||||||
self.constants.nvidia_kepler_gop_injection = False
|
self.constants.nvidia_kepler_gop_injection = False
|
||||||
|
|
||||||
def disable_tb_click(self, event=None):
|
def disable_tb_click(self, event=None):
|
||||||
if self.disable_thunderbolt_checkbox.GetValue():
|
if self.disable_thunderbolt_checkbox.GetValue():
|
||||||
print("Disable Thunderbolt Enabled")
|
logging.info("Disable Thunderbolt Enabled")
|
||||||
self.constants.disable_tb = True
|
self.constants.disable_tb = True
|
||||||
else:
|
else:
|
||||||
print("Disable Thunderbolt Disabled")
|
logging.info("Disable Thunderbolt Disabled")
|
||||||
self.constants.disable_tb = False
|
self.constants.disable_tb = False
|
||||||
|
|
||||||
def ts2_accel_click(self, event=None):
|
def ts2_accel_click(self, event=None):
|
||||||
if self.set_terascale_accel_checkbox.GetValue():
|
if self.set_terascale_accel_checkbox.GetValue():
|
||||||
print("TS2 Acceleration Enabled")
|
logging.info("TS2 Acceleration Enabled")
|
||||||
global_settings.global_settings().write_property("MacBookPro_TeraScale_2_Accel", True)
|
global_settings.global_settings().write_property("MacBookPro_TeraScale_2_Accel", True)
|
||||||
self.constants.allow_ts2_accel = True
|
self.constants.allow_ts2_accel = True
|
||||||
else:
|
else:
|
||||||
print("TS2 Acceleration Disabled")
|
logging.info("TS2 Acceleration Disabled")
|
||||||
global_settings.global_settings().write_property("MacBookPro_TeraScale_2_Accel", False)
|
global_settings.global_settings().write_property("MacBookPro_TeraScale_2_Accel", False)
|
||||||
self.constants.allow_ts2_accel = False
|
self.constants.allow_ts2_accel = False
|
||||||
|
|
||||||
def force_web_drivers_click(self, event=None):
|
def force_web_drivers_click(self, event=None):
|
||||||
if self.force_web_drivers_checkbox.GetValue():
|
if self.force_web_drivers_checkbox.GetValue():
|
||||||
print("Force Web Drivers Enabled")
|
logging.info("Force Web Drivers Enabled")
|
||||||
global_settings.global_settings().write_property("Force_Web_Drivers", True)
|
global_settings.global_settings().write_property("Force_Web_Drivers", True)
|
||||||
self.constants.force_nv_web = True
|
self.constants.force_nv_web = True
|
||||||
else:
|
else:
|
||||||
print("Force Web Drivers Disabled")
|
logging.info("Force Web Drivers Disabled")
|
||||||
global_settings.global_settings().write_property("Force_Web_Drivers", False)
|
global_settings.global_settings().write_property("Force_Web_Drivers", False)
|
||||||
self.constants.force_nv_web = False
|
self.constants.force_nv_web = False
|
||||||
|
|
||||||
def windows_gmux_click(self, event=None):
|
def windows_gmux_click(self, event=None):
|
||||||
if self.windows_gmux_checkbox.GetValue():
|
if self.windows_gmux_checkbox.GetValue():
|
||||||
print("Windows GMUX Enabled")
|
logging.info("Windows GMUX Enabled")
|
||||||
self.constants.dGPU_switch = True
|
self.constants.dGPU_switch = True
|
||||||
else:
|
else:
|
||||||
print("Windows GMUX Disabled")
|
logging.info("Windows GMUX Disabled")
|
||||||
self.constants.dGPU_switch = False
|
self.constants.dGPU_switch = False
|
||||||
|
|
||||||
def hibernation_click(self, event=None):
|
def hibernation_click(self, event=None):
|
||||||
if self.hibernation_checkbox.GetValue():
|
if self.hibernation_checkbox.GetValue():
|
||||||
print("Hibernation Enabled")
|
logging.info("Hibernation Enabled")
|
||||||
self.constants.disable_connectdrivers = True
|
self.constants.disable_connectdrivers = True
|
||||||
else:
|
else:
|
||||||
print("Hibernation Disabled")
|
logging.info("Hibernation Disabled")
|
||||||
self.constants.disable_connectdrivers = False
|
self.constants.disable_connectdrivers = False
|
||||||
|
|
||||||
def disable_battery_throttling_click(self, event=None):
|
def disable_battery_throttling_click(self, event=None):
|
||||||
if self.disable_battery_throttling_checkbox.GetValue():
|
if self.disable_battery_throttling_checkbox.GetValue():
|
||||||
print("Disable Battery Throttling Enabled")
|
logging.info("Disable Battery Throttling Enabled")
|
||||||
self.constants.disable_msr_power_ctl = True
|
self.constants.disable_msr_power_ctl = True
|
||||||
else:
|
else:
|
||||||
print("Disable Battery Throttling Disabled")
|
logging.info("Disable Battery Throttling Disabled")
|
||||||
self.constants.disable_msr_power_ctl = False
|
self.constants.disable_msr_power_ctl = False
|
||||||
|
|
||||||
def disable_xcpm_click(self, event=None):
|
def disable_xcpm_click(self, event=None):
|
||||||
if self.disable_xcpm_checkbox.GetValue():
|
if self.disable_xcpm_checkbox.GetValue():
|
||||||
print("Disable XCPM Enabled")
|
logging.info("Disable XCPM Enabled")
|
||||||
self.constants.disable_xcpm = True
|
self.constants.disable_xcpm = True
|
||||||
else:
|
else:
|
||||||
print("Disable XCPM Disabled")
|
logging.info("Disable XCPM Disabled")
|
||||||
self.constants.disable_xcpm = False
|
self.constants.disable_xcpm = False
|
||||||
|
|
||||||
def software_demux_click(self, event=None):
|
def software_demux_click(self, event=None):
|
||||||
if self.software_demux_checkbox.GetValue():
|
if self.software_demux_checkbox.GetValue():
|
||||||
print("Software Demux Enabled")
|
logging.info("Software Demux Enabled")
|
||||||
self.constants.software_demux = True
|
self.constants.software_demux = True
|
||||||
else:
|
else:
|
||||||
print("Software Demux Disabled")
|
logging.info("Software Demux Disabled")
|
||||||
self.constants.software_demux = False
|
self.constants.software_demux = False
|
||||||
|
|
||||||
def disable_cpu_friend_click(self, event=None):
|
def disable_cpu_friend_click(self, event=None):
|
||||||
if self.disable_cpu_friend_checkbox.GetValue():
|
if self.disable_cpu_friend_checkbox.GetValue():
|
||||||
print("Disable CPUFriend Enabled")
|
logging.info("Disable CPUFriend Enabled")
|
||||||
self.constants.disallow_cpufriend = True
|
self.constants.disallow_cpufriend = True
|
||||||
else:
|
else:
|
||||||
print("Disable CPUFriend Disabled")
|
logging.info("Disable CPUFriend Disabled")
|
||||||
self.constants.disallow_cpufriend = False
|
self.constants.disallow_cpufriend = False
|
||||||
|
|
||||||
def apple_alc_click(self, event=None):
|
def apple_alc_click(self, event=None):
|
||||||
if self.apple_alc_checkbox.GetValue():
|
if self.apple_alc_checkbox.GetValue():
|
||||||
print("AppleALC Usage Enabled")
|
logging.info("AppleALC Usage Enabled")
|
||||||
self.constants.set_alc_usage = True
|
self.constants.set_alc_usage = True
|
||||||
else:
|
else:
|
||||||
print("AppleALC Usage Disabled")
|
logging.info("AppleALC Usage Disabled")
|
||||||
self.constants.set_alc_usage = False
|
self.constants.set_alc_usage = False
|
||||||
|
|
||||||
def set_enhanced_3rd_party_ssd_click(self, event=None):
|
def set_enhanced_3rd_party_ssd_click(self, event=None):
|
||||||
if self.set_enhanced_3rd_party_ssd_checkbox.GetValue():
|
if self.set_enhanced_3rd_party_ssd_checkbox.GetValue():
|
||||||
print("Enhanced 3rd Party SSDs Enabled")
|
logging.info("Enhanced 3rd Party SSDs Enabled")
|
||||||
self.constants.allow_3rd_party_drives = True
|
self.constants.allow_3rd_party_drives = True
|
||||||
else:
|
else:
|
||||||
print("Enhanced 3rd Party SSDs Disabled")
|
logging.info("Enhanced 3rd Party SSDs Disabled")
|
||||||
self.constants.allow_3rd_party_drives = False
|
self.constants.allow_3rd_party_drives = False
|
||||||
|
|
||||||
def gpu_selection_click(self, event=None):
|
def gpu_selection_click(self, event=None):
|
||||||
gpu_choice = self.gpu_dropdown.GetStringSelection()
|
gpu_choice = self.gpu_dropdown.GetStringSelection()
|
||||||
print(f"GPU Selection: {gpu_choice}")
|
logging.info(f"GPU Selection: {gpu_choice}")
|
||||||
if "AMD" in gpu_choice:
|
if "AMD" in gpu_choice:
|
||||||
self.constants.imac_vendor = "AMD"
|
self.constants.imac_vendor = "AMD"
|
||||||
self.constants.metal_build = True
|
self.constants.metal_build = True
|
||||||
@@ -3015,8 +3079,8 @@ class wx_python_gui:
|
|||||||
self.constants.imac_vendor = "None"
|
self.constants.imac_vendor = "None"
|
||||||
self.constants.metal_build = False
|
self.constants.metal_build = False
|
||||||
|
|
||||||
print(f"GPU Vendor: {self.constants.imac_vendor}")
|
logging.info(f"GPU Vendor: {self.constants.imac_vendor}")
|
||||||
print(f"GPU Model: {self.constants.imac_model}")
|
logging.info(f"GPU Model: {self.constants.imac_model}")
|
||||||
|
|
||||||
def fu_selection_click(self, event=None):
|
def fu_selection_click(self, event=None):
|
||||||
fu_choice = self.feature_unlock_dropdown.GetStringSelection()
|
fu_choice = self.feature_unlock_dropdown.GetStringSelection()
|
||||||
@@ -3032,10 +3096,10 @@ class wx_python_gui:
|
|||||||
|
|
||||||
def set_writeflash_click(self, event=None):
|
def set_writeflash_click(self, event=None):
|
||||||
if self.set_writeflash_checkbox.GetValue():
|
if self.set_writeflash_checkbox.GetValue():
|
||||||
print("Write Flash Enabled")
|
logging.info("Write Flash Enabled")
|
||||||
self.constants.nvram_write = True
|
self.constants.nvram_write = True
|
||||||
else:
|
else:
|
||||||
print("Write Flash Disabled")
|
logging.info("Write Flash Disabled")
|
||||||
self.constants.nvram_write = False
|
self.constants.nvram_write = False
|
||||||
|
|
||||||
def smbios_settings_menu(self, event=None):
|
def smbios_settings_menu(self, event=None):
|
||||||
@@ -3184,10 +3248,10 @@ class wx_python_gui:
|
|||||||
|
|
||||||
def native_spoof_click(self, event):
|
def native_spoof_click(self, event):
|
||||||
if self.native_spoof_checkbox.GetValue():
|
if self.native_spoof_checkbox.GetValue():
|
||||||
print("Allow Native Spoofs Enabled")
|
logging.info("Allow Native Spoofs Enabled")
|
||||||
self.constants.allow_native_spoofs = True
|
self.constants.allow_native_spoofs = True
|
||||||
else:
|
else:
|
||||||
print("Allow Native Spoofs Disabled")
|
logging.info("Allow Native Spoofs Disabled")
|
||||||
self.constants.allow_native_spoofs = False
|
self.constants.allow_native_spoofs = False
|
||||||
|
|
||||||
def smbios_spoof_level_click(self, event=None):
|
def smbios_spoof_level_click(self, event=None):
|
||||||
@@ -3198,7 +3262,7 @@ class wx_python_gui:
|
|||||||
if dlg.ShowModal() == wx.ID_NO:
|
if dlg.ShowModal() == wx.ID_NO:
|
||||||
self.smbios_dropdown.SetStringSelection(self.constants.serial_settings)
|
self.smbios_dropdown.SetStringSelection(self.constants.serial_settings)
|
||||||
return
|
return
|
||||||
print(f"SMBIOS Spoof Level: {selection}")
|
logging.info(f"SMBIOS Spoof Level: {selection}")
|
||||||
self.constants.serial_settings = selection
|
self.constants.serial_settings = selection
|
||||||
if selection == "None":
|
if selection == "None":
|
||||||
self.smbios_model_dropdown.Disable()
|
self.smbios_model_dropdown.Disable()
|
||||||
@@ -3207,7 +3271,7 @@ class wx_python_gui:
|
|||||||
|
|
||||||
def smbios_model_click(self, event=None):
|
def smbios_model_click(self, event=None):
|
||||||
selection = self.smbios_model_dropdown.GetStringSelection()
|
selection = self.smbios_model_dropdown.GetStringSelection()
|
||||||
print(f"SMBIOS Spoof Model: {selection}")
|
logging.info(f"SMBIOS Spoof Model: {selection}")
|
||||||
self.constants.override_smbios = selection
|
self.constants.override_smbios = selection
|
||||||
|
|
||||||
def additional_info_menu(self, event=None):
|
def additional_info_menu(self, event=None):
|
||||||
@@ -3680,18 +3744,18 @@ OpenCore Legacy Patcher by default knows the most ideal
|
|||||||
subprocess.run(["defaults", "write", "-g", "Moraea_BlurBeta", "-bool", "true"])
|
subprocess.run(["defaults", "write", "-g", "Moraea_BlurBeta", "-bool", "true"])
|
||||||
else:
|
else:
|
||||||
subprocess.run(["defaults", "write", "-g", "Moraea_BlurBeta", "-bool", "false"])
|
subprocess.run(["defaults", "write", "-g", "Moraea_BlurBeta", "-bool", "false"])
|
||||||
print("Beta Blur Enabled:", event.IsChecked())
|
logging.info("Beta Blur Enabled:", event.IsChecked())
|
||||||
|
|
||||||
def enable_dark_menubar_click(self, event=None):
|
def enable_dark_menubar_click(self, event=None):
|
||||||
if event.IsChecked():
|
if event.IsChecked():
|
||||||
subprocess.run(["defaults", "write", "-g", "Moraea_DarkMenuBar", "-bool", "true"])
|
subprocess.run(["defaults", "write", "-g", "Moraea_DarkMenuBar", "-bool", "true"])
|
||||||
else:
|
else:
|
||||||
subprocess.run(["defaults", "write", "-g", "Moraea_DarkMenuBar", "-bool", "false"])
|
subprocess.run(["defaults", "write", "-g", "Moraea_DarkMenuBar", "-bool", "false"])
|
||||||
print("Dark Menu Bar Enabled:", event.IsChecked())
|
logging.info("Dark Menu Bar Enabled:", event.IsChecked())
|
||||||
|
|
||||||
def enable_beta_rim_click(self, event=None):
|
def enable_beta_rim_click(self, event=None):
|
||||||
if event.IsChecked():
|
if event.IsChecked():
|
||||||
subprocess.run(["defaults", "write", "-g", "Moraea_RimBetaDisabled", "-bool", "true"])
|
subprocess.run(["defaults", "write", "-g", "Moraea_RimBetaDisabled", "-bool", "true"])
|
||||||
else:
|
else:
|
||||||
subprocess.run(["defaults", "write", "-g", "Moraea_RimBetaDisabled", "-bool", "false"])
|
subprocess.run(["defaults", "write", "-g", "Moraea_RimBetaDisabled", "-bool", "false"])
|
||||||
print("Beta Rim Enabled:", event.IsChecked())
|
logging.info("Beta Rim Enabled:", event.IsChecked())
|
||||||
@@ -23,12 +23,15 @@ class RedirectLabel(object):
|
|||||||
self.out=aWxTextCtrl
|
self.out=aWxTextCtrl
|
||||||
|
|
||||||
def write(self,string):
|
def write(self,string):
|
||||||
if string.endswith("MB/s"):
|
if "MB/s" in string:
|
||||||
self.out.SetLabel(string)
|
self.out.SetLabel(string)
|
||||||
self.out.Centre(wx.HORIZONTAL)
|
self.out.Centre(wx.HORIZONTAL)
|
||||||
wx.GetApp().Yield()
|
wx.GetApp().Yield()
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
def fileno(self):
|
||||||
|
return 1
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
+31
-30
@@ -6,6 +6,7 @@ import plistlib
|
|||||||
import subprocess
|
import subprocess
|
||||||
import shutil
|
import shutil
|
||||||
import os
|
import os
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from resources import utilities, constants, tui_helpers
|
from resources import utilities, constants, tui_helpers
|
||||||
from data import os_data
|
from data import os_data
|
||||||
@@ -79,7 +80,7 @@ class tui_disk_installation:
|
|||||||
utilities.header(["Installing OpenCore to Drive"])
|
utilities.header(["Installing OpenCore to Drive"])
|
||||||
|
|
||||||
if not self.constants.opencore_release_folder.exists():
|
if not self.constants.opencore_release_folder.exists():
|
||||||
tui_helpers.TUIOnlyPrint(
|
tui_helpers.TUIOnlyLogging.info(
|
||||||
["Installing OpenCore to Drive"],
|
["Installing OpenCore to Drive"],
|
||||||
"Press [Enter] to go back.\n",
|
"Press [Enter] to go back.\n",
|
||||||
[
|
[
|
||||||
@@ -89,7 +90,7 @@ Please build OpenCore first!"""
|
|||||||
).start()
|
).start()
|
||||||
return
|
return
|
||||||
|
|
||||||
print("\nDisk picker is loading...")
|
logging.info("\nDisk picker is loading...")
|
||||||
|
|
||||||
all_disks = self.list_disks()
|
all_disks = self.list_disks()
|
||||||
menu = tui_helpers.TUIMenu(
|
menu = tui_helpers.TUIMenu(
|
||||||
@@ -169,17 +170,17 @@ Please build OpenCore first!"""
|
|||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
tui_helpers.TUIOnlyPrint(
|
tui_helpers.TUIOnlyLogging.info(
|
||||||
["Copying OpenCore"], "Press [Enter] to go back.\n", ["An error occurred!"] + result.stderr.decode().split("\n") + [""]
|
["Copying OpenCore"], "Press [Enter] to go back.\n", ["An error occurred!"] + result.stderr.decode().split("\n") + [""]
|
||||||
).start()
|
).start()
|
||||||
else:
|
else:
|
||||||
print("An error occurred!")
|
logging.info("An error occurred!")
|
||||||
print(result.stderr.decode())
|
logging.info(result.stderr.decode())
|
||||||
|
|
||||||
# Check if we're in Safe Mode, and if so, tell user FAT32 is unsupported
|
# Check if we're in Safe Mode, and if so, tell user FAT32 is unsupported
|
||||||
if utilities.check_boot_mode() == "safe_boot":
|
if utilities.check_boot_mode() == "safe_boot":
|
||||||
print("\nSafe Mode detected. FAT32 is unsupported by macOS in this mode.")
|
logging.info("\nSafe Mode detected. FAT32 is unsupported by macOS in this mode.")
|
||||||
print("Please disable Safe Mode and try again.")
|
logging.info("Please disable Safe Mode and try again.")
|
||||||
return
|
return
|
||||||
partition_info = plistlib.loads(subprocess.run(f"diskutil info -plist {full_disk_identifier}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
partition_info = plistlib.loads(subprocess.run(f"diskutil info -plist {full_disk_identifier}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||||
parent_disk = partition_info["ParentWholeDisk"]
|
parent_disk = partition_info["ParentWholeDisk"]
|
||||||
@@ -196,65 +197,65 @@ Please build OpenCore first!"""
|
|||||||
|
|
||||||
if mount_path.exists():
|
if mount_path.exists():
|
||||||
if (mount_path / Path("EFI/Microsoft")).exists() and self.constants.gui_mode is False:
|
if (mount_path / Path("EFI/Microsoft")).exists() and self.constants.gui_mode is False:
|
||||||
print("- Found Windows Boot Loader")
|
logging.info("- Found Windows Boot Loader")
|
||||||
print("\nWould you like to continue installing OpenCore?")
|
logging.info("\nWould you like to continue installing OpenCore?")
|
||||||
print("Installing OpenCore onto this drive may make Windows unbootable until OpenCore")
|
logging.info("Installing OpenCore onto this drive may make Windows unbootable until OpenCore")
|
||||||
print("is removed from the partition")
|
logging.info("is removed from the partition")
|
||||||
print("We highly recommend users partition 200MB off their drive with Disk Utility")
|
logging.info("We highly recommend users partition 200MB off their drive with Disk Utility")
|
||||||
print(" Name:\t\t OPENCORE")
|
logging.info(" Name:\t\t OPENCORE")
|
||||||
print(" Format:\t\t FAT32")
|
logging.info(" Format:\t\t FAT32")
|
||||||
print(" Size:\t\t 200MB")
|
logging.info(" Size:\t\t 200MB")
|
||||||
choice = input("\nWould you like to still install OpenCore to this drive?(y/n): ")
|
choice = input("\nWould you like to still install OpenCore to this drive?(y/n): ")
|
||||||
if not choice in ["y", "Y", "Yes", "yes"]:
|
if not choice in ["y", "Y", "Yes", "yes"]:
|
||||||
subprocess.run(["diskutil", "umount", mount_path], stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
subprocess.run(["diskutil", "umount", mount_path], stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
||||||
return False
|
return False
|
||||||
if (mount_path / Path("EFI/OC")).exists():
|
if (mount_path / Path("EFI/OC")).exists():
|
||||||
print("- Removing preexisting EFI/OC folder")
|
logging.info("- Removing preexisting EFI/OC folder")
|
||||||
shutil.rmtree(mount_path / Path("EFI/OC"), onerror=rmtree_handler)
|
shutil.rmtree(mount_path / Path("EFI/OC"), onerror=rmtree_handler)
|
||||||
if (mount_path / Path("System")).exists():
|
if (mount_path / Path("System")).exists():
|
||||||
print("- Removing preexisting System folder")
|
logging.info("- Removing preexisting System folder")
|
||||||
shutil.rmtree(mount_path / Path("System"), onerror=rmtree_handler)
|
shutil.rmtree(mount_path / Path("System"), onerror=rmtree_handler)
|
||||||
if (mount_path / Path("boot.efi")).exists():
|
if (mount_path / Path("boot.efi")).exists():
|
||||||
print("- Removing preexisting boot.efi")
|
logging.info("- Removing preexisting boot.efi")
|
||||||
os.remove(mount_path / Path("boot.efi"))
|
os.remove(mount_path / Path("boot.efi"))
|
||||||
print("- Copying OpenCore onto EFI partition")
|
logging.info("- Copying OpenCore onto EFI partition")
|
||||||
shutil.copytree(self.constants.opencore_release_folder / Path("EFI/OC"), mount_path / Path("EFI/OC"))
|
shutil.copytree(self.constants.opencore_release_folder / Path("EFI/OC"), mount_path / Path("EFI/OC"))
|
||||||
shutil.copytree(self.constants.opencore_release_folder / Path("System"), mount_path / Path("System"))
|
shutil.copytree(self.constants.opencore_release_folder / Path("System"), mount_path / Path("System"))
|
||||||
if Path(self.constants.opencore_release_folder / Path("boot.efi")).exists():
|
if Path(self.constants.opencore_release_folder / Path("boot.efi")).exists():
|
||||||
shutil.copy(self.constants.opencore_release_folder / Path("boot.efi"), mount_path / Path("boot.efi"))
|
shutil.copy(self.constants.opencore_release_folder / Path("boot.efi"), mount_path / Path("boot.efi"))
|
||||||
if self.constants.boot_efi is True:
|
if self.constants.boot_efi is True:
|
||||||
print("- Converting Bootstrap to BOOTx64.efi")
|
logging.info("- Converting Bootstrap to BOOTx64.efi")
|
||||||
if (mount_path / Path("EFI/BOOT")).exists():
|
if (mount_path / Path("EFI/BOOT")).exists():
|
||||||
shutil.rmtree(mount_path / Path("EFI/BOOT"), onerror=rmtree_handler)
|
shutil.rmtree(mount_path / Path("EFI/BOOT"), onerror=rmtree_handler)
|
||||||
Path(mount_path / Path("EFI/BOOT")).mkdir()
|
Path(mount_path / Path("EFI/BOOT")).mkdir()
|
||||||
shutil.move(mount_path / Path("System/Library/CoreServices/boot.efi"), mount_path / Path("EFI/BOOT/BOOTx64.efi"))
|
shutil.move(mount_path / Path("System/Library/CoreServices/boot.efi"), mount_path / Path("EFI/BOOT/BOOTx64.efi"))
|
||||||
shutil.rmtree(mount_path / Path("System"), onerror=rmtree_handler)
|
shutil.rmtree(mount_path / Path("System"), onerror=rmtree_handler)
|
||||||
if determine_sd_card(sd_type) is True:
|
if determine_sd_card(sd_type) is True:
|
||||||
print("- Adding SD Card icon")
|
logging.info("- Adding SD Card icon")
|
||||||
shutil.copy(self.constants.icon_path_sd, mount_path)
|
shutil.copy(self.constants.icon_path_sd, mount_path)
|
||||||
elif ssd_type is True:
|
elif ssd_type is True:
|
||||||
print("- Adding SSD icon")
|
logging.info("- Adding SSD icon")
|
||||||
shutil.copy(self.constants.icon_path_ssd, mount_path)
|
shutil.copy(self.constants.icon_path_ssd, mount_path)
|
||||||
elif disk_type == "USB":
|
elif disk_type == "USB":
|
||||||
print("- Adding External USB Drive icon")
|
logging.info("- Adding External USB Drive icon")
|
||||||
shutil.copy(self.constants.icon_path_external, mount_path)
|
shutil.copy(self.constants.icon_path_external, mount_path)
|
||||||
else:
|
else:
|
||||||
print("- Adding Internal Drive icon")
|
logging.info("- Adding Internal Drive icon")
|
||||||
shutil.copy(self.constants.icon_path_internal, mount_path)
|
shutil.copy(self.constants.icon_path_internal, mount_path)
|
||||||
|
|
||||||
print("- Cleaning install location")
|
logging.info("- Cleaning install location")
|
||||||
if not self.constants.recovery_status:
|
if not self.constants.recovery_status:
|
||||||
print("- Unmounting EFI partition")
|
logging.info("- Unmounting EFI partition")
|
||||||
subprocess.run(["diskutil", "umount", mount_path], stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
subprocess.run(["diskutil", "umount", mount_path], stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
||||||
print("- OpenCore transfer complete")
|
logging.info("- OpenCore transfer complete")
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
print("\nPress [Enter] to continue.\n")
|
logging.info("\nPress [Enter] to continue.\n")
|
||||||
input()
|
input()
|
||||||
else:
|
else:
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
tui_helpers.TUIOnlyPrint(["Copying OpenCore"], "Press [Enter] to go back.\n", ["EFI failed to mount!"]).start()
|
tui_helpers.TUIOnlyLogging.info(["Copying OpenCore"], "Press [Enter] to go back.\n", ["EFI failed to mount!"]).start()
|
||||||
else:
|
else:
|
||||||
print("EFI failed to mount!")
|
logging.info("EFI failed to mount!")
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
+29
-26
@@ -2,9 +2,9 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import plistlib
|
import plistlib
|
||||||
import subprocess
|
import subprocess
|
||||||
import requests
|
|
||||||
import tempfile
|
import tempfile
|
||||||
from resources import utilities, tui_helpers
|
import logging
|
||||||
|
from resources import utilities, tui_helpers, network_handler
|
||||||
|
|
||||||
def list_local_macOS_installers():
|
def list_local_macOS_installers():
|
||||||
# Finds all applicable macOS installers
|
# Finds all applicable macOS installers
|
||||||
@@ -123,21 +123,24 @@ def create_installer(installer_path, volume_name):
|
|||||||
if (createinstallmedia_path).exists():
|
if (createinstallmedia_path).exists():
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Starting createinstallmedia"])
|
utilities.header(["Starting createinstallmedia"])
|
||||||
print("This will take some time, recommend making some coffee while you wait\n")
|
logging.info("This will take some time, recommend making some coffee while you wait\n")
|
||||||
utilities.elevated([createinstallmedia_path, "--volume", f"/Volumes/{volume_name}", "--nointeraction"])
|
utilities.elevated([createinstallmedia_path, "--volume", f"/Volumes/{volume_name}", "--nointeraction"])
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print("- Failed to find createinstallmedia")
|
logging.info("- Failed to find createinstallmedia")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def download_install_assistant(download_path, ia_link):
|
def download_install_assistant(download_path, ia_link):
|
||||||
# Downloads InstallAssistant.pkg
|
# Downloads InstallAssistant.pkg
|
||||||
if utilities.download_file(ia_link, (Path(download_path) / Path("InstallAssistant.pkg"))):
|
ia_download = network_handler.DownloadObject(ia_link, (Path(download_path) / Path("InstallAssistant.pkg")))
|
||||||
|
ia_download.download(display_progress=True, spawn_thread=False)
|
||||||
|
|
||||||
|
if ia_download.download_complete is True:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def install_macOS_installer(download_path):
|
def install_macOS_installer(download_path):
|
||||||
print("- Extracting macOS installer from InstallAssistant.pkg\n This may take some time")
|
logging.info("- Extracting macOS installer from InstallAssistant.pkg\n This may take some time")
|
||||||
args = [
|
args = [
|
||||||
"osascript",
|
"osascript",
|
||||||
"-e",
|
"-e",
|
||||||
@@ -149,11 +152,11 @@ def install_macOS_installer(download_path):
|
|||||||
|
|
||||||
result = subprocess.run(args,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
result = subprocess.run(args,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
print("- InstallAssistant installed")
|
logging.info("- InstallAssistant installed")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print("- Failed to install InstallAssistant")
|
logging.info("- Failed to install InstallAssistant")
|
||||||
print(f" Error Code: {result.returncode}")
|
logging.info(f" Error Code: {result.returncode}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def list_downloadable_macOS_installers(download_path, catalog):
|
def list_downloadable_macOS_installers(download_path, catalog):
|
||||||
@@ -165,9 +168,9 @@ def list_downloadable_macOS_installers(download_path, catalog):
|
|||||||
else:
|
else:
|
||||||
link = "https://swscan.apple.com/content/catalogs/others/index-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"
|
link = "https://swscan.apple.com/content/catalogs/others/index-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"
|
||||||
|
|
||||||
if utilities.verify_network_connection(link) is True:
|
if network_handler.NetworkUtilities(link).verify_network_connection() is True:
|
||||||
try:
|
try:
|
||||||
catalog_plist = plistlib.loads(utilities.SESSION.get(link).content)
|
catalog_plist = plistlib.loads(network_handler.SESSION.get(link).content)
|
||||||
except plistlib.InvalidFileException:
|
except plistlib.InvalidFileException:
|
||||||
return available_apps
|
return available_apps
|
||||||
|
|
||||||
@@ -181,7 +184,7 @@ def list_downloadable_macOS_installers(download_path, catalog):
|
|||||||
for bm_package in catalog_plist["Products"][item]["Packages"]:
|
for bm_package in catalog_plist["Products"][item]["Packages"]:
|
||||||
if "Info.plist" in bm_package["URL"] and "InstallInfo.plist" not in bm_package["URL"]:
|
if "Info.plist" in bm_package["URL"] and "InstallInfo.plist" not in bm_package["URL"]:
|
||||||
try:
|
try:
|
||||||
build_plist = plistlib.loads(utilities.SESSION.get(bm_package["URL"]).content)
|
build_plist = plistlib.loads(network_handler.SESSION.get(bm_package["URL"]).content)
|
||||||
except plistlib.InvalidFileException:
|
except plistlib.InvalidFileException:
|
||||||
continue
|
continue
|
||||||
# Ensure Apple Silicon specific Installers are not listed
|
# Ensure Apple Silicon specific Installers are not listed
|
||||||
@@ -307,18 +310,18 @@ def format_drive(disk_id):
|
|||||||
header = f"# Formatting disk{disk_id} for macOS installer #"
|
header = f"# Formatting disk{disk_id} for macOS installer #"
|
||||||
box_length = len(header)
|
box_length = len(header)
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
print("#" * box_length)
|
logging.info("#" * box_length)
|
||||||
print(header)
|
logging.info(header)
|
||||||
print("#" * box_length)
|
logging.info("#" * box_length)
|
||||||
print("")
|
logging.info("")
|
||||||
#print(f"- Formatting disk{disk_id} for macOS installer")
|
#logging.info(f"- Formatting disk{disk_id} for macOS installer")
|
||||||
format_process = utilities.elevated(["diskutil", "eraseDisk", "HFS+", "OCLP-Installer", f"disk{disk_id}"])
|
format_process = utilities.elevated(["diskutil", "eraseDisk", "HFS+", "OCLP-Installer", f"disk{disk_id}"])
|
||||||
if format_process.returncode == 0:
|
if format_process.returncode == 0:
|
||||||
print("- Disk formatted")
|
logging.info("- Disk formatted")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print("- Failed to format disk")
|
logging.info("- Failed to format disk")
|
||||||
print(f" Error Code: {format_process.returncode}")
|
logging.info(f" Error Code: {format_process.returncode}")
|
||||||
input("\nPress Enter to exit")
|
input("\nPress Enter to exit")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -326,7 +329,7 @@ def select_disk_to_format():
|
|||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Installing OpenCore to Drive"])
|
utilities.header(["Installing OpenCore to Drive"])
|
||||||
|
|
||||||
print("\nDisk picker is loading...")
|
logging.info("\nDisk picker is loading...")
|
||||||
|
|
||||||
all_disks = {}
|
all_disks = {}
|
||||||
# TODO: AllDisksAndPartitions is not supported in Snow Leopard and older
|
# TODO: AllDisksAndPartitions is not supported in Snow Leopard and older
|
||||||
@@ -396,7 +399,7 @@ def list_disk_to_format():
|
|||||||
# Ensure user doesn't format their boot drive
|
# Ensure user doesn't format their boot drive
|
||||||
if not any(all_disks[disk]['removable'] is False for partition in all_disks[disk]):
|
if not any(all_disks[disk]['removable'] is False for partition in all_disks[disk]):
|
||||||
continue
|
continue
|
||||||
print(f"disk {disk}: {all_disks[disk]['name']} ({utilities.human_fmt(all_disks[disk]['size'])})")
|
logging.info(f"disk {disk}: {all_disks[disk]['name']} ({utilities.human_fmt(all_disks[disk]['size'])})")
|
||||||
list_disks.update({
|
list_disks.update({
|
||||||
disk: {
|
disk: {
|
||||||
"identifier": all_disks[disk]["identifier"],
|
"identifier": all_disks[disk]["identifier"],
|
||||||
@@ -431,7 +434,7 @@ def generate_installer_creation_script(tmp_location, installer_path, disk):
|
|||||||
global tmp_dir
|
global tmp_dir
|
||||||
ia_tmp = tmp_dir.name
|
ia_tmp = tmp_dir.name
|
||||||
|
|
||||||
print(f"Creating temporary directory at {ia_tmp}")
|
logging.info(f"Creating temporary directory at {ia_tmp}")
|
||||||
# Delete all files in tmp_dir
|
# Delete all files in tmp_dir
|
||||||
for file in Path(ia_tmp).glob("*"):
|
for file in Path(ia_tmp).glob("*"):
|
||||||
subprocess.run(["rm", "-rf", str(file)])
|
subprocess.run(["rm", "-rf", str(file)])
|
||||||
@@ -445,15 +448,15 @@ def generate_installer_creation_script(tmp_location, installer_path, disk):
|
|||||||
space_available = utilities.get_free_space()
|
space_available = utilities.get_free_space()
|
||||||
space_needed = Path(ia_tmp).stat().st_size
|
space_needed = Path(ia_tmp).stat().st_size
|
||||||
if space_available < space_needed:
|
if space_available < space_needed:
|
||||||
print("Not enough free space to create installer.sh")
|
logging.info("Not enough free space to create installer.sh")
|
||||||
print(f"{utilities.human_fmt(space_available)} available, {utilities.human_fmt(space_needed)} required")
|
logging.info(f"{utilities.human_fmt(space_available)} available, {utilities.human_fmt(space_needed)} required")
|
||||||
return False
|
return False
|
||||||
subprocess.run(args)
|
subprocess.run(args)
|
||||||
|
|
||||||
# Adjust installer_path to point to the copied installer
|
# Adjust installer_path to point to the copied installer
|
||||||
installer_path = Path(ia_tmp) / Path(Path(installer_path).name)
|
installer_path = Path(ia_tmp) / Path(Path(installer_path).name)
|
||||||
if not Path(installer_path).exists():
|
if not Path(installer_path).exists():
|
||||||
print(f"Failed to copy installer to {ia_tmp}")
|
logging.info(f"Failed to copy installer to {ia_tmp}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
createinstallmedia_path = str(Path(installer_path) / Path("Contents/Resources/createinstallmedia"))
|
createinstallmedia_path = str(Path(installer_path) / Path("Contents/Resources/createinstallmedia"))
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import binascii
|
import binascii
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
CHUNK_LENGTH = 4 + 32
|
CHUNK_LENGTH = 4 + 32
|
||||||
@@ -42,10 +43,10 @@ def chunk(file_path, chunklist, verbose):
|
|||||||
for chunk in chunks:
|
for chunk in chunks:
|
||||||
status = hashlib.sha256(f.read(chunk["length"])).digest()
|
status = hashlib.sha256(f.read(chunk["length"])).digest()
|
||||||
if not status == chunk["checksum"]:
|
if not status == chunk["checksum"]:
|
||||||
print(
|
logging.info(
|
||||||
f"Chunk {chunks.index(chunk) + 1} checksum status FAIL: chunk sum {binascii.hexlify(chunk['checksum']).decode()}, calculated sum {binascii.hexlify(status).decode()}")
|
f"Chunk {chunks.index(chunk) + 1} checksum status FAIL: chunk sum {binascii.hexlify(chunk['checksum']).decode()}, calculated sum {binascii.hexlify(status).decode()}")
|
||||||
return False
|
return False
|
||||||
elif verbose:
|
elif verbose:
|
||||||
print(
|
logging.info(
|
||||||
f"Chunk {chunks.index(chunk) + 1} checksum status success")
|
f"Chunk {chunks.index(chunk) + 1} checksum status success")
|
||||||
return True
|
return True
|
||||||
+338
-110
@@ -1,8 +1,7 @@
|
|||||||
# Kernel Debug Kit downloader
|
# Module for parsing and determining best Kernel Debug Kit for host OS
|
||||||
|
# Copyright (C) 2022-2023, Dhinak G, Mykola Grymalyuk
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import re
|
|
||||||
import urllib.parse
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
@@ -10,138 +9,354 @@ import packaging.version
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import os
|
||||||
|
|
||||||
from resources import utilities
|
import logging
|
||||||
|
|
||||||
|
from resources import utilities, network_handler
|
||||||
from resources.constants import Constants
|
from resources.constants import Constants
|
||||||
|
|
||||||
|
KDK_INSTALL_PATH = "/Library/Developer/KDKs"
|
||||||
|
|
||||||
class kernel_debug_kit_handler:
|
|
||||||
def __init__(self, constants: Constants):
|
|
||||||
self.constants = constants
|
|
||||||
|
|
||||||
def get_available_kdks(self):
|
class KernelDebugKitObject:
|
||||||
|
"""
|
||||||
|
Library for querying and downloading Kernel Debug Kits (KDK) for macOS
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
>>> kdk_object = KernelDebugKitObject(constants, host_build, host_version)
|
||||||
|
|
||||||
|
>>> if kdk_object.success:
|
||||||
|
|
||||||
|
>>> # Query whether a KDK is already installed
|
||||||
|
>>> if kdk_object.kdk_already_installed:
|
||||||
|
>>> # Use the installed KDK
|
||||||
|
>>> kdk_path = kdk_object.kdk_installed_path
|
||||||
|
|
||||||
|
>>> else:
|
||||||
|
>>> # Get DownloadObject for the KDK
|
||||||
|
>>> # See network_handler.py's DownloadObject documentation for usage
|
||||||
|
>>> kdk_download_object = kdk_object.retrieve_download()
|
||||||
|
|
||||||
|
>>> # Once downloaded, recommend verifying KDK's checksum
|
||||||
|
>>> valid = kdk_object.validate_kdk_checksum()
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, constants: Constants, host_build: str, host_version: str):
|
||||||
|
self.constants: Constants = constants
|
||||||
|
|
||||||
|
self.host_build: str = host_build # ex. 20A5384c
|
||||||
|
self.host_version: str = host_version # ex. 11.0.1
|
||||||
|
|
||||||
|
self.kdk_already_installed: bool = False
|
||||||
|
|
||||||
|
self.kdk_installed_path: str = ""
|
||||||
|
|
||||||
|
self.kdk_url: str = ""
|
||||||
|
self.kdk_url_build: str = ""
|
||||||
|
self.kdk_url_version: str = ""
|
||||||
|
|
||||||
|
self.kdk_url_is_exactly_match: bool = False
|
||||||
|
|
||||||
|
self.kdk_closest_match_url: str = ""
|
||||||
|
self.kdk_closest_match_url_build: str = ""
|
||||||
|
self.kdk_closest_match_url_version: str = ""
|
||||||
|
|
||||||
|
self.success: bool = False
|
||||||
|
|
||||||
|
self.error_msg: str = ""
|
||||||
|
|
||||||
|
self._get_latest_kdk()
|
||||||
|
|
||||||
|
|
||||||
|
def _get_available_kdks(self):
|
||||||
|
"""
|
||||||
|
Fetches a list of available KDKs from the KdkSupportPkg API
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: A list of KDKs, sorted by version and date if available. Returns None if the API is unreachable
|
||||||
|
"""
|
||||||
|
|
||||||
KDK_API_LINK = "https://raw.githubusercontent.com/dortania/KdkSupportPkg/gh-pages/manifest.json"
|
KDK_API_LINK = "https://raw.githubusercontent.com/dortania/KdkSupportPkg/gh-pages/manifest.json"
|
||||||
|
|
||||||
print("- Fetching available KDKs")
|
logging.info("- Pulling KDK list from KdkSupportPkg API")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
results = utilities.SESSION.get(KDK_API_LINK, headers={"User-Agent": f"OCLP/{self.constants.patcher_version}"}, timeout=10)
|
results = network_handler.SESSION.get(
|
||||||
|
KDK_API_LINK,
|
||||||
|
headers={
|
||||||
|
"User-Agent": f"OCLP/{self.constants.patcher_version}"
|
||||||
|
},
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
except (requests.exceptions.Timeout, requests.exceptions.TooManyRedirects, requests.exceptions.ConnectionError):
|
except (requests.exceptions.Timeout, requests.exceptions.TooManyRedirects, requests.exceptions.ConnectionError):
|
||||||
print("- Could not contact KDK API")
|
logging.info("- Could not contact KDK API")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if results.status_code != 200:
|
if results.status_code != 200:
|
||||||
print("- Could not fetch KDK list")
|
logging.info("- Could not fetch KDK list")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return sorted(results.json(), key=lambda x: (packaging.version.parse(x["version"]), datetime.datetime.fromisoformat(x["date"])), reverse=True)
|
return sorted(results.json(), key=lambda x: (packaging.version.parse(x["version"]), datetime.datetime.fromisoformat(x["date"])), reverse=True)
|
||||||
|
|
||||||
def download_kdk(self, version: str, build: str):
|
|
||||||
detected_build = build
|
|
||||||
|
|
||||||
if self.is_kdk_installed(detected_build) is True:
|
def _get_latest_kdk(self, host_build: str = None, host_version: str = None):
|
||||||
print("- KDK is already installed")
|
"""
|
||||||
self.remove_unused_kdks(exclude_builds=[detected_build])
|
Fetches the latest KDK for the current macOS version
|
||||||
return True, "", detected_build
|
|
||||||
|
|
||||||
download_link = None
|
Args:
|
||||||
closest_match_download_link = None
|
host_build (str, optional): The build version of the current macOS version.
|
||||||
closest_version = ""
|
If empty, will use the host_build from the class. Defaults to None.
|
||||||
closest_build = ""
|
host_version (str, optional): The version of the current macOS version.
|
||||||
|
If empty, will use the host_version from the class. Defaults to None.
|
||||||
|
"""
|
||||||
|
|
||||||
kdk_list = self.get_available_kdks()
|
if host_build is None and host_version is None:
|
||||||
|
host_build = self.host_build
|
||||||
|
host_version = self.host_version
|
||||||
|
|
||||||
parsed_version = cast(packaging.version.Version, packaging.version.parse(version))
|
logging.info(f"- Fetching latest KDK for {host_build} ({host_version})")
|
||||||
|
self.kdk_installed_path = self._local_kdk_installed_build()
|
||||||
|
if self.kdk_installed_path:
|
||||||
|
logging.info(f"- KDK already installed ({Path(self.kdk_installed_path).name}), skipping")
|
||||||
|
self.kdk_already_installed = True
|
||||||
|
self.success = True
|
||||||
|
return
|
||||||
|
|
||||||
if kdk_list:
|
remote_kdk_version = self._get_available_kdks()
|
||||||
for kdk in kdk_list:
|
|
||||||
kdk_version = cast(packaging.version.Version, packaging.version.parse(kdk["version"]))
|
parsed_version = cast(packaging.version.Version, packaging.version.parse(host_version))
|
||||||
if kdk["build"] == build:
|
|
||||||
download_link = kdk["url"]
|
if remote_kdk_version is None:
|
||||||
elif not closest_match_download_link and kdk_version <= parsed_version and kdk_version.major == parsed_version.major and (kdk_version.minor in range(parsed_version.minor - 1, parsed_version.minor + 1)):
|
logging.warning("- Failed to fetch KDK list, falling back to local KDK matching")
|
||||||
# The KDK list is already sorted by version then date, so the first match is the closest
|
|
||||||
closest_match_download_link = kdk["url"]
|
# First check if a KDK matching the current macOS version is installed
|
||||||
closest_version = kdk["version"]
|
# ex. 13.0.1 vs 13.0
|
||||||
closest_build = kdk["build"]
|
loose_version = f"{parsed_version.major}.{parsed_version.minor}"
|
||||||
|
logging.info(f"- Checking for KDKs loosely matching {loose_version}")
|
||||||
|
self.kdk_installed_path = self._local_kdk_installed_version(loose_version)
|
||||||
|
if self.kdk_installed_path:
|
||||||
|
logging.info(f"- Found matching KDK: {Path(self.kdk_installed_path).name}")
|
||||||
|
self.success = True
|
||||||
|
return
|
||||||
|
|
||||||
|
older_version = f"{parsed_version.major}.{parsed_version.minor - 1 if parsed_version.minor > 0 else 0}"
|
||||||
|
logging.info(f"- Checking for KDKs matching {older_version}")
|
||||||
|
self.kdk_installed_path = self._local_kdk_installed_version(older_version)
|
||||||
|
if self.kdk_installed_path:
|
||||||
|
logging.info(f"- Found matching KDK: {Path(self.kdk_installed_path).name}")
|
||||||
|
self.success = True
|
||||||
|
return
|
||||||
|
|
||||||
|
logging.warning(f"- Couldn't find KDK matching {host_version} or {older_version}, please install one manually")
|
||||||
|
|
||||||
|
self.error_msg = f"Could not contact KdkSupportPkg API, and no KDK matching {host_version} ({host_build}) or {older_version} was installed.\nPlease ensure you have a network connection or manually install a KDK."
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
for kdk in remote_kdk_version:
|
||||||
|
kdk_version = cast(packaging.version.Version, packaging.version.parse(kdk["version"]))
|
||||||
|
if (kdk["build"] == host_build):
|
||||||
|
self.kdk_url = kdk["url"]
|
||||||
|
self.kdk_url_build = kdk["build"]
|
||||||
|
self.kdk_url_version = kdk["version"]
|
||||||
|
self.kdk_url_is_exactly_match = True
|
||||||
|
break
|
||||||
|
if kdk_version <= parsed_version and kdk_version.major == parsed_version.major and (kdk_version.minor in range(parsed_version.minor - 1, parsed_version.minor + 1)):
|
||||||
|
# The KDK list is already sorted by version then date, so the first match is the closest
|
||||||
|
self.kdk_closest_match_url = kdk["url"]
|
||||||
|
self.kdk_closest_match_url_build = kdk["build"]
|
||||||
|
self.kdk_closest_match_url_version = kdk["version"]
|
||||||
|
self.kdk_url_is_exactly_match = False
|
||||||
|
break
|
||||||
|
|
||||||
|
if self.kdk_url == "":
|
||||||
|
if self.kdk_closest_match_url == "":
|
||||||
|
logging.warning(f"- No KDKs found for {host_build} ({host_version})")
|
||||||
|
self.error_msg = f"No KDKs found for {host_build} ({host_version})"
|
||||||
|
return
|
||||||
|
logging.info(f"- No direct match found for {host_build}, falling back to closest match")
|
||||||
|
logging.info(f"- Closest Match: {self.kdk_closest_match_url_build} ({self.kdk_closest_match_url_version})")
|
||||||
|
|
||||||
|
self.kdk_url = self.kdk_closest_match_url
|
||||||
|
self.kdk_url_build = self.kdk_closest_match_url_build
|
||||||
|
self.kdk_url_version = self.kdk_closest_match_url_version
|
||||||
else:
|
else:
|
||||||
msg = "Could not fetch KDK list"
|
logging.info(f"- Direct match found for {host_build} ({host_version})")
|
||||||
print(f"- {msg}")
|
|
||||||
return False, msg, ""
|
|
||||||
|
|
||||||
print(f"- Checking for KDK matching macOS {version} build {build}")
|
|
||||||
# download_link is None if no matching KDK is found, so we'll fall back to the closest match
|
|
||||||
if not download_link:
|
|
||||||
print("- Could not find KDK, finding closest match")
|
|
||||||
|
|
||||||
if self.is_kdk_installed(closest_build) is True:
|
# Check if this KDK is already installed
|
||||||
print(f"- Closest build ({closest_build}) already installed")
|
self.kdk_installed_path = self._local_kdk_installed_build(self.kdk_url_build)
|
||||||
self.remove_unused_kdks(exclude_builds=[detected_build, closest_build])
|
if self.kdk_installed_path:
|
||||||
return True, "", closest_build
|
logging.info(f"- KDK already installed ({Path(self.kdk_installed_path).name}), skipping")
|
||||||
|
self.kdk_already_installed = True
|
||||||
|
self.success = True
|
||||||
|
return
|
||||||
|
|
||||||
if closest_match_download_link is None:
|
logging.info("- Following KDK is recommended:")
|
||||||
msg = "Could not find KDK for host, nor closest match"
|
logging.info(f"- KDK Build: {self.kdk_url_build}")
|
||||||
print(f"- {msg}")
|
logging.info(f"- KDK Version: {self.kdk_url_version}")
|
||||||
return False, msg, ""
|
logging.info(f"- KDK URL: {self.kdk_url}")
|
||||||
|
|
||||||
print(f"- Closest match: {closest_version} build {closest_build}")
|
self.success = True
|
||||||
download_link = closest_match_download_link
|
|
||||||
|
|
||||||
if utilities.verify_network_connection(download_link):
|
|
||||||
print("- Downloading KDK")
|
|
||||||
else:
|
|
||||||
msg = "Could not contact download site"
|
|
||||||
print(f"- {msg}")
|
|
||||||
return False, msg, ""
|
|
||||||
|
|
||||||
result = utilities.download_file(download_link, self.constants.kdk_download_path)
|
def retrieve_download(self):
|
||||||
|
"""
|
||||||
|
Returns a DownloadObject for the KDK
|
||||||
|
|
||||||
if result:
|
Returns:
|
||||||
# TODO: should we use the checksum from the API?
|
DownloadObject: DownloadObject for the KDK, None if no download required
|
||||||
result = subprocess.run(["hdiutil", "verify", self.constants.kdk_download_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
"""
|
||||||
if result.returncode != 0:
|
|
||||||
print("Error: Kernel Debug Kit checksum verification failed!")
|
|
||||||
print(f"Output: {result.stderr}")
|
|
||||||
msg = "Kernel Debug Kit checksum verification failed, please try again.\n\nIf this continues to fail, ensure you're downloading on a stable network connection (ie. Ethernet)"
|
|
||||||
print(f"- {msg}")
|
|
||||||
return False, msg, ""
|
|
||||||
self.remove_unused_kdks(exclude_builds=[detected_build, closest_build])
|
|
||||||
return True, "", detected_build
|
|
||||||
msg = "Failed to download KDK"
|
|
||||||
print(f"- {msg}")
|
|
||||||
return False, msg, ""
|
|
||||||
|
|
||||||
def is_kdk_installed(self, build):
|
self.success = False
|
||||||
kexts_to_check = [
|
self.error_msg = ""
|
||||||
|
|
||||||
|
if self.kdk_already_installed:
|
||||||
|
logging.info("- No download required, KDK already installed")
|
||||||
|
self.success = True
|
||||||
|
return None
|
||||||
|
|
||||||
|
if self.kdk_url == "":
|
||||||
|
self.error_msg = "Could not retrieve KDK catalog, no KDK to download"
|
||||||
|
logging.error(self.error_msg)
|
||||||
|
return None
|
||||||
|
|
||||||
|
logging.info(f"- Returning DownloadObject for KDK: {Path(self.kdk_url).name}")
|
||||||
|
self.success = True
|
||||||
|
return network_handler.DownloadObject(self.kdk_url, self.constants.kdk_download_path)
|
||||||
|
|
||||||
|
|
||||||
|
def _local_kdk_valid(self, kdk_path: str):
|
||||||
|
"""
|
||||||
|
Validates provided KDK, ensure no corruption
|
||||||
|
|
||||||
|
The reason for this is due to macOS deleting files from the KDK during OS updates,
|
||||||
|
similar to how Install macOS.app is deleted during OS updates
|
||||||
|
|
||||||
|
Args:
|
||||||
|
kdk_path (str): Path to KDK
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if valid, False if invalid
|
||||||
|
"""
|
||||||
|
|
||||||
|
KEXT_CATALOG = [
|
||||||
"System.kext/PlugIns/Libkern.kext/Libkern",
|
"System.kext/PlugIns/Libkern.kext/Libkern",
|
||||||
"apfs.kext/Contents/MacOS/apfs",
|
"apfs.kext/Contents/MacOS/apfs",
|
||||||
"IOUSBHostFamily.kext/Contents/MacOS/IOUSBHostFamily",
|
"IOUSBHostFamily.kext/Contents/MacOS/IOUSBHostFamily",
|
||||||
"AMDRadeonX6000.kext/Contents/MacOS/AMDRadeonX6000",
|
"AMDRadeonX6000.kext/Contents/MacOS/AMDRadeonX6000",
|
||||||
]
|
]
|
||||||
|
|
||||||
if Path("/Library/Developer/KDKs").exists():
|
kdk_path = Path(kdk_path)
|
||||||
for file in Path("/Library/Developer/KDKs").iterdir():
|
|
||||||
if file.is_dir():
|
for kext in KEXT_CATALOG:
|
||||||
if file.name.endswith(f"{build}.kdk"):
|
if not Path(f"{kdk_path}/System/Library/Extensions/{kext}").exists():
|
||||||
for kext in kexts_to_check:
|
logging.info(f"- Corrupted KDK found, removing due to missing: {kdk_path}/System/Library/Extensions/{kext}")
|
||||||
if not Path(f"{file}/System/Library/Extensions/{kext}").exists():
|
self._remove_kdk(kdk_path)
|
||||||
print(f"- Corrupted KDK found, removing due to missing: {file}/System/Library/Extensions/{kext}")
|
return False
|
||||||
utilities.elevated(["rm", "-rf", file], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
||||||
return False
|
return True
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
def _local_kdk_installed_build(self, build: str = None):
|
||||||
|
"""
|
||||||
|
Checks if KDK matching build is installed
|
||||||
|
If so, validates it has not been corrupted
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Path to KDK if valid, None if not
|
||||||
|
"""
|
||||||
|
|
||||||
|
if build is None:
|
||||||
|
build = self.host_build
|
||||||
|
|
||||||
|
if not Path(KDK_INSTALL_PATH).exists():
|
||||||
|
return None
|
||||||
|
|
||||||
|
for kdk_folder in Path(KDK_INSTALL_PATH).iterdir():
|
||||||
|
if not kdk_folder.is_dir():
|
||||||
|
continue
|
||||||
|
if not kdk_folder.name.endswith(f"{build}.kdk"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if self._local_kdk_valid(kdk_folder):
|
||||||
|
return kdk_folder
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _local_kdk_installed_version(self, version: str = None):
|
||||||
|
"""
|
||||||
|
Checks if KDK matching version is installed
|
||||||
|
If so, validates it has not been corrupted
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Path to KDK if valid, None if not
|
||||||
|
"""
|
||||||
|
|
||||||
|
if version is None:
|
||||||
|
version = self.host_version
|
||||||
|
|
||||||
|
if not Path(KDK_INSTALL_PATH).exists():
|
||||||
|
return None
|
||||||
|
|
||||||
|
for kdk_folder in Path(KDK_INSTALL_PATH).iterdir():
|
||||||
|
if not kdk_folder.is_dir():
|
||||||
|
continue
|
||||||
|
if version not in kdk_folder.name:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if self._local_kdk_valid(kdk_folder):
|
||||||
|
return kdk_folder
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_kdk(self, kdk_path: str):
|
||||||
|
"""
|
||||||
|
Removes provided KDK
|
||||||
|
|
||||||
|
Args:
|
||||||
|
kdk_path (str): Path to KDK
|
||||||
|
"""
|
||||||
|
|
||||||
|
if os.getuid() != 0:
|
||||||
|
logging.warning("- Cannot remove KDK, not running as root")
|
||||||
|
return
|
||||||
|
|
||||||
|
result = utilities.elevated(["rm", "-rf", kdk_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
if result.returncode != 0:
|
||||||
|
logging.warning(f"- Failed to remove KDK: {kdk_path}")
|
||||||
|
logging.warning(f"- {result.stdout.decode('utf-8')}")
|
||||||
|
|
||||||
|
logging.info(f"- Successfully removed KDK: {kdk_path}")
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_unused_kdks(self, exclude_builds: list = None):
|
||||||
|
"""
|
||||||
|
Removes KDKs that are not in use
|
||||||
|
|
||||||
|
Args:
|
||||||
|
exclude_builds (list, optional): Builds to exclude from removal.
|
||||||
|
If None, defaults to host and closest match builds.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
if exclude_builds is None:
|
||||||
|
exclude_builds = [
|
||||||
|
self.kdk_url_build,
|
||||||
|
self.kdk_closest_match_url_build,
|
||||||
|
]
|
||||||
|
|
||||||
def remove_unused_kdks(self, exclude_builds=[]):
|
|
||||||
if self.constants.should_nuke_kdks is False:
|
if self.constants.should_nuke_kdks is False:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not Path("/Library/Developer/KDKs").exists():
|
if not Path(KDK_INSTALL_PATH).exists():
|
||||||
return
|
return
|
||||||
|
|
||||||
if exclude_builds == []:
|
logging.info("- Cleaning unused KDKs")
|
||||||
return
|
for kdk_folder in Path(KDK_INSTALL_PATH).iterdir():
|
||||||
|
|
||||||
print("- Cleaning unused KDKs")
|
|
||||||
for kdk_folder in Path("/Library/Developer/KDKs").iterdir():
|
|
||||||
if kdk_folder.is_dir():
|
if kdk_folder.is_dir():
|
||||||
if kdk_folder.name.endswith(".kdk"):
|
if kdk_folder.name.endswith(".kdk"):
|
||||||
should_remove = True
|
should_remove = True
|
||||||
@@ -151,27 +366,40 @@ class kernel_debug_kit_handler:
|
|||||||
break
|
break
|
||||||
if should_remove is False:
|
if should_remove is False:
|
||||||
continue
|
continue
|
||||||
print(f" - Removing {kdk_folder.name}")
|
self._remove_kdk(kdk_folder)
|
||||||
utilities.elevated(["rm", "-rf", kdk_folder], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
||||||
|
|
||||||
|
|
||||||
def kdk_backup_site(self, build):
|
def validate_kdk_checksum(self, kdk_dmg_path: str = None):
|
||||||
KDK_MIRROR_REPOSITORY = "https://api.github.com/repos/dortania/KdkSupportPkg/releases"
|
"""
|
||||||
|
Validates KDK DMG checksum
|
||||||
|
|
||||||
# Check if tag exists
|
Args:
|
||||||
catalog = requests.get(KDK_MIRROR_REPOSITORY)
|
kdk_dmg_path (str, optional): Path to KDK DMG. Defaults to None.
|
||||||
if catalog.status_code != 200:
|
|
||||||
print(f"- Could not contact KDK mirror repository")
|
|
||||||
return None
|
|
||||||
|
|
||||||
catalog = catalog.json()
|
Returns:
|
||||||
|
bool: True if valid, False if invalid
|
||||||
|
"""
|
||||||
|
|
||||||
for release in catalog:
|
self.success = False
|
||||||
if release["tag_name"] == build:
|
self.error_msg = ""
|
||||||
print(f"- Found KDK mirror for build: {build}")
|
|
||||||
for asset in release["assets"]:
|
|
||||||
if asset["name"].endswith(".dmg"):
|
|
||||||
return asset["browser_download_url"]
|
|
||||||
|
|
||||||
print(f"- Could not find KDK mirror for build {build}")
|
if kdk_dmg_path is None:
|
||||||
return None
|
kdk_dmg_path = self.constants.kdk_download_path
|
||||||
|
|
||||||
|
if not Path(kdk_dmg_path).exists():
|
||||||
|
logging.error(f"KDK DMG does not exist: {kdk_dmg_path}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# TODO: should we use the checksum from the API?
|
||||||
|
result = subprocess.run(["hdiutil", "verify", self.constants.kdk_download_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
if result.returncode != 0:
|
||||||
|
logging.info("- Error: Kernel Debug Kit checksum verification failed!")
|
||||||
|
logging.info(f"- Output: {result.stderr.decode('utf-8')}")
|
||||||
|
msg = "Kernel Debug Kit checksum verification failed, please try again.\n\nIf this continues to fail, ensure you're downloading on a stable network connection (ie. Ethernet)"
|
||||||
|
logging.info(f"- {msg}")
|
||||||
|
|
||||||
|
self.error_msg = msg
|
||||||
|
|
||||||
|
self._remove_unused_kdks()
|
||||||
|
|
||||||
|
self.success = True
|
||||||
|
|||||||
@@ -0,0 +1,145 @@
|
|||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
class InitializeLoggingSupport:
|
||||||
|
"""
|
||||||
|
Initialize logging framework for program
|
||||||
|
|
||||||
|
Primary responsibilities:
|
||||||
|
- Determine where to store log file
|
||||||
|
- Clean log file if it's near the max file size
|
||||||
|
- Initialize logging framework configuration
|
||||||
|
- Implement custom traceback handler
|
||||||
|
- Implement error handling for file write
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
>>> from resources.logging_handler import InitializeLoggingSupport
|
||||||
|
>>> InitializeLoggingSupport()
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.log_filename: str = "OpenCore-Patcher.log"
|
||||||
|
self.log_filepath: Path = None
|
||||||
|
|
||||||
|
self.original_excepthook: sys = sys.excepthook
|
||||||
|
self.original_thread_excepthook: threading = threading.excepthook
|
||||||
|
|
||||||
|
self.max_file_size: int = 1024 * 1024 * 10 # 10 MB
|
||||||
|
self.file_size_redline: int = 1024 * 1024 * 9 # 9 MB, when to start cleaning log file
|
||||||
|
|
||||||
|
self._initialize_logging_path()
|
||||||
|
self._clean_log_file()
|
||||||
|
self._attempt_initialize_logging_configuration()
|
||||||
|
self._implement_custom_traceback_handler()
|
||||||
|
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self._restore_original_excepthook()
|
||||||
|
|
||||||
|
|
||||||
|
def _initialize_logging_path(self):
|
||||||
|
"""
|
||||||
|
Initialize logging framework storage path
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.log_filepath = Path(f"~/Library/Logs/{self.log_filename}").expanduser()
|
||||||
|
|
||||||
|
if not self.log_filepath.parent.exists():
|
||||||
|
# Likely in an installer environment, store in /Users/Shared
|
||||||
|
self.log_filepath = Path("/Users/Shared") / self.log_filename
|
||||||
|
|
||||||
|
print("- Initializing logging framework...")
|
||||||
|
print(f" - Log file: {self.log_filepath}")
|
||||||
|
|
||||||
|
|
||||||
|
def _clean_log_file(self):
|
||||||
|
"""
|
||||||
|
Determine if log file should be cleaned
|
||||||
|
|
||||||
|
We check if we're near the max file size, and if so, we clean the log file
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not self.log_filepath.exists():
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.log_filepath.stat().st_size < self.file_size_redline:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check if backup log file exists
|
||||||
|
backup_log_filepath = self.log_filepath.with_suffix(".old.log")
|
||||||
|
try:
|
||||||
|
if backup_log_filepath.exists():
|
||||||
|
backup_log_filepath.unlink()
|
||||||
|
|
||||||
|
# Rename current log file to backup log file
|
||||||
|
self.log_filepath.rename(backup_log_filepath)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"- Failed to clean log file: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def _initialize_logging_configuration(self, log_to_file: bool = True):
|
||||||
|
"""
|
||||||
|
Initialize logging framework configuration
|
||||||
|
|
||||||
|
StreamHandler's format is used to mimic the default behavior of print()
|
||||||
|
While FileHandler's format is for more in-depth logging
|
||||||
|
"""
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.NOTSET,
|
||||||
|
format="%(asctime)s - %(filename)s (%(lineno)d): %(message)s",
|
||||||
|
handlers=[
|
||||||
|
logging.StreamHandler(stream = sys.stdout),
|
||||||
|
logging.FileHandler(self.log_filepath) if log_to_file is True else logging.NullHandler()
|
||||||
|
],
|
||||||
|
)
|
||||||
|
logging.getLogger().setLevel(logging.INFO)
|
||||||
|
logging.getLogger().handlers[0].setFormatter(logging.Formatter("%(message)s"))
|
||||||
|
logging.getLogger().handlers[1].maxBytes = self.max_file_size
|
||||||
|
|
||||||
|
def _attempt_initialize_logging_configuration(self):
|
||||||
|
"""
|
||||||
|
Attempt to initialize logging framework configuration
|
||||||
|
|
||||||
|
If we fail to initialize the logging framework, we will disable logging to file
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._initialize_logging_configuration()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"- Failed to initialize logging framework: {e}")
|
||||||
|
print("- Retrying without logging to file...")
|
||||||
|
self._initialize_logging_configuration(log_to_file=False)
|
||||||
|
|
||||||
|
|
||||||
|
def _implement_custom_traceback_handler(self):
|
||||||
|
"""
|
||||||
|
Reroute traceback to logging module
|
||||||
|
"""
|
||||||
|
|
||||||
|
def custom_excepthook(type, value, tb):
|
||||||
|
"""
|
||||||
|
Reroute traceback in main thread to logging module
|
||||||
|
"""
|
||||||
|
logging.error("Uncaught exception in main thread", exc_info=(type, value, tb))
|
||||||
|
|
||||||
|
def custom_thread_excepthook(args):
|
||||||
|
"""
|
||||||
|
Reroute traceback in spawned thread to logging module
|
||||||
|
"""
|
||||||
|
logging.error("Uncaught exception in spawned thread", exc_info=(args))
|
||||||
|
|
||||||
|
sys.excepthook = custom_excepthook
|
||||||
|
threading.excepthook = custom_thread_excepthook
|
||||||
|
|
||||||
|
def _restore_original_excepthook(self):
|
||||||
|
"""
|
||||||
|
Restore original traceback handlers
|
||||||
|
"""
|
||||||
|
|
||||||
|
sys.excepthook = self.original_excepthook
|
||||||
|
threading.excepthook = self.original_thread_excepthook
|
||||||
+27
-8
@@ -1,20 +1,38 @@
|
|||||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
|
||||||
import time
|
import time
|
||||||
|
import logging
|
||||||
import threading
|
import threading
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from resources import cli_menu, constants, utilities, device_probe, os_probe, defaults, arguments, install, tui_helpers, reroute_payloads, commit_info
|
|
||||||
from resources.build import build
|
|
||||||
from data import model_array
|
from data import model_array
|
||||||
|
from resources.build import build
|
||||||
|
from resources import (
|
||||||
|
cli_menu,
|
||||||
|
constants,
|
||||||
|
utilities,
|
||||||
|
device_probe,
|
||||||
|
os_probe,
|
||||||
|
defaults,
|
||||||
|
arguments,
|
||||||
|
install,
|
||||||
|
tui_helpers,
|
||||||
|
reroute_payloads,
|
||||||
|
commit_info,
|
||||||
|
logging_handler
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class OpenCoreLegacyPatcher:
|
class OpenCoreLegacyPatcher:
|
||||||
def __init__(self, launch_gui=False):
|
def __init__(self, launch_gui=False):
|
||||||
print("- Loading...")
|
|
||||||
self.constants = constants.Constants()
|
self.constants = constants.Constants()
|
||||||
self.constants.wxpython_variant = launch_gui
|
self.constants.wxpython_variant = launch_gui
|
||||||
|
logging_handler.InitializeLoggingSupport()
|
||||||
|
|
||||||
|
logging.info(f"- Loading OpenCore Legacy Patcher v{self.constants.patcher_version}...")
|
||||||
|
|
||||||
self.generate_base_data()
|
self.generate_base_data()
|
||||||
if utilities.check_cli_args() is None:
|
if utilities.check_cli_args() is None:
|
||||||
if launch_gui is True:
|
if launch_gui is True:
|
||||||
@@ -24,6 +42,7 @@ class OpenCoreLegacyPatcher:
|
|||||||
else:
|
else:
|
||||||
self.main_menu()
|
self.main_menu()
|
||||||
|
|
||||||
|
|
||||||
def generate_base_data(self):
|
def generate_base_data(self):
|
||||||
self.constants.detected_os = os_probe.detect_kernel_major()
|
self.constants.detected_os = os_probe.detect_kernel_major()
|
||||||
self.constants.detected_os_minor = os_probe.detect_kernel_minor()
|
self.constants.detected_os_minor = os_probe.detect_kernel_minor()
|
||||||
@@ -58,14 +77,14 @@ class OpenCoreLegacyPatcher:
|
|||||||
defaults.generate_defaults(self.computer.real_model, True, self.constants)
|
defaults.generate_defaults(self.computer.real_model, True, self.constants)
|
||||||
|
|
||||||
if utilities.check_cli_args() is not None:
|
if utilities.check_cli_args() is not None:
|
||||||
print("- Detected arguments, switching to CLI mode")
|
logging.info("- Detected arguments, switching to CLI mode")
|
||||||
self.constants.gui_mode = True # Assumes no user interaction is required
|
self.constants.gui_mode = True # Assumes no user interaction is required
|
||||||
ignore_args = ["--auto_patch", "--gui_patch", "--gui_unpatch"]
|
ignore_args = ["--auto_patch", "--gui_patch", "--gui_unpatch"]
|
||||||
if not any(x in sys.argv for x in ignore_args):
|
if not any(x in sys.argv for x in ignore_args):
|
||||||
self.constants.current_path = Path.cwd()
|
self.constants.current_path = Path.cwd()
|
||||||
self.constants.cli_mode = True
|
self.constants.cli_mode = True
|
||||||
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
|
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
|
||||||
print("- Rerouting payloads location")
|
logging.info("- Rerouting payloads location")
|
||||||
self.constants.payload_path = sys._MEIPASS / Path("payloads")
|
self.constants.payload_path = sys._MEIPASS / Path("payloads")
|
||||||
ignore_args = ignore_args.pop(0)
|
ignore_args = ignore_args.pop(0)
|
||||||
if not any(x in sys.argv for x in ignore_args):
|
if not any(x in sys.argv for x in ignore_args):
|
||||||
@@ -73,7 +92,7 @@ class OpenCoreLegacyPatcher:
|
|||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
arguments.arguments().parse_arguments(self.constants)
|
arguments.arguments().parse_arguments(self.constants)
|
||||||
else:
|
else:
|
||||||
print(f"- No arguments present, loading {'GUI' if self.constants.wxpython_variant is True else 'TUI'} mode")
|
logging.info(f"- No arguments present, loading {'GUI' if self.constants.wxpython_variant is True else 'TUI'} mode")
|
||||||
|
|
||||||
|
|
||||||
def main_menu(self):
|
def main_menu(self):
|
||||||
|
|||||||
@@ -0,0 +1,383 @@
|
|||||||
|
# Library dedicated to Network Handling tasks including downloading files
|
||||||
|
# Primarily based around the DownloadObject class, which provides a simple
|
||||||
|
# object for libraries to query download progress and status
|
||||||
|
# Copyright (C) 2023, Mykola Grymalyuk
|
||||||
|
|
||||||
|
import time
|
||||||
|
import requests
|
||||||
|
import threading
|
||||||
|
import logging
|
||||||
|
import enum
|
||||||
|
import hashlib
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from resources import utilities
|
||||||
|
|
||||||
|
SESSION = requests.Session()
|
||||||
|
|
||||||
|
|
||||||
|
class DownloadStatus(enum.Enum):
|
||||||
|
"""
|
||||||
|
Enum for download status
|
||||||
|
"""
|
||||||
|
|
||||||
|
INACTIVE: str = "Inactive"
|
||||||
|
DOWNLOADING: str = "Downloading"
|
||||||
|
ERROR: str = "Error"
|
||||||
|
COMPLETE: str = "Complete"
|
||||||
|
|
||||||
|
|
||||||
|
class NetworkUtilities:
|
||||||
|
"""
|
||||||
|
Utilities for network related tasks, primarily used for downloading files
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, url: str = None):
|
||||||
|
self.url: str = url
|
||||||
|
|
||||||
|
if self.url is None:
|
||||||
|
self.url = "https://github.com"
|
||||||
|
|
||||||
|
|
||||||
|
def verify_network_connection(self):
|
||||||
|
"""
|
||||||
|
Verifies that the network is available
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if network is available, False otherwise
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
requests.head(self.url, timeout=5, allow_redirects=True)
|
||||||
|
return True
|
||||||
|
except (
|
||||||
|
requests.exceptions.Timeout,
|
||||||
|
requests.exceptions.TooManyRedirects,
|
||||||
|
requests.exceptions.ConnectionError,
|
||||||
|
requests.exceptions.HTTPError
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def validate_link(self):
|
||||||
|
# Check if link is 404
|
||||||
|
try:
|
||||||
|
response = SESSION.head(self.url, timeout=5, allow_redirects=True)
|
||||||
|
if response.status_code == 404:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
except (
|
||||||
|
requests.exceptions.Timeout,
|
||||||
|
requests.exceptions.TooManyRedirects,
|
||||||
|
requests.exceptions.ConnectionError,
|
||||||
|
requests.exceptions.HTTPError
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class DownloadObject:
|
||||||
|
"""
|
||||||
|
Object for downloading files from the network
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
>>> download_object = DownloadObject(url, path)
|
||||||
|
>>> download_object.download(display_progress=True)
|
||||||
|
|
||||||
|
>>> if download_object.is_active():
|
||||||
|
>>> print(download_object.get_percent())
|
||||||
|
|
||||||
|
>>> if not download_object.download_complete:
|
||||||
|
>>> print("Download failed")
|
||||||
|
|
||||||
|
>>> print("Download complete"")
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, url: str, path: str):
|
||||||
|
self.url: str = url
|
||||||
|
self.status: str = DownloadStatus.INACTIVE
|
||||||
|
self.error_msg: str = ""
|
||||||
|
self.filename: str = self._get_filename()
|
||||||
|
|
||||||
|
self.filepath: Path = Path(path)
|
||||||
|
|
||||||
|
self.total_file_size: float = 0.0
|
||||||
|
self.downloaded_file_size: float = 0.0
|
||||||
|
self.start_time: float = time.time()
|
||||||
|
|
||||||
|
self.error: bool = False
|
||||||
|
self.should_stop: bool = False
|
||||||
|
self.download_complete: bool = False
|
||||||
|
self.has_network: bool = NetworkUtilities(self.url).verify_network_connection()
|
||||||
|
|
||||||
|
self.active_thread: threading.Thread = None
|
||||||
|
|
||||||
|
self.should_checksum: bool = False
|
||||||
|
|
||||||
|
self.checksum = None
|
||||||
|
self._checksum_storage: hash = None
|
||||||
|
|
||||||
|
if self.has_network:
|
||||||
|
self._populate_file_size()
|
||||||
|
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
|
||||||
|
def download(self, display_progress: bool = False, spawn_thread: bool = True, verify_checksum: bool = False):
|
||||||
|
"""
|
||||||
|
Download the file
|
||||||
|
|
||||||
|
Spawns a thread to download the file, so that the main thread can continue
|
||||||
|
Note sleep is disabled while the download is active
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
display_progress (bool): Display progress in console
|
||||||
|
spawn_thread (bool): Spawn a thread to download the file, otherwise download in the current thread
|
||||||
|
verify_checksum (bool): Calculate checksum of downloaded file if True
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.status = DownloadStatus.DOWNLOADING
|
||||||
|
logging.info(f"Starting download: {self.filename}")
|
||||||
|
if spawn_thread:
|
||||||
|
if self.active_thread:
|
||||||
|
logging.error("Download already in progress")
|
||||||
|
return
|
||||||
|
self.should_checksum = verify_checksum
|
||||||
|
self.active_thread = threading.Thread(target=self._download, args=(display_progress,))
|
||||||
|
self.active_thread.start()
|
||||||
|
return
|
||||||
|
|
||||||
|
self.should_checksum = verify_checksum
|
||||||
|
self._download(display_progress)
|
||||||
|
|
||||||
|
def download_simple(self, verify_checksum: bool = False):
|
||||||
|
"""
|
||||||
|
Alternative to download(), mimics utilities.py's old download_file() function
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
verify_checksum (bool): Return checksum of downloaded file if True
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
If verify_checksum is True, returns the checksum of the downloaded file
|
||||||
|
Otherwise, returns True if download was successful, False otherwise
|
||||||
|
"""
|
||||||
|
|
||||||
|
if verify_checksum:
|
||||||
|
self.should_checksum = True
|
||||||
|
self.checksum = hashlib.sha256()
|
||||||
|
|
||||||
|
self.download(spawn_thread=False)
|
||||||
|
|
||||||
|
if not self.download_complete:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return self.checksum.hexdigest() if self.checksum else True
|
||||||
|
|
||||||
|
|
||||||
|
def _get_filename(self):
|
||||||
|
"""
|
||||||
|
Get the filename from the URL
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Filename
|
||||||
|
"""
|
||||||
|
|
||||||
|
return Path(self.url).name
|
||||||
|
|
||||||
|
|
||||||
|
def _populate_file_size(self):
|
||||||
|
"""
|
||||||
|
Get the file size of the file to be downloaded
|
||||||
|
|
||||||
|
If unable to get file size, set to zero
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = SESSION.head(self.url, allow_redirects=True, timeout=5)
|
||||||
|
if 'Content-Length' in result.headers:
|
||||||
|
self.total_file_size = float(result.headers['Content-Length'])
|
||||||
|
else:
|
||||||
|
raise Exception("Content-Length missing from headers")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error determining file size {self.url}: {str(e)}")
|
||||||
|
logging.error("Assuming file size is 0")
|
||||||
|
self.total_file_size = 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def _update_checksum(self, chunk: bytes):
|
||||||
|
"""
|
||||||
|
Update checksum with new chunk
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
chunk (bytes): Chunk to update checksum with
|
||||||
|
"""
|
||||||
|
self._checksum_storage.update(chunk)
|
||||||
|
|
||||||
|
|
||||||
|
def _prepare_working_directory(self, path: Path):
|
||||||
|
"""
|
||||||
|
Validates working enviroment, including free space and removing existing files
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
path (str): Path to the file
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if successful, False if not
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
if Path(path).exists():
|
||||||
|
logging.info(f"Deleting existing file: {path}")
|
||||||
|
Path(path).unlink()
|
||||||
|
return True
|
||||||
|
|
||||||
|
if not Path(path).parent.exists():
|
||||||
|
logging.info(f"Creating directory: {Path(path).parent}")
|
||||||
|
Path(path).parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
available_space = utilities.get_free_space()
|
||||||
|
if self.total_file_size > available_space:
|
||||||
|
msg = f"Not enough free space to download {self.filename}, need {utilities.human_fmt(self.total_file_size)}, have {utilities.human_fmt(available_space)}"
|
||||||
|
logging.error(msg)
|
||||||
|
raise Exception(msg)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.error = True
|
||||||
|
self.error_msg = str(e)
|
||||||
|
self.status = DownloadStatus.ERROR
|
||||||
|
logging.error(f"Error preparing working directory {path}: {self.error_msg}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _download(self, display_progress: bool = False):
|
||||||
|
"""
|
||||||
|
Download the file
|
||||||
|
|
||||||
|
Libraries should invoke download() instead of this method
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
display_progress (bool): Display progress in console
|
||||||
|
"""
|
||||||
|
|
||||||
|
utilities.disable_sleep_while_running()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not self.has_network:
|
||||||
|
raise Exception("No network connection")
|
||||||
|
|
||||||
|
if self._prepare_working_directory(self.filepath) is False:
|
||||||
|
raise Exception(self.error_msg)
|
||||||
|
|
||||||
|
response = SESSION.get(self.url, stream=True, timeout=10)
|
||||||
|
|
||||||
|
with open(self.filepath, 'wb') as file:
|
||||||
|
for i, chunk in enumerate(response.iter_content(1024 * 1024 * 4)):
|
||||||
|
if self.should_stop:
|
||||||
|
raise Exception("Download stopped")
|
||||||
|
if chunk:
|
||||||
|
file.write(chunk)
|
||||||
|
self.downloaded_file_size += len(chunk)
|
||||||
|
if self.should_checksum:
|
||||||
|
self._update_checksum(chunk)
|
||||||
|
if display_progress and i % 100:
|
||||||
|
# Don't use logging here, as we'll be spamming the log file
|
||||||
|
if self.total_file_size == 0.0:
|
||||||
|
print(f"Downloaded {utilities.human_fmt(self.downloaded_file_size)} of {self.filename}")
|
||||||
|
else:
|
||||||
|
print(f"Downloaded {self.get_percent():.2f}% of {self.filename} ({utilities.human_fmt(self.get_speed())}/s) ({self.get_time_remaining():.2f} seconds remaining)")
|
||||||
|
self.download_complete = True
|
||||||
|
logging.info(f"Download complete: {self.filename}")
|
||||||
|
logging.info("Stats:")
|
||||||
|
logging.info(f" Downloaded size: {utilities.human_fmt(self.downloaded_file_size)}")
|
||||||
|
logging.info(f" Time elapsed: {(time.time() - self.start_time):.2f} seconds")
|
||||||
|
logging.info(f" Speed: {utilities.human_fmt(self.downloaded_file_size / (time.time() - self.start_time))}/s")
|
||||||
|
logging.info(f" Location: {self.filepath}")
|
||||||
|
except Exception as e:
|
||||||
|
self.error = True
|
||||||
|
self.error_msg = str(e)
|
||||||
|
self.status = DownloadStatus.ERROR
|
||||||
|
logging.error(f"Error downloading {self.url}: {self.error_msg}")
|
||||||
|
|
||||||
|
self.status = DownloadStatus.COMPLETE
|
||||||
|
utilities.enable_sleep_after_running()
|
||||||
|
|
||||||
|
|
||||||
|
def get_percent(self):
|
||||||
|
"""
|
||||||
|
Query the download percent
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
float: The download percent, or -1 if unknown
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.total_file_size == 0.0:
|
||||||
|
logging.error("File size is 0, cannot calculate percent")
|
||||||
|
return -1
|
||||||
|
return self.downloaded_file_size / self.total_file_size * 100
|
||||||
|
|
||||||
|
|
||||||
|
def get_speed(self):
|
||||||
|
"""
|
||||||
|
Query the download speed
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
float: The download speed in bytes per second
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.downloaded_file_size / (time.time() - self.start_time)
|
||||||
|
|
||||||
|
|
||||||
|
def get_time_remaining(self):
|
||||||
|
"""
|
||||||
|
Query the time remaining for the download
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
float: The time remaining in seconds, or -1 if unknown
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.total_file_size == 0.0:
|
||||||
|
logging.error("File size is 0, cannot calculate time remaining")
|
||||||
|
return -1
|
||||||
|
return (self.total_file_size - self.downloaded_file_size) / self.get_speed()
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_size(self):
|
||||||
|
"""
|
||||||
|
Query the file size of the file to be downloaded
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
float: The file size in bytes, or 0.0 if unknown
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.total_file_size
|
||||||
|
|
||||||
|
|
||||||
|
def is_active(self):
|
||||||
|
"""
|
||||||
|
Query if the download is active
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
boolean: True if active, False if completed, failed, stopped, or inactive
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.status == DownloadStatus.DOWNLOADING:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""
|
||||||
|
Stop the download
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
boolean: If the download is active, this function will hold the thread until stopped
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.should_stop = True
|
||||||
|
if self.active_thread:
|
||||||
|
while self.active_thread.is_alive():
|
||||||
|
time.sleep(1)
|
||||||
@@ -7,6 +7,7 @@ from pathlib import Path
|
|||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
import atexit
|
import atexit
|
||||||
|
import logging
|
||||||
|
|
||||||
class reroute_payloads:
|
class reroute_payloads:
|
||||||
def __init__(self, constants):
|
def __init__(self, constants):
|
||||||
@@ -17,10 +18,10 @@ class reroute_payloads:
|
|||||||
# Then reroute r/w to this new temp directory
|
# Then reroute r/w to this new temp directory
|
||||||
# Currently only applicable for GUI variant
|
# Currently only applicable for GUI variant
|
||||||
if self.constants.wxpython_variant is True and not self.constants.launcher_script:
|
if self.constants.wxpython_variant is True and not self.constants.launcher_script:
|
||||||
print("- Running in Binary GUI mode, switching to tmp directory")
|
logging.info("- Running in Binary GUI mode, switching to tmp directory")
|
||||||
self.temp_dir = tempfile.TemporaryDirectory()
|
self.temp_dir = tempfile.TemporaryDirectory()
|
||||||
print(f"- New payloads location: {self.temp_dir.name}")
|
logging.info(f"- New payloads location: {self.temp_dir.name}")
|
||||||
print("- Creating payloads directory")
|
logging.info("- Creating payloads directory")
|
||||||
Path(self.temp_dir.name / Path("payloads")).mkdir(parents=True, exist_ok=True)
|
Path(self.temp_dir.name / Path("payloads")).mkdir(parents=True, exist_ok=True)
|
||||||
self.unmount_active_dmgs(unmount_all_active=False)
|
self.unmount_active_dmgs(unmount_all_active=False)
|
||||||
output = subprocess.run(
|
output = subprocess.run(
|
||||||
@@ -34,14 +35,14 @@ class reroute_payloads:
|
|||||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
if output.returncode == 0:
|
if output.returncode == 0:
|
||||||
print("- Mounted payloads.dmg")
|
logging.info("- Mounted payloads.dmg")
|
||||||
self.constants.current_path = Path(self.temp_dir.name)
|
self.constants.current_path = Path(self.temp_dir.name)
|
||||||
self.constants.payload_path = Path(self.temp_dir.name) / Path("payloads")
|
self.constants.payload_path = Path(self.temp_dir.name) / Path("payloads")
|
||||||
atexit.register(self.unmount_active_dmgs, unmount_all_active=False)
|
atexit.register(self.unmount_active_dmgs, unmount_all_active=False)
|
||||||
else:
|
else:
|
||||||
print("- Failed to mount payloads.dmg")
|
logging.info("- Failed to mount payloads.dmg")
|
||||||
print(f"Output: {output.stdout.decode()}")
|
logging.info(f"Output: {output.stdout.decode()}")
|
||||||
print(f"Return Code: {output.returncode}")
|
logging.info(f"Return Code: {output.returncode}")
|
||||||
|
|
||||||
def unmount_active_dmgs(self, unmount_all_active=True):
|
def unmount_active_dmgs(self, unmount_all_active=True):
|
||||||
# Find all DMGs that are mounted, and forcefully unmount them
|
# Find all DMGs that are mounted, and forcefully unmount them
|
||||||
@@ -56,13 +57,13 @@ class reroute_payloads:
|
|||||||
# Check that only our personal payloads.dmg is unmounted
|
# Check that only our personal payloads.dmg is unmounted
|
||||||
if "shadow-path" in image:
|
if "shadow-path" in image:
|
||||||
if self.temp_dir.name in image["shadow-path"]:
|
if self.temp_dir.name in image["shadow-path"]:
|
||||||
print("- Unmounting personal payloads.dmg")
|
logging.info("- Unmounting personal payloads.dmg")
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["hdiutil", "detach", image["system-entities"][0]["dev-entry"], "-force"],
|
["hdiutil", "detach", image["system-entities"][0]["dev-entry"], "-force"],
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print(f"- Unmounting payloads.dmg at: {image['system-entities'][0]['dev-entry']}")
|
logging.info(f"- Unmounting payloads.dmg at: {image['system-entities'][0]['dev-entry']}")
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["hdiutil", "detach", image["system-entities"][0]["dev-entry"], "-force"],
|
["hdiutil", "detach", image["system-entities"][0]["dev-entry"], "-force"],
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
|
|||||||
+6
-9
@@ -2,11 +2,8 @@
|
|||||||
# Written by CorpNewt
|
# Written by CorpNewt
|
||||||
# Source: https://github.com/corpnewt/pymodules/blob/884c3de15b6a2570afde52fe8a14a3e946ffb18a/run.py
|
# Source: https://github.com/corpnewt/pymodules/blob/884c3de15b6a2570afde52fe8a14a3e946ffb18a/run.py
|
||||||
|
|
||||||
import sys, subprocess, time, threading, shlex
|
import sys, subprocess, time, threading, shlex, logging
|
||||||
try:
|
from queue import Queue, Empty
|
||||||
from Queue import Queue, Empty
|
|
||||||
except:
|
|
||||||
from queue import Queue, Empty
|
|
||||||
|
|
||||||
ON_POSIX = 'posix' in sys.builtin_module_names
|
ON_POSIX = 'posix' in sys.builtin_module_names
|
||||||
|
|
||||||
@@ -115,7 +112,7 @@ class Run:
|
|||||||
show = comm.get("show", False)
|
show = comm.get("show", False)
|
||||||
|
|
||||||
if not mess == None:
|
if not mess == None:
|
||||||
print(mess)
|
logging.info(mess)
|
||||||
|
|
||||||
if not len(args):
|
if not len(args):
|
||||||
# nothing to process
|
# nothing to process
|
||||||
@@ -131,7 +128,7 @@ class Run:
|
|||||||
args = out[0].replace("\n", "") + " " + args # add to start of string
|
args = out[0].replace("\n", "") + " " + args # add to start of string
|
||||||
|
|
||||||
if show:
|
if show:
|
||||||
print(" ".join(args))
|
logging.info(" ".join(args))
|
||||||
|
|
||||||
if stream:
|
if stream:
|
||||||
# Stream it!
|
# Stream it!
|
||||||
@@ -140,9 +137,9 @@ class Run:
|
|||||||
# Just run and gather output
|
# Just run and gather output
|
||||||
out = self._run_command(args, shell)
|
out = self._run_command(args, shell)
|
||||||
if stdout and len(out[0]):
|
if stdout and len(out[0]):
|
||||||
print(out[0])
|
logging.info(out[0])
|
||||||
if stderr and len(out[1]):
|
if stderr and len(out[1]):
|
||||||
print(out[1])
|
logging.info(out[1])
|
||||||
# Append output
|
# Append output
|
||||||
output_list.append(out)
|
output_list.append(out)
|
||||||
# Check for errors
|
# Check for errors
|
||||||
|
|||||||
+132
-119
@@ -37,9 +37,10 @@ import shutil
|
|||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
import logging
|
||||||
|
|
||||||
from resources import constants, utilities, kdk_handler
|
from resources import constants, utilities, kdk_handler
|
||||||
from resources.sys_patch import sys_patch_download, sys_patch_detect, sys_patch_auto, sys_patch_helpers
|
from resources.sys_patch import sys_patch_detect, sys_patch_auto, sys_patch_helpers
|
||||||
|
|
||||||
from data import os_data
|
from data import os_data
|
||||||
|
|
||||||
@@ -90,27 +91,63 @@ class PatchSysVolume:
|
|||||||
# Returns boolean if Root Volume is available
|
# Returns boolean if Root Volume is available
|
||||||
self.root_mount_path = utilities.get_disk_path()
|
self.root_mount_path = utilities.get_disk_path()
|
||||||
if self.root_mount_path.startswith("disk"):
|
if self.root_mount_path.startswith("disk"):
|
||||||
print(f"- Found Root Volume at: {self.root_mount_path}")
|
logging.info(f"- Found Root Volume at: {self.root_mount_path}")
|
||||||
if Path(self.mount_extensions).exists():
|
if Path(self.mount_extensions).exists():
|
||||||
print("- Root Volume is already mounted")
|
logging.info("- Root Volume is already mounted")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
if self.root_supports_snapshot is True:
|
if self.root_supports_snapshot is True:
|
||||||
print("- Mounting APFS Snapshot as writable")
|
logging.info("- Mounting APFS Snapshot as writable")
|
||||||
result = utilities.elevated(["mount", "-o", "nobrowse", "-t", "apfs", f"/dev/{self.root_mount_path}", self.mount_location], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
result = utilities.elevated(["mount", "-o", "nobrowse", "-t", "apfs", f"/dev/{self.root_mount_path}", self.mount_location], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
print(f"- Mounted APFS Snapshot as writable at: {self.mount_location}")
|
logging.info(f"- Mounted APFS Snapshot as writable at: {self.mount_location}")
|
||||||
if Path(self.mount_extensions).exists():
|
if Path(self.mount_extensions).exists():
|
||||||
print("- Successfully mounted the Root Volume")
|
logging.info("- Successfully mounted the Root Volume")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print("- Root Volume appears to have unmounted unexpectedly")
|
logging.info("- Root Volume appears to have unmounted unexpectedly")
|
||||||
else:
|
else:
|
||||||
print("- Unable to mount APFS Snapshot as writable")
|
logging.info("- Unable to mount APFS Snapshot as writable")
|
||||||
print("Reason for mount failure:")
|
logging.info("Reason for mount failure:")
|
||||||
print(result.stdout.decode().strip())
|
logging.info(result.stdout.decode().strip())
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def invoke_kdk_handler(self):
|
||||||
|
# If we're invoked, there is no KDK installed (or something went wrong)
|
||||||
|
kdk_result = False
|
||||||
|
error_msg = ""
|
||||||
|
|
||||||
|
kdk_obj = kdk_handler.KernelDebugKitObject(self.constants, self.constants.detected_os_build, self.constants.detected_os_version)
|
||||||
|
|
||||||
|
if kdk_obj.success is False:
|
||||||
|
error_msg = kdk_obj.error_msg
|
||||||
|
return kdk_result, error_msg, None
|
||||||
|
|
||||||
|
kdk_download_obj = kdk_obj.retrieve_download()
|
||||||
|
|
||||||
|
# We didn't get a download object, something's wrong
|
||||||
|
if not kdk_download_obj:
|
||||||
|
if kdk_obj.kdk_already_installed is True:
|
||||||
|
error_msg = "KDK already installed, function should not have been invoked"
|
||||||
|
return kdk_result, error_msg, None
|
||||||
|
else:
|
||||||
|
error_msg = "Could not retrieve KDK"
|
||||||
|
return kdk_result, error_msg, None
|
||||||
|
|
||||||
|
# Hold thread until download is complete
|
||||||
|
kdk_download_obj.download(spawn_thread=False)
|
||||||
|
|
||||||
|
if kdk_download_obj.download_complete is False:
|
||||||
|
error_msg = kdk_download_obj.error_msg
|
||||||
|
return kdk_result, error_msg, None
|
||||||
|
|
||||||
|
kdk_result = kdk_obj.validate_kdk_checksum()
|
||||||
|
downloaded_kdk = self.constants.kdk_download_path
|
||||||
|
|
||||||
|
return kdk_result, error_msg, downloaded_kdk
|
||||||
|
|
||||||
|
|
||||||
def merge_kdk_with_root(self, save_hid_cs=False):
|
def merge_kdk_with_root(self, save_hid_cs=False):
|
||||||
if self.skip_root_kmutil_requirement is True:
|
if self.skip_root_kmutil_requirement is True:
|
||||||
return
|
return
|
||||||
@@ -121,7 +158,7 @@ class PatchSysVolume:
|
|||||||
kdk_path = sys_patch_helpers.sys_patch_helpers(self.constants).determine_kdk_present(match_closest=False)
|
kdk_path = sys_patch_helpers.sys_patch_helpers(self.constants).determine_kdk_present(match_closest=False)
|
||||||
if kdk_path is None:
|
if kdk_path is None:
|
||||||
if not self.constants.kdk_download_path.exists():
|
if not self.constants.kdk_download_path.exists():
|
||||||
kdk_result, error_msg, downloaded_kdk = kdk_handler.kernel_debug_kit_handler(self.constants).download_kdk(self.constants.detected_os_version, self.constants.detected_os_build)
|
kdk_result, error_msg, downloaded_kdk = self.invoke_kdk_handler()
|
||||||
if kdk_result is False:
|
if kdk_result is False:
|
||||||
raise Exception(f"Unable to download KDK: {error_msg}")
|
raise Exception(f"Unable to download KDK: {error_msg}")
|
||||||
sys_patch_helpers.sys_patch_helpers(self.constants).install_kdk()
|
sys_patch_helpers.sys_patch_helpers(self.constants).install_kdk()
|
||||||
@@ -135,25 +172,25 @@ class PatchSysVolume:
|
|||||||
oclp_plist_data = plistlib.load(open(oclp_plist, "rb"))
|
oclp_plist_data = plistlib.load(open(oclp_plist, "rb"))
|
||||||
if "Kernel Debug Kit Used" in oclp_plist_data:
|
if "Kernel Debug Kit Used" in oclp_plist_data:
|
||||||
if oclp_plist_data["Kernel Debug Kit Used"] == str(kdk_path):
|
if oclp_plist_data["Kernel Debug Kit Used"] == str(kdk_path):
|
||||||
print("- Matching KDK determined to already be merged, skipping")
|
logging.info("- Matching KDK determined to already be merged, skipping")
|
||||||
return
|
return
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if kdk_path is None:
|
if kdk_path is None:
|
||||||
print(f"- Unable to find Kernel Debug Kit: {downloaded_kdk}")
|
logging.info(f"- Unable to find Kernel Debug Kit: {downloaded_kdk}")
|
||||||
raise Exception("Unable to find Kernel Debug Kit")
|
raise Exception("Unable to find Kernel Debug Kit")
|
||||||
self.kdk_path = kdk_path
|
self.kdk_path = kdk_path
|
||||||
print(f"- Found KDK at: {kdk_path}")
|
logging.info(f"- Found KDK at: {kdk_path}")
|
||||||
|
|
||||||
# Due to some IOHIDFamily oddities, we need to ensure their CodeSignature is retained
|
# Due to some IOHIDFamily oddities, we need to ensure their CodeSignature is retained
|
||||||
cs_path = Path(self.mount_location) / Path("System/Library/Extensions/IOHIDFamily.kext/Contents/PlugIns/IOHIDEventDriver.kext/Contents/_CodeSignature")
|
cs_path = Path(self.mount_location) / Path("System/Library/Extensions/IOHIDFamily.kext/Contents/PlugIns/IOHIDEventDriver.kext/Contents/_CodeSignature")
|
||||||
if save_hid_cs is True and cs_path.exists():
|
if save_hid_cs is True and cs_path.exists():
|
||||||
print("- Backing up IOHIDEventDriver CodeSignature")
|
logging.info("- Backing up IOHIDEventDriver CodeSignature")
|
||||||
# Note it's a folder, not a file
|
# Note it's a folder, not a file
|
||||||
utilities.elevated(["cp", "-r", cs_path, f"{self.constants.payload_path}/IOHIDEventDriver_CodeSignature.bak"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
utilities.elevated(["cp", "-r", cs_path, f"{self.constants.payload_path}/IOHIDEventDriver_CodeSignature.bak"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
|
||||||
print("- Merging KDK with Root Volume")
|
logging.info("- Merging KDK with Root Volume")
|
||||||
utilities.elevated(
|
utilities.elevated(
|
||||||
# Only merge '/System/Library/Extensions'
|
# Only merge '/System/Library/Extensions'
|
||||||
# 'Kernels' and 'KernelSupport' is wasted space for root patching (we don't care above dev kernels)
|
# 'Kernels' and 'KernelSupport' is wasted space for root patching (we don't care above dev kernels)
|
||||||
@@ -163,15 +200,15 @@ class PatchSysVolume:
|
|||||||
# During reversing, we found that kmutil uses this path to determine whether the KDK was successfully merged
|
# During reversing, we found that kmutil uses this path to determine whether the KDK was successfully merged
|
||||||
# Best to verify now before we cause any damage
|
# Best to verify now before we cause any damage
|
||||||
if not (Path(self.mount_location) / Path("System/Library/Extensions/System.kext/PlugIns/Libkern.kext/Libkern")).exists():
|
if not (Path(self.mount_location) / Path("System/Library/Extensions/System.kext/PlugIns/Libkern.kext/Libkern")).exists():
|
||||||
print("- Failed to merge KDK with Root Volume")
|
logging.info("- Failed to merge KDK with Root Volume")
|
||||||
raise Exception("Failed to merge KDK with Root Volume")
|
raise Exception("Failed to merge KDK with Root Volume")
|
||||||
print("- Successfully merged KDK with Root Volume")
|
logging.info("- Successfully merged KDK with Root Volume")
|
||||||
|
|
||||||
# Restore IOHIDEventDriver CodeSignature
|
# Restore IOHIDEventDriver CodeSignature
|
||||||
if save_hid_cs is True and Path(f"{self.constants.payload_path}/IOHIDEventDriver_CodeSignature.bak").exists():
|
if save_hid_cs is True and Path(f"{self.constants.payload_path}/IOHIDEventDriver_CodeSignature.bak").exists():
|
||||||
print("- Restoring IOHIDEventDriver CodeSignature")
|
logging.info("- Restoring IOHIDEventDriver CodeSignature")
|
||||||
if not cs_path.exists():
|
if not cs_path.exists():
|
||||||
print(" - CodeSignature folder missing, creating")
|
logging.info(" - CodeSignature folder missing, creating")
|
||||||
utilities.elevated(["mkdir", "-p", cs_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
utilities.elevated(["mkdir", "-p", cs_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
utilities.elevated(["cp", "-r", f"{self.constants.payload_path}/IOHIDEventDriver_CodeSignature.bak", cs_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
utilities.elevated(["cp", "-r", f"{self.constants.payload_path}/IOHIDEventDriver_CodeSignature.bak", cs_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
utilities.elevated(["rm", "-rf", f"{self.constants.payload_path}/IOHIDEventDriver_CodeSignature.bak"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
utilities.elevated(["rm", "-rf", f"{self.constants.payload_path}/IOHIDEventDriver_CodeSignature.bak"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
@@ -179,36 +216,36 @@ class PatchSysVolume:
|
|||||||
|
|
||||||
def unpatch_root_vol(self):
|
def unpatch_root_vol(self):
|
||||||
if self.constants.detected_os > os_data.os_data.catalina and self.root_supports_snapshot is True:
|
if self.constants.detected_os > os_data.os_data.catalina and self.root_supports_snapshot is True:
|
||||||
print("- Reverting to last signed APFS snapshot")
|
logging.info("- Reverting to last signed APFS snapshot")
|
||||||
result = utilities.elevated(["bless", "--mount", self.mount_location, "--bootefi", "--last-sealed-snapshot"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
result = utilities.elevated(["bless", "--mount", self.mount_location, "--bootefi", "--last-sealed-snapshot"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
print("- Unable to revert root volume patches")
|
logging.info("- Unable to revert root volume patches")
|
||||||
print("Reason for unpatch Failure:")
|
logging.info("Reason for unpatch Failure:")
|
||||||
print(result.stdout.decode())
|
logging.info(result.stdout.decode())
|
||||||
print("- Failed to revert snapshot via Apple's 'bless' command")
|
logging.info("- Failed to revert snapshot via Apple's 'bless' command")
|
||||||
else:
|
else:
|
||||||
self.clean_skylight_plugins()
|
self.clean_skylight_plugins()
|
||||||
self.delete_nonmetal_enforcement()
|
self.delete_nonmetal_enforcement()
|
||||||
self.clean_auxiliary_kc()
|
self.clean_auxiliary_kc()
|
||||||
self.constants.root_patcher_succeeded = True
|
self.constants.root_patcher_succeeded = True
|
||||||
print("- Unpatching complete")
|
logging.info("- Unpatching complete")
|
||||||
print("\nPlease reboot the machine for patches to take effect")
|
logging.info("\nPlease reboot the machine for patches to take effect")
|
||||||
|
|
||||||
def rebuild_snapshot(self):
|
def rebuild_snapshot(self):
|
||||||
if self.rebuild_kernel_collection() is True:
|
if self.rebuild_kernel_collection() is True:
|
||||||
self.update_preboot_kernel_cache()
|
self.update_preboot_kernel_cache()
|
||||||
self.rebuild_dyld_shared_cache()
|
self.rebuild_dyld_shared_cache()
|
||||||
if self.create_new_apfs_snapshot() is True:
|
if self.create_new_apfs_snapshot() is True:
|
||||||
print("- Patching complete")
|
logging.info("- Patching complete")
|
||||||
print("\nPlease reboot the machine for patches to take effect")
|
logging.info("\nPlease reboot the machine for patches to take effect")
|
||||||
if self.needs_kmutil_exemptions is True:
|
if self.needs_kmutil_exemptions is True:
|
||||||
print("Note: Apple will require you to open System Preferences -> Security to allow the new kernel extensions to be loaded")
|
logging.info("Note: Apple will require you to open System Preferences -> Security to allow the new kernel extensions to be loaded")
|
||||||
self.constants.root_patcher_succeeded = True
|
self.constants.root_patcher_succeeded = True
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
input("\nPress [ENTER] to continue")
|
input("\nPress [ENTER] to continue")
|
||||||
|
|
||||||
def rebuild_kernel_collection(self):
|
def rebuild_kernel_collection(self):
|
||||||
print("- Rebuilding Kernel Cache (This may take some time)")
|
logging.info("- Rebuilding Kernel Cache (This may take some time)")
|
||||||
if self.constants.detected_os > os_data.os_data.catalina:
|
if self.constants.detected_os > os_data.os_data.catalina:
|
||||||
# Base Arguments
|
# Base Arguments
|
||||||
args = ["kmutil", "install"]
|
args = ["kmutil", "install"]
|
||||||
@@ -255,7 +292,7 @@ class PatchSysVolume:
|
|||||||
if self.needs_kmutil_exemptions is True:
|
if self.needs_kmutil_exemptions is True:
|
||||||
# When installing to '/Library/Extensions', following args skip kext consent
|
# When installing to '/Library/Extensions', following args skip kext consent
|
||||||
# prompt in System Preferences when SIP's disabled
|
# prompt in System Preferences when SIP's disabled
|
||||||
print(" (You will get a prompt by System Preferences, ignore for now)")
|
logging.info(" (You will get a prompt by System Preferences, ignore for now)")
|
||||||
args.append("--no-authentication")
|
args.append("--no-authentication")
|
||||||
args.append("--no-authorization")
|
args.append("--no-authorization")
|
||||||
else:
|
else:
|
||||||
@@ -271,11 +308,11 @@ class PatchSysVolume:
|
|||||||
# - will return 31 on 'No binaries or codeless kexts were provided'
|
# - will return 31 on 'No binaries or codeless kexts were provided'
|
||||||
# - will return -10 if the volume is missing (ie. unmounted by another process)
|
# - will return -10 if the volume is missing (ie. unmounted by another process)
|
||||||
if result.returncode != 0 or (self.constants.detected_os < os_data.os_data.catalina and "KernelCache ID" not in result.stdout.decode()):
|
if result.returncode != 0 or (self.constants.detected_os < os_data.os_data.catalina and "KernelCache ID" not in result.stdout.decode()):
|
||||||
print("- Unable to build new kernel cache")
|
logging.info("- Unable to build new kernel cache")
|
||||||
print(f"\nReason for Patch Failure ({result.returncode}):")
|
logging.info(f"\nReason for Patch Failure ({result.returncode}):")
|
||||||
print(result.stdout.decode())
|
logging.info(result.stdout.decode())
|
||||||
print("")
|
logging.info("")
|
||||||
print("\nPlease reboot the machine to avoid potential issues rerunning the patcher")
|
logging.info("\nPlease reboot the machine to avoid potential issues rerunning the patcher")
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
input("Press [ENTER] to continue")
|
input("Press [ENTER] to continue")
|
||||||
return False
|
return False
|
||||||
@@ -284,11 +321,11 @@ class PatchSysVolume:
|
|||||||
# Force rebuild the Auxiliary KC
|
# Force rebuild the Auxiliary KC
|
||||||
result = utilities.elevated(["killall", "syspolicyd", "kernelmanagerd"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
result = utilities.elevated(["killall", "syspolicyd", "kernelmanagerd"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
print("- Unable to remove kernel extension policy files")
|
logging.info("- Unable to remove kernel extension policy files")
|
||||||
print(f"\nReason for Patch Failure ({result.returncode}):")
|
logging.info(f"\nReason for Patch Failure ({result.returncode}):")
|
||||||
print(result.stdout.decode())
|
logging.info(result.stdout.decode())
|
||||||
print("")
|
logging.info("")
|
||||||
print("\nPlease reboot the machine to avoid potential issues rerunning the patcher")
|
logging.info("\nPlease reboot the machine to avoid potential issues rerunning the patcher")
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
input("Press [ENTER] to continue")
|
input("Press [ENTER] to continue")
|
||||||
return False
|
return False
|
||||||
@@ -299,12 +336,12 @@ class PatchSysVolume:
|
|||||||
# Install RSRHelper utility to handle desynced KCs
|
# Install RSRHelper utility to handle desynced KCs
|
||||||
sys_patch_helpers.sys_patch_helpers(self.constants).install_rsr_repair_binary()
|
sys_patch_helpers.sys_patch_helpers(self.constants).install_rsr_repair_binary()
|
||||||
|
|
||||||
print("- Successfully built new kernel cache")
|
logging.info("- Successfully built new kernel cache")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def create_new_apfs_snapshot(self):
|
def create_new_apfs_snapshot(self):
|
||||||
if self.root_supports_snapshot is True:
|
if self.root_supports_snapshot is True:
|
||||||
print("- Creating new APFS snapshot")
|
logging.info("- Creating new APFS snapshot")
|
||||||
bless = utilities.elevated(
|
bless = utilities.elevated(
|
||||||
[
|
[
|
||||||
"bless",
|
"bless",
|
||||||
@@ -313,43 +350,43 @@ class PatchSysVolume:
|
|||||||
], stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
], stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
if bless.returncode != 0:
|
if bless.returncode != 0:
|
||||||
print("- Unable to create new snapshot")
|
logging.info("- Unable to create new snapshot")
|
||||||
print("Reason for snapshot failure:")
|
logging.info("Reason for snapshot failure:")
|
||||||
print(bless.stdout.decode())
|
logging.info(bless.stdout.decode())
|
||||||
if "Can't use last-sealed-snapshot or create-snapshot on non system volume" in bless.stdout.decode():
|
if "Can't use last-sealed-snapshot or create-snapshot on non system volume" in bless.stdout.decode():
|
||||||
print("- This is an APFS bug with Monterey and newer! Perform a clean installation to ensure your APFS volume is built correctly")
|
logging.info("- This is an APFS bug with Monterey and newer! Perform a clean installation to ensure your APFS volume is built correctly")
|
||||||
return False
|
return False
|
||||||
self.unmount_drive()
|
self.unmount_drive()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def unmount_drive(self):
|
def unmount_drive(self):
|
||||||
print("- Unmounting Root Volume (Don't worry if this fails)")
|
logging.info("- Unmounting Root Volume (Don't worry if this fails)")
|
||||||
utilities.elevated(["diskutil", "unmount", self.root_mount_path], stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
utilities.elevated(["diskutil", "unmount", self.root_mount_path], stdout=subprocess.PIPE).stdout.decode().strip().encode()
|
||||||
|
|
||||||
def rebuild_dyld_shared_cache(self):
|
def rebuild_dyld_shared_cache(self):
|
||||||
if self.constants.detected_os <= os_data.os_data.catalina:
|
if self.constants.detected_os <= os_data.os_data.catalina:
|
||||||
print("- Rebuilding dyld shared cache")
|
logging.info("- Rebuilding dyld shared cache")
|
||||||
utilities.process_status(utilities.elevated(["update_dyld_shared_cache", "-root", f"{self.mount_location}/"]))
|
utilities.process_status(utilities.elevated(["update_dyld_shared_cache", "-root", f"{self.mount_location}/"]))
|
||||||
|
|
||||||
def update_preboot_kernel_cache(self):
|
def update_preboot_kernel_cache(self):
|
||||||
if self.constants.detected_os == os_data.os_data.catalina:
|
if self.constants.detected_os == os_data.os_data.catalina:
|
||||||
print("- Rebuilding preboot kernel cache")
|
logging.info("- Rebuilding preboot kernel cache")
|
||||||
utilities.process_status(utilities.elevated(["kcditto"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["kcditto"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
def clean_skylight_plugins(self):
|
def clean_skylight_plugins(self):
|
||||||
if (Path(self.mount_application_support) / Path("SkyLightPlugins/")).exists():
|
if (Path(self.mount_application_support) / Path("SkyLightPlugins/")).exists():
|
||||||
print("- Found SkylightPlugins folder, removing old plugins")
|
logging.info("- Found SkylightPlugins folder, removing old plugins")
|
||||||
utilities.process_status(utilities.elevated(["rm", "-Rf", f"{self.mount_application_support}/SkyLightPlugins"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["rm", "-Rf", f"{self.mount_application_support}/SkyLightPlugins"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
utilities.process_status(utilities.elevated(["mkdir", f"{self.mount_application_support}/SkyLightPlugins"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["mkdir", f"{self.mount_application_support}/SkyLightPlugins"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
else:
|
else:
|
||||||
print("- Creating SkylightPlugins folder")
|
logging.info("- Creating SkylightPlugins folder")
|
||||||
utilities.process_status(utilities.elevated(["mkdir", "-p", f"{self.mount_application_support}/SkyLightPlugins/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["mkdir", "-p", f"{self.mount_application_support}/SkyLightPlugins/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
def delete_nonmetal_enforcement(self):
|
def delete_nonmetal_enforcement(self):
|
||||||
for arg in ["useMetal", "useIOP"]:
|
for arg in ["useMetal", "useIOP"]:
|
||||||
result = subprocess.run(["defaults", "read", "/Library/Preferences/com.apple.CoreDisplay", arg], stdout=subprocess.PIPE).stdout.decode("utf-8").strip()
|
result = subprocess.run(["defaults", "read", "/Library/Preferences/com.apple.CoreDisplay", arg], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.decode("utf-8").strip()
|
||||||
if result in ["0", "false", "1", "true"]:
|
if result in ["0", "false", "1", "true"]:
|
||||||
print(f"- Removing non-Metal Enforcement Preference: {arg}")
|
logging.info(f"- Removing non-Metal Enforcement Preference: {arg}")
|
||||||
utilities.elevated(["defaults", "delete", "/Library/Preferences/com.apple.CoreDisplay", arg])
|
utilities.elevated(["defaults", "delete", "/Library/Preferences/com.apple.CoreDisplay", arg])
|
||||||
|
|
||||||
def clean_auxiliary_kc(self):
|
def clean_auxiliary_kc(self):
|
||||||
@@ -360,7 +397,7 @@ class PatchSysVolume:
|
|||||||
if self.constants.detected_os < os_data.os_data.big_sur:
|
if self.constants.detected_os < os_data.os_data.big_sur:
|
||||||
return
|
return
|
||||||
|
|
||||||
print("- Cleaning Auxiliary Kernel Collection")
|
logging.info("- Cleaning Auxiliary Kernel Collection")
|
||||||
oclp_path = "/System/Library/CoreServices/OpenCore-Legacy-Patcher.plist"
|
oclp_path = "/System/Library/CoreServices/OpenCore-Legacy-Patcher.plist"
|
||||||
if Path(oclp_path).exists():
|
if Path(oclp_path).exists():
|
||||||
oclp_plist_data = plistlib.load(Path(oclp_path).open("rb"))
|
oclp_plist_data = plistlib.load(Path(oclp_path).open("rb"))
|
||||||
@@ -388,7 +425,7 @@ class PatchSysVolume:
|
|||||||
for file in Path("/Library/Extensions").glob("*.kext"):
|
for file in Path("/Library/Extensions").glob("*.kext"):
|
||||||
try:
|
try:
|
||||||
if datetime.fromtimestamp(file.stat().st_mtime) < datetime(2021, 10, 1):
|
if datetime.fromtimestamp(file.stat().st_mtime) < datetime(2021, 10, 1):
|
||||||
print(f" - Relocating {file.name} kext to {relocation_path}")
|
logging.info(f" - Relocating {file.name} kext to {relocation_path}")
|
||||||
if Path(relocation_path) / Path(file.name).exists():
|
if Path(relocation_path) / Path(file.name).exists():
|
||||||
utilities.elevated(["rm", "-Rf", relocation_path / Path(file.name)])
|
utilities.elevated(["rm", "-Rf", relocation_path / Path(file.name)])
|
||||||
utilities.elevated(["mv", file, relocation_path])
|
utilities.elevated(["mv", file, relocation_path])
|
||||||
@@ -402,7 +439,7 @@ class PatchSysVolume:
|
|||||||
file_name = "OpenCore-Legacy-Patcher.plist"
|
file_name = "OpenCore-Legacy-Patcher.plist"
|
||||||
destination_path_file = f"{destination_path}/{file_name}"
|
destination_path_file = f"{destination_path}/{file_name}"
|
||||||
if sys_patch_helpers.sys_patch_helpers(self.constants).generate_patchset_plist(patchset, file_name, self.kdk_path):
|
if sys_patch_helpers.sys_patch_helpers(self.constants).generate_patchset_plist(patchset, file_name, self.kdk_path):
|
||||||
print("- Writing patchset information to Root Volume")
|
logging.info("- Writing patchset information to Root Volume")
|
||||||
if Path(destination_path_file).exists():
|
if Path(destination_path_file).exists():
|
||||||
utilities.process_status(utilities.elevated(["rm", destination_path_file], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["rm", destination_path_file], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
utilities.process_status(utilities.elevated(["cp", f"{self.constants.payload_path}/{file_name}", destination_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["cp", f"{self.constants.payload_path}/{file_name}", destination_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
@@ -429,7 +466,7 @@ class PatchSysVolume:
|
|||||||
|
|
||||||
updated_install_location = str(self.mount_location_data) + "/Library/Extensions"
|
updated_install_location = str(self.mount_location_data) + "/Library/Extensions"
|
||||||
|
|
||||||
print(f" - Adding AuxKC support to {install_file}")
|
logging.info(f" - Adding AuxKC support to {install_file}")
|
||||||
plist_path = Path(Path(source_folder_path) / Path(install_file) / Path("Contents/Info.plist"))
|
plist_path = Path(Path(source_folder_path) / Path(install_file) / Path("Contents/Info.plist"))
|
||||||
plist_data = plistlib.load((plist_path).open("rb"))
|
plist_data = plistlib.load((plist_path).open("rb"))
|
||||||
|
|
||||||
@@ -466,11 +503,11 @@ class PatchSysVolume:
|
|||||||
except PermissionError:
|
except PermissionError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
print(f" - {kext_name} requires authentication in System Preferences")
|
logging.info(f" - {kext_name} requires authentication in System Preferences")
|
||||||
self.constants.needs_to_open_preferences = True # Notify in GUI to open System Preferences
|
self.constants.needs_to_open_preferences = True # Notify in GUI to open System Preferences
|
||||||
|
|
||||||
def patch_root_vol(self):
|
def patch_root_vol(self):
|
||||||
print(f"- Running patches for {self.model}")
|
logging.info(f"- Running patches for {self.model}")
|
||||||
if self.patch_set_dictionary != {}:
|
if self.patch_set_dictionary != {}:
|
||||||
self.execute_patchset(self.patch_set_dictionary)
|
self.execute_patchset(self.patch_set_dictionary)
|
||||||
else:
|
else:
|
||||||
@@ -485,10 +522,10 @@ class PatchSysVolume:
|
|||||||
source_files_path = str(self.constants.payload_local_binaries_root_path)
|
source_files_path = str(self.constants.payload_local_binaries_root_path)
|
||||||
self.preflight_checks(required_patches, source_files_path)
|
self.preflight_checks(required_patches, source_files_path)
|
||||||
for patch in required_patches:
|
for patch in required_patches:
|
||||||
print("- Installing Patchset: " + patch)
|
logging.info("- Installing Patchset: " + patch)
|
||||||
if "Remove" in required_patches[patch]:
|
if "Remove" in required_patches[patch]:
|
||||||
for remove_patch_directory in required_patches[patch]["Remove"]:
|
for remove_patch_directory in required_patches[patch]["Remove"]:
|
||||||
print("- Remove Files at: " + remove_patch_directory)
|
logging.info("- Remove Files at: " + remove_patch_directory)
|
||||||
for remove_patch_file in required_patches[patch]["Remove"][remove_patch_directory]:
|
for remove_patch_file in required_patches[patch]["Remove"][remove_patch_directory]:
|
||||||
destination_folder_path = str(self.mount_location) + remove_patch_directory
|
destination_folder_path = str(self.mount_location) + remove_patch_directory
|
||||||
self.remove_file(destination_folder_path, remove_patch_file)
|
self.remove_file(destination_folder_path, remove_patch_file)
|
||||||
@@ -497,7 +534,7 @@ class PatchSysVolume:
|
|||||||
for method_install in ["Install", "Install Non-Root"]:
|
for method_install in ["Install", "Install Non-Root"]:
|
||||||
if method_install in required_patches[patch]:
|
if method_install in required_patches[patch]:
|
||||||
for install_patch_directory in list(required_patches[patch][method_install]):
|
for install_patch_directory in list(required_patches[patch][method_install]):
|
||||||
print(f"- Handling Installs in: {install_patch_directory}")
|
logging.info(f"- Handling Installs in: {install_patch_directory}")
|
||||||
for install_file in list(required_patches[patch][method_install][install_patch_directory]):
|
for install_file in list(required_patches[patch][method_install][install_patch_directory]):
|
||||||
source_folder_path = source_files_path + "/" + required_patches[patch][method_install][install_patch_directory][install_file] + install_patch_directory
|
source_folder_path = source_files_path + "/" + required_patches[patch][method_install][install_patch_directory][install_file] + install_patch_directory
|
||||||
if method_install == "Install":
|
if method_install == "Install":
|
||||||
@@ -526,10 +563,10 @@ class PatchSysVolume:
|
|||||||
# Some processes need sudo, however we cannot directly call sudo in some scenarios
|
# Some processes need sudo, however we cannot directly call sudo in some scenarios
|
||||||
# Instead, call elevated funtion if string's boolean is True
|
# Instead, call elevated funtion if string's boolean is True
|
||||||
if required_patches[patch]["Processes"][process] is True:
|
if required_patches[patch]["Processes"][process] is True:
|
||||||
print(f"- Running Process as Root:\n{process}")
|
logging.info(f"- Running Process as Root:\n{process}")
|
||||||
utilities.process_status(utilities.elevated(process.split(" "), stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(process.split(" "), stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
else:
|
else:
|
||||||
print(f"- Running Process:\n{process}")
|
logging.info(f"- Running Process:\n{process}")
|
||||||
utilities.process_status(subprocess.run(process, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True))
|
utilities.process_status(subprocess.run(process, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True))
|
||||||
if any(x in required_patches for x in ["AMD Legacy GCN", "AMD Legacy Polaris", "AMD Legacy Vega"]):
|
if any(x in required_patches for x in ["AMD Legacy GCN", "AMD Legacy Polaris", "AMD Legacy Vega"]):
|
||||||
sys_patch_helpers.sys_patch_helpers(self.constants).disable_window_server_caching()
|
sys_patch_helpers.sys_patch_helpers(self.constants).disable_window_server_caching()
|
||||||
@@ -538,7 +575,7 @@ class PatchSysVolume:
|
|||||||
self.write_patchset(required_patches)
|
self.write_patchset(required_patches)
|
||||||
|
|
||||||
def preflight_checks(self, required_patches, source_files_path):
|
def preflight_checks(self, required_patches, source_files_path):
|
||||||
print("- Running Preflight Checks before patching")
|
logging.info("- Running Preflight Checks before patching")
|
||||||
|
|
||||||
# Make sure old SkyLight plugins aren't being used
|
# Make sure old SkyLight plugins aren't being used
|
||||||
self.clean_skylight_plugins()
|
self.clean_skylight_plugins()
|
||||||
@@ -567,7 +604,7 @@ class PatchSysVolume:
|
|||||||
should_save_cs = True
|
should_save_cs = True
|
||||||
self.merge_kdk_with_root(save_hid_cs=should_save_cs)
|
self.merge_kdk_with_root(save_hid_cs=should_save_cs)
|
||||||
|
|
||||||
print("- Finished Preflight, starting patching")
|
logging.info("- Finished Preflight, starting patching")
|
||||||
|
|
||||||
def install_new_file(self, source_folder, destination_folder, file_name):
|
def install_new_file(self, source_folder, destination_folder, file_name):
|
||||||
# .frameworks are merged
|
# .frameworks are merged
|
||||||
@@ -575,36 +612,36 @@ class PatchSysVolume:
|
|||||||
file_name_str = str(file_name)
|
file_name_str = str(file_name)
|
||||||
|
|
||||||
if not Path(destination_folder).exists():
|
if not Path(destination_folder).exists():
|
||||||
print(f" - Skipping {file_name}, cannot locate {source_folder}")
|
logging.info(f" - Skipping {file_name}, cannot locate {source_folder}")
|
||||||
return
|
return
|
||||||
|
|
||||||
if file_name_str.endswith(".framework"):
|
if file_name_str.endswith(".framework"):
|
||||||
# merge with rsync
|
# merge with rsync
|
||||||
print(f" - Installing: {file_name}")
|
logging.info(f" - Installing: {file_name}")
|
||||||
utilities.elevated(["rsync", "-r", "-i", "-a", f"{source_folder}/{file_name}", f"{destination_folder}/"], stdout=subprocess.PIPE)
|
utilities.elevated(["rsync", "-r", "-i", "-a", f"{source_folder}/{file_name}", f"{destination_folder}/"], stdout=subprocess.PIPE)
|
||||||
self.fix_permissions(destination_folder + "/" + file_name)
|
self.fix_permissions(destination_folder + "/" + file_name)
|
||||||
elif Path(source_folder + "/" + file_name_str).is_dir():
|
elif Path(source_folder + "/" + file_name_str).is_dir():
|
||||||
# Applicable for .kext, .app, .plugin, .bundle, all of which are directories
|
# Applicable for .kext, .app, .plugin, .bundle, all of which are directories
|
||||||
if Path(destination_folder + "/" + file_name).exists():
|
if Path(destination_folder + "/" + file_name).exists():
|
||||||
print(f" - Found existing {file_name}, overwriting...")
|
logging.info(f" - Found existing {file_name}, overwriting...")
|
||||||
utilities.process_status(utilities.elevated(["rm", "-R", f"{destination_folder}/{file_name}"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["rm", "-R", f"{destination_folder}/{file_name}"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
else:
|
else:
|
||||||
print(f" - Installing: {file_name}")
|
logging.info(f" - Installing: {file_name}")
|
||||||
utilities.process_status(utilities.elevated(["cp", "-R", f"{source_folder}/{file_name}", destination_folder], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["cp", "-R", f"{source_folder}/{file_name}", destination_folder], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
self.fix_permissions(destination_folder + "/" + file_name)
|
self.fix_permissions(destination_folder + "/" + file_name)
|
||||||
else:
|
else:
|
||||||
# Assume it's an individual file, replace as normal
|
# Assume it's an individual file, replace as normal
|
||||||
if Path(destination_folder + "/" + file_name).exists():
|
if Path(destination_folder + "/" + file_name).exists():
|
||||||
print(f" - Found existing {file_name}, overwriting...")
|
logging.info(f" - Found existing {file_name}, overwriting...")
|
||||||
utilities.process_status(utilities.elevated(["rm", f"{destination_folder}/{file_name}"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["rm", f"{destination_folder}/{file_name}"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
else:
|
else:
|
||||||
print(f" - Installing: {file_name}")
|
logging.info(f" - Installing: {file_name}")
|
||||||
utilities.process_status(utilities.elevated(["cp", f"{source_folder}/{file_name}", destination_folder], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["cp", f"{source_folder}/{file_name}", destination_folder], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
self.fix_permissions(destination_folder + "/" + file_name)
|
self.fix_permissions(destination_folder + "/" + file_name)
|
||||||
|
|
||||||
def remove_file(self, destination_folder, file_name):
|
def remove_file(self, destination_folder, file_name):
|
||||||
if Path(destination_folder + "/" + file_name).exists():
|
if Path(destination_folder + "/" + file_name).exists():
|
||||||
print(f" - Removing: {file_name}")
|
logging.info(f" - Removing: {file_name}")
|
||||||
if Path(destination_folder + "/" + file_name).is_dir():
|
if Path(destination_folder + "/" + file_name).is_dir():
|
||||||
utilities.process_status(utilities.elevated(["rm", "-R", f"{destination_folder}/{file_name}"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["rm", "-R", f"{destination_folder}/{file_name}"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
else:
|
else:
|
||||||
@@ -624,87 +661,63 @@ class PatchSysVolume:
|
|||||||
|
|
||||||
def check_files(self):
|
def check_files(self):
|
||||||
if Path(self.constants.payload_local_binaries_root_path).exists():
|
if Path(self.constants.payload_local_binaries_root_path).exists():
|
||||||
print("- Found local Apple Binaries")
|
logging.info("- Local PatcherSupportPkg resources available, continuing...")
|
||||||
if self.constants.gui_mode is False:
|
return True
|
||||||
patch_input = input("Would you like to redownload?(y/n): ")
|
|
||||||
if patch_input in {"y", "Y", "yes", "Yes"}:
|
|
||||||
shutil.rmtree(Path(self.constants.payload_local_binaries_root_path))
|
|
||||||
output = self.download_files()
|
|
||||||
else:
|
|
||||||
output = True
|
|
||||||
else:
|
|
||||||
output = self.download_files()
|
|
||||||
else:
|
|
||||||
output = self.download_files()
|
|
||||||
return output
|
|
||||||
|
|
||||||
def download_files(self):
|
if Path(self.constants.payload_local_binaries_root_path_zip).exists():
|
||||||
if self.constants.cli_mode is True:
|
logging.info("- Local PatcherSupportPkg resources available, unzipping...")
|
||||||
download_result, link = sys_patch_download.grab_patcher_support_pkg(self.constants).download_files()
|
logging.info("- Unzipping binaries...")
|
||||||
else:
|
|
||||||
download_result = True
|
|
||||||
link = sys_patch_download.grab_patcher_support_pkg(self.constants).generate_pkg_link()
|
|
||||||
|
|
||||||
if download_result and self.constants.payload_local_binaries_root_path_zip.exists():
|
|
||||||
print("- Unzipping binaries...")
|
|
||||||
utilities.process_status(subprocess.run(["ditto", "-V", "-x", "-k", "--sequesterRsrc", "--rsrc", self.constants.payload_local_binaries_root_path_zip, self.constants.payload_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(subprocess.run(["ditto", "-V", "-x", "-k", "--sequesterRsrc", "--rsrc", self.constants.payload_local_binaries_root_path_zip, self.constants.payload_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
print("- Binaries downloaded to:")
|
return True
|
||||||
print(self.constants.payload_path)
|
|
||||||
return self.constants.payload_local_binaries_root_path
|
logging.info("- PatcherSupportPkg resources missing, Patcher likely corrupted!!!")
|
||||||
else:
|
return False
|
||||||
if self.constants.gui_mode is True:
|
|
||||||
print("- Download failed, please verify the below link work:")
|
|
||||||
print(link)
|
|
||||||
print("\nIf you continue to have issues, try using the Offline builds")
|
|
||||||
print("located on Github next to the other builds")
|
|
||||||
else:
|
|
||||||
input("\nPress enter to continue")
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Entry Function
|
# Entry Function
|
||||||
def start_patch(self):
|
def start_patch(self):
|
||||||
print("- Starting Patch Process")
|
logging.info("- Starting Patch Process")
|
||||||
print(f"- Determining Required Patch set for Darwin {self.constants.detected_os}")
|
logging.info(f"- Determining Required Patch set for Darwin {self.constants.detected_os}")
|
||||||
self.patch_set_dictionary = sys_patch_detect.detect_root_patch(self.computer.real_model, self.constants).generate_patchset(self.hardware_details)
|
self.patch_set_dictionary = sys_patch_detect.detect_root_patch(self.computer.real_model, self.constants).generate_patchset(self.hardware_details)
|
||||||
|
|
||||||
if self.patch_set_dictionary == {}:
|
if self.patch_set_dictionary == {}:
|
||||||
change_menu = None
|
change_menu = None
|
||||||
print("- No Root Patches required for your machine!")
|
logging.info("- No Root Patches required for your machine!")
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
input("\nPress [ENTER] to return to the main menu: ")
|
input("\nPress [ENTER] to return to the main menu: ")
|
||||||
elif self.constants.gui_mode is False:
|
elif self.constants.gui_mode is False:
|
||||||
change_menu = input("Would you like to continue with Root Volume Patching?(y/n): ")
|
change_menu = input("Would you like to continue with Root Volume Patching?(y/n): ")
|
||||||
else:
|
else:
|
||||||
change_menu = "y"
|
change_menu = "y"
|
||||||
print("- Continuing root patching")
|
logging.info("- Continuing root patching")
|
||||||
if change_menu in ["y", "Y"]:
|
if change_menu in ["y", "Y"]:
|
||||||
print("- Verifying whether Root Patching possible")
|
logging.info("- Verifying whether Root Patching possible")
|
||||||
if sys_patch_detect.detect_root_patch(self.computer.real_model, self.constants).verify_patch_allowed(print_errors=not self.constants.wxpython_variant) is True:
|
if sys_patch_detect.detect_root_patch(self.computer.real_model, self.constants).verify_patch_allowed(print_errors=not self.constants.wxpython_variant) is True:
|
||||||
print("- Patcher is capable of patching")
|
logging.info("- Patcher is capable of patching")
|
||||||
if self.check_files():
|
if self.check_files():
|
||||||
if self.mount_root_vol() is True:
|
if self.mount_root_vol() is True:
|
||||||
self.patch_root_vol()
|
self.patch_root_vol()
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
input("\nPress [ENTER] to return to the main menu")
|
input("\nPress [ENTER] to return to the main menu")
|
||||||
else:
|
else:
|
||||||
print("- Recommend rebooting the machine and trying to patch again")
|
logging.info("- Recommend rebooting the machine and trying to patch again")
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
input("- Press [ENTER] to exit: ")
|
input("- Press [ENTER] to exit: ")
|
||||||
elif self.constants.gui_mode is False:
|
elif self.constants.gui_mode is False:
|
||||||
input("\nPress [ENTER] to return to the main menu: ")
|
input("\nPress [ENTER] to return to the main menu: ")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print("- Returning to main menu")
|
logging.info("- Returning to main menu")
|
||||||
|
|
||||||
def start_unpatch(self):
|
def start_unpatch(self):
|
||||||
print("- Starting Unpatch Process")
|
logging.info("- Starting Unpatch Process")
|
||||||
if sys_patch_detect.detect_root_patch(self.computer.real_model, self.constants).verify_patch_allowed(print_errors=True) is True:
|
if sys_patch_detect.detect_root_patch(self.computer.real_model, self.constants).verify_patch_allowed(print_errors=True) is True:
|
||||||
if self.mount_root_vol() is True:
|
if self.mount_root_vol() is True:
|
||||||
self.unpatch_root_vol()
|
self.unpatch_root_vol()
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
input("\nPress [ENTER] to return to the main menu")
|
input("\nPress [ENTER] to return to the main menu")
|
||||||
else:
|
else:
|
||||||
print("- Recommend rebooting the machine and trying to patch again")
|
logging.info("- Recommend rebooting the machine and trying to patch again")
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
input("- Press [ENTER] to exit: ")
|
input("- Press [ENTER] to exit: ")
|
||||||
elif self.constants.gui_mode is False:
|
elif self.constants.gui_mode is False:
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ from pathlib import Path
|
|||||||
import plistlib
|
import plistlib
|
||||||
import subprocess
|
import subprocess
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from resources import utilities, updates, global_settings
|
import logging
|
||||||
|
from resources import utilities, updates, global_settings, network_handler
|
||||||
from resources.sys_patch import sys_patch_detect
|
from resources.sys_patch import sys_patch_detect
|
||||||
from resources.gui import gui_main
|
from resources.gui import gui_main
|
||||||
|
|
||||||
@@ -23,23 +24,23 @@ class AutomaticSysPatch:
|
|||||||
|
|
||||||
|
|
||||||
def start_auto_patch(self):
|
def start_auto_patch(self):
|
||||||
print("- Starting Automatic Patching")
|
logging.info("- Starting Automatic Patching")
|
||||||
if self.constants.wxpython_variant is False:
|
if self.constants.wxpython_variant is False:
|
||||||
print("- Auto Patch option is not supported on TUI, please use GUI")
|
logging.info("- Auto Patch option is not supported on TUI, please use GUI")
|
||||||
return
|
return
|
||||||
|
|
||||||
if utilities.check_seal() is True:
|
if utilities.check_seal() is True:
|
||||||
print("- Detected Snapshot seal intact, detecting patches")
|
logging.info("- Detected Snapshot seal intact, detecting patches")
|
||||||
patches = sys_patch_detect.detect_root_patch(self.constants.computer.real_model, self.constants).detect_patch_set()
|
patches = sys_patch_detect.detect_root_patch(self.constants.computer.real_model, self.constants).detect_patch_set()
|
||||||
if not any(not patch.startswith("Settings") and not patch.startswith("Validation") and patches[patch] is True for patch in patches):
|
if not any(not patch.startswith("Settings") and not patch.startswith("Validation") and patches[patch] is True for patch in patches):
|
||||||
patches = []
|
patches = []
|
||||||
if patches:
|
if patches:
|
||||||
print("- Detected applicable patches, determining whether possible to patch")
|
logging.info("- Detected applicable patches, determining whether possible to patch")
|
||||||
if patches["Validation: Patching Possible"] is False:
|
if patches["Validation: Patching Possible"] is False:
|
||||||
print("- Cannot run patching")
|
logging.info("- Cannot run patching")
|
||||||
return
|
return
|
||||||
|
|
||||||
print("- Determined patching is possible, checking for OCLP updates")
|
logging.info("- Determined patching is possible, checking for OCLP updates")
|
||||||
patch_string = ""
|
patch_string = ""
|
||||||
for patch in patches:
|
for patch in patches:
|
||||||
if patches[patch] is True and not patch.startswith("Settings") and not patch.startswith("Validation"):
|
if patches[patch] is True and not patch.startswith("Settings") and not patch.startswith("Validation"):
|
||||||
@@ -47,14 +48,14 @@ class AutomaticSysPatch:
|
|||||||
# Check for updates
|
# Check for updates
|
||||||
dict = updates.check_binary_updates(self.constants).check_binary_updates()
|
dict = updates.check_binary_updates(self.constants).check_binary_updates()
|
||||||
if not dict:
|
if not dict:
|
||||||
print("- No new binaries found on Github, proceeding with patching")
|
logging.info("- No new binaries found on Github, proceeding with patching")
|
||||||
if self.constants.launcher_script is None:
|
if self.constants.launcher_script is None:
|
||||||
args_string = f"'{self.constants.launcher_binary}' --gui_patch"
|
args_string = f"'{self.constants.launcher_binary}' --gui_patch"
|
||||||
else:
|
else:
|
||||||
args_string = f"{self.constants.launcher_binary} {self.constants.launcher_script} --gui_patch"
|
args_string = f"{self.constants.launcher_binary} {self.constants.launcher_script} --gui_patch"
|
||||||
|
|
||||||
warning_str = ""
|
warning_str = ""
|
||||||
if utilities.verify_network_connection("https://api.github.com/repos/dortania/OpenCore-Legacy-Patcher/releases/latest") is False:
|
if network_handler.NetworkUtilities("https://api.github.com/repos/dortania/OpenCore-Legacy-Patcher/releases/latest").verify_network_connection() is False:
|
||||||
warning_str = f"""\n\nWARNING: We're unable to verify whether there are any new releases of OpenCore Legacy Patcher on Github. Be aware that you may be using an outdated version for this OS. If you're unsure, verify on Github that OpenCore Legacy Patcher {self.constants.patcher_version} is the latest official release"""
|
warning_str = f"""\n\nWARNING: We're unable to verify whether there are any new releases of OpenCore Legacy Patcher on Github. Be aware that you may be using an outdated version for this OS. If you're unsure, verify on Github that OpenCore Legacy Patcher {self.constants.patcher_version} is the latest official release"""
|
||||||
|
|
||||||
args = [
|
args = [
|
||||||
@@ -87,7 +88,7 @@ class AutomaticSysPatch:
|
|||||||
for key in dict:
|
for key in dict:
|
||||||
version = dict[key]["Version"]
|
version = dict[key]["Version"]
|
||||||
github_link = dict[key]["Github Link"]
|
github_link = dict[key]["Github Link"]
|
||||||
print(f"- Found new version: {version}")
|
logging.info(f"- Found new version: {version}")
|
||||||
|
|
||||||
# launch osascript to ask user if they want to apply the update
|
# launch osascript to ask user if they want to apply the update
|
||||||
# if yes, open the link in the default browser
|
# if yes, open the link in the default browser
|
||||||
@@ -108,29 +109,29 @@ class AutomaticSysPatch:
|
|||||||
|
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
print("- No patches detected")
|
logging.info("- No patches detected")
|
||||||
else:
|
else:
|
||||||
print("- Detected Snapshot seal not intact, skipping")
|
logging.info("- Detected Snapshot seal not intact, skipping")
|
||||||
|
|
||||||
if self.determine_if_versions_match() is False:
|
if self.determine_if_versions_match() is False:
|
||||||
self.determine_if_boot_matches()
|
self.determine_if_boot_matches()
|
||||||
|
|
||||||
|
|
||||||
def determine_if_versions_match(self):
|
def determine_if_versions_match(self):
|
||||||
print("- Checking booted vs installed OCLP Build")
|
logging.info("- Checking booted vs installed OCLP Build")
|
||||||
if self.constants.computer.oclp_version is None:
|
if self.constants.computer.oclp_version is None:
|
||||||
print("- Booted version not found")
|
logging.info("- Booted version not found")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.constants.computer.oclp_version == self.constants.patcher_version:
|
if self.constants.computer.oclp_version == self.constants.patcher_version:
|
||||||
print("- Versions match")
|
logging.info("- Versions match")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check if installed version is newer than booted version
|
# Check if installed version is newer than booted version
|
||||||
if updates.check_binary_updates(self.constants).check_if_build_newer(
|
if updates.check_binary_updates(self.constants).check_if_build_newer(
|
||||||
self.constants.computer.oclp_version.split("."), self.constants.patcher_version.split(".")
|
self.constants.computer.oclp_version.split("."), self.constants.patcher_version.split(".")
|
||||||
) is True:
|
) is True:
|
||||||
print("- Installed version is newer than booted version")
|
logging.info("- Installed version is newer than booted version")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
args = [
|
args = [
|
||||||
@@ -145,7 +146,7 @@ class AutomaticSysPatch:
|
|||||||
stderr=subprocess.STDOUT
|
stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
if output.returncode == 0:
|
if output.returncode == 0:
|
||||||
print("- Launching GUI's Build/Install menu")
|
logging.info("- Launching GUI's Build/Install menu")
|
||||||
self.constants.start_build_install = True
|
self.constants.start_build_install = True
|
||||||
gui_main.wx_python_gui(self.constants).main_menu(None)
|
gui_main.wx_python_gui(self.constants).main_menu(None)
|
||||||
|
|
||||||
@@ -159,31 +160,31 @@ class AutomaticSysPatch:
|
|||||||
# If we determine them to be mismatched, notify the user
|
# If we determine them to be mismatched, notify the user
|
||||||
# and ask if they want to install to install to disk
|
# and ask if they want to install to install to disk
|
||||||
|
|
||||||
print("- Determining if macOS drive matches boot drive")
|
logging.info("- Determining if macOS drive matches boot drive")
|
||||||
should_notify = global_settings.global_settings().read_property("AutoPatch_Notify_Mismatched_Disks")
|
should_notify = global_settings.global_settings().read_property("AutoPatch_Notify_Mismatched_Disks")
|
||||||
if should_notify is False:
|
if should_notify is False:
|
||||||
print("- Skipping due to user preference")
|
logging.info("- Skipping due to user preference")
|
||||||
return
|
return
|
||||||
if self.constants.host_is_hackintosh is True:
|
if self.constants.host_is_hackintosh is True:
|
||||||
print("- Skipping due to hackintosh")
|
logging.info("- Skipping due to hackintosh")
|
||||||
return
|
return
|
||||||
if not self.constants.booted_oc_disk:
|
if not self.constants.booted_oc_disk:
|
||||||
print("- Failed to find disk OpenCore launched from")
|
logging.info("- Failed to find disk OpenCore launched from")
|
||||||
return
|
return
|
||||||
|
|
||||||
root_disk = self.constants.booted_oc_disk.strip("disk")
|
root_disk = self.constants.booted_oc_disk.strip("disk")
|
||||||
root_disk = "disk" + root_disk.split("s")[0]
|
root_disk = "disk" + root_disk.split("s")[0]
|
||||||
|
|
||||||
print(f" - Boot Drive: {self.constants.booted_oc_disk} ({root_disk})")
|
logging.info(f" - Boot Drive: {self.constants.booted_oc_disk} ({root_disk})")
|
||||||
macOS_disk = utilities.get_disk_path()
|
macOS_disk = utilities.get_disk_path()
|
||||||
print(f" - macOS Drive: {macOS_disk}")
|
logging.info(f" - macOS Drive: {macOS_disk}")
|
||||||
physical_stores = utilities.find_apfs_physical_volume(macOS_disk)
|
physical_stores = utilities.find_apfs_physical_volume(macOS_disk)
|
||||||
print(f" - APFS Physical Stores: {physical_stores}")
|
logging.info(f" - APFS Physical Stores: {physical_stores}")
|
||||||
|
|
||||||
disk_match = False
|
disk_match = False
|
||||||
for disk in physical_stores:
|
for disk in physical_stores:
|
||||||
if root_disk in disk:
|
if root_disk in disk:
|
||||||
print(f"- Boot drive matches macOS drive ({disk})")
|
logging.info(f"- Boot drive matches macOS drive ({disk})")
|
||||||
disk_match = True
|
disk_match = True
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -191,15 +192,15 @@ class AutomaticSysPatch:
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Check if OpenCore is on a USB drive
|
# Check if OpenCore is on a USB drive
|
||||||
print("- Boot Drive does not match macOS drive, checking if OpenCore is on a USB drive")
|
logging.info("- Boot Drive does not match macOS drive, checking if OpenCore is on a USB drive")
|
||||||
|
|
||||||
disk_info = plistlib.loads(subprocess.run(["diskutil", "info", "-plist", root_disk], stdout=subprocess.PIPE).stdout)
|
disk_info = plistlib.loads(subprocess.run(["diskutil", "info", "-plist", root_disk], stdout=subprocess.PIPE).stdout)
|
||||||
try:
|
try:
|
||||||
if disk_info["Ejectable"] is False:
|
if disk_info["Ejectable"] is False:
|
||||||
print("- Boot Disk is not removable, skipping prompt")
|
logging.info("- Boot Disk is not removable, skipping prompt")
|
||||||
return
|
return
|
||||||
|
|
||||||
print("- Boot Disk is ejectable, prompting user to install to internal")
|
logging.info("- Boot Disk is ejectable, prompting user to install to internal")
|
||||||
|
|
||||||
args = [
|
args = [
|
||||||
"osascript",
|
"osascript",
|
||||||
@@ -213,12 +214,12 @@ class AutomaticSysPatch:
|
|||||||
stderr=subprocess.STDOUT
|
stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
if output.returncode == 0:
|
if output.returncode == 0:
|
||||||
print("- Launching GUI's Build/Install menu")
|
logging.info("- Launching GUI's Build/Install menu")
|
||||||
self.constants.start_build_install = True
|
self.constants.start_build_install = True
|
||||||
gui_main.wx_python_gui(self.constants).main_menu(None)
|
gui_main.wx_python_gui(self.constants).main_menu(None)
|
||||||
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
print("- Unable to determine if boot disk is removable, skipping prompt")
|
logging.info("- Unable to determine if boot disk is removable, skipping prompt")
|
||||||
|
|
||||||
|
|
||||||
def install_auto_patcher_launch_agent(self):
|
def install_auto_patcher_launch_agent(self):
|
||||||
@@ -226,52 +227,52 @@ class AutomaticSysPatch:
|
|||||||
# - OpenCore-Patcher.app in /Library/Application Support/Dortania/
|
# - OpenCore-Patcher.app in /Library/Application Support/Dortania/
|
||||||
# - com.dortania.opencore-legacy-patcher.auto-patch.plist in /Library/LaunchAgents/
|
# - com.dortania.opencore-legacy-patcher.auto-patch.plist in /Library/LaunchAgents/
|
||||||
if self.constants.launcher_script is not None:
|
if self.constants.launcher_script is not None:
|
||||||
print("- Skipping Auto Patcher Launch Agent, not supported when running from source")
|
logging.info("- Skipping Auto Patcher Launch Agent, not supported when running from source")
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.constants.launcher_binary.startswith("/Library/Application Support/Dortania/"):
|
if self.constants.launcher_binary.startswith("/Library/Application Support/Dortania/"):
|
||||||
print("- Skipping Auto Patcher Launch Agent, already installed")
|
logging.info("- Skipping Auto Patcher Launch Agent, already installed")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Verify our binary isn't located in '/Library/Application Support/Dortania/'
|
# Verify our binary isn't located in '/Library/Application Support/Dortania/'
|
||||||
# As we'd simply be duplicating ourselves
|
# As we'd simply be duplicating ourselves
|
||||||
print("- Installing Auto Patcher Launch Agent")
|
logging.info("- Installing Auto Patcher Launch Agent")
|
||||||
|
|
||||||
if not Path("Library/Application Support/Dortania").exists():
|
if not Path("Library/Application Support/Dortania").exists():
|
||||||
print("- Creating /Library/Application Support/Dortania/")
|
logging.info("- Creating /Library/Application Support/Dortania/")
|
||||||
utilities.process_status(utilities.elevated(["mkdir", "-p", "/Library/Application Support/Dortania"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["mkdir", "-p", "/Library/Application Support/Dortania"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
print("- Copying OpenCore Patcher to /Library/Application Support/Dortania/")
|
logging.info("- Copying OpenCore Patcher to /Library/Application Support/Dortania/")
|
||||||
if Path("/Library/Application Support/Dortania/OpenCore-Patcher.app").exists():
|
if Path("/Library/Application Support/Dortania/OpenCore-Patcher.app").exists():
|
||||||
print("- Deleting existing OpenCore-Patcher")
|
logging.info("- Deleting existing OpenCore-Patcher")
|
||||||
utilities.process_status(utilities.elevated(["rm", "-R", "/Library/Application Support/Dortania/OpenCore-Patcher.app"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["rm", "-R", "/Library/Application Support/Dortania/OpenCore-Patcher.app"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
# Strip everything after OpenCore-Patcher.app
|
# Strip everything after OpenCore-Patcher.app
|
||||||
path = str(self.constants.launcher_binary).split("/Contents/MacOS/OpenCore-Patcher")[0]
|
path = str(self.constants.launcher_binary).split("/Contents/MacOS/OpenCore-Patcher")[0]
|
||||||
print(f"- Copying {path} to /Library/Application Support/Dortania/")
|
logging.info(f"- Copying {path} to /Library/Application Support/Dortania/")
|
||||||
utilities.process_status(utilities.elevated(["ditto", path, "/Library/Application Support/Dortania/OpenCore-Patcher.app"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["ditto", path, "/Library/Application Support/Dortania/OpenCore-Patcher.app"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
if not Path("/Library/Application Support/Dortania/OpenCore-Patcher.app").exists():
|
if not Path("/Library/Application Support/Dortania/OpenCore-Patcher.app").exists():
|
||||||
# Sometimes the binary the user launches may have a suffix (ie. OpenCore-Patcher 3.app)
|
# Sometimes the binary the user launches may have a suffix (ie. OpenCore-Patcher 3.app)
|
||||||
# We'll want to rename it to OpenCore-Patcher.app
|
# We'll want to rename it to OpenCore-Patcher.app
|
||||||
path = path.split("/")[-1]
|
path = path.split("/")[-1]
|
||||||
print(f"- Renaming {path} to OpenCore-Patcher.app")
|
logging.info(f"- Renaming {path} to OpenCore-Patcher.app")
|
||||||
utilities.process_status(utilities.elevated(["mv", f"/Library/Application Support/Dortania/{path}", "/Library/Application Support/Dortania/OpenCore-Patcher.app"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["mv", f"/Library/Application Support/Dortania/{path}", "/Library/Application Support/Dortania/OpenCore-Patcher.app"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
subprocess.run(["xattr", "-cr", "/Library/Application Support/Dortania/OpenCore-Patcher.app"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
subprocess.run(["xattr", "-cr", "/Library/Application Support/Dortania/OpenCore-Patcher.app"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
|
||||||
# Copy over our launch agent
|
# Copy over our launch agent
|
||||||
print("- Copying auto-patch.plist Launch Agent to /Library/LaunchAgents/")
|
logging.info("- Copying auto-patch.plist Launch Agent to /Library/LaunchAgents/")
|
||||||
if Path("/Library/LaunchAgents/com.dortania.opencore-legacy-patcher.auto-patch.plist").exists():
|
if Path("/Library/LaunchAgents/com.dortania.opencore-legacy-patcher.auto-patch.plist").exists():
|
||||||
print("- Deleting existing auto-patch.plist")
|
logging.info("- Deleting existing auto-patch.plist")
|
||||||
utilities.process_status(utilities.elevated(["rm", "/Library/LaunchAgents/com.dortania.opencore-legacy-patcher.auto-patch.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["rm", "/Library/LaunchAgents/com.dortania.opencore-legacy-patcher.auto-patch.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
if not Path("/Library/LaunchAgents/").exists():
|
if not Path("/Library/LaunchAgents/").exists():
|
||||||
print("- Creating /Library/LaunchAgents/")
|
logging.info("- Creating /Library/LaunchAgents/")
|
||||||
utilities.process_status(utilities.elevated(["mkdir", "-p", "/Library/LaunchAgents/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["mkdir", "-p", "/Library/LaunchAgents/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
utilities.process_status(utilities.elevated(["cp", self.constants.auto_patch_launch_agent_path, "/Library/LaunchAgents/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["cp", self.constants.auto_patch_launch_agent_path, "/Library/LaunchAgents/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
|
||||||
# Set the permissions on the com.dortania.opencore-legacy-patcher.auto-patch.plist
|
# Set the permissions on the com.dortania.opencore-legacy-patcher.auto-patch.plist
|
||||||
print("- Setting permissions on auto-patch.plist")
|
logging.info("- Setting permissions on auto-patch.plist")
|
||||||
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))
|
||||||
|
|
||||||
@@ -279,5 +280,5 @@ class AutomaticSysPatch:
|
|||||||
# 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():
|
||||||
print("- 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))
|
||||||
@@ -3,13 +3,14 @@
|
|||||||
# 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
|
||||||
|
|
||||||
from resources import constants, device_probe, utilities, amfi_detect
|
from resources import constants, device_probe, utilities, amfi_detect, network_handler
|
||||||
from resources.sys_patch import sys_patch_helpers
|
from resources.sys_patch import sys_patch_helpers
|
||||||
from data import model_array, os_data, sip_data, sys_patch_dict, smbios_data, cpu_data
|
from data import model_array, os_data, sip_data, sys_patch_dict, smbios_data, cpu_data
|
||||||
|
|
||||||
import py_sip_xnu
|
import py_sip_xnu
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import plistlib
|
import plistlib
|
||||||
|
import logging
|
||||||
|
|
||||||
class detect_root_patch:
|
class detect_root_patch:
|
||||||
def __init__(self, model, versions):
|
def __init__(self, model, versions):
|
||||||
@@ -67,7 +68,7 @@ class detect_root_patch:
|
|||||||
non_metal_os = os_data.os_data.catalina
|
non_metal_os = os_data.os_data.catalina
|
||||||
for i, gpu in enumerate(gpus):
|
for i, gpu in enumerate(gpus):
|
||||||
if gpu.class_code and gpu.class_code != 0xFFFFFFFF:
|
if gpu.class_code and gpu.class_code != 0xFFFFFFFF:
|
||||||
print(f"- Found GPU ({i}): {utilities.friendly_hex(gpu.vendor_id)}:{utilities.friendly_hex(gpu.device_id)}")
|
logging.info(f"- Found GPU ({i}): {utilities.friendly_hex(gpu.vendor_id)}:{utilities.friendly_hex(gpu.device_id)}")
|
||||||
if gpu.arch in [device_probe.NVIDIA.Archs.Tesla] and self.constants.force_nv_web is False:
|
if gpu.arch in [device_probe.NVIDIA.Archs.Tesla] and self.constants.force_nv_web is False:
|
||||||
if self.constants.detected_os > non_metal_os:
|
if self.constants.detected_os > non_metal_os:
|
||||||
self.nvidia_tesla = True
|
self.nvidia_tesla = True
|
||||||
@@ -401,7 +402,7 @@ class detect_root_patch:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def detect_patch_set(self):
|
def detect_patch_set(self):
|
||||||
self.has_network = utilities.verify_network_connection()
|
self.has_network = network_handler.NetworkUtilities().verify_network_connection()
|
||||||
|
|
||||||
if self.check_uhci_ohci() is True:
|
if self.check_uhci_ohci() is True:
|
||||||
self.legacy_uhci_ohci = True
|
self.legacy_uhci_ohci = True
|
||||||
@@ -511,50 +512,50 @@ class detect_root_patch:
|
|||||||
|
|
||||||
if print_errors is True:
|
if print_errors is True:
|
||||||
if self.sip_enabled is True:
|
if self.sip_enabled is True:
|
||||||
print("\nCannot patch! Please disable System Integrity Protection (SIP).")
|
logging.info("\nCannot patch! Please disable System Integrity Protection (SIP).")
|
||||||
print("Disable SIP in Patcher Settings and Rebuild OpenCore\n")
|
logging.info("Disable SIP in Patcher Settings and Rebuild OpenCore\n")
|
||||||
print("Ensure the following bits are set for csr-active-config:")
|
logging.info("Ensure the following bits are set for csr-active-config:")
|
||||||
print("\n".join(sip))
|
logging.info("\n".join(sip))
|
||||||
print(sip_value)
|
logging.info(sip_value)
|
||||||
|
|
||||||
if self.sbm_enabled is True:
|
if self.sbm_enabled is True:
|
||||||
print("\nCannot patch! Please disable Apple Secure Boot.")
|
logging.info("\nCannot patch! Please disable Apple Secure Boot.")
|
||||||
print("Disable SecureBootModel in Patcher Settings and Rebuild OpenCore")
|
logging.info("Disable SecureBootModel in Patcher Settings and Rebuild OpenCore")
|
||||||
print("For Hackintoshes, set SecureBootModel to Disabled")
|
logging.info("For Hackintoshes, set SecureBootModel to Disabled")
|
||||||
|
|
||||||
if self.fv_enabled is True:
|
if self.fv_enabled is True:
|
||||||
print("\nCannot patch! Please disable FileVault.")
|
logging.info("\nCannot patch! Please disable FileVault.")
|
||||||
print("For OCLP Macs, please rebuild your config with 0.2.5 or newer")
|
logging.info("For OCLP Macs, please rebuild your config with 0.2.5 or newer")
|
||||||
print("For others, Go to System Preferences -> Security and disable FileVault")
|
logging.info("For others, Go to System Preferences -> Security and disable FileVault")
|
||||||
|
|
||||||
if self.amfi_enabled is True and self.amfi_must_disable is True:
|
if self.amfi_enabled is True and self.amfi_must_disable is True:
|
||||||
print("\nCannot patch! Please disable AMFI.")
|
logging.info("\nCannot patch! Please disable AMFI.")
|
||||||
print("For Hackintoshes, please add amfi_get_out_of_my_way=1 to boot-args")
|
logging.info("For Hackintoshes, please add amfi_get_out_of_my_way=1 to boot-args")
|
||||||
|
|
||||||
if self.dosdude_patched is True:
|
if self.dosdude_patched is True:
|
||||||
print("\nCannot patch! Detected machine has already been patched by another patcher")
|
logging.info("\nCannot patch! Detected machine has already been patched by another patcher")
|
||||||
print("Please ensure your install is either clean or patched with OpenCore Legacy Patcher")
|
logging.info("Please ensure your install is either clean or patched with OpenCore Legacy Patcher")
|
||||||
|
|
||||||
if self.nvidia_web is True:
|
if self.nvidia_web is True:
|
||||||
if self.missing_nv_web_opengl is True:
|
if self.missing_nv_web_opengl is True:
|
||||||
print("\nCannot patch! Force OpenGL property missing")
|
logging.info("\nCannot patch! Force OpenGL property missing")
|
||||||
print("Please ensure ngfxgl=1 is set in boot-args")
|
logging.info("Please ensure ngfxgl=1 is set in boot-args")
|
||||||
|
|
||||||
if self.missing_nv_compat is True:
|
if self.missing_nv_compat is True:
|
||||||
print("\nCannot patch! Force Nvidia compatibility property missing")
|
logging.info("\nCannot patch! Force Nvidia compatibility property missing")
|
||||||
print("Please ensure ngfxcompat=1 is set in boot-args")
|
logging.info("Please ensure ngfxcompat=1 is set in boot-args")
|
||||||
|
|
||||||
if self.missing_nv_web_nvram is True:
|
if self.missing_nv_web_nvram is True:
|
||||||
print("\nCannot patch! nvda_drv(_vrl) variable missing")
|
logging.info("\nCannot patch! nvda_drv(_vrl) variable missing")
|
||||||
print("Please ensure nvda_drv_vrl=1 is set in boot-args")
|
logging.info("Please ensure nvda_drv_vrl=1 is set in boot-args")
|
||||||
|
|
||||||
if self.missing_whatever_green is True:
|
if self.missing_whatever_green is True:
|
||||||
print("\nCannot patch! WhateverGreen.kext missing")
|
logging.info("\nCannot patch! WhateverGreen.kext missing")
|
||||||
print("Please ensure WhateverGreen.kext is installed")
|
logging.info("Please ensure WhateverGreen.kext is installed")
|
||||||
|
|
||||||
if (not self.has_network) if (self.requires_root_kc and self.missing_kdk and self.constants.detected_os >= os_data.os_data.ventura.value) else False:
|
if (not self.has_network) if (self.requires_root_kc and self.missing_kdk and self.constants.detected_os >= os_data.os_data.ventura.value) else False:
|
||||||
print("\nCannot patch! Network Connection Required")
|
logging.info("\nCannot patch! Network Connection Required")
|
||||||
print("Please ensure you have an active internet connection")
|
logging.info("Please ensure you have an active internet connection")
|
||||||
|
|
||||||
if any(
|
if any(
|
||||||
[
|
[
|
||||||
@@ -586,7 +587,7 @@ class detect_root_patch:
|
|||||||
all_hardware_patchset = sys_patch_dict.SystemPatchDictionary(self.constants.detected_os, self.constants.detected_os_minor, self.constants.legacy_accel_support)
|
all_hardware_patchset = sys_patch_dict.SystemPatchDictionary(self.constants.detected_os, self.constants.detected_os_minor, self.constants.legacy_accel_support)
|
||||||
required_patches = {}
|
required_patches = {}
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
print("- The following patches will be applied:")
|
logging.info("- The following patches will be applied:")
|
||||||
if hardware_details["Graphics: Intel Ironlake"] is True:
|
if hardware_details["Graphics: Intel Ironlake"] is True:
|
||||||
required_patches.update({"Non-Metal Common": all_hardware_patchset["Graphics"]["Non-Metal Common"]})
|
required_patches.update({"Non-Metal Common": all_hardware_patchset["Graphics"]["Non-Metal Common"]})
|
||||||
required_patches.update({"WebKit Monterey Common": all_hardware_patchset["Graphics"]["WebKit Monterey Common"]})
|
required_patches.update({"WebKit Monterey Common": all_hardware_patchset["Graphics"]["WebKit Monterey Common"]})
|
||||||
@@ -705,8 +706,8 @@ class detect_root_patch:
|
|||||||
del(required_patches[patch_name])
|
del(required_patches[patch_name])
|
||||||
else:
|
else:
|
||||||
if required_patches[patch_name]["Display Name"]:
|
if required_patches[patch_name]["Display Name"]:
|
||||||
print(f" - {required_patches[patch_name]['Display Name']}")
|
logging.info(f" - {required_patches[patch_name]['Display Name']}")
|
||||||
else:
|
else:
|
||||||
print(" - No patch sets found for booted model")
|
logging.info(" - No patch sets found for booted model")
|
||||||
|
|
||||||
return required_patches
|
return required_patches
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# Download PatcherSupportPkg for usage with Root Patching
|
|
||||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
|
||||||
|
|
||||||
from resources import utilities
|
|
||||||
from pathlib import Path
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
class grab_patcher_support_pkg:
|
|
||||||
|
|
||||||
def __init__(self, constants):
|
|
||||||
self.constants = constants
|
|
||||||
|
|
||||||
def generate_pkg_link(self):
|
|
||||||
link = f"{self.constants.url_patcher_support_pkg}{self.constants.patcher_support_pkg_version}/Universal-Binaries.zip"
|
|
||||||
return link
|
|
||||||
|
|
||||||
def download_files(self):
|
|
||||||
link = self.generate_pkg_link()
|
|
||||||
if Path(self.constants.payload_local_binaries_root_path).exists():
|
|
||||||
print("- Removing old Root Patcher Payload folder")
|
|
||||||
# Delete folder
|
|
||||||
shutil.rmtree(self.constants.payload_local_binaries_root_path)
|
|
||||||
|
|
||||||
download_result = None
|
|
||||||
if Path(self.constants.payload_local_binaries_root_path_zip).exists():
|
|
||||||
print(f"- Found local Universal-Binaries.zip, skipping download")
|
|
||||||
download_result = True
|
|
||||||
else:
|
|
||||||
print(f"- No local version found, downloading...")
|
|
||||||
download_result = utilities.download_file(link, self.constants.payload_local_binaries_root_path_zip)
|
|
||||||
|
|
||||||
return download_result, link
|
|
||||||
@@ -9,6 +9,7 @@ from pathlib import Path
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import plistlib
|
import plistlib
|
||||||
import os
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
from resources import constants, bplist
|
from resources import constants, bplist
|
||||||
|
|
||||||
@@ -25,9 +26,9 @@ class sys_patch_helpers:
|
|||||||
# to supplement the ideal Board ID
|
# to supplement the ideal Board ID
|
||||||
source_files_path = str(source_files_path)
|
source_files_path = str(source_files_path)
|
||||||
if self.constants.computer.reported_board_id not in self.constants.sandy_board_id_stock:
|
if self.constants.computer.reported_board_id not in self.constants.sandy_board_id_stock:
|
||||||
print(f"- Found unsupported Board ID {self.constants.computer.reported_board_id}, performing AppleIntelSNBGraphicsFB bin patching")
|
logging.info(f"- Found unsupported Board ID {self.constants.computer.reported_board_id}, performing AppleIntelSNBGraphicsFB bin patching")
|
||||||
board_to_patch = generate_smbios.determine_best_board_id_for_sandy(self.constants.computer.reported_board_id, self.constants.computer.gpus)
|
board_to_patch = generate_smbios.determine_best_board_id_for_sandy(self.constants.computer.reported_board_id, self.constants.computer.gpus)
|
||||||
print(f"- Replacing {board_to_patch} with {self.constants.computer.reported_board_id}")
|
logging.info(f"- Replacing {board_to_patch} with {self.constants.computer.reported_board_id}")
|
||||||
|
|
||||||
board_to_patch_hex = bytes.fromhex(board_to_patch.encode('utf-8').hex())
|
board_to_patch_hex = bytes.fromhex(board_to_patch.encode('utf-8').hex())
|
||||||
reported_board_hex = bytes.fromhex(self.constants.computer.reported_board_id.encode('utf-8').hex())
|
reported_board_hex = bytes.fromhex(self.constants.computer.reported_board_id.encode('utf-8').hex())
|
||||||
@@ -36,7 +37,7 @@ class sys_patch_helpers:
|
|||||||
# Pad the reported Board ID with zeros to match the length of the board to patch
|
# Pad the reported Board ID with zeros to match the length of the board to patch
|
||||||
reported_board_hex = reported_board_hex + bytes(len(board_to_patch_hex) - len(reported_board_hex))
|
reported_board_hex = reported_board_hex + bytes(len(board_to_patch_hex) - len(reported_board_hex))
|
||||||
elif len(board_to_patch_hex) < len(reported_board_hex):
|
elif len(board_to_patch_hex) < len(reported_board_hex):
|
||||||
print(f"- Error: Board ID {self.constants.computer.reported_board_id} is longer than {board_to_patch}")
|
logging.info(f"- Error: Board ID {self.constants.computer.reported_board_id} is longer than {board_to_patch}")
|
||||||
raise Exception("Host's Board ID is longer than the kext's Board ID, cannot patch!!!")
|
raise Exception("Host's Board ID is longer than the kext's Board ID, cannot patch!!!")
|
||||||
|
|
||||||
path = source_files_path + "/10.13.6/System/Library/Extensions/AppleIntelSNBGraphicsFB.kext/Contents/MacOS/AppleIntelSNBGraphicsFB"
|
path = source_files_path + "/10.13.6/System/Library/Extensions/AppleIntelSNBGraphicsFB.kext/Contents/MacOS/AppleIntelSNBGraphicsFB"
|
||||||
@@ -47,7 +48,7 @@ class sys_patch_helpers:
|
|||||||
with open(path, 'wb') as f:
|
with open(path, 'wb') as f:
|
||||||
f.write(data)
|
f.write(data)
|
||||||
else:
|
else:
|
||||||
print(f"- Error: Could not find {path}")
|
logging.info(f"- Error: Could not find {path}")
|
||||||
raise Exception("Failed to find AppleIntelSNBGraphicsFB.kext, cannot patch!!!")
|
raise Exception("Failed to find AppleIntelSNBGraphicsFB.kext, cannot patch!!!")
|
||||||
|
|
||||||
|
|
||||||
@@ -80,7 +81,7 @@ class sys_patch_helpers:
|
|||||||
if not self.constants.kdk_download_path.exists():
|
if not self.constants.kdk_download_path.exists():
|
||||||
return
|
return
|
||||||
|
|
||||||
print(f"- Installing downloaded KDK (this may take a while)")
|
logging.info(f"- Installing downloaded KDK (this may take a while)")
|
||||||
with tempfile.TemporaryDirectory() as mount_point:
|
with tempfile.TemporaryDirectory() as mount_point:
|
||||||
utilities.process_status(subprocess.run(["hdiutil", "attach", self.constants.kdk_download_path, "-mountpoint", mount_point, "-nobrowse"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(subprocess.run(["hdiutil", "attach", self.constants.kdk_download_path, "-mountpoint", mount_point, "-nobrowse"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
# Due to a permissions bug in macOS, sometimes the OS will fail on a Read-only file system error
|
# Due to a permissions bug in macOS, sometimes the OS will fail on a Read-only file system error
|
||||||
@@ -92,15 +93,15 @@ class sys_patch_helpers:
|
|||||||
utilities.process_status(subprocess.run(["cp", f"{mount_point}/KernelDebugKit.pkg", self.constants.payload_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(subprocess.run(["cp", f"{mount_point}/KernelDebugKit.pkg", self.constants.payload_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
result = utilities.elevated(["installer", "-pkg", kdk_dst_path, "-target", "/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
result = utilities.elevated(["installer", "-pkg", kdk_dst_path, "-target", "/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
print("- Failed to install KDK:")
|
logging.info("- Failed to install KDK:")
|
||||||
print(result.stdout.decode('utf-8'))
|
logging.info(result.stdout.decode('utf-8'))
|
||||||
if result.stderr:
|
if result.stderr:
|
||||||
print(result.stderr.decode('utf-8'))
|
logging.info(result.stderr.decode('utf-8'))
|
||||||
utilities.elevated(["hdiutil", "detach", mount_point], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
utilities.elevated(["hdiutil", "detach", mount_point], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
raise Exception("Failed to install KDK")
|
raise Exception("Failed to install KDK")
|
||||||
utilities.process_status(utilities.elevated(["rm", kdk_dst_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
utilities.process_status(utilities.elevated(["rm", kdk_dst_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
utilities.elevated(["hdiutil", "detach", mount_point], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
utilities.elevated(["hdiutil", "detach", mount_point], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
print("- Successfully installed KDK")
|
logging.info("- Successfully installed KDK")
|
||||||
|
|
||||||
|
|
||||||
def determine_kdk_present(self, match_closest=False, override_build=None):
|
def determine_kdk_present(self, match_closest=False, override_build=None):
|
||||||
@@ -138,7 +139,7 @@ class sys_patch_helpers:
|
|||||||
|
|
||||||
if match_closest is True:
|
if match_closest is True:
|
||||||
result = os_data.os_conversion.find_largest_build(kdk_array)
|
result = os_data.os_conversion.find_largest_build(kdk_array)
|
||||||
print(f"- Closest KDK match to {search_build}: {result}")
|
logging.info(f"- Closest KDK match to {search_build}: {result}")
|
||||||
for kdk_folder in Path("/Library/Developer/KDKs").iterdir():
|
for kdk_folder in Path("/Library/Developer/KDKs").iterdir():
|
||||||
if kdk_folder.name.endswith(f"{result}.kdk"):
|
if kdk_folder.name.endswith(f"{result}.kdk"):
|
||||||
# Verify that the KDK is valid
|
# Verify that the KDK is valid
|
||||||
@@ -154,7 +155,7 @@ class sys_patch_helpers:
|
|||||||
# And force macOS into properly generating the Opaque shaders
|
# And force macOS into properly generating the Opaque shaders
|
||||||
if self.constants.detected_os < os_data.os_data.ventura:
|
if self.constants.detected_os < os_data.os_data.ventura:
|
||||||
return
|
return
|
||||||
print("- Disabling WindowServer Caching")
|
logging.info("- Disabling WindowServer Caching")
|
||||||
# Invoke via 'bash -c' to resolve pathing
|
# Invoke via 'bash -c' to resolve pathing
|
||||||
utilities.elevated(["bash", "-c", "rm -rf /private/var/folders/*/*/*/WindowServer/com.apple.WindowServer"])
|
utilities.elevated(["bash", "-c", "rm -rf /private/var/folders/*/*/*/WindowServer/com.apple.WindowServer"])
|
||||||
# Disable writing to WindowServer folder
|
# Disable writing to WindowServer folder
|
||||||
@@ -170,12 +171,12 @@ class sys_patch_helpers:
|
|||||||
# we manually remove all News Widgets
|
# we manually remove all News Widgets
|
||||||
if self.constants.detected_os < os_data.os_data.ventura:
|
if self.constants.detected_os < os_data.os_data.ventura:
|
||||||
return
|
return
|
||||||
print("- Parsing Notification Centre Widgets")
|
logging.info("- Parsing Notification Centre Widgets")
|
||||||
file_path = "~/Library/Containers/com.apple.notificationcenterui/Data/Library/Preferences/com.apple.notificationcenterui.plist"
|
file_path = "~/Library/Containers/com.apple.notificationcenterui/Data/Library/Preferences/com.apple.notificationcenterui.plist"
|
||||||
file_path = Path(file_path).expanduser()
|
file_path = Path(file_path).expanduser()
|
||||||
|
|
||||||
if not file_path.exists():
|
if not file_path.exists():
|
||||||
print(" - Defaults file not found, skipping")
|
logging.info(" - Defaults file not found, skipping")
|
||||||
return
|
return
|
||||||
|
|
||||||
did_find = False
|
did_find = False
|
||||||
@@ -194,7 +195,7 @@ class sys_patch_helpers:
|
|||||||
continue
|
continue
|
||||||
if not b'com.apple.news' in sub_data[sub_entry][2]:
|
if not b'com.apple.news' in sub_data[sub_entry][2]:
|
||||||
continue
|
continue
|
||||||
print(f" - Found News Widget to remove: {sub_data[sub_entry][2].decode('ascii')}")
|
logging.info(f" - Found News Widget to remove: {sub_data[sub_entry][2].decode('ascii')}")
|
||||||
data["widgets"]["instances"].remove(widget)
|
data["widgets"]["instances"].remove(widget)
|
||||||
did_find = True
|
did_find = True
|
||||||
if did_find:
|
if did_find:
|
||||||
@@ -218,7 +219,7 @@ class sys_patch_helpers:
|
|||||||
if self.constants.detected_os < os_data.os_data.big_sur:
|
if self.constants.detected_os < os_data.os_data.big_sur:
|
||||||
return
|
return
|
||||||
|
|
||||||
print("- Installing Kernel Collection syncing utility")
|
logging.info("- Installing Kernel Collection syncing utility")
|
||||||
result = utilities.elevated([self.constants.rsrrepair_userspace_path, "--install"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
result = utilities.elevated([self.constants.rsrrepair_userspace_path, "--install"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
print(f" - Failed to install RSRRepair: {result.stdout.decode()}")
|
logging.info(f" - Failed to install RSRRepair: {result.stdout.decode()}")
|
||||||
+13
-21
@@ -3,6 +3,9 @@
|
|||||||
# 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 requests
|
import requests
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from resources import network_handler
|
||||||
|
|
||||||
|
|
||||||
class check_binary_updates:
|
class check_binary_updates:
|
||||||
@@ -15,17 +18,6 @@ class check_binary_updates:
|
|||||||
|
|
||||||
self.available_binaries = {}
|
self.available_binaries = {}
|
||||||
|
|
||||||
def verify_network_connection(self, url):
|
|
||||||
try:
|
|
||||||
response = requests.head(url, timeout=5)
|
|
||||||
if response:
|
|
||||||
return True
|
|
||||||
except (requests.exceptions.Timeout,
|
|
||||||
requests.exceptions.TooManyRedirects,
|
|
||||||
requests.exceptions.ConnectionError,
|
|
||||||
requests.exceptions.HTTPError):
|
|
||||||
return False
|
|
||||||
return False
|
|
||||||
|
|
||||||
def check_if_build_newer(self, remote_version=None, local_version=None):
|
def check_if_build_newer(self, remote_version=None, local_version=None):
|
||||||
if remote_version is None:
|
if remote_version is None:
|
||||||
@@ -62,24 +54,24 @@ class check_binary_updates:
|
|||||||
return "Unknown"
|
return "Unknown"
|
||||||
|
|
||||||
def check_binary_updates(self):
|
def check_binary_updates(self):
|
||||||
# print("- Checking for updates...")
|
# logging.info("- Checking for updates...")
|
||||||
if self.verify_network_connection(self.binary_url):
|
if network_handler.NetworkUtilities(self.binary_url).verify_network_connection():
|
||||||
# print("- Network connection functional")
|
# logging.info("- Network connection functional")
|
||||||
response = requests.get(self.binary_url)
|
response = requests.get(self.binary_url)
|
||||||
data_set = response.json()
|
data_set = response.json()
|
||||||
# print("- Retrieved latest version data")
|
# logging.info("- Retrieved latest version data")
|
||||||
self.remote_version = data_set["tag_name"]
|
self.remote_version = data_set["tag_name"]
|
||||||
# print(f"- Latest version: {self.remote_version}")
|
# logging.info(f"- Latest version: {self.remote_version}")
|
||||||
self.remote_version_array = self.remote_version.split(".")
|
self.remote_version_array = self.remote_version.split(".")
|
||||||
self.remote_version_array = [
|
self.remote_version_array = [
|
||||||
int(x) for x in self.remote_version_array
|
int(x) for x in self.remote_version_array
|
||||||
]
|
]
|
||||||
if self.check_if_build_newer() is True:
|
if self.check_if_build_newer() is True:
|
||||||
# print("- Remote version is newer")
|
# logging.info("- Remote version is newer")
|
||||||
for asset in data_set["assets"]:
|
for asset in data_set["assets"]:
|
||||||
print(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():
|
||||||
# print(f"- Found matching asset: {asset['name']}")
|
# logging.info(f"- Found matching asset: {asset['name']}")
|
||||||
self.available_binaries.update({
|
self.available_binaries.update({
|
||||||
asset['name']: {
|
asset['name']: {
|
||||||
"Name":
|
"Name":
|
||||||
@@ -98,8 +90,8 @@ class check_binary_updates:
|
|||||||
if self.available_binaries:
|
if self.available_binaries:
|
||||||
return self.available_binaries
|
return self.available_binaries
|
||||||
else:
|
else:
|
||||||
# print("- No matching binaries available")
|
# logging.info("- No matching binaries available")
|
||||||
return None
|
return None
|
||||||
# else:
|
# else:
|
||||||
# print("- Failed to connect to GitHub API")
|
# logging.info("- Failed to connect to GitHub API")
|
||||||
return None
|
return None
|
||||||
+12
-112
@@ -1,6 +1,5 @@
|
|||||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
# Copyright (C) 2020-2023, Dhinak G, Mykola Grymalyuk
|
||||||
|
|
||||||
import hashlib
|
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
import plistlib
|
import plistlib
|
||||||
@@ -9,18 +8,16 @@ from pathlib import Path
|
|||||||
import os
|
import os
|
||||||
import binascii
|
import binascii
|
||||||
import argparse
|
import argparse
|
||||||
import time
|
|
||||||
import atexit
|
import atexit
|
||||||
import requests
|
import requests
|
||||||
import shutil
|
import shutil
|
||||||
import urllib.parse
|
|
||||||
import py_sip_xnu
|
import py_sip_xnu
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
from resources import constants, ioreg
|
from resources import constants, ioreg
|
||||||
from data import sip_data, os_data
|
from data import sip_data, os_data
|
||||||
|
|
||||||
SESSION = requests.Session()
|
|
||||||
|
|
||||||
|
|
||||||
def hexswap(input_hex: str):
|
def hexswap(input_hex: str):
|
||||||
hex_pairs = [input_hex[i : i + 2] for i in range(0, len(input_hex), 2)]
|
hex_pairs = [input_hex[i : i + 2] for i in range(0, len(input_hex), 2)]
|
||||||
@@ -39,8 +36,8 @@ def string_to_hex(input_string):
|
|||||||
|
|
||||||
def process_status(process_result):
|
def process_status(process_result):
|
||||||
if process_result.returncode != 0:
|
if process_result.returncode != 0:
|
||||||
print(f"Process failed with exit code {process_result.returncode}")
|
logging.info(f"Process failed with exit code {process_result.returncode}")
|
||||||
print(f"Please report the issue on the Discord server")
|
logging.info(f"Please report the issue on the Discord server")
|
||||||
raise Exception(f"Process result: \n{process_result.stdout.decode()}")
|
raise Exception(f"Process result: \n{process_result.stdout.decode()}")
|
||||||
|
|
||||||
|
|
||||||
@@ -55,11 +52,11 @@ def human_fmt(num):
|
|||||||
def header(lines):
|
def header(lines):
|
||||||
lines = [i for i in lines if i is not None]
|
lines = [i for i in lines if i is not None]
|
||||||
total_length = len(max(lines, key=len)) + 4
|
total_length = len(max(lines, key=len)) + 4
|
||||||
print("#" * (total_length))
|
logging.info("#" * (total_length))
|
||||||
for line in lines:
|
for line in lines:
|
||||||
left_side = math.floor(((total_length - 2 - len(line.strip())) / 2))
|
left_side = math.floor(((total_length - 2 - len(line.strip())) / 2))
|
||||||
print("#" + " " * left_side + line.strip() + " " * (total_length - len("#" + " " * left_side + line.strip()) - 1) + "#")
|
logging.info("#" + " " * left_side + line.strip() + " " * (total_length - len("#" + " " * left_side + line.strip()) - 1) + "#")
|
||||||
print("#" * total_length)
|
logging.info("#" * total_length)
|
||||||
|
|
||||||
|
|
||||||
RECOVERY_STATUS = None
|
RECOVERY_STATUS = None
|
||||||
@@ -124,7 +121,7 @@ sleep_process = None
|
|||||||
|
|
||||||
def disable_sleep_while_running():
|
def disable_sleep_while_running():
|
||||||
global sleep_process
|
global sleep_process
|
||||||
print("- Disabling Idle Sleep")
|
logging.info("- Disabling Idle Sleep")
|
||||||
if sleep_process is None:
|
if sleep_process is None:
|
||||||
# If sleep_process is active, we'll just keep it running
|
# If sleep_process is active, we'll just keep it running
|
||||||
sleep_process = subprocess.Popen(["caffeinate", "-d", "-i", "-s"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
sleep_process = subprocess.Popen(["caffeinate", "-d", "-i", "-s"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
@@ -134,7 +131,7 @@ def disable_sleep_while_running():
|
|||||||
def enable_sleep_after_running():
|
def enable_sleep_after_running():
|
||||||
global sleep_process
|
global sleep_process
|
||||||
if sleep_process:
|
if sleep_process:
|
||||||
print("- Re-enabling Idle Sleep")
|
logging.info("- Re-enabling Idle Sleep")
|
||||||
sleep_process.kill()
|
sleep_process.kill()
|
||||||
sleep_process = None
|
sleep_process = None
|
||||||
|
|
||||||
@@ -283,7 +280,7 @@ def cls():
|
|||||||
if not check_recovery():
|
if not check_recovery():
|
||||||
os.system("cls" if os.name == "nt" else "clear")
|
os.system("cls" if os.name == "nt" else "clear")
|
||||||
else:
|
else:
|
||||||
print("\u001Bc")
|
logging.info("\u001Bc")
|
||||||
|
|
||||||
def check_command_line_tools():
|
def check_command_line_tools():
|
||||||
# Determine whether Command Line Tools exist
|
# Determine whether Command Line Tools exist
|
||||||
@@ -360,93 +357,6 @@ def get_firmware_vendor(*, decode: bool = False):
|
|||||||
value = value.strip("\0")
|
value = value.strip("\0")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def verify_network_connection(url=None):
|
|
||||||
if url is None:
|
|
||||||
url = "https://www.google.com"
|
|
||||||
try:
|
|
||||||
response = SESSION.head(url, timeout=5, allow_redirects=True)
|
|
||||||
return True
|
|
||||||
except (requests.exceptions.Timeout, requests.exceptions.TooManyRedirects, requests.exceptions.ConnectionError, requests.exceptions.HTTPError):
|
|
||||||
return False
|
|
||||||
|
|
||||||
def download_file(link, location, is_gui=None, verify_checksum=False):
|
|
||||||
if verify_network_connection(link):
|
|
||||||
disable_sleep_while_running()
|
|
||||||
base_name = Path(link).name
|
|
||||||
|
|
||||||
if Path(location).exists():
|
|
||||||
Path(location).unlink()
|
|
||||||
|
|
||||||
head_response = SESSION.head(link, allow_redirects=True)
|
|
||||||
try:
|
|
||||||
# Handle cases where Content-Length has garbage or is missing
|
|
||||||
total_file_size = int(head_response.headers['Content-Length'])
|
|
||||||
except KeyError:
|
|
||||||
total_file_size = 0
|
|
||||||
|
|
||||||
if total_file_size > 1024:
|
|
||||||
file_size_rounded = round(total_file_size / 1024 / 1024, 2)
|
|
||||||
file_size_string = f" of {file_size_rounded}MB"
|
|
||||||
|
|
||||||
# Check if we have enough space
|
|
||||||
if total_file_size > get_free_space():
|
|
||||||
print(f"Not enough space to download {base_name} ({file_size_rounded}MB)")
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
file_size_string = ""
|
|
||||||
|
|
||||||
response = SESSION.get(link, stream=True)
|
|
||||||
|
|
||||||
# SU Catalog's link is quite long, strip to make it bearable
|
|
||||||
if "sucatalog.gz" in base_name:
|
|
||||||
base_name = "sucatalog.gz"
|
|
||||||
|
|
||||||
header = f"# Downloading: {base_name} #"
|
|
||||||
box_length = len(header)
|
|
||||||
box_string = "#" * box_length
|
|
||||||
dl = 0
|
|
||||||
total_downloaded_string = ""
|
|
||||||
global clear
|
|
||||||
checksum = hashlib.sha256() if verify_checksum else None
|
|
||||||
with location.open("wb") as file:
|
|
||||||
count = 0
|
|
||||||
start = time.perf_counter()
|
|
||||||
for chunk in response.iter_content(1024 * 1024 * 4):
|
|
||||||
dl += len(chunk)
|
|
||||||
file.write(chunk)
|
|
||||||
if checksum:
|
|
||||||
checksum.update(chunk)
|
|
||||||
count += len(chunk)
|
|
||||||
if is_gui is None:
|
|
||||||
if clear:
|
|
||||||
cls()
|
|
||||||
print(box_string)
|
|
||||||
print(header)
|
|
||||||
print(box_string)
|
|
||||||
print("")
|
|
||||||
if total_file_size > 1024:
|
|
||||||
total_downloaded_string = f" ({round(float(dl / total_file_size * 100), 2)}%)"
|
|
||||||
print(f"{round(count / 1024 / 1024, 2)}MB Downloaded{file_size_string}{total_downloaded_string}\nAverage Download Speed: {round(dl//(time.perf_counter() - start) / 100000 / 8, 2)} MB/s")
|
|
||||||
|
|
||||||
enable_sleep_after_running()
|
|
||||||
return checksum.hexdigest() if checksum else True
|
|
||||||
else:
|
|
||||||
cls()
|
|
||||||
header = "# Could not establish Network Connection with provided link! #"
|
|
||||||
box_length = len(header)
|
|
||||||
box_string = "#" * box_length
|
|
||||||
print(box_string)
|
|
||||||
print(header)
|
|
||||||
print(box_string)
|
|
||||||
if constants.Constants().url_patcher_support_pkg in link:
|
|
||||||
# If we're downloading PatcherSupportPkg, present offline build
|
|
||||||
print("\nPlease grab the offline variant of OpenCore Legacy Patcher from Github:")
|
|
||||||
print(f"https://github.com/dortania/OpenCore-Legacy-Patcher/releases/download/{constants.Constants().patcher_version}/OpenCore-Patcher-TUI-Offline.app.zip")
|
|
||||||
else:
|
|
||||||
print(link)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def dump_constants(constants):
|
def dump_constants(constants):
|
||||||
with open(os.path.join(os.path.expanduser('~'), 'Desktop', 'internal_data.txt'), 'w') as f:
|
with open(os.path.join(os.path.expanduser('~'), 'Desktop', 'internal_data.txt'), 'w') as f:
|
||||||
f.write(str(vars(constants)))
|
f.write(str(vars(constants)))
|
||||||
@@ -531,16 +441,6 @@ def monitor_disk_output(disk):
|
|||||||
output = output[-2]
|
output = output[-2]
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def validate_link(link):
|
|
||||||
# Check if link is 404
|
|
||||||
try:
|
|
||||||
response = SESSION.head(link, timeout=5, allow_redirects=True)
|
|
||||||
if response.status_code == 404:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
except (requests.exceptions.Timeout, requests.exceptions.TooManyRedirects, requests.exceptions.ConnectionError, requests.exceptions.HTTPError):
|
|
||||||
return False
|
|
||||||
|
|
||||||
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
|
||||||
@@ -560,7 +460,7 @@ def block_os_updaters():
|
|||||||
for bad_process in bad_processes:
|
for bad_process in bad_processes:
|
||||||
if bad_process in current_process:
|
if bad_process in current_process:
|
||||||
if pid != "":
|
if pid != "":
|
||||||
print(f"- Killing Process: {pid} - {current_process.split('/')[-1]}")
|
logging.info(f"- Killing Process: {pid} - {current_process.split('/')[-1]}")
|
||||||
subprocess.run(["kill", "-9", pid])
|
subprocess.run(["kill", "-9", pid])
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|||||||
+14
-13
@@ -3,6 +3,7 @@ from resources.sys_patch import sys_patch_helpers
|
|||||||
from resources.build import build
|
from resources.build import build
|
||||||
from data import example_data, model_array, sys_patch_dict, os_data
|
from data import example_data, model_array, sys_patch_dict, os_data
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
def validate(settings):
|
def validate(settings):
|
||||||
@@ -41,30 +42,30 @@ def validate(settings):
|
|||||||
|
|
||||||
def build_prebuilt():
|
def build_prebuilt():
|
||||||
for model in model_array.SupportedSMBIOS:
|
for model in model_array.SupportedSMBIOS:
|
||||||
print(f"Validating predefined model: {model}")
|
logging.info(f"Validating predefined model: {model}")
|
||||||
settings.custom_model = model
|
settings.custom_model = model
|
||||||
build.build_opencore(settings.custom_model, settings).build_opencore()
|
build.build_opencore(settings.custom_model, settings).build_opencore()
|
||||||
result = subprocess.run([settings.ocvalidate_path, f"{settings.opencore_release_folder}/EFI/OC/config.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
result = subprocess.run([settings.ocvalidate_path, f"{settings.opencore_release_folder}/EFI/OC/config.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
print("Error on build!")
|
logging.info("Error on build!")
|
||||||
print(result.stdout.decode())
|
logging.info(result.stdout.decode())
|
||||||
raise Exception(f"Validation failed for predefined model: {model}")
|
raise Exception(f"Validation failed for predefined model: {model}")
|
||||||
else:
|
else:
|
||||||
print(f"Validation succeeded for predefined model: {model}")
|
logging.info(f"Validation succeeded for predefined model: {model}")
|
||||||
|
|
||||||
def build_dumps():
|
def build_dumps():
|
||||||
for model in valid_dumps:
|
for model in valid_dumps:
|
||||||
settings.computer = model
|
settings.computer = model
|
||||||
settings.custom_model = ""
|
settings.custom_model = ""
|
||||||
print(f"Validating dumped model: {settings.computer.real_model}")
|
logging.info(f"Validating dumped model: {settings.computer.real_model}")
|
||||||
build.build_opencore(settings.computer.real_model, settings).build_opencore()
|
build.build_opencore(settings.computer.real_model, settings).build_opencore()
|
||||||
result = subprocess.run([settings.ocvalidate_path, f"{settings.opencore_release_folder}/EFI/OC/config.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
result = subprocess.run([settings.ocvalidate_path, f"{settings.opencore_release_folder}/EFI/OC/config.plist"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
print("Error on build!")
|
logging.info("Error on build!")
|
||||||
print(result.stdout.decode())
|
logging.info(result.stdout.decode())
|
||||||
raise Exception(f"Validation failed for predefined model: {settings.computer.real_model}")
|
raise Exception(f"Validation failed for predefined model: {settings.computer.real_model}")
|
||||||
else:
|
else:
|
||||||
print(f"Validation succeeded for predefined model: {settings.computer.real_model}")
|
logging.info(f"Validation succeeded for predefined model: {settings.computer.real_model}")
|
||||||
|
|
||||||
|
|
||||||
def validate_root_patch_files(major_kernel, minor_kernel):
|
def validate_root_patch_files(major_kernel, minor_kernel):
|
||||||
@@ -82,10 +83,10 @@ def validate(settings):
|
|||||||
for install_file in patchset[patch_subject][patch_core][install_type][install_directory]:
|
for install_file in patchset[patch_subject][patch_core][install_type][install_directory]:
|
||||||
source_file = str(settings.payload_local_binaries_root_path) + "/" + patchset[patch_subject][patch_core][install_type][install_directory][install_file] + install_directory + "/" + install_file
|
source_file = str(settings.payload_local_binaries_root_path) + "/" + patchset[patch_subject][patch_core][install_type][install_directory][install_file] + install_directory + "/" + install_file
|
||||||
if not Path(source_file).exists():
|
if not Path(source_file).exists():
|
||||||
print(f"File not found: {source_file}")
|
logging.info(f"File not found: {source_file}")
|
||||||
raise Exception(f"Failed to find {source_file}")
|
raise Exception(f"Failed to find {source_file}")
|
||||||
|
|
||||||
print(f"- Validating against Darwin {major_kernel}.{minor_kernel}")
|
logging.info(f"- Validating against Darwin {major_kernel}.{minor_kernel}")
|
||||||
if not sys_patch_helpers.sys_patch_helpers(settings).generate_patchset_plist(patchset, f"OpenCore-Legacy-Patcher-{major_kernel}.{minor_kernel}.plist", None):
|
if not sys_patch_helpers.sys_patch_helpers(settings).generate_patchset_plist(patchset, f"OpenCore-Legacy-Patcher-{major_kernel}.{minor_kernel}.plist", None):
|
||||||
raise Exception("Failed to generate patchset plist")
|
raise Exception("Failed to generate patchset plist")
|
||||||
|
|
||||||
@@ -95,17 +96,17 @@ def validate(settings):
|
|||||||
|
|
||||||
def validate_sys_patch():
|
def validate_sys_patch():
|
||||||
if Path(settings.payload_local_binaries_root_path_zip).exists():
|
if Path(settings.payload_local_binaries_root_path_zip).exists():
|
||||||
print("Validating Root Patch File integrity")
|
logging.info("Validating Root Patch File integrity")
|
||||||
if not Path(settings.payload_local_binaries_root_path).exists():
|
if not Path(settings.payload_local_binaries_root_path).exists():
|
||||||
subprocess.run(["ditto", "-V", "-x", "-k", "--sequesterRsrc", "--rsrc", settings.payload_local_binaries_root_path_zip, settings.payload_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
subprocess.run(["ditto", "-V", "-x", "-k", "--sequesterRsrc", "--rsrc", settings.payload_local_binaries_root_path_zip, settings.payload_path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
for supported_os in [os_data.os_data.big_sur, os_data.os_data.monterey, os_data.os_data.ventura]:
|
for supported_os in [os_data.os_data.big_sur, os_data.os_data.monterey, os_data.os_data.ventura]:
|
||||||
for i in range(0, 10):
|
for i in range(0, 10):
|
||||||
validate_root_patch_files(supported_os, i)
|
validate_root_patch_files(supported_os, i)
|
||||||
print("Validating SNB Board ID patcher")
|
logging.info("Validating SNB Board ID patcher")
|
||||||
settings.computer.reported_board_id = "Mac-7BA5B2DFE22DDD8C"
|
settings.computer.reported_board_id = "Mac-7BA5B2DFE22DDD8C"
|
||||||
sys_patch_helpers.sys_patch_helpers(settings).snb_board_id_patch(settings.payload_local_binaries_root_path)
|
sys_patch_helpers.sys_patch_helpers(settings).snb_board_id_patch(settings.payload_local_binaries_root_path)
|
||||||
else:
|
else:
|
||||||
print("- Skipping Root Patch File integrity validation")
|
logging.info("- Skipping Root Patch File integrity validation")
|
||||||
|
|
||||||
|
|
||||||
def validate_configs():
|
def validate_configs():
|
||||||
|
|||||||
Reference in New Issue
Block a user