1/*
2 * Copyright (c) 1998-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * Copyright (c) 1998 Apple Inc.  All rights reserved.
30 *
31 * HISTORY
32 *
33 */
34/*
35 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
36 * support for mandatory and extensible security protections.  This notice
37 * is included in support of clause 2.2 (b) of the Apple Public License,
38 * Version 2.0.
39 */
40
41extern "C" {
42#include <machine/machine_routines.h>
43#include <libkern/kernel_mach_header.h>
44#include <kern/host.h>
45#include <security/mac_data.h>
46};
47
48#include <libkern/c++/OSContainers.h>
49#include <libkern/c++/OSUnserialize.h>
50#include <libkern/c++/OSKext.h>
51#include <libkern/OSKextLibPrivate.h>
52#include <libkern/OSDebug.h>
53
54#include <IOKit/IODeviceTreeSupport.h>
55#include <IOKit/IOService.h>
56#include <IOKit/IOCatalogue.h>
57
58#include <IOKit/IOLib.h>
59#include <IOKit/assert.h>
60
61#if PRAGMA_MARK
62#pragma mark Internal Declarations
63#endif
64/*********************************************************************
65*********************************************************************/
66
67IOCatalogue    * gIOCatalogue;
68const OSSymbol * gIOClassKey;
69const OSSymbol * gIOProbeScoreKey;
70const OSSymbol * gIOModuleIdentifierKey;
71IORWLock         * gIOCatalogLock;
72
73#if PRAGMA_MARK
74#pragma mark Utility functions
75#endif
76
77#if PRAGMA_MARK
78#pragma mark IOCatalogue class implementation
79#endif
80/*********************************************************************
81*********************************************************************/
82
83#define super OSObject
84OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
85
86static bool isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
87                                       OSDictionary *theModuleDict);
88
89
90/*********************************************************************
91*********************************************************************/
92void IOCatalogue::initialize(void)
93{
94    OSArray              * array;
95    OSString             * errorString;
96    bool		   rc;
97
98    extern const char * gIOKernelConfigTables;
99
100    array = OSDynamicCast(OSArray, OSUnserialize(gIOKernelConfigTables, &errorString));
101    if (!array && errorString) {
102        IOLog("KernelConfigTables syntax error: %s\n",
103            errorString->getCStringNoCopy());
104        errorString->release();
105    }
106
107    gIOClassKey              = OSSymbol::withCStringNoCopy( kIOClassKey );
108    gIOProbeScoreKey 	     = OSSymbol::withCStringNoCopy( kIOProbeScoreKey );
109    gIOModuleIdentifierKey   = OSSymbol::withCStringNoCopy( kCFBundleIdentifierKey );
110
111    assert( array && gIOClassKey && gIOProbeScoreKey
112	    && gIOModuleIdentifierKey);
113
114    gIOCatalogue = new IOCatalogue;
115    assert(gIOCatalogue);
116    rc = gIOCatalogue->init(array);
117    assert(rc);
118    array->release();
119}
120
121/*********************************************************************
122* Initialize the IOCatalog object.
123*********************************************************************/
124OSArray * IOCatalogue::arrayForPersonality(OSDictionary * dict)
125{
126    const OSSymbol * sym;
127
128    sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
129    if (!sym) 	return (0);
130
131    return ((OSArray *) personalities->getObject(sym));
132}
133
134void IOCatalogue::addPersonality(OSDictionary * dict)
135{
136    const OSSymbol * sym;
137    OSArray * arr;
138
139    sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
140    if (!sym) return;
141    arr = (OSArray *) personalities->getObject(sym);
142    if (arr) arr->setObject(dict);
143    else
144    {
145        arr = OSArray::withObjects((const OSObject **)&dict, 1, 2);
146        personalities->setObject(sym, arr);
147        arr->release();
148    }
149}
150
151/*********************************************************************
152* Initialize the IOCatalog object.
153*********************************************************************/
154bool IOCatalogue::init(OSArray * initArray)
155{
156    OSDictionary         * dict;
157    OSObject * obj;
158
159    if ( !super::init() )
160        return false;
161
162    generation = 1;
163
164    personalities = OSDictionary::withCapacity(32);
165    personalities->setOptions(OSCollection::kSort, OSCollection::kSort);
166    for (unsigned int idx = 0; (obj = initArray->getObject(idx)); idx++)
167    {
168	dict = OSDynamicCast(OSDictionary, obj);
169	if (!dict) continue;
170	OSKext::uniquePersonalityProperties(dict);
171        if( 0 == dict->getObject( gIOClassKey ))
172        {
173            IOLog("Missing or bad \"%s\" key\n",
174                    gIOClassKey->getCStringNoCopy());
175	    continue;
176	}
177	dict->setObject("KernelConfigTable", kOSBooleanTrue);
178        addPersonality(dict);
179    }
180
181    gIOCatalogLock = IORWLockAlloc();
182    lock = gIOCatalogLock;
183
184    return true;
185}
186
187/*********************************************************************
188* Release all resources used by IOCatalogue and deallocate.
189* This will probably never be called.
190*********************************************************************/
191void IOCatalogue::free( void )
192{
193    panic("");
194}
195
196/*********************************************************************
197*********************************************************************/
198OSOrderedSet *
199IOCatalogue::findDrivers(
200    IOService * service,
201    SInt32 * generationCount)
202{
203    OSDictionary         * nextTable;
204    OSOrderedSet         * set;
205    OSArray              * array;
206    const OSMetaClass    * meta;
207    unsigned int           idx;
208
209    set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
210                                      (void *)gIOProbeScoreKey );
211    if( !set )
212	return( 0 );
213
214    IORWLockRead(lock);
215
216    meta = service->getMetaClass();
217    while (meta)
218    {
219    	array = (OSArray *) personalities->getObject(meta->getClassNameSymbol());
220	if (array) for (idx = 0; (nextTable = (OSDictionary *) array->getObject(idx)); idx++)
221	{
222            set->setObject(nextTable);
223	}
224	if (meta == &IOService::gMetaClass) break;
225	meta = meta->getSuperClass();
226    }
227
228    *generationCount = getGenerationCount();
229
230    IORWLockUnlock(lock);
231
232    return( set );
233}
234
235/*********************************************************************
236* Is personality already in the catalog?
237*********************************************************************/
238OSOrderedSet *
239IOCatalogue::findDrivers(
240    OSDictionary * matching,
241    SInt32 * generationCount)
242{
243    OSCollectionIterator * iter;
244    OSDictionary         * dict;
245    OSOrderedSet         * set;
246    OSArray              * array;
247    const OSSymbol       * key;
248    unsigned int           idx;
249
250    OSKext::uniquePersonalityProperties(matching);
251
252    set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
253                                      (void *)gIOProbeScoreKey );
254    if (!set) return (0);
255    iter = OSCollectionIterator::withCollection(personalities);
256    if (!iter)
257    {
258    	set->release();
259    	return (0);
260    }
261
262    IORWLockRead(lock);
263    while ((key = (const OSSymbol *) iter->getNextObject()))
264    {
265        array = (OSArray *) personalities->getObject(key);
266        if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++)
267        {
268	   /* This comparison must be done with only the keys in the
269	    * "matching" dict to enable general searches.
270	    */
271	    if ( dict->isEqualTo(matching, matching) )
272		set->setObject(dict);
273	}
274    }
275    *generationCount = getGenerationCount();
276    IORWLockUnlock(lock);
277
278    iter->release();
279    return set;
280}
281
282/*********************************************************************
283* Add driver config tables to catalog and start matching process.
284*
285* Important that existing personalities are kept (not replaced)
286* if duplicates found. Personalities can come from OSKext objects
287* or from userland kext library. We want to minimize distinct
288* copies between OSKext & IOCatalogue.
289*
290* xxx - userlib used to refuse to send personalities with IOKitDebug
291* xxx - during safe boot. That would be better implemented here.
292*********************************************************************/
293
294bool IOCatalogue::addDrivers(
295    OSArray * drivers,
296    bool doNubMatching)
297{
298    bool                   result = false;
299    OSCollectionIterator * iter = NULL;       // must release
300    OSOrderedSet         * set = NULL;        // must release
301    OSObject             * object = NULL;       // do not release
302    OSArray              * persons = NULL;    // do not release
303
304    persons = OSDynamicCast(OSArray, drivers);
305    if (!persons) {
306        goto finish;
307    }
308
309    set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
310        (void *)gIOProbeScoreKey );
311    if (!set) {
312        goto finish;
313    }
314
315    iter = OSCollectionIterator::withCollection(persons);
316    if (!iter) {
317        goto finish;
318    }
319
320   /* Start with success; clear it on an error.
321    */
322    result = true;
323
324    IORWLockWrite(lock);
325    while ( (object = iter->getNextObject()) ) {
326
327        // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL
328
329        OSDictionary * personality = OSDynamicCast(OSDictionary, object);
330
331        SInt count;
332
333        if (!personality) {
334            IOLog("IOCatalogue::addDrivers() encountered non-dictionary; bailing.\n");
335            result = false;
336            break;
337        }
338
339        OSKext::uniquePersonalityProperties(personality);
340
341        // Add driver personality to catalogue.
342
343	OSArray * array = arrayForPersonality(personality);
344	if (!array) addPersonality(personality);
345	else
346	{
347	    count = array->getCount();
348	    while (count--) {
349		OSDictionary * driver;
350
351		// Be sure not to double up on personalities.
352		driver = (OSDictionary *)array->getObject(count);
353
354	       /* Unlike in other functions, this comparison must be exact!
355		* The catalogue must be able to contain personalities that
356		* are proper supersets of others.
357		* Do not compare just the properties present in one driver
358		* personality or the other.
359		*/
360		if (personality->isEqualTo(driver)) {
361		    break;
362		}
363	    }
364	    if (count >= 0) {
365		// its a dup
366		continue;
367	    }
368	    result = array->setObject(personality);
369	    if (!result) {
370		break;
371	    }
372        }
373
374	set->setObject(personality);
375    }
376    // Start device matching.
377    if (result && doNubMatching && (set->getCount() > 0)) {
378        IOService::catalogNewDrivers(set);
379        generation++;
380    }
381    IORWLockUnlock(lock);
382
383finish:
384    if (set)  set->release();
385    if (iter) iter->release();
386
387    return result;
388}
389
390/*********************************************************************
391* Remove drivers from the catalog which match the
392* properties in the matching dictionary.
393*********************************************************************/
394bool
395IOCatalogue::removeDrivers(
396    OSDictionary * matching,
397    bool doNubMatching)
398{
399    OSOrderedSet         * set;
400    OSCollectionIterator * iter;
401    OSDictionary         * dict;
402    OSArray              * array;
403    const OSSymbol       * key;
404    unsigned int           idx;
405
406    if ( !matching )
407        return false;
408
409    set = OSOrderedSet::withCapacity(10,
410                                     IOServiceOrdering,
411                                     (void *)gIOProbeScoreKey);
412    if ( !set )
413        return false;
414    iter = OSCollectionIterator::withCollection(personalities);
415    if (!iter)
416    {
417    	set->release();
418    	return (false);
419    }
420
421    IORWLockWrite(lock);
422    while ((key = (const OSSymbol *) iter->getNextObject()))
423    {
424        array = (OSArray *) personalities->getObject(key);
425        if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++)
426        {
427           /* This comparison must be done with only the keys in the
428            * "matching" dict to enable general searches.
429            */
430            if ( dict->isEqualTo(matching, matching) ) {
431                set->setObject(dict);
432                array->removeObject(idx);
433                idx--;
434            }
435        }
436        // Start device matching.
437        if ( doNubMatching && (set->getCount() > 0) ) {
438            IOService::catalogNewDrivers(set);
439            generation++;
440        }
441    }
442    IORWLockUnlock(lock);
443
444    set->release();
445    iter->release();
446
447    return true;
448}
449
450// Return the generation count.
451SInt32 IOCatalogue::getGenerationCount(void) const
452{
453    return( generation );
454}
455
456bool IOCatalogue::isModuleLoaded(OSString * moduleName) const
457{
458    return isModuleLoaded(moduleName->getCStringNoCopy());
459}
460
461bool IOCatalogue::isModuleLoaded(const char * moduleName) const
462{
463    OSReturn ret;
464    ret = OSKext::loadKextWithIdentifier(moduleName);
465    if (kOSKextReturnDeferred == ret) {
466        // a request has been queued but the module isn't necessarily
467        // loaded yet, so stall.
468        return false;
469    }
470    // module is present or never will be
471    return true;
472}
473
474// Check to see if module has been loaded already.
475bool IOCatalogue::isModuleLoaded(OSDictionary * driver) const
476{
477    OSString             * moduleName = NULL;
478    OSString             * publisherName = NULL;
479
480    if ( !driver )
481        return false;
482
483    /* The personalities of codeless kexts often contain the bundle ID of the
484     * kext they reference, and not the bundle ID of the codeless kext itself.
485     * The prelinked kernel needs to know the bundle ID of the codeless kext
486     * so it can include these personalities, so OSKext stores that bundle ID
487     * in the IOPersonalityPublisher key, and we record it as requested here.
488     */
489    publisherName = OSDynamicCast(OSString,
490        driver->getObject(kIOPersonalityPublisherKey));
491    OSKext::recordIdentifierRequest(publisherName);
492
493    moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKey));
494    if ( moduleName )
495        return isModuleLoaded(moduleName);
496
497   /* If a personality doesn't hold the "CFBundleIdentifier" key
498    * it is assumed to be an "in-kernel" driver.
499    */
500    return true;
501}
502
503/* This function is called after a module has been loaded.
504 * Is invoked from user client call, ultimately from IOKitLib's
505 * IOCatalogueModuleLoaded(). Sent from kextd.
506 */
507void IOCatalogue::moduleHasLoaded(OSString * moduleName)
508{
509    OSDictionary * dict;
510
511    dict = OSDictionary::withCapacity(2);
512    dict->setObject(gIOModuleIdentifierKey, moduleName);
513    startMatching(dict);
514    dict->release();
515
516    (void) OSKext::setDeferredLoadSucceeded();
517    (void) OSKext::considerRebuildOfPrelinkedKernel();
518}
519
520void IOCatalogue::moduleHasLoaded(const char * moduleName)
521{
522    OSString * name;
523
524    name = OSString::withCString(moduleName);
525    moduleHasLoaded(name);
526    name->release();
527}
528
529// xxx - return is really OSReturn/kern_return_t
530IOReturn IOCatalogue::unloadModule(OSString * moduleName) const
531{
532    return OSKext::removeKextWithIdentifier(moduleName->getCStringNoCopy());
533}
534
535IOReturn IOCatalogue::_terminateDrivers(OSDictionary * matching)
536{
537    OSDictionary         * dict;
538    OSIterator           * iter;
539    IOService            * service;
540    IOReturn               ret;
541
542    if ( !matching )
543        return kIOReturnBadArgument;
544
545    ret = kIOReturnSuccess;
546    dict = 0;
547    iter = IORegistryIterator::iterateOver(gIOServicePlane,
548                                kIORegistryIterateRecursively);
549    if ( !iter )
550        return kIOReturnNoMemory;
551
552    OSKext::uniquePersonalityProperties( matching );
553
554    // terminate instances.
555    do {
556        iter->reset();
557        while( (service = (IOService *)iter->getNextObject()) ) {
558            dict = service->getPropertyTable();
559            if ( !dict )
560                continue;
561
562           /* Terminate only for personalities that match the matching dictionary.
563            * This comparison must be done with only the keys in the
564            * "matching" dict to enable general matching.
565            */
566            if ( !dict->isEqualTo(matching, matching) )
567                 continue;
568
569            if ( !service->terminate(kIOServiceRequired|kIOServiceSynchronous) ) {
570                ret = kIOReturnUnsupported;
571                break;
572            }
573        }
574    } while( !service && !iter->isValid());
575    iter->release();
576
577    return ret;
578}
579
580IOReturn IOCatalogue::_removeDrivers(OSDictionary * matching)
581{
582    IOReturn               ret = kIOReturnSuccess;
583    OSCollectionIterator * iter;
584    OSDictionary         * dict;
585    OSArray              * array;
586    const OSSymbol       * key;
587    unsigned int           idx;
588
589    // remove configs from catalog.
590
591    iter = OSCollectionIterator::withCollection(personalities);
592    if (!iter) return (kIOReturnNoMemory);
593
594    while ((key = (const OSSymbol *) iter->getNextObject()))
595    {
596        array = (OSArray *) personalities->getObject(key);
597        if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++)
598        {
599
600	    /* Remove from the catalogue's array any personalities
601	     * that match the matching dictionary.
602	     * This comparison must be done with only the keys in the
603	     * "matching" dict to enable general matching.
604	     */
605            if (dict->isEqualTo(matching, matching))
606            {
607                array->removeObject(idx);
608                idx--;
609            }
610        }
611    }
612    iter->release();
613
614    return ret;
615}
616
617IOReturn IOCatalogue::terminateDrivers(OSDictionary * matching)
618{
619    IOReturn ret;
620
621    ret = _terminateDrivers(matching);
622    IORWLockWrite(lock);
623    if (kIOReturnSuccess == ret)
624	ret = _removeDrivers(matching);
625    IORWLockUnlock(lock);
626
627    return ret;
628}
629
630IOReturn IOCatalogue::terminateDriversForModule(
631    OSString * moduleName,
632    bool unload)
633{
634    IOReturn ret;
635    OSDictionary * dict;
636    bool isLoaded = false;
637
638   /* Check first if the kext currently has any linkage dependents;
639    * in such a case the unload would fail so let's not terminate any
640    * IOServices (since doing so typically results in a panic when there
641    * are loaded dependencies). Note that we aren't locking the kext here
642    * so it might lose or gain dependents by the time we call unloadModule();
643    * I think that's ok, our unload can fail if a kext comes in on top of
644    * this one even after we've torn down IOService objects. Conversely,
645    * if we fail the unload here and then lose a library, the autounload
646    * thread will get us in short order.
647    */
648    if (OSKext::isKextWithIdentifierLoaded(moduleName->getCStringNoCopy())) {
649
650        isLoaded = true;
651
652        if (!OSKext::canUnloadKextWithIdentifier(moduleName,
653            /* checkClasses */ false)) {
654            ret = kOSKextReturnInUse;
655            goto finish;
656        }
657    }
658    dict = OSDictionary::withCapacity(1);
659    if (!dict) {
660        ret = kIOReturnNoMemory;
661        goto finish;
662    }
663
664    dict->setObject(gIOModuleIdentifierKey, moduleName);
665
666    ret = _terminateDrivers(dict);
667
668   /* No goto between IOLock calls!
669    */
670    IORWLockWrite(lock);
671    if (kIOReturnSuccess == ret) {
672        ret = _removeDrivers(dict);
673    }
674
675    // Unload the module itself.
676    if (unload && isLoaded && ret == kIOReturnSuccess) {
677        ret = unloadModule(moduleName);
678    }
679
680    IORWLockUnlock(lock);
681
682    dict->release();
683
684finish:
685    return ret;
686}
687
688IOReturn IOCatalogue::terminateDriversForModule(
689    const char * moduleName,
690    bool unload)
691{
692    OSString * name;
693    IOReturn ret;
694
695    name = OSString::withCString(moduleName);
696    if ( !name )
697        return kIOReturnNoMemory;
698
699    ret = terminateDriversForModule(name, unload);
700    name->release();
701
702    return ret;
703}
704
705bool IOCatalogue::startMatching( OSDictionary * matching )
706{
707    OSCollectionIterator * iter;
708    OSDictionary         * dict;
709    OSOrderedSet         * set;
710    OSArray              * array;
711    const OSSymbol *       key;
712    unsigned int           idx;
713
714    if ( !matching )
715        return false;
716
717    set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
718                                     (void *)gIOProbeScoreKey);
719    if ( !set )
720        return false;
721
722    iter = OSCollectionIterator::withCollection(personalities);
723    if (!iter)
724    {
725    	set->release();
726        return false;
727    }
728
729    IORWLockRead(lock);
730
731    while ((key = (const OSSymbol *) iter->getNextObject()))
732    {
733        array = (OSArray *) personalities->getObject(key);
734        if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++)
735        {
736	   /* This comparison must be done with only the keys in the
737	    * "matching" dict to enable general matching.
738	    */
739            if (dict->isEqualTo(matching, matching)) {
740                set->setObject(dict);
741            }
742        }
743    }
744
745    // Start device matching.
746    if ( set->getCount() > 0 ) {
747        IOService::catalogNewDrivers(set);
748        generation++;
749    }
750
751    IORWLockUnlock(lock);
752
753    set->release();
754    iter->release();
755
756    return true;
757}
758
759void IOCatalogue::reset(void)
760{
761    IOCatalogue::resetAndAddDrivers(/* no drivers; true reset */ NULL,
762        /* doMatching */ false);
763    return;
764}
765
766bool IOCatalogue::resetAndAddDrivers(OSArray * drivers, bool doNubMatching)
767{
768    bool                   result              = false;
769    OSArray              * newPersonalities    = NULL;  // do not release
770    OSCollectionIterator * iter                = NULL;  // must release
771    OSOrderedSet         * matchSet            = NULL;  // must release
772    const OSSymbol       * key;
773    OSArray              * array;
774    OSDictionary         * thisNewPersonality   = NULL; // do not release
775    OSDictionary         * thisOldPersonality   = NULL; // do not release
776    OSDictionary         * myKexts              = NULL; // must release
777    signed int             idx, newIdx;
778
779    if (drivers) {
780        newPersonalities = OSDynamicCast(OSArray, drivers);
781        if (!newPersonalities) {
782            goto finish;
783        }
784    }
785    matchSet = OSOrderedSet::withCapacity(10, IOServiceOrdering,
786        (void *)gIOProbeScoreKey);
787    if (!matchSet) {
788        goto finish;
789    }
790    iter = OSCollectionIterator::withCollection(personalities);
791    if (!iter) {
792        goto finish;
793    }
794
795    /* need copy of loaded kexts so we can check if for loaded modules without
796     * taking the OSKext lock.  There is a potential of deadlocking if we get
797     * an OSKext via the normal path.  See 14672140.
798     */
799    myKexts = OSKext::copyKexts();
800
801    result = true;
802
803    IOLog("Resetting IOCatalogue.\n");
804
805   /* No goto finish from here to unlock.
806    */
807    IORWLockWrite(lock);
808
809    while ((key = (const OSSymbol *) iter->getNextObject()))
810    {
811        array = (OSArray *) personalities->getObject(key);
812        if (!array) continue;
813
814        for (idx = 0;
815             (thisOldPersonality = (OSDictionary *) array->getObject(idx));
816             idx++)
817        {
818            if (thisOldPersonality->getObject("KernelConfigTable")) continue;
819            thisNewPersonality = NULL;
820
821            if (newPersonalities) {
822                for  (newIdx = 0;
823                      (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx));
824                      newIdx++)
825                {
826                    /* Unlike in other functions, this comparison must be exact!
827                     * The catalogue must be able to contain personalities that
828                     * are proper supersets of others.
829                     * Do not compare just the properties present in one driver
830                     * personality or the other.
831                     */
832                    if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) {
833                        /* skip thisNewPersonality if it is not an OSDictionary */
834                        continue;
835                    }
836                    if (thisNewPersonality->isEqualTo(thisOldPersonality))
837                        break;
838                }
839            }
840            if (thisNewPersonality) {
841                // dup, ignore
842               newPersonalities->removeObject(newIdx);
843            }
844            else {
845                // not in new set - remove
846                // only remove dictionary if this module in not loaded - 9953845
847                if ( isModuleLoadedNoOSKextLock(myKexts, thisOldPersonality) == false ) {
848                    if (matchSet) {
849                        matchSet->setObject(thisOldPersonality);
850                    }
851                    array->removeObject(idx);
852                    idx--;
853                }
854            }
855        } // for...
856    } // while...
857
858    // add new
859    if (newPersonalities) {
860        for (newIdx = 0;
861             (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx));
862             newIdx++)
863        {
864            if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) {
865                /* skip thisNewPersonality if it is not an OSDictionary */
866                continue;
867            }
868
869            OSKext::uniquePersonalityProperties(thisNewPersonality);
870            addPersonality(thisNewPersonality);
871            matchSet->setObject(thisNewPersonality);
872        }
873    }
874
875   /* Finally, start device matching on all new & removed personalities.
876    */
877    if (result && doNubMatching && (matchSet->getCount() > 0)) {
878        IOService::catalogNewDrivers(matchSet);
879        generation++;
880    }
881
882    IORWLockUnlock(lock);
883
884finish:
885    if (matchSet)   matchSet->release();
886    if (iter)       iter->release();
887    if (myKexts)    myKexts->release();
888
889    return result;
890}
891
892bool IOCatalogue::serialize(OSSerialize * s) const
893{
894    if ( !s )
895        return false;
896
897    return super::serialize(s);
898}
899
900bool IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const
901{
902    kern_return_t kr = kIOReturnSuccess;
903
904    switch ( kind )
905    {
906        case kIOCatalogGetContents:
907            kr = KERN_NOT_SUPPORTED;
908            break;
909
910        case kIOCatalogGetModuleDemandList:
911            kr = KERN_NOT_SUPPORTED;
912            break;
913
914        case kIOCatalogGetCacheMissList:
915            kr = KERN_NOT_SUPPORTED;
916            break;
917
918        case kIOCatalogGetROMMkextList:
919            kr = KERN_NOT_SUPPORTED;
920            break;
921
922        default:
923            kr = kIOReturnBadArgument;
924            break;
925    }
926
927    return kr;
928}
929
930/* isModuleLoadedNoOSKextLock - used to check to see if a kext is loaded
931 * without taking the OSKext lock.  We use this to avoid the problem
932 * where taking the IOCatalog lock then the OSKext lock will dealock when
933 * a kext load or unload is happening at the same time as IOCatalog changing.
934 *
935 * theKexts - is a dictionary of current kexts (from OSKext::copyKexts) with
936 *      key set to the kext bundle ID and value set to an OSKext object
937 * theModuleDict - is an IOKit personality dictionary for a given module (kext)
938 */
939static bool isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
940                                       OSDictionary *theModuleDict)
941{
942    bool                    myResult = false;
943    const OSString *        myBundleID = NULL;  // do not release
944    OSKext *                myKext = NULL;      // do not release
945
946    if (theKexts == NULL || theModuleDict == NULL) {
947        return( myResult );
948    }
949
950    // gIOModuleIdentifierKey is "CFBundleIdentifier"
951    myBundleID = OSDynamicCast(OSString,
952                               theModuleDict->getObject(gIOModuleIdentifierKey));
953    if (myBundleID == NULL) {
954        return( myResult );
955    }
956
957    myKext = OSDynamicCast(OSKext, theKexts->getObject(myBundleID->getCStringNoCopy()));
958    if (myKext) {
959        myResult = myKext->isLoaded();
960    }
961
962    return( myResult );
963}
964
965
966#if PRAGMA_MARK
967#pragma mark Obsolete Kext Loading Stuff
968#endif
969/*********************************************************************
970**********************************************************************
971***                  BINARY COMPATIBILITY SECTION                  ***
972**********************************************************************
973**********************************************************************
974* These functions are no longer used are necessary for C++ binary
975* compatibility on i386.
976**********************************************************************/
977