diff --git a/Resources/Build.py b/Resources/Build.py
index 53548ea571..06446da71d 100644
--- a/Resources/Build.py
+++ b/Resources/Build.py
@@ -586,6 +586,25 @@ def amd_patch(self, backlight_path):
self.config["DeviceProperties"]["Add"][tb_device_path] = {"class-code": binascii.unhexlify("FFFFFFFF"), "device-id": binascii.unhexlify("FFFF0000")}
+ # Bluetooth Detection
+ if not self.constants.custom_model and self.computer.bluetooth_chipset:
+ if self.computer.bluetooth_chipset == "BRCM2070 Hub":
+ print("- Enabling Bluetooth BRCM2070 for macOS Monterey")
+ self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -brcm2070_patch"
+ self.enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
+ elif self.computer.bluetooth_chipset == "BRCM2046 Hub":
+ print("- Enabling Bluetooth BRCM2046 for macOS Monterey")
+ self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -brcm2046_patch"
+ self.enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
+ elif self.model in ModelArray.Bluetooth_BRCM2070:
+ print("- Enabling Bluetooth BRCM2070 for macOS Monterey")
+ self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -brcm2070_patch"
+ self.enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
+ elif self.model in ModelArray.Bluetooth_BRCM2046:
+ print("- Enabling Bluetooth BRCM2046 for macOS Monterey")
+ self.config["NVRAM"]["Add"]["7C436110-AB2A-4BBB-A880-FE41995C9F82"]["boot-args"] += " -brcm2046_patch"
+ self.enable_kext("BlueToolFixup.kext", self.constants.bluetool_version, self.constants.bluetool_path)
+
# Add XhciDxe if firmware doesn't have XHCI controller support and XCHI controller detected
# TODO: Fix XhciDxe to work on pre UEFI 2.0 Macs
# Ref: https://github.com/acidanthera/bugtracker/issues/1663
@@ -697,7 +716,6 @@ def amd_patch(self, backlight_path):
print("- Allowing FileVault on Root Patched systems")
self.get_item_by_kv(self.config["Kernel"]["Patch"], "Identifier", "com.apple.filesystems.apfs")["Enabled"] = True
-
def set_smbios(self):
spoofed_model = self.model
if self.constants.override_smbios == "Default":
@@ -847,7 +865,6 @@ def get_efi_binary_by_path(self, bundle_path, entry_location, efi_type):
print(f"- Could not find {efi_type}: {bundle_path}!")
raise IndexError
return efi_binary
-
def enable_kext(self, kext_name, kext_version, kext_path, check=False):
kext = self.get_kext_by_bundle_path(kext_name)
diff --git a/Resources/Constants.py b/Resources/Constants.py
index 179e8a46da..0415325e6e 100644
--- a/Resources/Constants.py
+++ b/Resources/Constants.py
@@ -34,6 +34,7 @@ def __init__(self):
self.featureunlock_version = "1.0.3" # FeatureUnlock
self.debugenhancer_version = "1.0.4" # DebugEnhancer
self.cpufriend_version = "1.2.4" # CPUFriend
+ self.bluetool_version = "2.6.1" # BlueToolFixup
## Apple
## https://www.apple.com
@@ -325,6 +326,10 @@ def featureunlock_path(self):
def debugenhancer_path(self):
return self.payload_kexts_path / Path(f"Acidanthera/DebugEnhancer-v{self.debugenhancer_version}.zip")
+ @property
+ def bluetool_path(self):
+ return self.payload_kexts_path / Path(f"Acidanthera/BlueToolFixup-v{self.bluetool_version}.zip")
+
@property
def innie_path(self):
return self.payload_kexts_path / Path(f"Misc/Innie-v{self.innie_version}.zip")
@@ -653,7 +658,7 @@ def legacy_wifi_libexec(self):
"j215ap", # MacBookPro16,4
"j185ap", # iMac20,1
"j185fap", # iMac20,2
- #"x86legacy", # non-T2 Macs/VMs, Monterey's boot.efi enforces this on all Macs
+ # "x86legacy", # non-T2 Macs/VMs, Monterey's boot.efi enforces this on all Macs
]
sandy_board_id = [
diff --git a/Resources/ModelArray.py b/Resources/ModelArray.py
index 688990bd1d..32e4de0bec 100644
--- a/Resources/ModelArray.py
+++ b/Resources/ModelArray.py
@@ -1146,8 +1146,8 @@
"iMac12,2",
"MacPro3,1",
"MacPro4,1",
- "XServer2,1",
- "XServer3,1",
+ "XServe2,1",
+ "XServe3,1",
]
dGPU_switch = [
@@ -1165,3 +1165,46 @@
"MacBookPro16,1",
"MacBookPro16,4",
]
+
+Bluetooth_BRCM2046 = [
+ "MacBook4,1",
+ "MacBook5,1",
+ "MacBook5,2",
+ "MacBookAir2,1",
+ "MacBookAir3,1",
+ "MacBookAir3,2",
+ "MacBookPro4,1",
+ "MacBookPro5,1",
+ "MacBookPro5,2",
+ "MacBookPro5,3",
+ "MacBookPro5,4",
+ "MacBookPro5,5",
+ "MacBookPro7,1",
+ "Macmini3,1",
+ "iMac8,1",
+ "iMac9,1",
+ "iMac10,1",
+ "iMac11,1",
+ "iMac11,2",
+ "iMac11,3",
+ "iMac12,1",
+ "iMac12,2",
+ "MacPro4,1",
+ "MacPro5,1",
+]
+
+Bluetooth_BRCM2070 = [
+ "MacBook6,1",
+ "MacBook7,1",
+ "MacBookAir4,1",
+ "MacBookAir4,2",
+ "MacBookPro6,1",
+ "MacBookPro6,2",
+ "MacBookPro8,1",
+ "MacBookPro8,2",
+ "MacBookPro8,3",
+ "Macmini4,1",
+ "Macmini5,1",
+ "Macmini5,2",
+ "Macmini5,3",
+]
diff --git a/Resources/Utilities.py b/Resources/Utilities.py
index cbefeb792f..f4e359616e 100644
--- a/Resources/Utilities.py
+++ b/Resources/Utilities.py
@@ -259,7 +259,7 @@ def download_file(link, location):
def enable_apfs(fw_feature, fw_mask):
fw_feature |= 2 ** 19
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]
diff --git a/Resources/device_probe.py b/Resources/device_probe.py
index 54f98dcf2f..aff61baa8d 100644
--- a/Resources/device_probe.py
+++ b/Resources/device_probe.py
@@ -313,6 +313,7 @@ class Computer:
cpu: Optional[CPU] = None
oclp_version: Optional[str] = None
opencore_version: Optional[str] = None
+ bluetooth_chipset: Optional[str] = None
@staticmethod
def probe():
@@ -324,6 +325,7 @@ def probe():
computer.storage_probe()
computer.smbios_probe()
computer.cpu_probe()
+ computer.bluetooth_probe()
return computer
def gpu_probe(self):
@@ -437,3 +439,12 @@ def cpu_probe(self):
subprocess.run("sysctl machdep.cpu.brand_string".split(), stdout=subprocess.PIPE).stdout.decode().partition(": ")[2].strip(),
subprocess.run("sysctl machdep.cpu.features".split(), stdout=subprocess.PIPE).stdout.decode().partition(": ")[2].strip().split(" "),
)
+
+ def bluetooth_probe(self):
+ usb_data: str = subprocess.run("system_profiler SPUSBDataType".split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.decode()
+ if "BRCM2070 Hub" in usb_data:
+ self.bluetooth_chipset = "BRCM2070 Hub"
+ elif "BRCM2046 Hub" in usb_data:
+ self.bluetooth_chipset = "BRCM2046 Hub"
+ elif "Bluetooth":
+ self.bluetooth_chipset = "Generic"
diff --git a/payloads/Config/config.plist b/payloads/Config/config.plist
index 633c05a40c..d7ffcdb343 100644
--- a/payloads/Config/config.plist
+++ b/payloads/Config/config.plist
@@ -912,7 +912,25 @@
MaxKernel
MinKernel
- 20.4.0
+ 16.0.0
+ PlistPath
+ Contents/Info.plist
+
+
+ Arch
+ x86_64
+ BundlePath
+ BlueToolFixup.kext
+ Comment
+ Fix Monterey Bluetooth
+ Enabled
+
+ ExecutablePath
+ Contents/MacOS/BlueToolFixup
+ MaxKernel
+
+ MinKernel
+ 21.0.0
PlistPath
Contents/Info.plist
diff --git a/payloads/Kexts/Acidanthera/BlueToolFixup-v2.6.1.zip b/payloads/Kexts/Acidanthera/BlueToolFixup-v2.6.1.zip
new file mode 100644
index 0000000000..efd4f88421
Binary files /dev/null and b/payloads/Kexts/Acidanthera/BlueToolFixup-v2.6.1.zip differ
diff --git a/payloads/Kexts/Acidanthera/BlueToolFixup.patch b/payloads/Kexts/Acidanthera/BlueToolFixup.patch
new file mode 100644
index 0000000000..28c807cadd
--- /dev/null
+++ b/payloads/Kexts/Acidanthera/BlueToolFixup.patch
@@ -0,0 +1,42 @@
+diff --git a/BrcmPatchRAM/BlueToolFixup.cpp b/BrcmPatchRAM/BlueToolFixup.cpp
+index 0fa891a..819eb3f 100644
+--- a/BrcmPatchRAM/BlueToolFixup.cpp
++++ b/BrcmPatchRAM/BlueToolFixup.cpp
+@@ -50,7 +50,15 @@ bool BlueToolFixup::start(IOService *provider) {
+ static const uint8_t kSkipUpdateFilePathOriginal[] = "/etc/bluetool/SkipBluetoothAutomaticFirmwareUpdate";
+ static const uint8_t kSkipUpdateFilePathPatched[] = "/System/Library/CoreServices/boot.efi";
+
++static const uint8_t kBluetoothUSBNameOriginal[] = "Bluetooth USB Host Controller";
++static const uint8_t kBluetoothUSBNamePatched2070[] = "BRCM2070 Hub Host Controller";
++static const uint8_t kBluetoothUSBNamePatched2046[] = "BRCM2046 Hub Host Controller";
++
+ static const char *blueToolPath = "/usr/sbin/BlueTool";
++static const char *bluetoothdPath = "/usr/sbin/bluetoothd";
++
++static const char brcm2046_patch = checkKernelArgument("-brcm2046_patch");
++static const char brcm2070_patch = checkKernelArgument("-brcm2070_patch");
+
+ static mach_vm_address_t orig_cs_validate {};
+
+@@ -71,8 +79,19 @@ static void patched_cs_validate_page(vnode_t vp, memory_object_t pager, memory_o
+ char path[PATH_MAX];
+ int pathlen = PATH_MAX;
+ FunctionCast(patched_cs_validate_page, orig_cs_validate)(vp, pager, page_offset, data, validated_p, tainted_p, nx_p);
+- if (vn_getpath(vp, path, &pathlen) == 0 && UNLIKELY(strcmp(path, blueToolPath) == 0)) {
+- searchAndPatch(data, PAGE_SIZE, path, kSkipUpdateFilePathOriginal, kSkipUpdateFilePathPatched);
++ if (vn_getpath(vp, path, &pathlen) == 0) {
++ if (UNLIKELY(strcmp(path, blueToolPath) == 0)) {
++ searchAndPatch(data, PAGE_SIZE, path, kSkipUpdateFilePathOriginal, kSkipUpdateFilePathPatched);
++ }
++ if (UNLIKELY(strcmp(path, bluetoothdPath) == 0)) {
++ if (brcm2046_patch) {
++ DBGLOG(MODULE_SHORT, "Patching BRCM2046 Hub into bluetoothd");
++ searchAndPatch(data, PAGE_SIZE, path, kBluetoothUSBNameOriginal, kBluetoothUSBNamePatched2046);
++ } else if (brcm2070_patch) {
++ DBGLOG(MODULE_SHORT, "Patching BRCM2070 Hub into bluetoothd");
++ searchAndPatch(data, PAGE_SIZE, path, kBluetoothUSBNameOriginal, kBluetoothUSBNamePatched2070);
++ }
++ }
+ }
+ }
+