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`). + +