diff --git a/QualcommWifi/QualcommWifi.cpp b/QualcommWifi/QualcommWifi.cpp index abd7a6d..29e4435 100644 --- a/QualcommWifi/QualcommWifi.cpp +++ b/QualcommWifi/QualcommWifi.cpp @@ -14,13 +14,38 @@ extern "C" { void _ZN19IONetworkController29_RESERVEDIONetworkController7Ev(void) {} } +#include +#include + +static char gLogBuffer[2048] = "QCOM_BOOT:"; + +static void logNvramStage(const char *tag) { + size_t curLen = strlen(gLogBuffer); + if (curLen + strlen(tag) + 2 < sizeof(gLogBuffer)) { + strcat(gLogBuffer, ">"); + strcat(gLogBuffer, tag); + } + IORegistryEntry *options = IORegistryEntry::fromPath("/options", gIODTPlane); + if (options) { + OSString *val = OSString::withCString(gLogBuffer); + if (val) { + options->setProperty("qcom_wifi_log", val); + val->release(); + } + } + IOLog("QualcommWifi: >>> [STAGE] %s <<<\n", tag); +} + #define super IO80211Controller OSDefineMetaClassAndStructors(QualcommWifi, IO80211Controller) bool QualcommWifi::init(OSDictionary *dictionary) { + logNvramStage("init_enter"); if (!super::init(dictionary)) { + logNvramStage("init_super_failed"); return false; } + logNvramStage("init_super_ok"); fPciDevice = nullptr; fBar0Map = nullptr; fBar0Virt = nullptr; @@ -56,12 +81,15 @@ void QualcommWifi::free(void) { } IOService *QualcommWifi::probe(IOService *provider, SInt32 *score) { + logNvramStage("probe_enter"); if (!super::probe(provider, score)) { + logNvramStage("probe_super_failed"); return nullptr; } IOPCIDevice *pciDev = OSDynamicCast(IOPCIDevice, provider); if (!pciDev) { + logNvramStage("probe_not_pci"); return nullptr; } @@ -71,9 +99,11 @@ IOService *QualcommWifi::probe(IOService *provider, SInt32 *score) { if (vendorId == 0x17cb && deviceId == 0x1107) { IOLog("QualcommWifi: Controleur Wi-Fi 7 Qualcomm WCN7850 detecte (0x%04x:0x%04x) !\n", vendorId, deviceId); *score += 20000; + logNvramStage("probe_match_ok"); return this; } + logNvramStage("probe_no_match"); return nullptr; } @@ -513,64 +543,78 @@ bool QualcommWifi::loadBhiFirmware(void) { } bool QualcommWifi::start(IOService *provider) { + logNvramStage("start_enter"); IOLog("QualcommWifi: Demarrage du pilote Wi-Fi natif (IO80211Controller)...\n"); if (!super::start(provider)) { + logNvramStage("super_start_failed"); IOLog("QualcommWifi: Erreur - IO80211Controller::start(provider) a echoue !\n"); return false; } + logNvramStage("super_start_ok"); fPciDevice = OSDynamicCast(IOPCIDevice, provider); if (!fPciDevice) { + logNvramStage("start_no_pci"); return false; } fPciDevice->retain(); + logNvramStage("pci_open"); if (!fPciDevice->open(this)) { + logNvramStage("pci_open_failed"); OSSafeReleaseNULL(fPciDevice); return false; } + logNvramStage("pci_open_ok"); + + // Réveil formel du contrôleur PCIe vers l'état d'alimentation D0 + logNvramStage("pci_enable_d0"); + fPciDevice->enablePCIPowerManagement(kPCIPMCSPowerStateD0); UInt16 pciCommand = fPciDevice->configRead16(kIOPCIConfigCommand); pciCommand |= kIOPCICommandMemorySpace; pciCommand &= ~kIOPCICommandBusMaster; // Protection absolue contre tout accès DMA non configuré sur AMD-Vi + logNvramStage("pci_cmd_write"); fPciDevice->configWrite16(kIOPCIConfigCommand, pciCommand); - fBar0Map = fPciDevice->mapDeviceMemoryWithRegister(kIOPCIConfigBaseAddress0); - if (!fBar0Map) { - fPciDevice->close(this); - OSSafeReleaseNULL(fPciDevice); - return false; - } - fBar0Virt = (volatile void *)fBar0Map->getVirtualAddress(); - - UInt32 mhiStatus = read32(ATH12K_MHI_MHISTATUS); - UInt32 mhiCtrl = read32(ATH12K_MHI_MHICTRL); - UInt32 bhiOff = read32(ATH12K_MHI_BHIOFF); - UInt32 bhieOff = read32(ATH12K_MHI_BHIEOFF); - IOLog("QualcommWifi: MHI STATUS=0x%08x, CTRL=0x%08x, BHIOFF=0x%08x, BHIEOFF=0x%08x\n", - mhiStatus, mhiCtrl, bhiOff, bhieOff); - - setProperty("MHI_Status", mhiStatus, 32); - setProperty("MHI_Ctrl", mhiCtrl, 32); - setProperty("BHI_Offset", bhiOff, 32); - setProperty("BHIE_Offset", bhieOff, 32); + int allow_mmio = 0; + PE_parse_boot_argn("qcom_mmio", &allow_mmio, sizeof(allow_mmio)); UInt32 bhiSerial = 0x123456; - if (bhiOff != 0xFFFFFFFF && bhiOff < 0x200000) { - UInt32 bhiMajor = read32(bhiOff + ATH12K_BHI_BHIVERSION_MAJOR); - UInt32 bhiMinor = read32(bhiOff + ATH12K_BHI_BHIVERSION_MINOR); - UInt32 bhiEe = read32(bhiOff + ATH12K_BHI_EXECENV); - UInt32 bhiStat = read32(bhiOff + ATH12K_BHI_STATUS); - bhiSerial = read32(bhiOff + ATH12K_BHI_SERIALNU); - IOLog("QualcommWifi: BHI v%u.%u: ExecEnv=0x%x, Status=0x%x, Serial=0x%08x\n", - bhiMajor, bhiMinor, bhiEe, bhiStat, bhiSerial); + if (allow_mmio) { + logNvramStage("bar0_map"); + fBar0Map = fPciDevice->mapDeviceMemoryWithRegister(kIOPCIConfigBaseAddress0); + if (fBar0Map) { + fBar0Virt = (volatile void *)fBar0Map->getVirtualAddress(); + logNvramStage("read_mhi"); + UInt32 mhiStatus = read32(ATH12K_MHI_MHISTATUS); + UInt32 mhiCtrl = read32(ATH12K_MHI_MHICTRL); + UInt32 bhiOff = read32(ATH12K_MHI_BHIOFF); + UInt32 bhieOff = read32(ATH12K_MHI_BHIEOFF); + setProperty("MHI_Status", mhiStatus, 32); + setProperty("MHI_Ctrl", mhiCtrl, 32); + setProperty("BHI_Offset", bhiOff, 32); + setProperty("BHIE_Offset", bhieOff, 32); - setProperty("BHI_Major", bhiMajor, 32); - setProperty("BHI_Minor", bhiMinor, 32); - setProperty("BHI_ExecEnv", bhiEe, 32); - setProperty("BHI_Status", bhiStat, 32); - setProperty("BHI_Serial", bhiSerial, 32); + if (bhiOff != 0xFFFFFFFF && bhiOff > 0 && bhiOff < 0x200000) { + logNvramStage("read_bhi"); + UInt32 bhiMajor = read32(bhiOff + ATH12K_BHI_BHIVERSION_MAJOR); + UInt32 bhiMinor = read32(bhiOff + ATH12K_BHI_BHIVERSION_MINOR); + UInt32 bhiEe = read32(bhiOff + ATH12K_BHI_EXECENV); + UInt32 bhiStat = read32(bhiOff + ATH12K_BHI_STATUS); + bhiSerial = read32(bhiOff + ATH12K_BHI_SERIALNU); + + setProperty("BHI_Major", bhiMajor, 32); + setProperty("BHI_Minor", bhiMinor, 32); + setProperty("BHI_ExecEnv", bhiEe, 32); + setProperty("BHI_Status", bhiStat, 32); + setProperty("BHI_Serial", bhiSerial, 32); + } + } + } else { + logNvramStage("safe_mode_active"); + setProperty("QualcommWifi_SafeMode", "Active"); } // Configuration de l'adresse MAC (OUI Qualcomm 00:03:7F + BHI serial) @@ -586,6 +630,7 @@ bool QualcommWifi::start(IOService *provider) { fMacAddress.bytes[3], fMacAddress.bytes[4], fMacAddress.bytes[5]); // Propriétés Wi-Fi AirPort pour macOS et airportd + logNvramStage("set_airport_props"); setProperty("IO80211AirPort", true); setProperty("AirPort", true); setProperty("IO80211Locale", "ETSI"); @@ -594,6 +639,7 @@ bool QualcommWifi::start(IOService *provider) { setProperty("IO80211RadioState", (UInt64)1, 32); // Configuration et publication des médiums réseau (IEEE 802.11) + logNvramStage("pub_mediums"); OSDictionary *mediumDict = OSDictionary::withCapacity(2); if (mediumDict) { IONetworkMedium *medium = IONetworkMedium::medium(kIOMediumIEEE80211, 54000000); @@ -608,7 +654,9 @@ bool QualcommWifi::start(IOService *provider) { } // Enregistrement IOKit du contrôleur Wi-Fi natif (déclenche le matching airportd) + logNvramStage("register_service"); registerService(); + logNvramStage("start_done"); IOLog("QualcommWifi: Pilote Wi-Fi natif (IO80211Controller) demarre avec succes !\n"); return true; } @@ -616,11 +664,6 @@ bool QualcommWifi::start(IOService *provider) { void QualcommWifi::stop(IOService *provider) { IOLog("QualcommWifi: Arret du pilote Wi-Fi natif, liberation MSI, DMA et BAR0.\n"); - if (fNetif) { - IOEthernetController::detachInterface(fNetif); - OSSafeReleaseNULL(fNetif); - } - IOWorkLoop *workLoop = getWorkLoop(); if (fInterruptSource) { fInterruptSource->disable(); @@ -646,14 +689,17 @@ void QualcommWifi::stop(IOService *provider) { } bool QualcommWifi::createWorkQueue(void) { + logNvramStage("createWorkQueue"); if (fWorkQueue) { return true; } fWorkQueue = IO80211WorkQueue::workQueue(); if (!fWorkQueue) { + logNvramStage("workQueue_failed"); IOLog("QualcommWifi: Erreur - Impossible d'allouer IO80211WorkQueue !\n"); return false; } + logNvramStage("workQueue_ok"); IOLog("QualcommWifi: IO80211WorkQueue allouee avec succes (0x%p) !\n", fWorkQueue); return true; } @@ -671,12 +717,14 @@ IOWorkLoop* QualcommWifi::getWorkLoop(void) const { } IOReturn QualcommWifi::getHardwareAddress(IOEthernetAddress *addrP) { + logNvramStage("getHardwareAddress"); if (!addrP) return kIOReturnBadArgument; bcopy(&fMacAddress, addrP, sizeof(IOEthernetAddress)); return kIOReturnSuccess; } IOReturn QualcommWifi::enable(IONetworkInterface *netif) { + logNvramStage("netif_enable"); IOLog("QualcommWifi: Interface reseau activee par macOS.\n"); const IONetworkMedium *medium = getSelectedMedium(); setLinkStatus(kIONetworkLinkValid | kIONetworkLinkActive, medium); @@ -684,6 +732,7 @@ IOReturn QualcommWifi::enable(IONetworkInterface *netif) { } IOReturn QualcommWifi::disable(IONetworkInterface *netif) { + logNvramStage("netif_disable"); IOLog("QualcommWifi: Interface reseau desactivee par macOS.\n"); setLinkStatus(kIONetworkLinkValid, nullptr); return kIOReturnSuccess; @@ -697,6 +746,7 @@ UInt32 QualcommWifi::outputPacket(mbuf_t m, void *param) { } void QualcommWifi::dataLinkLayerAttachComplete(void) { + logNvramStage("dataLinkAttachDone"); IOLog("QualcommWifi: dataLinkLayerAttachComplete (Skywalk Tahoe).\n"); } @@ -721,6 +771,7 @@ IOReturn QualcommWifi::getPOWER(IO80211SkywalkInterface *iface, apple80211_power } IOReturn QualcommWifi::setPOWER(IO80211SkywalkInterface *iface, apple80211_power_data *pwr) { + logNvramStage("setPOWER"); int val = (pwr && pwr->power_state[0]) ? 1 : 0; fLinkActive = (val == 1); IOLog("QualcommWifi: setPOWER invoqué par airportd (val=%d, fLinkActive=%d)\n", val, fLinkActive); @@ -732,6 +783,9 @@ IOReturn QualcommWifi::getCOUNTRY_CODE(IO80211SkywalkInterface *iface, apple8021 } SInt32 QualcommWifi::handleApple80211Request(unsigned int req_type, int req_val, void* req_data) { + char iocTag[32]; + snprintf(iocTag, sizeof(iocTag), "ioc_%u", req_type); + logNvramStage(iocTag); switch (req_type) { case APPLE80211_IOC_CARD_CAPABILITIES: { apple80211_capability_data *cap = (apple80211_capability_data *)req_data;