- Breakthroughs & Rétro-ingénierie :
* Analyse binaire approfondie de BootKernelExtensions.kc (__ZN17IO80211Controller5startEP9IOService @ 0xffffff8002291f30 et __ZN19IONetworkController5startEP9IOService @ 0xffffff80026f34dc).
* Découverte de la cause racine exacte du message 'IO80211Controller::start fails' :
1. Dans IO80211Controller sur macOS Tahoe / Darwin 25 (architecture Skywalk), la méthode virtuelle createWorkLoop() (slot 306) ne crée plus un IOWorkLoop classique, mais effectue un saut indirect vers le slot 395 (createWorkQueue()).
2. De même, getWorkLoop() (slot 209) effectue un saut indirect vers le slot 397 (getWorkQueue()).
3. Dans la classe de base abstraite IO80211Controller, les implémentations par défaut de createWorkQueue() (0xffffff8002295e20) et getWorkQueue() (0xffffff8002295e28) retournent simplement 0 (NULL/false).
4. Lors de l'appel super::start(provider), IONetworkController::start invoque this->createWorkLoop(), qui appelle createWorkQueue() et échoue immédiatement car celle-ci retournait false, provoquant l'avortement de start() et la libération (free) de QualcommWifi.
5. De plus, IO80211Controller::start requiert un IO80211WorkQueue non nul pour instancier IO80211CommandGate, IO80211PostOffice, IO80211TimerSource et IO80211TimerFactory via allocWithParams().
* Solution architecturale :
- Implémentation explicite de createWorkQueue() et getWorkQueue() ainsi que createWorkLoop() et getWorkLoop() dans QualcommWifi.
- Allocation dynamique de IO80211WorkQueue via sa fabrique système IO80211WorkQueue::workQueue().
- 0 conflit de padslot OpenCore : les slots 306, 209, 395 et 397 sont des symboles concrets dans le parent (__ZN17IO80211Controller15createWorkQueueEv, etc.).
- Initialisation d'une adresse MAC Qualcomm par défaut valide dans init() pour garantir le succès des vérifications d'interface.
- Modifications apportées :
* QualcommWifi/QualcommWifi.hpp : ajout du membre fWorkQueue et déclaration des méthodes virtuelles createWorkQueue, getWorkQueue, createWorkLoop, getWorkLoop.
* QualcommWifi/QualcommWifi.cpp : initialisation et libération de fWorkQueue, implémentation des créateurs WorkQueue/WorkLoop, et sécurisation des appels d'attachement d'interface réseau.
- Validation :
* Compilation sans erreur via ./build_wifi.sh.
* kmutil libraries -p QualcommWifi.kext validé à 100% contre BootKernelExtensions.kc.
* Simulation binaire OpenCore du chaînage de vtables : 0 violation de padslot (463 slots alignés).
* Déploiement direct synchronisé dans /Volumes/EFI/EFI/OC/Kexts/QualcommWifi.kext.
264 lines
10 KiB
C++
264 lines
10 KiB
C++
#ifndef _QUALCOMMWIFI_HPP
|
|
#define _QUALCOMMWIFI_HPP
|
|
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
|
|
|
#include <IOKit/IOService.h>
|
|
#include <IOKit/pci/IOPCIDevice.h>
|
|
#include <IOKit/IOWorkLoop.h>
|
|
#include <IOKit/IOInterruptEventSource.h>
|
|
#include <IOKit/IOBufferMemoryDescriptor.h>
|
|
#include <IOKit/network/IOEthernetController.h>
|
|
#include <IOKit/network/IOEthernetInterface.h>
|
|
#include <IOKit/network/IOOutputQueue.h>
|
|
#include <IOKit/network/IONetworkMedium.h>
|
|
|
|
#include <IOKit/80211/apple80211_var.h>
|
|
#include <IOKit/80211/apple80211_ioctl.h>
|
|
#include <IOKit/80211/IO80211Controller.h>
|
|
#include <IOKit/80211/IO80211SkywalkInterface.h>
|
|
#include <IOKit/80211/IO80211WorkQueue.h>
|
|
#include "Firmware_WCN7850_Wifi.h"
|
|
|
|
// Registres PCIe et constantes de fenêtrage (ath12k/pci.h)
|
|
#define ATH12K_PCI_SOC_GLOBAL_RESET 0x3008
|
|
#define ATH12K_PCI_WINDOW_REG_ADDRESS 0x310c
|
|
#define ATH12K_PCI_WINDOW_ENABLE_BIT 0x40000000
|
|
#define ATH12K_PCI_WINDOW_START 0x80000
|
|
#define ATH12K_PCI_WINDOW_RANGE_MASK 0x7FFFF
|
|
#define ATH12K_PCI_WINDOW_SHIFT 19
|
|
#define ATH12K_PCI_WINDOW_VALUE_MASK 0x3F
|
|
|
|
// Registre de révision matérielle du SoC Qualcomm WCN7850
|
|
#define TCSR_SOC_HW_VERSION 0x1B00000
|
|
#define TCSR_SOC_HW_VERSION_MAJOR_MASK 0x0F00
|
|
#define TCSR_SOC_HW_VERSION_MAJOR_SHIFT 8
|
|
#define TCSR_SOC_HW_VERSION_MINOR_MASK 0x00FF
|
|
|
|
// Masque DMA 36-bit aligné sur 4 Ko (4096 octets) exigé par WCN7850
|
|
#define ATH12K_DMA_MASK_36BIT_PAGE 0x0000000FFFFFF000ULL
|
|
#define ATH12K_DMA_TEST_RING_SIZE 65536 // 64 Ko pour le contexte MHI
|
|
|
|
// Registres MHI MMIO (bar0 direct)
|
|
#define ATH12K_MHI_MHIREGLEN 0x00
|
|
#define ATH12K_MHI_MHIVER 0x08
|
|
#define ATH12K_MHI_MHICFG 0x10
|
|
#define ATH12K_MHI_CHDBOFF 0x18
|
|
#define ATH12K_MHI_ERDBOFF 0x20
|
|
#define ATH12K_MHI_BHIOFF 0x28
|
|
#define ATH12K_MHI_BHIEOFF 0x2c
|
|
#define ATH12K_MHI_DEBUGOFF 0x30
|
|
#define ATH12K_MHI_MHICTRL 0x38
|
|
#define ATH12K_MHI_MHISTATUS 0x48
|
|
#define ATH12K_MHI_CCABAP_LOWER 0x58
|
|
#define ATH12K_MHI_CCABAP_HIGHER 0x5c
|
|
#define ATH12K_MHI_ECABAP_LOWER 0x60
|
|
#define ATH12K_MHI_ECABAP_HIGHER 0x64
|
|
#define ATH12K_MHI_CRCBAP_LOWER 0x68
|
|
#define ATH12K_MHI_CRCBAP_HIGHER 0x6c
|
|
#define ATH12K_MHI_CRDB_LOWER 0x70
|
|
#define ATH12K_MHI_CRDB_HIGHER 0x74
|
|
#define ATH12K_MHI_MHICTRLBASE_LOWER 0x80
|
|
#define ATH12K_MHI_MHICTRLBASE_HIGHER 0x84
|
|
#define ATH12K_MHI_MHICTRLLIMIT_LOWER 0x88
|
|
#define ATH12K_MHI_MHICTRLLIMIT_HIGHER 0x8c
|
|
#define ATH12K_MHI_MHIDATABASE_LOWER 0x98
|
|
#define ATH12K_MHI_MHIDATABASE_HIGHER 0x9c
|
|
#define ATH12K_MHI_MHIDATALIMIT_LOWER 0xa0
|
|
#define ATH12K_MHI_MHIDATALIMIT_HIGHER 0xa4
|
|
|
|
// États MHI
|
|
#define ATH12K_MHI_STATE_RESET 0x0
|
|
#define ATH12K_MHI_STATE_READY 0x1
|
|
#define ATH12K_MHI_STATE_M0 0x2
|
|
#define ATH12K_MHI_STATE_M1 0x3
|
|
#define ATH12K_MHI_STATE_M2 0x4
|
|
#define ATH12K_MHI_STATE_M3 0x5
|
|
|
|
// Environnements d'exécution MHI (EE)
|
|
#define ATH12K_MHI_EE_PBL 0x00
|
|
#define ATH12K_MHI_EE_SBL 0x01
|
|
#define ATH12K_MHI_EE_AMSS 0x02
|
|
#define ATH12K_MHI_EE_RDDM 0x03
|
|
#define ATH12K_MHI_EE_WFW 0x04
|
|
|
|
#define ATH12K_MHISTATUS_READY_MASK 0x00000001
|
|
#define ATH12K_MHICTRL_RESET_MASK 0x00000002
|
|
#define ATH12K_MHICTRL_MHISTATE_SHIFT 8
|
|
#define ATH12K_MHICTRL_MHISTATE_MASK 0x0000FF00
|
|
#define ATH12K_MHISTATUS_MHISTATE_SHIFT 8
|
|
#define ATH12K_MHISTATUS_MHISTATE_MASK 0x0000FF00
|
|
#define ATH12K_MHICFG_NER_MASK 0x00FF0000
|
|
#define ATH12K_MHICFG_NHWER_MASK 0xFF000000
|
|
|
|
// Types de paquets d'événements MHI
|
|
#define ATH12K_MHI_PKT_TYPE_STATE_CHANGE_EVENT 0x20
|
|
#define ATH12K_MHI_PKT_TYPE_EE_EVENT 0x40
|
|
|
|
// Registres BHI (Boot Host Interface)
|
|
#define ATH12K_BHI_BHIVERSION_MINOR 0x00
|
|
#define ATH12K_BHI_BHIVERSION_MAJOR 0x04
|
|
#define ATH12K_BHI_IMGADDR_LOW 0x08
|
|
#define ATH12K_BHI_IMGADDR_HIGH 0x0c
|
|
#define ATH12K_BHI_IMGSIZE 0x10
|
|
#define ATH12K_BHI_IMGTXDB 0x18
|
|
#define ATH12K_BHI_EXECENV 0x28
|
|
#define ATH12K_BHI_STATUS 0x2c
|
|
#define ATH12K_BHI_ERRCODE 0x30
|
|
#define ATH12K_BHI_SERIALNU 0x40
|
|
|
|
#define ATH12K_BHI_STATUS_RESET 0x00
|
|
#define ATH12K_BHI_STATUS_MASK 0xC0000000
|
|
#define ATH12K_BHI_STATUS_SHIFT 30
|
|
#define ATH12K_BHI_STATUS_SUCCESS 0x02
|
|
#define ATH12K_BHI_STATUS_ERROR 0x03
|
|
|
|
// Registres BHIe (Boot Host Interface extension)
|
|
#define ATH12K_BHIE_MSMSOCID 0x00
|
|
#define ATH12K_BHIE_TXVECADDR_LOW 0x2c
|
|
#define ATH12K_BHIE_TXVECADDR_HIGH 0x30
|
|
#define ATH12K_BHIE_TXVECSIZE 0x34
|
|
#define ATH12K_BHIE_TXVECDB 0x3c
|
|
#define ATH12K_BHIE_TXVECSTATUS 0x44
|
|
#define ATH12K_BHIE_RXVECADDR_LOW 0x60
|
|
#define ATH12K_BHIE_RXVECADDR_HIGH 0x64
|
|
#define ATH12K_BHIE_RXVECSIZE 0x68
|
|
#define ATH12K_BHIE_RXVECDB 0x70
|
|
#define ATH12K_BHIE_RXVECSTATUS 0x78
|
|
|
|
#define ATH12K_BHIE_TXVECSTATUS_STATUS_MASK 0xC0000000
|
|
#define ATH12K_BHIE_TXVECSTATUS_STATUS_SHIFT 30
|
|
#define ATH12K_BHIE_TXVECSTATUS_XFER_COMPL 0x02
|
|
|
|
struct bhi_vec_entry {
|
|
uint64_t dma_addr;
|
|
uint64_t size;
|
|
} __attribute__((packed));
|
|
|
|
struct mhi_chan_ctxt {
|
|
UInt32 chcfg;
|
|
UInt32 chtype;
|
|
UInt32 erindex;
|
|
UInt64 rbase __attribute__((packed, aligned(4)));
|
|
UInt64 rlen __attribute__((packed, aligned(4)));
|
|
UInt64 rp __attribute__((packed, aligned(4)));
|
|
UInt64 wp __attribute__((packed, aligned(4)));
|
|
} __attribute__((packed));
|
|
|
|
struct mhi_event_ctxt {
|
|
UInt32 intmod;
|
|
UInt32 ertype;
|
|
UInt32 msivec;
|
|
UInt64 rbase __attribute__((packed, aligned(4)));
|
|
UInt64 rlen __attribute__((packed, aligned(4)));
|
|
UInt64 rp __attribute__((packed, aligned(4)));
|
|
UInt64 wp __attribute__((packed, aligned(4)));
|
|
} __attribute__((packed));
|
|
|
|
struct mhi_cmd_ctxt {
|
|
UInt32 reserved0;
|
|
UInt32 reserved1;
|
|
UInt32 reserved2;
|
|
UInt64 rbase __attribute__((packed, aligned(4)));
|
|
UInt64 rlen __attribute__((packed, aligned(4)));
|
|
UInt64 rp __attribute__((packed, aligned(4)));
|
|
UInt64 wp __attribute__((packed, aligned(4)));
|
|
} __attribute__((packed));
|
|
|
|
struct mhi_ring_element {
|
|
UInt64 ptr;
|
|
UInt32 dword[2];
|
|
} __attribute__((packed));
|
|
|
|
#define MHI_TRE_GET_EV_TYPE(tre) (((tre)->dword[1] >> 16) & 0xFF)
|
|
#define MHI_TRE_GET_EV_STATE(tre) (((tre)->dword[0] >> 24) & 0xFF)
|
|
#define MHI_TRE_GET_EV_EXECENV(tre) (((tre)->dword[0] >> 24) & 0xFF)
|
|
|
|
class QualcommWifi : public IO80211Controller {
|
|
OSDeclareDefaultStructors(QualcommWifi)
|
|
|
|
private:
|
|
IOPCIDevice *fPciDevice;
|
|
IOMemoryMap *fBar0Map;
|
|
volatile void *fBar0Virt;
|
|
UInt32 fCurrWindow;
|
|
|
|
IOInterruptEventSource *fInterruptSource;
|
|
IO80211WorkQueue *fWorkQueue;
|
|
IONetworkInterface *fNetif;
|
|
IOEthernetAddress fMacAddress;
|
|
|
|
// État réseau Wi-Fi
|
|
bool fLinkActive;
|
|
UInt16 fCurrentChannel;
|
|
SInt32 fLastRssi;
|
|
UInt8 fSsid[APPLE80211_MAX_SSID_LEN];
|
|
UInt32 fSsidLen;
|
|
UInt8 fBssid[6];
|
|
bool fScanInProgress;
|
|
|
|
// Tampon DMA physiquement contigu
|
|
IOBufferMemoryDescriptor *fDmaBuf;
|
|
IOPhysicalAddress fDmaPhysAddr;
|
|
void *fDmaVirtAddr;
|
|
bool fDmaPrepared;
|
|
bool fFirmwareLoaded;
|
|
|
|
UInt32 read32(UInt32 offset);
|
|
void write32(UInt32 offset, UInt32 value);
|
|
|
|
void selectWindow(UInt32 offset);
|
|
UInt32 socRead32(UInt32 offset);
|
|
void socWrite32(UInt32 offset, UInt32 value);
|
|
|
|
bool allocDmaContext(IOByteCount size);
|
|
void freeDmaContext(void);
|
|
|
|
bool loadBhiFirmware(void);
|
|
|
|
static void interruptOccurred(OSObject *owner, IOInterruptEventSource *src, int count);
|
|
|
|
public:
|
|
virtual bool init(OSDictionary *dictionary = 0) override;
|
|
virtual void free(void) override;
|
|
virtual IOService *probe(IOService *provider, SInt32 *score) override;
|
|
virtual bool start(IOService *provider) override;
|
|
virtual void stop(IOService *provider) override;
|
|
|
|
// WorkQueue / WorkLoop interface required by IO80211Controller / IONetworkController
|
|
virtual bool createWorkLoop(void) override;
|
|
virtual IOWorkLoop* getWorkLoop(void) const override;
|
|
virtual bool createWorkQueue(void) override;
|
|
virtual IO80211WorkQueue* getWorkQueue(void) const override;
|
|
|
|
// IOEthernetController / IONetworkController interface
|
|
virtual IOReturn getHardwareAddress(IOEthernetAddress *addrP) override;
|
|
virtual IOReturn enable(IONetworkInterface *netif) override;
|
|
virtual IOReturn disable(IONetworkInterface *netif) override;
|
|
virtual UInt32 outputPacket(mbuf_t m, void *param) override;
|
|
|
|
// macOS Tahoe 26.x (Darwin 25) IO80211Controller Skywalk overrides
|
|
virtual bool isCommandProhibited(int command) override { return false; }
|
|
virtual IOReturn handleCardSpecific(IO80211SkywalkInterface *iface, unsigned long req_type, void *req_data, bool isSet) override;
|
|
virtual UInt32 hardwareOutputQueueDepth(void) override { return 0; }
|
|
virtual SInt32 performCountryCodeOperation(IO80211CountryCodeOp op) override { return 0; }
|
|
virtual void dataLinkLayerAttachComplete(void) override;
|
|
virtual SInt32 enableFeature(IO80211FeatureCode code, void *arg) override { return 0; }
|
|
virtual IOReturn getDRIVER_VERSION(IO80211SkywalkInterface *iface, apple80211_version_data *vd) override;
|
|
virtual IOReturn getHARDWARE_VERSION(IO80211SkywalkInterface *iface, apple80211_version_data *vd) override;
|
|
virtual IOReturn getCARD_CAPABILITIES(IO80211SkywalkInterface *iface, apple80211_capability_data *cap) override;
|
|
virtual IOReturn getPOWER(IO80211SkywalkInterface *iface, apple80211_power_data *pwr) override;
|
|
virtual IOReturn setPOWER(IO80211SkywalkInterface *iface, apple80211_power_data *pwr) override;
|
|
virtual IOReturn getCOUNTRY_CODE(IO80211SkywalkInterface *iface, apple80211_country_code_data *cc) override;
|
|
virtual IOReturn setCOUNTRY_CODE(IO80211SkywalkInterface *iface, apple80211_country_code_data *cc) override { return kIOReturnSuccess; }
|
|
virtual IOReturn setGET_DEBUG_INFO(IO80211SkywalkInterface *iface, apple80211_debug_command *dbg) override { return kIOReturnSuccess; }
|
|
virtual void* getLogger(void) const override { return nullptr; }
|
|
virtual void* getFaultReporterFromDriver(void) override { return nullptr; }
|
|
|
|
// Dispatcher de requêtes Apple80211 / airportd
|
|
SInt32 handleApple80211Request(unsigned int req_type, int req_val, void* req_data);
|
|
};
|
|
|
|
#endif
|