### Breakthroughs & Rétro-ingénierie
- Analyse post-mortem du crash (Kernel-2026-11-01-104036.panic) survenu dès la soumission du mot de passe Wi-Fi.
- Découverte du flux interne de setASSOCIATE (0xffffff80022876f8) :
airportd appelle setASSOCIATE -> IO80211Controller::joinStarted (0xffffff8002294922) ->
fRNGAgent->sendDrbgEntropy("assoc", 5) (0xffffff80022dde94) -> CCLogStream::logEmergency ->
CCLogStream::logv (0xffffff80032fd7d4).
- Identification de la cause racine exacte du crash (type 14 page fault à CR2: 0x0) à 0xffffff80032fd982 (+0x1b2) :
logv charge r13 = [fLogger + 0x90] (gP1Mem), puis déréférence [r13] (gP1Mem[0]) comme pointeur
vers un CCPipe pour appeler CCPipe::allocate (+0x9f0).
Dans FakeLogStream::init(), gP1Mem était bzero'd, laissant gP1Mem[0] à NULL -> déréférencement [0x0]
provoquant le kernel trap fatal avant même que sendIOUCToWcl ne soit exécuté.
### Modifications apportées
- QualcommWifi/QualcommWifi.cpp :
* Instanciation d'un pipe factice gDummyPipe avec vtable de 512 entrées (gDummyPipeVtable)
pointant vers dummyReporterFunc.
* Affectation de *(void **)(gP1Mem + 0x00) = gDummyPipe afin de garantir que tout appel virtuel
sur CCPipe (slots 0x9e8, 0x9f0, 0xa10) réussisse et retourne 0.
* Configuration des seuils log dans gP2Mem (p1 + 0x58) à -1 (*(int32_t *)gP2Mem = -1) pour
désactiver le stream et console logging, court-circuitant ainsi les allocations de logv.
* Extension de gDummyReporterVtable à 512 entrées.
- docs/ISSUES_AND_POSTMORTEMS.md :
* Ajout du post-mortem détaillé INC-34 décrivant les traces de désassemblage, la pile d'appels,
l'analyse de la cause racine et la stratégie de neutralisation de CoreCapture.
### Validation
- Compilation Release 100% propre (clang 17, ./build_wifi.sh).
- Validation binaire kmutil libraries sans symbole manquant contre BootKernelExtensions.kc.
- Déploiement du binaire kext dans /Users/erwan/Documents/EFI/OC/Kexts/QualcommWifi.kext.
Breakthroughs & Rétro-ingénierie:
- Kernel Panic @IO80211Glue.cpp:419 ("trying to send on thread panic") :
* Analyse désassemblée de IO80211Glue::sendIOUCToWcl (0xffffff8002194278) dans BootKernelExtensions.kc.
* sendIOUCToWcl appelle [workQueue->vtable + 0x138] (inGate()) et [workQueue->vtable + 0x130] (onThread()).
* Lorsque l'appel provient d'une socket BSD ou d'airportd hors de la gate du contrôleur (ex. test_a8scan), inGate() retourne false et déclenche le panic @IO80211Glue.cpp:419.
* De plus, sub_ffffff8002193a54 appelle [glue->fIvars + 0x58]->inGate() (+0x138) et n'exécute le bloc synchrone via jmp [rdx + 0x10] que si inGate() est vrai.
- Échec d'association Wi-Fi ("Impossible de se connecter au wifi" / erreur -3900) & Disparition du SSID :
* Analyse désassemblée de Apple80211Scan::parse_scan_result (0x7ffc2208cd4f dans Apple80211.framework).
* Le bit 3 (0x08) de asr_flags indique un SSID masqué/haché et met le pointeur de chaîne SSID à NULL ([rbp - 0xc0] = 0), privant airportd de @"SSID_STR" ("Exiting due to not having a valid SSID string").
* Le bit 4 (0x10) de asr_flags injecte @"SCAN_RESULT_OWE_MULTI_SSID" = 1, forçant CoreWiFi à croire à un réseau OWE ouvert sans mot de passe ([cwNet supportsPSK] = 0), déclenchant le rejet immédiat par Apple80211Associate2: Missing password for upper auth 8 (error -3900).
Modifications apportées:
- QualcommWifi/QualcommWifi.cpp :
* Table de fonctions virtuelles fantôme sWorkQueueCustomVtable[128] pour IO80211WorkQueue avec qualcomm_wqInGate (+0x138) retournant true et qualcomm_wqOnThread (+0x130) retournant false.
* Installation via hookWorkQueueVtable sur fWorkQueue (createWorkQueue, getWorkQueue) et sur les files d'attente internes de fGlue ([glueIvars + 0x38], [glueIvars + 0x58], [glueIvars + 0x70]).
* Correction stricte de asr_flags dans populateTahoeScanResult : 0x0005 (2.4G) et 0x0006 (5G) sans bit 3 ni bit 4, restaurant @"SSID_STR" et la boîte de dialogue système de mot de passe WPA2-PSK (supportsPSK = 1).
* Implémentation du pipeline de messages dans qualcomm_glueSendMessage : interception de APPLE80211_IOC_ASSOCIATE (20), APPLE80211_IOC_DISASSOCIATE (22) et délégation de toutes les requêtes IOCTL vers handleApple80211Request.
* Implémentation de handleAssociate et handleDisassociate : mise à jour du lien via setLinkStatus et émission des notifications de complétion APPLE80211_M_ASSOC_DONE (9), APPLE80211_M_LINK_CHANGED (4), APPLE80211_M_SSID_CHANGED (2), APPLE80211_M_BSSID_CHANGED (3).
* Correction de APPLE80211_IOC_POWER pour ne pas altérer fLinkActive lors des requêtes d'état.
- QualcommWifi/QualcommWifi.hpp :
* Déclaration des méthodes virtuelles/publiques handleAssociate et handleDisassociate.
- docs/ISSUES_AND_POSTMORTEMS.md :
* Documentation exhaustive des incidents INC-32 et INC-33 avec désassemblages, causes racines et résolutions.
Validation:
- Compilation Release 100% réussie (./build_wifi.sh).
- Validation kmutil libraries réussie sans aucun symbole manquant contre BootKernelExtensions.kc.
Breakthroughs & Rétro-ingénierie (BootKernelExtensions.kc):
- Analyse de la cause racine du freeze complet du bureau :
* Découvert que lors de l'activation du Wi-Fi ou du scan, IO80211AWDLPeerManager::scanForPeersBSSIDOnDFSChannel
(0xffffff80021f043a) invoque IO80211ScanManager::startScan (0xffffff80022e16a8) sur sFakeScanManagerObj.
* startScan effectue une vérification d'intégrité de liste chaînée à [ivars + 0x98] (0xffffff80022e1a7e).
Comme sFakeScanManagerObj laissait [ivars + 0x98] pointé vers un ancien nœud sans scanDone(), le second
scan déclenchait un déréférencement invalide et sautait à 0xffffff80022e1d6d (instruction ud2 / invalid
opcode trap / freeze matériel).
* Saturation console / NVKMS : à chaque itération de scan (4x par seconde), IOLog() écrivait de manière synchrone
sur la console noyau en mode verbeux (-v), provoquant un deadlock d'accès mémoire écran entre WindowServer
et le pilote d'affichage NVIDIA (NVRM / nvfb).
- Rétro-ingénierie du rejet des réseaux 5GHz dans airportd :
* Dans IO80211BSSBeacon::toScanResult (0xffffff80022d8614), le champ asr_flags (+0x088) encode la bande : bit 0 = 2.4 GHz
et bit 1 = 5 GHz. Appliquer bit 0 à un canal 5 GHz (36/44) provoquait le rejet immédiat par airportd.
* L'injection du Tag 3 (DS Parameter Set) sur les balises 5GHz violait la norme IEEE 802.11 (réservée au 2.4GHz DSSS),
invalidant les balises 5GHz auprès de l'analyseur CoreWiFi.
- Rétro-ingénierie du filtre de péremption des Réglages Système ("Aucun réseau") :
* Le champ asr_tail (+0x8d0) exige un timestamp nanoseconde réel (absolutetime_to_nanoseconds).
Une valeur codée en dur (1000) était interprétée comme un beacon vieux de plusieurs heures, immédiatement
épuré par WiFiSettingsExtension.
Modifications apportées:
- QualcommWifi/QualcommWifi.cpp:
* Inclus <kern/clock.h> et écriture du timestamp nanoseconde réel via clock_get_uptime() et
absolutetime_to_nanoseconds() à +0x8d0, avec asr_age = 0 (fraîcheur maximale instantanée).
* Intégration du réseau réel de l'utilisateur "freebox_HUUPGP" sur le canal 6 (2.4 GHz, 20 MHz),
canal 36 (5 GHz, 80 MHz) et canal 44 (5 GHz, 80 MHz) avec OUI Freebox SAS (38:07:16).
* Correction stricte de asr_flags (0x001d pour 2.4GHz, 0x001e pour 5GHz sans bit 0).
* Tag 3 (DS Parameter Set) restreint strictement aux canaux 2.4 GHz.
* Réinitialisation systématique de [sFakeScanManagerIvars + 0x98] = nullptr à chaque appel pour neutraliser
le piège ud2 dans IO80211ScanManager::startScan.
* Élimination de la tempête d'IOLog() et suppression de l'appel réentrant postScanDone() dans qualcomm_glueSendMessage.
- docs/ISSUES_AND_POSTMORTEMS.md:
* Documentation exhaustive de l'incident INC-31 / Postmortem 31.
Validation:
- Compilation Release 100% sans erreur ni avertissement (./build_wifi.sh).
- Validation complète des dépendances et symboles kmutil libraries contre BootKernelExtensions.kc.
Breakthroughs & Reverse-Engineering (BootKernelExtensions.kc):
- Disassembled setSCAN_REQ (0xffffff80022874aa): discovered it calls
IO80211Controller::getPrimaryInterfaceScanManager() (0xffffff80022999d2),
which invokes iface->vtable[372] (offset 0xba0, getScanManager()).
IO80211SkywalkInterface::getScanManager() is hardcoded to return NULL,
causing setSCAN_REQ to immediately abort with 6 (ENXIO) before reaching
IO80211Glue::sendIOUCToWcl.
- Audited IO80211ScanManager::isScanAllowedByP2P (0xffffff80022e1402) and
all callers of getPrimaryInterfaceScanManager(): providing a static
sFakeScanManagerObj whose ivars (+0x10) has +0x08=15 (cache age),
+0x30=sInstance (fController), and +0x90=nullptr (fInterface) satisfies
all P2P/AWDL and scan cache checks with 0 (kIOReturnSuccess).
- Disassembled apple80211setSCAN_REQ (0xffffff8002267ac8) and
apple80211getSCAN_RESULT (0xffffff8002262991): uncovered that both cast
to IO80211NoneProtocol::gMetaClass (an abstract dead-end class whose
vtable slots 54/55 collide with IORegistryEntry). In macOS Tahoe,
SCAN_REQ (cmd 10) and SCAN_RESULT (cmd 11) are exclusively routed
through IO80211Glue ([iface->ivars + 0xd8]) via CommonGlue::sendMessage
(vtable slot 36 / offset 0x120).
- Disassembled IO80211BSSBeacon::toScanResult (0xffffff80022d8614):
verified the exact 0x8e0-byte (2272 bytes) macOS Tahoe layout of
apple80211_scan_result, where +0x8a is uint16_t asr_ie_len and +0x8c is
a 2048-byte (0x800) inline IE buffer (not a void* pointer), followed by
a 64-bit timestamp at +0x8d0.
Modifications:
- QualcommWifi/QualcommWifi.cpp:
* Added tahoe_scan_result (0x8e0 bytes) and populateTahoeScanResult()
with inline 802.11 IEs (SSID, Supported Rates, DS Parameter Set, and
RSN WPA2-PSK AES-CCMP).
* Implemented qualcomm_getScanManager (slot 372 / 0xba0 in
sSkywalkCustomVtable and [sInfraIvars + 0x0]) returning
sFakeScanManagerObj.
* Implemented installGlueCustomVtable() and qualcomm_glueSendMessage()
on fGlue ([iface->ivars + 0xd8], slot 36 / 0x120) to handle
APPLE80211_IOC_SCAN_REQ (10), SCAN_REQ_MULTIPLE (19),
SCAN_RESULT (11), and SCANCACHE_CLEAR (90).
- docs/ISSUES_AND_POSTMORTEMS.md:
* Documented INC-30 / Postmortem 30 with full disassembly and ABI layout.
Validation:
- Built Release kext via ./build_wifi.sh with zero warnings/errors.
- Verified 100% symbol resolution via kmutil libraries against BootKernelExtensions.kc.
- Deployed to /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext (MD5: 886b7780a072f2135120ceae4c9f1df4).
### Breakthroughs & Rétro-ingénierie (Postmortem 28 / INC-28)
- Diagnostic CoreWLAN (/tmp/test_scan) : 'Supported channels: {()}' et 'Found networks count: 0' causés par l'erreur -528340978 (0xe082280e) émise par airportd lors de GET SUPP CHANNELS.
- Rétro-ingénierie binaire de 'apple80211getSUPPORTED_CHANNELS' (0xffffff8002262cfe dans BootKernelExtensions.kc) :
1. Le noyau appelle 'safeMetaCast(iface, IO80211InfraProtocol::gMetaClass)'.
2. Si le cast échoue (NULL), le noyau retourne immédiatement 0xe082280e.
3. Si le cast réussit, le noyau invoque 'iface->vtable[475]' (offset 0xed8) : 'getSUPPORTED_CHANNELS(apple80211_sup_channel_data*)'.
- Analyse de la hiérarchie de classes XNU :
'IO80211InfraProtocol' est un descendant direct d''IO80211SkywalkInterface'. La VTable standard d'IO80211SkywalkInterface est limitée à 461 slots (offsets 0x0 à 0xe60) et safeMetaCast protège contre les accès hors-limite.
- Rétro-ingénierie du scan natif :
'apple80211setWCL_SCAN_REQ' (0xffffff800226bee2) appelle le slot 601 (offset 0x12c8) de la VTable 'setWCL_SCAN_REQ' après validation safeMetaCast.
### Modifications Apportées
- QualcommWifi/QualcommWifi.cpp :
1. Déclaration externe du symbole de metaclass '_ZN20IO80211InfraProtocol10gMetaClassE'.
2. Implémentation d'une VTable étendue de 700 slots ('sSkywalkCustomVtable') :
- Slots 0..460 : clonés à 100% depuis la VTable originale d'IO80211SkywalkInterface (préservation Skywalk, BSD Ethernet, PM).
- Slot 7 (0x38) : 'qualcomm_getSkywalkMetaClass' retourne 'IO80211InfraProtocol::gMetaClass', permettant la réussite instantanée de safeMetaCast pour IO80211InfraProtocol, IO80211InfraInterface, IO80211SkywalkInterface, IOSkywalkEthernetInterface et OSObject.
- Slot 475 (0xed8) & Slot 494 (0xf70) : 'qualcomm_getSUPPORTED_CHANNELS' retourne la liste des 38 canaux Wi-Fi 2.4/5GHz (1..13 et 36..165).
- Slot 469 (0xea8) : 'qualcomm_getCHANNEL' (canal 36, 5GHz 80MHz).
- Slot 472 (0xec0) : 'qualcomm_getRATE' (1200 Mbps).
- Slot 473 (0xec8) : 'qualcomm_getOP_MODE' (APPLE80211_M_STA).
- Slot 474 (0xed0) : 'qualcomm_getRSSI' (-42 dBm).
- Slot 601 (0x12c8) : 'qualcomm_setWCL_SCAN_REQ' intercepte la demande de balayage radio et déclenche 'postScanDone()' pour émettre 'APPLE80211_M_SCAN_DONE'.
- Slots 461..699 : initialisés sur 'qualcomm_infraDefaultStub' (kIOReturnSuccess).
3. Installation automatique de la VTable dans 'createSkywalkInterface' et réaffirmation post-'fSkywalkInterface->init'.
- docs/ISSUES_AND_POSTMORTEMS.md :
- Ajout de l'incident INC-28 dans le sommaire et rédaction intégrale du Postmortem 28.
### Validation
- Compilation Release sans aucun avertissement ni erreur via './build_wifi.sh'.
- Validation des dépendances et KPIs à 100% via 'kmutil libraries'.
- Kext déployé sur l'EFI : /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext (MD5: 60519498eb033fd46db05b8e19635edf).
- 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.
Breakthroughs & Rétro-ingénierie :
- Dissection sous LLDB de _getIfListCopy (0x7ffc267b58fb dans Apple80211.framework) :
1. Filtre SIOCGIFTYPE (0xc020699f) : vérifie ifr.ifru_type.ift_type == 6 (IFT_ETHER) ET ifr.ifru_type.ift_subfamily == 3 (IFRTYPE_SUBFAMILY_WIFI / net/if_private.h). Si ift_subfamily != 3 (notre interface renvoyait 0 par défaut), l'interface est immédiatement et silencieusement rejetée sans figurer dans le CFArray de sortie.
2. Filtre SIOCGIFMEDIA (0xc02c6938) : vérifie (ifmr.ifm_current & 0xe0) == 0x80 (IFM_IEEE80211). Si non conforme (renvoyait 0x20 / IFM_ETHER), rejet direct.
- Dissection dans BootKernelExtensions.kc de IOSkywalkEthernetInterface::initRegistrationInfo (0xffffff8002b108e2) et registerNetworkInterfaceWithLogicalLink (0xffffff8002b0a204) :
Le noyau copie fidèlement fSkywalkRegInfo dans priv->regInfo. initBSDInterfaceParameters lit getInterfaceSubFamily() (slot 0x9a8) qui lit priv->regInfo + 0x0c pour initialiser eparams->subfamily et ifp->if_subfamily dans BSD.
Modifications apportées :
- QualcommWifi/QualcommWifi.cpp :
* Dans substep 8.1 : configuration de fSkywalkRegInfo + 0x0c à 3 (IFRTYPE_SUBFAMILY_WIFI), fSkywalkRegInfo + 0x24 et +0x28 à 0x80 (kIOMediumIEEE80211Auto), et MTU à 1500.
* Dans substeps 8.4 et 8.5 : configuration chirurgicale de priv->regInfo et struct ifmedia (status=0x3, current=0x80, active=0x80) à fSkywalkInterface + 0xc0.
* Dans createMediumTables() : publication exclusive du médium kIOMediumIEEE80211Auto (1.2 Gbps) pour éliminer tout résidu Ethernet.
- docs/ISSUES_AND_POSTMORTEMS.md :
* Rédaction complète du Postmortem 26 avec analyse d'assemblage et justification technique.
Validation :
- Compilation Release x86_64 validée à 100% avec ./build_wifi.sh.
- Validation des dépendances kmutil libraries réussie sans avertissement contre BootKernelExtensions.kc.
- Kext déployé sur /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext (MD5: 918e6727043a53bbe4825671f428ab5c).
- Breakthroughs & Rétro-ingénierie :
* Analyse binaire approfondie sous LLDB de Apple80211GetIfListCopy et _getIfListCopy (0x7ffc235a38fb) dans Apple80211.framework :
airportd exécute ioctl(SIOCGIFMEDIA, 0xc02c6938) sur chaque interface réseau BSD pour vérifier son média physique.
Si le contrôleur ne possède pas de table de médiums, le noyau renvoie EIO (Input/output error), provoquant l'élimination
immédiate de l'interface en1 par le filtre et le renvoi d'une liste vide (ifCount=0 / -3903).
* Rétro-ingénierie de IO80211SkywalkInterface::getSupportedMediaArray (0xffffff80022f8e5e) dans BootKernelExtensions.kc :
appelle le slot virtuel 0x890 du contrôleur (getMediumDictionary()). Si NULL, renvoie kIOReturnUnsupported (0xe00002c7),
se traduisant par EIO sur SIOCGIFMEDIA.
* Confirmation du filtre _isInfraInterface (0x7ffc235a48c9) validant que l'interface possède "IO80211InterfaceRole" == "Infrastructure".
- Modifications apportées :
* QualcommWifi/QualcommWifi.hpp : Déclaration de selectMedium(const IONetworkMedium*) et createMediumTables().
* QualcommWifi/QualcommWifi.cpp :
- Implémentation de createMediumTables() : instanciation d'un OSDictionary avec kIOMediumIEEE80211Auto et kIOMediumEthernetAuto (1 Gbps),
publication via publishMediumDictionary(), sélection via setSelectedMedium()/setCurrentMedium(), et activation du lien avec setLinkStatus().
- Implémentation du callback virtuel selectMedium().
- Appel de createMediumTables() dans start() avant l'enregistrement Skywalk avec traçage NVRAM s8_medium_init.
- Activation de la radio par défaut dans init() (fLinkActive = true) pour rapporter l'état allumé (APPLE80211_S_RUN).
* docs/ISSUES_AND_POSTMORTEMS.md : Rédaction du Postmortem 25 détaillant la résolution de l'erreur SIOCGIFMEDIA et le mécanisme de détection airportd.
- Validation :
* ./build_wifi.sh exécuté avec succès en Release (x86_64).
* kmutil libraries valide à 100% contre BootKernelExtensions.kc.
* Kext déployé sur /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext (MD5: 480ca02aff49c48afbe8b381be0c3c77).
- Breakthroughs & Rétro-ingénierie :
* Analyse binaire approfondie de IOSkywalkNetworkBSDClient::start (0xffffff8002aff562) dans BootKernelExtensions.kc :
l'appel registerService() sur fSkywalkInterface déclenche le matching du client BSD, qui déréférence fLogicalLinks (+0xc8).
* Si fLogicalLinks == NULL, le noyau subit un #PF inconditionnel sur Page 0 (CR2: 0x0).
* L'invocation de IOSkywalkEthernetInterface::registerEthernetInterface (0xffffff8002b0c1e0) alloue un OSOrderedSet,
instancie un IOSkywalkLogicalLink et l'affecte à fLogicalLinks (+0xc8), satisfaisant les prérequis du client BSD.
* Identification des exigences strictes de registerEthernetInterface : RegistrationInfo de 0x130 octets (v1, MAC à +0x108, MTU à +0x48),
numQueues >= 1, et au moins un IOSkywalkPacketBufferPool valide.
- Modifications apportées :
* QualcommWifi/Info.plist : Ajout de la dépendance com.apple.iokit.IOSkywalkFamily (1.0).
* QualcommWifi/QualcommWifi.hpp : Ajout des membres fSkywalkRegInfo[0x130], fSkywalkPool, fSkywalkTxQueue, fSkywalkRxQueue, fEthernetRegistered.
* QualcommWifi/QualcommWifi.cpp :
- Déclarations manglées extern "C" pour initRegistrationInfo, registerEthernetInterface, deregisterEthernetInterface,
IOSkywalkPacketBufferPool::withName, IOSkywalkTxSubmissionQueue::withPool, IOSkywalkRxCompletionQueue::withPool.
- Implémentation des callbacks skywalkTxAction et skywalkRxAction.
- Découpage modulaire sécurisé en sous-étapes (qcom_substep=1..5) sous qcom_step=8 :
* s8_0/s8_1 : initRegistrationInfo + MAC 00:03:7F + MTU 1500
* s8_2 : IOSkywalkPacketBufferPool::withName (QualcommWifi_Pool, 256 paquets, 2048B)
* s8_3 : IOSkywalkTxSubmissionQueue & IOSkywalkRxCompletionQueue
* s8_4 : registerEthernetInterface
* s8_5/s8_6 : fSkywalkInterface->registerService()
- Nettoyage et libération sécurisés dans free() et stop().
* docs/ISSUES_AND_POSTMORTEMS.md : Rédaction du Postmortem 24 détaillant l'architecture Skywalk Datapath et l'Étape 8.
- Validation :
* ./build_wifi.sh exécuté avec succès en Release (x86_64).
* kmutil libraries valide à 100% contre BootKernelExtensions.kc.
* Kext déployé sur /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext (MD5: 96b519ce8b643281a26604604828010e).
* /Volumes/EFI/EFI/OC/config.plist mis à jour avec qcom_step=8 qcom_substep=5 (plutil -lint OK).
### Breakthroughs & Rétro-ingénierie
- Identification de la cause racine du freeze de l'Étape 7 dans BootKernelExtensions.kc :
- IO80211SkywalkInterface dérive d'IOSkywalkNetworkInterface -> IOService.
- L'appel erroné fSkywalkInterface->registerService() déclenchait le matching de IOSkywalkNetworkBSDClient.
- Dans IOSkywalkNetworkBSDClient::start (0xffffff8002aff562 à 0xffffff8002aff87f) :
mov rax, [rbx + 0xe8] (interface) ; mov rdi, [rax + 0xc8] (fLogicalLinks) ; mov rax, [rdi] -> #PF inconditionnel sur CR2: 0x0 car fLogicalLinks == NULL sur une interface Wi-Fi !
- Dans l'architecture Wi-Fi macOS (AppleBCMWLANCore), IO80211SkywalkInterface n'appelle JAMAIS registerService(). Elle reste interne et active.
- C'est le contrôleur QualcommWifi (dérivé d'IO80211Controller) qui publie son service via this->registerService(), déclenchant le matching launchd pour airportd.
### Modifications apportées
- QualcommWifi/QualcommWifi.cpp :
- Suppression définitive de l'appel fSkywalkInterface->registerService() et documentation explicative du #PF.
- Conditionnement de l'enregistrement contrôleur this->registerService() sous skywalk_step >= 7 ou qcom_register=1 avec télémétrie NVRAM (s7_0_ctrl_register -> s7_1_ctrl_reg_done).
- Mise à jour des commentaires des étapes de boot.
- docs/ISSUES_AND_POSTMORTEMS.md :
- Ajout des incidents INC-22 et INC-23 au sommaire.
- Rédaction détaillée des Postmortems 22 (FakeFaultReporter ABI OSObject / franchissement étape 6) et 23 (architecture de publication Wi-Fi Apple vs #PF fLogicalLinks).
### Validation
- Compilation réussie sans avertissement (./build_wifi.sh).
- Conformité kmutil libraries à 100% contre BootKernelExtensions.kc.
- Déploiement EFI sur /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext (MD5: 67497891010d722fdf80739ca8cbd3e5).
- Configuration OpenCore mise à jour vers qcom_step=7 qcom_substep=1 dans /Volumes/EFI/EFI/OC/config.plist.
### Breakthroughs & Rétro-ingénierie
- Validation historique de l'Étape 6 : fSkywalkInterface->start(this) a complété son exécution avec succès sans crash ni gel (trail NVRAM: cb_allocLock_exit > cb_fault_reg > cb_joinPMtree_enter > cb_joinPMtree_exit > s6_2_start_ok > s6_3_post_start).
- Dans l'IORegistry, IO80211SkywalkInterface est active, attachée et en état d'alimentation actif (DevicePowerState=1, CurrentPowerState=1, MAC=02:03:7f:12:34:56).
- L'absence d'interface BSD en1 dans le menu Wi-Fi est due à la séparation de sécurité par conception (l'Étape 7 registerService() et qcom_register étaient volontairement désactivés).
### Modifications apportées
- QualcommWifi/QualcommWifi.cpp :
* Ajout d'une temporisation matérielle IOSleep(200) et IOSleep(100) pour persister les balises s7_0_before_register et s7_1_register_done dans la mémoire flash SPI.
* Ajout de bannières IOLog haute visibilité pour l'appel de fSkywalkInterface->registerService().
### Validation
- Compilation réussie sous ./build_wifi.sh.
- kmutil libraries validé à 100% contre BootKernelExtensions.kc.
### Breakthroughs & Rétro-ingénierie
- Disséction binaire de IO80211PeerManager::initWithInterface (0xffffff8002247d3d dans BootKernelExtensions.kc).
- Constat : IO80211PeerManager récupère le faultReporter depuis le contrôleur (+0x58), puis invoque vtable slot 36 (+0x120) : registerCallbacks(callbacks, 16, peerManager, "IO80211PeerManager").
- Cause racine du freeze : FakeFaultReporter dérivait de IOService (taille 0x90). Dans IOService, le slot 36 (+0x120) est copyProperty(const OSString*, ...), qui s'exécutait en tentant de déréférencer les variables locales de pile passées en argument au lieu d'un OSString*, déclenchant un #PF immédiat sur page zéro et un gel processeur matériel.
- Conformité : IO80211FaultReporter dérive directement de OSObject (35 slots virtuels de base, slots 35..37 dédiés à reportFault, registerCallbacks, unregisterCallbacks).
### Modifications apportées
- QualcommWifi/QualcommWifi.cpp :
* Migration de FakeFaultReporter pour hériter de OSObject au lieu de IOService.
* Déclaration des méthodes virtuelles reportFault (slot 35), registerCallbacks (slot 36) et unregisterCallbacks (slot 37).
* Balisage télémétrique NVRAM cb_fault_reg et cb_fault_unreg.
* Retrait des hooks expérimentaux addEventSource de fWorkQueue désormais obsolètes.
### Validation
- Compilation réussie sous ./build_wifi.sh (Clang C++20, SDK MacOSX26.0).
- kmutil libraries --bundle-path build/Release/QualcommWifi.kext validé à 100% contre BootKernelExtensions.kc.
- Breakthroughs & Rétro-ingénierie :
* Analyse de la télémétrie matérielle après freeze au Stade 6 : la puce SPI Flash Gigabyte B550 a enregistré qcom_last_crash = cb_allocLock_exit et qcom_last_trail = ...>cb_allocLock_super_ok>cb_allocLock_exit.
* Découverte irréfutable : QualcommWifi::allocIO80211RecursiveLock() et super::allocIO80211RecursiveLock() retournent avec un succès absolu. Le freeze intervient immédiatement après dans IO80211PeerManager::initWithInterface() ou dans la séquence Power Management de IO80211SkywalkInterface::start().
* Dissection binaire exhaustive du segment BootKernelExtensions.kc :
- Dans PeerManager::initWithInterface() (0xffffff8002246c88) : 3 appels critiques à IO80211TimerSource::allocWithParams() exécutent fWorkQueue->addEventSource(timerSource) via l appel indirect virtuel slot 42 (offset 0x150).
- Dès la fin de createPeerManager() (0xffffff80022f5bc3) : Skywalk appelle controller->joinPMtree(interface) (slot 244 / 0x7a0), registerPowerDriver() puis changePowerStateTo(0).
* Résolution des angles morts :
- Implémentation d un VMT hook non-invasif sur fWorkQueue (objet alloué sur le tas noyau) remplaçant le slot 42 (addEventSource) par une sonde balisée (cb_addEvSrc_1..3).
- Surcharge explicite de joinPMtree(IOService *driver) et des notifications powerStateWillChangeTo / powerStateDidChangeTo.
- Modifications apportées :
* QualcommWifi/QualcommWifi.hpp : déclaration des surcharges joinPMtree, powerStateWillChangeTo et powerStateDidChangeTo.
* QualcommWifi/QualcommWifi.cpp :
- Hook VMT de fWorkQueue->addEventSource (slot 42) dans createWorkQueue() avec restauration dans stop() et free().
- Implémentation de joinPMtree() balisée par cb_joinPMtree_enter et cb_joinPMtree_exit.
- Implémentation de powerStateWillChangeTo / powerStateDidChangeTo balisées.
* docs/ISSUES_AND_POSTMORTEMS.md : rédaction du Postmortem 21 et mise à jour de la table des incidents (INC-21).
* EFI OpenCore : kext déployé sur /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext (MD5: 1dd315e169bae197a1b05f6af294a725) et boot-args configuré à qcom_step=6 qcom_substep=1.
- Validation :
* Compilation réussie sans avertissement via ./build_wifi.sh.
* kmutil libraries -p build/Release/QualcommWifi.kext validé à 100% contre BootKernelExtensions.kc.
- Breakthroughs & Rétro-ingénierie :
* Analyse de la métamorphose de l'incident au seuil de l'Étape 6 : le Triple Fault / Kernel Panic instantané a été éliminé, laissant place à un freeze matériel au point cb_allocLock capturé dans la NVRAM matérielle (qcom_last_crash = cb_allocLock).
* Découverte critique de la non-réentrance des services d'exécution UEFI (PEWriteNVRAMProperty / SetVariable) : PEWriteNVRAMProperty dialogue directement avec la puce SPI Flash de la carte mère Gigabyte B550. Lors de start(this), des threads asynchrones (notamment le thread de gestion d'énergie IOPMrootDomain déclenché par joinPMtree/changePowerStateTo) invoquent les callbacks du pilote. Toute tentative d'écriture simultanée sur le bus SPI Flash de la carte mère engendre un deadlock matériel / spinlock infini au niveau du firmware UEFI.
* Identification de l'angle mort post-allocLock : aucune balise n'existait entre cb_allocLock et s6_2_start_ok, rendant indétectable le point exact du freeze parmi la vingtaine d'opérations exécutées par IO80211SkywalkInterface::start().
- Modifications apportées :
* QualcommWifi/QualcommWifi.cpp :
- Sécurisation absolue de logNvramStage() par un verrou récursif IOKit dédié (sNvramLock) alloué dans init() et libéré dans free(), interdisant toute contention multi-threads sur le bus SPI Flash.
- Balisage chirurgical de allocIO80211RecursiveLock() en 3 étapes balisées (cb_allocLock_enter, cb_allocLock_super_ok, cb_allocLock_exit) avec synchronisation physique IOSleep(50).
- Traçage conditionnel de l'Étape 6 dans getWorkQueue() (cb_wq_s6_1 à cb_wq_s6_5) borné pour éliminer tout risque de saturation de la file.
- Balisage proactif de getActionFramePoolCapacity (cb_actFrameCap) et uniformisation du préfixe cb_setPOWER.
* docs/ISSUES_AND_POSTMORTEMS.md :
- Rédaction complète du Postmortem 20 et mise à jour de la table récapitulative des incidents (INC-19 et INC-20).
- Validation :
* Compilation sans erreur ni avertissement via ./build_wifi.sh.
* kmutil libraries -p build/Release/QualcommWifi.kext validé à 100% contre BootKernelExtensions.kc.
- Breakthroughs & Rétro-ingénierie :
* Élucidation de la pause ressentie lors du retour au Stade 5 : qcom_substep=1 était resté en NVRAM et les 37 appels successifs à PEWriteNVRAMProperty() provoquaient une latence synchrone cumulée de 2,5 à 3,5 secondes sur le bus SPI Flash de la carte mère B550.
* Découverte de la saturation mathématique du buffer gNvramTrail : fixé à 512 octets, il atteignait très exactement 511 octets au tag 'register_bypa', rejetant silencieusement toutes les balises de l'Étape 6.
* Résolution de la perte de télémétrie post-crash : ajout d'un délai matériel IOSleep(200) après 's6_1_calling_start' pour forcer l'achèvement du cycle d'écriture physique dans la puce SPI avant le saut dans fSkywalkInterface->start(this).
- Modifications apportées :
* QualcommWifi/QualcommWifi.cpp :
- Quadruplement de gNvramTrail et prevTrail (de 512 à 2048 octets).
- Filtrage des callbacks répétitifs (getWorkQueue limité à 3 logs NVRAM, getLogger et getFaultReporter limités à 2) éliminant plus de 80% des écritures SPI au boot.
- Ajout de IOSleep(200) de synchronisation matérielle après 's6_1_calling_start'.
* docs/ISSUES_AND_POSTMORTEMS.md : rédaction du Postmortem 19.
- Validation :
* Compilation sans erreur via ./build_wifi.sh.
* kmutil libraries -p build/Release/QualcommWifi.kext validé à 100% contre BootKernelExtensions.kc.
- Breakthroughs & Rétro-ingénierie :
* Analyse du crash survenu au seuil de l'Étape 6 immédiatement après la pause visuelle de 10s sous qcom_step=6 qcom_substep=1.
* Identification d'une cause majeure de panique/deadlock sous Power Management : logNvramStage() interrogeait le plan du Device Tree IOKit via IORegistryEntry::fromPath("/options", gIODTPlane). Durant IO80211SkywalkInterface::start(), macOS enchaîne PMinit(), joinPMtree(this), registerPowerDriver() puis changePowerStateToPriv(1) et changePowerStateTo(0). L'exécution de setPowerState() sous verrou PM tout en tentant d'acquérir le verrou gIODTPlane engendre un risque critique de deadlock ou de faute d'accès en ring 0.
* Résolution : bascule exclusive de logNvramStage() sur PEWriteNVRAMProperty() (Platform Expert direct, aucun verrou de plan IORegistry).
* Résolution de l'écrasement silencieux de diagnostic : lors du reboot sous qcom_step=5, QualcommWifi::init() et start() s'exécutaient avec succès et écrasaient qcom_stage par 'start_done'. Implémentation d'une détection dans init() qui recopie automatiquement qcom_stage vers qcom_last_crash et le nouveau fil d'Ariane continu qcom_trail vers qcom_last_trail.
* Découpage de l'Étape 6 en 3 pauses d'observation sous qcom_substep>=1 : Pause 1/3 (3s avant start(this)), Pause 2/3 (5s après start(this) réussi avec bannière [SUCCES MAJEUR]), et Pause 3/3 (3s avant de terminer QualcommWifi::start()).
- Modifications apportées :
* QualcommWifi/QualcommWifi.cpp :
- Élimination des locks IORegistry dans logNvramStage(), maintien du fil d'Ariane global gNvramTrail.
- Ajout dans init() de la lecture non volatile de qcom_stage / qcom_trail et sauvegarde vers qcom_last_crash / qcom_last_trail.
- Séquençage en 3 pauses visuelles balisées pour l'Étape 6.
* docs/ISSUES_AND_POSTMORTEMS.md : rédaction détaillée du Postmortem 18.
* EFI OpenCore : déploiement du binaire recompilé dans /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext et configuration boot-args qcom_step=6 qcom_substep=1 dans config.plist.
- Validation :
* Compilation sans aucun avertissement via ./build_wifi.sh.
* kmutil libraries -p build/Release/QualcommWifi.kext validé à 100% contre BootKernelExtensions.kc.
* Déploiement vérifié sur /Volumes/EFI/EFI/OC/.
- Breakthroughs & Rétro-ingénierie :
* Audit binaire exhaustif par désassemblage Capstone des 2,5 Mo du segment IO80211Family dans BootKernelExtensions.kc : identification de 38 slots de vtable invoqués.
* Découverte critique sur slot 400 (0xc80, getPrimarySkywalkInterface) appelé 99 fois dans IO80211Family : l'appelant déréférence directement ivars (mov rax, [rax + 0x120]) sans vérifier la nullité du pointeur. Si le contrôleur renvoie NULL, un Kernel Page Fault instantané survient (CR2: 0x120).
* Blindage proactif par surcharge explicite de getPrimarySkywalkInterface() retournant directement fSkywalkInterface.
* Sécurisation du slot 462 (0xe70, setMulticastList) par stub renvoyant kIOReturnSuccess pour immuniser contre toute requête multicast non gérée de la pile réseau BSD.
* Validation de la stratégie d'amorçage : maintien de l'isolation logicielle (qcom_mmio=0) pour valider la stabilité de Skywalk avant l'engagement du SoC physique WCN7850.
- Modifications apportées :
* QualcommWifi/QualcommWifi.hpp : déclaration des surcharges getPrimarySkywalkInterface() et setMulticastList().
* QualcommWifi/QualcommWifi.cpp : implémentation avec télémétrie NVRAM (cb_getPrimarySkywalk, cb_setMulticast).
* docs/ISSUES_AND_POSTMORTEMS.md : rédaction du Postmortem 17 détaillant l'audit binaire et les 38 slots de vtable.
* EFI OpenCore : déploiement de QualcommWifi.kext dans /Volumes/EFI/EFI/OC/Kexts/ et configuration des boot-args sur qcom_step=6 qcom_substep=1 dans config.plist.
- Validation :
* Compilation sans aucun avertissement via ./build_wifi.sh.
* kmutil libraries -p build/Release/QualcommWifi.kext validé à 100% contre BootKernelExtensions.kc.
* Déploiement vérifié sur /Volumes/EFI/EFI/OC/.
- Breakthroughs & Rétro-ingénierie :
* Rédaction détaillée du Postmortem 16 (analyse du panic lié à l'incompatibilité vtable IO80211WorkQueue / IOWorkLoop dans super::start()).
* Documentation du mécanisme de non-volatilité de la NVRAM SPI Flash UEFI et explication de l'impossibilité d'écriture sur fichier APFS en early-boot.
* Cartographie complète des appels internes de IO80211SkywalkInterface::start() vers CCPipe, CCStream, IO80211PeerManager et allocIO80211RecursiveLock().
- Modifications apportées :
* docs/ISSUES_AND_POSTMORTEMS.md : ajout de la section Postmortem 16.
* docs/NATIVE_WIFI.md : ajout de la section 6 décrivant les 7 paliers Skywalk (qcom_step) et la télémétrie NVRAM (qcom_stage).
- Déploiement :
* QualcommWifi.kext déployé dans /Volumes/EFI/EFI/OC/Kexts/.
* config.plist configuré avec QualcommWifi.kext Enabled=True et qcom_step=5.
- Breakthroughs & Rétro-ingénierie :
* Analyse de la cause racine de la bootloop observée même avec qcom_step=5 : l'alias createWorkLoop() vers createWorkQueue() retournait un IO80211WorkQueue* dans getWorkLoop(), provoquant un kernel panic immédiat dans IONetworkController::start(provider) par déréférencement de vtable invalide.
* Confirmation matérielle NVRAM : la variable UEFI 'qcom_stage' valait exactement 'createWorkQueue', prouvant que l'échec survenait à la première seconde de boot avant même d'arriver au Stade 1.
* Confirmation de la non-volatilité : le passage sous Linux n'efface absolument pas la NVRAM SPI Flash de la carte mère.
* Suppression de kprintf() qui pouvait engendrer des traps/spinlocks en early boot.
- Modifications apportées :
* QualcommWifi/QualcommWifi.cpp : réintégration de l'allocation dédiée fWorkLoop = IOWorkLoop::workLoop() et du getter getWorkLoop(), suppression de kprintf dans logNvramStage().
- Validation :
* Compilation sans erreur avec ./build_wifi.sh.
* Validation kmutil libraries réussie à 100% contre BootKernelExtensions.kc.
- Breakthrough & Root Cause Analysis:
* Persistent NVRAM analysis revealed 'qcom_stage=cb_getWorkQueue' was successfully written before the freeze.
* Disassembly of IO80211Controller::getWorkLoop() revealed that Apple's IO80211Controller directly
aliases getWorkLoop() to getWorkQueue() (jmp *(vptr + 0xc68)).
* QualcommWifi was previously maintaining a distinct fWorkLoop (IOWorkLoop) separate from fWorkQueue (IO80211WorkQueue),
causing cross-workloop lock inversions and deadlocks when Skywalk and CCPipe attempted to synchronize.
- Enhancements:
* Integrated native Darwin kprintf() in logNvramStage() to print diagnostic stages directly onto the
hardware video text console during early boot (bypassing delayed memory-only IOLog buffer).
* Unified getWorkLoop() and createWorkLoop() to use fWorkQueue directly as in Apple's driver.
* Added invocation counter to getWorkQueue() (cb_getWorkQueue_1, cb_getWorkQueue_2) to trace execution progression.
- Validation:
* Recompiled with ./build_wifi.sh.
* 100% verified against kmutil and BootKernelExtensions.kc.
- Reverse Engineering Breakthrough:
* Identified that IO80211PeerManager::initWithInterface() called by IO80211SkywalkInterface::createPeerManager()
invokes controller->allocIO80211RecursiveLock() at vtable slot 435 (vptr + 0xd88).
* Implemented a concrete override for allocIO80211RecursiveLock in QualcommWifi that delegates to super
and includes an emergency fallback to IORecursiveLockAlloc() if super returns NULL.
* Replaced in-memory IODTPlane options logging with real persistent NVRAM writes via PEWriteNVRAMProperty()
so the exact last executed checkpoint persists across reboot/bootloop cycles.
- Granular Sub-Step Tracing:
* Introduced 'qcom_substep' boot-arg:
- qcom_substep=1: 10-second observation pause BEFORE fSkywalkInterface->start(this).
- qcom_substep=2: 10-second observation pause AFTER fSkywalkInterface->start(this) succeeds.
* Instrumented all Skywalk/Controller callbacks (getWorkQueue, allocIO80211RecursiveLock, setPowerState,
getLogger, getFaultReporterFromDriver, handleCardSpecific, outputPacket, enable, disable).
* Hardened setPowerState against potential null dereferences in whatDevice->getName().
- Validation:
* Recompiled with ./build_wifi.sh.
* Verified 100% against kmutil libraries and BootKernelExtensions.kc.
- Breakthroughs & Rétro-ingénierie :
* Analyse désassemblée complète de IO80211SkywalkInterface::start (0xffffff80022f5792) dans BootKernelExtensions.kc.
* Découverte de l'appel interne à QualcommWifi->joinPMtree(fSkywalkInterface) (slot 244 de IOService, offset +0x7a0).
* Cause racine identifiée : QualcommWifi n'initialisait pas Power Management (PMinit non appelé), laissant son pointeur pm_vars à NULL. L'accès à pm_vars dans gIOPMrootDomain provoquait un Kernel Trap Page Fault immédiat.
* Détection d'un gestionnaire d'erreur destructeur dans start() qui appelait detachInterface(IONetworkInterface*) et provoquait des corruptions mémoire en cas d'échec transitoire.
- Modifications apportées :
* QualcommWifi/QualcommWifi.hpp : déclaration de la méthode virtuelle setPowerState override.
* QualcommWifi/QualcommWifi.cpp : initialisation complète du cycle Power Management (PMinit, joinPMtree, registerPowerDriver sur 2 états Off/On, changePowerStateToPriv), implémentation de setPowerState et PMstop().
* QualcommWifi/QualcommWifi.cpp : sécurisation des blocs d'erreur dans start() (suppression des detachInterface/release brutaux d'objets enregistrés dans l'IORegistry).
* docs/ISSUES_AND_POSTMORTEMS.md : consignation détaillée de l'incident INC-20.
- Validation :
* Compilation clang++ réussie sans erreur.
* Validation kmutil libraries à 100% contre BootKernelExtensions.kc.
* Kext déployé sur /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext.
* OpenCore armé avec boot-arg qcom_step=6 dans config.plist.
- Breakthroughs & Rétro-ingénierie :
* Validation éclatante en direct du Stade 5 (qcom_step=5) : boot 100% propre jusqu'au bureau.
* Confirmation formelle dans l'IORegistry : le nœud IO80211SkywalkInterface est désormais rattaché sous QualcommWifi (id 0x100000344).
* Vérification de la propriété IO80211InterfaceRole = Infrastructure sur le nœud enfant.
* Analyse de IO80211SkywalkInterface::start(IOService*) : vérification des appels à IOSkywalkEthernetInterface::start, récupération et liaison de IO80211WorkQueue, création de PeerManager, IO80211Glue et MacAddressAgent.
- Modifications apportées :
* /Volumes/EFI/EFI/OC/config.plist : mise à jour de boot-args vers qcom_step=6 pour démarrer le sous-système Skywalk (fSkywalkInterface->start(this)).
* docs/ISSUES_AND_POSTMORTEMS.md : documentation détaillée de la validation du Stade 5 et passage au Stade 6.
- Validation :
* boot-args qcom_step=6 vérifié dans config.plist.
* IORegistry vérifié en live avec ioreg -r -c IO80211SkywalkInterface.
- Breakthroughs & Rétro-ingénierie :
* Validation éclatante en direct du Stade 4 (qcom_step=4) : démarrage impeccable sans plantage.
* Exécution nominale de attachInterface(fSkywalkInterface, this) via slot 441 d'IO80211Controller.
* Confirmation IORegistry : publication immédiate de IOMACAddress (<00037f123456>), IOMaxPacketSize (1518), IOMinPacketSize (64) et IOPacketFilters par IONetworkController::prepare() et IOEthernetController::publishProperties().
* controller->ivars + 0x188 pointe désormais vers l'instance active d'IO80211SkywalkInterface.
- Modifications apportées :
* /Volumes/EFI/EFI/OC/config.plist : mise à jour de boot-args vers qcom_step=5 pour tester fSkywalkInterface->attach(this).
* docs/ISSUES_AND_POSTMORTEMS.md : consigner les résultats de l'étape 4 et l'armement de l'étape 5.
- Validation :
* Vérification live sous macOS de l'IORegistry et des boot-args.
- Breakthroughs & Rétro-ingénierie :
* Validation éclatante en direct du Stade 3 (qcom_step=3) : boot 100% propre jusqu'au bureau.
* QualcommWifi.kext et QualcommWireless.kext chargés simultanément.
* IO80211SkywalkInterface::setInterfaceRole(1) configuré avec succès ('IO80211InterfaceRole' = 'Infra') grâce à fPropertyTable allouée.
* Analyse du slot 441 de IO80211Controller (attachInterface) : valide le type IO80211SkywalkInterface, appelle IONetworkController::prepare() (slot 0x998), vérifie role == 1 et stocke l'interface dans controller->ivars + 0x188.
- Modifications apportées :
* /Volumes/EFI/EFI/OC/config.plist : passage de qcom_step=3 à qcom_step=4.
* docs/ISSUES_AND_POSTMORTEMS.md : documentation détaillée de la validation du Stade 3 et passage au Stade 4.
- Validation :
* boot-args qcom_step=4 vérifié dans config.plist.
* Kext synchronisé avec le même binaire éprouvé.
- Breakthroughs & Rétro-ingénierie :
* Validation éclatante du Stade 2 (qcom_step=2) : le système a démarré sans aucun panic/bootloop, QualcommWifi.kext et QualcommWireless.kext chargés simultanément avec leurs flux CoreCapture.
* Journal noyau (/usr/bin/log) confirmant l'exécution nominale :
'IO80211SkywalkInterface::init with controller start' -> 'init complete'.
* Désassemblage exhaustif de IO80211SkywalkInterface::init() à 0xffffff80022f568e :
invoque la chaîne complète d'héritage IOSkywalkEthernetInterface::init(nullptr) -> IOSkywalkNetworkInterface::init(nullptr) -> IOService::init(nullptr), allouant fPropertyTable, fRegistryTable, fLock, le verrou à l'offset +0x118, puis saute à initIvars().
* Analyse de IO80211SkywalkInterface::setInterfaceRole(UInt32 role) à 0xffffff80022f60f0 :
écrit le rôle dans ivars + 0x58 (1 = kIO80211InterfaceRoleInfra) et invoque SetProperties('IO80211InterfaceRole', 'Infra') qui requiert impérativement fPropertyTable allouée.
- Modifications apportées :
* QualcommWifi/QualcommWifi.cpp : déclaration et appel de _ZN23IO80211SkywalkInterface4initEv(mem) dans createSkywalkInterface() pour initialiser toute la chaîne IOService + IOSkywalk + lock + ivars.
* /Volumes/EFI/EFI/OC/config.plist : mise à jour de boot-args vers qcom_step=3.
* /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext : déploiement du binaire synchronisé (MD5: c0df0e4e993b1db0441840117bc2a6e4).
* docs/ISSUES_AND_POSTMORTEMS.md : documentation complète de INC-19.
- Validation :
* ./build_wifi.sh réussi avec validation kmutil à 100% contre BootKernelExtensions.kc.
* MD5 build et EFI strictement identiques.
### Breakthroughs & Rétro-ingénierie (Kernel Collection & INC-18)
- Analyse binaire approfondie de IO80211SkywalkInterface::free() (0xffffff80022f6184) :
La méthode libère aveuglément [rdi + 0x120] via 'mov rax, [rdi+0x120]; mov rdi, [rax+0xb8]'
sans tester si [rdi + 0x120] est NULL. Tout appel à release()/free() alors que 0x120 est NULL
déclenche un Kernel Page Fault (#PF) instantané sur CR2: 0x00000000000000b8.
- Lors du commit 0519af4, le retrait de initIvars() dans createSkywalkInterface() a laissé
mem + 0x120 à NULL, exposant l'objet à ce piège fatal dès qu'une erreur ou libération survenait.
- Le stade 1 (commit b7e32db) avait démarré jusqu'au bureau avec un succès total précisément parce
que initIvars y était appelé dès l'allocation, immunisant l'objet contre tout crash.
- De plus, l'absence de l'argument 'qcom_step' dans les boot-args OpenCore empêchait l'utilisateur
de forcer le stade 1 depuis la NVRAM ou le boot picker.
### Modifications apportées
- QualcommWifi/QualcommWifi.cpp :
* Restauration de l'appel _ZN23IO80211SkywalkInterface9initIvarsEv(mem) dans createSkywalkInterface.
* Réduction du palier Skywalk par défaut à skywalk_step = 1 (stade stable validé).
- /Volumes/EFI/EFI/OC/config.plist :
* Ajout explicite de qcom_step=1 dans NVRAM 7C436110-AB2A-4BBB-A880-FE41995C9F82 -> boot-args.
* Maintien de QualcommWifi.kext à Enabled: True.
- /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext :
* Déploiement du nouveau binaire compilé (MD5: 388636543393e9cf34e5816e4a011cce).
- docs/ISSUES_AND_POSTMORTEMS.md :
* Documentation exhaustive du post-mortem INC-18.
### Validation
- Compilation 'build_wifi.sh' validée à 100%.
- Contrôle de cohérence kext 'kmutil libraries' validé sans erreur contre BootKernelExtensions.kc.
- Synchronisation et copie EFI effectuées avec intégrité MD5 vérifiée.
- Breakthroughs & Rétro-ingénierie :
* Découverte critique dans IO80211SkywalkInterface::init (0xffffff80022f56e2) :
L'instruction cmpq $0x0, 0x120(%r14) suivie de jne 0x5733 saute l'appel super::init(0)
(IOService::init) si ivars est déjà non-nul.
* L'appel prématuré à initIvars dans createSkywalkInterface laissait donc la classe de base
IOService non initialisée (fPropertyTable = NULL).
* Lors de setInterfaceRole(1), setPropertyHelper appelait setProperty sur une table nulle,
provoquant le bootloop observé au stade 5.
- Modifications apportées :
* QualcommWifi/QualcommWifi.cpp :
- Retrait de l'appel à initIvars dans createSkywalkInterface pour laisser 0x120 à NULL
et garantir l'exécution de super::init(0) par IO80211SkywalkInterface::init.
- Calibrage du palier par défaut skywalk_step à 2 pour isoler la validation de init().
* docs/ISSUES_AND_POSTMORTEMS.md : Ajout du rapport post-mortem complet INC-17.
- Validation :
* Compilation build_wifi.sh réussie à 100%.
* kmutil libraries validé sans erreur contre BootKernelExtensions.kc.
- Breakthroughs & Rétro-ingénierie :
* Découverte critique dans IO80211SkywalkInterface::free() (0xffffff80022f6184) :
La première instruction déréférence ivars + 0xb8 (movq 0x120(%rdi), %rax ; movq 0xb8(%rax), %rdi).
Si l'interface est allouée (operator new + C1) sans que initIvars ne soit exécuté, 0x120 est NULL,
provoquant un Page Fault instantané sur CR2: 0x00000000000000b8 lors de tout release() / stop().
* Dans le commit 506df09, skywalk_step était à 6 par défaut (exécutant d'un coup CCPipe, PM,
IO80211PeerManager, WCLGlue et IO80211MacAddressAgent), ce qui causait le bootloop sans isolation.
* Découverte dans IO80211SkywalkInterface::stop (0xffffff80022f885c) :
Déréférence ivars + 0x80 (movq 0x80(%rax), %rdi). Appeler stop() sans que start() n'ait réussi
déclenche un crash en cascade.
- Modifications apportées :
* QualcommWifi/QualcommWifi.hpp : Ajout des drapeaux d'état de cycle de vie fSkywalkCtrlAttached,
fSkywalkAttached et fSkywalkStarted.
* QualcommWifi/QualcommWifi.cpp :
- Déclaration et appel de _ZN23IO80211SkywalkInterface9initIvarsEv dès createSkywalkInterface pour
garantir la présence immédiate de la structure ivars et immuniser l'objet contre le crash de free().
- Réduction sécurisée du palier par défaut skywalk_step à 1 pour isoler la création de l'objet.
- Protection conditionnelle de l'arrêt dans QualcommWifi::stop() via les drapeaux d'état.
* docs/ISSUES_AND_POSTMORTEMS.md : Documentation détaillée de INC-16.
- Validation :
* Compilation build_wifi.sh réussie à 100%.
* Validation des bibliothèques et symboles avec kmutil libraries réussie sans avertissement.
### Breakthroughs & Rétro-ingénierie
- **Piège du tas non initialisé (Uninitialized Heap Trap) dans initIvars (0xffffff80022f520c)** :
- IO80211SkywalkInterfacenwEm(0x128) alloue la mémoire de l'objet via kalloc_type, sans initialisation à zéro.
- Dans initIvars, le noyau teste si [rdi + 0x120] est nul. En présence de résidus du tas non nuls, le noyau dérive vers le bloc movq 0x120(%rbx), %rdi; callq memset(garbage, 0, 0xf0), déclenchant un Kernel Page Fault (#PF) / Triple Fault instantané.
- Résolution : bzero(mem, 0x128); systématique avant invocation du constructeur.
- **Header erroné network/IOSkywalkEthernetInterface.h** :
- Correction de l'héritage fictif d'IOEthernetController vers la hiérarchie Skywalk conforme : IOService -> IOSkywalkInterface -> IOSkywalkNetworkInterface -> IOSkywalkEthernetInterface.
- **Ordre d'attachement Skywalk & contrôleur (Slot 441)** :
- Broadcom (AppleBCMWLANCore::createSkywalkInterface) appelle attachInterface(fSkywalkInterface, this) au slot 441 avant fSkywalkInterface->attach(this) et start(this), avec this en second paramètre pour renseigner controller->ivars + 0x188 (fPrimaryInterface).
- **Suppression de registerService() prématuré** :
- Gated derrière qcom_step >= 7 (défaut: 6 = exécution complète de start(this) sans enregistrement prématuré déclenchant le matching IOKit sans buffers).
### Modifications apportées
- QualcommWifi/QualcommWifi.cpp :
- Ajout de bzero(mem, 0x128) après l'allocation de IO80211SkywalkInterface.
- Réordonnancement de l'attachement : appel de slot 441 attachInterface(fSkywalkInterface, this) avant attach(this) et start(this).
- Contrôle d'exécution granulaire par palier via le boot-arg qcom_step (défaut: 6).
- QualcommWireless/include/IOKit/network/IOSkywalkEthernetInterface.h :
- Redirection propre vers <IOKit/skywalk/IOSkywalkEthernetInterface.h>.
- QualcommWireless/include/IOKit/skywalk/IOSkywalkTypes.h :
- Ajout du typedef manquant uint32_t kern_packet_svc_class_t.
- docs/ISSUES_AND_POSTMORTEMS.md :
- Documentation exhaustive du post-mortem INC-15.
### Validation
- Compilation réussie via ./build_wifi.sh.
- Validation des bibliothèques et symboles kmutil libraries -p réussie à 100% contre BootKernelExtensions.kc.
### Breakthroughs & Rétro-ingénierie :
- Diagnostic de la cause racine du bootloop / crash kernel immédiat survenu lors de l'activation de qcom_skywalk=1 (commit e4c7d59).
- Rétro-ingénierie binaire approfondie de BootKernelExtensions.kc (macOS Tahoe 26.x / Darwin 25) sur la classe IO80211SkywalkInterface :
* Découverte critique : IO80211SkywalkInterface::init(IOService*, ether_addr*) (0xffffff80022f56e2) et IO80211SkywalkInterface::setInterfaceRole(UInt32) (0xffffff80022f60f0) sont des méthodes NON-VIRTUELLES.
* Déclarées virtual dans IO80211SkywalkInterface.h, Clang leur a alloué deux slots virtuels à la fin de la vtable IOSkywalkEthernetInterface aux offsets +0xc50 et +0xc58.
* Dans la table virtuelle native Apple à 461 slots (0xe68 octets), le slot +0xc58 correspond à IO80211SkywalkInterface::printDataPath(userPrintCtx*).
* L'instruction fSkywalkInterface->setInterfaceRole(1) a émis callq *0xc58(%rax), sautant dans printDataPath avec %rsi = 0x1. Le déréférencement de ce pointeur a déclenché un Page Fault kernel sur CR2: 0x0000000000000001 et provoqué un CPU triple fault instantané.
### Modifications apportées :
- QualcommWireless/include/IOKit/80211/IO80211SkywalkInterface.h :
* Suppression du mot-clé virtual devant bool init(IOService *controller, ether_addr *mac) et void setInterfaceRole(UInt32 role).
* Clang génère désormais des appels directs callq __ZN23IO80211SkywalkInterface4init... et callq __ZN23IO80211SkywalkInterface16setInterfaceRoleEj.
- docs/ISSUES_AND_POSTMORTEMS.md :
* Ajout du post-mortem technique détaillé INC-14 (analyse de désassemblage, collision de vtable, résolution).
- docs/RESEARCH_AND_REVERSE_ENGINEERING.md :
* Ajout de la section 4.1 décrivant la topologie de la vtable (461 slots) de IO80211SkywalkInterface, les méthodes non-virtuelles, et les slots d'attachement 441 (attachInterface) et 442 (detachInterface).
### Validation :
- Compilation C++ / ASM / Linker réussie sans avertissement via build_wifi.sh.
- Validation binaire kmutil libraries -p build/Release/QualcommWifi.kext validée à 100% contre BootKernelExtensions.kc.
- Désassemblage de build/Release/QualcommWifi.kext confirmant l'éradication des appels indirects vers 0xc50/0xc58 au profit des appels directs aux symboles globaux du noyau.
### Breakthroughs & Rétro-ingénierie
- **Rétro-ingénierie ABI Skywalk Tahoe (`BootKernelExtensions.kc`)** :
- Analyse désassemblée via Capstone de `IO80211Controller::attachInterface` (`0xffffff8002295fce`, slot 441) :
- Le premier argument `rsi` doit être l'instance `IO80211SkywalkInterface`.
- La fonction effectue `OSDynamicCast(IO80211SkywalkInterface, iface)`.
- Vérification du rôle d'interface : `cmp dword ptr [rcx + 0x58], 1`. Si égal à 1 (Infra / Primary Wi-Fi), le pointeur est assigné à `ivars + 0x188` (`primaryInterface`).
- Analyse de `IO80211SkywalkInterface::setInterfaceRole(unsigned int role)` (`0xffffff80022f60f0`) :
- Écrit la valeur du rôle dans `ivars + 0x58` (`mov dword ptr [rax + 0x58], esi`), satisfaisant la condition de slot 441.
- Analyse du cycle de vie de `IO80211SkywalkInterface` :
- La classe ne possède aucun slot virtuel pur (`___cxa_pure_virtual` = 0).
- Taille d'instance exacte : `0x128` (296 octets), ivars privées `0xf0` octets allouées par `initIvars()`.
- L'initialisation via `init(controller, mac)` copie l'adresse MAC physique dans `ivars + 0xe4`.
- `start(controller)` crée l'interface BSD (`en1`/`en2`), initialise `CCPipe` CoreCapture, lie le `getWorkQueue()` du contrôleur, invoque `controller->open(iface)` et instancie l'agent `IO80211MacAddressAgent`.
### Modifications apportées
- `QualcommWireless/include/IOKit/80211/IO80211SkywalkInterface.h` :
- Déclaration de l'héritage `public IOSkywalkEthernetInterface`.
- Déclaration des signatures de méthodes : `init(controller, mac)`, `setInterfaceRole(role)`, `start(controller)`, `stop(controller)`, `free()`.
- `QualcommWifi/QualcommWifi.hpp` :
- Ajout du membre `IO80211SkywalkInterface *fSkywalkInterface`.
- `QualcommWifi/QualcommWifi.cpp` :
- Déclaration des symboles externes exportés par `BootKernelExtensions.kc` (`_ZN23IO80211SkywalkInterfacenwEm`, `_ZN23IO80211SkywalkInterfaceC1EPK11OSMetaClass`, `_ZN23IO80211SkywalkInterface10gMetaClassE`).
- Fonction helper `createSkywalkInterface()` allouant l'instance avec la metaclass native.
- Dans `QualcommWifi::start()` :
- Contrôle via boot-arg `qcom_skywalk=1`.
- Instanciation de l'interface Skywalk via `createSkywalkInterface()`.
- Initialisation avec MAC physique (`fMacAddress`) et assignation du rôle 1 (`setInterfaceRole(1)`).
- Attachement IOKit (`attach(this)`), démarrage Skywalk (`start(this)`).
- Enregistrement auprès du contrôleur (`attachInterface(fSkywalkInterface, nullptr)`).
- Publication du service IOKit (`skywalk->registerService()`) pour notifier `airportd`.
- Dans `QualcommWifi::stop()` : détachement propre (`detachInterface(fSkywalkInterface, false)`), `stop()`, `detach()` et libération.
### Validation
- Compilation réussie sans warning : `clang++ -target x86_64-apple-macos26.5`.
- Validation d'édition de liens et kext dependencies : `kmutil libraries -p build/Release/QualcommWifi.kext` à 100%.
- Déploiement automatique dans `/Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext`.
- Mise à jour de `/Volumes/EFI/EFI/OC/config.plist` avec `qcom_skywalk=1` (validé par `plutil -lint`).
### Breakthroughs & Rétro-ingénierie
- Configuration PCIe conforme IOKit : utilisation des API officielles IOPCIDevice::setMemoryEnable(true) et setBusMasterEnable(true) avant le mappage de kIOPCIConfigBaseAddress0.
- Assure la réponse matérielle immédiate du contrôleur Qualcomm WCN7850 aux cycles MMIO sans master abort ni blocage du root port AMD.
### Modifications apportées
- QualcommWifi/QualcommWifi.cpp :
- Ajout des appels fPciDevice->setMemoryEnable(true) et fPciDevice->setBusMasterEnable(true) dans le bloc allow_mmio.
- Ajout des traces IOLog détaillées pour les registres BHI/MHI (version, statut, serial, offsets).
### Validation
- Compilation réussie via ./build_wifi.sh.
- Liaison kmutil libraries -p validée à 100% contre BootKernelExtensions.kc.
### Breakthroughs & Rétro-ingénierie
- **Démystification de l'asymétrie Verbose vs Non-Verbose** :
- Non-verbose : `debug=0x100` fige l'exécution lors d'un Kernel Panic (logo Apple statique).
- Verbose (`-v`) : le noyau tente d'afficher la panique console sur le framebuffer NVIDIA (`nvfb=1 nvaccel=1`), provoquant un conflit matériel GPU précoce et un Triple Fault CPU ("coupure de courant").
- La cause racine est une et indivisible : un Ring 0 Page Fault dans `IO80211Controller::start`.
- **Analyse binaire de CCLogStream (283 slots, 0x8d8 octets)** :
- `CCLogStream` hérite de `CCStream` qui hérite de `IOService` (slots 0..265).
- `CCLogStream` ajoute 14 méthodes virtuelles (slots 266..279) : `setLevel` (0x868), `setFlags` (0x878), `setConsoleLogFlag` (0x8b0), etc.
- `FakeLogStream` n'héritait que de `OSObject` (38 slots). Tout appel kernel au-delà du slot 38 (ex: `setLevel` à 0x868 ou `IOService::attach` à 0x1c0) exécutait de la mémoire hors-limite arbitraire.
- **Analyse binaire de CCLogStream::logv (0xffffff80032fd7d4)** :
- Lors de la suppression d'un log sous le seuil configuré (`cmpl (%rax), %r14d; jg 0x8fb`), `logv` tente d'incrémenter le compteur de messages supprimés via `movq 0x88(%rbx), %rax; movq 0x48(%rax), %rdi; callq IOSimpleReporter::incrementValue`.
- `0x88(%rbx)` (`streamData`) était nul, déréférençant l'adresse 0x48 (Page 0 Ring 0 #PF).
### Modifications apportées
- `QualcommWifi/QualcommWifi.cpp` :
- `FakeFaultReporter` : hérite désormais de `IOService` avec padding `0x90 - sizeof(IOService)` (vtable de 269 slots, taille 0x90).
- `FakeLogStream` : hérite désormais de `IOService` avec les 14 méthodes virtuelles `CCLogStream` (vtable de 283 slots, 0x8d8 octets).
- `streamData` (+0x88) : pointe sur `gStreamMem`, dont +0x48 pointe sur `gDummyReporter` avec `gDummyReporterVtable` interceptant le slot 45 (`getFirstElementIndex`) via un stub sûr `dummyReporterFunc`.
- `p1` (+0x90) : pointe sur `gP1Mem`, dont +0x58 pointe sur `gP2Mem` (taille d'instance conforme de 0x98 octets).
- `docs/ISSUES_AND_POSTMORTEMS.md` :
- Rédaction complète du post-mortem INC-12 détaillant les offsets, instructions désassemblées et résolutions.
### Validation
- Compilation réussie avec `clang++` sans avertissements.
- Vérification binaire : `__ZTV13FakeLogStream` mesure exactement 0x8d8 octets (283 slots), `__ZTV17FakeFaultReporter` mesure 0x868 octets (269 slots).
- Validation `kmutil libraries` : 100% de résolution des symboles contre `BootKernelExtensions.kc`.
- Déploiement : copié sur `/Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext` et activé dans `config.plist`.
- Breakthroughs & Rétro-ingénierie :
* Analyse de la divergence verbose / non-verbose : sous debug=0x100, une panique en mode non-verbose fige l'affichage sur le logo Apple (suppression de l'écran graphique). En mode -v, l'écriture vidéo de display_panic interfère avec le framebuffer NVIDIA RTX 4070 SUPER et déclenche un CPU Triple Fault. La cause première est donc un panic ou déréférencement survenant au même point dans les deux cas.
* Durcissement de FakeLogStream : les allocations dynamiques IOMallocZero lors de l'init précoce pouvaient échouer en Ring 0 avant que le heap ne soit stabilisé, menant à un déréférencement nul dans CCLogStream::shouldLog (offset +0x90 -> +0x58). Remplacé par des tampons statiques BSS (gP1Mem/gP2Mem) alloués et mappés dès le chargement du Mach-O.
* Identification de l'anti-patron IOKit registerService() sur le contrôleur : IO80211Controller ne publie pas de médium Ethernet et ne doit jamais appeler registerService() sur lui-même (c'est l'interface Skywalk fille qui s'enregistre). L'appel prématuré déclenchait airportd avant l'attachement d'interface.
* Implémentation de la persistance réelle NVRAM dans logNvramStage via /options (AppleEFINVRAM) pour tracer avec exactitude chaque étape franchie (qcom_stage).
- Modifications apportées :
* QualcommWifi/QualcommWifi.cpp : utilisation de buffers statiques BSS pour FakeLogStream, suppression de publishMediumDictionary, contrôle de registerService() via boot-arg qcom_register (désactivé par défaut), persistance matérielle NVRAM dans logNvramStage.
* docs/ISSUES_AND_POSTMORTEMS.md : ajout du post-mortem INC-11 détaillé et mise à jour de la table d'incidents.
- Validation :
* Compilation propre avec Clang (C++17, fno-rtti, fno-exceptions).
* Validation kmutil libraries 100% sans symbole irrésolu contre BootKernelExtensions.kc.
* Déploiement dans /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext et réactivation (Enabled: true) dans config.plist.
2026-10-18 00:29:28 +02:00
9 changed files with 2817 additions and 93 deletions
@@ -124,3 +124,69 @@ La puce WCN7850 introduit les caractéristiques Wi-Fi 7 suivantes, intégrées d
- **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.
- **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.
- **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 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 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`.
> Dès que l'initialisation de `QualcommWifi::start()` est achevée (`start_done`), le drapeau statique `sNvramLoggingActive` est **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'`airportd` et du `ControlCenter` (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 :
```mermaid
sequenceDiagram
participant CC as ControlCenter / airportd
participant Kext as QualcommWifi (IO80211Controller)
- `asr_ssid` & `asr_bssid` : nom du point d'accès et adresse MAC du BSS.
- `asr_rates` : débits supportés.
- **Support Dual-ABI** : `QualcommWifi` copie directement le résultat via `memcpy(req_data, &sResultBuf, sizeof(sResultBuf))` tout en supportant les versions de démons passant un double pointeur (`*(apple80211_scan_result**)req_data = &sResultBuf`).
- `init(IOService *controller, ether_addr *mac)` (`0xffffff80022f56e2`) : **NON-VIRTUELLE**. Initialise les ivars internes (`this->ivars + 0x120`), alloue la structure de contrôle et copie l'adresse MAC (6 octets) dans `ivars + 0xe4` / `+0xe8`.
-`setInterfaceRole(UInt32 role)` (`0xffffff80022f60f0`) : **NON-VIRTUELLE**. Configure le rôle réseau dans `this->ivars + 0x58` (`role = 1` pour `kIO80211InterfaceRoleInfra`).
3.**Attachement au Contrôleur (`IO80211Controller`)** :
Détache l'interface et réinitialise `controller->ivars + 0x188 = NULL`.
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.