Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 734dbc9
Author: Dhinak G <[email protected]>
Date:   Thu Sep 9 11:12:52 2021 -0400

    Pretend to be `Broadcom Bluetooth Download Device`

commit 33e8b27
Author: Dhinak G <[email protected]>
Date:   Tue Sep 7 11:45:57 2021 -0400

    Pretend to be `Bluetooth USB Host Controller`

    Test for beta 6 issues
Merge branch 'btflx_b6' into pr/34
  • Loading branch information
EmberPhoenix89 committed Nov 24, 2024
2 parents 8fcb9dd + 734dbc9 commit ef72249
Showing 1 changed file with 14 additions and 170 deletions.
184 changes: 14 additions & 170 deletions BrcmPatchRAM/BlueToolFixup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <Headers/kern_user.hpp>
#include <Headers/kern_util.hpp>
#include <Headers/kern_version.hpp>
#include <Headers/kern_devinfo.hpp>


#define MODULE_SHORT "btlfx"
Expand All @@ -37,6 +36,9 @@ bool BlueToolFixup::start(IOService *provider) {
return false;
}
setProperty("VersionInfo", kextVersion);
setName("Broadcom Bluetooth Download Device");
// uint8_t bytes[] {0x00, 0x00, 0x00, 0x00};
// setProperty("transport-encoding", bytes, sizeof(bytes));
registerService();

return true;
Expand All @@ -46,178 +48,31 @@ bool BlueToolFixup::start(IOService *provider) {
#pragma mark - Patches

static const uint8_t kSkipUpdateFilePathOriginal[] = "/etc/bluetool/SkipBluetoothAutomaticFirmwareUpdate";
static const uint8_t kSkipUpdateFilePathPatched[] = "/System/Library/CoreServices/boot.efi";
static const uint8_t kSkipUpdateFilePathPatched[] = "/System/Library/CoreServices/boot.efi";


// Workaround 12.4 Beta 3+ bug where macOS may detect the Bluetooth chipset twice
// Once as internal, and second as an external dongle:
// 'ERROR -- Third Party Dongle has the same address as the internal module'
// Mainly applicable for BCM2046 and BCM2070 chipsets (BT2.1)
static const uint8_t kSkipAddressCheckOriginal[] =
{
0x48, 0x89, 0xF3, // mov rbx, rsi
0xE8, 0x00, 0x00, 0x00, 0x00, // call <somewhere>
0x85, 0xC0, // test eax, eax
0x74, 0x1D, // je
};

static const uint8_t kSkipAddressCheckPatched[] =
{
0x48, 0x89, 0xF3, // mov rbx, rsi
0xE8, 0x00, 0x00, 0x00, 0x00, // call <somewhere>
0x85, 0xC0, // test eax, eax
0x72, 0x1D, // jb short
};

static const uint8_t kSkipAddressCheckMask[] =
{
0xFF, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF,
0xFF, 0xFF,
};

static const uint8_t kVendorCheckOriginal[] =
{
0x81, 0xFA, // cmp edx
0x5C, 0x0A, 0x00, 0x00, // Vendor BRCM,
0x74 // jnz short
};

static const uint8_t kVendorCheckPatched[] =
{
0x81, 0xFA, // cmp edx
0x5C, 0x0A, 0x00, 0x00, // Vendor BRCM,
0xEB // jmp short
};

// Workaround for bugged chipset range check that
// doesn't consider 0 "THIRD_PARTY_DONGLE" as valid.
// This patch allows bluetooth to turn back on after the first power cycle.
// See https://github.com/acidanthera/BrcmPatchRAM/pull/18 for more details.
static const uint8_t kBadChipsetCheckOriginal[] =
{
0x81, 0xF9, // cmp ecx
0xCF, 0x07, 0x00, 0x00, // int 1999
0x72 // jb short
};

static const uint8_t kBadChipsetCheckPatched[] =
{
0x81, 0xF9, // cmp ecx
0xCF, 0x07, 0x00, 0x00, // int 1999
0xEB // jmp short
};

static const uint8_t kBadChipsetCheckOriginal13_3[] =
{
0x81, 0xF9, // cmp ecx
0x9E, 0x0F, 0x00, 0x00, // int 3998
0x77, 0x1A // ja short
};

static const uint8_t kBadChipsetCheckPatched13_3[] =
{
0x90, 0x90,
0x90, 0x90, 0x90, 0x90,
0x90, 0x90
};

static const uint8_t kSkipInternalControllerNVRAMCheck13_3[] =
{
0x41, 0x80, 0x00, 0x01, // xor r15b, 1
0x75, 0x00, // jnz short
0x84, 0xDB, // test bl, bl
0x75, 0x00 // jnz short
};

static const uint8_t kSkipInternalControllerNVRAMCheckMask13_3[] =
{
0xFF, 0xFF, 0x00, 0xFF,
0xFF, 0x00,
0xFF, 0xFF,
0xFF, 0x00
};

static const uint8_t kSkipInternalControllerNVRAMCheckPatched13_3[] =
{
0x90, 0x90, 0x90, 0x90,
0x90, 0x90,
0x90, 0x90,
0x90, 0x90
};

static bool shouldPatchBoardId = false;
static bool shouldPatchAddress = false;

static constexpr size_t kBoardIdSize = sizeof("Mac-F60DEB81FF30ACF6");
static constexpr size_t kBoardIdSizeLegacy = sizeof("Mac-F22586C8");

static const char boardIdsWithUSBBluetooth[][kBoardIdSize] = {
"Mac-F60DEB81FF30ACF6",
"Mac-9F18E312C5C2BF0B",
"Mac-937CB26E2E02BB01",
"Mac-E43C1C25D4880AD6",
"Mac-06F11FD93F0323C5",
"Mac-06F11F11946D27C5",
"Mac-A369DDC4E67F1C45",
"Mac-FFE5EF870D7BA81A",
"Mac-DB15BD556843C820",
"Mac-B809C3757DA9BB8D",
"Mac-65CE76090165799A",
"Mac-4B682C642B45593E",
"Mac-77F17D7DA9285301",
"Mac-BE088AF8C5EB4FA2"
};
static const char *blueToolPath = "/usr/sbin/BlueTool";

static mach_vm_address_t orig_cs_validate {};

#pragma mark - Kernel patching code

static inline void searchAndPatch(const void *haystack, size_t haystackSize, const char *path, const void *needle, size_t findSize, const void *patch, size_t replaceSize) {
if (KernelPatcher::findAndReplace(const_cast<void *>(haystack), haystackSize, needle, findSize, patch, replaceSize))
DBGLOG(MODULE_SHORT, "found string to patch at %s!", path);
}

template <size_t findSize, size_t replaceSize, typename T>
static inline void searchAndPatch(const void *haystack, size_t haystackSize, const char *path, const T (&needle)[findSize], const T (&patch)[replaceSize]) {
searchAndPatch(haystack, haystackSize, path, needle, findSize * sizeof(T), patch, replaceSize * sizeof(T));
}

static inline void searchAndPatchWithMask(const void *haystack, size_t haystackSize, const char *path, const void *needle, size_t findSize, const void *findMask, size_t findMaskSize, const void *patch, size_t replaceSize, const void *patchMask, size_t replaceMaskSize) {
if (KernelPatcher::findAndReplaceWithMask(const_cast<void *>(haystack), haystackSize, needle, findSize, findMask, findMaskSize, patch, replaceSize, patchMask, replaceMaskSize))
DBGLOG(MODULE_SHORT, "found string to patch at %s!", path);
template <size_t findSize, size_t replaceSize>
static inline void searchAndPatch(const void *haystack, size_t haystackSize, const char *path, const uint8_t (&needle)[findSize], const uint8_t (&patch)[replaceSize]) {
if (UNLIKELY(KernelPatcher::findAndReplace(const_cast<void *>(haystack), haystackSize, needle, findSize, patch, replaceSize)))
DBGLOG(MODULE_SHORT, "found string to patch at %s!", path);
}

template <size_t findSize, size_t findMaskSize, size_t replaceSize, size_t replaceMaskSize, typename T>
static inline void searchAndPatchWithMask(const void *haystack, size_t haystackSize, const char *path, const T (&needle)[findSize], const T (&findMask)[findMaskSize], const T (&patch)[replaceSize], const T (&patchMask)[replaceMaskSize]) {
searchAndPatchWithMask(haystack, haystackSize, path, needle, findSize * sizeof(T), findMask, findMaskSize * sizeof(T), patch, replaceSize * sizeof(T), patchMask, replaceSize * sizeof(T));
}


#pragma mark - Patched functions

// For Big Sur
static void patched_cs_validate_page(vnode_t vp, memory_object_t pager, memory_object_offset_t page_offset, const void *data, int *validated_p, int *tainted_p, int *nx_p) {
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);
static constexpr size_t dirLength = sizeof("/usr/sbin/")-1;
if (vn_getpath(vp, path, &pathlen) == 0 && UNLIKELY(strncmp(path, "/usr/sbin/", dirLength) == 0)) {
if (strcmp(path + dirLength, "BlueTool") == 0) {
searchAndPatch(data, PAGE_SIZE, path, kSkipUpdateFilePathOriginal, kSkipUpdateFilePathPatched);
if (shouldPatchBoardId)
searchAndPatch(data, PAGE_SIZE, path, boardIdsWithUSBBluetooth[0], kBoardIdSize, BaseDeviceInfo::get().boardIdentifier, kBoardIdSize);
}
else if (strcmp(path + dirLength, "bluetoothd") == 0) {
searchAndPatch(data, PAGE_SIZE, path, kVendorCheckOriginal, kVendorCheckPatched);
searchAndPatch(data, PAGE_SIZE, path, kBadChipsetCheckOriginal, kBadChipsetCheckPatched);
searchAndPatch(data, PAGE_SIZE, path, kBadChipsetCheckOriginal13_3, kBadChipsetCheckPatched13_3);
searchAndPatchWithMask(data, PAGE_SIZE, path, kSkipInternalControllerNVRAMCheck13_3, sizeof(kSkipInternalControllerNVRAMCheck13_3), kSkipInternalControllerNVRAMCheckMask13_3, sizeof(kSkipInternalControllerNVRAMCheckMask13_3), kSkipInternalControllerNVRAMCheckPatched13_3, sizeof(kSkipInternalControllerNVRAMCheckPatched13_3), nullptr, 0);
if (shouldPatchBoardId)
searchAndPatch(data, PAGE_SIZE, path, boardIdsWithUSBBluetooth[0], kBoardIdSize, BaseDeviceInfo::get().boardIdentifier, kBoardIdSize);
if (shouldPatchAddress)
searchAndPatchWithMask(data, PAGE_SIZE, path, kSkipAddressCheckOriginal, kSkipAddressCheckMask, kSkipAddressCheckPatched, kSkipAddressCheckMask);
}
if (vn_getpath(vp, path, &pathlen) == 0 && UNLIKELY(strcmp(path, blueToolPath) == 0)) {
searchAndPatch(data, PAGE_SIZE, path, kSkipUpdateFilePathOriginal, kSkipUpdateFilePathPatched);
}
}

Expand All @@ -229,18 +84,6 @@ static void pluginStart() {
// There is no point in routing cs_validate_range, because this kext should only be running on Monterey+
if (getKernelVersion() >= KernelVersion::Monterey) {
lilu.onPatcherLoadForce([](void *user, KernelPatcher &patcher) {
auto boardId = BaseDeviceInfo::get().boardIdentifier;
auto boardIdSize = strlen(boardId) + 1;
shouldPatchBoardId = boardIdSize == kBoardIdSize || boardIdSize == kBoardIdSizeLegacy;
if (shouldPatchBoardId)
for (size_t i = 0; i < arrsize(boardIdsWithUSBBluetooth); i++)
if (strcmp(boardIdsWithUSBBluetooth[i], boardId) == 0) {
shouldPatchBoardId = false;
break;
}
if ((getKernelVersion() == KernelVersion::Monterey && getKernelMinorVersion() >= 5) || getKernelVersion() > KernelVersion::Monterey)
// 12.4 Beta 3+, XNU 21.5
shouldPatchAddress = checkKernelArgument("-btlfxallowanyaddr");
KernelPatcher::RouteRequest csRoute = KernelPatcher::RouteRequest("_cs_validate_page", patched_cs_validate_page, orig_cs_validate);
if (!patcher.routeMultipleLong(KernelPatcher::KernelID, &csRoute, 1))
SYSLOG(MODULE_SHORT, "failed to route cs validation pages");
Expand Down Expand Up @@ -271,6 +114,7 @@ PluginConfiguration ADDPR(config) {
bootargBeta,
arrsize(bootargBeta),
KernelVersion::Monterey,
KernelVersion::Sequoia,
KernelVersion::Monterey,
pluginStart
};

0 comments on commit ef72249

Please sign in to comment.