]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOCatalogue.cpp
xnu-2422.115.4.tar.gz
[apple/xnu.git] / iokit / Kernel / IOCatalogue.cpp
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
41 extern "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
67 IOCatalogue * gIOCatalogue;
68 const OSSymbol * gIOClassKey;
69 const OSSymbol * gIOProbeScoreKey;
70 const OSSymbol * gIOModuleIdentifierKey;
71 IORWLock * 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
84 OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
85
86 /*********************************************************************
87 *********************************************************************/
88 void 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 *********************************************************************/
120 OSArray * 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
130 void 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 *********************************************************************/
150 bool 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 *********************************************************************/
187 void IOCatalogue::free( void )
188 {
189 panic("");
190 }
191
192 /*********************************************************************
193 *********************************************************************/
194 OSOrderedSet *
195 IOCatalogue::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 *********************************************************************/
234 OSOrderedSet *
235 IOCatalogue::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
290 bool 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
379 finish:
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 *********************************************************************/
390 bool
391 IOCatalogue::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.
447 SInt32 IOCatalogue::getGenerationCount(void) const
448 {
449 return( generation );
450 }
451
452 bool IOCatalogue::isModuleLoaded(OSString * moduleName) const
453 {
454 return isModuleLoaded(moduleName->getCStringNoCopy());
455 }
456
457 bool 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.
471 bool 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 */
503 void 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
516 void 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
526 IOReturn IOCatalogue::unloadModule(OSString * moduleName) const
527 {
528 return OSKext::removeKextWithIdentifier(moduleName->getCStringNoCopy());
529 }
530
531 IOReturn 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
576 IOReturn 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
613 IOReturn 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
626 IOReturn 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
680 finish:
681 return ret;
682 }
683
684 IOReturn 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
701 bool 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
755 void IOCatalogue::reset(void)
756 {
757 IOCatalogue::resetAndAddDrivers(/* no drivers; true reset */ NULL,
758 /* doMatching */ false);
759 return;
760 }
761
762 bool 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
867 finish:
868 if (matchSet) matchSet->release();
869 if (iter) iter->release();
870
871 return result;
872 }
873
874 bool IOCatalogue::serialize(OSSerialize * s) const
875 {
876 if ( !s )
877 return false;
878
879 return super::serialize(s);
880 }
881
882 bool 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 **********************************************************************/