gui_main.py: Add support for KDK chainloading

This commit is contained in:
Mykola Grymalyuk
2023-02-06 21:28:28 -07:00
parent 68af20d2fa
commit fe8a2d253a
7 changed files with 109 additions and 15 deletions

View File

@@ -7,6 +7,9 @@
- 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)
- Implement Kernel Debug Kit installation during OS installs
- Avoids network requirement for first time installs
- Paired along side AutoPkgInstaller
- Backend Changes: - Backend Changes:
- Refactored kdk_handler.py - Refactored kdk_handler.py
- Prioritizes KdkSupportPkg repository for downloads - Prioritizes KdkSupportPkg repository for downloads
@@ -30,6 +33,7 @@
- packaging - 23.0 - packaging - 23.0
- Increment Binaries: - Increment Binaries:
- PatcherSupportPkg 0.8.3 - release - PatcherSupportPkg 0.8.3 - release
- AutoPkgInstaller 1.0.2 - release
## 0.6.1 ## 0.6.1
- Avoid usage of KDKlessWorkaround on hardware not requiring it - Avoid usage of KDKlessWorkaround on hardware not requiring it

View File

@@ -43,7 +43,7 @@ class Constants:
self.cpufriend_version = "1.2.6" # CPUFriend self.cpufriend_version = "1.2.6" # CPUFriend
self.bluetool_version = "2.6.4" # BlueToolFixup (BrcmPatchRAM) self.bluetool_version = "2.6.4" # BlueToolFixup (BrcmPatchRAM)
self.cslvfixup_version = "2.6.1" # CSLVFixup self.cslvfixup_version = "2.6.1" # CSLVFixup
self.autopkg_version = "1.0.1" # AutoPkgInstaller self.autopkg_version = "1.0.2" # AutoPkgInstaller
self.cryptexfixup_version = "1.0.1" # CryptexFixup self.cryptexfixup_version = "1.0.1" # CryptexFixup
## Apple ## Apple

View File

@@ -3,23 +3,30 @@
# Currently Work in Progress # Currently Work in Progress
import plistlib import plistlib
import wx
import sys
import webbrowser
import subprocess
import time
import os
import wx.adv
from wx.lib.agw import hyperlink
import threading
from pathlib import Path from pathlib import Path
from datetime import datetime
import os
import sys
import subprocess
import threading
import webbrowser
import time
import binascii import binascii
import hashlib import hashlib
from datetime import datetime
import py_sip_xnu
import logging import logging
import tempfile import tempfile
import wx
import wx.adv
from wx.lib.agw import hyperlink
import py_sip_xnu
from resources import ( from resources import (
constants, constants,
defaults, defaults,
@@ -34,11 +41,14 @@ from resources import (
kdk_handler, kdk_handler,
network_handler network_handler
) )
from resources.sys_patch import sys_patch_detect, sys_patch 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 resources.gui import menu_redirect, gui_help from resources.gui import menu_redirect, gui_help
from data import model_array, os_data, smbios_data, sip_data, cpu_data
class wx_python_gui: class wx_python_gui:
def __init__(self, versions, frame=None, frame_modal=None): def __init__(self, versions, frame=None, frame_modal=None):
@@ -2167,7 +2177,7 @@ class wx_python_gui:
self.developer_note_label_2.Centre(wx.HORIZONTAL) self.developer_note_label_2.Centre(wx.HORIZONTAL)
# Progress Bar # Progress Bar
max_file_size = 1024 * 1024 * 1024 * 18 # 18GB, best guess for installer + chainloaded packages max_file_size = 19000 # Best guess for installer + chainloaded packages
self.progress_bar = wx.Gauge(self.frame, range=max_file_size, size=(-1, 20)) self.progress_bar = wx.Gauge(self.frame, range=max_file_size, size=(-1, 20))
self.progress_bar.SetPosition( self.progress_bar.SetPosition(
wx.Point( wx.Point(
@@ -2239,7 +2249,7 @@ class wx_python_gui:
output = float(utilities.monitor_disk_output(disk)) output = float(utilities.monitor_disk_output(disk))
bytes_written = output - default_output bytes_written = output - default_output
if install_thread.is_alive(): if install_thread.is_alive():
self.progress_bar.SetValue(bytes_written) self.progress_bar.SetValue(int(bytes_written))
self.progress_label.SetLabel(f"Bytes Written: {round(bytes_written, 2)}MB") self.progress_label.SetLabel(f"Bytes Written: {round(bytes_written, 2)}MB")
wx.GetApp().Yield() wx.GetApp().Yield()
else: else:
@@ -2339,6 +2349,84 @@ class wx_python_gui:
subprocess.run(["ditto", "-V", "-x", "-k", "--sequesterRsrc", "--rsrc", self.constants.installer_pkg_zip_path, self.constants.payload_path]) subprocess.run(["ditto", "-V", "-x", "-k", "--sequesterRsrc", "--rsrc", self.constants.installer_pkg_zip_path, self.constants.payload_path])
def _kdk_chainload(self, build: str, version: str, download_dir: str):
"""
Download the correct KDK to be chainloaded in the macOS installer
Parameters
build (str): The build number of the macOS installer (e.g. 20A5343j)
version (str): The version of the macOS installer (e.g. 11.0.1)
"""
kdk_dmg_path = Path(download_dir) / "KDK.dmg"
kdk_pkg_path = Path(download_dir) / "KDK.pkg"
if kdk_dmg_path.exists():
kdk_dmg_path.unlink()
if kdk_pkg_path.exists():
kdk_pkg_path.unlink()
logging.info("- Initiating KDK download")
logging.info(f" - Build: {build}")
logging.info(f" - Version: {version}")
logging.info(f" - Working Directory: {download_dir}")
kdk_obj = kdk_handler.KernelDebugKitObject(self.constants, build, version, ignore_installed=True)
if kdk_obj.success is False:
logging.info("- Failed to retrieve KDK")
logging.info(kdk_obj.error_msg)
return
kdk_download_obj = kdk_obj.retrieve_download(override_path=kdk_dmg_path)
if kdk_download_obj is None:
logging.info("- Failed to retrieve KDK")
logging.info(kdk_obj.error_msg)
# Check remaining disk space before downloading
space = utilities.get_free_space(download_dir)
if space < (kdk_obj.kdk_url_expected_size * 2):
logging.info("- Not enough disk space to download and install KDK")
logging.info(f"- Attempting to download locally first")
if space < kdk_obj.kdk_url_expected_size:
logging.info("- Not enough disk space to install KDK, skipping")
return
# Ideally we'd download the KDK onto the disk to display progress in the UI
# However we'll just download to our temp directory and move it to the target disk
kdk_dmg_path = self.constants.kdk_download_path
kdk_download_obj.download(spawn_thread=False)
if kdk_download_obj.download_complete is False:
logging.info("- Failed to download KDK")
logging.info(kdk_download_obj.error_msg)
return
if not kdk_dmg_path.exists():
logging.info(f"- KDK missing: {kdk_dmg_path}")
return
# Now that we have a KDK, extract it to get the pkg
with tempfile.TemporaryDirectory() as mount_point:
logging.info("- Mounting KDK")
result = subprocess.run(["hdiutil", "attach", kdk_dmg_path, "-mountpoint", mount_point, "-nobrowse"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if result.returncode != 0:
logging.info("- Failed to mount KDK")
logging.info(result.stdout.decode("utf-8"))
return
logging.info("- Copying KDK")
subprocess.run(["cp", "-r", f"{mount_point}/KernelDebugKit.pkg", kdk_pkg_path])
logging.info("- Unmounting KDK")
result = subprocess.run(["hdiutil", "detach", mount_point], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if result.returncode != 0:
logging.info("- Failed to unmount KDK")
logging.info(result.stdout.decode("utf-8"))
return
logging.info("- Removing KDK Disk Image")
kdk_dmg_path.unlink()
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
@@ -2358,6 +2446,8 @@ 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/"])
self._kdk_chainload(os_version["ProductBuildVersion"], os_version["ProductVersion"], Path(path + "/Library/Packages/"))
def settings_menu(self, event=None): def settings_menu(self, event=None):
# Define Menu # Define Menu