diff --git a/CHANGELOG.md b/CHANGELOG.md index 93007259b..a3ca2650a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ - Implement automatic Kernel Debug Kit downloader for systems requiring Boot/SysKC rebuilding - ex. AMD GCN - Relies on N-1 system for when matching KDK is not present + - Delete unused KDKs in `/Library/Developer/KDKs` during root patching - Increment Binaries: - OpenCorePkg 0.8.5 release - Lilu 1.6.2 - release diff --git a/gui/gui_main.py b/gui/gui_main.py index 32680a597..e8bee9158 100644 --- a/gui/gui_main.py +++ b/gui/gui_main.py @@ -2589,13 +2589,24 @@ class wx_python_gui: self.disable_amfi_checkbox.Disable() + # Delete Unused KDKs during patching + self.delete_unused_kdks_checkbox = wx.CheckBox(self.frame_modal, label="Delete Unused KDKs") + self.delete_unused_kdks_checkbox.SetValue(self.constants.should_nuke_kdks) + self.delete_unused_kdks_checkbox.Bind(wx.EVT_CHECKBOX, self.delete_unused_kdks_click) + self.delete_unused_kdks_checkbox.SetPosition(wx.Point( + self.disable_amfi_checkbox.GetPosition().x, + self.disable_amfi_checkbox.GetPosition().y + self.disable_amfi_checkbox.GetSize().height + )) + self.delete_unused_kdks_checkbox.SetToolTip(wx.ToolTip("This will delete unused KDKs during root patching.\nThis will save space on your drive, however can be disabled if you wish to keep KDKs installed.")) + + # Set Ignore App Updates self.set_ignore_app_updates_checkbox = wx.CheckBox(self.frame_modal, label="Ignore App Updates") self.set_ignore_app_updates_checkbox.SetValue(self.constants.ignore_updates) self.set_ignore_app_updates_checkbox.Bind(wx.EVT_CHECKBOX, self.set_ignore_app_updates_click) self.set_ignore_app_updates_checkbox.SetPosition(wx.Point( - self.disable_amfi_checkbox.GetPosition().x, - self.disable_amfi_checkbox.GetPosition().y + self.disable_amfi_checkbox.GetSize().height)) + self.delete_unused_kdks_checkbox.GetPosition().x, + self.delete_unused_kdks_checkbox.GetPosition().y + self.delete_unused_kdks_checkbox.GetSize().height)) self.set_ignore_app_updates_checkbox.SetToolTip(wx.ToolTip("This will set whether OpenCore will ignore App Updates on launch.\nEnable this option if you do not want to be prompted for App Updates")) # Button: Developer Debug Info @@ -2619,6 +2630,15 @@ class wx_python_gui: self.frame_modal.SetSize(wx.Size(-1, self.return_to_main_menu_button.GetPosition().y + self.return_to_main_menu_button.GetSize().height + 40)) self.frame_modal.ShowWindowModal() + def delete_unused_kdks_click(self, event): + if self.delete_unused_kdks_checkbox.GetValue() is True: + print("Nuke KDKs enabled") + self.constants.should_nuke_kdks = True + else: + print("Nuke KDKs disabled") + self.constants.should_nuke_kdks = False + global_settings.global_settings().write_property("ShouldNukeKDKs", self.constants.should_nuke_kdks) + def disable_library_validation_click(self, event): if self.disable_library_validation_checkbox.GetValue(): print("Disable Library Validation") diff --git a/resources/constants.py b/resources/constants.py index 91cfbfa86..4174e7b05 100644 --- a/resources/constants.py +++ b/resources/constants.py @@ -114,6 +114,7 @@ class Constants: self.wxpython_variant = False # Determine if using wxPython variant self.unpack_thread = None # Determine if unpack thread finished self.cli_mode = False # Determine if running in CLI mode + self.should_nuke_kdks = True # Determine if KDKs should be nuked if unused in /L*/D*/KDKs ## Hardware self.computer: device_probe.Computer = None # type: ignore diff --git a/resources/defaults.py b/resources/defaults.py index b9aa8106f..621533213 100644 --- a/resources/defaults.py +++ b/resources/defaults.py @@ -69,6 +69,10 @@ class generate_defaults: if global_settings.global_settings().read_property("Force_Web_Drivers") is True: self.constants.force_nv_web = True + result = global_settings.global_settings().read_property("ShouldNukeKDKs") + if result is False: + self.constants.should_nuke_kdks = False + def smbios_probe(self): if not self.host_is_target: if self.model in ["MacPro4,1", "MacPro5,1"]: diff --git a/resources/kdk_handler.py b/resources/kdk_handler.py index 283d37482..87a9a13f5 100644 --- a/resources/kdk_handler.py +++ b/resources/kdk_handler.py @@ -9,6 +9,8 @@ from typing import cast import packaging.version import requests +import subprocess + from resources import utilities from resources.constants import Constants @@ -111,8 +113,9 @@ class kernel_debug_kit_handler: def download_kdk(self, version: str, build: str): detected_build = build - if self.is_kdk_installed(build) is True: + if self.is_kdk_installed(detected_build) is True: print("- KDK is already installed") + self.remove_unused_kdks(detected_build) return True, "", detected_build download_link = None @@ -148,6 +151,7 @@ class kernel_debug_kit_handler: print("- Could not find KDK, finding closest match") if self.is_kdk_installed(closest_build) is True: + self.remove_unused_kdks(closest_build) return True, "", closest_build if closest_match_download_link is None: @@ -168,6 +172,7 @@ class kernel_debug_kit_handler: return False, "Could not contact Apple download servers", "" if utilities.download_apple_developer_portal(download_link, self.constants.kdk_download_path): + self.remove_unused_kdks(detected_build) return True, "", detected_build return False, "Failed to download KDK", "" @@ -178,3 +183,18 @@ class kernel_debug_kit_handler: if file.name.endswith(f"{build}.kdk"): return True return False + + def remove_unused_kdks(self, exclude_build): + if self.constants.should_nuke_kdks is False: + return + + if not Path("/Library/Developer/KDKs").exists(): + return + + print("- Removing unused KDKs") + for kdk_folder in Path("/Library/Developer/KDKs").iterdir(): + if kdk_folder.is_dir(): + if kdk_folder.name.endswith(".kdk"): + if not kdk_folder.name.endswith(f"{exclude_build}.kdk"): + print(f" - Removing {kdk_folder.name}") + utilities.elevated(["sudo", "rm", "-rf", kdk_folder], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) \ No newline at end of file