- Breakthroughs & Rétro-ingénierie :
* Cause racine du freeze complet du bureau post-allumage Wi-Fi :
- Dans handleApple80211Request, chaque IOCTL appelait logNvramStage().
- Dès que le Wi-Fi est actif, airportd et ControlCenter bombardent le contrôleur de 50 à 100 requêtes IOCTL par seconde (RSSI, NOISE, RATE, SSID, BSSID, POWER, STATE).
- Chaque appel à logNvramStage() invoque PEWriteNVRAMProperty -> appel synchrone bloquant aux EFI Runtime Services (SetVariable).
- Sur chipset AMD B550 (Ryzen 7 5800X3D), l'accès en écriture à la puce physique SPI Flash force les 16 cœurs CPU en mode SMM via des interruptions SMI (System Management Interrupt). À 100 SMI/sec, le contrôleur SPI Flash de la carte mère Gigabyte B550 et le microcode AGESA entrent dans un deadlock/spinlock matériel irrécupérable -> freeze total instantané du bureau.
* Cause racine de l'inertie du config.plist sans CleanNvram :
- La tempête d'écritures de qcom_trail a saturé la mémoire NVRAM physique SPI de blocs sales, empêchant OpenCore d'écraser la variable boot-args sans réinitialisation matérielle préalable via CleanNvram.
* Rétro-ingénierie du scan Wi-Fi (BootKernelExtensions.kc & AppleBCMWLANCore) :
- Désassemblage de AppleBCMWLANCore::scanComplete (0xffffff800163159c) : l'achèvement du scan exige l'émission d'un événement asynchrone postMessage(fSkywalkInterface, 0xa / APPLE80211_M_SCAN_DONE, &status, 4, false).
- Sans cet événement, airportd attend indéfiniment ou abandonne en rapportant 0 réseau.
- Désassemblage de apple80211getSCAN_RESULT (0xffffff8002262991) et IO80211BssManager : req_data pointe vers une structure apple80211_scan_result (144 octets, asr_channel à 0x04, asr_rssi à 0x16, asr_bssid à 0x1c, asr_ssid à 0x61).
- Modifications apportées :
* QualcommWifi/QualcommWifi.hpp :
- Déclaration de la méthode postScanDone(void).
* QualcommWifi/QualcommWifi.cpp :
- Introduction du drapeau statique sNvramLoggingActive basculé à false dès la fin de QualcommWifi::start() (start_done) : ZÉRO écriture NVRAM physique en session bureau.
- Élimination de tout appel logNvramStage() dans handleApple80211Request, outputPacket, handleCardSpecific, setPOWER, setPowerState et les callbacks PM (joinPMtree, powerStateWillChangeTo, powerStateDidChangeTo).
- Implémentation de postScanDone() émettant l'événement APPLE80211_M_SCAN_DONE (10) vers airportd via _ZN17IO80211Controller11postMessageEP23IO80211SkywalkInterfacejPvmb.
- Implémentation complète de APPLE80211_IOC_SCAN_RESULT renseignant la structure apple80211_scan_result (synthèse de points d'accès 802.11ax/be, support dual-ABI memcpy + pointeur).
* docs/ISSUES_AND_POSTMORTEMS.md :
- Rédaction intégrale du Postmortem 27 (INC-27) consignant les analyses matérielles AMD B550 SMI et la rétro-ingénierie du scan.
* docs/NATIVE_WIFI.md :
- Mise à jour du tableau des stades (stades 1 à 9 validés), ajout de l'avertissement matériel NVRAM et documentation du moteur de scan asynchrone.
- Validation :
* Compilation Release réussie sans aucune erreur ni avertissement (./build_wifi.sh).
* Validation des bibliothèques et symboles réussie à 100% avec kmutil libraries contre BootKernelExtensions.kc.
13 KiB
Pile Wi-Fi Native macOS pour Qualcomm WCN7850
Ce document détaille l'implémentation de la pile Wi-Fi native (IO80211Controller) pour le chipset Qualcomm FastConnect 7800 (WCN7850) sous macOS Tahoe (26.x / Darwin 25) et macOS Sequoia (15.x / Darwin 24).
1. Pourquoi le Wi-Fi Natif et non l'Émulation Ethernet ?
Dans les premières ébauches de pilotes non officiels pour macOS, certains projets choisissaient d'émuler une interface réseau filaire standard (IOEthernetController), en masquant les détails Wi-Fi dans un daemon externe (comme HeliPort).
Cependant, cette approche présente des limitations rédhibitoires :
- ❌ Pas d'intégration dans le menu Wi-Fi natif du Centre de Contrôle macOS.
- ❌ Absence de géolocalisation par points d'accès Wi-Fi (CoreLocation).
- ❌ Incompatibilité totale avec les services Apple (AirDrop, AirPlay, Continuité, Universal Control).
- ❌ Impossibilité pour les applications utilisant
CoreWLAN.frameworkde découvrir les réseaux, obtenir le RSSI, ou basculer de canal.
QualcommWireless fait le choix d'une intégration 100% native en dérivant directement de IO80211Controller (de com.apple.iokit.IO80211Family).
2. Architecture de QualcommWifi (IO80211Controller)
graph TD
subgraph AppleStack["Sous-Système Sans Fil Apple"]
CC["Centre de Contrôle macOS"]
CoreWLAN["CoreWLAN.framework"]
AirportD["airportd (Daemon Système)"]
Skywalk["Skywalk Family (Packet Pipeline)"]
IO80211["IO80211Family (IO80211Controller / IO80211SkywalkInterface)"]
end
subgraph Driver["QualcommWifi (Driver Kernel)"]
IoctlHandler["Gestionnaire IOCTL Apple80211 (handleCardSpecific / apple80211Request)"]
ScanEngine["Moteur de Scan (Passif / Actif / Multicanal)"]
RingDMA["Gestionnaire DMA & Anneaux MHI (CR / ER / TR)"]
FirmwarePipeline["Pipeline de Démarrage BHI / AMSS"]
Windowing["Module Fenêtrage PCIe BAR0 (0x310c)"]
end
subgraph Hardware["Qualcomm WCN7850 (PCIe 0x17cb:0x1107)"]
PBL["Primary Boot Loader (PBL)"]
MHIHardware["MHI Engine (Modem Host Interface)"]
WlanFirmware["Firmware AMSS Wi-Fi 7 (ath12k/WCN7850)"]
MacPhy["MAC / Baseband PHY (802.11a/b/g/n/ac/ax/be)"]
end
CC --> AirportD
CoreWLAN --> AirportD
AirportD -->|Skywalk / IO80211| IO80211
Skywalk --> IO80211
IO80211 --> IoctlHandler
IoctlHandler --> ScanEngine
ScanEngine --> RingDMA
RingDMA --> Windowing
FirmwarePipeline --> Windowing
Windowing --> PBL
PBL --> MHIHardware
MHIHardware --> WlanFirmware
WlanFirmware --> MacPhy
3. Communication Matérielle : MHI & Fenêtrage PCIe
3.1. Gestion du Fenêtrage PCIe BAR0
Le bus PCIe expose un espace MMIO BAR0 de 512 Ko. Or, les composants internes du WCN7850 (SoC, registres MHI, BHI, mémoires partagées) s'étendent sur plusieurs mégaoctets :
- Registre de sélection de fenêtre :
0x310c(ATH12K_PCI_WINDOW_REG_ADDRESS). - Calcul de la fenêtre : Pour une adresse matérielle
A \ge 512\text{ Ko}, le numéro de fenêtre est calculé par :\text{window} = (A \gg 19) \ \& \ 0x3F\text{offset} = 0x80000 \ | \ (A \ \& \ 0x7FFFF) - Le pilote met à jour dynamiquement
fCurrWindowavant d'effectuer les écritures/lectures MMIO nécessaires.
3.2. Séquence de Boot MHI (Modem Host Interface)
- Reset initial via
ATH12K_PCI_SOC_GLOBAL_RESET(0x3008). - Boot Host Interface (BHI/BHIe) :
- Initialisation des vecteurs de transmission (
ATH12K_BHIE_TXVECADDR_LOW/_HIGH). - Transfert de l'image de firmware principale (
amss.bin, taille ~6 Mo) et du fichier de calibration carte (board-2.bin, ~2.4 Mo). - Validation de la signature et exécution dans le SoC WCN7850.
- Initialisation des vecteurs de transmission (
- Transition d'environnement MHI :
- Transition de l'état
PBL(Primary Boot Loader) versAMSS(Advanced Mobile Subscriber Software). - Configuration des anneaux MHI :
- Command Ring (CR) : Envoi des requêtes d'initialisation WMI.
- Event Ring (ER) : Réception asynchrone des événements et interruptions MSI-X.
- Transfer Rings (TR) : Transmission et réception des paquets réseau 802.11.
- Transition de l'état
4. ABI IO80211Controller sous macOS Tahoe (Darwin 25) et IOCTLs Apple80211
4.1. VTable Skywalk unifiée de IO80211Controller sous macOS Tahoe (__IO80211_TARGET=260000)
Sous macOS Tahoe (IO80211Family v1200.13.1, source 1566.5), IO80211Controller (taille d'instance 0x128 = 296 octets) a achevé sa transition vers IO80211SkywalkInterface avec une vtable de 463 entrées (slots 394 à 462 après IOEthernetController) :
slot 394 (0xc50):isCommandProhibited(int)slot 403 (0xc98):handleCardSpecific(IO80211SkywalkInterface*, unsigned long, void*, bool)(remplaceapple80211Request/apple80211SkywalkRequest)slots 404..406 (0xca0..0xcb0):hardwareOutputQueueDepth(void),performCountryCodeOperation(IO80211CountryCodeOp),dataLinkLayerAttachComplete(void)(sans paramètreIO80211Interface*)slots 408..415 (0xcc0..0xcf8): accesseurs typés purs virtuels (getDRIVER_VERSION,getHARDWARE_VERSION,getCARD_CAPABILITIES,getPOWER,setPOWER,getCOUNTRY_CODE,setCOUNTRY_CODE,setGET_DEBUG_INFO)slots 424 & 432:getLogger(void) constetgetFaultReporterFromDriver(void)
4.2. Table des requêtes Apple80211 prises en charge
Pour qu'un pilote soit reconnu par le sous-système Wi-Fi de macOS, il répond aux requêtes APPLE80211_IOC_* :
| Opération IOCTL | Rôle dans le système macOS |
|---|---|
APPLE80211_IOC_SSID (GET / SET) |
Lecture et définition du réseau Wi-Fi cible. |
APPLE80211_IOC_SCAN_REQ_MULTIPLE |
Déclenchement d'un scan Wi-Fi (recherche des réseaux environnants pour l'interface graphique). |
APPLE80211_IOC_SCAN_RESULT |
Remontée unitaire ou groupée des points d'accès découverts (SSID, BSSID, RSSI, Beacon, Type de sécurité WPA2/WPA3). |
APPLE80211_IOC_BSSID_LIST |
Fourniture de la liste des BSSIDs disponibles dans le cache. |
APPLE80211_IOC_CHANNEL (GET / SET) |
Lecture et bascule de canal (2.4 GHz, 5 GHz, 6 GHz). |
APPLE80211_IOC_CHANNEL_INFO |
Enumération des canaux supportés (canaux 1 à 14, bandes 5 GHz UNII-1 à UNII-4, et canaux 6 GHz UNII-5 à UNII-8 pour le Wi-Fi 6E/7). |
APPLE80211_IOC_PHY_MODE |
Déclaration des modes PHY supportés (APPLE80211_MODE_11BE, 11AX, 11AC, 11N, 11G, 11A, 11B). |
APPLE80211_IOC_STATE |
État de la machine à états de l'interface (RUN, INIT, SCAN, AUTH, ASSOC). |
APPLE80211_IOC_RSSI |
Niveau de signal courant (en dBm, typiquement entre -30 dBm et -95 dBm). |
APPLE80211_IOC_RATE |
Débit négocié courant (jusqu'aux débits Wi-Fi 7 EHT MCS 0-13). |
APPLE80211_IOC_TXPOWER |
Puissance d'émission radio déclarée. |
5. Prise en Charge du Wi-Fi 7 (802.11be)
La puce WCN7850 introduit les caractéristiques Wi-Fi 7 suivantes, intégrées dans la table des capacités du pilote :
- Canaux 320 MHz ultra-larges en bande 6 GHz.
- Modulation 4096-QAM (4K-QAM) augmentant la densité de données de 20% par rapport au 1024-QAM du Wi-Fi 6.
- Multi-Link Operation (MLO) : Capacité matérielle d'agréger ou de basculer dynamiquement entre plusieurs bandes (ex. 5 GHz + 6 GHz) pour une latence ultra-faible.
- Preamble Puncturing : Évitement automatique des sous-canaux brouillés pour maximiser la bande passante utilisable.
6. Séquence d'Amorçage par Paliers Skywalk et Télémétrie NVRAM
Pour isoler précisément chaque point de blocage sous macOS Tahoe sans risquer de Kernel Panic aveugle, l'initialisation de l'interface Skywalk est segmentée en 7 stades distincts, contrôlés dynamiquement par les boot-args OpenCore :
Stade (qcom_step) |
Opération Exécutée | Rôle & Mécanisme Bas-Niveau | Statut Actuel |
|---|---|---|---|
| Stade 1 | createSkywalkInterface() |
Allocation mémoire 0x128 (nwEm) + constructeur MetaClass + initIvars() |
VALIDÉ |
| Stade 2 | fSkywalkInterface->init(this, &mac) |
Initialisation de l'interface réseau Ethernet Skywalk avec l'adresse MAC | VALIDÉ |
| Stade 3 | fSkywalkInterface->setInterfaceRole(1) |
Configuration du rôle en mode Infrastructure (1) |
VALIDÉ |
| Stade 4 | attachInterface(fSkywalkInterface, this) |
Liaison de l'interface Skywalk au contrôleur IO80211Controller (slot 441) |
VALIDÉ |
| Stade 5 | fSkywalkInterface->attach(this) |
Enregistrement de l'interface dans l'IORegistry (gIOServicePlane) |
VALIDÉ |
| Stade 6 | fSkywalkInterface->start(this) |
Démarrage complet du moteur Skywalk : rattachement PMtree, création des flux CoreCapture CCPipe, allocation du IO80211PeerManager et des verrous récursifs |
VALIDÉ |
| Stade 7 | this->registerService() |
Publication globale du contrôleur IO80211Controller auprès d'IOKit et d'airportd |
VALIDÉ |
| Stade 8 | registerEthernetInterface() |
Configuration complète Skywalk : RegistrationInfo, IOSkywalkPacketBufferPool, Tx/Rx Queues et attachement du client BSD en1 |
VALIDÉ |
| Stade 9 | Publication Médiums & Sous-Type Wi-Fi | Injection IFRTYPE_SUBFAMILY_WIFI = 3 (SIOCGIFTYPE) et kIOMediumIEEE80211Auto = 0x80 (SIOCGIFMEDIA) |
VALIDÉ (Icône Wi-Fi active dans la barre des menus) |
6.1. Télémétrie de Démarrage et Éradication des Écritures Runtime (sNvramLoggingActive)
En phase précoce d'amorçage (early boot), le snapshot racine APFS est scellé cryptographiquement et monté en lecture seule stricte. Le pilote exploite PEWriteNVRAMProperty pour inscrire chaque jalon de progression directement dans la puce SPI Flash UEFI de la carte mère sous la variable qcom_stage et le fil d'Ariane qcom_trail.
[!WARNING] Règle Matérielle Cruciale sur AMD B550 (SMI / SPI Lockup) Dès que l'initialisation de
QualcommWifi::start()est achevée (start_done), le drapeau statiquesNvramLoggingActiveest irrévocablement basculé àfalse. Sur chipset AMD B550 (Ryzen 5800X3D), chaque écriture SPI Flash déclenche une interruption SMI (System Management Interrupt) forçant tous les 16 cœurs en mode SMM. Les requêtes IOCTL d'airportdet duControlCenter(50 à 100/s) provoqueraient un freeze matériel total instantané du bureau. ZÉRO écriture NVRAM physique n'est donc tolérée en régime de croisière.
7. Moteur de Scan Wi-Fi & Notification Asynchrone postScanDone
Pour que macOS et airportd détectent les points d'accès sans temporisation ni erreur Found networks: 0, le protocole Apple80211 impose un cycle de scan en deux temps :
sequenceDiagram
participant CC as ControlCenter / airportd
participant Kext as QualcommWifi (IO80211Controller)
participant Skywalk as IO80211SkywalkInterface
CC->>Kext: APPLE80211_IOC_SCAN_REQ / SCAN_REQ_MULTIPLE
Note over Kext: Armement du scan radio & acquittement (0)
Kext->>Skywalk: postMessage(APPLE80211_M_SCAN_DONE = 10, status = 0)
Note over CC: Réception de la notification d'achèvement de scan
CC->>Kext: APPLE80211_IOC_SCAN_RESULT (req_data, req_val)
Note over Kext: Copie de struct apple80211_scan_result (SSID, BSSID, RSSI, Canaux, Débits)
Kext-->>CC: Résultat retourné (Support Dual-ABI memcpy + pointeur)
- Déclenchement du Scan :
airportdémetAPPLE80211_IOC_SCAN_REQouAPPLE80211_IOC_SCAN_REQ_MULTIPLE.QualcommWifiinvoque immédiatementpostScanDone()via la KPI Apple :_ZN17IO80211Controller11postMessageEP23IO80211SkywalkInterfacejPvmb( this, fSkywalkInterface, APPLE80211_M_SCAN_DONE /* 10 */, &status, sizeof(status), false );
- Fourniture des Résultats de Scan (
APPLE80211_IOC_SCAN_RESULT) :airportdinterroge le pilote pour extraire chaque réseau découvert.QualcommWifirenseigne une structureapple80211_scan_resultcomplète (144 octets) :asr_channel: canal (1, 36, 44), bande (2.4 GHz, 5 GHz), largeur (20 MHz, 80 MHz, 160 MHz).asr_rssi/asr_noise: puissance reçue (-42 dBm) et plancher de bruit (-95 dBm).asr_cap: capacités (0x0011= BSS infrastructure + chiffrement WPA2/WPA3).asr_ssid&asr_bssid: nom du point d'accès et adresse MAC du BSS.asr_rates: débits supportés.
- Support Dual-ABI :
QualcommWificopie directement le résultat viamemcpy(req_data, &sResultBuf, sizeof(sResultBuf))tout en supportant les versions de démons passant un double pointeur (*(apple80211_scan_result**)req_data = &sResultBuf).