mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-24 12:00:15 +10:00
Add support for KDK downloads
This commit is contained in:
@@ -601,6 +601,10 @@ class Constants:
|
|||||||
def payload_local_binaries_root_path_zip(self):
|
def payload_local_binaries_root_path_zip(self):
|
||||||
return self.payload_path / Path("Universal-Binaries.zip")
|
return self.payload_path / Path("Universal-Binaries.zip")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def kdk_download_path(self):
|
||||||
|
return self.payload_path / Path("KDK.dmg")
|
||||||
|
|
||||||
|
|
||||||
sbm_values = [
|
sbm_values = [
|
||||||
"j137ap", # iMacPro1,1
|
"j137ap", # iMacPro1,1
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class OpenCoreLegacyPatcher:
|
|||||||
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()
|
||||||
self.constants.detected_os_build = os_probe.detect_kernel_build()
|
self.constants.detected_os_build = os_probe.detect_os_build()
|
||||||
self.constants.computer = device_probe.Computer.probe()
|
self.constants.computer = device_probe.Computer.probe()
|
||||||
self.constants.recovery_status = utilities.check_recovery()
|
self.constants.recovery_status = utilities.check_recovery()
|
||||||
self.computer = self.constants.computer
|
self.computer = self.constants.computer
|
||||||
|
|||||||
@@ -16,7 +16,13 @@ def detect_kernel_minor():
|
|||||||
return int(platform.uname().release.partition(".")[2].partition(".")[0])
|
return int(platform.uname().release.partition(".")[2].partition(".")[0])
|
||||||
|
|
||||||
|
|
||||||
def detect_kernel_build():
|
def detect_os_version():
|
||||||
|
# Return OS version
|
||||||
|
# Example Output: 12.0 (string)
|
||||||
|
return subprocess.run("sw_vers -productVersion".split(), stdout=subprocess.PIPE).stdout.decode().strip()
|
||||||
|
|
||||||
|
|
||||||
|
def detect_os_build():
|
||||||
# Return OS build
|
# Return OS build
|
||||||
# Example Output: 21A5522h (string)
|
# Example Output: 21A5522h (string)
|
||||||
return subprocess.run("sw_vers -buildVersion".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode().split("\n")[0]
|
return subprocess.run("sw_vers -buildVersion".split(), stdout=subprocess.PIPE).stdout.decode().strip()
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
# Additional support functions for sys_patch.py
|
# Additional support functions for sys_patch.py
|
||||||
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
# Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
from data import os_data
|
from data import os_data
|
||||||
from resources import generate_smbios
|
from resources import generate_smbios, utilities
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import plistlib
|
import plistlib
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from resources import constants
|
||||||
|
|
||||||
class sys_patch_helpers:
|
class sys_patch_helpers:
|
||||||
|
|
||||||
@@ -67,6 +70,24 @@ class sys_patch_helpers:
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def download_and_install_kdk(self, version: str, build: str):
|
||||||
|
# Note: cannot do lazy matching as we don't store old version/build numbers nor can we enumerate KDKs from the portal
|
||||||
|
URL_TEMPLATE = f"https://download.developer.apple.com/macOS/Kernel_Debug_Kit_{version}_build_{build}/Kernel_Debug_Kit_{version}_build_{build}.dmg"
|
||||||
|
|
||||||
|
print(f"- Downloading Apple KDK for macOS {version} build {build}")
|
||||||
|
if utilities.download_apple_developer_portal(URL_TEMPLATE, self.constants.kdk_download_path):
|
||||||
|
print("- Successfully downloaded KDK, installing")
|
||||||
|
# Set up a new temporary directory to mount the KDK to
|
||||||
|
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))
|
||||||
|
# Install the KDK
|
||||||
|
utilities.process_status(utilities.elevated(["installer", "-pkg", f"{mount_point}/KDK.pkg", "-target", "/"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT))
|
||||||
|
subprocess.run(["hdiutil", "detach", mount_point], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # Do not really care if this fails
|
||||||
|
print("- Successfully installed KDK")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("- Failed to download KDK")
|
||||||
|
return False
|
||||||
|
|
||||||
def determine_kdk_present(self, match_closest=False):
|
def determine_kdk_present(self, match_closest=False):
|
||||||
# Check if KDK is present
|
# Check if KDK is present
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import time
|
|||||||
import atexit
|
import atexit
|
||||||
import requests
|
import requests
|
||||||
import shutil
|
import shutil
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
from resources import constants, ioreg, amfi_detect
|
from resources import constants, ioreg, amfi_detect
|
||||||
from data import sip_data, os_data
|
from data import sip_data, os_data
|
||||||
@@ -376,7 +377,7 @@ def get_firmware_vendor(*, decode: bool = False):
|
|||||||
|
|
||||||
def verify_network_connection(url):
|
def verify_network_connection(url):
|
||||||
try:
|
try:
|
||||||
response = SESSION.head(url, timeout=5)
|
response = SESSION.head(url, timeout=5, allow_redirects=True)
|
||||||
return True
|
return True
|
||||||
except (requests.exceptions.Timeout, requests.exceptions.TooManyRedirects, requests.exceptions.ConnectionError, requests.exceptions.HTTPError):
|
except (requests.exceptions.Timeout, requests.exceptions.TooManyRedirects, requests.exceptions.ConnectionError, requests.exceptions.HTTPError):
|
||||||
return False
|
return False
|
||||||
@@ -384,33 +385,31 @@ def verify_network_connection(url):
|
|||||||
def download_file(link, location, is_gui=None, verify_checksum=False):
|
def download_file(link, location, is_gui=None, verify_checksum=False):
|
||||||
if verify_network_connection(link):
|
if verify_network_connection(link):
|
||||||
disable_sleep_while_running()
|
disable_sleep_while_running()
|
||||||
short_link = os.path.basename(link)
|
base_name = Path(link).name
|
||||||
|
|
||||||
if Path(location).exists():
|
if Path(location).exists():
|
||||||
Path(location).unlink()
|
Path(location).unlink()
|
||||||
header = SESSION.head(link).headers
|
|
||||||
try:
|
head_response = SESSION.head(link, allow_redirects=True)
|
||||||
# Try to get true file
|
|
||||||
# ex. Github's release links provides a "fake" header
|
|
||||||
# Thus need to resolve to the real link
|
|
||||||
link = SESSION.head(link).headers["location"]
|
|
||||||
header = SESSION.head(link).headers
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
try:
|
try:
|
||||||
# Handle cases where Content-Length has garbage or is missing
|
# Handle cases where Content-Length has garbage or is missing
|
||||||
total_file_size = int(SESSION.head(link).headers['Content-Length'])
|
total_file_size = int(head_response.headers['Content-Length'])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
total_file_size = 0
|
total_file_size = 0
|
||||||
|
|
||||||
if total_file_size > 1024:
|
if total_file_size > 1024:
|
||||||
file_size_rounded = round(total_file_size / 1024 / 1024, 2)
|
file_size_rounded = round(total_file_size / 1024 / 1024, 2)
|
||||||
file_size_string = f" of {file_size_rounded}MB"
|
file_size_string = f" of {file_size_rounded}MB"
|
||||||
else:
|
else:
|
||||||
file_size_string = ""
|
file_size_string = ""
|
||||||
|
|
||||||
response = SESSION.get(link, stream=True)
|
response = SESSION.get(link, stream=True)
|
||||||
|
|
||||||
# SU Catalog's link is quite long, strip to make it bearable
|
# SU Catalog's link is quite long, strip to make it bearable
|
||||||
if "sucatalog.gz" in short_link:
|
if "sucatalog.gz" in base_name:
|
||||||
short_link = "sucatalog.gz"
|
base_name = "sucatalog.gz"
|
||||||
header = f"# Downloading: {short_link} #"
|
|
||||||
|
header = f"# Downloading: {base_name} #"
|
||||||
box_length = len(header)
|
box_length = len(header)
|
||||||
box_string = "#" * box_length
|
box_string = "#" * box_length
|
||||||
dl = 0
|
dl = 0
|
||||||
@@ -463,6 +462,30 @@ def download_file(link, location, is_gui=None, verify_checksum=False):
|
|||||||
print(link)
|
print(link)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def download_apple_developer_portal(link, location, is_gui=None, verify_checksum=False):
|
||||||
|
TOKEN_URL_BASE = "https://developerservices2.apple.com/services/download?path="
|
||||||
|
remote_path = urllib.parse.urlparse(link).path
|
||||||
|
token_url = urllib.parse.urlunparse(urllib.parse.urlparse(TOKEN_URL_BASE)._replace(query=urllib.parse.urlencode({"path": remote_path})))
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = SESSION.get(token_url, timeout=5)
|
||||||
|
except (requests.exceptions.Timeout, requests.exceptions.TooManyRedirects, requests.exceptions.ConnectionError):
|
||||||
|
print(" - Could not contact Apple download servers")
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
response.raise_for_status()
|
||||||
|
except requests.exceptions.HTTPError:
|
||||||
|
if response.status_code == 400 and "The path specified is invalid" in response.text:
|
||||||
|
print(" - File does not exist on Apple download servers")
|
||||||
|
else:
|
||||||
|
print(" - Could not request download authorization from Apple download servers")
|
||||||
|
return None
|
||||||
|
|
||||||
|
return download_file(link, location, is_gui, verify_checksum)
|
||||||
|
|
||||||
|
|
||||||
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)))
|
||||||
@@ -550,7 +573,7 @@ def monitor_disk_output(disk):
|
|||||||
def validate_link(link):
|
def validate_link(link):
|
||||||
# Check if link is 404
|
# Check if link is 404
|
||||||
try:
|
try:
|
||||||
response = SESSION.head(link, timeout=5)
|
response = SESSION.head(link, timeout=5, allow_redirects=True)
|
||||||
if response.status_code == 404:
|
if response.status_code == 404:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user