mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-24 03:50:14 +10:00
sys_patch.py: Add backend for MetallibSupportPkg
This commit is contained in:
@@ -812,6 +812,10 @@ class Constants:
|
||||
def kdk_download_path(self):
|
||||
return self.payload_path / Path("KDK.dmg")
|
||||
|
||||
@property
|
||||
def metallib_download_path(self):
|
||||
return self.payload_path / Path("MetallibSupportPkg.pkg")
|
||||
|
||||
@property
|
||||
def icons_path(self):
|
||||
return [
|
||||
|
||||
@@ -2,11 +2,16 @@
|
||||
sys_patch_dict.py: Dictionary defining patch sets used during Root Volume patching (sys_patch.py)
|
||||
"""
|
||||
|
||||
import enum
|
||||
import packaging.version
|
||||
|
||||
from . import os_data
|
||||
|
||||
|
||||
class DynamicPatchset(enum.Enum):
|
||||
MetallibSupportPkg = "MetallibSupportPkg"
|
||||
|
||||
|
||||
class SystemPatchDictionary():
|
||||
"""
|
||||
Library for generating patch sets for sys_patch.py and supporting modules
|
||||
@@ -70,8 +75,8 @@ class SystemPatchDictionary():
|
||||
self.patchset_dict: dict = {}
|
||||
self.marketing_version: str = marketing_version
|
||||
|
||||
self.affected_by_cve_2024_23227: bool = self.__is_affect_by_cve_2024_23227()
|
||||
self.metallib_directory: str = self.__resolve_metallibsupportpkg()
|
||||
self.affected_by_cve_2024_23227: bool = self.__is_affect_by_cve_2024_23227()
|
||||
self.metallib_directory: DynamicPatchset = DynamicPatchset.MetallibSupportPkg
|
||||
|
||||
# XNU Kernel versions
|
||||
self.macOS_12_0_B7: float = 21.1
|
||||
@@ -149,13 +154,6 @@ class SystemPatchDictionary():
|
||||
return False
|
||||
|
||||
|
||||
def __resolve_metallibsupportpkg(self) -> str:
|
||||
"""
|
||||
Temporarily hard coded
|
||||
"""
|
||||
return "/Library/Application Support/Dortania/MetallibSupportPkg/15.0-24A5327a"
|
||||
|
||||
|
||||
def _generate_sys_patch_dict(self):
|
||||
"""
|
||||
Generates the sys_patch_dict dictionary
|
||||
@@ -804,6 +802,12 @@ class SystemPatchDictionary():
|
||||
"default.metallib": self.metallib_directory,
|
||||
},
|
||||
},
|
||||
"Remove": {
|
||||
"/System/Library/PrivateFrameworks/RenderBox.framework/Versions/A/Resources": [
|
||||
# For some reason Ivy Bridge can't tell the metallib lacks AIR64 support, and errors out
|
||||
"archive.metallib",
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
# Primarily for AMD GCN GPUs
|
||||
|
||||
271
opencore_legacy_patcher/support/metallib_handler.py
Normal file
271
opencore_legacy_patcher/support/metallib_handler.py
Normal file
@@ -0,0 +1,271 @@
|
||||
"""
|
||||
metallib_handler.py: Library for handling Metal libraries
|
||||
"""
|
||||
|
||||
import logging
|
||||
import requests
|
||||
import subprocess
|
||||
import packaging.version
|
||||
|
||||
from typing import cast
|
||||
from pathlib import Path
|
||||
|
||||
from . import network_handler, subprocess_wrapper
|
||||
from .. import constants
|
||||
|
||||
from ..datasets import os_data
|
||||
|
||||
|
||||
METALLIB_INSTALL_PATH: str = "/Library/Application Support/Dortania/MetallibSupportPkg"
|
||||
METALLIB_API_LINK: str = "https://dortania.github.io/MetallibSupportPkg/manifest.json"
|
||||
|
||||
METALLIB_ASSET_LIST: list = None
|
||||
|
||||
|
||||
class MetalLibraryObject:
|
||||
|
||||
def __init__(self, global_constants: constants.Constants,
|
||||
host_build: str, host_version: str,
|
||||
ignore_installed: bool = False, passive: bool = False
|
||||
) -> None:
|
||||
|
||||
self.constants: constants.Constants = global_constants
|
||||
|
||||
self.host_build: str = host_build # ex. 20A5384c
|
||||
self.host_version: str = host_version # ex. 11.0.1
|
||||
|
||||
self.passive: bool = passive # Don't perform actions requiring elevated privileges
|
||||
|
||||
self.ignore_installed: bool = ignore_installed # If True, will ignore any installed MetallibSupportPkg PKGs and download the latest
|
||||
self.metallib_already_installed: bool = False
|
||||
|
||||
self.metallib_installed_path: str = ""
|
||||
|
||||
self.metallib_url: str = ""
|
||||
self.metallib_url_build: str = ""
|
||||
self.metallib_url_version: str = ""
|
||||
|
||||
self.metallib_url_is_exactly_match: bool = False
|
||||
|
||||
self.metallib_closest_match_url: str = ""
|
||||
self.metallib_closest_match_url_build: str = ""
|
||||
self.metallib_closest_match_url_version: str = ""
|
||||
|
||||
self.success: bool = False
|
||||
|
||||
self.error_msg: str = ""
|
||||
|
||||
self._get_latest_metallib()
|
||||
|
||||
|
||||
def _get_remote_metallibs(self) -> dict:
|
||||
"""
|
||||
Get the MetallibSupportPkg list from the API
|
||||
"""
|
||||
|
||||
global METALLIB_ASSET_LIST
|
||||
|
||||
logging.info("Pulling metallib list from MetallibSupportPkg API")
|
||||
if METALLIB_ASSET_LIST:
|
||||
return METALLIB_ASSET_LIST
|
||||
|
||||
try:
|
||||
results = network_handler.NetworkUtilities().get(
|
||||
METALLIB_API_LINK,
|
||||
headers={
|
||||
"User-Agent": f"OCLP/{self.constants.patcher_version}"
|
||||
},
|
||||
timeout=5
|
||||
)
|
||||
except (requests.exceptions.Timeout, requests.exceptions.TooManyRedirects, requests.exceptions.ConnectionError):
|
||||
logging.info("Could not contact MetallibSupportPkg API")
|
||||
return None
|
||||
|
||||
if results.status_code != 200:
|
||||
logging.info("Could not fetch Metallib list")
|
||||
return None
|
||||
|
||||
METALLIB_ASSET_LIST = results.json()
|
||||
|
||||
return METALLIB_ASSET_LIST
|
||||
|
||||
|
||||
def _get_latest_metallib(self) -> None:
|
||||
"""
|
||||
Get the latest MetallibSupportPkg PKG
|
||||
"""
|
||||
|
||||
parsed_version = cast(packaging.version.Version, packaging.version.parse(self.host_version))
|
||||
|
||||
if os_data.os_conversion.os_to_kernel(str(parsed_version.major)) < os_data.os_data.sequoia:
|
||||
self.error_msg = "MetallibSupportPkg is not required for macOS Sonoma or older"
|
||||
logging.warning(f"{self.error_msg}")
|
||||
return
|
||||
|
||||
self.metallib_installed_path = self._local_metallib_installed()
|
||||
if self.metallib_installed_path:
|
||||
logging.info(f"metallib already installed ({Path(self.metallib_installed_path).name}), skipping")
|
||||
self.metallib_already_installed = True
|
||||
self.success = True
|
||||
return
|
||||
|
||||
remote_metallib_version = self._get_remote_metallibs()
|
||||
|
||||
if remote_metallib_version is None:
|
||||
logging.warning("Failed to fetch metallib list, falling back to local metallib matching")
|
||||
|
||||
# First check if a metallib matching the current macOS version is installed
|
||||
# ex. 13.0.1 vs 13.0
|
||||
loose_version = f"{parsed_version.major}.{parsed_version.minor}"
|
||||
logging.info(f"Checking for metallibs loosely matching {loose_version}")
|
||||
self.metallib_installed_path = self._local_metallib_installed(match=loose_version, check_version=True)
|
||||
if self.metallib_installed_path:
|
||||
logging.info(f"Found matching metallib: {Path(self.metallib_installed_path).name}")
|
||||
self.metallib_already_installed = True
|
||||
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 metallibs matching {older_version}")
|
||||
self.metallib_installed_path = self._local_metallib_installed(match=older_version, check_version=True)
|
||||
if self.metallib_installed_path:
|
||||
logging.info(f"Found matching metallib: {Path(self.metallib_installed_path).name}")
|
||||
self.metallib_already_installed = True
|
||||
self.success = True
|
||||
return
|
||||
|
||||
logging.warning(f"Couldn't find metallib matching {self.host_version} or {older_version}, please install one manually")
|
||||
|
||||
self.error_msg = f"Could not contact MetallibSupportPkg API, and no metallib matching {self.host_version} ({self.host_build}) or {older_version} was installed.\nPlease ensure you have a network connection or manually install a metallib."
|
||||
|
||||
return
|
||||
|
||||
|
||||
# First check exact match
|
||||
for metallib in remote_metallib_version:
|
||||
if (metallib["build"] != self.host_build):
|
||||
continue
|
||||
self.metallib_url = metallib["url"]
|
||||
self.metallib_url_build = metallib["build"]
|
||||
self.metallib_url_version = metallib["version"]
|
||||
self.metallib_url_is_exactly_match = True
|
||||
break
|
||||
|
||||
# If no exact match, check for closest match
|
||||
if self.metallib_url == "":
|
||||
for metallib in remote_metallib_version:
|
||||
metallib_version = cast(packaging.version.Version, packaging.version.parse(metallib["version"]))
|
||||
if metallib_version > parsed_version:
|
||||
continue
|
||||
if metallib_version.major != parsed_version.major:
|
||||
continue
|
||||
if metallib_version.minor not in range(parsed_version.minor - 1, parsed_version.minor + 1):
|
||||
continue
|
||||
|
||||
# The metallib list is already sorted by version then date, so the first match is the closest
|
||||
self.metallib_closest_match_url = metallib["url"]
|
||||
self.metallib_closest_match_url_build = metallib["build"]
|
||||
self.metallib_closest_match_url_version = metallib["version"]
|
||||
self.metallib_url_is_exactly_match = False
|
||||
break
|
||||
|
||||
if self.metallib_url == "":
|
||||
if self.metallib_closest_match_url == "":
|
||||
logging.warning(f"No metallibs found for {self.host_build} ({self.host_version})")
|
||||
self.error_msg = f"No metallibs found for {self.host_build} ({self.host_version})"
|
||||
return
|
||||
logging.info(f"No direct match found for {self.host_build}, falling back to closest match")
|
||||
logging.info(f"Closest Match: {self.metallib_closest_match_url_build} ({self.metallib_closest_match_url_version})")
|
||||
|
||||
self.metallib_url = self.metallib_closest_match_url
|
||||
self.metallib_url_build = self.metallib_closest_match_url_build
|
||||
self.metallib_url_version = self.metallib_closest_match_url_version
|
||||
else:
|
||||
logging.info(f"Direct match found for {self.host_build} ({self.host_version})")
|
||||
|
||||
|
||||
# Check if this metallib is already installed
|
||||
self.metallib_installed_path = self._local_metallib_installed(match=self.metallib_url_build)
|
||||
if self.metallib_installed_path:
|
||||
logging.info(f"metallib already installed ({Path(self.metallib_installed_path).name}), skipping")
|
||||
self.metallib_already_installed = True
|
||||
self.success = True
|
||||
return
|
||||
|
||||
logging.info("Following metallib is recommended:")
|
||||
logging.info(f"- metallib Build: {self.metallib_url_build}")
|
||||
logging.info(f"- metallib Version: {self.metallib_url_version}")
|
||||
logging.info(f"- metallib URL: {self.metallib_url}")
|
||||
|
||||
self.success = True
|
||||
|
||||
|
||||
def _local_metallib_installed(self, match: str = None, check_version: bool = False) -> str:
|
||||
"""
|
||||
Check if a metallib is already installed
|
||||
"""
|
||||
|
||||
if not Path(METALLIB_INSTALL_PATH).exists():
|
||||
return None
|
||||
|
||||
for metallib_folder in Path(METALLIB_INSTALL_PATH).iterdir():
|
||||
if not metallib_folder.is_dir():
|
||||
continue
|
||||
if check_version:
|
||||
if match not in metallib_folder.name:
|
||||
continue
|
||||
else:
|
||||
if not metallib_folder.name.endswith(f"-{match}"):
|
||||
continue
|
||||
|
||||
return metallib_folder
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def retrieve_download(self, override_path: str = "") -> network_handler.DownloadObject:
|
||||
"""
|
||||
Retrieve MetallibSupportPkg PKG download object
|
||||
"""
|
||||
|
||||
self.success = False
|
||||
self.error_msg = ""
|
||||
|
||||
if self.metallib_already_installed:
|
||||
logging.info("No download required, metallib already installed")
|
||||
self.success = True
|
||||
return None
|
||||
|
||||
if self.metallib_url == "":
|
||||
self.error_msg = "Could not retrieve metallib catalog, no metallib to download"
|
||||
logging.error(self.error_msg)
|
||||
return None
|
||||
|
||||
logging.info(f"Returning DownloadObject for metallib: {Path(self.metallib_url).name}")
|
||||
self.success = True
|
||||
|
||||
metallib_download_path = self.constants.metallib_download_path if override_path == "" else Path(override_path)
|
||||
return network_handler.DownloadObject(self.metallib_url, metallib_download_path)
|
||||
|
||||
|
||||
def install_metallib(self, metallib: str = None) -> None:
|
||||
"""
|
||||
Install MetallibSupportPkg PKG
|
||||
"""
|
||||
|
||||
if not self.success:
|
||||
logging.error("Cannot install metallib, no metallib was successfully retrieved")
|
||||
return False
|
||||
|
||||
if self.metallib_already_installed:
|
||||
logging.info("No installation required, metallib already installed")
|
||||
return True
|
||||
|
||||
result = subprocess_wrapper.run_as_root([
|
||||
"/usr/sbin/installer", "-pkg", metallib if metallib else self.constants.metallib_download_path, "-target", "/"
|
||||
])
|
||||
if result.returncode != 0:
|
||||
subprocess_wrapper.log(result)
|
||||
return False
|
||||
|
||||
return True
|
||||
@@ -132,6 +132,8 @@ class PatcherValidation:
|
||||
if install_type in patchset[patch_subject][patch_core]:
|
||||
for install_directory in patchset[patch_subject][patch_core][install_type]:
|
||||
for install_file in patchset[patch_subject][patch_core][install_type][install_directory]:
|
||||
if patchset[patch_subject][patch_core][install_type][install_directory][install_file] in sys_patch_dict.DynamicPatchset:
|
||||
continue
|
||||
source_file = str(self.constants.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():
|
||||
logging.info(f"File not found: {source_file}")
|
||||
|
||||
@@ -660,13 +660,14 @@ class DetectRootPatch:
|
||||
"Settings: Requires AMFI exemption": self.amfi_must_disable,
|
||||
"Settings: Supports Auxiliary Cache": not self.requires_root_kc,
|
||||
"Settings: Kernel Debug Kit missing": self.missing_kdk if self.os_major >= os_data.os_data.ventura.value else False,
|
||||
"Settings: MetallibSupportPkg missing": self.os_major >= os_data.os_data.sequoia.value and any([self.kepler_gpu, self.ivy_gpu, self.haswell_gpu]),
|
||||
"Validation: Patching Possible": self.verify_patch_allowed(),
|
||||
"Validation: Unpatching Possible": self._verify_unpatch_allowed(),
|
||||
f"Validation: Unsupported Host OS": self.unsupported_os,
|
||||
f"Validation: SIP is enabled (Required: {self._check_sip()[2]} or higher)": self.sip_enabled,
|
||||
f"Validation: Currently Booted SIP: ({hex(py_sip_xnu.SipXnu().get_sip_status().value)})": self.sip_enabled,
|
||||
"Validation: SecureBootModel is enabled": self.sbm_enabled,
|
||||
f"Validation: {'AMFI' if self.constants.host_is_hackintosh is True or self._get_amfi_level_needed() > 2 else 'Library Validation'} is enabled": self.amfi_enabled if self.amfi_must_disable is True else False,
|
||||
f"Validation: {'AMFI' if self.constants.host_is_hackintosh is True or self._get_amfi_level_needed() > 2 else 'Library Validation'} is enabled": self.amfi_enabled if self.amfi_must_disable is True else False,
|
||||
"Validation: FileVault is enabled": self.fv_enabled,
|
||||
"Validation: System is dosdude1 patched": self.dosdude_patched,
|
||||
"Validation: WhateverGreen.kext missing": self.missing_whatever_green if self.nvidia_web is True else False,
|
||||
@@ -719,9 +720,7 @@ class DetectRootPatch:
|
||||
return True
|
||||
if any([self.kepler_gpu, self.ivy_gpu, self.haswell_gpu]):
|
||||
if Path("~/.dortania_developer").expanduser().exists():
|
||||
# Temporarily hard coded
|
||||
if Path("/Library/Application Support/Dortania/MetallibSupportPkg/15.0-24A5327a").exists():
|
||||
return True
|
||||
return True
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@@ -39,7 +39,8 @@ import logging
|
||||
import plistlib
|
||||
import subprocess
|
||||
|
||||
from pathlib import Path
|
||||
from pathlib import Path
|
||||
from functools import cache
|
||||
|
||||
from .mount import (
|
||||
RootVolumeMount,
|
||||
@@ -54,12 +55,16 @@ from .utilities import (
|
||||
|
||||
from .. import constants
|
||||
|
||||
from ..datasets import os_data
|
||||
from ..volume import generate_copy_arguments
|
||||
|
||||
from ..datasets import (
|
||||
os_data,
|
||||
sys_patch_dict
|
||||
)
|
||||
from ..support import (
|
||||
utilities,
|
||||
subprocess_wrapper
|
||||
subprocess_wrapper,
|
||||
metallib_handler
|
||||
)
|
||||
from . import (
|
||||
sys_patch_helpers,
|
||||
@@ -357,7 +362,7 @@ class PatchSysVolume:
|
||||
)
|
||||
|
||||
source_files_path = str(self.constants.payload_local_binaries_root_path)
|
||||
self._preflight_checks(required_patches, source_files_path)
|
||||
required_patches = self._preflight_checks(required_patches, source_files_path)
|
||||
for patch in required_patches:
|
||||
logging.info("- Installing Patchset: " + patch)
|
||||
for method_remove in ["Remove", "Remove Non-Root"]:
|
||||
@@ -429,13 +434,56 @@ class PatchSysVolume:
|
||||
self._write_patchset(required_patches)
|
||||
|
||||
|
||||
def _preflight_checks(self, required_patches: dict, source_files_path: Path) -> None:
|
||||
def _resolve_metallib_support_pkg(self) -> str:
|
||||
"""
|
||||
Resolves MetalLibSupportPkg
|
||||
"""
|
||||
metallib_obj = metallib_handler.MetalLibraryObject(self.constants, self.constants.detected_os_build, self.constants.detected_os_version)
|
||||
if metallib_obj.success is False:
|
||||
logging.error(f"Failed to find MetalLibSupportPkg: {metallib_obj.error_msg}")
|
||||
raise Exception(f"Failed to find MetalLibSupportPkg: {metallib_obj.error_msg}")
|
||||
|
||||
metallib_download_obj = metallib_obj.retrieve_download()
|
||||
if not metallib_download_obj:
|
||||
# Already downloaded, return path
|
||||
logging.info(f"Using MetalLibSupportPkg: {metallib_obj.metallib_installed_path}")
|
||||
return str(metallib_obj.metallib_installed_path)
|
||||
|
||||
metallib_download_obj.download(spawn_thread=False)
|
||||
if metallib_download_obj.download_complete is False:
|
||||
error_msg = metallib_download_obj.error_msg
|
||||
logging.error(f"Could not download MetalLibSupportPkg: {error_msg}")
|
||||
raise Exception(f"Could not download MetalLibSupportPkg: {error_msg}")
|
||||
|
||||
if metallib_obj.install_metallib() is False:
|
||||
logging.error("Failed to install MetalLibSupportPkg")
|
||||
raise Exception("Failed to install MetalLibSupportPkg")
|
||||
|
||||
# After install, check if it's present
|
||||
return self._resolve_metallib_support_pkg()
|
||||
|
||||
|
||||
@cache
|
||||
def _resolve_dynamic_patchset(self, variant: sys_patch_dict.DynamicPatchset) -> str:
|
||||
"""
|
||||
Resolves dynamic patchset to a path
|
||||
"""
|
||||
if variant == sys_patch_dict.DynamicPatchset.MetallibSupportPkg:
|
||||
return self._resolve_metallib_support_pkg()
|
||||
|
||||
raise Exception(f"Unknown Dynamic Patchset: {variant}")
|
||||
|
||||
|
||||
def _preflight_checks(self, required_patches: dict, source_files_path: Path) -> dict:
|
||||
"""
|
||||
Runs preflight checks before patching
|
||||
|
||||
Parameters:
|
||||
required_patches (dict): Patchset dictionary (from sys_patch_generate.GenerateRootPatchSets)
|
||||
source_files_path (Path): Path to the source files (PatcherSupportPkg)
|
||||
|
||||
Returns:
|
||||
dict: Updated patchset dictionary
|
||||
"""
|
||||
|
||||
logging.info("- Running Preflight Checks before patching")
|
||||
@@ -447,6 +495,9 @@ class PatchSysVolume:
|
||||
continue
|
||||
for install_patch_directory in required_patches[patch][method_type]:
|
||||
for install_file in required_patches[patch][method_type][install_patch_directory]:
|
||||
if required_patches[patch][method_type][install_patch_directory][install_file] in sys_patch_dict.DynamicPatchset:
|
||||
required_patches[patch][method_type][install_patch_directory][install_file] = self._resolve_dynamic_patchset(required_patches[patch][method_type][install_patch_directory][install_file])
|
||||
|
||||
source_file = required_patches[patch][method_type][install_patch_directory][install_file] + install_patch_directory + "/" + install_file
|
||||
|
||||
# Check whether to source from root
|
||||
@@ -477,6 +528,8 @@ class PatchSysVolume:
|
||||
|
||||
logging.info("- Finished Preflight, starting patching")
|
||||
|
||||
return required_patches
|
||||
|
||||
|
||||
# Entry Function
|
||||
def start_patch(self):
|
||||
|
||||
@@ -16,8 +16,11 @@ from pathlib import Path
|
||||
from .. import constants
|
||||
|
||||
from ..datasets import os_data
|
||||
from ..support import kdk_handler
|
||||
|
||||
from ..support import (
|
||||
kdk_handler,
|
||||
metallib_handler
|
||||
)
|
||||
from ..sys_patch import (
|
||||
sys_patch,
|
||||
)
|
||||
@@ -137,6 +140,95 @@ class SysPatchStartFrame(wx.Frame):
|
||||
return True
|
||||
|
||||
|
||||
def _metallib_download(self, frame: wx.Frame = None) -> bool:
|
||||
frame = self if not frame else frame
|
||||
|
||||
logging.info("MetallibSupportPkg missing, generating Metallib download frame")
|
||||
|
||||
header = wx.StaticText(frame, label="Downloading Metal Libraries", pos=(-1,5))
|
||||
header.SetFont(gui_support.font_factory(19, wx.FONTWEIGHT_BOLD))
|
||||
header.Centre(wx.HORIZONTAL)
|
||||
|
||||
subheader = wx.StaticText(frame, label="Fetching MetallibSupportPkg database...", pos=(-1, header.GetPosition()[1] + header.GetSize()[1] + 5))
|
||||
subheader.SetFont(gui_support.font_factory(13, wx.FONTWEIGHT_NORMAL))
|
||||
subheader.Centre(wx.HORIZONTAL)
|
||||
|
||||
progress_bar = wx.Gauge(frame, range=100, pos=(-1, subheader.GetPosition()[1] + subheader.GetSize()[1] + 5), size=(250, 20))
|
||||
progress_bar.Centre(wx.HORIZONTAL)
|
||||
|
||||
progress_bar_animation = gui_support.GaugePulseCallback(self.constants, progress_bar)
|
||||
progress_bar_animation.start_pulse()
|
||||
|
||||
# Set size of frame
|
||||
frame.SetSize((-1, progress_bar.GetPosition()[1] + progress_bar.GetSize()[1] + 35))
|
||||
frame.Show()
|
||||
|
||||
self.metallib_obj: metallib_handler.MetalLibraryObject = None
|
||||
def _metallib_thread_spawn():
|
||||
self.metallib_obj = metallib_handler.MetalLibraryObject(self.constants, self.constants.detected_os_build, self.constants.detected_os_version)
|
||||
|
||||
metallib_thread = threading.Thread(target=_metallib_thread_spawn)
|
||||
metallib_thread.start()
|
||||
|
||||
while metallib_thread.is_alive():
|
||||
wx.Yield()
|
||||
|
||||
if self.metallib_obj.success is False:
|
||||
progress_bar_animation.stop_pulse()
|
||||
progress_bar.SetValue(0)
|
||||
wx.MessageBox(f"Metallib download failed: {self.metallib_obj.error_msg}", "Error", wx.OK | wx.ICON_ERROR)
|
||||
return False
|
||||
|
||||
self.metallib_download_obj = self.metallib_obj.retrieve_download()
|
||||
if not self.metallib_download_obj:
|
||||
# Metallib is already downloaded
|
||||
return True
|
||||
|
||||
gui_download.DownloadFrame(
|
||||
self,
|
||||
title=self.title,
|
||||
global_constants=self.constants,
|
||||
download_obj=self.metallib_download_obj,
|
||||
item_name=f"Metallib Build {self.metallib_obj.metallib_url_build}"
|
||||
)
|
||||
if self.metallib_download_obj.download_complete is False:
|
||||
return False
|
||||
|
||||
logging.info("Metallib download complete, installing Metallib PKG")
|
||||
|
||||
header.SetLabel(f"Installing Metallib: {self.metallib_obj.metallib_url_build}")
|
||||
header.Centre(wx.HORIZONTAL)
|
||||
|
||||
subheader.SetLabel("Installing MetallibSupportPkg PKG...")
|
||||
subheader.Centre(wx.HORIZONTAL)
|
||||
|
||||
self.result = False
|
||||
def _install_metallib():
|
||||
self.result = self.metallib_obj.install_metallib()
|
||||
|
||||
install_thread = threading.Thread(target=_install_metallib)
|
||||
install_thread.start()
|
||||
|
||||
while install_thread.is_alive():
|
||||
wx.Yield()
|
||||
|
||||
if self.result is False:
|
||||
progress_bar_animation.stop_pulse()
|
||||
progress_bar.SetValue(0)
|
||||
wx.MessageBox(f"Metallib installation failed: {self.metallib_obj.error_msg}", "Error", wx.OK | wx.ICON_ERROR)
|
||||
return False
|
||||
|
||||
progress_bar_animation.stop_pulse()
|
||||
progress_bar.SetValue(100)
|
||||
|
||||
logging.info("Metallib installation complete")
|
||||
|
||||
for child in frame.GetChildren():
|
||||
child.Destroy()
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def _generate_modal(self, patches: dict = {}, variant: str = "Root Patching"):
|
||||
"""
|
||||
Create UI for root patching/unpatching
|
||||
@@ -227,6 +319,10 @@ class SysPatchStartFrame(wx.Frame):
|
||||
if self._kdk_download(self) is False:
|
||||
sys.exit(1)
|
||||
|
||||
if self.patches["Settings: MetallibSupportPkg missing"] is True:
|
||||
if self._metallib_download(self) is False:
|
||||
sys.exit(1)
|
||||
|
||||
self._generate_modal(self.patches, "Root Patching")
|
||||
self.return_button.Disable()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user