diff --git a/.github/workflows/build-app-offline.yml b/.github/workflows/build-app-offline.yml new file mode 100644 index 000000000..f5e22b465 --- /dev/null +++ b/.github/workflows/build-app-offline.yml @@ -0,0 +1,33 @@ +name: CI - Build Offline TUI + +on: + push: + workflow_dispatch: + release: + types: [published] + +jobs: + build: + name: Build Offline TUI + runs-on: x86_64_mojave + steps: + - uses: actions/checkout@v2 + - run: python3 create-offline-build.py + - run: /Library/Frameworks/Python.framework/Versions/3.9/bin/pyinstaller OpenCore-Patcher.spec + - run: ./after_pyinstaller.sh + - run: 'codesign -s "Developer ID Application: Mykola Grymalyuk (S74BDJXQMD)" -v --force --deep --timestamp --entitlements entitlements.plist -o runtime "dist/OpenCore-Patcher.app"' + - run: cd dist; zip -r ../OpenCore-Patcher-TUI-Offline.app.zip OpenCore-Patcher.app + - name: Upload App to Artifacts + uses: actions/upload-artifact@v2 + with: + name: OpenCore-Patcher-TUI-Offline.app + path: OpenCore-Patcher-TUI-Offline.app.zip + + - name: Upload to Release + if: github.event_name == 'release' + uses: svenstaro/upload-release-action@e74ff71f7d8a4c4745b560a485cc5fdb9b5b999d + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: OpenCore-Patcher-TUI.app.zip + tag: ${{ github.ref }} + file_glob: true diff --git a/.gitignore b/.gitignore index b4d483c42..c2d213861 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ .DS_Store OCLP-GUI.command /payloads/Apple -/payloads/Apple.zip +/payloads/*.zip /payloads/__MACOSX /App /Build-Folder diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ed8f8b98..446411965 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,10 @@ - System Preferences will not report settings however - Allow Root Volume Patched Systems to use FileVault 2 - Requires macOS 11.3 (20E232) or newer +- Add offline TUI build + - Allows for root patching without network connection +- Add Legacy Wireless support for Monterey + - Applicable for BCM94328, BCM94322 and Atheros chipsets ## 0.2.4 diff --git a/README.md b/README.md index 0e2ec3976..93f2f7c8c 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Nightly builds can be found here courteous of nightly.link: * [Nightly OpenCore Patcher (GUI)](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-gui/main/OpenCore-Patcher-GUI.app.zip) * [Nightly OpenCore Patcher (TUI)](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app/main/OpenCore-Patcher-TUI.app.zip) + * [Offline Variant](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-app-offline/main/OpenCore-Patcher-TUI-Offline.app.zip) (No network connection needed on target Mac for Root Patching) * [Nightly OpenCore Patcher (CLI)](https://nightly.link/dortania/OpenCore-Legacy-Patcher/workflows/build-gui/main/OCLP-CLI.zip) ## Credits diff --git a/Resources/Build.py b/Resources/Build.py index a860bfee0..06446da71 100644 --- a/Resources/Build.py +++ b/Resources/Build.py @@ -278,28 +278,32 @@ class BuildOpenCore: elif self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirPortBrcm4360: wifi_fake_id(self) elif self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirPortBrcm4331: - self.enable_kext("IO80211Mojave.kext", self.constants.io80211mojave_version, self.constants.io80211mojave_path) - self.get_kext_by_bundle_path("IO80211Mojave.kext/Contents/PlugIns/AirPortBrcm4331.kext")["Enabled"] = True + self.enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path) + self.enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path) + self.get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AirPortBrcm4331.kext")["Enabled"] = True elif self.computer.wifi.chipset == device_probe.Broadcom.Chipsets.AirPortBrcm43224: self.enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path) self.enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path) self.get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AppleAirPortBrcm43224.kext")["Enabled"] = True elif isinstance(self.computer.wifi, device_probe.Atheros) and self.computer.wifi.chipset == device_probe.Atheros.Chipsets.AirPortAtheros40: - self.enable_kext("IO80211HighSierra.kext", self.constants.io80211high_sierra_version, self.constants.io80211high_sierra_path) - self.get_kext_by_bundle_path("IO80211HighSierra.kext/Contents/PlugIns/AirPortAtheros40.kext")["Enabled"] = True + self.enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path) + self.enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path) + self.get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AirPortAtheros40.kext")["Enabled"] = True else: if self.model in ModelArray.WifiBCM94331: wifi_fake_id(self) elif self.model in ModelArray.WifiBCM94322: - self.enable_kext("IO80211Mojave.kext", self.constants.io80211mojave_version, self.constants.io80211mojave_path) - self.get_kext_by_bundle_path("IO80211Mojave.kext/Contents/PlugIns/AirPortBrcm4331.kext")["Enabled"] = True + self.enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path) + self.enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path) + self.get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AirPortBrcm4331.kext")["Enabled"] = True elif self.model in ModelArray.WifiBCM94328: self.enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path) self.enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path) self.get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AppleAirPortBrcm43224.kext")["Enabled"] = True elif self.model in ModelArray.WifiAtheros: - self.enable_kext("IO80211HighSierra.kext", self.constants.io80211high_sierra_version, self.constants.io80211high_sierra_path) - self.get_kext_by_bundle_path("IO80211HighSierra.kext/Contents/PlugIns/AirPortAtheros40.kext")["Enabled"] = True + self.enable_kext("corecaptureElCap.kext", self.constants.corecaptureelcap_version, self.constants.corecaptureelcap_path) + self.enable_kext("IO80211ElCap.kext", self.constants.io80211elcap_version, self.constants.io80211elcap_path) + self.get_kext_by_bundle_path("IO80211ElCap.kext/Contents/PlugIns/AirPortAtheros40.kext")["Enabled"] = True else: self.enable_kext("AirportBrcmFixup.kext", self.constants.airportbcrmfixup_version, self.constants.airportbcrmfixup_path) # print(f"- Setting Wireless Card's Country Code: {self.computer.wifi.country_code}") diff --git a/Resources/Constants.py b/Resources/Constants.py index 4702d3942..0415325e6 100644 --- a/Resources/Constants.py +++ b/Resources/Constants.py @@ -14,7 +14,7 @@ class Constants: def __init__(self): # Patcher Versioning self.patcher_version = "0.2.5" # OpenCore-Legacy-Patcher - self.patcher_support_pkg_version = "0.1.0" # PatcherSupportPkg + self.patcher_support_pkg_version = "0.1.1" # PatcherSupportPkg # OpenCore Versioning # https://github.com/acidanthera/OpenCorePkg @@ -47,7 +47,7 @@ class Constants: ## Apple - Dortania Modified self.bcm570_version = "1.0.1" # CatalinaBCM5701Ethernet self.corecaptureelcap_version = "1.0.0" # corecaptureElCap - self.io80211elcap_version = "1.0.0" # IO80211ElCap + self.io80211elcap_version = "2.0.0" # IO80211ElCap self.io80211high_sierra_version = "1.0.0" # IO80211HighSierra self.io80211mojave_version = "1.0.0" # IO80211Mojave @@ -495,6 +495,18 @@ class Constants: def payload_apple_kexts_path(self): return self.payload_apple_root_path / Path("Extensions") + @property + def payload_apple_coreservices_path(self): + return self.payload_apple_root_path / Path("CoreServices") + + @property + def payload_apple_usr_path(self): + return self.payload_apple_root_path / Path("usr") + + @property + def payload_apple_libexec_path(self): + return self.payload_apple_usr_path / Path("libexec") + @property def payload_apple_frameworks_path(self): return self.payload_apple_root_path / Path("Frameworks") @@ -585,6 +597,14 @@ class Constants: @property def legacy_brightness(self): return self.payload_apple_kexts_path / Path("Brightness-Control") + + @property + def legacy_wifi_coreservices(self): + return self.payload_apple_coreservices_path / Path("Legacy-Wifi") + + @property + def legacy_wifi_libexec(self): + return self.payload_apple_libexec_path / Path("Legacy-Wifi") csr_values = { # Source: macOS 11.4 (XNU's csr.h) diff --git a/Resources/SysPatch.py b/Resources/SysPatch.py index ebc239826..5d09b46d3 100644 --- a/Resources/SysPatch.py +++ b/Resources/SysPatch.py @@ -33,6 +33,7 @@ class PatchSysVolume: self.ivy_gpu = False self.brightness_legacy = False self.legacy_audio = False + self.legacy_wifi = False self.added_legacy_kexts = False self.amfi_must_disable = False self.check_board_id = False @@ -48,10 +49,12 @@ class PatchSysVolume: self.mount_location = "/System/Volumes/Update/mnt1" else: self.mount_location = "" + self.mount_coreservices = f"{self.mount_location}/System/Library/CoreServices" self.mount_extensions = f"{self.mount_location}/System/Library/Extensions" self.mount_frameworks = f"{self.mount_location}/System/Library/Frameworks" self.mount_lauchd = f"{self.mount_location}/System/Library/LaunchDaemons" self.mount_private_frameworks = f"{self.mount_location}/System/Library/PrivateFrameworks" + self.mount_libexec = f"{self.mount_location}/usr/libexec" def elevated(self, *args, **kwargs) -> subprocess.CompletedProcess: if os.getuid() == 0 or self.constants.gui_mode is True: @@ -292,6 +295,12 @@ set million colour before rebooting""" self.delete_old_binaries(SysPatchArray.DeleteVolumeControl) self.add_new_binaries(SysPatchArray.AddVolumeControl, self.constants.audio_path) + def add_wifi_patch(self): + print("- Merging Wireless CoreSerices patches") + self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.legacy_wifi_coreservices}/", self.mount_coreservices], stdout=subprocess.PIPE) + print("- Merging Wireless usr/libexec patches") + self.elevated(["rsync", "-r", "-i", "-a", f"{self.constants.legacy_wifi_libexec}/", self.mount_libexec], stdout=subprocess.PIPE) + def gpu_accel_legacy(self): if self.constants.detected_os == self.constants.mojave: print("- Installing General Acceleration Kext patches for Mojave") @@ -503,6 +512,11 @@ set million colour before rebooting""" if self.legacy_audio is True: print("- Fixing Volume Control Support") self.add_audio_patch() + + if self.legacy_wifi is True: + print("- Installing legacy Wireless support") + self.add_wifi_patch() + if self.validate is False: self.rebuild_snapshot() @@ -540,7 +554,13 @@ set million colour before rebooting""" print("- Removing old Apple Binaries zip") Path(self.constants.payload_apple_root_path_zip).unlink() - Utilities.download_file(link, self.constants.payload_apple_root_path_zip) + local_zip = Path(self.constants.payload_path) / f"{os_ver}.zip" + if Path(local_zip).exists(): + print(f"- Found local {os_ver} zip, skipping download") + print(f"- Duplicating into Apple.zip") + shutil.copy(local_zip, self.constants.payload_apple_root_path_zip) + else: + Utilities.download_file(link, self.constants.payload_apple_root_path_zip) if self.constants.payload_apple_root_path_zip.exists(): print("- Download completed") @@ -612,6 +632,13 @@ set million colour before rebooting""" if self.constants.detected_os > self.constants.catalina: self.legacy_audio = True + if ( + isinstance(self.constants.computer.wifi, device_probe.Broadcom) + and self.computer.wifi.chipset in [device_probe.Broadcom.Chipsets.AirPortBrcm4331, device_probe.Broadcom.Chipsets.AirPortBrcm43224] + ) or (isinstance(self.computer.wifi, device_probe.Atheros) and self.computer.wifi.chipset == device_probe.Atheros.Chipsets.AirPortAtheros40): + if self.constants.detected_os > self.constants.big_sur and Utilities.check_monterey_wifi is True: + self.legacy_wifi = True + Utilities.cls() print("The following patches will be applied:") if self.nvidia_legacy is True: @@ -630,6 +657,8 @@ set million colour before rebooting""" print("- Add Legacy Brightness Control") if self.legacy_audio is True: print("- Add legacy Audio Control") + if self.legacy_wifi is True: + print("- Add legacy WiFi Control") self.no_patch = not any( [ @@ -641,6 +670,7 @@ set million colour before rebooting""" self.ivy_gpu, self.brightness_legacy, self.legacy_audio, + self.legacy_wifi, ] ) diff --git a/Resources/Utilities.py b/Resources/Utilities.py index 6b15e0b9d..f4e359616 100644 --- a/Resources/Utilities.py +++ b/Resources/Utilities.py @@ -143,6 +143,16 @@ def check_oclp_boot(): return False +def check_monterey_wifi(): + IO80211ElCap = "com.apple.iokit.IO80211ElCap (1110.26)" + CoreCaptureElCap = "com.apple.driver.corecaptureElCap (1.0.4)" + loaded_kexts: str = subprocess.run("kextcache".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode() + if IO80211ElCap in loaded_kexts and CoreCaptureElCap in loaded_kexts: + return True + else: + return False + + def patching_status(os_sip, os): # Detection for Root Patching sip_enabled = True # System Integrity Protection @@ -251,7 +261,6 @@ def enable_apfs(fw_feature, fw_mask): fw_mask |= 2 ** 19 return fw_feature, fw_mask - # 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) diff --git a/create-offline-build.py b/create-offline-build.py new file mode 100644 index 000000000..b22cb8335 --- /dev/null +++ b/create-offline-build.py @@ -0,0 +1,14 @@ +import subprocess +from Resources import Constants + +patcher_support_pkg_version = Constants.Constants().patcher_support_pkg_version +binary_packages = ["10.14-Mojave", "10.15-Catalina", "11-Big-Sur", "12-Monterey"] + +for binary_package in binary_packages: + print(f"- Downloading {binary_package}...") + download_cmd = f"curl -LO https://github.com/dortania/PatcherSupportPkg/releases/download/{patcher_support_pkg_version}/{binary_package}.zip" + subprocess.run(download_cmd, shell=True) + print("- Moving into payloads") + move_cmd = f"mv {binary_package}.zip ./payloads/" + subprocess.run(move_cmd, shell=True) +print("- Download complete") diff --git a/payloads/Config/config.plist b/payloads/Config/config.plist index 1a29c5a78..d7ffcdb34 100644 --- a/payloads/Config/config.plist +++ b/payloads/Config/config.plist @@ -456,7 +456,7 @@ Enabled MaxKernel - 20.99.99 + MinKernel 16.0.0 BundlePath @@ -470,33 +470,15 @@ Arch x86_64 Comment - Atheros Wifi Patch + Monterey Atheros Wifi Patch Enabled MaxKernel - 20.99.99 + MinKernel 18.0.0 BundlePath - IO80211HighSierra.kext - ExecutablePath - Contents/MacOS/IO80211HighSierra - PlistPath - Contents/Info.plist - - - Arch - x86_64 - Comment - Atheros Wifi Patch - Enabled - - MaxKernel - 20.99.99 - MinKernel - 18.0.0 - BundlePath - IO80211HighSierra.kext/Contents/PlugIns/AirPortAtheros40.kext + IO80211ElCap.kext/Contents/PlugIns/AirPortAtheros40.kext ExecutablePath Contents/MacOS/AirPortAtheros40 PlistPath @@ -506,33 +488,15 @@ Arch x86_64 Comment - Broadcom Wifi Patch + Monterey BCM94322 Wifi Patch Enabled MaxKernel - 20.99.99 + MinKernel 19.0.0 BundlePath - IO80211Mojave.kext - ExecutablePath - Contents/MacOS/IO80211Mojave - PlistPath - Contents/Info.plist - - - Arch - x86_64 - Comment - Broadcom Wifi Patch - Enabled - - MaxKernel - 20.99.99 - MinKernel - 19.0.0 - BundlePath - IO80211Mojave.kext/Contents/PlugIns/AirPortBrcm4331.kext + IO80211ElCap.kext/Contents/PlugIns/AirPortBrcm4331.kext ExecutablePath Contents/MacOS/AirPortBrcm4331 PlistPath diff --git a/payloads/Kexts/Wifi/IO80211ElCap-v2.0.0.zip b/payloads/Kexts/Wifi/IO80211ElCap-v2.0.0.zip new file mode 100644 index 000000000..752226d66 Binary files /dev/null and b/payloads/Kexts/Wifi/IO80211ElCap-v2.0.0.zip differ