Esempio n. 1
0
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;
}
Esempio n. 2
0
/**
 * 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