コード例 #1
0
bool IOCatalogue::startMatching( OSDictionary * matching )
{
    OSDictionary         * dict;
    OSOrderedSet         * set;

    if ( !matching )
        return false;

    set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
                                     (void *)gIOProbeScoreKey);
    if ( !set )
        return false;

    IOLockLock(lock);
    kernelTables->reset();

    while ( (dict = (OSDictionary *)kernelTables->getNextObject()) ) {

        /* This comparison must be done with only the keys in the
         * "matching" dict to enable general matching.
         */
        if ( dict->isEqualTo(matching, matching) )
            AddNewImports(set, dict);
    }
    // Start device matching.
    if ( set->getCount() > 0 ) {
        IOService::catalogNewDrivers(set);
        generation++;
    }

    IOLockUnlock(lock);

    set->release();

    return true;
}
コード例 #2
0
/*********************************************************************
* Add driver config tables to catalog and start matching process.
*
* Important that existing personalities are kept (not replaced)
* if duplicates found. Personalities can come from OSKext objects
* or from userland kext library. We want to minimize distinct
* copies between OSKext & IOCatalogue.
*
* xxx - userlib used to refuse to send personalities with IOKitDebug
* xxx - during safe boot. That would be better implemented here.
*********************************************************************/
bool IOCatalogue::addDrivers(
    OSArray * drivers,
    bool doNubMatching)
{
    bool                   result = false;
    OSCollectionIterator * iter = NULL;       // must release
    OSOrderedSet         * set = NULL;        // must release
    OSDictionary         * dict = NULL;       // do not release
    OSArray              * persons = NULL;    // do not release

    persons = OSDynamicCast(OSArray, drivers);
    if (!persons) {
        goto finish;
    }

    set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
                                      (void *)gIOProbeScoreKey );
    if (!set) {
        goto finish;
    }

    iter = OSCollectionIterator::withCollection(persons);
    if (!iter) {
        goto finish;
    }

    result = true;

    IOLockLock(lock);
    while ( (dict = (OSDictionary *) iter->getNextObject()) ) {

        // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL

        SInt count;

        UniqueProperties(dict);

        // Add driver personality to catalogue.
        count = array->getCount();
        while (count--) {
            OSDictionary * driver;

            // Be sure not to double up on personalities.
            driver = (OSDictionary *)array->getObject(count);

            /* Unlike in other functions, this comparison must be exact!
             * The catalogue must be able to contain personalities that
             * are proper supersets of others.
             * Do not compare just the properties present in one driver
             * pesonality or the other.
             */
            if (dict->isEqualTo(driver)) {
                break;
            }
        }
        if (count >= 0) {
            // its a dup
            continue;
        }

        result = array->setObject(dict);
        if (!result) {
            break;
        }

        AddNewImports(set, dict);
    }
    // Start device matching.
    if (doNubMatching && (set->getCount() > 0)) {
        IOService::catalogNewDrivers(set);
        generation++;
    }
    IOLockUnlock(lock);

finish:
    if (set)  set->release();
    if (iter) iter->release();

    return result;
}
コード例 #3
0
/*********************************************************************
* Remove drivers from the catalog which match the
* properties in the matching dictionary.
*********************************************************************/
bool
IOCatalogue::removeDrivers(
    OSDictionary * matching,
    bool doNubMatching)
{
    OSCollectionIterator * tables;
    OSDictionary         * dict;
    OSOrderedSet         * set;
    OSArray              * arrayCopy;

    if ( !matching )
        return false;

    set = OSOrderedSet::withCapacity(10,
                                     IOServiceOrdering,
                                     (void *)gIOProbeScoreKey);
    if ( !set )
        return false;

    arrayCopy = OSArray::withCapacity(100);
    if ( !arrayCopy ) {
        set->release();
        return false;
    }

    tables = OSCollectionIterator::withCollection(arrayCopy);
    arrayCopy->release();
    if ( !tables ) {
        set->release();
        return false;
    }

    UniqueProperties( matching );

    IOLockLock(lock);
    kernelTables->reset();
    arrayCopy->merge(array);
    array->flushCollection();
    tables->reset();
    while ( (dict = (OSDictionary *)tables->getNextObject()) ) {

        /* This comparison must be done with only the keys in the
         * "matching" dict to enable general searches.
         */
        if ( dict->isEqualTo(matching, matching) ) {
            AddNewImports( set, dict );
            continue;
        }

        array->setObject(dict);
    }
    // Start device matching.
    if ( doNubMatching && (set->getCount() > 0) ) {
        IOService::catalogNewDrivers(set);
        generation++;
    }
    IOLockUnlock(lock);

    set->release();
    tables->release();

    return true;
}
コード例 #4
0
ファイル: IOCatalogue.cpp プロジェクト: Prajna/xnu
bool IOCatalogue::resetAndAddDrivers(OSArray * drivers, bool doNubMatching)
{
    bool                   result              = false;
    OSArray              * newPersonalities    = NULL;  // do not release
    OSCollectionIterator * newPIterator        = NULL;  // must release
    OSOrderedSet         * matchSet            = NULL;  // must release
    OSArray              * oldPersonalities    = NULL;  // must release
    OSArray              * kernelPersonalities = NULL;  // must release
    OSString             * errorString         = NULL;  // must release
    OSObject             * object              = NULL;  // do not release
    OSDictionary         * thisNewPersonality  = NULL;  // do not release
    signed int             count, i;

    extern const char    * gIOKernelConfigTables;

    if (drivers) {
        newPersonalities = OSDynamicCast(OSArray, drivers);
        if (!newPersonalities) {
            goto finish;
        }

        newPIterator = OSCollectionIterator::withCollection(newPersonalities);
        if (!newPIterator) {
            goto finish;
        }
        
        matchSet = OSOrderedSet::withCapacity(10, IOServiceOrdering,
            (void *)gIOProbeScoreKey);
        if (!matchSet) {
            goto finish;
        }
    }

   /* Read personalities for the built-in kernel driver classes.
    * We don't have many any more.
    */
    kernelPersonalities = OSDynamicCast(OSArray,
        OSUnserialize(gIOKernelConfigTables, &errorString));
    if (!kernelPersonalities && errorString) {
        IOLog("KernelConfigTables syntax error: %s\n",
            errorString->getCStringNoCopy());
        goto finish;
    }
    
   /* Now copy the current array of personalities so we can reuse them
    * if the new list contains any duplicates. This saves on memory
    * consumption.
    */
    oldPersonalities = OSDynamicCast(OSArray, array->copyCollection());
    if (!oldPersonalities) {
        goto finish;
    }

    result = true;

    IOLog("Resetting IOCatalogue.\n");
    
   /* No goto finish from here to unlock.
    */
    IOLockLock(lock);
    
    array->flushCollection();

   /* Add back the kernel personalities and remove them from the old
    * array so we don't try to match on them again. Go forward through
    * the arrays as this causes the least iteration since kernel personalities
    * should always be first.
    */
    count = kernelPersonalities->getCount();
    for (i = 0; i < count; i++) {
    
       /* Static cast here, as the data is coming from within the kernel image.
        */
        OSDictionary * thisNewPersonality = (OSDictionary *)
            kernelPersonalities->getObject(i);
        array->setObject(thisNewPersonality);

        signed int oldPCount = oldPersonalities->getCount();
        for (signed int oldPIndex = 0; oldPIndex < oldPCount; oldPIndex++) {
            if (thisNewPersonality->isEqualTo(oldPersonalities->getObject(oldPIndex))) {
                oldPersonalities->removeObject(oldPIndex);
                break;
            }
        }
    }

   /* Now add the new set of personalities passed in, using existing
    * copies if we had them in kernel memory already.
    */
    if (newPIterator) {
        OSDictionary * thisOldPersonality = NULL;  // do not release
        
        while ( (object = newPIterator->getNextObject()) ) {

            thisNewPersonality = OSDynamicCast(OSDictionary, object);
            if (!thisNewPersonality) {
                IOLog("IOCatalogue::resetAndAddDrivers() encountered non-dictionary; bailing.\n");
            result = false;
            break;
            }

           /* Convert common OSString property values to OSSymbols.
            */
            OSKext::uniquePersonalityProperties(thisNewPersonality);
            
           /* Add driver personality to catalogue, but if we had a copy already
            * use that instead so we don't have multiple copies from OSKext instances.
            */
            count = oldPersonalities->getCount();
            thisOldPersonality = NULL;
            while (count--) {
                
                thisOldPersonality = (OSDictionary *)oldPersonalities->getObject(count);
                
               /* Unlike in other functions, this comparison must be exact!
                * The catalogue must be able to contain personalities that
                * are proper supersets of others.
                * Do not compare just the properties present in one driver
                * pesonality or the other.
                */
                if (thisNewPersonality->isEqualTo(thisOldPersonality)) {
                    break;
                }
            }

           /* If we found a dup, add the *original* back to the catalogue,
            * remove it from our bookkeeping list, and continue.
            * Don't worry about matching on personalities we already had.
            */
            if (count >= 0) {
                array->setObject(thisOldPersonality);
                oldPersonalities->removeObject(count);
                continue;
            }

           /* Otherwise add the new personality and mark it for matching.
            */
            array->setObject(thisNewPersonality);
            AddNewImports(matchSet, thisNewPersonality);                
        }

       /*****
        * Now, go through remaining old personalities, which have effectively
        * been removed, and add them to the match set as necessary.
        */
        count = oldPersonalities->getCount();
        while (count--) {
        
           /* Static cast here is ok as these dictionaries were already in the catalogue.
            */
            thisOldPersonality = (OSDictionary *)oldPersonalities->getObject(count);
            AddNewImports(matchSet, thisOldPersonality);
        }

       /* Finally, start device matching on all new & removed personalities.
        */
        if (result && doNubMatching && (matchSet->getCount() > 0)) {
            IOService::catalogNewDrivers(matchSet);
            generation++;
        }
    }

    IOLockUnlock(lock);

finish:
    if (newPIterator) newPIterator->release();
    if (matchSet) matchSet->release();
    if (oldPersonalities) oldPersonalities->release();
    if (kernelPersonalities) kernelPersonalities->release();
    if (errorString) errorString->release();

    return result;
}