diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000000..56c34a3f39
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,13 @@
+[MASTER]
+
+init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.dirname(find_pylintrc()))"
+
+[MESSAGES CONTROL]
+
+disable=unused-import,
+ subprocess-run-check,
+ line-too-long,
+ too-few-public-methods,
+ missing-module-docstring,
+ missing-class-docstring,
+ missing-function-docstring
\ No newline at end of file
diff --git a/Build-App.command b/Build-App.command
new file mode 100755
index 0000000000..d5ecf2a0cb
--- /dev/null
+++ b/Build-App.command
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+from __future__ import print_function
+
+from shutil import copy
+from shutil import rmtree
+from distutils.dir_util import copy_tree
+
+import os
+import json
+import subprocess
+import sys
+import zipfile
+
+os.chdir(os.path.dirname(os.path.realpath(__file__)))
+current_path = os.getcwd()
+
+print(current_path)
+
+# File location
+command_path = os.path.join(current_path, "OpenCore-Patcher.command")
+resources_path = os.path.join(current_path, "Resources/")
+payloads_path = os.path.join(current_path, "payloads/")
+icns_path = os.path.join(current_path, "OC-Patcher.icns")
+plist_path = os.path.join(current_path, "Info.plist")
+
+app_path = os.path.join(current_path, "App/")
+app_app_path = os.path.join(current_path, "App/OpenCore-Patcher.app/")
+contents_path = os.path.join(current_path, "App/OpenCore-Patcher.app/Contents/")
+app_macos_path = os.path.join(current_path, "App/OpenCore-Patcher.app/Contents/MacOS/")
+app_macos_payload_path = os.path.join(current_path, "App/OpenCore-Patcher.app/Contents/MacOS/payloads")
+app_macos_resources_path = os.path.join(current_path, "App/OpenCore-Patcher.app/Contents/MacOS/Resources")
+app_resources_path = os.path.join(current_path, "App/OpenCore-Patcher.app/Contents/Resources/")
+
+
+if os.path.exists(app_path):
+ print("Cleaning App folder")
+ rmtree(app_path)
+
+print("Creating new App folder")
+os.mkdir(app_path)
+os.mkdir(app_app_path)
+os.mkdir(contents_path)
+os.mkdir(app_macos_path)
+os.mkdir(app_resources_path)
+
+copy(command_path, app_macos_path)
+copy_tree(resources_path, app_macos_resources_path)
+copy_tree(payloads_path, app_macos_payload_path)
+copy(icns_path, app_resources_path)
+copy(plist_path, contents_path)
+copy(icns_path, app_macos_path)
+
diff --git a/OpenCore-Patcher.command b/OpenCore-Patcher.command
index d8e113c95e..676ad22fdf 100755
--- a/OpenCore-Patcher.command
+++ b/OpenCore-Patcher.command
@@ -1,234 +1,108 @@
-#!/usr/bin/env python
-from __future__ import print_function
+#!/usr/bin/env python3
-from shutil import copy
-from shutil import rmtree
+from __future__ import print_function
-import os
-import json
import subprocess
-import sys
-import zipfile
-
-from Resources import *
-
-
-# Allow py2 and 3 support
-try:
- input = raw_input
-except NameError:
- pass
-
-# List build versions
-patcher_version = "0.0.9"
-
-CustomSMBIOS=False
-MainMenu=True
-MenuWidth = 52
-header = '#' * MenuWidth
-subheader = '-' * MenuWidth
-
-while MainMenu:
- os.system('clear')
-
- print(header)
- print(" OpenCore Legacy patcher v%s" % patcher_version)
- print(" Current Model: %s" % BuildOpenCore.current_model)
- print(header)
- print("")
- if BuildOpenCore.current_model not in ModelArray.SupportedSMBIOS:
- print(" Your model is not supported by this patcher!")
- print("")
- print(" If you plan to create the USB for another machine,")
- print(" please select option 5")
- print(subheader)
- print("")
- elif BuildOpenCore.current_model in ("MacPro3,1", "iMac7,1"):
- print(" This model is supported")
- print(" However please ensure the CPU have been upgraded")
- print(" to support SSE4.1+")
- print(subheader)
- print("")
- else:
- print(" This model is supported")
- print(subheader)
- print("")
- print(" 1. Build OpenCore")
- print(" 2. Install OpenCore to USB/internal drive")
- print(" 3. Change model")
- print(" 4. Credits")
- print(" 5. Exit")
- print("")
-
- MainMenu = input('Please select an option: ')
-
- if MainMenu=="1":
- OpenCoreBuilderMenu=True
- while OpenCoreBuilderMenu:
- os.system('clear')
-
- print(header)
- print(" Build OpenCore v%s for model: %s" % (Versions.opencore_version, BuildOpenCore.current_model))
- print(header)
- print("")
- print(" 1. Auto build OpenCore")
- print(" 2. Change OpenCore version")
- print(" 3. Return to main menu")
- print("")
-
- OpenCoreBuilderMenu = input('Please select an option: ')
-
- if OpenCoreBuilderMenu=="1":
- AutoBuilderMenu=True
- while AutoBuilderMenu:
- os.system('clear')
- print(header)
- print(" Building OpenCore for model: %s" % BuildOpenCore.current_model)
- print(header)
- print("")
- print("The current working directory:")
- print (" %s" % Versions.current_path)
- print("")
- BuildOpenCore.BuildEFI()
- #BuildOpenCore.BuildGUI()
- BuildOpenCore.BuildSMBIOS()
- BuildOpenCore.SavePlist()
- BuildOpenCore.CleanBuildFolder()
- print("")
- print("Your OpenCore EFI has been built at:")
- print(" %s" % Versions.opencore_path_done)
- print("")
- AutoBuilderMenu = input("Press any key to return to previous menu: ")
- if AutoBuilderMenu=="1":
- print("Returning to previous menu...")
- AutoBuilderMenu=False
- OpenCoreBuilderMenu=False
- elif OpenCoreBuilderMenu=="2":
- ChangeOCversion=True
- while ChangeOCversion:
- os.system('clear')
- print(header)
- print(" Current OpenCore version: %s" % Versions.opencore_version)
- print(header)
- print("")
- print(" Supported versions: 0.6.3, 0.6.4")
- print("")
- OpenCoreOption = input('Please enter the OpenCore you want (Press enter to exit): ')
- if OpenCoreOption == "":
- print("Exiting...")
- ChangeOCversion=False
- MainMenu=True
- else:
- print("")
- print(" New SMBIOS: %s" % OpenCoreOption)
- print("")
- ChangeOCversionYN = input("Is this correct? (y/n)")
- if ChangeOCversionYN in {"y", "Y", "yes", "Yes"}:
- ChangeOCversion=False
- Versions.opencore_version = OpenCoreOption
- MainMenu=True
- elif OpenCoreBuilderMenu=="3":
- print("\n Returning to main menu...")
- OpenCoreBuilderMenu=False
- MainMenu=True
- else:
- print("\n Not Valid Choice Try again")
- OpenCoreBuilderMenu = True
-
-
- elif MainMenu=="2":
- print("\n Not yet implemented")
- OpenCoreInstallerMenu=True
- while OpenCoreInstallerMenu:
- os.system('clear')
-
- print(header)
- print(" Install OpenCore to drive")
- print(header)
- print("")
- print(" 1. Install to USB/internal drive")
- print(" 2. Return to main menu")
- print("")
-
- OpenCoreInstallerMenu = input('Please select an option: ')
-
- if OpenCoreInstallerMenu=="1":
- os.system('clear')
- if os.path.exists(Versions.opencore_path_done):
- print("Found OpenCore in Build Folder")
- BuildOpenCore.ListDiskutil()
- BuildOpenCore.MoveOpenCore()
-
- else:
- print("OpenCore folder missing!")
- print("Please build OpenCore first")
- print("")
- OpenCoreInstallerMenu = input("Press any key to exit: ")
- if OpenCoreInstallerMenu=="1":
- print("Returning to main menu...")
- OpenCoreInstallerMenu=False
- elif OpenCoreInstallerMenu=="2":
- print("\n Returning to main menu...")
- OpenCoreInstallerMenu=False
- MainMenu=True
+from pathlib import Path
+
+from Resources import build, ModelArray, Versions, utilities
+
+PATCHER_VERSION = "0.0.9"
+
+
+class OpenCoreLegacyPatcher():
+ def __init__(self):
+ 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]
+ 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)
+
+ def install_opencore(self):
+ utilities.cls()
+ utilities.header(["Installing OpenCore to Drive"])
+
+ if Path(Versions.opencore_path_done).exists():
+ print("\nFound OpenCore in Build Folder")
+ build.BuildOpenCore.copy_efi()
+ input("Press [Enter] to go back.")
+
+ else:
+ utilities.TUIOnlyPrint(["Installing OpenCore to Drive"],
+ "Press [Enter] to go back.\n",
+ ["""OpenCore folder missing!
+Please build OpenCore first!"""]).start()
+
+ def change_model(self):
+ utilities.cls()
+ utilities.header(["Select Different Model"])
+ print("""
+Tip: Run the following command on the target machine to find the model identifier:
+
+system_profiler SPHardwareDataType | grep 'Model Identifier'
+ """)
+ self.custom_model = input("Please enter the model identifier of the target machine: ").strip()
+
+ def credits(self):
+ utilities.TUIOnlyPrint(["Credits"], "Press enter to go back\n",
+ ["""Many thanks to the following:
+
+ - Acidanthera:\tOpenCore, kexts and other tools
+ - DhinakG:\t\tWriting and maintaining this patcher
+ - Khronokernel:\tWriting and maintaining this patcher
+ - Syncretic:\t\tAAAMouSSE and telemetrap
+ - Slice:\t\tVoodooHDA"""]).start()
+
+ def main_menu(self):
+ response = None
+ while not (response and response == -1):
+ title = [
+ f"OpenCore Legacy Patcher v{PATCHER_VERSION}",
+ f"Selected Model: {self.custom_model or self.current_model}"
+ ]
+
+ if (self.custom_model or self.current_model) not in ModelArray.SupportedSMBIOS:
+ in_between = [
+ 'Your model is not supported by this patcher!',
+ '',
+ 'If you plan to create the USB for another machine, please select the "Change Model" option in the menu.'
+ ]
+ elif not self.custom_model and self.current_model in ("MacPro3,1", "iMac7,1") and \
+ "SSE4.1" not in subprocess.run("sysctl machdep.cpu.features".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode():
+ in_between = [
+ 'Your model requires a CPU upgrade to a CPU supporting SSE4.1+ to be supported by this patcher!',
+ '',
+ 'If you plan to create the USB for another machine, please select option 5'
+ ]
+ elif self.custom_model in ("MacPro3,1", "iMac7,1"):
+ in_between = ["This model is supported",
+ "However please ensure the CPU has been upgraded to support SSE4.1+"
+ ]
else:
- print("\n Not Valid Choice Try again")
- OpenCoreInstallerMenu = True
-
- elif MainMenu=="3":
- SMBIOSMenu=True
- while SMBIOSMenu:
- os.system('clear')
-
- print(header)
- print(" Enter a new SMBIOS")
- print(header)
- print("")
- print(" Tip: Run this command on the machine to find the SMBIOS")
- print("")
- print(" system_profiler SPHardwareDataType | grep 'Model Identifier'")
- print("")
- SMBIOSOption = input('Please enter the SMBIOS of your machine (Press enter to exit): ')
- if SMBIOSOption == "":
- print("Exiting...")
- SMBIOSMenu=False
- MainMenu=True
- else:
- print("")
- print(" New SMBIOS: %s" % SMBIOSOption)
- print("")
- SMBIOSMenuYN = input("Is this correct? (y/n)")
- if SMBIOSMenuYN in {"y", "Y", "yes", "Yes"}:
- SMBIOSMenu=False
- BuildOpenCore.current_model = SMBIOSOption
- MainMenu=True
- CustomSMBIOS=True
- elif MainMenu=="4":
- CreditMenu=True
- while CreditMenu:
- os.system('clear')
-
- print(header)
- print(" Credits")
- print(header)
- print("")
- print(" Many thanks to the following:")
- print("")
- print(" - Acidanthera: OpenCore, kexts and other tools")
- print(" - DhinakG: Writing and maintaining this Patcher")
- print(" - Khronokernel: Writing and maintaining this Patcher")
- print(" - Syncretic: AAAMouSSE and telemetrap")
- print(" - Slice: VoodooHDA")
- print("")
- CreditMenu = input(" Press any key to exit: ")
- print("Returning to main menu...")
- CreditMenu=False
- MainMenu=True
-
- elif MainMenu=="5":
- print("\n Closing program...")
- sys.exit(1)
- else:
- print("\n Not Valid Choice Try again")
- MainMenu=True
+ in_between = ["This model is supported"]
+
+ menu = utilities.TUIMenu(title, "Please select an option: ", in_between=in_between, auto_number=True, top_level=True)
+
+ options = ([["Build OpenCore", self.build_opencore]] if ((self.custom_model or self.current_model) in ModelArray.SupportedSMBIOS) else []) + [
+ ["Install OpenCore to USB/internal drive", self.install_opencore],
+ ["Change Model", self.change_model],
+ ["Credits", self.credits]
+ ]
+
+ for option in options:
+ menu.add_menu_option(option[0], function=option[1])
+
+ response = menu.start()
+
+ print("Bye")
+
+OpenCoreLegacyPatcher().main_menu()
diff --git a/OpenCore-Patcher.spec b/OpenCore-Patcher.spec
new file mode 100644
index 0000000000..17e72ff41f
--- /dev/null
+++ b/OpenCore-Patcher.spec
@@ -0,0 +1,37 @@
+# -*- mode: python ; coding: utf-8 -*-
+
+block_cipher = None
+
+
+a = Analysis(['OpenCore-Patcher.command'],
+ pathex=['/Users/dhinak/Documents/GitHub/Opencore-Legacy-Patcher'],
+ binaries=[],
+ datas=[('payloads', 'payloads'), ('Resources', 'Resources')],
+ hiddenimports=[],
+ hookspath=[],
+ runtime_hooks=[],
+ excludes=[],
+ win_no_prefer_redirects=False,
+ win_private_assemblies=False,
+ cipher=block_cipher,
+ noarchive=False)
+pyz = PYZ(a.pure, a.zipped_data,
+ cipher=block_cipher)
+exe = EXE(pyz,
+ a.scripts,
+ a.binaries,
+ a.zipfiles,
+ a.datas,
+ [],
+ name='OpenCore-Patcher',
+ debug=False,
+ bootloader_ignore_signals=False,
+ strip=False,
+ upx=True,
+ upx_exclude=[],
+ runtime_tmpdir=None,
+ console=True )
+app = BUNDLE(exe,
+ name='OpenCore-Patcher.app',
+ icon=None,
+ bundle_identifier=None)
diff --git a/Resources/BuildOpenCore.py b/Resources/BuildOpenCore.py
deleted file mode 100644
index c6ffb4cdf1..0000000000
--- a/Resources/BuildOpenCore.py
+++ /dev/null
@@ -1,399 +0,0 @@
-# Commands for building the EFI and SMBIOS
-
-from __future__ import print_function
-
-from shutil import copy
-from shutil import rmtree
-from distutils.dir_util import copy_tree
-
-import os
-import json
-import subprocess
-import sys
-import zipfile
-
-from Resources import Versions
-from Resources import ModelArray
-
-# Allow py2 and 3 support
-try:
- input = raw_input
-except NameError:
- pass
-
-# Find SMBIOS of machine
-opencore_model = subprocess.Popen(["NVRAM", "4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-product"], stdout=subprocess.PIPE).communicate()[0]
-if opencore_model not in ("NVRAM: Error getting variable - '4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-product': (iokit/common) data was not found"):
- print("Detected OpenCore machine")
- opencore_model = subprocess.Popen("nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:oem-product".split(), stdout=subprocess.PIPE)
- opencore_model = [line.strip().split(":oem-product ", 1)[1] for line in opencore_model.stdout.read().split("\n") if line.strip().startswith("4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:")][0]
- current_model = opencore_model
-else:
- print("No OpenCore detected")
- current_model = subprocess.Popen("system_profiler SPHardwareDataType".split(), stdout=subprocess.PIPE)
- current_model = [line.strip().split(": ", 1)[1] for line in current_model.stdout.read().split("\n") if line.strip().startswith("Model Identifier")][0]
- print("Current Model: %s" % current_model)
-
-OCExist = False
-
-def BuildEFI():
-
- if not os.path.exists(Versions.build_path):
- os.makedirs(Versions.build_path)
- print("Created Build Folder")
- else:
- print("Build Folder already present, skipping")
- # Copy OpenCore into Build Folder
-
- if os.path.exists(Versions.opencore_path_build):
- print("Deleting old copy of OpenCore zip")
- os.remove(Versions.opencore_path_build)
- if os.path.exists(Versions.opencore_path_done):
- print("Deleting old copy of OpenCore folder")
- rmtree(Versions.opencore_path_done)
- print("")
- print("- Adding OpenCore v%s" % Versions.opencore_version)
- copy(Versions.opencore_path, Versions.build_path)
- zipfile.ZipFile(Versions.opencore_path_build).extractall(Versions.build_path)
-
- print("- Adding config.plist v%s" % Versions.opencore_version)
- # Setup config.plist for editing
- copy(Versions.plist_path, Versions.plist_path_build)
- with open(Versions.plist_path_build_full, 'r') as file :
- Versions.plist_data = file.read()
- # Adding must have kexts
- print("- Adding Lilu v%s" % Versions.lilu_version)
- copy(Versions.lilu_path, Versions.kext_path_build)
-
- print("- Adding WhateverGreen v%s" % Versions.whatevergreen_version)
- copy(Versions.whatevergreen_path, Versions.kext_path_build)
-
- if current_model in ModelArray.MacPro71:
- print("- Adding RestrictEvents v%s" % Versions.restrictevents_version)
- copy(Versions.restrictevents_path, Versions.kext_path_build)
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
-
- # Checks for kexts
- # CPU Kext Patches
- if current_model in ModelArray.DualSocket:
- print("- Adding AppleMCEReporterDisabler v%s" % Versions.mce_version)
- copy(Versions.mce_path, Versions.kext_path_build)
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
-
- if current_model in ModelArray.SSEEmulator:
- print("- Adding AAAMouSSE v%s" % Versions.mousse_version)
- copy(Versions.mousse_path, Versions.kext_path_build)
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
- if current_model in ModelArray.MissingSSE42:
- print("- Adding telemetrap v%s" % Versions.telemetrap_version)
- copy(Versions.telemetrap_path, Versions.kext_path_build)
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
-
- # Ethernet Patches
-
- if current_model in ModelArray.EthernetNvidia:
- print("- Adding nForceEthernet v%s" % Versions.nforce_version)
- copy(Versions.nforce_path, Versions.kext_path_build)
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
- if current_model in ModelArray.EthernetMarvell:
- print("- Adding MarvelYukonEthernet v%s" % Versions.marvel_version)
- copy(Versions.marvel_path, Versions.kext_path_build)
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
- if current_model in ModelArray.EthernetBroadcom:
- print("- Adding CatalinaBCM5701Ethernet v%s" % Versions.bcm570_version)
- copy(Versions.bcm570_path, Versions.kext_path_build)
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
-
- # Wifi Patches
-
- if current_model in ModelArray.WifiAtheros:
- print("- Adding IO80211HighSierra v%s" % Versions.io80211high_sierra_version)
- copy(Versions.io80211high_sierra_path, Versions.kext_path_build)
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
- #if current_model in ModelArray.WifiBCM94328:
- # print("- Wifi patches currently unsupported")
- #if current_model in ModelArray.WifiBCM94322:
- # print("- Adding IO80211Mojave %s" % Versions.io80211mojave_version)
- # copy(Versions.io80211mojave_path, Versions.kext_path_build)
- # Versions.plist_data = Versions.plist_data.replace(
- # "",
- # ""
- # )
- # Versions.plist_data = Versions.plist_data.replace(
- # "",
- # ""
- # )
- #if current_model in ModelArray.WifiBCM943224:
- # print("- Adding IO80211Mojave %s" % Versions.io80211mojave_version)
- # copy(Versions.io80211mojave_path, Versions.kext_path_build)
- # Versions.plist_data = Versions.plist_data.replace(
- # "",
- # ""
- # )
- # Versions.plist_data = Versions.plist_data.replace(
- # "",
- # ""
- # )
- if current_model in ModelArray.WifiBCM94331:
- print("- Adding AirportBrcmFixup and appling fake ID")
- copy(Versions.airportbcrmfixup_path, Versions.kext_path_build)
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
- if current_model in ModelArray.EthernetNvidia:
- # Nvidia chipsets all have the same path to ARPT
- Versions.plist_data = Versions.plist_data.replace(
- "#PciRoot(0x0)/Pci(0x1C,0x1)/Pci(0x0,0x0)",
- "PciRoot(0x0)/Pci(0x15,0x0)/Pci(0x0,0x0)"
- )
- if current_model in ("MacBookAir2,1", "MacBookAir3,1", "MacBookAir3,2" ):
- Versions.plist_data = Versions.plist_data.replace(
- "#PciRoot(0x0)/Pci(0x1C,0x1)/Pci(0x0,0x0)",
- "PciRoot(0x0)/Pci(0x15,0x0)/Pci(0x0,0x0)"
- )
- elif current_model in ("iMac7,1", "iMac8,1" ):
- Versions.plist_data = Versions.plist_data.replace(
- "#PciRoot(0x0)/Pci(0x1C,0x1)/Pci(0x0,0x0)",
- "PciRoot(0x0)/Pci(0x1C,0x4)/Pci(0x0,0x0)"
- )
- elif current_model in ("iMac13,1", "iMac13,2"):
- Versions.plist_data = Versions.plist_data.replace(
- "#PciRoot(0x0)/Pci(0x1C,0x1)/Pci(0x0,0x0)",
- "PciRoot(0x0)/Pci(0x1C,0x3)/Pci(0x0,0x0)"
- )
- elif current_model in ("MacPro5,1"):
- Versions.plist_data = Versions.plist_data.replace(
- "#PciRoot(0x0)/Pci(0x1C,0x1)/Pci(0x0,0x0)",
- "PciRoot(0x0)/Pci(0x1C,0x5)/Pci(0x0,0x0)"
- )
- else:
- # Assumes we have a laptop with Intel chipset
- Versions.plist_data = Versions.plist_data.replace(
- "#PciRoot(0x0)/Pci(0x1C,0x1)/Pci(0x0,0x0)",
- "PciRoot(0x0)/Pci(0x1C,0x1)/Pci(0x0,0x0)"
- )
- if current_model in ModelArray.LegacyHID:
- print("- Adding legacy IOHIDFamily Patch")
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
-
- if current_model in ModelArray.LegacyAudio:
- print("- Adding VoodooHDA v%s" % Versions.voodoohda_version)
- copy(Versions.voodoohda_path, Versions.kext_path_build)
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
-
- if current_model in ModelArray.pciSSDT:
- print("- Adding SSDT-CPBG")
- copy(Versions.pci_ssdt_path, Versions.acpi_path_build)
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
-
- usb_map_path = os.path.join(Versions.current_path, "payloads/Kexts/Maps/Zip/" "USB-Map-%s.zip" % current_model)
- if os.path.exists(usb_map_path):
- print("- Adding USB Map for %s" % current_model)
- copy(usb_map_path, Versions.kext_path_build)
- map_name = ("USB-Map-%s.kext" % current_model)
- Versions.plist_data = Versions.plist_data.replace(
- "",
- ""
- )
- Versions.plist_data = Versions.plist_data.replace(
- "USB-Map-SMBIOS.kext",
- map_name
- )
-
- if current_model in ModelArray.DualGPUPatch:
- print("- Adding dual GPU patch")
- Versions.plist_data = Versions.plist_data.replace(
- "debug=0x100",
- "debug=0x100 agdpmod=pikera"
- )
- if current_model in ModelArray.HiDPIpicker:
- print("- Setting HiDPI picker")
- Versions.plist_data = Versions.plist_data.replace(
- "AQ==",
- "Ag=="
- )
-
-
-def BuildGUI():
- print("- Adding OpenCanopy GUI")
- rmtree(Versions.gui_path_build)
- copy(Versions.gui_path, Versions.plist_path_build)
- Versions.plist_data = Versions.plist_data.replace(
- "#OpenCanopy.efi",
- "OpenCanopy.efi"
- )
-
-def BuildSMBIOS():
- # Set new SMBIOS
- new_model = current_model
- if current_model in ModelArray.MacBookAir61:
- print("- Spoofing to MacBookAir6,1")
- new_model = "MacBookAir6,1"
- elif current_model in ModelArray.MacBookAir62:
- print("- Spoofing to MacBookAir6,2")
- new_model = "MacBookAir6,2"
- elif current_model in ModelArray.MacBookPro111:
- print("- Spoofing to MacBookPro11,1")
- new_model = "MacBookPro11,1"
- elif current_model in ModelArray.MacBookPro112:
- print("- Spoofing to MacBookPro11,2")
- new_model = "MacBookPro11,2"
- elif current_model in ModelArray.Macmini71:
- print("- Spoofing to Macmini7,1")
- new_model = "Macmini7,1"
- elif current_model in ModelArray.iMac151:
- print("- Spoofing to iMac15,1")
- new_model = "iMac15,1"
- elif current_model in ModelArray.iMac144:
- print("- Spoofing to iMac14,4")
- new_model = "iMac14,4"
- elif current_model in ModelArray.MacPro71:
- print("- Spoofing to MacPro7,1")
- new_model = "MacPro7,1"
-
- # Grab serials from macserial
- serialPatch = subprocess.Popen(["xattr", "-cr", "./payloads/tools/macserial"], stdout=subprocess.PIPE).communicate()[0]
- print(serialPatch)
- serialData = subprocess.Popen((r"./payloads/tools/macserial -g -m " + new_model + " -n 1").split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- serialData = serialData.stdout.read().strip().split(" | ")
-
- # Patch SMBIOS
- Versions.plist_data = Versions.plist_data.replace(
- "iMac19,1",
- new_model
- )
-
- if serialData == "['']":
- # Used as a backup for when macserial fails
- print("Failed to load macserial")
- else:
- # Patch Number Serial
- Versions.plist_data = Versions.plist_data.replace(
- "W00000000001",
- serialData[0]
- )
- # Patch MLB
- Versions.plist_data = Versions.plist_data.replace(
- "M0000000000000001",
- serialData[1]
- )
-
- # Patch UUID
- uuidGen = subprocess.Popen(["uuidgen"], stdout=subprocess.PIPE).communicate()[0]
- Versions.plist_data = Versions.plist_data.replace(
- "00000000-0000-0000-0000-000000000000",
- uuidGen
- )
-
-def SavePlist():
- with open(Versions.plist_path_build_full, 'w') as file:
- file.write(Versions.plist_data)
-
-def CleanBuildFolder():
- # Clean up Build Folder
- print("")
- print("Cleaning build folder")
- os.chdir(Versions.kext_path_build)
- for item in os.listdir(Versions.kext_path_build):
- if item.endswith(".zip"):
- file_name = os.path.abspath(item)
- zip_ref = zipfile.ZipFile(file_name)
- zip_ref.extractall(Versions.kext_path_build)
- zip_ref.close()
- os.remove(file_name)
- # Clean up Python's unzip
- if os.path.exists("__MACOSX"):
- rmtree("__MACOSX")
- os.chdir(Versions.plist_path_build)
- os.chdir(Versions.plist_path_build)
- for item in os.listdir(Versions.plist_path_build):
- if item.endswith(".zip"):
- file_name = os.path.abspath(item)
- zip_ref = zipfile.ZipFile(file_name)
- zip_ref.extractall(Versions.plist_path_build)
- zip_ref.close()
- os.remove(file_name)
- if os.path.exists("__MACOSX"):
- rmtree("__MACOSX")
- os.chdir(Versions.build_path)
- if os.path.exists("__MACOSX"):
- rmtree("__MACOSX")
- os.remove(Versions.opencore_path_build)
- os.chdir(Versions.current_path)
-
-def ListDiskutil():
- DiskMenu = True
- while DiskMenu:
- os.system('clear')
- print("Loading diskutil...(This may take some time)")
- diskList = subprocess.Popen(["diskutil", "list"], stdout=subprocess.PIPE).communicate()[0]
- print(diskList)
- ChosenDisk = input('Please select the disk you want to install OpenCore to(ie. disk1): ')
- ChosenDisk = ChosenDisk + "s1"
- print("Trying to mount %s" % ChosenDisk)
- diskMount = subprocess.Popen(["sudo", "diskutil", "mount", ChosenDisk], stdout=subprocess.PIPE).communicate()[0]
- print(diskMount)
- DiskMenu = input("Press any key to continue: ")
-
-def MoveOpenCore():
- print("")
- efiVol = "/Volumes/EFI"
- if os.path.exists(efiVol):
- print("Coping OpenCore onto Volumes/EFI")
- if os.path.exists("/Volumes/EFI/EFI"):
- print("Cleaning EFI folder")
- rmtree("/Volumes/EFI/EFI")
- if os.path.exists(Versions.opencore_path_done):
- copy_tree(Versions.opencore_path_done, efiVol)
- copy(Versions.icon_path, efiVol)
- print("OpenCore transfer complete")
- print("")
- else:
- print("Couldn't find EFI partition")
- print("Please ensure your drive is formatted as GUID Partition Table")
- print("")
-
-def MountOpenCore():
- subprocess.Popen((r"sudo diskutil mount $(nvram 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102:boot-path | sed 's/.*GPT,\([^,]*\),.*/\1/')").split())
\ No newline at end of file
diff --git a/Resources/Versions.py b/Resources/Versions.py
index b0b6f8d5d5..ce28ea431c 100644
--- a/Resources/Versions.py
+++ b/Resources/Versions.py
@@ -9,6 +9,7 @@
import json
import subprocess
import sys
+from pathlib import Path
# List build versions
opencore_version = "0.6.6"
@@ -29,33 +30,34 @@
# List current location
os.chdir(os.path.dirname(os.path.realpath(__file__)))
os.chdir("..")
-current_path = os.getcwd()
+resource_path = os.getcwd()
+current_path = Path(sys.executable).parent
# Payload Location
# OpenCore
-opencore_path = os.path.join(current_path, "payloads/OpenCore/" "OpenCore-v%s.zip" % opencore_version)
-plist_path = os.path.join(current_path, "payloads/Config/v%s/" "config.plist" % opencore_version)
+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)
# ACPI
-pci_ssdt_path = os.path.join(current_path, "payloads/ACPI/" "SSDT-CPBG.aml")
+pci_ssdt_path = os.path.join(resource_path, "payloads/ACPI/" "SSDT-CPBG.aml")
# Drivers
-nvme_driver_path = os.path.join(current_path, "payloads/Drivers/" "NvmExpressDxe.efi")
+nvme_driver_path = os.path.join(resource_path, "payloads/Drivers/" "NvmExpressDxe.efi")
# Kexts
-lilu_path = os.path.join(current_path, "payloads/Kexts/Acidanthera/" "Lilu-v%s.zip" % lilu_version)
-whatevergreen_path = os.path.join(current_path, "payloads/Kexts/Acidanthera/" "WhateverGreen-v%s.zip" % whatevergreen_version)
-airportbcrmfixup_path = os.path.join(current_path, "payloads/Kexts/Acidanthera/" "AirportBrcmFixup-v%s.zip" % airportbcrmfixup_version)
-restrictevents_path = os.path.join(current_path, "payloads/Kexts/Acidanthera/" "RestrictEvents-v%s.zip" % restrictevents_version)
-bcm570_path = os.path.join(current_path, "payloads/Kexts/Ethernet/" "CatalinaBCM5701Ethernet-v%s.zip" % bcm570_version)
-marvel_path = os.path.join(current_path, "payloads/Kexts/Ethernet/" "MarvelYukonEthernet-v%s.zip" % marvel_version)
-nforce_path = os.path.join(current_path, "payloads/Kexts/Ethernet/" "nForceEthernet-v%s.zip" % nforce_version)
-mce_path = os.path.join(current_path, "payloads/Kexts/Misc/" "AppleMCEReporterDisabler-v%s.zip" % mce_version)
-mousse_path = os.path.join(current_path, "payloads/Kexts/SSE/" "AAAMouSSE-v%s.zip" % mousse_version)
-telemetrap_path = os.path.join(current_path, "payloads/Kexts/SSE/" "telemetrap-v%s.zip" % telemetrap_version)
-io80211high_sierra_path = os.path.join(current_path, "payloads/Kexts/Wifi/" "IO80211HighSierra-v%s.zip" % io80211high_sierra_version)
-io80211mojave_path = os.path.join(current_path, "payloads/Kexts/Wifi/" "IO80211Mojave-v%s.zip" % io80211mojave_version)
-voodoohda_path = os.path.join(current_path, "payloads/Kexts/Audio/" "VoodooHDA-v%s.zip" % voodoohda_version)
+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)
# Build Location
opencore_path_build = os.path.join(current_path, "Build-Folder/" "OpenCore-v%s.zip" % opencore_version)
@@ -65,13 +67,13 @@
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, r'Build-Folder/')
+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)
# Tools
-macserial_path = os.path.join(current_path, "payloads/" "Tools")
+macserial_path = os.path.join(resource_path, "payloads/" "Tools")
# Icons
-app_icon_path = os.path.join(current_path, "OC-Patcher.icns")
-icon_path = os.path.join(current_path, "payloads/Icon/" ".VolumeIcon.icns")
-gui_path = os.path.join(current_path, "payloads/Icon/" "Resources.zip")
\ No newline at end of file
+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")
diff --git a/Resources/build.py b/Resources/build.py
new file mode 100644
index 0000000000..74949f18ec
--- /dev/null
+++ b/Resources/build.py
@@ -0,0 +1,275 @@
+# Commands for building the EFI and SMBIOS
+
+from __future__ import print_function
+
+import binascii
+import plistlib
+import re
+import shutil
+import subprocess
+import uuid
+import zipfile
+from pathlib import Path
+
+from Resources import ModelArray, Versions, utilities
+
+
+class BuildOpenCore():
+ def __init__(self, model, version):
+ self.model = model
+ self.config = None
+ Versions.opencore_version = version
+
+ def build_efi(self):
+ utilities.cls()
+ if not Path(Versions.build_path).exists():
+ Path(Versions.build_path).mkdir()
+ print("Created build folder")
+ else:
+ print("Build folder already present, skipping")
+
+ if Path(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():
+ print("Deleting old copy of OpenCore folder")
+ shutil.rmtree(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 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"))
+
+ 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),
+ # 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),
+ # 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),
+ # Legacy audio
+ ("VoodooHDA.kext", Versions.voodoohda_version, 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.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.get_kext_by_bundle_path("AirportBrcmFixup.kext/Contents/PlugIns/AirPortBrcmNIC_Injector.kext")["Enabled"] = True
+
+ if self.model in ModelArray.EthernetNvidia:
+ # Nvidia chipsets all have the same path to ARPT
+ property_path = "PciRoot(0x0)/Pci(0x15,0x0)/Pci(0x0,0x0)"
+ if self.model in ("MacBookAir2,1", "MacBookAir3,1", "MacBookAir3,2"):
+ property_path = "PciRoot(0x0)/Pci(0x15,0x0)/Pci(0x0,0x0)"
+ elif self.model in ("iMac7,1", "iMac8,1"):
+ 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"):
+ property_path = "PciRoot(0x0)/Pci(0x1C,0x5)/Pci(0x0,0x0)"
+ else:
+ # Assumes we have a laptop with Intel chipset
+ property_path = "PciRoot(0x0)/Pci(0x1C,0x1)/Pci(0x0,0x0)"
+ print("- Applying fake ID for WiFi")
+ self.config["DeviceProperties"]["Add"][property_path] = {
+ "device-id": binascii.unhexlify("ba430000"),
+ "compatible": "pci14e4,43ba"
+ }
+
+ # HID patches
+ if self.model in ModelArray.LegacyHID:
+ print("- Adding IOHIDFamily patch")
+ self.get_item_by_kv(self.config["Kernel"]["Patch"], "Identifier", "com.apple.iokit.IOHIDFamily")["Enabled"] = True
+
+ # SSDT patches
+ if self.model in ModelArray.pciSSDT:
+ print("- Adding SSDT-CPBG.aml")
+ self.get_item_by_kv(self.config["ACPI"]["Add"], "Path", "SSDT-CPBG.aml")["Enabled"] = True
+
+ # 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}")
+ if usb_map_path.exists():
+ print(f"- Adding {map_entry}")
+ shutil.copy(usb_map_path, 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
+
+ if self.model in ModelArray.DualGPUPatch:
+ print("- Adding dual GPU patch")
+ self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " agdpmod=pikera"
+
+ 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)
+ self.config["UEFI"]["Drivers"] = ["OpenCanopy.efi", "OpenRuntime.efi"]
+
+ plistlib.dump(self.config, Path(Versions.plist_path_build_full).open("wb"), sort_keys=True)
+
+ def set_smbios(self):
+ spoofed_model = self.model
+ if self.model in ModelArray.MacBookAir61:
+ print("- Spoofing to MacBookAir6,1")
+ spoofed_model = "MacBookAir6,1"
+ elif self.model in ModelArray.MacBookAir62:
+ print("- Spoofing to MacBookAir6,2")
+ spoofed_model = "MacBookAir6,2"
+ elif self.model in ModelArray.MacBookPro111:
+ print("- Spoofing to MacBookPro11,1")
+ spoofed_model = "MacBookPro11,1"
+ elif self.model in ModelArray.MacBookPro112:
+ print("- Spoofing to MacBookPro11,2")
+ spoofed_model = "MacBookPro11,2"
+ elif self.model in ModelArray.Macmini71:
+ print("- Spoofing to Macmini7,1")
+ spoofed_model = "Macmini7,1"
+ elif self.model in ModelArray.iMac151:
+ print("- Spoofing to iMac15,1")
+ spoofed_model = "iMac15,1"
+ elif self.model in ModelArray.iMac144:
+ print("- Spoofing to iMac14,4")
+ spoofed_model = "iMac14,4"
+ elif self.model in ModelArray.MacPro71:
+ print("- Spoofing to MacPro7,1")
+ spoofed_model = "MacPro7,1"
+ macserial_output = subprocess.run((f"./payloads/tools/macserial -g -m {spoofed_model} -n 1").split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ macserial_output = macserial_output.stdout.decode().strip().split(" | ")
+ self.config["PlatformInfo"]["Generic"]["SystemProductName"] = spoofed_model
+ self.config["PlatformInfo"]["Generic"]["SystemSerialNumber"] = macserial_output[0]
+ self.config["PlatformInfo"]["Generic"]["MLB"] = macserial_output[1]
+ self.config["PlatformInfo"]["Generic"]["SystemUUID"] = str(uuid.uuid4()).upper()
+
+ @staticmethod
+ def get_item_by_kv(iterable, key, value):
+ item = None
+ for i in iterable:
+ if i[key] == value:
+ item = i
+ break
+ return item
+
+ def get_kext_by_bundle_path(self, bundle_path):
+ kext = self.get_item_by_kv(self.config["Kernel"]["Add"], "BundlePath", bundle_path)
+ if not kext:
+ print(f"- Could not find kext {bundle_path}!")
+ raise IndexError
+ return kext
+
+ def enable_kext(self, kext_name, kext_version, kext_path, check=False):
+ kext = self.get_kext_by_bundle_path(kext_name)
+
+ if callable(check) and not check():
+ # Check failed
+ return
+
+ print(f"- Adding {kext_name} {kext_version}")
+ shutil.copy(kext_path, Versions.kext_path_build)
+ kext["Enabled"] = True
+
+ def cleanup(self):
+ print("- Cleaning up files")
+ for kext in Path(Versions.kext_path_build).glob("*.zip"):
+ with zipfile.ZipFile(kext) as zip_file:
+ zip_file.extractall(Versions.kext_path_build)
+ kext.unlink()
+ shutil.rmtree((Path(Versions.kext_path_build) / Path("__MACOSX")), ignore_errors=True)
+
+ for item in Path(Versions.plist_path_build).glob("*.zip"):
+ with zipfile.ZipFile(item) as zip_file:
+ zip_file.extractall(Versions.plist_path_build)
+ item.unlink()
+ shutil.rmtree((Path(Versions.build_path) / Path("__MACOSX")), ignore_errors=True)
+ Path(Versions.opencore_path_build).unlink()
+
+ def build_opencore(self):
+ self.build_efi()
+ self.set_smbios()
+ self.cleanup()
+ print("")
+ print("Your OpenCore EFI has been built at:")
+ print(f" {Versions.opencore_path_done}")
+ print("")
+ input("Press enter to go back")
+
+ @staticmethod
+ def copy_efi():
+ 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)]:
+ menu.add_menu_option(disk.stem, key=disk.stem[4:])
+ disk_num = menu.start()
+ print(subprocess.run(("sudo diskutil mount disk" + disk_num).split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout)
+
+ utilities.cls()
+ utilities.header(["Copying OpenCore"])
+ efi_dir = Path("/Volumes/EFI")
+ if efi_dir.exists():
+ print("- Coping OpenCore onto EFI partition")
+ 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)
+ print("OpenCore transfer complete")
+ print("")
+ else:
+ print("Couldn't find EFI partition")
+ print("Please ensure your drive is formatted as GUID Partition Table")
+ print("")
+
+
+class OpenCoreMenus():
+ def __init__(self):
+ self.version = Versions.opencore_version
+
+ 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")
+ version = input("Please enter the desired OpenCore version: ").strip()
+ if version:
+ self.version = version
+
+ def build_opencore_menu(self, model):
+ response = None
+ while not (response and response == -1):
+ title = [
+ f"Build OpenCore v{self.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()],
+ ["Change OpenCore Version", self.change_opencore_version],
+ ]
+
+ for option in options:
+ menu.add_menu_option(option[0], function=option[1])
+
+ response = menu.start()
+ # response = utilities.menu(title, "zoomer, Please select an option: ", options, auto_number=True, top_level=True)
diff --git a/Resources/utilities.py b/Resources/utilities.py
new file mode 100644
index 0000000000..e55a0fff6d
--- /dev/null
+++ b/Resources/utilities.py
@@ -0,0 +1,114 @@
+from __future__ import print_function
+
+import os
+import math as m
+
+
+def header(lines):
+ lines = [i for i in lines if i is not None]
+ total_length = len(max(lines, key=len)) + 4
+ print("#" * (total_length))
+ for line in lines:
+ left_side = m.floor(((total_length - 2 - len(line.strip())) / 2))
+ print("#" + " " * left_side + line.strip() + " " * (total_length - len("#" + " " * left_side + line.strip()) - 1) + "#")
+ print("#" * total_length)
+
+
+def cls():
+ os.system('cls' if os.name == 'nt' else 'clear')
+
+# def menu(title, prompt, menu_options, add_quit=True, auto_number=False, in_between=[], top_level=False):
+# return_option = ["Q", "Quit", None] if top_level else ["B", "Back", None]
+# if add_quit: menu_options.append(return_option)
+
+# cls()
+# header(title)
+# print()
+
+# for i in in_between: print(i)
+# if in_between: print()
+
+# for index, option in enumerate(menu_options):
+# if auto_number and not (index == (len(menu_options) - 1) and add_quit):
+# option[0] = str((index + 1))
+# print(option[0] + ". " + option[1])
+
+# print()
+# selected = input(prompt)
+
+# keys = [option[0].upper() for option in menu_options]
+# if not selected or selected.upper() not in keys:
+# return
+# if selected.upper() == return_option[0]:
+# return -1
+# else:
+# menu_options[keys.index(selected.upper())][2]() if menu_options[keys.index(selected.upper())][2] else None
+
+
+class TUIMenu():
+ def __init__(self, title, prompt, options=None, return_number_instead_of_direct_call=False, add_quit=True, auto_number=False, in_between=None, top_level=False):
+ self.title = title
+ self.prompt = prompt
+ self.in_between = in_between or []
+ self.options = options or []
+ self.return_number_instead_of_direct_call = return_number_instead_of_direct_call
+ self.auto_number = auto_number
+ self.add_quit = add_quit
+ self.top_level = top_level
+
+ def add_menu_option(self, name, description="", function=None, key=""):
+ self.options.append([key, name, description, function])
+
+ def start(self):
+ return_option = ["Q", "Quit"] if self.top_level else ["B", "Back"]
+ if self.add_quit:
+ self.add_menu_option(
+ return_option[1], function=None, key=return_option[0])
+
+ cls()
+ header(self.title)
+ print()
+
+ for i in self.in_between:
+ print(i)
+ if self.in_between:
+ print()
+
+ for index, option in enumerate(self.options):
+ if self.auto_number and not (index == (len(self.options) - 1) and self.add_quit):
+ option[0] = str((index + 1))
+ print(option[0] + ". " + option[1])
+ for i in option[2]:
+ print("\t" + i)
+
+ print()
+ selected = input(self.prompt)
+
+ keys = [option[0].upper() for option in self.options]
+ if not selected or selected.upper() not in keys:
+ return
+ if self.add_quit and selected.upper() == return_option[0]:
+ return -1
+ elif self.return_number_instead_of_direct_call:
+ return self.options[keys.index(selected.upper())][0]
+ else:
+ self.options[keys.index(selected.upper())][3]() if self.options[keys.index(selected.upper())][3] else None
+
+
+class TUIOnlyPrint():
+ def __init__(self, title, prompt, in_between=None):
+ self.title = title
+ self.prompt = prompt
+ self.in_between = in_between or []
+
+ def start(self):
+ cls()
+ header(self.title)
+ print()
+
+ for i in self.in_between:
+ print(i)
+ if self.in_between:
+ print()
+
+ input(self.prompt)