Beispiel #1
0
void
IORegistrySetOSBuildVersion(char * build_version)
{
    IORegistryEntry * root = IORegistryEntry::getRegistryRoot();

    if (root) {
        if (build_version) {
            root->setProperty(kOSBuildVersionKey, build_version);
        } else {
            root->removeProperty(kOSBuildVersionKey);
        }
    }

    return;
}
void IODTFreeLoaderInfo( const char *key, void *infoAddr, int infoSize )
{
    vm_offset_t			range[2];
    IORegistryEntry		*chosen;

    range[0] = (vm_offset_t)infoAddr;
    range[1] = (vm_offset_t)infoSize;
    FreePhysicalMemory( range );

    if ( key != 0 ) {
        chosen = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane );
        if ( chosen != 0 ) {
            chosen->removeProperty(key);
        }
    }
}
Beispiel #3
0
IOReturn
IOPolledFilePollersClose(IOPolledFileIOVars * filevars, uint32_t state)
{
    IOPolledFilePollers * vars = filevars->pollers;
    IOPolledInterface * poller;
    IORegistryEntry *   next;
    IOReturn            err;
    int32_t		idx;

    (void) IOPolledFilePollersIODone(vars, false);

    if (kIOPolledPostflightState == state)
    {
        vars->openCount--;
        if (vars->openCount)
        {
            // 21207427
            IOPolledFilePollersOpen(filevars, vars->openState, vars->abortable);
            return (kIOReturnSuccess);
        }
    }

    for (idx = 0, err = kIOReturnSuccess;
            (poller = (IOPolledInterface *) vars->pollers->getObject(idx));
            idx++)
    {
        err = poller->close(state);
        if (err) HIBLOG("IOPolledInterface::close[%d] 0x%x\n", idx, err);
    }

    if (kIOPolledPostflightState == state)
    {
        next = vars->media;
        while (next)
        {
            next->removeProperty(kIOPolledInterfaceActiveKey);
            next = next->getParentEntry(gIOServicePlane);
        }

        if (vars->ioBuffer)
        {
            vars->ioBuffer->release();
            vars->ioBuffer = 0;
        }
    }
    return (err);
}
Beispiel #4
0
void
KLDBootstrap::readBooterExtensions(void)
{
    IORegistryEntry           * booterMemoryMap         = NULL;  // must release
    OSDictionary              * propertyDict            = NULL;  // must release
    OSCollectionIterator      * keyIterator             = NULL;  // must release
    OSString                  * deviceTreeName          = NULL;  // do not release
    
    const _DeviceTreeBuffer   * deviceTreeBuffer        = NULL;  // do not free
    char                      * booterDataPtr           = NULL;  // do not free
    OSData                    * booterData              = NULL;  // must release

    OSKext                    * aKext                   = NULL;  // must release

    OSKextLog(/* kext */ NULL,
        kOSKextLogProgressLevel |
        kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag,
        "Reading startup extensions from booter memory.");
    
    booterMemoryMap = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane);

    if (!booterMemoryMap) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag,
            "Can't read booter memory map.");
        goto finish;
    }

    propertyDict = booterMemoryMap->dictionaryWithProperties();
    if (!propertyDict) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogDirectoryScanFlag,
            "Can't get property dictionary from memory map.");
        goto finish;
    }

    keyIterator = OSCollectionIterator::withCollection(propertyDict);
    if (!keyIterator) {
        OSKextLog(/* kext */ NULL,
            kOSKextLogErrorLevel |
            kOSKextLogGeneralFlag,
            "Can't allocate iterator for driver images.");
        goto finish;
    }

    /* Create dictionary of excluded kexts
     */
    OSKext::createExcludeListFromBooterData(propertyDict, keyIterator);
    keyIterator->reset();

    while ( ( deviceTreeName =
        OSDynamicCast(OSString, keyIterator->getNextObject() ))) {

        const char * devTreeNameCString = deviceTreeName->getCStringNoCopy();
        OSData * deviceTreeEntry = OSDynamicCast(OSData,
            propertyDict->getObject(deviceTreeName));

       /* Clear out the booterData from the prior iteration.
        */
        OSSafeReleaseNULL(booterData);

        /* If there is no entry for the name, we can't do much with it. */
        if (!deviceTreeEntry) {
            continue;
        }

        /* Make sure it is a kext */
        if (strncmp(devTreeNameCString,
                    BOOTER_KEXT_PREFIX,
                    CONST_STRLEN(BOOTER_KEXT_PREFIX))) {
            continue;
        }

        deviceTreeBuffer = (const _DeviceTreeBuffer *)
            deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
        if (!deviceTreeBuffer) {
           /* We can't get to the data, so we can't do anything,
            * not even free it from physical memory (if it's there).
            */
            OSKextLog(/* kext */ NULL,
                kOSKextLogErrorLevel |
                kOSKextLogDirectoryScanFlag,
                "Device tree entry %s has NULL pointer.",
                devTreeNameCString);
            goto finish;  // xxx - continue, panic?
        }

        booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
        if (!booterDataPtr) {
            OSKextLog(/* kext */ NULL,
                kOSKextLogErrorLevel |
                kOSKextLogDirectoryScanFlag,
                "Can't get virtual address for device tree entry %s.",
                devTreeNameCString);
            goto finish;
        }

       /* Wrap the booter data buffer in an OSData and set a dealloc function
        * so it will take care of the physical memory when freed. Kexts will
        * retain the booterData for as long as they need it. Remove the entry
        * from the booter memory map after this is done.
        */
        booterData = OSData::withBytesNoCopy(booterDataPtr,
            deviceTreeBuffer->length);
        if (!booterData) {
            OSKextLog(/* kext */ NULL,
                kOSKextLogErrorLevel |
                kOSKextLogGeneralFlag,
                "Error - Can't allocate OSData wrapper for device tree entry %s.",
                devTreeNameCString);
            goto finish;
        }
        booterData->setDeallocFunction(osdata_phys_free);

        /* Create the kext for the entry, then release it, because the
         * kext system keeps them around until explicitly removed.
         * Any creation/registration failures are already logged for us.
         */
        OSKext * newKext = OSKext::withBooterData(deviceTreeName, booterData);
        OSSafeReleaseNULL(newKext);

        booterMemoryMap->removeProperty(deviceTreeName);

    } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */

finish:

    OSSafeReleaseNULL(booterMemoryMap);
    OSSafeReleaseNULL(propertyDict);
    OSSafeReleaseNULL(keyIterator);
    OSSafeReleaseNULL(booterData);
    OSSafeReleaseNULL(aKext);
    return;
}
Beispiel #5
0
IORegistryEntry *
IODeviceTreeAlloc( void * dtTop )
{
    IORegistryEntry *		parent;
    IORegistryEntry *		child;
    IORegistryIterator *	regIter;
    DTEntryIterator		iter;
    DTEntry			dtChild;
    DTEntry			mapEntry;
    OSArray *			stack;
    OSData *			prop;
    OSDictionary *		allInts;
    vm_offset_t *		dtMap;
    unsigned int		propSize;
    bool			intMap;
    bool			freeDT;

    gIODTPlane = IORegistryEntry::makePlane( kIODeviceTreePlane );

    gIODTNameKey 		= OSSymbol::withCStringNoCopy( "name" );
    gIODTUnitKey 		= OSSymbol::withCStringNoCopy( "AAPL,unit-string" );
    gIODTCompatibleKey 	= OSSymbol::withCStringNoCopy( "compatible" );
    gIODTTypeKey 		= OSSymbol::withCStringNoCopy( "device_type" );
    gIODTModelKey 		= OSSymbol::withCStringNoCopy( "model" );
    gIODTSizeCellKey 	= OSSymbol::withCStringNoCopy( "#size-cells" );
    gIODTAddressCellKey = OSSymbol::withCStringNoCopy( "#address-cells" );
    gIODTRangeKey 		= OSSymbol::withCStringNoCopy( "ranges" );
    gIODTPersistKey		= OSSymbol::withCStringNoCopy( "IODTPersist" );

    assert(    gIODTPlane && gIODTCompatibleKey
               && gIODTTypeKey && gIODTModelKey
               && gIODTSizeCellKey && gIODTAddressCellKey && gIODTRangeKey
               && gIODTPersistKey );

    gIODTDefaultInterruptController
        = OSSymbol::withCStringNoCopy("IOPrimaryInterruptController");
    gIODTNWInterruptMappingKey
        = OSSymbol::withCStringNoCopy("IONWInterrupts");

    gIODTAAPLInterruptsKey
        = OSSymbol::withCStringNoCopy("AAPL,interrupts");
    gIODTPHandleKey
        = OSSymbol::withCStringNoCopy("AAPL,phandle");

    gIODTInterruptParentKey
        = OSSymbol::withCStringNoCopy("interrupt-parent");

    gIODTPHandles	= OSArray::withCapacity( 1 );
    gIODTPHandleMap	= OSArray::withCapacity( 1 );

    gIODTInterruptCellKey
        = OSSymbol::withCStringNoCopy("#interrupt-cells");

    assert(    gIODTDefaultInterruptController && gIODTNWInterruptMappingKey
               && gIODTAAPLInterruptsKey
               && gIODTPHandleKey && gIODTInterruptParentKey
               && gIODTPHandles && gIODTPHandleMap
               && gIODTInterruptCellKey
          );

    freeDT = (kSuccess == DTLookupEntry( 0, "/chosen/memory-map", &mapEntry ))
             && (kSuccess == DTGetProperty( mapEntry,
                                            "DeviceTree", (void **) &dtMap, &propSize ))
             && ((2 * sizeof(uint32_t)) == propSize);

    parent = MakeReferenceTable( (DTEntry)dtTop, freeDT );

    stack = OSArray::withObjects( (const OSObject **) &parent, 1, 10 );
    DTCreateEntryIterator( (DTEntry)dtTop, &iter );

    do {
        parent = (IORegistryEntry *)stack->getObject( stack->getCount() - 1);
        //parent->release();
        stack->removeObject( stack->getCount() - 1);

        while( kSuccess == DTIterateEntries( iter, &dtChild) ) {

            child = MakeReferenceTable( dtChild, freeDT );
            child->attachToParent( parent, gIODTPlane);

            AddPHandle( child );

            if( kSuccess == DTEnterEntry( iter, dtChild)) {
                stack->setObject( parent);
                parent = child;
            }
            // only registry holds retain
            child->release();
        }

    } while( stack->getCount()
             && (kSuccess == DTExitEntry( iter, &dtChild)));

    stack->release();
    DTDisposeEntryIterator( iter);

    // parent is now root of the created tree

    // make root name first compatible entry (purely cosmetic)
    if( (prop = (OSData *) parent->getProperty( gIODTCompatibleKey))) {
        parent->setName( parent->getName(), gIODTPlane );
        parent->setName( (const char *) prop->getBytesNoCopy() );
    }

    // attach tree to meta root
    parent->attachToParent( IORegistryEntry::getRegistryRoot(), gIODTPlane);
    parent->release();

    if( freeDT ) {
        // free original device tree
        DTInit(0);
        IODTFreeLoaderInfo( "DeviceTree",
                            (void *)dtMap[0], (int) round_page(dtMap[1]) );
    }

    // adjust tree

    gIODTSharedInterrupts = OSDictionary::withCapacity(4);
    allInts = OSDictionary::withCapacity(4);
    intMap = false;
    regIter = IORegistryIterator::iterateOver( gIODTPlane,
              kIORegistryIterateRecursively );
    assert( regIter && allInts && gIODTSharedInterrupts );
    if( regIter && allInts && gIODTSharedInterrupts ) {
        while( (child = regIter->getNextObject())) {
            IODTMapInterruptsSharing( child, allInts );
            if( !intMap && child->getProperty( gIODTInterruptParentKey))
                intMap = true;

#if __ppc__
            OSObject * obj;

            // Look for a "driver,AAPL,MacOSX,PowerPC" property.
            if( (obj = child->getProperty( "driver,AAPL,MacOSX,PowerPC"))) {
                gIOCatalogue->addExtensionsFromArchive((OSData *)obj);
                child->removeProperty( "driver,AAPL,MacOSX,PowerPC");
            }

            // some gross pruning
            child->removeProperty( "lanLib,AAPL,MacOS,PowerPC");

            if( (obj = child->getProperty( "driver,AAPL,MacOS,PowerPC"))) {

                if( (0 == (prop = (OSData *)child->getProperty( gIODTTypeKey )))
                        || (strncmp("display", (char *)prop->getBytesNoCopy(), sizeof("display"))) ) {
                    child->removeProperty( "driver,AAPL,MacOS,PowerPC");
                }
            }
#endif /* __ppc__ */
        }
        regIter->release();
    }

#if IODTSUPPORTDEBUG
    parent->setProperty("allInts", allInts);
    parent->setProperty("sharedInts", gIODTSharedInterrupts);

    regIter = IORegistryIterator::iterateOver( gIODTPlane,
              kIORegistryIterateRecursively );
    if (regIter) {
        while( (child = regIter->getNextObject())) {
            OSArray *
            array = OSDynamicCast(OSArray, child->getProperty( gIOInterruptSpecifiersKey ));
            for( UInt32 i = 0; array && (i < array->getCount()); i++)
            {
                IOOptionBits options;
                IOReturn ret = IODTGetInterruptOptions( child, i, &options );
                if( (ret != kIOReturnSuccess) || options)
                    IOLog("%s[%ld] %ld (%x)\n", child->getName(), i, options, ret);
            }
        }
        regIter->release();
    }
#endif

    allInts->release();

    if( intMap)
        // set a key in the root to indicate we found NW interrupt mapping
        parent->setProperty( gIODTNWInterruptMappingKey,
                             (OSObject *) gIODTNWInterruptMappingKey );

    return( parent);
}