# Class for generating OpenCore Configurations tailored for Macs # Copyright (C) 2020-2022, Dhinak G, Mykola Grymalyuk import copy import pickle import plistlib import shutil import zipfile from pathlib import Path from datetime import date import logging from resources import constants, utilities from resources.build import bluetooth, firmware, graphics_audio, support, storage, smbios, security, misc from resources.build.networking import wired, wireless def rmtree_handler(func, path, exc_info): if exc_info[0] == FileNotFoundError: return raise # pylint: disable=misplaced-bare-raise class build_opencore: def __init__(self, model, versions): self.model = model self.config = None self.constants: constants.Constants = versions def build_efi(self): utilities.cls() if not self.constants.custom_model: logging.info(f"Building Configuration on model: {self.model}") else: logging.info(f"Building Configuration for external model: {self.model}") self.generate_base() self.set_revision() # Set Lilu and co. support.build_support(self.model, self.constants, self.config).enable_kext("Lilu.kext", self.constants.lilu_version, self.constants.lilu_path) self.config["Kernel"]["Quirks"]["DisableLinkeditJettison"] = True # Call support functions firmware.build_firmware(self.model, self.constants, self.config).build() wired.build_wired(self.model, self.constants, self.config).build() wireless.build_wireless(self.model, self.constants, self.config).build() graphics_audio.build_graphics_audio(self.model, self.constants, self.config).build() bluetooth.build_bluetooth(self.model, self.constants, self.config).build() storage.build_storage(self.model, self.constants, self.config).build() smbios.build_smbios(self.model, self.constants, self.config).build() security.build_security(self.model, self.constants, self.config).build() misc.build_misc(self.model, self.constants, self.config).build() # Work-around ocvalidate if self.constants.validate is False: logging.info("- Adding bootmgfw.efi BlessOverride") self.config["Misc"]["BlessOverride"] += ["\\EFI\\Microsoft\\Boot\\bootmgfw.efi"] def generate_base(self): # Generate OpenCore base folder and config if not Path(self.constants.build_path).exists(): logging.info("Creating build folder") Path(self.constants.build_path).mkdir() else: logging.info("Build folder already present, skipping") if Path(self.constants.opencore_zip_copied).exists(): logging.info("Deleting old copy of OpenCore zip") Path(self.constants.opencore_zip_copied).unlink() if Path(self.constants.opencore_release_folder).exists(): logging.info("Deleting old copy of OpenCore folder") shutil.rmtree(self.constants.opencore_release_folder, onerror=rmtree_handler, ignore_errors=True) logging.info("") logging.info(f"- Adding OpenCore v{self.constants.opencore_version} {self.constants.opencore_build}") shutil.copy(self.constants.opencore_zip_source, self.constants.build_path) zipfile.ZipFile(self.constants.opencore_zip_copied).extractall(self.constants.build_path) # Setup config.plist for editing logging.info("- Adding config.plist for OpenCore") shutil.copy(self.constants.plist_template, self.constants.oc_folder) self.config = plistlib.load(Path(self.constants.plist_path).open("rb")) def set_revision(self): # Set revision in config self.config["#Revision"]["Build-Version"] = f"{self.constants.patcher_version} - {date.today()}" if not self.constants.custom_model: self.config["#Revision"]["Build-Type"] = "OpenCore Built on Target Machine" computer_copy = copy.copy(self.constants.computer) computer_copy.ioregistry = None self.config["#Revision"]["Hardware-Probe"] = pickle.dumps(computer_copy) else: self.config["#Revision"]["Build-Type"] = "OpenCore Built for External Machine" self.config["#Revision"]["OpenCore-Version"] = f"{self.constants.opencore_version} - {self.constants.opencore_build} - {self.constants.opencore_commit}" self.config["#Revision"]["Original-Model"] = self.model self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Version"] = f"{self.constants.patcher_version}" self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Model"] = self.model def save_config(self): plistlib.dump(self.config, Path(self.constants.plist_path).open("wb"), sort_keys=True) def build_opencore(self): # Generate OpenCore Configuration self.build_efi() if self.constants.allow_oc_everywhere is False or self.constants.allow_native_spoofs is True or (self.constants.custom_serial_number != "" and self.constants.custom_board_serial_number != ""): smbios.build_smbios(self.model, self.constants, self.config).set_smbios() support.build_support(self.model, self.constants, self.config).cleanup() self.save_config() # Post-build handling support.build_support(self.model, self.constants, self.config).sign_files() support.build_support(self.model, self.constants, self.config).validate_pathing() logging.info("") logging.info(f"Your OpenCore EFI for {self.model} has been built at:") logging.info(f" {self.constants.opencore_release_folder}") logging.info("") if self.constants.gui_mode is False: input("Press [Enter] to continue\n")