/********************************************************************* * Remove drivers from the catalog which match the * properties in the matching dictionary. *********************************************************************/ bool IOCatalogue::removeDrivers( OSDictionary * matching, bool doNubMatching) { OSOrderedSet * set; OSCollectionIterator * iter; OSDictionary * dict; OSArray * array; const OSSymbol * key; unsigned int idx; if ( !matching ) return false; set = OSOrderedSet::withCapacity(10, IOServiceOrdering, (void *)gIOProbeScoreKey); if ( !set ) return false; iter = OSCollectionIterator::withCollection(personalities); if (!iter) { set->release(); return (false); } IORWLockWrite(lock); while ((key = (const OSSymbol *) iter->getNextObject())) { array = (OSArray *) personalities->getObject(key); if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) { /* This comparison must be done with only the keys in the * "matching" dict to enable general searches. */ if ( dict->isEqualTo(matching, matching) ) { set->setObject(dict); array->removeObject(idx); idx--; } } // Start device matching. if ( doNubMatching && (set->getCount() > 0) ) { IOService::catalogNewDrivers(set); generation++; } } IORWLockUnlock(lock); set->release(); iter->release(); return true; }
void IOPrintPlane( const IORegistryPlane * plane ) { IORegistryEntry * next; IORegistryIterator * iter; OSOrderedSet * all; char format[] = "%xxxs"; IOService * service; iter = IORegistryIterator::iterateOver( plane ); assert( iter ); all = iter->iterateAll(); if( all) { DEBG("Count %d\n", all->getCount() ); all->release(); } else DEBG("Empty\n"); iter->reset(); while( (next = iter->getNextObjectRecursive())) { snprintf(format + 1, sizeof(format) - 1, "%ds", 2 * next->getDepth( plane )); DEBG( format, ""); DEBG( "\033[33m%s", next->getName( plane )); if( (next->getLocation( plane ))) DEBG("@%s", next->getLocation( plane )); DEBG("\033[0m <class %s", next->getMetaClass()->getClassName()); if( (service = OSDynamicCast(IOService, next))) DEBG(", busy %ld", (long) service->getBusyState()); DEBG( ">\n"); // IOSleep(250); } iter->release(); }
void db_dumpiojunk( const IORegistryPlane * plane ) { IORegistryEntry * next; IORegistryIterator * iter; OSOrderedSet * all; char format[] = "%xxxs"; IOService * service; iter = IORegistryIterator::iterateOver( plane ); all = iter->iterateAll(); if( all) { dbugprintf("Count %d\n", all->getCount() ); all->release(); } else dbugprintf("Empty\n"); iter->reset(); while( (next = iter->getNextObjectRecursive())) { snprintf(format + 1, sizeof(format) - 1, "%ds", 2 * next->getDepth( plane )); dbugprintf( format, ""); dbugprintf( "%s", next->getName( plane )); if( (next->getLocation( plane ))) dbugprintf("@%s", next->getLocation( plane )); dbugprintf(" <class %s", next->getMetaClass()->getClassName()); if( (service = OSDynamicCast(IOService, next))) dbugprintf(", busy %ld", service->getBusyState()); dbugprintf( ">\n"); } iter->release(); }
OSCollection * OSOrderedSet::copyCollection(OSDictionary *cycleDict) { bool allocDict = !cycleDict; OSCollection *ret = 0; OSOrderedSet *newSet = 0; if (allocDict) { cycleDict = OSDictionary::withCapacity(16); if (!cycleDict) return 0; } do { // Check for a cycle ret = super::copyCollection(cycleDict); if (ret) continue; // Duplicate the set with no contents newSet = OSOrderedSet::withCapacity(capacity, ordering, orderingRef); if (!newSet) continue; // Insert object into cycle Dictionary cycleDict->setObject((const OSSymbol *) this, newSet); newSet->capacityIncrement = capacityIncrement; // Now copy over the contents to the new duplicate for (unsigned int i = 0; i < count; i++) { OSObject *obj = EXT_CAST(array[i].obj); OSCollection *coll = OSDynamicCast(OSCollection, obj); if (coll) { OSCollection *newColl = coll->copyCollection(cycleDict); if (newColl) { obj = newColl; // Rely on cycleDict ref for a bit newColl->release(); } else goto abortCopy; }; newSet->setLastObject(obj); }; ret = newSet; newSet = 0; } while (false); abortCopy: if (newSet) newSet->release(); if (allocDict) cycleDict->release(); return ret; }
OSOrderedSet * OSOrderedSet:: withCapacity(unsigned int capacity, OSOrderFunction ordering, void * orderingRef) { OSOrderedSet *me = new OSOrderedSet; if (me && !me->initWithCapacity(capacity, ordering, orderingRef)) { me->release(); me = 0; } return me; }
/********************************************************************* * Is personality already in the catalog? *********************************************************************/ OSOrderedSet * IOCatalogue::findDrivers( OSDictionary * matching, SInt32 * generationCount) { OSCollectionIterator * iter; OSDictionary * dict; OSOrderedSet * set; OSArray * array; const OSSymbol * key; unsigned int idx; OSKext::uniquePersonalityProperties(matching); set = OSOrderedSet::withCapacity( 1, IOServiceOrdering, (void *)gIOProbeScoreKey ); if (!set) return (0); iter = OSCollectionIterator::withCollection(personalities); if (!iter) { set->release(); return (0); } IORWLockRead(lock); while ((key = (const OSSymbol *) iter->getNextObject())) { array = (OSArray *) personalities->getObject(key); if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++) { /* This comparison must be done with only the keys in the * "matching" dict to enable general searches. */ if ( dict->isEqualTo(matching, matching) ) set->setObject(dict); } } *generationCount = getGenerationCount(); IORWLockUnlock(lock); iter->release(); return set; }
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; }
/********************************************************************* * 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; }
/********************************************************************* * 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; }
bool IOCatalogue::resetAndAddDrivers(OSArray * drivers, bool doNubMatching) { bool result = false; OSArray * newPersonalities = NULL; // do not release OSCollectionIterator * iter = NULL; // must release OSOrderedSet * matchSet = NULL; // must release const OSSymbol * key; OSArray * array; OSDictionary * thisNewPersonality = NULL; // do not release OSDictionary * thisOldPersonality = NULL; // do not release signed int idx, newIdx; if (drivers) { newPersonalities = OSDynamicCast(OSArray, drivers); if (!newPersonalities) { goto finish; } matchSet = OSOrderedSet::withCapacity(10, IOServiceOrdering, (void *)gIOProbeScoreKey); if (!matchSet) { goto finish; } iter = OSCollectionIterator::withCollection(personalities); if (!iter) { goto finish; } } result = true; IOLog("Resetting IOCatalogue.\n"); /* No goto finish from here to unlock. */ IORWLockWrite(lock); while ((key = (const OSSymbol *) iter->getNextObject())) { array = (OSArray *) personalities->getObject(key); if (!array) continue; for (idx = 0; (thisOldPersonality = (OSDictionary *) array->getObject(idx)); idx++) { if (thisOldPersonality->getObject("KernelConfigTable")) continue; if (newPersonalities) for (newIdx = 0; (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx)); newIdx++) { /* 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 (thisNewPersonality) { // dup, ignore newPersonalities->removeObject(newIdx); } else { // not in new set - remove // only remove dictionary if this module in not loaded - 9953845 if ( isModuleLoaded(thisOldPersonality) == false ) { if (matchSet) matchSet->setObject(thisOldPersonality); array->removeObject(idx); idx--; } } } } // add new for (newIdx = 0; (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx)); newIdx++) { OSKext::uniquePersonalityProperties(thisNewPersonality); addPersonality(thisNewPersonality); matchSet->setObject(thisNewPersonality); } /* Finally, start device matching on all new & removed personalities. */ if (result && doNubMatching && (matchSet->getCount() > 0)) { IOService::catalogNewDrivers(matchSet); generation++; } IORWLockUnlock(lock); finish: if (matchSet) matchSet->release(); if (iter) iter->release(); return result; }
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; }