feat(wifi): implement macOS Tahoe WorkQueue and FaultReporter for IO80211Controller
### Breakthroughs & Rétro-ingénierie (macOS Tahoe 26.7.1 / IO80211Family 1200.13.1)
1. WorkQueue Invariants (Slots 395 & 397):
- Analyse de `IO80211Controller::start(provider)` et `IONetworkController::start(provider)`.
- `createWorkLoop()` appelle directement le slot 395 `createWorkQueue()` (offset 0xc58), dont la classe de base renvoie `false`.
- `getWorkLoop()` appelle le slot 397 `getWorkQueue()` (offset 0xc68), dont la classe de base renvoie `nullptr`.
- Si non surchargés, `start()` échoue immédiatement avant l'allocation du timer.
- Broadcom (`AppleBCMWLANCore`) alloue `IO80211WorkQueue::workQueue()` (`__ZN16IO80211WorkQueue9workQueueEv`).
- Implémenté dans QualcommWifi avec `fWorkQueue` dérivé de `IOWorkLoop`.
2. Prévention du Kernel Panic dans `findAndAttachToFaultReporter` (Slot 432):
- `IO80211Controller::findAndAttachToFaultReporter` appelle le slot 432 `getFaultReporterFromDriver()` (offset 0xd80).
- Si `getFaultReporterFromDriver()` renvoie `nullptr` et que `ivars->_faultReporter` (offset 0x58) est nul, le kernel déclenche `panic("\"No ivars->_faultReporter\" @IO80211Controller.cpp:2877")`.
- Création de la classe `QualcommFaultReporter` (dérivée d'`OSObject`), instanciée et renvoyée par `getFaultReporterFromDriver()`, satisfaisant l'invariant sans panique.
### Modifications apportées
- `QualcommWireless/include/IOKit/80211/IO80211WorkQueue.h`:
- Déclaration de `IO80211WorkQueue` (dérivée d'`IOWorkLoop`) avec sa méthode statique `workQueue()`.
- `QualcommWireless/include/IOKit/80211/IO80211Controller.h`:
- Inclusion de `IO80211WorkQueue.h`.
- `QualcommWifi/QualcommWifi.hpp`:
- Déclaration de `QualcommFaultReporter : public OSObject`.
- Ajout des membres `fWorkQueue` et `fFaultReporter`.
- Déclaration des overrides `createWorkQueue()`, `getWorkQueue()` et `getFaultReporterFromDriver()`.
- `QualcommWifi/QualcommWifi.cpp`:
- Implémentation de `createWorkQueue()`, `getWorkQueue()` et `getFaultReporterFromDriver()`.
- Initialisation dans `init()` et libération dans `free()`.
- Sécurisation du prologue de `QualcommWifi::start()` avant `super::start(provider)`.
- `QualcommWifi/Info.plist`:
- Déclaration propre du kext Wi-Fi PCIe (`0x110717cb`), probe score 20000, et dépendances `IO80211Family`, `IONetworkingFamily`, `IOPCIFamily`.
- `build_wifi.sh`:
- Script automatisé de compilation, assemblage firmware radio WCN7850, linkage et validation `kmutil`.
### Validation
- Compilation réussie avec `clang++` (-target x86_64-apple-macos15.0).
- Validation `kmutil libraries` réussie à 100% avec code retour 0 contre `/System/Library/KernelCollections/BootKernelExtensions.kc`.
- Aucune régression sur le Bluetooth (`QualcommWireless.kext`), testé et validé via `xcodebuild`.
This commit is contained in:
1 parent
493c0989a1
commit
2dca4cd116
6 files changed
+179
-1
No files matched your search
@@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>QualcommWifi</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.nawrhehe.QualcommWifi</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>QualcommWifi</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>KEXT</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.1.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.1.0</string>
|
||||||
|
<key>IOKitPersonalities</key>
|
||||||
|
<dict>
|
||||||
|
<key>QualcommWifi_PCIe</key>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.nawrhehe.QualcommWifi</string>
|
||||||
|
<key>IOClass</key>
|
||||||
|
<string>QualcommWifi</string>
|
||||||
|
<key>IOMatchCategory</key>
|
||||||
|
<string>IODefaultMatchCategory</string>
|
||||||
|
<key>IOPCIPrimaryMatch</key>
|
||||||
|
<string>0x110717cb</string>
|
||||||
|
<key>IOProbeScore</key>
|
||||||
|
<integer>20000</integer>
|
||||||
|
<key>IOProviderClass</key>
|
||||||
|
<string>IOPCIDevice</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>OSBundleLibraries</key>
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.iokit.IO80211Family</key>
|
||||||
|
<string>1200.0</string>
|
||||||
|
<key>com.apple.iokit.IONetworkingFamily</key>
|
||||||
|
<string>3.2</string>
|
||||||
|
<key>com.apple.iokit.IOPCIFamily</key>
|
||||||
|
<string>2.9</string>
|
||||||
|
<key>com.apple.kpi.bsd</key>
|
||||||
|
<string>15.0</string>
|
||||||
|
<key>com.apple.kpi.iokit</key>
|
||||||
|
<string>15.0</string>
|
||||||
|
<key>com.apple.kpi.libkern</key>
|
||||||
|
<string>15.0</string>
|
||||||
|
<key>com.apple.kpi.mach</key>
|
||||||
|
<string>15.0</string>
|
||||||
|
</dict>
|
||||||
|
<key>OSBundleRequired</key>
|
||||||
|
<string>Network-Root</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define super IO80211Controller
|
#define super IO80211Controller
|
||||||
|
OSDefineMetaClassAndStructors(QualcommFaultReporter, OSObject)
|
||||||
OSDefineMetaClassAndStructors(QualcommWifi, IO80211Controller)
|
OSDefineMetaClassAndStructors(QualcommWifi, IO80211Controller)
|
||||||
|
|
||||||
bool QualcommWifi::init(OSDictionary *dictionary) {
|
bool QualcommWifi::init(OSDictionary *dictionary) {
|
||||||
@@ -29,10 +30,14 @@ bool QualcommWifi::init(OSDictionary *dictionary) {
|
|||||||
fDmaPhysAddr = 0;
|
fDmaPhysAddr = 0;
|
||||||
fDmaVirtAddr = nullptr;
|
fDmaVirtAddr = nullptr;
|
||||||
fDmaPrepared = false;
|
fDmaPrepared = false;
|
||||||
|
fWorkQueue = nullptr;
|
||||||
|
fFaultReporter = nullptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QualcommWifi::free(void) {
|
void QualcommWifi::free(void) {
|
||||||
|
OSSafeReleaseNULL(fFaultReporter);
|
||||||
|
OSSafeReleaseNULL(fWorkQueue);
|
||||||
super::free();
|
super::free();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,7 +537,20 @@ bool QualcommWifi::loadBhiFirmware(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool QualcommWifi::start(IOService *provider) {
|
bool QualcommWifi::start(IOService *provider) {
|
||||||
|
#if __IO80211_TARGET >= 260000
|
||||||
|
// Pré-allocation de l'infrastructure macOS Tahoe requise par IO80211Controller::start
|
||||||
|
if (!createWorkQueue()) {
|
||||||
|
IOLog("QualcommWifi: Erreur critique - Impossible d'allouer IO80211WorkQueue !\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!getFaultReporterFromDriver()) {
|
||||||
|
IOLog("QualcommWifi: Erreur critique - Impossible d'allouer le FaultReporter !\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!super::start(provider)) {
|
if (!super::start(provider)) {
|
||||||
|
IOLog("QualcommWifi: Erreur - Echec de IO80211Controller::start(provider) !\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1035,12 +1053,37 @@ IOReturn QualcommWifi::setGET_DEBUG_INFO(IO80211SkywalkInterface *iface, apple80
|
|||||||
return kIOReturnSuccess;
|
return kIOReturnSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QualcommWifi::createWorkQueue(void) {
|
||||||
|
if (!fWorkQueue) {
|
||||||
|
fWorkQueue = IO80211WorkQueue::workQueue();
|
||||||
|
if (fWorkQueue) {
|
||||||
|
IOLog("QualcommWifi: IO80211WorkQueue creee avec succes (%p).\n", fWorkQueue);
|
||||||
|
} else {
|
||||||
|
IOLog("QualcommWifi: Echec de creation de IO80211WorkQueue !\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (fWorkQueue != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IO80211WorkQueue* QualcommWifi::getWorkQueue(void) const {
|
||||||
|
return fWorkQueue;
|
||||||
|
}
|
||||||
|
|
||||||
void* QualcommWifi::getLogger(void) const {
|
void* QualcommWifi::getLogger(void) const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* QualcommWifi::getFaultReporterFromDriver(void) {
|
void* QualcommWifi::getFaultReporterFromDriver(void) {
|
||||||
return nullptr;
|
if (!fFaultReporter) {
|
||||||
|
fFaultReporter = new QualcommFaultReporter;
|
||||||
|
if (fFaultReporter) {
|
||||||
|
fFaultReporter->init();
|
||||||
|
IOLog("QualcommWifi: FaultReporter (QualcommFaultReporter) cree avec succes (%p).\n", fFaultReporter);
|
||||||
|
} else {
|
||||||
|
IOLog("QualcommWifi: Echec de creation du QualcommFaultReporter !\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fFaultReporter;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
SInt32 QualcommWifi::apple80211Request(unsigned int req_type, int req_val, IO80211Interface* iface, void* req_data) {
|
SInt32 QualcommWifi::apple80211Request(unsigned int req_type, int req_val, IO80211Interface* iface, void* req_data) {
|
||||||
|
|||||||
@@ -174,8 +174,18 @@ struct mhi_ring_element {
|
|||||||
#include <IOKit/80211/IO80211Controller.h>
|
#include <IOKit/80211/IO80211Controller.h>
|
||||||
#include <IOKit/80211/IO80211Interface.h>
|
#include <IOKit/80211/IO80211Interface.h>
|
||||||
#include <IOKit/80211/IO80211SkywalkInterface.h>
|
#include <IOKit/80211/IO80211SkywalkInterface.h>
|
||||||
|
#include <IOKit/80211/IO80211WorkQueue.h>
|
||||||
#include "Firmware_WCN7850_Wifi.h"
|
#include "Firmware_WCN7850_Wifi.h"
|
||||||
|
|
||||||
|
// Classe FaultReporter pour satisfaire findAndAttachToFaultReporter sous macOS Tahoe
|
||||||
|
class QualcommFaultReporter : public OSObject {
|
||||||
|
OSDeclareDefaultStructors(QualcommFaultReporter)
|
||||||
|
public:
|
||||||
|
virtual bool init() override {
|
||||||
|
return OSObject::init();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class QualcommWifi : public IO80211Controller {
|
class QualcommWifi : public IO80211Controller {
|
||||||
OSDeclareDefaultStructors(QualcommWifi)
|
OSDeclareDefaultStructors(QualcommWifi)
|
||||||
|
|
||||||
@@ -204,6 +214,10 @@ private:
|
|||||||
void *fDmaVirtAddr;
|
void *fDmaVirtAddr;
|
||||||
bool fDmaPrepared;
|
bool fDmaPrepared;
|
||||||
|
|
||||||
|
// Infrastructure macOS Tahoe IO80211Family
|
||||||
|
IO80211WorkQueue *fWorkQueue;
|
||||||
|
QualcommFaultReporter *fFaultReporter;
|
||||||
|
|
||||||
UInt32 read32(UInt32 offset);
|
UInt32 read32(UInt32 offset);
|
||||||
void write32(UInt32 offset, UInt32 value);
|
void write32(UInt32 offset, UInt32 value);
|
||||||
|
|
||||||
@@ -237,6 +251,8 @@ public:
|
|||||||
#if __IO80211_TARGET >= 260000
|
#if __IO80211_TARGET >= 260000
|
||||||
// macOS Tahoe 26.x (Darwin 25) Skywalk IO80211Controller overrides
|
// macOS Tahoe 26.x (Darwin 25) Skywalk IO80211Controller overrides
|
||||||
virtual bool isCommandProhibited(int command) override;
|
virtual bool isCommandProhibited(int command) override;
|
||||||
|
virtual bool createWorkQueue(void) override;
|
||||||
|
virtual IO80211WorkQueue* getWorkQueue(void) const override;
|
||||||
virtual IOReturn handleCardSpecific(IO80211SkywalkInterface *iface, unsigned long req_type, void *req_data, bool isSet) override;
|
virtual IOReturn handleCardSpecific(IO80211SkywalkInterface *iface, unsigned long req_type, void *req_data, bool isSet) override;
|
||||||
virtual UInt32 hardwareOutputQueueDepth(void) override;
|
virtual UInt32 hardwareOutputQueueDepth(void) override;
|
||||||
virtual SInt32 performCountryCodeOperation(IO80211CountryCodeOp op) override;
|
virtual SInt32 performCountryCodeOperation(IO80211CountryCodeOp op) override;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "apple80211_ioctl.h"
|
#include "apple80211_ioctl.h"
|
||||||
#include "IO80211SkywalkInterface.h"
|
#include "IO80211SkywalkInterface.h"
|
||||||
#include "IO80211WorkLoop.h"
|
#include "IO80211WorkLoop.h"
|
||||||
|
#include "IO80211WorkQueue.h"
|
||||||
|
|
||||||
#define AUTH_TIMEOUT 15 // seconds
|
#define AUTH_TIMEOUT 15 // seconds
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef _IO80211WORKQUEUE_H
|
||||||
|
#define _IO80211WORKQUEUE_H
|
||||||
|
|
||||||
|
#include <IOKit/IOWorkLoop.h>
|
||||||
|
|
||||||
|
class IO80211WorkQueue : public IOWorkLoop {
|
||||||
|
OSDeclareDefaultStructors(IO80211WorkQueue)
|
||||||
|
|
||||||
|
public:
|
||||||
|
static IO80211WorkQueue* workQueue();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _IO80211WORKQUEUE_H */
|
||||||
Executable
+46
@@ -0,0 +1,46 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
BUILD_DIR="${SCRIPT_DIR}/build/Release"
|
||||||
|
KEXT_BUNDLE="${BUILD_DIR}/QualcommWifi.kext"
|
||||||
|
KEXT_MACOS="${KEXT_BUNDLE}/Contents/MacOS"
|
||||||
|
|
||||||
|
echo "=== Compilation de QualcommWifi.kext (macOS Tahoe 26.x / Darwin 25) ==="
|
||||||
|
|
||||||
|
mkdir -p "${KEXT_MACOS}"
|
||||||
|
|
||||||
|
# 1. Assemblage du firmware embarqué (AMSS, Board-2, M3)
|
||||||
|
echo "[1/4] Assemblage du firmware radio WCN7850..."
|
||||||
|
clang -target x86_64-apple-macos15.0 \
|
||||||
|
-c "${SCRIPT_DIR}/QualcommWifi/Firmware_WCN7850_Wifi.s" \
|
||||||
|
-o "${BUILD_DIR}/Firmware_WCN7850_Wifi.o"
|
||||||
|
|
||||||
|
# 2. Compilation C++ du pilote QualcommWifi
|
||||||
|
echo "[2/4] Compilation C++ de QualcommWifi.cpp..."
|
||||||
|
clang++ -target x86_64-apple-macos15.0 \
|
||||||
|
-nostdinc -isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Headers \
|
||||||
|
-I"${SCRIPT_DIR}/QualcommWireless/include" \
|
||||||
|
-I"${SCRIPT_DIR}/QualcommWifi" \
|
||||||
|
-std=c++17 -fno-builtin -fno-common -mkernel -fno-rtti -fno-exceptions \
|
||||||
|
-fno-stack-protector -fno-strict-aliasing -Os \
|
||||||
|
-DKERNEL -D__IO80211_TARGET=260000 -DAPPLE_KEXT_OVERRIDE=override \
|
||||||
|
-c "${SCRIPT_DIR}/QualcommWifi/QualcommWifi.cpp" \
|
||||||
|
-o "${BUILD_DIR}/QualcommWifi.o"
|
||||||
|
|
||||||
|
# 3. Édition de liens (Mach-O Kext)
|
||||||
|
echo "[3/4] Édition de liens du binaire Kext..."
|
||||||
|
clang++ -target x86_64-apple-macos15.0 \
|
||||||
|
-nostdlib -mkernel -Xlinker -kext \
|
||||||
|
-Xlinker -dead_strip \
|
||||||
|
"${BUILD_DIR}/QualcommWifi.o" "${BUILD_DIR}/Firmware_WCN7850_Wifi.o" \
|
||||||
|
-o "${KEXT_MACOS}/QualcommWifi"
|
||||||
|
|
||||||
|
# 4. Copie de Info.plist
|
||||||
|
echo "[4/4] Copie de Info.plist..."
|
||||||
|
cp "${SCRIPT_DIR}/QualcommWifi/Info.plist" "${KEXT_BUNDLE}/Contents/Info.plist"
|
||||||
|
|
||||||
|
echo "=== Validation des bibliothèques et symboles avec kmutil ==="
|
||||||
|
kmutil libraries -p "${KEXT_BUNDLE}" > /dev/null
|
||||||
|
echo "✓ Validation kmutil réussie à 100% contre BootKernelExtensions.kc !"
|
||||||
|
echo "Kext produit : ${KEXT_BUNDLE}"
|
||||||
Reference in new issue
Block a user