diff --git a/.github/workflows/build-app-wxpython.yml b/.github/workflows/build-app-wxpython.yml index ecd65e5ca..ecc21b880 100644 --- a/.github/workflows/build-app-wxpython.yml +++ b/.github/workflows/build-app-wxpython.yml @@ -11,9 +11,9 @@ jobs: name: Build wxPython runs-on: x86_64_mojave env: - branch: ${{ github.event.ref }} - commiturl: ${{ github.event.head_commit.url }} - commitdate: ${{ github.event.head_commit.timestamp }} + branch: ${{ github.ref }} + commiturl: ${{ github.event.head_commit.url }}${{ github.event.release.html_url }} + commitdate: ${{ github.event.head_commit.timestamp }}${{ github.event.release.published_at }} steps: - uses: actions/checkout@v3 - run: /Library/Frameworks/Python.framework/Versions/3.9/bin/python3 Build-Binary.command --reset_binaries --branch "${{ env.branch }}" --commit "${{ env.commiturl }}" --commit_date "${{ env.commitdate }}" diff --git a/.github/workflows/build-app.yml b/.github/workflows/build-app.yml index 69035987c..fbf9a176f 100644 --- a/.github/workflows/build-app.yml +++ b/.github/workflows/build-app.yml @@ -11,9 +11,9 @@ jobs: name: Build TUI runs-on: x86_64_mojave env: - branch: ${{ github.event.ref }} - commiturl: ${{ github.event.head_commit.url }} - commitdate: ${{ github.event.head_commit.timestamp }} + branch: ${{ github.ref }} + commiturl: ${{ github.event.head_commit.url }}${{ github.event.release.html_url }} + commitdate: ${{ github.event.head_commit.timestamp }}${{ github.event.release.published_at }} steps: - uses: actions/checkout@v3 - run: /Library/Frameworks/Python.framework/Versions/3.9/bin/python3 Build-Binary.command --build_tui --reset_binaries --branch "${{ env.branch }}" --commit "${{ env.commiturl }}" --commit_date "${{ env.commitdate }}" diff --git a/Build-Binary.command b/Build-Binary.command index 1da9a6a71..65e913da6 100755 --- a/Build-Binary.command +++ b/Build-Binary.command @@ -123,6 +123,9 @@ class create_binary: if file.name in delete_files: print(f" - Deleting {file.name}") file.unlink() + elif (Path(file) / Path("Contents/Resources/createinstallmedia")).exists(): + print(f" - Deleting {file}") + subprocess.run(["rm", "-rf", file]) def download_resources(self): patcher_support_pkg_version = constants.Constants().patcher_support_pkg_version diff --git a/CHANGELOG.md b/CHANGELOG.md index 958871fc4..209278226 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ - Add error-handling to corrupt/non-standard NVRAM variables - Add warning prompt when using 'Allow native models' - Attempt to avoid misuse of option +- Work-around `Failed to extract AssetData` during installer creation + - Apple bug, resolved by using CoW into a different directory than `/Applications` - Ventura Specific Updates: - Switch boot.efi model patch to iMac18,1 - Resolve pre-Force Touch Trackpad support in Ventura diff --git a/docs/UNINSTALL.md b/docs/UNINSTALL.md index f3729b220..268bee612 100644 --- a/docs/UNINSTALL.md +++ b/docs/UNINSTALL.md @@ -7,6 +7,7 @@ To remove OpenCore is actually quite simply: * You'll need to mount the drive's EFI partition, and delete the `EFI/OC` and `System` folders * Note **do not** delete the entire EFI folder, this will likely break any existing Windows and Linux installations * [See here for an example on how to mount](https://dortania.github.io/OpenCore-Post-Install/universal/oc2hdd.html) + * For 5k iMac users, you will also need to delete `boot.efi` on the root of the EFI partition 2. [Reset NVRAM](https://support.apple.com/HT204063) diff --git a/gui/gui_main.py b/gui/gui_main.py index 1e0c0e1d1..4297a0947 100644 --- a/gui/gui_main.py +++ b/gui/gui_main.py @@ -31,6 +31,7 @@ class wx_python_gui: self.finished_cim_process = False self.target_disk = "" self.pulse_forward = False + self.prepare_result = False self.non_metal_required = self.use_non_metal_alternative() self.hyperlink_colour = (25, 179, 231) @@ -1832,9 +1833,8 @@ class wx_python_gui: 20 ) self.progress_bar.Centre(wx.HORIZONTAL) - self.progress_bar.SetValue(0) - self.progress_label = wx.StaticText(self.frame, label="Bytes Written: 0") + self.progress_label = wx.StaticText(self.frame, label="Preparing files, beginning shortly...") self.progress_label.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL)) self.progress_label.SetPosition( wx.Point( @@ -1863,7 +1863,18 @@ class wx_python_gui: print("- Creating installer.sh script") print(f"- Disk: {disk}") print(f"- Installer: {installer_path}") - if installer.generate_installer_creation_script(self.constants.installer_sh_path, installer_path, disk): + + self.prepare_script_thread = threading.Thread(target=self.prepare_script, args=(installer_path,disk)) + self.prepare_script_thread.start() + self.progress_bar.Pulse() + + while self.prepare_script_thread.is_alive(): + self.pulse_alternative(self.progress_bar) + wx.GetApp().Yield() + + if self.prepare_result is True: + self.progress_label.SetLabel("Bytes Written: 0") + self.progress_label.Centre(wx.HORIZONTAL) print("- Sucessfully generated creation script") print("- Starting creation script as admin") wx.GetApp().Yield() @@ -1875,6 +1886,7 @@ class wx_python_gui: self.download_thread = threading.Thread(target=self.download_and_unzip_pkg) self.download_thread.start() default_output = float(utilities.monitor_disk_output(disk)) + self.progress_bar.SetValue(0) while True: time.sleep(0.1) output = float(utilities.monitor_disk_output(disk)) @@ -1918,8 +1930,15 @@ class wx_python_gui: self.build_install_menu() else: print("- Failed to create installer script") + self.progress_label.SetLabel("Failed to copy files to tmp directory") + self.progress_label.Centre(wx.HORIZONTAL) + popup_message = wx.MessageDialog(self.frame, "Failed to prepare the base files for installer creation.\n\nPlease ensure you have 20GB~ free on-disk before starting to ensure the installer has enough room to work.", "Error", wx.OK) + popup_message.ShowModal() self.return_to_main_menu.Enable() + def prepare_script(self, installer_path, disk): + self.prepare_result = installer.generate_installer_creation_script(self.constants.payload_path, installer_path, disk) + def start_script(self): utilities.disable_sleep_while_running() args = [self.constants.oclp_helper_path, "/bin/sh", self.constants.installer_sh_path] @@ -2760,6 +2779,10 @@ class wx_python_gui: self.constants.custom_board_serial_number = self.smbios_board_serial_textbox.GetValue() def generate_new_serials_clicked(self, event): + # Throw pop up warning about misusing this feature + dlg = wx.MessageDialog(self.frame_modal, "Please take caution when using serial spoofing. This should only be used on machines that were legally obtained and require reserialization.\n\nNote: new serials are only overlayed through OpenCore and are not permanently installed into ROM.\n\nMisuse of this setting can break power management and other aspects of the OS if the system does not need spoofing\n\nDortania does not condone the use of our software on stolen devices.", "Warning", wx.YES_NO | wx.ICON_WARNING) + if dlg.ShowModal() == wx.ID_NO: + return macserial_output = subprocess.run([self.constants.macserial_path] + f"-g -m {self.constants.custom_model or self.computer.real_model} -n 1".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT) macserial_output = macserial_output.stdout.decode().strip().split(" | ") if len(macserial_output) == 2: diff --git a/resources/build.py b/resources/build.py index 1b0f713be..2f7c10d78 100644 --- a/resources/build.py +++ b/resources/build.py @@ -1237,6 +1237,8 @@ class BuildOpenCore: self.config["UEFI"]["ProtocolOverrides"]["DataHub"] = True self.config["PlatformInfo"]["Generic"]["SystemSerialNumber"] = self.constants.custom_serial_number self.config["PlatformInfo"]["Generic"]["MLB"] = self.constants.custom_board_serial_number + self.config["PlatformInfo"]["Generic"]["MaxBIOSVersion"] = False + self.config["PlatformInfo"]["Generic"]["SystemProductName"] = self.spoofed_model self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Spoofed-SN"] = self.constants.custom_serial_number self.config["NVRAM"]["Add"]["4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102"]["OCLP-Spoofed-MLB"] = self.constants.custom_board_serial_number diff --git a/resources/installer.py b/resources/installer.py index a855569a0..bac166d0e 100644 --- a/resources/installer.py +++ b/resources/installer.py @@ -3,6 +3,7 @@ from pathlib import Path import plistlib import subprocess import requests +import tempfile from resources import utilities, tui_helpers def list_local_macOS_installers(): @@ -331,8 +332,10 @@ def list_disk_to_format(): }) return list_disks +# Create global tmp directory +tmp_dir = tempfile.TemporaryDirectory() -def generate_installer_creation_script(script_location, installer_path, disk): +def generate_installer_creation_script(tmp_location, installer_path, disk): # Creates installer.sh to be piped to OCLP-Helper and run as admin # Goals: # - Format provided disk as HFS+ GPT @@ -341,6 +344,29 @@ def generate_installer_creation_script(script_location, installer_path, disk): # OCLP-Helper once to avoid nagging the user about permissions additional_args = "" + script_location = Path(tmp_location) / Path("Installer.sh") + + # Due to a bug in createinstallmedia, running from '/Applications' may sometimes error: + # 'Failed to extract AssetData/boot/Firmware/Manifests/InstallerBoot/*' + # This affects native Macs as well even when manually invoking createinstallmedia + + # To resolve, we'll copy into our temp directory and run from there + + # Create a new tmp directory + # Our current one is a disk image, thus CoW will not work + global tmp_dir + ia_tmp = tmp_dir.name + + print(f"Creating temporary directory at {ia_tmp}") + # Delete all files in tmp_dir + for file in Path(ia_tmp).glob("*"): + subprocess.run(["rm", "-rf", str(file)]) + + # Copy installer to tmp (use CoW to avoid extra disk writes) + subprocess.run(["cp", "-cR", installer_path, ia_tmp]) + + # Adjust installer_path to point to the copied installer + installer_path = Path(ia_tmp) / Path(Path(installer_path).name) createinstallmedia_path = str(Path(installer_path) / Path("Contents/Resources/createinstallmedia")) plist_path = str(Path(installer_path) / Path("Contents/Info.plist")) diff --git a/resources/sys_patch_helpers.py b/resources/sys_patch_helpers.py index a03d0505d..7db6e61fb 100644 --- a/resources/sys_patch_helpers.py +++ b/resources/sys_patch_helpers.py @@ -28,20 +28,23 @@ class sys_patch_helpers: board_to_patch_hex = bytes.fromhex(board_to_patch.encode('utf-8').hex()) reported_board_hex = bytes.fromhex(self.constants.computer.reported_board_id.encode('utf-8').hex()) - if len(board_to_patch_hex) != len(reported_board_hex): - print(f"- Error: Board ID {self.constants.computer.reported_board_id} is not the same length as {board_to_patch}") - raise Exception("Host's Board ID is not the same length as the kext's Board ID, cannot patch!!!") + if len(board_to_patch_hex) > len(reported_board_hex): + # Pad the reported Board ID with zeros to match the length of the board to patch + reported_board_hex = reported_board_hex + bytes(len(board_to_patch_hex) - len(reported_board_hex)) + elif len(board_to_patch_hex) < len(reported_board_hex): + print(f"- Error: Board ID {self.constants.computer.reported_board_id} is longer than {board_to_patch}") + raise Exception("Host's Board ID is longer than the kext's Board ID, cannot patch!!!") + + path = source_files_path + "/10.13.6/System/Library/Extensions/AppleIntelSNBGraphicsFB.kext/Contents/MacOS/AppleIntelSNBGraphicsFB" + if Path(path).exists(): + with open(path, 'rb') as f: + data = f.read() + data = data.replace(board_to_patch_hex, reported_board_hex) + with open(path, 'wb') as f: + f.write(data) else: - path = source_files_path + "/10.13.6/System/Library/Extensions/AppleIntelSNBGraphicsFB.kext/Contents/MacOS/AppleIntelSNBGraphicsFB" - if Path(path).exists(): - with open(path, 'rb') as f: - data = f.read() - data = data.replace(board_to_patch_hex, reported_board_hex) - with open(path, 'wb') as f: - f.write(data) - else: - print(f"- Error: Could not find {path}") - raise Exception("Failed to find AppleIntelSNBGraphicsFB.kext, cannot patch!!!") + print(f"- Error: Could not find {path}") + raise Exception("Failed to find AppleIntelSNBGraphicsFB.kext, cannot patch!!!") def generate_patchset_plist(self, patchset, file_name):