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