mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-24 03:50:14 +10:00
macOS Installer Creation: initial commit
This commit is contained in:
@@ -17,7 +17,7 @@ class OpenCoreLegacyPatcher:
|
|||||||
self.constants = constants.Constants()
|
self.constants = constants.Constants()
|
||||||
self.generate_base_data()
|
self.generate_base_data()
|
||||||
if utilities.check_cli_args() is None:
|
if utilities.check_cli_args() is None:
|
||||||
self.main_menu()
|
self.main_menu(True)
|
||||||
|
|
||||||
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()
|
||||||
@@ -38,7 +38,33 @@ class OpenCoreLegacyPatcher:
|
|||||||
else:
|
else:
|
||||||
print("- No arguments present, loading TUI")
|
print("- No arguments present, loading TUI")
|
||||||
|
|
||||||
def main_menu(self):
|
def first_setup(self):
|
||||||
|
# Order of operations:
|
||||||
|
# 1. Build OpenCore
|
||||||
|
# 2. Download macOS
|
||||||
|
# 3. Select USB drive
|
||||||
|
# 4. Format USB drive
|
||||||
|
# 5. Install OpenCore to ESP
|
||||||
|
# 6. flash macOS
|
||||||
|
# 7. Prompt user to reboot
|
||||||
|
build.BuildOpenCore(self.constants.custom_model or self.constants.computer.real_model, self.constants).build_opencore()
|
||||||
|
cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).download_macOS()
|
||||||
|
utilities.cls()
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def post_install(self):
|
||||||
|
# Order of operations:
|
||||||
|
# 1. Build OpenCore
|
||||||
|
# 2. Prompt drive to install OC to
|
||||||
|
# 3. Install OpenCore to ESP
|
||||||
|
# 4. Determine whether root patching needed
|
||||||
|
# 5. Prompt user to reboot
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
def main_menu(self, walkthrough):
|
||||||
response = None
|
response = None
|
||||||
while not (response and response == -1):
|
while not (response and response == -1):
|
||||||
title = [
|
title = [
|
||||||
@@ -67,17 +93,31 @@ class OpenCoreLegacyPatcher:
|
|||||||
|
|
||||||
menu = utilities.TUIMenu(title, "Please select an option: ", in_between=in_between, auto_number=True, top_level=True)
|
menu = utilities.TUIMenu(title, "Please select an option: ", in_between=in_between, auto_number=True, top_level=True)
|
||||||
|
|
||||||
options = (
|
if walkthrough is True:
|
||||||
[["Build OpenCore", build.BuildOpenCore(self.constants.custom_model or self.constants.computer.real_model, self.constants).build_opencore]]
|
options = (
|
||||||
if ((self.constants.custom_model or self.computer.real_model) in model_array.SupportedSMBIOS) or self.constants.allow_oc_everywhere is True
|
[["First Time Setup", self.first_setup]]
|
||||||
else []
|
if ((self.constants.custom_model or self.computer.real_model) in model_array.SupportedSMBIOS) or self.constants.allow_oc_everywhere is True
|
||||||
) + [
|
else []
|
||||||
["Install OpenCore to USB/internal drive", install.tui_disk_installation(self.constants).copy_efi],
|
) + [
|
||||||
["Post-Install Volume Patch", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).PatchVolume],
|
#["Post-Installation setup", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).closing_message],
|
||||||
["Change Model", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).change_model],
|
["Change Model", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).change_model],
|
||||||
["Patcher Settings", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).patcher_settings],
|
["Patcher Settings", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).patcher_settings],
|
||||||
["Credits", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).credits],
|
["Credits", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).credits],
|
||||||
]
|
["Legacy Menu", lambda: self.main_menu(False)],
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
options = (
|
||||||
|
[["Build OpenCore", build.BuildOpenCore(self.constants.custom_model or self.constants.computer.real_model, self.constants).build_opencore]]
|
||||||
|
if ((self.constants.custom_model or self.computer.real_model) in model_array.SupportedSMBIOS) or self.constants.allow_oc_everywhere is True
|
||||||
|
else []
|
||||||
|
) + [
|
||||||
|
["Install OpenCore to USB/internal drive", install.tui_disk_installation(self.constants).copy_efi],
|
||||||
|
["Post-Install Volume Patch", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).PatchVolume],
|
||||||
|
["Change Model", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).change_model],
|
||||||
|
["Patcher Settings", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).patcher_settings],
|
||||||
|
["Installer Creation", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).download_macOS],
|
||||||
|
["Credits", cli_menu.MenuOptions(self.constants.custom_model or self.computer.real_model, self.constants).credits],
|
||||||
|
]
|
||||||
|
|
||||||
for option in options:
|
for option in options:
|
||||||
menu.add_menu_option(option[0], function=option[1])
|
menu.add_menu_option(option[0], function=option[1])
|
||||||
|
|||||||
@@ -1074,4 +1074,4 @@ class BuildOpenCore:
|
|||||||
print(f" {self.constants.opencore_release_folder}")
|
print(f" {self.constants.opencore_release_folder}")
|
||||||
print("")
|
print("")
|
||||||
if self.constants.gui_mode is False:
|
if self.constants.gui_mode is False:
|
||||||
input("Press [Enter] to go back.\n")
|
input("Press [Enter] to continue\n")
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
# Handle misc CLI menu options
|
# Handle misc CLI menu options
|
||||||
# Copyright (C) 2020-2021, Dhinak G, Mykola Grymalyuk
|
# Copyright (C) 2020-2021, Dhinak G, Mykola Grymalyuk
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from resources import constants, utilities, defaults, sys_patch
|
from resources import constants, install, utilities, defaults, sys_patch, installer
|
||||||
from data import cpu_data, smbios_data, model_array, os_data
|
from data import cpu_data, smbios_data, model_array, os_data
|
||||||
|
|
||||||
|
|
||||||
@@ -1039,6 +1038,96 @@ system_profiler SPHardwareDataType | grep 'Model Identifier'
|
|||||||
|
|
||||||
response = menu.start()
|
response = menu.start()
|
||||||
|
|
||||||
|
def download_macOS(self):
|
||||||
|
utilities.cls()
|
||||||
|
utilities.header(["Create macOS installer"])
|
||||||
|
print(
|
||||||
|
"""
|
||||||
|
This option allows you to download and flash a macOS installer
|
||||||
|
to your USB drive.
|
||||||
|
|
||||||
|
1. Download macOS Installer
|
||||||
|
2. Use Existing Installer
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
change_menu = input("Select an option: ")
|
||||||
|
if change_menu == "1":
|
||||||
|
self.download_macOS_installer()
|
||||||
|
elif change_menu == "2":
|
||||||
|
self.find_local_installer()
|
||||||
|
else:
|
||||||
|
self.download_macOS()
|
||||||
|
|
||||||
|
def download_install_assistant(self, link):
|
||||||
|
installer.download_install_assistant(self.constants.payload_path, link)
|
||||||
|
# To avoid selecting the wrong installer by mistake, let user select the correct one
|
||||||
|
self.find_local_installer()
|
||||||
|
|
||||||
|
|
||||||
|
def download_macOS_installer(self):
|
||||||
|
response = None
|
||||||
|
while not (response and response == -1):
|
||||||
|
options = []
|
||||||
|
title = ["Select the macOS Installer you wish to download"]
|
||||||
|
menu = utilities.TUIMenu(title, "Please select an option: ", auto_number=True, top_level=True)
|
||||||
|
avalible_installers = installer.list_downloadable_macOS_installers(self.constants.payload_path, "DeveloperSeed")
|
||||||
|
if avalible_installers:
|
||||||
|
for app in avalible_installers:
|
||||||
|
options.append([f"macOS {avalible_installers[app]['Version']} ({avalible_installers[app]['Build']} - {utilities.human_fmt(avalible_installers[app]['Size'])})", lambda x=app: self.download_install_assistant(avalible_installers[x]['Link'])])
|
||||||
|
for option in options:
|
||||||
|
menu.add_menu_option(option[0], function=option[1])
|
||||||
|
response = menu.start()
|
||||||
|
|
||||||
|
def find_local_installer(self):
|
||||||
|
response = None
|
||||||
|
while not (response and response == -1):
|
||||||
|
options = []
|
||||||
|
title = ["Select the macOS Installer you wish to use"]
|
||||||
|
menu = utilities.TUIMenu(title, "Please select an option: ", auto_number=True, top_level=True)
|
||||||
|
avalible_installers = installer.list_local_macOS_installers()
|
||||||
|
if avalible_installers:
|
||||||
|
for app in avalible_installers:
|
||||||
|
options.append([f"{avalible_installers[app]['Short Name']}: {avalible_installers[app]['Version']} ({avalible_installers[app]['Build']})", lambda: self.list_disks(avalible_installers[app]['Path'])])
|
||||||
|
for option in options:
|
||||||
|
menu.add_menu_option(option[0], function=option[1])
|
||||||
|
response = menu.start()
|
||||||
|
|
||||||
|
def list_disks(self, installer_path):
|
||||||
|
disk = installer.select_disk_to_format()
|
||||||
|
if disk != None:
|
||||||
|
if installer.format_drive(disk) is True:
|
||||||
|
# Only install if OC is found
|
||||||
|
# Allows a user to create a macOS Installer without OCLP if desired
|
||||||
|
if self.constants.opencore_release_folder.exists():
|
||||||
|
# ESP will always be the first partition when formatted by disk utility
|
||||||
|
install.tui_disk_installation.install_opencore(self, f"disk{disk}", "1")
|
||||||
|
if installer.create_installer(installer_path, "OCLP-Installer") is True:
|
||||||
|
utilities.cls()
|
||||||
|
utilities.header(["Create macOS installer"])
|
||||||
|
print("Installer created successfully.")
|
||||||
|
input("Press enter to exit.")
|
||||||
|
self.closing_message()
|
||||||
|
else:
|
||||||
|
utilities.cls()
|
||||||
|
utilities.header(["Create macOS installer"])
|
||||||
|
print("Installer creation failed.")
|
||||||
|
input("Press enter to return to the previous.")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
exit()
|
||||||
|
|
||||||
|
def closing_message(self):
|
||||||
|
utilities.cls()
|
||||||
|
utilities.header(["Create macOS installer"])
|
||||||
|
print("Thank you for using OpenCore Legacy Patcher!")
|
||||||
|
print("Reboot your machine and select EFI Boot to load OpenCore")
|
||||||
|
print("")
|
||||||
|
print("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/")
|
||||||
|
print("\tDiscord: https://discord.gg/rqdPgH8xSN")
|
||||||
|
input("\nPress enter to exit: ")
|
||||||
|
exit()
|
||||||
|
|
||||||
big_sur = """Patches Root volume to fix misc issues such as:
|
big_sur = """Patches Root volume to fix misc issues such as:
|
||||||
|
|
||||||
- Non-Metal Graphics Acceleration
|
- Non-Metal Graphics Acceleration
|
||||||
|
|||||||
@@ -13,20 +13,6 @@ class tui_disk_installation:
|
|||||||
def __init__(self, versions):
|
def __init__(self, versions):
|
||||||
self.constants: constants.Constants = versions
|
self.constants: constants.Constants = versions
|
||||||
|
|
||||||
def determine_sd_card(self, media_name):
|
|
||||||
# Array filled with common SD Card names
|
|
||||||
# Note most USB-based SD Card readers generally report as "Storage Device"
|
|
||||||
# Thus no reliable way to detect further without parsing IOService output (kUSBProductString)
|
|
||||||
if (
|
|
||||||
"SD Card" in media_name or \
|
|
||||||
"SD/MMC" in media_name or \
|
|
||||||
"SDXC Reader" in media_name or \
|
|
||||||
"SD Reader" in media_name or \
|
|
||||||
"Card Reader" in media_name
|
|
||||||
):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def copy_efi(self):
|
def copy_efi(self):
|
||||||
utilities.cls()
|
utilities.cls()
|
||||||
utilities.header(["Installing OpenCore to Drive"])
|
utilities.header(["Installing OpenCore to Drive"])
|
||||||
@@ -109,6 +95,22 @@ Please build OpenCore first!"""
|
|||||||
|
|
||||||
if response == -1:
|
if response == -1:
|
||||||
return
|
return
|
||||||
|
self.install_opencore(disk_identifier, response)
|
||||||
|
|
||||||
|
def install_opencore(self, disk_identifier, response):
|
||||||
|
def determine_sd_card(media_name):
|
||||||
|
# Array filled with common SD Card names
|
||||||
|
# Note most USB-based SD Card readers generally report as "Storage Device"
|
||||||
|
# Thus no reliable way to detect further without parsing IOService output (kUSBProductString)
|
||||||
|
if (
|
||||||
|
"SD Card" in media_name or \
|
||||||
|
"SD/MMC" in media_name or \
|
||||||
|
"SDXC Reader" in media_name or \
|
||||||
|
"SD Reader" in media_name or \
|
||||||
|
"Card Reader" in media_name
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
# TODO: Apple Script fails in Yosemite(?) and older
|
# TODO: Apple Script fails in Yosemite(?) and older
|
||||||
args = [
|
args = [
|
||||||
@@ -134,8 +136,6 @@ Please build OpenCore first!"""
|
|||||||
["Copying OpenCore"], "Press [Enter] to go back.\n", ["An error occurred!"] + result.stderr.decode().split("\n") + ["", "Please report this to the devs at GitHub."]
|
["Copying OpenCore"], "Press [Enter] to go back.\n", ["An error occurred!"] + result.stderr.decode().split("\n") + ["", "Please report this to the devs at GitHub."]
|
||||||
).start()
|
).start()
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO: Remount if readonly
|
|
||||||
drive_host_info = plistlib.loads(subprocess.run(f"diskutil info -plist {disk_identifier}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
drive_host_info = plistlib.loads(subprocess.run(f"diskutil info -plist {disk_identifier}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||||
partition_info = plistlib.loads(subprocess.run(f"diskutil info -plist {disk_identifier}s{response}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
partition_info = plistlib.loads(subprocess.run(f"diskutil info -plist {disk_identifier}s{response}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||||
sd_type = drive_host_info["MediaName"]
|
sd_type = drive_host_info["MediaName"]
|
||||||
@@ -178,7 +178,7 @@ Please build OpenCore first!"""
|
|||||||
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 self.determine_sd_card(sd_type) is True:
|
if determine_sd_card(sd_type) is True:
|
||||||
print("- Adding SD Card icon")
|
print("- 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:
|
||||||
|
|||||||
174
resources/installer.py
Normal file
174
resources/installer.py
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
# Creates a macOS Installer
|
||||||
|
from pathlib import Path
|
||||||
|
import plistlib
|
||||||
|
import subprocess
|
||||||
|
from resources import utilities
|
||||||
|
|
||||||
|
def list_local_macOS_installers():
|
||||||
|
# Finds all applicable macOS installers
|
||||||
|
# within a user's /Applications folder
|
||||||
|
# Returns a list of installers
|
||||||
|
application_list = {}
|
||||||
|
|
||||||
|
for application in Path("/Applications").iterdir():
|
||||||
|
# Verify whether application has createinstallmedia
|
||||||
|
if (Path("/Applications") / Path(application) / Path("Contents/Resources/createinstallmedia")).exists():
|
||||||
|
plist = plistlib.load((Path("/Applications") / Path(application) / Path("Contents/Info.plist")).open("rb"))
|
||||||
|
try:
|
||||||
|
# Doesn't reflect true OS build, but best to report SDK in the event multiple installers are found with same version
|
||||||
|
app_version = plist["DTPlatformVersion"]
|
||||||
|
clean_name = plist["CFBundleDisplayName"]
|
||||||
|
try:
|
||||||
|
app_sdk = plist["DTSDKBuild"]
|
||||||
|
except KeyError:
|
||||||
|
app_sdk = "Unknown"
|
||||||
|
application_list.update({
|
||||||
|
application: {
|
||||||
|
"Short Name": clean_name,
|
||||||
|
"Version": app_version,
|
||||||
|
"Build": app_sdk,
|
||||||
|
"Path": application,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
return application_list
|
||||||
|
|
||||||
|
def create_installer(installer_path, volume_name):
|
||||||
|
# Creates a macOS installer
|
||||||
|
# Takes a path to the installer and the Volume
|
||||||
|
# Returns boolean on success status
|
||||||
|
|
||||||
|
createinstallmedia_path = Path("/Applications") / Path(installer_path) / Path("Contents/Resources/createinstallmedia")
|
||||||
|
|
||||||
|
# Sanity check in the event the user somehow deleted it between the time we found it and now
|
||||||
|
if (createinstallmedia_path).exists():
|
||||||
|
utilities.cls()
|
||||||
|
utilities.header(["Starting createinstallmedia"])
|
||||||
|
print("This will take some time, recommend making some coffee while you wait\n")
|
||||||
|
utilities.elevated([createinstallmedia_path, "--volume", f"/Volumes/{volume_name}", "--nointeraction"])
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("- Failed to find createinstallmedia")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def download_install_assistant(download_path, ia_link):
|
||||||
|
# Downloads and unpackages InstallAssistant.pkg into /Applications
|
||||||
|
utilities.download_file(ia_link, (Path(download_path) / Path("InstallAssistant.pkg")))
|
||||||
|
print("- Installing InstallAssistant.pkg to /Applications/")
|
||||||
|
utilities.elevated(["installer", "-pkg", (Path(download_path) / Path("InstallAssistant.pkg")), "-target", "/Applications"])
|
||||||
|
input("- Press ENTER to continue: ")
|
||||||
|
|
||||||
|
def list_downloadable_macOS_installers(download_path, catalog):
|
||||||
|
avalible_apps = {}
|
||||||
|
if catalog == "DeveloperSeed":
|
||||||
|
link = "https://swscan.apple.com/content/catalogs/others/index-12seed-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz"
|
||||||
|
elif catalog == "PublicSeed":
|
||||||
|
link = "https://swscan.apple.com/content/catalogs/others/index-12beta-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz"
|
||||||
|
else:
|
||||||
|
link = "https://swscan.apple.com/content/catalogs/others/index-12customerseed-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz"
|
||||||
|
|
||||||
|
# Download and unzip the catalog
|
||||||
|
utilities.download_file(link, (Path(download_path) / Path("seed.sucatalog.gz")))
|
||||||
|
subprocess.run(["gunzip", "-d", "-f", Path(download_path) / Path("seed.sucatalog.gz")])
|
||||||
|
catalog_plist = plistlib.load((Path(download_path) / Path("seed.sucatalog")).open("rb"))
|
||||||
|
|
||||||
|
for item in catalog_plist["Products"]:
|
||||||
|
try:
|
||||||
|
# Check if entry has SharedSupport and BuildManifest
|
||||||
|
# Ensures only Big Sur and newer Installers are listed
|
||||||
|
catalog_plist["Products"][item]["ExtendedMetaInfo"]["InstallAssistantPackageIdentifiers"]["SharedSupport"]
|
||||||
|
catalog_plist["Products"][item]["ExtendedMetaInfo"]["InstallAssistantPackageIdentifiers"]["BuildManifest"]
|
||||||
|
|
||||||
|
for bm_package in catalog_plist["Products"][item]["Packages"]:
|
||||||
|
if "BuildManifest.plist" in bm_package["URL"]:
|
||||||
|
utilities.download_file(bm_package["URL"], (Path(download_path) / Path("BuildManifest.plist")))
|
||||||
|
build_plist = plistlib.load((Path(download_path) / Path("BuildManifest.plist")).open("rb"))
|
||||||
|
version = build_plist["ProductVersion"]
|
||||||
|
build = build_plist["ProductBuildVersion"]
|
||||||
|
for ia_package in catalog_plist["Products"][item]["Packages"]:
|
||||||
|
if "InstallAssistant.pkg" in ia_package["URL"]:
|
||||||
|
download_link = ia_package["URL"]
|
||||||
|
size = ia_package["Size"]
|
||||||
|
integirty = ia_package["IntegrityDataURL"]
|
||||||
|
|
||||||
|
avalible_apps.update({
|
||||||
|
item: {
|
||||||
|
"Version": version,
|
||||||
|
"Build": build,
|
||||||
|
"Link": download_link,
|
||||||
|
"Size": size,
|
||||||
|
"integirty": integirty,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
return avalible_apps
|
||||||
|
|
||||||
|
def format_drive(disk_id):
|
||||||
|
# Formats a disk for macOS install
|
||||||
|
# Takes a disk ID
|
||||||
|
# Returns boolean on success status
|
||||||
|
header = f"# Formatting disk{disk_id} for macOS installer #"
|
||||||
|
box_length = len(header)
|
||||||
|
utilities.cls()
|
||||||
|
print("#" * box_length)
|
||||||
|
print(header)
|
||||||
|
print("#" * box_length)
|
||||||
|
print("")
|
||||||
|
#print(f"- Formatting disk{disk_id} for macOS installer")
|
||||||
|
format_process = utilities.elevated(["diskutil", "eraseDisk", "HFS+", "OCLP-Installer", f"disk{disk_id}"])
|
||||||
|
if format_process.returncode == 0:
|
||||||
|
print("- Disk formatted")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("- Failed to format disk")
|
||||||
|
print(f" Error Code: {format_process.returncode}")
|
||||||
|
input("\nPress Enter to exit")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def select_disk_to_format():
|
||||||
|
utilities.cls()
|
||||||
|
utilities.header(["Installing OpenCore to Drive"])
|
||||||
|
|
||||||
|
print("\nDisk picker is loading...")
|
||||||
|
|
||||||
|
all_disks = {}
|
||||||
|
# TODO: AllDisksAndPartitions is not supported in Snow Leopard and older
|
||||||
|
try:
|
||||||
|
# High Sierra and newer
|
||||||
|
disks = plistlib.loads(subprocess.run("diskutil list -plist physical".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||||
|
except ValueError:
|
||||||
|
# Sierra and older
|
||||||
|
disks = plistlib.loads(subprocess.run("diskutil list -plist".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||||
|
for disk in disks["AllDisksAndPartitions"]:
|
||||||
|
disk_info = plistlib.loads(subprocess.run(f"diskutil info -plist {disk['DeviceIdentifier']}".split(), stdout=subprocess.PIPE).stdout.decode().strip().encode())
|
||||||
|
try:
|
||||||
|
all_disks[disk["DeviceIdentifier"]] = {"identifier": disk_info["DeviceNode"], "name": disk_info["MediaName"], "size": disk_info["TotalSize"], "removable": disk_info["Internal"], "partitions": {}}
|
||||||
|
except KeyError:
|
||||||
|
# Avoid crashing with CDs installed
|
||||||
|
continue
|
||||||
|
menu = utilities.TUIMenu(
|
||||||
|
["Select Disk to write the macOS Installer onto"],
|
||||||
|
"Please select the disk you would like to install OpenCore to: ",
|
||||||
|
in_between=["Missing drives? Verify they are 14GB+ and external (ie. USB)", "", "Ensure all data is backed up on selected drive, entire drive will be erased!"],
|
||||||
|
return_number_instead_of_direct_call=True,
|
||||||
|
loop=True,
|
||||||
|
)
|
||||||
|
for disk in all_disks:
|
||||||
|
# Strip disks that are under 14GB (15,032,385,536 bytes)
|
||||||
|
# createinstallmedia isn't great at detecting if a disk has enough space
|
||||||
|
if not any(all_disks[disk]['size'] > 15032385536 for partition in all_disks[disk]):
|
||||||
|
continue
|
||||||
|
# Strip internal disks as well (avoid user formatting their SSD/HDD)
|
||||||
|
# Ensure user doesn't format their boot drive
|
||||||
|
if not any(all_disks[disk]['removable'] is False for partition in all_disks[disk]):
|
||||||
|
continue
|
||||||
|
menu.add_menu_option(f"{disk}: {all_disks[disk]['name']} ({utilities.human_fmt(all_disks[disk]['size'])})", key=disk[4:])
|
||||||
|
|
||||||
|
response = menu.start()
|
||||||
|
|
||||||
|
if response == -1:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return response
|
||||||
Reference in New Issue
Block a user