feat(wifi): publier les médiums réseau IEEE80211/Ethernet et activer la radio par défaut (Étape 9)
- 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).
This commit is contained in:
1 parent
29af992874
commit
5efd0dfbae
3 files changed
+121
-1
No files matched your search
@@ -319,7 +319,7 @@ bool QualcommWifi::init(OSDictionary *dictionary) {
|
|||||||
fMacAddress.bytes[3] = 0x11;
|
fMacAddress.bytes[3] = 0x11;
|
||||||
fMacAddress.bytes[4] = 0x07;
|
fMacAddress.bytes[4] = 0x07;
|
||||||
fMacAddress.bytes[5] = 0x01;
|
fMacAddress.bytes[5] = 0x01;
|
||||||
fLinkActive = false;
|
fLinkActive = true;
|
||||||
fCurrentChannel = 1;
|
fCurrentChannel = 1;
|
||||||
fLastRssi = -50;
|
fLastRssi = -50;
|
||||||
fSsidLen = 0;
|
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");
|
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) {
|
if (skywalk_step >= 8) {
|
||||||
int substep8 = 0;
|
int substep8 = 0;
|
||||||
PE_parse_boot_argn("qcom_substep", &substep8, sizeof(substep8));
|
PE_parse_boot_argn("qcom_substep", &substep8, sizeof(substep8));
|
||||||
@@ -1333,6 +1337,66 @@ IOReturn QualcommWifi::disable(IONetworkInterface *netif) {
|
|||||||
return kIOReturnSuccess;
|
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) {
|
UInt32 QualcommWifi::outputPacket(mbuf_t m, void *param) {
|
||||||
logNvramStage("cb_outputPacket");
|
logNvramStage("cb_outputPacket");
|
||||||
if (m) {
|
if (m) {
|
||||||
|
|||||||
@@ -282,6 +282,10 @@ public:
|
|||||||
|
|
||||||
// Dispatcher de requêtes Apple80211 / airportd
|
// Dispatcher de requêtes Apple80211 / airportd
|
||||||
SInt32 handleApple80211Request(unsigned int req_type, int req_val, void* req_data);
|
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
|
#endif
|
||||||
@@ -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`).
|
- Kext déployé sur l'EFI (`/Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext`).
|
||||||
- Configuration OpenCore activée : `qcom_step=8 qcom_substep=5`.
|
- 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`).
|
||||||
|
|
||||||
|
|
||||||
Reference in new issue
Block a user