kern_return_t pmem_iokit_enumerate_pci(pmem_pci_callback_t callback, void *ctx) { kern_return_t error = KERN_FAILURE; OSObject *obj = nullptr; OSDictionary *search = nullptr; OSIterator *iter = nullptr; IOPCIDevice *dev = nullptr; IODeviceMemory *mem = nullptr; IOItemCount mem_count = 0; int cmp; search = IOService::serviceMatching("IOPCIDevice"); iter = IOService::getMatchingServices(search); if (!iter) { pmem_error("Couldn't find any PCI devices."); goto bail; } while ((obj = iter->getNextObject())) { cmp = strncmp("IOPCIDevice", obj->getMetaClass()->getClassName(), strlen("IOPCIDevice")); if (cmp != 0) { // I haven't seen the above return anything other than // PCI devices, but Apple's documentation is sparse (which // is a nice word for what it is) and doesn't actually // say anything about what's guaranteed to be returned. // I'd just as well rather not chance it. pmem_warn("Expected IOPCIDevice but got %s - skipping.", obj->getMetaClass()->getClassName()); continue; } dev = (IOPCIDevice *)obj; mem_count = dev->getDeviceMemoryCount(); pmem_debug("Found PCI device %s", dev->getName()); for (unsigned idx = 0; idx < mem_count; ++idx) { pmem_debug("Memory segment %d found.", idx); mem = dev->getDeviceMemoryWithIndex(idx); pmem_signal_t signal = callback(dev, mem, idx, ctx); if (signal == pmem_Stop) { error = KERN_FAILURE; goto bail; } } } error = KERN_SUCCESS; bail: if (iter) { iter->release(); } if (search) { search->release(); } return error; }
/** * Start this service. */ bool org_virtualbox_VBoxGuest::start(IOService *pProvider) { if (!IOService::start(pProvider)) return false; /* Low level initialization should be performed only once */ if (!ASMAtomicCmpXchgBool(&g_fInstantiated, true, false)) { IOService::stop(pProvider); return false; } m_pIOPCIDevice = OSDynamicCast(IOPCIDevice, pProvider); if (m_pIOPCIDevice) { if (isVmmDev(m_pIOPCIDevice)) { /* Enable memory response from VMM device */ m_pIOPCIDevice->setMemoryEnable(true); m_pIOPCIDevice->setIOEnable(true); IOMemoryDescriptor *pMem = m_pIOPCIDevice->getDeviceMemoryWithIndex(0); if (pMem) { IOPhysicalAddress IOPortBasePhys = pMem->getPhysicalAddress(); /* Check that returned value is from I/O port range (at least it is 16-bit lenght) */ if((IOPortBasePhys >> 16) == 0) { RTIOPORT IOPortBase = (RTIOPORT)IOPortBasePhys; void *pvMMIOBase = NULL; uint32_t cbMMIO = 0; m_pMap = m_pIOPCIDevice->mapDeviceMemoryWithIndex(1); if (m_pMap) { pvMMIOBase = (void *)m_pMap->getVirtualAddress(); cbMMIO = m_pMap->getLength(); } int rc = VBoxGuestInitDevExt(&g_DevExt, IOPortBase, pvMMIOBase, cbMMIO, #if ARCH_BITS == 64 VBOXOSTYPE_MacOS_x64, #else VBOXOSTYPE_MacOS, #endif 0); if (RT_SUCCESS(rc)) { rc = VbgdDarwinCharDevInit(); if (rc == KMOD_RETURN_SUCCESS) { if (setupVmmDevInterrupts(pProvider)) { /* register the service. */ registerService(); LogRel(("VBoxGuest: IOService started\n")); return true; } LogRel(("VBoxGuest: Failed to set up interrupts\n")); VbgdDarwinCharDevRemove(); } else LogRel(("VBoxGuest: Failed to initialize character device (rc=%d).\n", rc)); VBoxGuestDeleteDevExt(&g_DevExt); } else LogRel(("VBoxGuest: Failed to initialize common code (rc=%d).\n", rc)); if (m_pMap) { m_pMap->release(); m_pMap = NULL; } } } else LogRel(("VBoxGuest: The device missing is the I/O port range (#0).\n")); } else