2 * Copyright (c) 1998-2006 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1998 Apple Inc. All rights reserved.
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,
42 #include <machine/machine_routines.h>
43 #include <libkern/kernel_mach_header.h>
44 #include <kern/host.h>
45 #include <security/mac_data.h>
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>
54 #include <IOKit/IODeviceTreeSupport.h>
55 #include <IOKit/IOService.h>
56 #include <IOKit/IOCatalogue.h>
58 #include <IOKit/IOLib.h>
59 #include <IOKit/assert.h>
62 #pragma mark Internal Declarations
64 /*********************************************************************
65 *********************************************************************/
67 IOCatalogue
* gIOCatalogue
;
68 const OSSymbol
* gIOClassKey
;
69 const OSSymbol
* gIOProbeScoreKey
;
70 const OSSymbol
* gIOModuleIdentifierKey
;
71 IORWLock
* gIOCatalogLock
;
74 #pragma mark Utility functions
78 #pragma mark IOCatalogue class implementation
80 /*********************************************************************
81 *********************************************************************/
83 #define super OSObject
84 OSDefineMetaClassAndStructors(IOCatalogue
, OSObject
)
86 /*********************************************************************
87 *********************************************************************/
88 void IOCatalogue::initialize(void)
91 OSString
* errorString
;
94 extern const char * gIOKernelConfigTables
;
96 array
= OSDynamicCast(OSArray
, OSUnserialize(gIOKernelConfigTables
, &errorString
));
97 if (!array
&& errorString
) {
98 IOLog("KernelConfigTables syntax error: %s\n",
99 errorString
->getCStringNoCopy());
100 errorString
->release();
103 gIOClassKey
= OSSymbol::withCStringNoCopy( kIOClassKey
);
104 gIOProbeScoreKey
= OSSymbol::withCStringNoCopy( kIOProbeScoreKey
);
105 gIOModuleIdentifierKey
= OSSymbol::withCStringNoCopy( kCFBundleIdentifierKey
);
107 assert( array
&& gIOClassKey
&& gIOProbeScoreKey
108 && gIOModuleIdentifierKey
);
110 gIOCatalogue
= new IOCatalogue
;
111 assert(gIOCatalogue
);
112 rc
= gIOCatalogue
->init(array
);
117 /*********************************************************************
118 * Initialize the IOCatalog object.
119 *********************************************************************/
120 OSArray
* IOCatalogue::arrayForPersonality(OSDictionary
* dict
)
122 const OSSymbol
* sym
;
124 sym
= OSDynamicCast(OSSymbol
, dict
->getObject(gIOProviderClassKey
));
125 if (!sym
) return (0);
127 return ((OSArray
*) personalities
->getObject(sym
));
130 void IOCatalogue::addPersonality(OSDictionary
* dict
)
132 const OSSymbol
* sym
;
135 sym
= OSDynamicCast(OSSymbol
, dict
->getObject(gIOProviderClassKey
));
137 arr
= (OSArray
*) personalities
->getObject(sym
);
138 if (arr
) arr
->setObject(dict
);
141 arr
= OSArray::withObjects((const OSObject
**)&dict
, 1, 2);
142 personalities
->setObject(sym
, arr
);
147 /*********************************************************************
148 * Initialize the IOCatalog object.
149 *********************************************************************/
150 bool IOCatalogue::init(OSArray
* initArray
)
155 if ( !super::init() )
160 personalities
= OSDictionary::withCapacity(32);
161 personalities
->setOptions(OSCollection::kSort
, OSCollection::kSort
);
162 for (unsigned int idx
= 0; (obj
= initArray
->getObject(idx
)); idx
++)
164 dict
= OSDynamicCast(OSDictionary
, obj
);
166 OSKext::uniquePersonalityProperties(dict
);
167 if( 0 == dict
->getObject( gIOClassKey
))
169 IOLog("Missing or bad \"%s\" key\n",
170 gIOClassKey
->getCStringNoCopy());
173 dict
->setObject("KernelConfigTable", kOSBooleanTrue
);
174 addPersonality(dict
);
177 gIOCatalogLock
= IORWLockAlloc();
178 lock
= gIOCatalogLock
;
183 /*********************************************************************
184 * Release all resources used by IOCatalogue and deallocate.
185 * This will probably never be called.
186 *********************************************************************/
187 void IOCatalogue::free( void )
192 /*********************************************************************
193 *********************************************************************/
195 IOCatalogue::findDrivers(
197 SInt32
* generationCount
)
199 OSDictionary
* nextTable
;
202 const OSMetaClass
* meta
;
205 set
= OSOrderedSet::withCapacity( 1, IOServiceOrdering
,
206 (void *)gIOProbeScoreKey
);
212 meta
= service
->getMetaClass();
215 array
= (OSArray
*) personalities
->getObject(meta
->getClassNameSymbol());
216 if (array
) for (idx
= 0; (nextTable
= (OSDictionary
*) array
->getObject(idx
)); idx
++)
218 set
->setObject(nextTable
);
220 if (meta
== &IOService::gMetaClass
) break;
221 meta
= meta
->getSuperClass();
224 *generationCount
= getGenerationCount();
226 IORWLockUnlock(lock
);
231 /*********************************************************************
232 * Is personality already in the catalog?
233 *********************************************************************/
235 IOCatalogue::findDrivers(
236 OSDictionary
* matching
,
237 SInt32
* generationCount
)
239 OSCollectionIterator
* iter
;
243 const OSSymbol
* key
;
246 OSKext::uniquePersonalityProperties(matching
);
248 set
= OSOrderedSet::withCapacity( 1, IOServiceOrdering
,
249 (void *)gIOProbeScoreKey
);
250 if (!set
) return (0);
251 iter
= OSCollectionIterator::withCollection(personalities
);
259 while ((key
= (const OSSymbol
*) iter
->getNextObject()))
261 array
= (OSArray
*) personalities
->getObject(key
);
262 if (array
) for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++)
264 /* This comparison must be done with only the keys in the
265 * "matching" dict to enable general searches.
267 if ( dict
->isEqualTo(matching
, matching
) )
268 set
->setObject(dict
);
271 *generationCount
= getGenerationCount();
272 IORWLockUnlock(lock
);
278 /*********************************************************************
279 * Add driver config tables to catalog and start matching process.
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.
286 * xxx - userlib used to refuse to send personalities with IOKitDebug
287 * xxx - during safe boot. That would be better implemented here.
288 *********************************************************************/
290 bool IOCatalogue::addDrivers(
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
300 persons
= OSDynamicCast(OSArray
, drivers
);
305 set
= OSOrderedSet::withCapacity( 10, IOServiceOrdering
,
306 (void *)gIOProbeScoreKey
);
311 iter
= OSCollectionIterator::withCollection(persons
);
316 /* Start with success; clear it on an error.
321 while ( (object
= iter
->getNextObject()) ) {
323 // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL
325 OSDictionary
* personality
= OSDynamicCast(OSDictionary
, object
);
330 IOLog("IOCatalogue::addDrivers() encountered non-dictionary; bailing.\n");
335 OSKext::uniquePersonalityProperties(personality
);
337 // Add driver personality to catalogue.
339 OSArray
* array
= arrayForPersonality(personality
);
340 if (!array
) addPersonality(personality
);
343 count
= array
->getCount();
345 OSDictionary
* driver
;
347 // Be sure not to double up on personalities.
348 driver
= (OSDictionary
*)array
->getObject(count
);
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 * pesonality or the other.
356 if (personality
->isEqualTo(driver
)) {
364 result
= array
->setObject(personality
);
370 set
->setObject(personality
);
372 // Start device matching.
373 if (result
&& doNubMatching
&& (set
->getCount() > 0)) {
374 IOService::catalogNewDrivers(set
);
377 IORWLockUnlock(lock
);
380 if (set
) set
->release();
381 if (iter
) iter
->release();
386 /*********************************************************************
387 * Remove drivers from the catalog which match the
388 * properties in the matching dictionary.
389 *********************************************************************/
391 IOCatalogue::removeDrivers(
392 OSDictionary
* matching
,
396 OSCollectionIterator
* iter
;
399 const OSSymbol
* key
;
405 set
= OSOrderedSet::withCapacity(10,
407 (void *)gIOProbeScoreKey
);
410 iter
= OSCollectionIterator::withCollection(personalities
);
418 while ((key
= (const OSSymbol
*) iter
->getNextObject()))
420 array
= (OSArray
*) personalities
->getObject(key
);
421 if (array
) for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++)
423 /* This comparison must be done with only the keys in the
424 * "matching" dict to enable general searches.
426 if ( dict
->isEqualTo(matching
, matching
) ) {
427 set
->setObject(dict
);
428 array
->removeObject(idx
);
432 // Start device matching.
433 if ( doNubMatching
&& (set
->getCount() > 0) ) {
434 IOService::catalogNewDrivers(set
);
438 IORWLockUnlock(lock
);
446 // Return the generation count.
447 SInt32
IOCatalogue::getGenerationCount(void) const
449 return( generation
);
452 bool IOCatalogue::isModuleLoaded(OSString
* moduleName
) const
454 return isModuleLoaded(moduleName
->getCStringNoCopy());
457 bool IOCatalogue::isModuleLoaded(const char * moduleName
) const
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.
466 // module is present or never will be
470 // Check to see if module has been loaded already.
471 bool IOCatalogue::isModuleLoaded(OSDictionary
* driver
) const
473 OSString
* moduleName
= NULL
;
474 OSString
* publisherName
= NULL
;
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.
485 publisherName
= OSDynamicCast(OSString
,
486 driver
->getObject(kIOPersonalityPublisherKey
));
487 OSKext::recordIdentifierRequest(publisherName
);
489 moduleName
= OSDynamicCast(OSString
, driver
->getObject(gIOModuleIdentifierKey
));
491 return isModuleLoaded(moduleName
);
493 /* If a personality doesn't hold the "CFBundleIdentifier" key
494 * it is assumed to be an "in-kernel" driver.
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.
503 void IOCatalogue::moduleHasLoaded(OSString
* moduleName
)
507 dict
= OSDictionary::withCapacity(2);
508 dict
->setObject(gIOModuleIdentifierKey
, moduleName
);
512 (void) OSKext::setDeferredLoadSucceeded();
513 (void) OSKext::considerRebuildOfPrelinkedKernel();
516 void IOCatalogue::moduleHasLoaded(const char * moduleName
)
520 name
= OSString::withCString(moduleName
);
521 moduleHasLoaded(name
);
525 // xxx - return is really OSReturn/kern_return_t
526 IOReturn
IOCatalogue::unloadModule(OSString
* moduleName
) const
528 return OSKext::removeKextWithIdentifier(moduleName
->getCStringNoCopy());
531 IOReturn
IOCatalogue::_terminateDrivers(OSDictionary
* matching
)
539 return kIOReturnBadArgument
;
541 ret
= kIOReturnSuccess
;
543 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
544 kIORegistryIterateRecursively
);
546 return kIOReturnNoMemory
;
548 OSKext::uniquePersonalityProperties( matching
);
550 // terminate instances.
553 while( (service
= (IOService
*)iter
->getNextObject()) ) {
554 dict
= service
->getPropertyTable();
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.
562 if ( !dict
->isEqualTo(matching
, matching
) )
565 if ( !service
->terminate(kIOServiceRequired
|kIOServiceSynchronous
) ) {
566 ret
= kIOReturnUnsupported
;
570 } while( !service
&& !iter
->isValid());
576 IOReturn
IOCatalogue::_removeDrivers(OSDictionary
* matching
)
578 IOReturn ret
= kIOReturnSuccess
;
579 OSCollectionIterator
* iter
;
582 const OSSymbol
* key
;
585 // remove configs from catalog.
587 iter
= OSCollectionIterator::withCollection(personalities
);
588 if (!iter
) return (kIOReturnNoMemory
);
590 while ((key
= (const OSSymbol
*) iter
->getNextObject()))
592 array
= (OSArray
*) personalities
->getObject(key
);
593 if (array
) for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++)
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.
601 if (dict
->isEqualTo(matching
, matching
))
603 array
->removeObject(idx
);
613 IOReturn
IOCatalogue::terminateDrivers(OSDictionary
* matching
)
617 ret
= _terminateDrivers(matching
);
619 if (kIOReturnSuccess
== ret
)
620 ret
= _removeDrivers(matching
);
621 IORWLockUnlock(lock
);
626 IOReturn
IOCatalogue::terminateDriversForModule(
627 OSString
* moduleName
,
632 bool isLoaded
= false;
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.
644 if (OSKext::isKextWithIdentifierLoaded(moduleName
->getCStringNoCopy())) {
648 if (!OSKext::canUnloadKextWithIdentifier(moduleName
,
649 /* checkClasses */ false)) {
650 ret
= kOSKextReturnInUse
;
654 dict
= OSDictionary::withCapacity(1);
656 ret
= kIOReturnNoMemory
;
660 dict
->setObject(gIOModuleIdentifierKey
, moduleName
);
662 ret
= _terminateDrivers(dict
);
664 /* No goto between IOLock calls!
667 if (kIOReturnSuccess
== ret
) {
668 ret
= _removeDrivers(dict
);
671 // Unload the module itself.
672 if (unload
&& isLoaded
&& ret
== kIOReturnSuccess
) {
673 ret
= unloadModule(moduleName
);
676 IORWLockUnlock(lock
);
684 IOReturn
IOCatalogue::terminateDriversForModule(
685 const char * moduleName
,
691 name
= OSString::withCString(moduleName
);
693 return kIOReturnNoMemory
;
695 ret
= terminateDriversForModule(name
, unload
);
701 bool IOCatalogue::startMatching( OSDictionary
* matching
)
703 OSCollectionIterator
* iter
;
707 const OSSymbol
* key
;
713 set
= OSOrderedSet::withCapacity(10, IOServiceOrdering
,
714 (void *)gIOProbeScoreKey
);
718 iter
= OSCollectionIterator::withCollection(personalities
);
727 while ((key
= (const OSSymbol
*) iter
->getNextObject()))
729 array
= (OSArray
*) personalities
->getObject(key
);
730 if (array
) for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++)
732 /* This comparison must be done with only the keys in the
733 * "matching" dict to enable general matching.
735 if (dict
->isEqualTo(matching
, matching
)) {
736 set
->setObject(dict
);
741 // Start device matching.
742 if ( set
->getCount() > 0 ) {
743 IOService::catalogNewDrivers(set
);
747 IORWLockUnlock(lock
);
755 void IOCatalogue::reset(void)
757 IOCatalogue::resetAndAddDrivers(/* no drivers; true reset */ NULL
,
758 /* doMatching */ false);
762 bool IOCatalogue::resetAndAddDrivers(OSArray
* drivers
, bool doNubMatching
)
765 OSArray
* newPersonalities
= NULL
; // do not release
766 OSCollectionIterator
* iter
= NULL
; // must release
767 OSOrderedSet
* matchSet
= NULL
; // must release
768 const OSSymbol
* key
;
770 OSDictionary
* thisNewPersonality
= NULL
; // do not release
771 OSDictionary
* thisOldPersonality
= NULL
; // do not release
772 signed int idx
, newIdx
;
775 newPersonalities
= OSDynamicCast(OSArray
, drivers
);
776 if (!newPersonalities
) {
780 matchSet
= OSOrderedSet::withCapacity(10, IOServiceOrdering
,
781 (void *)gIOProbeScoreKey
);
785 iter
= OSCollectionIterator::withCollection(personalities
);
793 IOLog("Resetting IOCatalogue.\n");
795 /* No goto finish from here to unlock.
799 while ((key
= (const OSSymbol
*) iter
->getNextObject()))
801 array
= (OSArray
*) personalities
->getObject(key
);
802 if (!array
) continue;
803 for (idx
= 0; (thisOldPersonality
= (OSDictionary
*) array
->getObject(idx
)); idx
++)
805 if (thisOldPersonality
->getObject("KernelConfigTable")) continue;
806 if (newPersonalities
) for (newIdx
= 0;
807 (thisNewPersonality
= (OSDictionary
*) newPersonalities
->getObject(newIdx
));
810 /* Unlike in other functions, this comparison must be exact!
811 * The catalogue must be able to contain personalities that
812 * are proper supersets of others.
813 * Do not compare just the properties present in one driver
814 * pesonality or the other.
816 if (thisNewPersonality
->isEqualTo(thisOldPersonality
))
819 if (thisNewPersonality
)
822 newPersonalities
->removeObject(newIdx
);
826 // not in new set - remove
827 // only remove dictionary if this module in not loaded - 9953845
828 if ( isModuleLoaded(thisOldPersonality
) == false )
830 if (matchSet
) matchSet
->setObject(thisOldPersonality
);
831 array
->removeObject(idx
);
840 (thisNewPersonality
= (OSDictionary
*) newPersonalities
->getObject(newIdx
));
843 OSKext::uniquePersonalityProperties(thisNewPersonality
);
844 addPersonality(thisNewPersonality
);
845 matchSet
->setObject(thisNewPersonality
);
848 /* Finally, start device matching on all new & removed personalities.
850 if (result
&& doNubMatching
&& (matchSet
->getCount() > 0)) {
851 IOService::catalogNewDrivers(matchSet
);
855 IORWLockUnlock(lock
);
858 if (matchSet
) matchSet
->release();
859 if (iter
) iter
->release();
864 bool IOCatalogue::serialize(OSSerialize
* s
) const
869 return super::serialize(s
);
872 bool IOCatalogue::serializeData(IOOptionBits kind
, OSSerialize
* s
) const
874 kern_return_t kr
= kIOReturnSuccess
;
878 case kIOCatalogGetContents
:
879 kr
= KERN_NOT_SUPPORTED
;
882 case kIOCatalogGetModuleDemandList
:
883 kr
= KERN_NOT_SUPPORTED
;
886 case kIOCatalogGetCacheMissList
:
887 kr
= KERN_NOT_SUPPORTED
;
890 case kIOCatalogGetROMMkextList
:
891 kr
= KERN_NOT_SUPPORTED
;
895 kr
= kIOReturnBadArgument
;
903 #pragma mark Obsolete Kext Loading Stuff
905 /*********************************************************************
906 **********************************************************************
907 *** BINARY COMPATIBILITY SECTION ***
908 **********************************************************************
909 **********************************************************************
910 * These functions are no longer used are necessary for C++ binary
911 * compatibility on i386.
912 **********************************************************************/
915 bool IOCatalogue::recordStartupExtensions(void)
918 bool IOCatalogue::addExtensionsFromArchive(OSData
* mkext
)
919 { return KERN_NOT_SUPPORTED
; }
921 kern_return_t
IOCatalogue::removeKernelLinker(void)
922 { return KERN_NOT_SUPPORTED
; }
924 #endif /* __i386__ */