/*
- * Copyright (c) 1998-2006 Apple Inc. All rights reserved.
+ * Copyright (c) 1998-2012 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <libkern/c++/OSUnserialize.h>
#include <libkern/c++/OSKext.h>
#include <libkern/OSKextLibPrivate.h>
+#include <libkern/OSDebug.h>
#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/IOService.h>
/*********************************************************************
*********************************************************************/
-#define CATALOGTEST 0
-
IOCatalogue * gIOCatalogue;
const OSSymbol * gIOClassKey;
const OSSymbol * gIOProbeScoreKey;
const OSSymbol * gIOModuleIdentifierKey;
-IOLock * gIOCatalogLock;
+IORWLock * gIOCatalogLock;
#if PRAGMA_MARK
#pragma mark Utility functions
#endif
-/*********************************************************************
-*********************************************************************/
-static void
-UniqueProperties(OSDictionary * dict)
-{
- OSString * data;
-
- data = OSDynamicCast(OSString, dict->getObject(gIOClassKey));
- if (data) {
- const OSSymbol *classSymbol = OSSymbol::withString(data);
-
- dict->setObject( gIOClassKey, (OSSymbol *) classSymbol);
- classSymbol->release();
- }
-
- data = OSDynamicCast(OSString, dict->getObject(gIOMatchCategoryKey));
- if (data) {
- const OSSymbol *classSymbol = OSSymbol::withString(data);
-
- dict->setObject(gIOMatchCategoryKey, (OSSymbol *) classSymbol);
- classSymbol->release();
- }
- return;
-}
-
-/*********************************************************************
-* Add a new personality to the set if it has a unique IOResourceMatchKey value.
-* XXX -- svail: This should be optimized.
-* esb - There doesn't seem like any reason to do this - it causes problems
-* esb - when there are more than one loadable driver matching on the same provider class
-*********************************************************************/
-static void
-AddNewImports(OSOrderedSet * set, OSDictionary * dict)
-{
- set->setObject(dict);
-}
#if PRAGMA_MARK
#pragma mark IOCatalogue class implementation
#define super OSObject
OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
+static bool isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
+ OSDictionary *theModuleDict);
+
+
/*********************************************************************
*********************************************************************/
void IOCatalogue::initialize(void)
array->release();
}
+/*********************************************************************
+* Initialize the IOCatalog object.
+*********************************************************************/
+OSArray * IOCatalogue::arrayForPersonality(OSDictionary * dict)
+{
+ const OSSymbol * sym;
+
+ sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
+ if (!sym) return (0);
+
+ return ((OSArray *) personalities->getObject(sym));
+}
+
+void IOCatalogue::addPersonality(OSDictionary * dict)
+{
+ const OSSymbol * sym;
+ OSArray * arr;
+
+ sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
+ if (!sym) return;
+ arr = (OSArray *) personalities->getObject(sym);
+ if (arr) arr->setObject(dict);
+ else
+ {
+ arr = OSArray::withObjects((const OSObject **)&dict, 1, 2);
+ personalities->setObject(sym, arr);
+ arr->release();
+ }
+}
+
/*********************************************************************
* Initialize the IOCatalog object.
*********************************************************************/
bool IOCatalogue::init(OSArray * initArray)
{
OSDictionary * dict;
-
+ OSObject * obj;
+
if ( !super::init() )
return false;
generation = 1;
- array = initArray;
- array->retain();
- kernelTables = OSCollectionIterator::withCollection( array );
-
- gIOCatalogLock = IOLockAlloc();
-
- lock = gIOCatalogLock;
-#if __ppc__ || __i386__
- kld_lock = NULL;
-#endif /* __ppc__ || __i386__ */
-
- kernelTables->reset();
- while( (dict = (OSDictionary *) kernelTables->getNextObject())) {
- UniqueProperties(dict);
+ personalities = OSDictionary::withCapacity(32);
+ personalities->setOptions(OSCollection::kSort, OSCollection::kSort);
+ for (unsigned int idx = 0; (obj = initArray->getObject(idx)); idx++)
+ {
+ dict = OSDynamicCast(OSDictionary, obj);
+ if (!dict) continue;
+ OSKext::uniquePersonalityProperties(dict);
if( 0 == dict->getObject( gIOClassKey ))
+ {
IOLog("Missing or bad \"%s\" key\n",
gIOClassKey->getCStringNoCopy());
+ continue;
+ }
+ dict->setObject("KernelConfigTable", kOSBooleanTrue);
+ addPersonality(dict);
}
-#if CATALOGTEST
- AbsoluteTime deadline;
- clock_interval_to_deadline( 1000, kMillisecondScale );
- thread_call_func_delayed( ping, this, deadline );
-#endif
+ gIOCatalogLock = IORWLockAlloc();
+ lock = gIOCatalogLock;
return true;
}
*********************************************************************/
void IOCatalogue::free( void )
{
- if ( array )
- array->release();
-
- if ( kernelTables )
- kernelTables->release();
-
- super::free();
+ panic("");
}
-/*********************************************************************
-*********************************************************************/
-#if CATALOGTEST
-
-static int hackLimit;
-enum { kDriversPerIter = 4 };
-
-void
-IOCatalogue::ping(thread_call_param_t arg, thread_call_param_t)
-{
- IOCatalogue * self = (IOCatalogue *) arg;
- OSOrderedSet * set;
- OSDictionary * table;
- int newLimit;
-
- set = OSOrderedSet::withCapacity( 1 );
-
- IOLockLock( &self->lock );
-
- for( newLimit = 0; newLimit < kDriversPerIter; newLimit++) {
- table = (OSDictionary *) self->array->getObject(
- hackLimit + newLimit );
- if( table) {
- set->setLastObject( table );
-
- OSSymbol * sym = (OSSymbol *) table->getObject(gIOClassKey);
- kprintf("enabling %s\n", sym->getCStringNoCopy());
-
- } else {
- newLimit--;
- break;
- }
- }
-
- IOService::catalogNewDrivers( set );
-
- hackLimit += newLimit;
- self->generation++;
-
- IOLockUnlock( &self->lock );
-
- if( kDriversPerIter == newLimit) {
- AbsoluteTime deadline;
- clock_interval_to_deadline(500, kMillisecondScale);
- thread_call_func_delayed(ping, this, deadline);
- }
-}
-#endif
-
/*********************************************************************
*********************************************************************/
OSOrderedSet *
{
OSDictionary * nextTable;
OSOrderedSet * set;
- OSString * imports;
+ OSArray * array;
+ const OSMetaClass * meta;
+ unsigned int idx;
set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
(void *)gIOProbeScoreKey );
if( !set )
return( 0 );
- IOLockLock(lock);
- kernelTables->reset();
+ IORWLockRead(lock);
-#if CATALOGTEST
- int hackIndex = 0;
-#endif
- while( (nextTable = (OSDictionary *) kernelTables->getNextObject())) {
-#if CATALOGTEST
- if( hackIndex++ > hackLimit)
- break;
-#endif
- imports = OSDynamicCast( OSString,
- nextTable->getObject( gIOProviderClassKey ));
- if( imports && service->metaCast( imports ))
- set->setObject( nextTable );
+ meta = service->getMetaClass();
+ while (meta)
+ {
+ array = (OSArray *) personalities->getObject(meta->getClassNameSymbol());
+ if (array) for (idx = 0; (nextTable = (OSDictionary *) array->getObject(idx)); idx++)
+ {
+ set->setObject(nextTable);
+ }
+ if (meta == &IOService::gMetaClass) break;
+ meta = meta->getSuperClass();
}
*generationCount = getGenerationCount();
- IOLockUnlock(lock);
+ IORWLockUnlock(lock);
return( set );
}
OSDictionary * matching,
SInt32 * generationCount)
{
+ OSCollectionIterator * iter;
OSDictionary * dict;
OSOrderedSet * set;
+ OSArray * array;
+ const OSSymbol * key;
+ unsigned int idx;
- UniqueProperties(matching);
+ OSKext::uniquePersonalityProperties(matching);
set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
(void *)gIOProbeScoreKey );
+ if (!set) return (0);
+ iter = OSCollectionIterator::withCollection(personalities);
+ if (!iter)
+ {
+ set->release();
+ return (0);
+ }
- 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 searches.
- */
- if ( dict->isEqualTo(matching, matching) )
- set->setObject(dict);
+ 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();
- IOLockUnlock(lock);
+ IORWLockUnlock(lock);
+ iter->release();
return set;
}
* 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
+ OSObject * object = NULL; // do not release
OSArray * persons = NULL; // do not release
-
+
persons = OSDynamicCast(OSArray, drivers);
if (!persons) {
goto finish;
goto finish;
}
+ /* Start with success; clear it on an error.
+ */
result = true;
- IOLockLock(lock);
- while ( (dict = (OSDictionary *) iter->getNextObject()) ) {
+ IORWLockWrite(lock);
+ while ( (object = iter->getNextObject()) ) {
// xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL
+ OSDictionary * personality = OSDynamicCast(OSDictionary, object);
+
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) {
+
+ if (!personality) {
+ IOLog("IOCatalogue::addDrivers() encountered non-dictionary; bailing.\n");
+ result = false;
break;
}
-
- AddNewImports(set, dict);
+
+ OSKext::uniquePersonalityProperties(personality);
+
+ // Add driver personality to catalogue.
+
+ OSArray * array = arrayForPersonality(personality);
+ if (!array) addPersonality(personality);
+ else
+ {
+ 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
+ * personality or the other.
+ */
+ if (personality->isEqualTo(driver)) {
+ break;
+ }
+ }
+ if (count >= 0) {
+ // its a dup
+ continue;
+ }
+ result = array->setObject(personality);
+ if (!result) {
+ break;
+ }
+ }
+
+ set->setObject(personality);
}
// Start device matching.
- if (doNubMatching && (set->getCount() > 0)) {
+ if (result && doNubMatching && (set->getCount() > 0)) {
IOService::catalogNewDrivers(set);
generation++;
}
- IOLockUnlock(lock);
+ IORWLockUnlock(lock);
finish:
if (set) set->release();
OSDictionary * matching,
bool doNubMatching)
{
- OSCollectionIterator * tables;
- OSDictionary * dict;
OSOrderedSet * set;
- OSArray * arrayCopy;
+ 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;
-
- arrayCopy = OSArray::withCapacity(100);
- if ( !arrayCopy ) {
- set->release();
- return false;
- }
-
- tables = OSCollectionIterator::withCollection(arrayCopy);
- arrayCopy->release();
- if ( !tables ) {
- set->release();
- return false;
+ iter = OSCollectionIterator::withCollection(personalities);
+ if (!iter)
+ {
+ 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;
+ 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++;
}
-
- array->setObject(dict);
- }
- // Start device matching.
- if ( doNubMatching && (set->getCount() > 0) ) {
- IOService::catalogNewDrivers(set);
- generation++;
}
- IOLockUnlock(lock);
-
+ IORWLockUnlock(lock);
+
set->release();
- tables->release();
+ iter->release();
return true;
}
return OSKext::removeKextWithIdentifier(moduleName->getCStringNoCopy());
}
-static IOReturn _terminateDrivers(OSDictionary * matching)
+IOReturn IOCatalogue::_terminateDrivers(OSDictionary * matching)
{
OSDictionary * dict;
OSIterator * iter;
if ( !iter )
return kIOReturnNoMemory;
- UniqueProperties( matching );
+ OSKext::uniquePersonalityProperties( matching );
// terminate instances.
do {
return ret;
}
-static IOReturn _removeDrivers( OSArray * array, OSDictionary * matching )
+IOReturn IOCatalogue::_removeDrivers(OSDictionary * matching)
{
- OSCollectionIterator * tables;
- OSDictionary * dict;
- OSArray * arrayCopy;
IOReturn ret = kIOReturnSuccess;
+ OSCollectionIterator * iter;
+ OSDictionary * dict;
+ OSArray * array;
+ const OSSymbol * key;
+ unsigned int idx;
// remove configs from catalog.
- arrayCopy = OSArray::withCapacity(100);
- if ( !arrayCopy )
- return kIOReturnNoMemory;
-
- tables = OSCollectionIterator::withCollection(arrayCopy);
- arrayCopy->release();
- if ( !tables )
- return kIOReturnNoMemory;
-
- arrayCopy->merge(array);
- array->flushCollection();
- tables->reset();
- while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
-
- /* Remove from the catalogue's array any personalities
- * that match the matching dictionary.
- * This comparison must be done with only the keys in the
- * "matching" dict to enable general matching.
- */
- if ( dict->isEqualTo(matching, matching) )
- continue;
-
- array->setObject(dict);
- }
-
- tables->release();
-
- return ret;
-}
-
-bool IOCatalogue::removePersonalities(OSArray * personalitiesToRemove)
-{
- bool result = true;
- OSArray * arrayCopy = NULL; // do not release
- OSCollectionIterator * iterator = NULL; // must release
- OSDictionary * personality = NULL; // do not release
- OSDictionary * checkPersonality = NULL; // do not release
- unsigned int count, i;
-
- // remove configs from catalog.
-
- arrayCopy = OSArray::withArray(array);
- if (!arrayCopy) {
- result = false;
- goto finish;
- }
-
- iterator = OSCollectionIterator::withCollection(arrayCopy);
- arrayCopy->release();
- if (!iterator) {
- result = false;
- goto finish;
- }
-
- array->flushCollection();
-
- count = personalitiesToRemove->getCount();
-
- /* Go through the old catalog's list of personalities and add back any that
- * are *not* found in 'personalitiesToRemove'.
- */
- while ((personality = (OSDictionary *)iterator->getNextObject())) {
- bool found = false;
-
- for (i = 0; i < count; i++) {
- checkPersonality = OSDynamicCast(OSDictionary,
- personalitiesToRemove->getObject(i));
+ iter = OSCollectionIterator::withCollection(personalities);
+ if (!iter) return (kIOReturnNoMemory);
- /* Do isEqualTo() with the single-arg version to make an exact
- * comparison (unlike _removeDrivers() above).
- */
- if (personality->isEqualTo(checkPersonality)) {
- found = true;
- break;
+ while ((key = (const OSSymbol *) iter->getNextObject()))
+ {
+ array = (OSArray *) personalities->getObject(key);
+ if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++)
+ {
+
+ /* Remove from the catalogue's array any personalities
+ * that match the matching dictionary.
+ * This comparison must be done with only the keys in the
+ * "matching" dict to enable general matching.
+ */
+ if (dict->isEqualTo(matching, matching))
+ {
+ array->removeObject(idx);
+ idx--;
}
}
-
- if (!found) {
- array->setObject(personality);
- }
}
+ iter->release();
-finish:
-
- OSSafeRelease(iterator);
- return result;
+ return ret;
}
IOReturn IOCatalogue::terminateDrivers(OSDictionary * matching)
IOReturn ret;
ret = _terminateDrivers(matching);
- IOLockLock(lock);
+ IORWLockWrite(lock);
if (kIOReturnSuccess == ret)
- ret = _removeDrivers(array, matching);
- kernelTables->reset();
- IOLockUnlock(lock);
+ ret = _removeDrivers(matching);
+ IORWLockUnlock(lock);
return ret;
}
/* No goto between IOLock calls!
*/
- IOLockLock(lock);
+ IORWLockWrite(lock);
if (kIOReturnSuccess == ret) {
- ret = _removeDrivers(array, dict);
+ ret = _removeDrivers(dict);
}
- kernelTables->reset();
// Unload the module itself.
if (unload && isLoaded && ret == kIOReturnSuccess) {
ret = unloadModule(moduleName);
}
- IOLockUnlock(lock);
+ IORWLockUnlock(lock);
dict->release();
bool IOCatalogue::startMatching( OSDictionary * matching )
{
+ OSCollectionIterator * iter;
OSDictionary * dict;
OSOrderedSet * set;
+ OSArray * array;
+ const OSSymbol * key;
+ unsigned int idx;
if ( !matching )
return false;
if ( !set )
return false;
- IOLockLock(lock);
- kernelTables->reset();
+ iter = OSCollectionIterator::withCollection(personalities);
+ if (!iter)
+ {
+ set->release();
+ return false;
+ }
- while ( (dict = (OSDictionary *)kernelTables->getNextObject()) ) {
+ IORWLockRead(lock);
- /* 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);
+ 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 matching.
+ */
+ if (dict->isEqualTo(matching, matching)) {
+ set->setObject(dict);
+ }
+ }
}
+
// Start device matching.
if ( set->getCount() > 0 ) {
IOService::catalogNewDrivers(set);
generation++;
}
- IOLockUnlock(lock);
+ IORWLockUnlock(lock);
set->release();
+ iter->release();
return true;
}
void IOCatalogue::reset(void)
{
+ IOCatalogue::resetAndAddDrivers(/* no drivers; true reset */ NULL,
+ /* doMatching */ false);
+ return;
+}
+
+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
+ OSDictionary * myKexts = NULL; // must 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;
+ }
+
+ /* need copy of loaded kexts so we can check if for loaded modules without
+ * taking the OSKext lock. There is a potential of deadlocking if we get
+ * an OSKext via the normal path. See 14672140.
+ */
+ myKexts = OSKext::copyKexts();
+
+ 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;
+ thisNewPersonality = NULL;
+
+ 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
+ * personality or the other.
+ */
+ if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) {
+ /* skip thisNewPersonality if it is not an OSDictionary */
+ continue;
+ }
+ 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 ( isModuleLoadedNoOSKextLock(myKexts, thisOldPersonality) == false ) {
+ if (matchSet) {
+ matchSet->setObject(thisOldPersonality);
+ }
+ array->removeObject(idx);
+ idx--;
+ }
+ }
+ } // for...
+ } // while...
+
+ // add new
+ if (newPersonalities) {
+ for (newIdx = 0;
+ (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx));
+ newIdx++)
+ {
+ if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) {
+ /* skip thisNewPersonality if it is not an OSDictionary */
+ continue;
+ }
+
+ 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();
+ if (myKexts) myKexts->release();
+
+ return result;
}
bool IOCatalogue::serialize(OSSerialize * s) const
switch ( kind )
{
case kIOCatalogGetContents:
- if (!array->serialize(s))
- kr = kIOReturnNoMemory;
+ kr = KERN_NOT_SUPPORTED;
break;
case kIOCatalogGetModuleDemandList:
return kr;
}
+/* isModuleLoadedNoOSKextLock - used to check to see if a kext is loaded
+ * without taking the OSKext lock. We use this to avoid the problem
+ * where taking the IOCatalog lock then the OSKext lock will dealock when
+ * a kext load or unload is happening at the same time as IOCatalog changing.
+ *
+ * theKexts - is a dictionary of current kexts (from OSKext::copyKexts) with
+ * key set to the kext bundle ID and value set to an OSKext object
+ * theModuleDict - is an IOKit personality dictionary for a given module (kext)
+ */
+static bool isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
+ OSDictionary *theModuleDict)
+{
+ bool myResult = false;
+ const OSString * myBundleID = NULL; // do not release
+ OSKext * myKext = NULL; // do not release
+
+ if (theKexts == NULL || theModuleDict == NULL) {
+ return( myResult );
+ }
+
+ // gIOModuleIdentifierKey is "CFBundleIdentifier"
+ myBundleID = OSDynamicCast(OSString,
+ theModuleDict->getObject(gIOModuleIdentifierKey));
+ if (myBundleID == NULL) {
+ return( myResult );
+ }
+
+ myKext = OSDynamicCast(OSKext, theKexts->getObject(myBundleID->getCStringNoCopy()));
+ if (myKext) {
+ myResult = myKext->isLoaded();
+ }
+
+ return( myResult );
+}
+
#if PRAGMA_MARK
#pragma mark Obsolete Kext Loading Stuff
**********************************************************************
**********************************************************************
* These functions are no longer used are necessary for C++ binary
-* compatibility on ppc/i386.
+* compatibility on i386.
**********************************************************************/
-#if __ppc__ || __i386__
-
-bool IOCatalogue::recordStartupExtensions(void)
-{ return false; }
-
-bool IOCatalogue::addExtensionsFromArchive(OSData * mkext)
-{ return KERN_NOT_SUPPORTED; }
-
-kern_return_t IOCatalogue::removeKernelLinker(void)
-{ return KERN_NOT_SUPPORTED; }
-
-#endif /* __ppc__ || __i386__ */