docs(wifi): documenter le postmortem 16, la persistance NVRAM et les 7 paliers d'amorçage

- 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.
This commit is contained in:
Erwan committed 2026-10-19 00:01:31 +02:00
1 parent 92ce7e7839
commit cc3fff7dc7
2 files changed
+72

No files matched your search

+51
View File
@@ -613,6 +613,57 @@ Ce document répertorie de manière exhaustive l'ensemble des anomalies, blocage
- Déploiement du nouveau kext sur `/Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext`.
- Configuration du boot-arg dans `/Volumes/EFI/EFI/OC/config.plist` : `qcom_step=6` prêt pour test en direct.
---
### Postmortem 16 : Diagnostic par Persistance NVRAM du Crash Early-Boot (Régression de l'Alias WorkLoop et Isolation Chirurgicale du Stade 6)
* **Date** : 18-19 Octobre 2026
* **Cible** : macOS Tahoe 26.x (Darwin 25.6.0 x86_64), AMD Ryzen 7 5800X3D, `QualcommWifi.kext` (WCN7850 `0x17cb:0x1107`)
* **Symptômes & Constats** :
- Après avoir testé le commit `e0414a9` avec `qcom_step=6` puis en revenant sur `qcom_step=5`, la machine est restée bloquée en bootloop immédiat dès les premières lignes du noyau XNU.
- La pause visuelle de 10 secondes prévue dans `qcom_substep=1` ne s'exécutait même plus.
- L'utilisateur a dû désactiver temporairement `QualcommWifi.kext` (`Enabled: false`) via Linux pour redémarrer sur le bureau macOS.
- Interrogation en direct de la mémoire NVRAM macOS (`nvram -p | grep qcom`) :
```text
qcom_stage createWorkQueue
boot-args ... qcom_step=5 qcom_substep=1
```
* **Causes Racines (Breakthroughs & Rétro-ingénierie du Noyau)** :
1. **Origine du Panic Instantané : Régression de l'Alias `createWorkLoop()`** :
- Dans le commit `e0414a9`, une tentative d'unification avait été faite pour que `createWorkLoop()` appelle `createWorkQueue()` et que `getWorkLoop()` retourne `(IOWorkLoop*)fWorkQueue`.
- Dans la hiérarchie IOKit, `IONetworkController::start(provider)` invoque `createWorkLoop()` puis `getWorkLoop()`, s'attendant impérativement à une instance allouée via `IOWorkLoop::workLoop()`.
- `IO80211WorkQueue` n'hérite pas de `IOWorkLoop` : leurs tables virtuelles (vtables) sont incompatibles.
- Dès le déréférencement de `fWorkLoop` dans `super::start(provider)` (ligne 706 de `QualcommWifi.cpp`), le noyau a subi un Kernel Panic immédiat avant même d'atteindre le Stade 1 ou le Stade 5, et avant le `IOSleep(10000)`.
- La variable NVRAM `qcom_stage` figée sur `createWorkQueue` a fourni la preuve irréfutable du lieu exact du crash.
2. **Confirmation du Comportement Matériel de la NVRAM UEFI** :
- La NVRAM UEFI réside physiquement dans la puce **SPI Flash** de la carte mère.
- Elle est totalement non-volatile : un reboot, une coupure de courant ou un démarrage sous Linux ne supprime **aucunement** les propriétés NVRAM.
- L'impossibilité d'écrire dans un fichier disque en early boot : au chargement des kexts de boot, les volumes APFS sont scellés cryptographiquement en lecture seule (snapshot système) et le VFS BSD n'est pas encore monté. `PEWriteNVRAMProperty` constitue ainsi l'unique canal de diagnostic persistant bas-niveau disponible.
3. **Cartographie Précise du Chemin d'Exécution entre `getWorkQueue()` et `allocIO80211RecursiveLock()` dans `IO80211SkywalkInterface::start()`** :
- Le désassemblage Capstone complet a révélé la séquence exacte exécutée par `IO80211SkywalkInterface::start(IOService *provider)` (`0xffffff80022f5792`) :
1. `0xffffff80022f5867`: `call [rax + 0xc68]` -> 1er appel à `QualcommWifi::getWorkQueue()`.
2. `0xffffff80022f5888`: `fWorkQueue->retain()`.
3. `0xffffff80022f59f4`: `call CCPipe::withOwnerNameCapacity` (CoreCapture data/log pipe).
4. `0xffffff80022f5a62`: `call IO80211Controller::io80211isDebuggable(bool*)`.
5. `0xffffff80022f5a8f`: `call CCStream::withPipeAndName`.
6. `0xffffff80022f5abc`: `call CCPipe::startPipe`.
7. `0xffffff80022f5bca`: `call IO80211SkywalkInterface::createPeerManager()` (`0xffffff80022f7be6`).
8. Dans `IO80211PeerManager::initWithInterface()` (`0xffffff8002246c88`) :
- `0xffffff8002246ed5`: `call [rax + 0xc68]` -> **2ème appel** à `QualcommWifi::getWorkQueue()`.
- `0xffffff8002246ee6`: `fWorkQueue->retain()`.
- `0xffffff8002246f04`: `call [rax + 0xd88]` -> `QualcommWifi::allocIO80211RecursiveLock()`.
* **Résolutions Techniques Appliquées** :
1. **Restauration de l'Allocation Dédiée `IOWorkLoop`** :
- Réintégration de `fWorkLoop = IOWorkLoop::workLoop()` dans `createWorkLoop()` et du retour de `fWorkLoop` dans `getWorkLoop()`.
2. **Suppression de `kprintf()`** :
- Élimination de `kprintf` de `logNvramStage()` pour prévenir tout blocage spinlock/MSR avant l'attachement de la console série.
3. **Traçage Numéroté Granulaire dans la NVRAM** :
- `getWorkQueue()` incrémente un compteur statique et enregistre `cb_getWorkQueue_1`, `cb_getWorkQueue_2` dans la NVRAM.
- `allocIO80211RecursiveLock()` enregistre `cb_allocLock` dans la NVRAM.
4. **Validation** :
- Compilation réussie sans avertissement (`./build_wifi.sh`), validation `kmutil libraries` à 100% contre `BootKernelExtensions.kc`.
+21
View File
@@ -124,3 +124,24 @@ 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.
- **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É** (Visibilité confirmée dans IORegistry) |
| **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 | **EN COURS** (Traçage fin via `cb_getWorkQueue_1/2` et `cb_allocLock`) |
| **Stade 7** | `fSkywalkInterface->registerService()` | Publication globale du service réseau pour `airportd` et l'interface utilisateur macOS | En attente de validation du Stade 6 |
### 6.1. Télémétrie et Persistance NVRAM (`qcom_stage`)
En phase précoce d'amorçage (*early boot*), le snapshot racine APFS est scellé cryptographiquement et monté en lecture seule stricte, rendant toute écriture sur fichier disque impossible. Le pilote exploite donc l'API `PEWriteNVRAMProperty` pour inscrire chaque jalon de progression directement dans la puce **SPI Flash UEFI** de la carte mère sous la variable `qcom_stage`.
Cette variable survit aux plantages matériels, aux redémarrages forcés ainsi qu'aux sessions Linux.