From 5efd0dfbae3fe1f39fdfebe7e846b4c7e5e49213 Mon Sep 17 00:00:00 2001 From: Erwan Date: Mon, 19 Oct 2026 18:35:13 +0200 Subject: [PATCH] =?UTF-8?q?feat(wifi):=20publier=20les=20m=C3=A9diums=20r?= =?UTF-8?q?=C3=A9seau=20IEEE80211/Ethernet=20et=20activer=20la=20radio=20p?= =?UTF-8?q?ar=20d=C3=A9faut=20(=C3=89tape=209)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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). --- QualcommWifi/QualcommWifi.cpp | 66 +++++++++++++++++++++++++++++++++- QualcommWifi/QualcommWifi.hpp | 4 +++ docs/ISSUES_AND_POSTMORTEMS.md | 52 +++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) diff --git a/QualcommWifi/QualcommWifi.cpp b/QualcommWifi/QualcommWifi.cpp index 0c12efb..3ecef4b 100644 --- a/QualcommWifi/QualcommWifi.cpp +++ b/QualcommWifi/QualcommWifi.cpp @@ -319,7 +319,7 @@ bool QualcommWifi::init(OSDictionary *dictionary) { fMacAddress.bytes[3] = 0x11; fMacAddress.bytes[4] = 0x07; fMacAddress.bytes[5] = 0x01; - fLinkActive = false; + fLinkActive = true; fCurrentChannel = 1; fLastRssi = -50; fSsidLen = 0; @@ -1071,6 +1071,10 @@ bool QualcommWifi::start(IOService *provider) { IOLog("QualcommWifi: Publication du contrôleur contournée (qcom_step < 7 et qcom_register=0).\n"); } + // Initialisation et publication de la table des médiums (requis pour SIOCGIFMEDIA / Apple80211GetIfListCopy) + logNvramStage("s8_medium_init"); + createMediumTables(); + if (skywalk_step >= 8) { int substep8 = 0; PE_parse_boot_argn("qcom_substep", &substep8, sizeof(substep8)); @@ -1333,6 +1337,66 @@ IOReturn QualcommWifi::disable(IONetworkInterface *netif) { return kIOReturnSuccess; } +bool QualcommWifi::createMediumTables(void) { + IOLog("QualcommWifi: Creation et publication du dictionnaire de mediums reseau...\n"); + OSDictionary *mediumDict = OSDictionary::withCapacity(2); + if (!mediumDict) { + IOLog("QualcommWifi: ERREUR allocation mediumDict !\n"); + return false; + } + + IONetworkMedium *mediumWifi = IONetworkMedium::medium( + kIOMediumIEEE80211Auto, + 1000000000ULL, // 1 Gbps + 0, + 0, + "Auto" + ); + IONetworkMedium *mediumEth = IONetworkMedium::medium( + kIOMediumEthernetAuto, + 1000000000ULL, + 0, + 1, + "EthernetAuto" + ); + + if (mediumWifi) { + IONetworkMedium::addMedium(mediumDict, mediumWifi); + mediumWifi->release(); + } + if (mediumEth) { + IONetworkMedium::addMedium(mediumDict, mediumEth); + mediumEth->release(); + } + + bool published = publishMediumDictionary(mediumDict); + if (published) { + const IONetworkMedium *selected = IONetworkMedium::getMediumWithType(mediumDict, kIOMediumIEEE80211Auto); + if (!selected) { + selected = IONetworkMedium::getMediumWithType(mediumDict, kIOMediumEthernetAuto); + } + if (selected) { + setSelectedMedium(selected); + setCurrentMedium(selected); + setLinkStatus(kIONetworkLinkValid | kIONetworkLinkActive, selected, 1000000000ULL, nullptr); + IOLog("QualcommWifi: Medium selectionne et linkStatus(Active) configure avec succes !\n"); + } + } else { + IOLog("QualcommWifi: ERREUR publishMediumDictionary !\n"); + } + + mediumDict->release(); + return published; +} + +IOReturn QualcommWifi::selectMedium(const IONetworkMedium *medium) { + if (!medium) return kIOReturnBadArgument; + setSelectedMedium(medium); + setCurrentMedium(medium); + setLinkStatus(kIONetworkLinkValid | kIONetworkLinkActive, medium); + return kIOReturnSuccess; +} + UInt32 QualcommWifi::outputPacket(mbuf_t m, void *param) { logNvramStage("cb_outputPacket"); if (m) { diff --git a/QualcommWifi/QualcommWifi.hpp b/QualcommWifi/QualcommWifi.hpp index 3dffe10..496ff81 100644 --- a/QualcommWifi/QualcommWifi.hpp +++ b/QualcommWifi/QualcommWifi.hpp @@ -282,6 +282,10 @@ public: // Dispatcher de requêtes Apple80211 / airportd SInt32 handleApple80211Request(unsigned int req_type, int req_val, void* req_data); + + // Gestion des Médiums Réseau (IONetworkController / SIOCGIFMEDIA) + virtual IOReturn selectMedium(const IONetworkMedium *medium) override; + bool createMediumTables(void); }; #endif diff --git a/docs/ISSUES_AND_POSTMORTEMS.md b/docs/ISSUES_AND_POSTMORTEMS.md index 9f68efd..14aeac7 100644 --- a/docs/ISSUES_AND_POSTMORTEMS.md +++ b/docs/ISSUES_AND_POSTMORTEMS.md @@ -1008,3 +1008,55 @@ Ce document répertorie de manière exhaustive l'ensemble des anomalies, blocage - Kext déployé sur l'EFI (`/Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext`). - Configuration OpenCore activée : `qcom_step=8 qcom_substep=5`. +--- + +### Postmortem 25 : Résolution de l'Erreur SIOCGIFMEDIA (`EIO`), Rétro-ingénierie d'`Apple80211GetIfListCopy` et Publication des Médiums Réseau (Étape 9) + +* **Date** : 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 & Retours Utilisateur (/grill-me)** : + - Démarrage sans freeze ni crash validé à 100% avec l'Étape 8. + - L'interface BSD `en1` existe dans `ifconfig` et est reconnue par `networksetup -listallhardwareports` comme `Hardware Port: Wi-Fi`. + - Cependant, l'icône Wi-Fi ne s'affiche pas encore dans la barre des menus macOS, et `networksetup -getairportpower en1` affiche `Wi-Fi Power (en1): Off (forced)`. + - La commande `ifconfig en1` renvoie : `ifconfig: SIOCGIFXMEDIA: Input/output error`. +* **Breakthroughs & Rétro-ingénierie Binaire Exhaustive (`Apple80211.framework` & `BootKernelExtensions.kc`)** : + 1. **Dissection de `Apple80211GetIfListCopy` et `_getIfListCopy` sous LLDB** : + - `airportd` appelle `Apple80211GetIfListCopy` pour dresser la liste des interfaces Wi-Fi. + - Dans `_getIfListCopy` (`0x7ffc235a38fb`), après avoir énuméré les interfaces via `getifaddrs()`, il exécute systématiquement : + ```assembly + 0x7ffc235a3ba4: callq ioctl ; ioctl(fd, 0xc02c6938 / SIOCGIFMEDIA, &ifmr) + 0x7ffc235a3ba9: movl %eax, %r13d + ... + 0x7ffc235a3cc3: testl %r13d, %r13d + 0x7ffc235a3cc6: je 0x7ffc235a4002 ; Si succès (0) -> ajoute l'interface à la liste ! + 0x7ffc235a3cde: jne 0x7ffc235a4091 ; Si échec (EIO) -> IGNORE L'INTERFACE ! + ``` + - Si `SIOCGIFMEDIA` renvoie une erreur (autre que `ENOTSUP`), l'interface est purement et simplement éliminée du filtrage. `Apple80211GetIfListCopy` retourne alors `-3903` (`ifCount = 0`). + 2. **Dissection de `IO80211SkywalkInterface::getSupportedMediaArray` (`0xffffff80022f8e5e`)** : + - Lors du traitement noyau de `SIOCGIFMEDIA` par `IOSkywalkNetworkInterface::ioctl_gifmedia` (`0xffffff8002b0ae78`), le noyau invoque `getSupportedMediaArray`. + - Dans `IO80211SkywalkInterface::getSupportedMediaArray` : + ```assembly + 0xffffff80022f8e80: mov rax, qword ptr [rdi] ; rdi = controller (QualcommWifi) + 0xffffff80022f8e83: call qword ptr [rax + 0x890] ; Slot 0x890 = getMediumDictionary() + 0xffffff80022f8e89: test rax, rax + 0xffffff80022f8e8c: je 0xffffff80022f8f24 ; SI NULL -> ERREUR EIO ! + ``` + - Faute d'un dictionnaire de médiums publié, le noyau renvoie inconditionnellement `EIO`. + 3. **Vérification du Rôle de l'Interface (`_isInfraInterface`)** : + - Dès que `SIOCGIFMEDIA` réussit, `Apple80211GetIfListCopy` invoque `_isInfraInterface` (`0x7ffc235a48c9`). + - `_isInfraInterface` recherche le service correspondant via `{ "IOPropertyMatch" = { "IOInterfaceName" = "en1" } }` et vérifie `"IO80211InterfaceRole" == "Infrastructure"`, propriété déjà configurée avec succès sur notre `IO80211SkywalkInterface`. +* **Résolutions Techniques Appliquées dans `QualcommWifi`** : + 1. **Création et Publication de la Table des Médiums (`createMediumTables`)** : + - Instanciation d'un `OSDictionary` avec les médiums `kIOMediumIEEE80211Auto` et `kIOMediumEthernetAuto` (1 Gbps) via `IONetworkMedium::medium(...)`. + - Publication auprès du noyau via `publishMediumDictionary(mediumDict)`. + - Configuration du médium sélectionné et actif via `setSelectedMedium`, `setCurrentMedium` et `setLinkStatus(kIONetworkLinkValid | kIONetworkLinkActive)`. + 2. **Implémentation de `selectMedium(const IONetworkMedium *medium)`** : + - Prise en charge des requêtes de changement de média du sous-système réseau. + 3. **Activation de la Radio par Défaut (`fLinkActive = true`)** : + - Initialisation à `true` dès `QualcommWifi::init()`. + - Réponses immédiates `APPLE80211_S_RUN` à `APPLE80211_IOC_STATE` et `power_state[0] = 1` à `APPLE80211_IOC_POWER`. + 4. **Validation Binaire & Déploiement** : + - Compilation `Release` validée à 100% par `kmutil libraries`. + - Binaire déployé sur `/Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext` (MD5: `480ca02aff49c48afbe8b381be0c3c77`). + +