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>
53 #include <IOKit/IODeviceTreeSupport.h>
54 #include <IOKit/IOService.h>
55 #include <IOKit/IOCatalogue.h>
57 #include <IOKit/IOLib.h>
58 #include <IOKit/assert.h>
61 #pragma mark Internal Declarations
63 /*********************************************************************
64 *********************************************************************/
68 IOCatalogue
* gIOCatalogue
;
69 const OSSymbol
* gIOClassKey
;
70 const OSSymbol
* gIOProbeScoreKey
;
71 const OSSymbol
* gIOModuleIdentifierKey
;
72 IOLock
* gIOCatalogLock
;
75 #pragma mark Utility functions
77 /*********************************************************************
78 *********************************************************************/
80 UniqueProperties(OSDictionary
* dict
)
84 data
= OSDynamicCast(OSString
, dict
->getObject(gIOClassKey
));
86 const OSSymbol
*classSymbol
= OSSymbol::withString(data
);
88 dict
->setObject( gIOClassKey
, (OSSymbol
*) classSymbol
);
89 classSymbol
->release();
92 data
= OSDynamicCast(OSString
, dict
->getObject(gIOMatchCategoryKey
));
94 const OSSymbol
*classSymbol
= OSSymbol::withString(data
);
96 dict
->setObject(gIOMatchCategoryKey
, (OSSymbol
*) classSymbol
);
97 classSymbol
->release();
102 /*********************************************************************
103 * Add a new personality to the set if it has a unique IOResourceMatchKey value.
104 * XXX -- svail: This should be optimized.
105 * esb - There doesn't seem like any reason to do this - it causes problems
106 * esb - when there are more than one loadable driver matching on the same provider class
107 *********************************************************************/
109 AddNewImports(OSOrderedSet
* set
, OSDictionary
* dict
)
111 set
->setObject(dict
);
115 #pragma mark IOCatalogue class implementation
117 /*********************************************************************
118 *********************************************************************/
120 #define super OSObject
121 OSDefineMetaClassAndStructors(IOCatalogue
, OSObject
)
123 /*********************************************************************
124 *********************************************************************/
125 void IOCatalogue::initialize(void)
128 OSString
* errorString
;
131 extern const char * gIOKernelConfigTables
;
133 array
= OSDynamicCast(OSArray
, OSUnserialize(gIOKernelConfigTables
, &errorString
));
134 if (!array
&& errorString
) {
135 IOLog("KernelConfigTables syntax error: %s\n",
136 errorString
->getCStringNoCopy());
137 errorString
->release();
140 gIOClassKey
= OSSymbol::withCStringNoCopy( kIOClassKey
);
141 gIOProbeScoreKey
= OSSymbol::withCStringNoCopy( kIOProbeScoreKey
);
142 gIOModuleIdentifierKey
= OSSymbol::withCStringNoCopy( kCFBundleIdentifierKey
);
144 assert( array
&& gIOClassKey
&& gIOProbeScoreKey
145 && gIOModuleIdentifierKey
);
147 gIOCatalogue
= new IOCatalogue
;
148 assert(gIOCatalogue
);
149 rc
= gIOCatalogue
->init(array
);
154 /*********************************************************************
155 * Initialize the IOCatalog object.
156 *********************************************************************/
157 bool IOCatalogue::init(OSArray
* initArray
)
161 if ( !super::init() )
168 kernelTables
= OSCollectionIterator::withCollection( array
);
170 gIOCatalogLock
= IOLockAlloc();
172 lock
= gIOCatalogLock
;
173 #if __ppc__ || __i386__
175 #endif /* __ppc__ || __i386__ */
177 kernelTables
->reset();
178 while( (dict
= (OSDictionary
*) kernelTables
->getNextObject())) {
179 UniqueProperties(dict
);
180 if( 0 == dict
->getObject( gIOClassKey
))
181 IOLog("Missing or bad \"%s\" key\n",
182 gIOClassKey
->getCStringNoCopy());
186 AbsoluteTime deadline
;
187 clock_interval_to_deadline( 1000, kMillisecondScale
);
188 thread_call_func_delayed( ping
, this, deadline
);
194 /*********************************************************************
195 * Release all resources used by IOCatalogue and deallocate.
196 * This will probably never be called.
197 *********************************************************************/
198 void IOCatalogue::free( void )
204 kernelTables
->release();
209 /*********************************************************************
210 *********************************************************************/
213 static int hackLimit
;
214 enum { kDriversPerIter
= 4 };
217 IOCatalogue::ping(thread_call_param_t arg
, thread_call_param_t
)
219 IOCatalogue
* self
= (IOCatalogue
*) arg
;
221 OSDictionary
* table
;
224 set
= OSOrderedSet::withCapacity( 1 );
226 IOLockLock( &self
->lock
);
228 for( newLimit
= 0; newLimit
< kDriversPerIter
; newLimit
++) {
229 table
= (OSDictionary
*) self
->array
->getObject(
230 hackLimit
+ newLimit
);
232 set
->setLastObject( table
);
234 OSSymbol
* sym
= (OSSymbol
*) table
->getObject(gIOClassKey
);
235 kprintf("enabling %s\n", sym
->getCStringNoCopy());
243 IOService::catalogNewDrivers( set
);
245 hackLimit
+= newLimit
;
248 IOLockUnlock( &self
->lock
);
250 if( kDriversPerIter
== newLimit
) {
251 AbsoluteTime deadline
;
252 clock_interval_to_deadline(500, kMillisecondScale
);
253 thread_call_func_delayed(ping
, this, deadline
);
258 /*********************************************************************
259 *********************************************************************/
261 IOCatalogue::findDrivers(
263 SInt32
* generationCount
)
265 OSDictionary
* nextTable
;
269 set
= OSOrderedSet::withCapacity( 1, IOServiceOrdering
,
270 (void *)gIOProbeScoreKey
);
275 kernelTables
->reset();
280 while( (nextTable
= (OSDictionary
*) kernelTables
->getNextObject())) {
282 if( hackIndex
++ > hackLimit
)
285 imports
= OSDynamicCast( OSString
,
286 nextTable
->getObject( gIOProviderClassKey
));
287 if( imports
&& service
->metaCast( imports
))
288 set
->setObject( nextTable
);
291 *generationCount
= getGenerationCount();
298 /*********************************************************************
299 * Is personality already in the catalog?
300 *********************************************************************/
302 IOCatalogue::findDrivers(
303 OSDictionary
* matching
,
304 SInt32
* generationCount
)
309 UniqueProperties(matching
);
311 set
= OSOrderedSet::withCapacity( 1, IOServiceOrdering
,
312 (void *)gIOProbeScoreKey
);
315 kernelTables
->reset();
316 while ( (dict
= (OSDictionary
*) kernelTables
->getNextObject()) ) {
318 /* This comparison must be done with only the keys in the
319 * "matching" dict to enable general searches.
321 if ( dict
->isEqualTo(matching
, matching
) )
322 set
->setObject(dict
);
324 *generationCount
= getGenerationCount();
330 /*********************************************************************
331 * Add driver config tables to catalog and start matching process.
333 * Important that existing personalities are kept (not replaced)
334 * if duplicates found. Personalities can come from OSKext objects
335 * or from userland kext library. We want to minimize distinct
336 * copies between OSKext & IOCatalogue.
338 * xxx - userlib used to refuse to send personalities with IOKitDebug
339 * xxx - during safe boot. That would be better implemented here.
340 *********************************************************************/
341 bool IOCatalogue::addDrivers(
346 OSCollectionIterator
* iter
= NULL
; // must release
347 OSOrderedSet
* set
= NULL
; // must release
348 OSDictionary
* dict
= NULL
; // do not release
349 OSArray
* persons
= NULL
; // do not release
351 persons
= OSDynamicCast(OSArray
, drivers
);
356 set
= OSOrderedSet::withCapacity( 10, IOServiceOrdering
,
357 (void *)gIOProbeScoreKey
);
362 iter
= OSCollectionIterator::withCollection(persons
);
370 while ( (dict
= (OSDictionary
*) iter
->getNextObject()) ) {
372 // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL
376 UniqueProperties(dict
);
378 // Add driver personality to catalogue.
379 count
= array
->getCount();
381 OSDictionary
* driver
;
383 // Be sure not to double up on personalities.
384 driver
= (OSDictionary
*)array
->getObject(count
);
386 /* Unlike in other functions, this comparison must be exact!
387 * The catalogue must be able to contain personalities that
388 * are proper supersets of others.
389 * Do not compare just the properties present in one driver
390 * pesonality or the other.
392 if (dict
->isEqualTo(driver
)) {
401 result
= array
->setObject(dict
);
406 AddNewImports(set
, dict
);
408 // Start device matching.
409 if (doNubMatching
&& (set
->getCount() > 0)) {
410 IOService::catalogNewDrivers(set
);
416 if (set
) set
->release();
417 if (iter
) iter
->release();
422 /*********************************************************************
423 * Remove drivers from the catalog which match the
424 * properties in the matching dictionary.
425 *********************************************************************/
427 IOCatalogue::removeDrivers(
428 OSDictionary
* matching
,
431 OSCollectionIterator
* tables
;
439 set
= OSOrderedSet::withCapacity(10,
441 (void *)gIOProbeScoreKey
);
445 arrayCopy
= OSArray::withCapacity(100);
451 tables
= OSCollectionIterator::withCollection(arrayCopy
);
452 arrayCopy
->release();
458 UniqueProperties( matching
);
461 kernelTables
->reset();
462 arrayCopy
->merge(array
);
463 array
->flushCollection();
465 while ( (dict
= (OSDictionary
*)tables
->getNextObject()) ) {
467 /* This comparison must be done with only the keys in the
468 * "matching" dict to enable general searches.
470 if ( dict
->isEqualTo(matching
, matching
) ) {
471 AddNewImports( set
, dict
);
475 array
->setObject(dict
);
477 // Start device matching.
478 if ( doNubMatching
&& (set
->getCount() > 0) ) {
479 IOService::catalogNewDrivers(set
);
490 // Return the generation count.
491 SInt32
IOCatalogue::getGenerationCount(void) const
493 return( generation
);
496 bool IOCatalogue::isModuleLoaded(OSString
* moduleName
) const
498 return isModuleLoaded(moduleName
->getCStringNoCopy());
501 bool IOCatalogue::isModuleLoaded(const char * moduleName
) const
504 ret
= OSKext::loadKextWithIdentifier(moduleName
);
505 if (kOSKextReturnDeferred
== ret
) {
506 // a request has been queued but the module isn't necessarily
507 // loaded yet, so stall.
510 // module is present or never will be
514 // Check to see if module has been loaded already.
515 bool IOCatalogue::isModuleLoaded(OSDictionary
* driver
) const
517 OSString
* moduleName
= NULL
;
518 OSString
* publisherName
= NULL
;
523 /* The personalities of codeless kexts often contain the bundle ID of the
524 * kext they reference, and not the bundle ID of the codeless kext itself.
525 * The prelinked kernel needs to know the bundle ID of the codeless kext
526 * so it can include these personalities, so OSKext stores that bundle ID
527 * in the IOPersonalityPublisher key, and we record it as requested here.
529 publisherName
= OSDynamicCast(OSString
,
530 driver
->getObject(kIOPersonalityPublisherKey
));
531 OSKext::recordIdentifierRequest(publisherName
);
533 moduleName
= OSDynamicCast(OSString
, driver
->getObject(gIOModuleIdentifierKey
));
535 return isModuleLoaded(moduleName
);
537 /* If a personality doesn't hold the "CFBundleIdentifier" key
538 * it is assumed to be an "in-kernel" driver.
543 /* This function is called after a module has been loaded.
544 * Is invoked from user client call, ultimately from IOKitLib's
545 * IOCatalogueModuleLoaded(). Sent from kextd.
547 void IOCatalogue::moduleHasLoaded(OSString
* moduleName
)
551 dict
= OSDictionary::withCapacity(2);
552 dict
->setObject(gIOModuleIdentifierKey
, moduleName
);
556 (void) OSKext::setDeferredLoadSucceeded();
557 (void) OSKext::considerRebuildOfPrelinkedKernel();
560 void IOCatalogue::moduleHasLoaded(const char * moduleName
)
564 name
= OSString::withCString(moduleName
);
565 moduleHasLoaded(name
);
569 // xxx - return is really OSReturn/kern_return_t
570 IOReturn
IOCatalogue::unloadModule(OSString
* moduleName
) const
572 return OSKext::removeKextWithIdentifier(moduleName
->getCStringNoCopy());
575 static IOReturn
_terminateDrivers(OSDictionary
* matching
)
583 return kIOReturnBadArgument
;
585 ret
= kIOReturnSuccess
;
587 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
588 kIORegistryIterateRecursively
);
590 return kIOReturnNoMemory
;
592 UniqueProperties( matching
);
594 // terminate instances.
597 while( (service
= (IOService
*)iter
->getNextObject()) ) {
598 dict
= service
->getPropertyTable();
602 /* Terminate only for personalities that match the matching dictionary.
603 * This comparison must be done with only the keys in the
604 * "matching" dict to enable general matching.
606 if ( !dict
->isEqualTo(matching
, matching
) )
609 if ( !service
->terminate(kIOServiceRequired
|kIOServiceSynchronous
) ) {
610 ret
= kIOReturnUnsupported
;
614 } while( !service
&& !iter
->isValid());
620 static IOReturn
_removeDrivers( OSArray
* array
, OSDictionary
* matching
)
622 OSCollectionIterator
* tables
;
625 IOReturn ret
= kIOReturnSuccess
;
627 // remove configs from catalog.
629 arrayCopy
= OSArray::withCapacity(100);
631 return kIOReturnNoMemory
;
633 tables
= OSCollectionIterator::withCollection(arrayCopy
);
634 arrayCopy
->release();
636 return kIOReturnNoMemory
;
638 arrayCopy
->merge(array
);
639 array
->flushCollection();
641 while ( (dict
= (OSDictionary
*)tables
->getNextObject()) ) {
643 /* Remove from the catalogue's array any personalities
644 * that match the matching dictionary.
645 * This comparison must be done with only the keys in the
646 * "matching" dict to enable general matching.
648 if ( dict
->isEqualTo(matching
, matching
) )
651 array
->setObject(dict
);
659 IOReturn
IOCatalogue::terminateDrivers(OSDictionary
* matching
)
663 ret
= _terminateDrivers(matching
);
665 if (kIOReturnSuccess
== ret
)
666 ret
= _removeDrivers(array
, matching
);
667 kernelTables
->reset();
673 IOReturn
IOCatalogue::terminateDriversForModule(
674 OSString
* moduleName
,
679 bool isLoaded
= false;
681 /* Check first if the kext currently has any linkage dependents;
682 * in such a case the unload would fail so let's not terminate any
683 * IOServices (since doing so typically results in a panic when there
684 * are loaded dependencies). Note that we aren't locking the kext here
685 * so it might lose or gain dependents by the time we call unloadModule();
686 * I think that's ok, our unload can fail if a kext comes in on top of
687 * this one even after we've torn down IOService objects. Conversely,
688 * if we fail the unload here and then lose a library, the autounload
689 * thread will get us in short order.
691 if (OSKext::isKextWithIdentifierLoaded(moduleName
->getCStringNoCopy())) {
695 if (!OSKext::canUnloadKextWithIdentifier(moduleName
,
696 /* checkClasses */ false)) {
697 ret
= kOSKextReturnInUse
;
701 dict
= OSDictionary::withCapacity(1);
703 ret
= kIOReturnNoMemory
;
707 dict
->setObject(gIOModuleIdentifierKey
, moduleName
);
709 ret
= _terminateDrivers(dict
);
711 /* No goto between IOLock calls!
714 if (kIOReturnSuccess
== ret
) {
715 ret
= _removeDrivers(array
, dict
);
717 kernelTables
->reset();
719 // Unload the module itself.
720 if (unload
&& isLoaded
&& ret
== kIOReturnSuccess
) {
721 ret
= unloadModule(moduleName
);
732 IOReturn
IOCatalogue::terminateDriversForModule(
733 const char * moduleName
,
739 name
= OSString::withCString(moduleName
);
741 return kIOReturnNoMemory
;
743 ret
= terminateDriversForModule(name
, unload
);
749 bool IOCatalogue::startMatching( OSDictionary
* matching
)
757 set
= OSOrderedSet::withCapacity(10, IOServiceOrdering
,
758 (void *)gIOProbeScoreKey
);
763 kernelTables
->reset();
765 while ( (dict
= (OSDictionary
*)kernelTables
->getNextObject()) ) {
767 /* This comparison must be done with only the keys in the
768 * "matching" dict to enable general matching.
770 if ( dict
->isEqualTo(matching
, matching
) )
771 AddNewImports(set
, dict
);
773 // Start device matching.
774 if ( set
->getCount() > 0 ) {
775 IOService::catalogNewDrivers(set
);
786 void IOCatalogue::reset(void)
788 IOLog("Resetting IOCatalogue.\n");
791 bool IOCatalogue::serialize(OSSerialize
* s
) const
796 return super::serialize(s
);
799 bool IOCatalogue::serializeData(IOOptionBits kind
, OSSerialize
* s
) const
801 kern_return_t kr
= kIOReturnSuccess
;
805 case kIOCatalogGetContents
:
806 if (!array
->serialize(s
))
807 kr
= kIOReturnNoMemory
;
810 case kIOCatalogGetModuleDemandList
:
811 kr
= KERN_NOT_SUPPORTED
;
814 case kIOCatalogGetCacheMissList
:
815 kr
= KERN_NOT_SUPPORTED
;
818 case kIOCatalogGetROMMkextList
:
819 kr
= KERN_NOT_SUPPORTED
;
823 kr
= kIOReturnBadArgument
;
832 #pragma mark Obsolete Kext Loading Stuff
834 /*********************************************************************
835 **********************************************************************
836 *** BINARY COMPATIBILITY SECTION ***
837 **********************************************************************
838 **********************************************************************
839 * These functions are no longer used are necessary for C++ binary
840 * compatibility on ppc/i386.
841 **********************************************************************/
842 #if __ppc__ || __i386__
844 bool IOCatalogue::recordStartupExtensions(void)
847 bool IOCatalogue::addExtensionsFromArchive(OSData
* mkext
)
848 { return KERN_NOT_SUPPORTED
; }
850 kern_return_t
IOCatalogue::removeKernelLinker(void)
851 { return KERN_NOT_SUPPORTED
; }
853 #endif /* __ppc__ || __i386__ */