diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..16520fcd4 --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +ignore = E501 \ No newline at end of file diff --git a/OpenCore-Patcher.command b/OpenCore-Patcher.command index 676ad22fd..443dffd4b 100755 --- a/OpenCore-Patcher.command +++ b/OpenCore-Patcher.command @@ -3,7 +3,6 @@ from __future__ import print_function import subprocess -from pathlib import Path from Resources import build, ModelArray, Versions, utilities @@ -12,27 +11,27 @@ PATCHER_VERSION = "0.0.9" class OpenCoreLegacyPatcher(): def __init__(self): + self.versions = Versions.Versions() self.custom_model: str = None self.current_model: str = None opencore_model: str = subprocess.run("nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-product".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode() if not opencore_model.startswith("nvram: Error getting variable"): - opencore_model = subprocess.run("nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-product".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - opencore_model = [line.strip().split(":oem-product ", 1)[1] for line in opencore_model.stdout.decode().split("\n") if line.strip().startswith("4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:")][0] + opencore_model = [line.strip().split(":oem-product ", 1)[1] for line in opencore_model.split("\n") if line.strip().startswith("4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:")][0] self.current_model = opencore_model else: self.current_model = subprocess.run("system_profiler SPHardwareDataType".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT) self.current_model = [line.strip().split(": ", 1)[1] for line in self.current_model.stdout.decode().split("\n") if line.strip().startswith("Model Identifier")][0] def build_opencore(self): - build.OpenCoreMenus().build_opencore_menu(self.custom_model or self.current_model) + build.OpenCoreMenus(self.versions).build_opencore_menu(self.custom_model or self.current_model) def install_opencore(self): utilities.cls() utilities.header(["Installing OpenCore to Drive"]) - if Path(Versions.opencore_path_done).exists(): + if self.versions.opencore_path_done.exists(): print("\nFound OpenCore in Build Folder") - build.BuildOpenCore.copy_efi() + build.BuildOpenCore(self.custom_model or self.current_model, self.versions).copy_efi() input("Press [Enter] to go back.") else: diff --git a/Resources/Versions.py b/Resources/Versions.py index ce28ea431..4fbe05a07 100644 --- a/Resources/Versions.py +++ b/Resources/Versions.py @@ -11,69 +11,100 @@ import subprocess import sys from pathlib import Path -# List build versions -opencore_version = "0.6.6" -lilu_version = "1.5.0" -whatevergreen_version = "1.4.6" -airportbcrmfixup_version = "2.1.2" -bcm570_version = "1.0.0" -marvel_version = "1.0.0" -nforce_version = "1.0.0" -mce_version = "1.0.0" -mousse_version = "0.93" -telemetrap_version = "1.0.0" -io80211high_sierra_version = "1.0.0" -io80211mojave_version = "1.0.0" -voodoohda_version = "296" -restrictevents_version = "1.0.0" -# List current location -os.chdir(os.path.dirname(os.path.realpath(__file__))) -os.chdir("..") -resource_path = os.getcwd() -current_path = Path(sys.executable).parent +class Versions: + def __init__(self): + self.default_opencore_version = "0.6.6" + self.opencore_version = "0.6.6" + self.lilu_version = "1.5.0" + self.whatevergreen_version = "1.4.6" + self.airportbcrmfixup_version = "2.1.2" + self.bcm570_version = "1.0.0" + self.marvel_version = "1.0.0" + self.nforce_version = "1.0.0" + self.mce_version = "1.0.0" + self.mousse_version = "0.93" + self.telemetrap_version = "1.0.0" + self.io80211high_sierra_version = "1.0.0" + self.io80211mojave_version = "1.0.0" + self.voodoohda_version = "296" + self.restrictevents_version = "1.0.0" -# Payload Location -# OpenCore -opencore_path = os.path.join(resource_path, "payloads/OpenCore/" "OpenCore-v%s.zip" % opencore_version) -plist_path = os.path.join(resource_path, "payloads/Config/v%s/" "config.plist" % opencore_version) + # Get resource path + self.current_path = Path(__file__).parent.parent.resolve() + self.payload_path = self.current_path / Path("payloads") -# ACPI -pci_ssdt_path = os.path.join(resource_path, "payloads/ACPI/" "SSDT-CPBG.aml") + # Payload Location + # OpenCore + @property + def opencore_path(self): return self.current_path / Path(f"payloads/OpenCore/OpenCore-v{self.opencore_version}.zip") + @property + def plist_path(self): return self.current_path / Path(f"payloads/Config/v{self.opencore_version}/config.plist") -# Drivers -nvme_driver_path = os.path.join(resource_path, "payloads/Drivers/" "NvmExpressDxe.efi") + # ACPI + @property + def pci_ssdt_path(self): return self.current_path / Path("payloads/ACPI/SSDT-CPBG.aml") -# Kexts -lilu_path = os.path.join(resource_path, "payloads/Kexts/Acidanthera/" "Lilu-v%s.zip" % lilu_version) -whatevergreen_path = os.path.join(resource_path, "payloads/Kexts/Acidanthera/" "WhateverGreen-v%s.zip" % whatevergreen_version) -airportbcrmfixup_path = os.path.join(resource_path, "payloads/Kexts/Acidanthera/" "AirportBrcmFixup-v%s.zip" % airportbcrmfixup_version) -restrictevents_path = os.path.join(resource_path, "payloads/Kexts/Acidanthera/" "RestrictEvents-v%s.zip" % restrictevents_version) -bcm570_path = os.path.join(resource_path, "payloads/Kexts/Ethernet/" "CatalinaBCM5701Ethernet-v%s.zip" % bcm570_version) -marvel_path = os.path.join(resource_path, "payloads/Kexts/Ethernet/" "MarvelYukonEthernet-v%s.zip" % marvel_version) -nforce_path = os.path.join(resource_path, "payloads/Kexts/Ethernet/" "nForceEthernet-v%s.zip" % nforce_version) -mce_path = os.path.join(resource_path, "payloads/Kexts/Misc/" "AppleMCEReporterDisabler-v%s.zip" % mce_version) -mousse_path = os.path.join(resource_path, "payloads/Kexts/SSE/" "AAAMouSSE-v%s.zip" % mousse_version) -telemetrap_path = os.path.join(resource_path, "payloads/Kexts/SSE/" "telemetrap-v%s.zip" % telemetrap_version) -io80211high_sierra_path = os.path.join(resource_path, "payloads/Kexts/Wifi/" "IO80211HighSierra-v%s.zip" % io80211high_sierra_version) -io80211mojave_path = os.path.join(resource_path, "payloads/Kexts/Wifi/" "IO80211Mojave-v%s.zip" % io80211mojave_version) -voodoohda_path = os.path.join(resource_path, "payloads/Kexts/Audio/" "VoodooHDA-v%s.zip" % voodoohda_version) + # Drivers + @property + def nvme_driver_path(self): return self.current_path / Path("payloads/Drivers/NvmExpressDxe.efi") -# Build Location -opencore_path_build = os.path.join(current_path, "Build-Folder/" "OpenCore-v%s.zip" % opencore_version) -plist_path_build = os.path.join(current_path, "Build-Folder/" "OpenCore-v%s/EFI/OC/" % opencore_version) -plist_path_build_full = os.path.join(current_path, "Build-Folder/" "OpenCore-v%s/EFI/OC/config.plist" % opencore_version) -acpi_path_build = os.path.join(current_path, "Build-Folder/" "OpenCore-v%s/EFI/OC/ACPI" % opencore_version) -drivers_path_build = os.path.join(current_path, "Build-Folder/" "OpenCore-v%s/EFI/OC/Drivers" % opencore_version) -kext_path_build = os.path.join(current_path, "Build-Folder/" "OpenCore-v%s/EFI/OC/Kexts" % opencore_version) -opencore_path_done = os.path.join(current_path, "Build-Folder/" "OpenCore-v%s" % opencore_version) -build_path = os.path.join(current_path, "Build-Folder/") -gui_path_build = os.path.join(current_path, "Build-Folder/" "OpenCore-v%s/EFI/OC/Resources" % opencore_version) + # Kexts + @property + def lilu_path(self): return self.current_path / Path(f"payloads/Kexts/Acidanthera/Lilu-v{self.lilu_version}.zip") + @property + def whatevergreen_path(self): return self.current_path / Path(f"payloads/Kexts/Acidanthera/WhateverGreen-v{self.whatevergreen_version}.zip") + @property + def airportbcrmfixup_path(self): return self.current_path / Path(f"payloads/Kexts/Acidanthera/AirportBrcmFixup-v{self.airportbcrmfixup_version}.zip") + @property + def restrictevents_path(self): return self.current_path / Path(f"payloads/Kexts/Acidanthera/RestrictEvents-v{self.restrictevents_version}.zip") + @property + def bcm570_path(self): return self.current_path / Path(f"payloads/Kexts/Ethernet/CatalinaBCM5701Ethernet-v{self.bcm570_version}.zip") + @property + def marvel_path(self): return self.current_path / Path(f"payloads/Kexts/Ethernet/MarvelYukonEthernet-v{self.marvel_version}.zip") + @property + def nforce_path(self): return self.current_path / Path(f"payloads/Kexts/Ethernet/nForceEthernet-v{self.nforce_version}.zip") + @property + def mce_path(self): return self.current_path / Path(f"payloads/Kexts/Misc/AppleMCEReporterDisabler-v{self.mce_version}.zip") + @property + def mousse_path(self): return self.current_path / Path(f"payloads/Kexts/SSE/AAAMouSSE-v{self.mousse_version}.zip") + @property + def telemetrap_path(self): return self.current_path / Path(f"payloads/Kexts/SSE/telemetrap-v{self.telemetrap_version}.zip") + @property + def io80211high_sierra_path(self): return self.current_path / Path(f"payloads/Kexts/Wifi/IO80211HighSierra-v{self.io80211high_sierra_version}.zip") + @property + def io80211mojave_path(self): return self.current_path / Path(f"payloads/Kexts/Wifi/IO80211Mojave-v{self.io80211mojave_version}.zip") + @property + def voodoohda_path(self): return self.current_path / Path(f"payloads/Kexts/Audio/VoodooHDA-v{self.voodoohda_version}.zip") -# Tools -macserial_path = os.path.join(resource_path, "payloads/" "Tools") + # Build Location + @property + def opencore_path_build(self): return self.current_path / Path(f"Build-Folder/OpenCore-v{self.opencore_version}.zip") + @property + def plist_path_build(self): return self.current_path / Path(f"Build-Folder/OpenCore-v{self.opencore_version}/EFI/OC/") + @property + def plist_path_build_full(self): return self.current_path / Path(f"Build-Folder/OpenCore-v{self.opencore_version}/EFI/OC/config.plist") + @property + def acpi_path_build(self): return self.current_path / Path(f"Build-Folder/OpenCore-v{self.opencore_version}/EFI/OC/ACPI") + @property + def drivers_path_build(self): return self.current_path / Path(f"Build-Folder/OpenCore-v{self.opencore_version}/EFI/OC/Drivers") + @property + def kext_path_build(self): return self.current_path / Path(f"Build-Folder/OpenCore-v{self.opencore_version}/EFI/OC/Kexts") + @property + def opencore_path_done(self): return self.current_path / Path(f"Build-Folder/OpenCore-v{self.opencore_version}") + @property + def build_path(self): return self.current_path / Path("Build-Folder/") + @property + def gui_path_build(self): return self.current_path / Path(f"Build-Folder/OpenCore-v{self.opencore_version}/EFI/OC/Resources") -# Icons -app_icon_path = os.path.join(resource_path, "OC-Patcher.icns") -icon_path = os.path.join(resource_path, "payloads/Icon/" ".VolumeIcon.icns") -gui_path = os.path.join(resource_path, "payloads/Icon/" "Resources.zip") + # Tools + @property + def macserial_path(self): return self.current_path / Path("payloads/Tools") + + # Icons + @property + def app_icon_path(self): return self.current_path / Path("OC-Patcher.icns") + @property + def icon_path(self): return self.current_path / Path(f"payloads/Icon/.VolumeIcon.icns") + @property + def gui_path(self): return self.current_path / Path(f"payloads/Icon/Resources.zip") diff --git a/Resources/build.py b/Resources/build.py index 74949f18e..a6dca72f8 100644 --- a/Resources/build.py +++ b/Resources/build.py @@ -15,62 +15,62 @@ from Resources import ModelArray, Versions, utilities class BuildOpenCore(): - def __init__(self, model, version): + def __init__(self, model, versions): self.model = model self.config = None - Versions.opencore_version = version + self.versions: Versions.Versions = versions def build_efi(self): utilities.cls() - if not Path(Versions.build_path).exists(): - Path(Versions.build_path).mkdir() + if not Path(self.versions.build_path).exists(): + Path(self.versions.build_path).mkdir() print("Created build folder") else: print("Build folder already present, skipping") - if Path(Versions.opencore_path_build).exists(): + if Path(self.versions.opencore_path_build).exists(): print("Deleting old copy of OpenCore zip") - Path(Versions.opencore_path_build).unlink() - if Path(Versions.opencore_path_done).exists(): + Path(self.versions.opencore_path_build).unlink() + if Path(self.versions.opencore_path_done).exists(): print("Deleting old copy of OpenCore folder") - shutil.rmtree(Versions.opencore_path_done) + shutil.rmtree(self.versions.opencore_path_done) print() - print("- Adding OpenCore v" + Versions.opencore_version) - shutil.copy(Versions.opencore_path, Versions.build_path) - zipfile.ZipFile(Versions.opencore_path_build).extractall(Versions.build_path) + print("- Adding OpenCore v" + self.versions.opencore_version) + shutil.copy(self.versions.opencore_path, self.versions.build_path) + zipfile.ZipFile(self.versions.opencore_path_build).extractall(self.versions.build_path) print("- Adding config.plist for OpenCore") # Setup config.plist for editing - shutil.copy(Versions.plist_path, Versions.plist_path_build) - self.config = plistlib.load(Path(Versions.plist_path_build_full).open("rb")) + shutil.copy(self.versions.plist_path, self.versions.plist_path_build) + self.config = plistlib.load(Path(self.versions.plist_path_build_full).open("rb")) for name, version, path, check in [ # Essential kexts - ("Lilu.kext", Versions.lilu_version, Versions.lilu_path, lambda: True), - ("WhateverGreen.kext", Versions.whatevergreen_version, Versions.whatevergreen_path, lambda: True), - ("RestrictEvents.kext", Versions.restrictevents_version, Versions.restrictevents_path, lambda: self.model in ModelArray.MacPro71), + ("Lilu.kext", self.versions.lilu_version, self.versions.lilu_path, lambda: True), + ("WhateverGreen.kext", self.versions.whatevergreen_version, self.versions.whatevergreen_path, lambda: True), + ("RestrictEvents.kext", self.versions.restrictevents_version, self.versions.restrictevents_path, lambda: self.model in ModelArray.MacPro71), # CPU patches - ("AppleMCEReporterDisabler.kext", Versions.mce_version, Versions.mce_path, lambda: self.model in ModelArray.DualSocket), - ("AAAMouSSE.kext", Versions.mousse_version, Versions.mousse_path, lambda: self.model in ModelArray.SSEEmulator), - ("telemetrap.kext", Versions.telemetrap_version, Versions.telemetrap_path, lambda: self.model in ModelArray.MissingSSE42), + ("AppleMCEReporterDisabler.kext", self.versions.mce_version, self.versions.mce_path, lambda: self.model in ModelArray.DualSocket), + ("AAAMouSSE.kext", self.versions.mousse_version, self.versions.mousse_path, lambda: self.model in ModelArray.SSEEmulator), + ("telemetrap.kext", self.versions.telemetrap_version, self.versions.telemetrap_path, lambda: self.model in ModelArray.MissingSSE42), # Ethernet patches - ("nForceEthernet.kext", Versions.nforce_version, Versions.nforce_path, lambda: self.model in ModelArray.EthernetNvidia), - ("MarvelYukonEthernet.kext", Versions.marvel_version, Versions.marvel_path, lambda: self.model in ModelArray.EthernetMarvell), - ("CatalinaBCM5701Ethernet.kext", Versions.bcm570_version, Versions.bcm570_path, lambda: self.model in ModelArray.EthernetBroadcom), + ("nForceEthernet.kext", self.versions.nforce_version, self.versions.nforce_path, lambda: self.model in ModelArray.EthernetNvidia), + ("MarvelYukonEthernet.kext", self.versions.marvel_version, self.versions.marvel_path, lambda: self.model in ModelArray.EthernetMarvell), + ("CatalinaBCM5701Ethernet.kext", self.versions.bcm570_version, self.versions.bcm570_path, lambda: self.model in ModelArray.EthernetBroadcom), # Legacy audio - ("VoodooHDA.kext", Versions.voodoohda_version, Versions.voodoohda_path, lambda: self.model in ModelArray.LegacyAudio) + ("VoodooHDA.kext", self.versions.voodoohda_version, self.versions.voodoohda_path, lambda: self.model in ModelArray.LegacyAudio) ]: self.enable_kext(name, version, path, check) # WiFi patches if self.model in ModelArray.WifiAtheros: - self.enable_kext("IO80211HighSierra.kext", Versions.io80211high_sierra_version, Versions.io80211high_sierra_path) + self.enable_kext("IO80211HighSierra.kext", self.versions.io80211high_sierra_version, self.versions.io80211high_sierra_path) self.get_kext_by_bundle_path("IO80211HighSierra.kext/Contents/PlugIns/AirPortAtheros40.kext")["Enabled"] = True if self.model in ModelArray.WifiBCM94331: - self.enable_kext("AirportBrcmFixup.kext", Versions.airportbcrmfixup_version, Versions.airportbcrmfixup_path) + self.enable_kext("AirportBrcmFixup.kext", self.versions.airportbcrmfixup_version, self.versions.airportbcrmfixup_path) self.get_kext_by_bundle_path("AirportBrcmFixup.kext/Contents/PlugIns/AirPortBrcmNIC_Injector.kext")["Enabled"] = True if self.model in ModelArray.EthernetNvidia: @@ -82,7 +82,7 @@ class BuildOpenCore(): property_path = "PciRoot(0x0)/Pci(0x1C,0x4)/Pci(0x0,0x0)" elif self.model in ("iMac13,1", "iMac13,2"): property_path = "PciRoot(0x0)/Pci(0x1C,0x3)/Pci(0x0,0x0)" - elif self.model in ("MacPro5,1"): + elif self.model == "MacPro5,1": property_path = "PciRoot(0x0)/Pci(0x1C,0x5)/Pci(0x0,0x0)" else: # Assumes we have a laptop with Intel chipset @@ -106,10 +106,10 @@ class BuildOpenCore(): # USB map map_name = f"USB-Map-{self.model}.zip" map_entry = f"USB-Map-{self.model}.kext" - usb_map_path = Path(Versions.current_path) / Path(f"payloads/Kexts/Maps/Zip/{map_name}") + usb_map_path = Path(self.versions.current_path) / Path(f"payloads/Kexts/Maps/Zip/{map_name}") if usb_map_path.exists(): print(f"- Adding {map_entry}") - shutil.copy(usb_map_path, Versions.kext_path_build) + shutil.copy(usb_map_path, self.versions.kext_path_build) self.get_kext_by_bundle_path("USB-Map-SMBIOS.kext")["Enabled"] = True self.get_kext_by_bundle_path("USB-Map-SMBIOS.kext")["BundlePath"] = map_entry @@ -120,14 +120,14 @@ class BuildOpenCore(): if self.model in ModelArray.HiDPIpicker: print("- Setting HiDPI picker") self.config["NVRAM"]["Add"]["4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14"]["UIScale"] = binascii.unhexlify("02") - + # Add OpenCanopy print("- Adding OpenCanopy GUI") - shutil.rmtree(Versions.gui_path_build) - shutil.copy(Versions.gui_path, Versions.plist_path_build) + shutil.rmtree(self.versions.gui_path_build) + shutil.copy(self.versions.gui_path, self.versions.plist_path_build) self.config["UEFI"]["Drivers"] = ["OpenCanopy.efi", "OpenRuntime.efi"] - plistlib.dump(self.config, Path(Versions.plist_path_build_full).open("wb"), sort_keys=True) + plistlib.dump(self.config, Path(self.versions.plist_path_build_full).open("wb"), sort_keys=True) def set_smbios(self): spoofed_model = self.model @@ -186,23 +186,23 @@ class BuildOpenCore(): return print(f"- Adding {kext_name} {kext_version}") - shutil.copy(kext_path, Versions.kext_path_build) + shutil.copy(kext_path, self.versions.kext_path_build) kext["Enabled"] = True def cleanup(self): print("- Cleaning up files") - for kext in Path(Versions.kext_path_build).glob("*.zip"): + for kext in Path(self.versions.kext_path_build).glob("*.zip"): with zipfile.ZipFile(kext) as zip_file: - zip_file.extractall(Versions.kext_path_build) + zip_file.extractall(self.versions.kext_path_build) kext.unlink() - shutil.rmtree((Path(Versions.kext_path_build) / Path("__MACOSX")), ignore_errors=True) + shutil.rmtree((Path(self.versions.kext_path_build) / Path("__MACOSX")), ignore_errors=True) - for item in Path(Versions.plist_path_build).glob("*.zip"): + for item in Path(self.versions.plist_path_build).glob("*.zip"): with zipfile.ZipFile(item) as zip_file: - zip_file.extractall(Versions.plist_path_build) + zip_file.extractall(self.versions.plist_path_build) item.unlink() - shutil.rmtree((Path(Versions.build_path) / Path("__MACOSX")), ignore_errors=True) - Path(Versions.opencore_path_build).unlink() + shutil.rmtree((Path(self.versions.build_path) / Path("__MACOSX")), ignore_errors=True) + Path(self.versions.opencore_path_build).unlink() def build_opencore(self): self.build_efi() @@ -210,12 +210,11 @@ class BuildOpenCore(): self.cleanup() print("") print("Your OpenCore EFI has been built at:") - print(f" {Versions.opencore_path_done}") + print(f" {self.versions.opencore_path_done}") print("") input("Press enter to go back") - @staticmethod - def copy_efi(): + def copy_efi(self): diskutil = [subprocess.run("diskutil list".split(), stdout=subprocess.PIPE).stdout.decode().strip()] menu = utilities.TUIMenu(["Select Disk"], "Please select the disk you want to install OpenCore to: ", in_between=diskutil, return_number_instead_of_direct_call=True, add_quit=False) for disk in [i for i in Path("/dev").iterdir() if re.fullmatch("disk[0-9]+", i.stem)]: @@ -231,9 +230,9 @@ class BuildOpenCore(): if (efi_dir / Path("EFI")).exists(): print("Removing preexisting EFI folder") shutil.rmtree(efi_dir / Path("EFI")) - if Path(Versions.opencore_path_done).exists(): - shutil.copytree(Versions.opencore_path_done, efi_dir) - shutil.copy(Versions.icon_path, efi_dir) + if Path(self.versions.opencore_path_done).exists(): + shutil.copytree(self.versions.opencore_path_done, efi_dir) + shutil.copy(self.versions.icon_path, efi_dir) print("OpenCore transfer complete") print("") else: @@ -243,28 +242,28 @@ class BuildOpenCore(): class OpenCoreMenus(): - def __init__(self): - self.version = Versions.opencore_version + def __init__(self, versions): + self.versions: Versions.Versions = versions def change_opencore_version(self): utilities.cls() utilities.header(["Change OpenCore Version"]) - print(f"\nCurrent OpenCore version: {self.version}\nSupported versions: 0.6.3, 0.6.4") + print(f"\nCurrent OpenCore version: {self.versions.opencore_version}\nSupported versions: 0.6.6 (recommended), 0.6.5, 0.6.4, 0.6.3") version = input("Please enter the desired OpenCore version: ").strip() if version: - self.version = version + self.versions.opencore_version = version def build_opencore_menu(self, model): response = None while not (response and response == -1): title = [ - f"Build OpenCore v{self.version} EFI", + f"Build OpenCore v{self.versions.opencore_version} EFI", "Selected Model: " + model ] menu = utilities.TUIMenu(title, "Please select an option: ", auto_number=True) options = [ - ["Build OpenCore", lambda: BuildOpenCore(model, self.version).build_opencore()], + ["Build OpenCore", lambda: BuildOpenCore(model, self.versions).build_opencore()], ["Change OpenCore Version", self.change_opencore_version], ]