+ 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);
+ }
+ }