2 * Copyright (c) 1998-2012 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,
41 #define IOKIT_ENABLE_SHARED_PTR
44 #include <machine/machine_routines.h>
45 #include <libkern/kernel_mach_header.h>
46 #include <kern/host.h>
47 #include <security/mac_data.h>
50 #include <libkern/c++/OSContainers.h>
51 #include <libkern/c++/OSUnserialize.h>
52 #include <libkern/c++/OSKext.h>
53 #include <libkern/c++/OSSharedPtr.h>
54 #include <libkern/OSKextLibPrivate.h>
55 #include <libkern/OSDebug.h>
57 #include <IOKit/IODeviceTreeSupport.h>
58 #include <IOKit/IOService.h>
59 #include <IOKit/IOCatalogue.h>
61 #include <IOKit/IOLib.h>
62 #include <IOKit/assert.h>
63 #include <IOKit/IOKitKeysPrivate.h>
66 #pragma mark Internal Declarations
68 /*********************************************************************
69 *********************************************************************/
71 OSSharedPtr
<IOCatalogue
> gIOCatalogue
;
72 OSSharedPtr
<const OSSymbol
> gIOClassKey
;
73 OSSharedPtr
<const OSSymbol
> gIOProbeScoreKey
;
74 OSSharedPtr
<const OSSymbol
> gIOModuleIdentifierKey
;
75 OSSharedPtr
<const OSSymbol
> gIOModuleIdentifierKernelKey
;
76 OSSharedPtr
<const OSSymbol
> gIOHIDInterfaceClassName
;
77 IORWLock
* gIOCatalogLock
;
80 #pragma mark Utility functions
84 #pragma mark IOCatalogue class implementation
86 /*********************************************************************
87 *********************************************************************/
89 #define super OSObject
90 OSDefineMetaClassAndStructors(IOCatalogue
, OSObject
)
92 static bool isModuleLoadedNoOSKextLock(OSDictionary
*theKexts
,
93 OSDictionary
*theModuleDict
);
96 /*********************************************************************
97 *********************************************************************/
99 IOCatalogue::initialize(void)
101 OSSharedPtr
<OSArray
> array
;
102 OSSharedPtr
<OSString
> errorString
;
105 extern const char * gIOKernelConfigTables
;
107 array
= OSDynamicPtrCast
<OSArray
>(OSUnserialize(gIOKernelConfigTables
, errorString
));
108 if (!array
&& errorString
) {
109 IOLog("KernelConfigTables syntax error: %s\n",
110 errorString
->getCStringNoCopy());
113 gIOClassKey
= OSSymbol::withCStringNoCopy( kIOClassKey
);
114 gIOProbeScoreKey
= OSSymbol::withCStringNoCopy( kIOProbeScoreKey
);
115 gIOModuleIdentifierKey
= OSSymbol::withCStringNoCopy( kCFBundleIdentifierKey
);
116 gIOModuleIdentifierKernelKey
= OSSymbol::withCStringNoCopy( kCFBundleIdentifierKernelKey
);
117 gIOHIDInterfaceClassName
= OSSymbol::withCStringNoCopy( "IOHIDInterface" );
120 assert( array
&& gIOClassKey
&& gIOProbeScoreKey
121 && gIOModuleIdentifierKey
);
123 gIOCatalogue
= OSMakeShared
<IOCatalogue
>();
124 assert(gIOCatalogue
);
125 rc
= gIOCatalogue
->init(array
.get());
129 /*********************************************************************
130 * Initialize the IOCatalog object.
131 *********************************************************************/
133 IOCatalogue::arrayForPersonality(OSDictionary
* dict
)
135 const OSSymbol
* sym
;
137 sym
= OSDynamicCast(OSSymbol
, dict
->getObject(gIOProviderClassKey
));
142 return (OSArray
*) personalities
->getObject(sym
);
146 IOCatalogue::addPersonality(OSDictionary
* dict
)
148 const OSSymbol
* sym
;
151 sym
= OSDynamicCast(OSSymbol
, dict
->getObject(gIOProviderClassKey
));
155 arr
= (OSArray
*) personalities
->getObject(sym
);
157 arr
->setObject(dict
);
159 OSSharedPtr
<OSArray
> sharedArr
= OSArray::withObjects((const OSObject
**)&dict
, 1, 2);
160 personalities
->setObject(sym
, sharedArr
.get());
164 /*********************************************************************
165 * Initialize the IOCatalog object.
166 *********************************************************************/
168 IOCatalogue::init(OSArray
* initArray
)
173 if (!super::init()) {
179 personalities
= OSDictionary::withCapacity(32);
180 personalities
->setOptions(OSCollection::kSort
, OSCollection::kSort
);
181 for (unsigned int idx
= 0; (obj
= initArray
->getObject(idx
)); idx
++) {
182 dict
= OSDynamicCast(OSDictionary
, obj
);
186 OSKext::uniquePersonalityProperties(dict
);
187 if (NULL
== dict
->getObject( gIOClassKey
.get())) {
188 IOLog("Missing or bad \"%s\" key\n",
189 gIOClassKey
->getCStringNoCopy());
192 dict
->setObject("KernelConfigTable", kOSBooleanTrue
);
193 addPersonality(dict
);
196 gIOCatalogLock
= IORWLockAlloc();
197 lock
= gIOCatalogLock
;
202 /*********************************************************************
203 * Release all resources used by IOCatalogue and deallocate.
204 * This will probably never be called.
205 *********************************************************************/
207 IOCatalogue::free( void )
212 /*********************************************************************
213 *********************************************************************/
215 IOCatalogue::findDrivers(
217 SInt32
* generationCount
)
219 OSDictionary
* nextTable
;
220 OSSharedPtr
<OSOrderedSet
> set
;
222 const OSMetaClass
* meta
;
225 set
= OSOrderedSet::withCapacity( 1, IOServiceOrdering
,
226 (void *)(gIOProbeScoreKey
.get()));
233 meta
= service
->getMetaClass();
235 array
= (OSArray
*) personalities
->getObject(meta
->getClassNameSymbol());
237 for (idx
= 0; (nextTable
= (OSDictionary
*) array
->getObject(idx
)); idx
++) {
238 set
->setObject(nextTable
);
241 if (meta
== &IOService::gMetaClass
) {
244 meta
= meta
->getSuperClass();
247 *generationCount
= getGenerationCount();
249 IORWLockUnlock(lock
);
254 /*********************************************************************
255 * Is personality already in the catalog?
256 *********************************************************************/
258 IOCatalogue::findDrivers(
259 OSDictionary
* matching
,
260 SInt32
* generationCount
)
262 OSSharedPtr
<OSCollectionIterator
> iter
;
264 OSSharedPtr
<OSOrderedSet
> set
;
266 const OSSymbol
* key
;
269 OSKext::uniquePersonalityProperties(matching
);
271 set
= OSOrderedSet::withCapacity( 1, IOServiceOrdering
,
272 (void *)(gIOProbeScoreKey
.get()));
276 iter
= OSCollectionIterator::withCollection(personalities
.get());
282 while ((key
= (const OSSymbol
*) iter
->getNextObject())) {
283 array
= (OSArray
*) personalities
->getObject(key
);
285 for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++) {
286 /* This comparison must be done with only the keys in the
287 * "matching" dict to enable general searches.
289 if (dict
->isEqualTo(matching
, matching
)) {
290 set
->setObject(dict
);
295 *generationCount
= getGenerationCount();
296 IORWLockUnlock(lock
);
301 /*********************************************************************
302 * Add driver config tables to catalog and start matching process.
304 * Important that existing personalities are kept (not replaced)
305 * if duplicates found. Personalities can come from OSKext objects
306 * or from userland kext library. We want to minimize distinct
307 * copies between OSKext & IOCatalogue.
309 * xxx - userlib used to refuse to send personalities with IOKitDebug
310 * xxx - during safe boot. That would be better implemented here.
311 *********************************************************************/
314 IOCatalogue::addDrivers(
319 OSSharedPtr
<OSOrderedSet
> set
;
320 OSSharedPtr
<OSCollectionIterator
> iter
;
321 OSObject
* object
= NULL
; // do not release
322 OSArray
* persons
= NULL
;// do not release
324 persons
= OSDynamicCast(OSArray
, drivers
);
329 set
= OSOrderedSet::withCapacity( 10, IOServiceOrdering
,
330 (void *)(gIOProbeScoreKey
.get()));
335 iter
= OSCollectionIterator::withCollection(persons
);
340 /* Start with success; clear it on an error.
345 while ((object
= iter
->getNextObject())) {
346 // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL
348 OSDictionary
* personality
= OSDynamicCast(OSDictionary
, object
);
353 IOLog("IOCatalogue::addDrivers() encountered non-dictionary; bailing.\n");
358 OSKext::uniquePersonalityProperties(personality
);
360 // Add driver personality to catalogue.
362 OSArray
* array
= arrayForPersonality(personality
);
364 addPersonality(personality
);
366 count
= array
->getCount();
368 OSDictionary
* driver
;
370 // Be sure not to double up on personalities.
371 driver
= (OSDictionary
*)array
->getObject(count
);
373 /* Unlike in other functions, this comparison must be exact!
374 * The catalogue must be able to contain personalities that
375 * are proper supersets of others.
376 * Do not compare just the properties present in one driver
377 * personality or the other.
379 if (personality
->isEqualTo(driver
)) {
387 result
= array
->setObject(personality
);
393 set
->setObject(personality
);
395 // Start device matching.
396 if (result
&& doNubMatching
&& (set
->getCount() > 0)) {
397 IOService::catalogNewDrivers(set
.get());
400 IORWLockUnlock(lock
);
408 IOCatalogue::removeDrivers(bool doNubMatching
, bool (^shouldRemove
)(OSDictionary
*personality
))
410 OSSharedPtr
<OSOrderedSet
> set
;
411 OSSharedPtr
<OSCollectionIterator
> iter
;
414 const OSSymbol
* key
;
417 set
= OSOrderedSet::withCapacity(10,
419 (void *)(gIOProbeScoreKey
.get()));
423 iter
= OSCollectionIterator::withCollection(personalities
.get());
429 while ((key
= (const OSSymbol
*) iter
->getNextObject())) {
430 array
= (OSArray
*) personalities
->getObject(key
);
432 for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++) {
433 if (shouldRemove(dict
)) {
434 set
->setObject(dict
);
435 array
->removeObject(idx
);
440 // Start device matching.
441 if (doNubMatching
&& (set
->getCount() > 0)) {
442 IOService::catalogNewDrivers(set
.get());
446 IORWLockUnlock(lock
);
451 /*********************************************************************
452 * Remove drivers from the catalog which match the
453 * properties in the matching dictionary.
454 *********************************************************************/
456 IOCatalogue::removeDrivers(
457 OSDictionary
* matching
,
463 return removeDrivers(doNubMatching
, ^(OSDictionary
*dict
) {
464 /* This comparison must be done with only the keys in the
465 * "matching" dict to enable general searches.
467 return dict
->isEqualTo(matching
, matching
);
471 // Return the generation count.
473 IOCatalogue::getGenerationCount(void) const
478 // Check to see if kernel module has been loaded already, and request its load.
480 IOCatalogue::isModuleLoaded(OSDictionary
* driver
, OSObject
** kextRef
) const
482 OSString
* moduleName
= NULL
;
483 OSString
* publisherName
= NULL
;
493 /* The personalities of codeless kexts often contain the bundle ID of the
494 * kext they reference, and not the bundle ID of the codeless kext itself.
495 * The prelinked kernel needs to know the bundle ID of the codeless kext
496 * so it can include these personalities, so OSKext stores that bundle ID
497 * in the IOPersonalityPublisher key, and we record it as requested here.
499 publisherName
= OSDynamicCast(OSString
,
500 driver
->getObject(kIOPersonalityPublisherKey
));
501 OSKext::recordIdentifierRequest(publisherName
);
503 moduleName
= OSDynamicCast(OSString
, driver
->getObject(gIOModuleIdentifierKernelKey
.get()));
505 ret
= OSKext::loadKextWithIdentifier(moduleName
, kextRef
);
506 if (kOSKextReturnDeferred
== ret
) {
507 // a request has been queued but the module isn't necessarily
508 // loaded yet, so stall.
511 OSString
*moduleDextName
= OSDynamicCast(OSString
, driver
->getObject(gIOModuleIdentifierKey
.get()));
512 if (moduleDextName
&& !(moduleName
->isEqualTo(moduleDextName
))) {
513 OSSharedPtr
<OSObject
> dextRef
;
514 ret
= OSKext::loadKextWithIdentifier(moduleDextName
, dextRef
);
516 // module is present or never will be
520 /* If a personality doesn't hold the "CFBundleIdentifier" or "CFBundleIdentifierKernel" key
521 * it is assumed to be an "in-kernel" driver.
527 IOCatalogue::isModuleLoaded(OSDictionary
* driver
, OSSharedPtr
<OSObject
>& kextRef
) const
529 OSObject
* kextRefRaw
= NULL
;
530 bool result
= isModuleLoaded(driver
, &kextRefRaw
);
531 kextRef
.reset(kextRefRaw
, OSNoRetain
);
535 /* This function is called after a module has been loaded.
536 * Is invoked from user client call, ultimately from IOKitLib's
537 * IOCatalogueModuleLoaded(). Sent from kextd.
540 IOCatalogue::moduleHasLoaded(const OSSymbol
* moduleName
)
542 startMatching(moduleName
);
544 (void) OSKext::setDeferredLoadSucceeded();
545 (void) OSKext::considerRebuildOfPrelinkedKernel();
549 IOCatalogue::moduleHasLoaded(const char * moduleName
)
551 OSSharedPtr
<const OSSymbol
> name
;
553 name
= OSSymbol::withCString(moduleName
);
554 moduleHasLoaded(name
.get());
557 // xxx - return is really OSReturn/kern_return_t
559 IOCatalogue::unloadModule(OSString
* moduleName
) const
561 return OSKext::removeKextWithIdentifier(moduleName
->getCStringNoCopy());
565 IOCatalogue::terminateDrivers(OSDictionary
* matching
, io_name_t className
)
568 OSSharedPtr
<OSIterator
> iter
;
572 ret
= kIOReturnSuccess
;
574 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
575 kIORegistryIterateRecursively
);
577 return kIOReturnNoMemory
;
581 OSKext::uniquePersonalityProperties( matching
, false );
584 // terminate instances.
587 while ((service
= (IOService
*)iter
->getNextObject())) {
588 if (className
&& !service
->metaCast(className
)) {
592 /* Terminate only for personalities that match the matching dictionary.
593 * This comparison must be done with only the keys in the
594 * "matching" dict to enable general matching.
596 dict
= service
->getPropertyTable();
600 if (!dict
->isEqualTo(matching
, matching
)) {
606 OSSharedPtr
<OSString
> dextBundleID
;
607 const char * bundleIDStr
;
610 bool isDext
= service
->hasUserServer();
611 for (okToTerminate
= true;;) {
613 dextBundleID
= OSDynamicPtrCast
<OSString
>(service
->copyProperty(gIOModuleIdentifierKey
.get()));
617 bundleIDStr
= dextBundleID
->getCStringNoCopy();
619 kext
= service
->getMetaClass()->getKext();
623 bundleIDStr
= kext
->getIdentifierCString();
624 prop
= kext
->getPropertyForHostArch(kOSBundleAllowUserTerminateKey
);
626 okToTerminate
= (kOSBooleanTrue
== prop
);
633 if (!strcmp(kOSKextKernelIdentifier
, bundleIDStr
)) {
634 okToTerminate
= false;
637 if (!strncmp("com.apple.", bundleIDStr
, strlen("com.apple."))) {
638 okToTerminate
= false;
643 if (!okToTerminate
) {
644 #if DEVELOPMENT || DEBUG
645 okToTerminate
= true;
646 #endif /* DEVELOPMENT || DEBUG */
647 IOLog("%sallowing kextunload terminate for bundleID %s\n",
648 okToTerminate
? "" : "dis", bundleIDStr
? bundleIDStr
: "?");
649 if (!okToTerminate
) {
650 ret
= kIOReturnUnsupported
;
654 IOOptionBits terminateOptions
= kIOServiceRequired
| kIOServiceSynchronous
;
656 terminateOptions
|= kIOServiceTerminateNeedWillTerminate
;
658 if (!service
->terminate(terminateOptions
)) {
659 ret
= kIOReturnUnsupported
;
663 } while (!service
&& !iter
->isValid());
669 IOCatalogue::_removeDrivers(OSDictionary
* matching
)
671 IOReturn ret
= kIOReturnSuccess
;
672 OSSharedPtr
<OSCollectionIterator
> iter
;
675 const OSSymbol
* key
;
678 // remove configs from catalog.
680 iter
= OSCollectionIterator::withCollection(personalities
.get());
682 return kIOReturnNoMemory
;
685 while ((key
= (const OSSymbol
*) iter
->getNextObject())) {
686 array
= (OSArray
*) personalities
->getObject(key
);
688 for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++) {
689 /* Remove from the catalogue's array any personalities
690 * that match the matching dictionary.
691 * This comparison must be done with only the keys in the
692 * "matching" dict to enable general matching.
694 if (dict
->isEqualTo(matching
, matching
)) {
695 array
->removeObject(idx
);
706 IOCatalogue::terminateDrivers(OSDictionary
* matching
)
711 return kIOReturnBadArgument
;
713 ret
= terminateDrivers(matching
, NULL
);
715 if (kIOReturnSuccess
== ret
) {
716 ret
= _removeDrivers(matching
);
718 IORWLockUnlock(lock
);
724 IOCatalogue::terminateDriversForUserspaceReboot()
726 IOReturn ret
= kIOReturnSuccess
;
729 OSSharedPtr
<OSIterator
> iter
;
731 bool isDeferredMatch
;
733 IOOptionBits terminateOptions
;
735 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
736 kIORegistryIterateRecursively
);
738 return kIOReturnNoMemory
;
743 while ((service
= (IOService
*)iter
->getNextObject())) {
744 isDeferredMatch
= service
->propertyHasValue(gIOMatchDeferKey
, kOSBooleanTrue
);
745 isDext
= service
->hasUserServer();
746 if (isDeferredMatch
|| isDext
) {
748 OSSharedPtr
<OSString
> name
= OSDynamicPtrCast
<OSString
>(service
->copyProperty(gIOUserServerNameKey
));
749 const char *userServerName
= NULL
;
751 userServerName
= name
->getCStringNoCopy();
753 IOLog("terminating service %s-0x%llx [dext %s]\n", service
->getName(), service
->getRegistryEntryID(), userServerName
? userServerName
: "(null)");
755 OSKext
*kext
= service
->getMetaClass()->getKext();
756 const char *bundleID
= NULL
;
758 bundleID
= kext
->getIdentifierCString();
760 IOLog("terminating service %s-0x%llx [kext %s]\n", service
->getName(), service
->getRegistryEntryID(), bundleID
? bundleID
: "(null)");
762 terminateOptions
= kIOServiceRequired
| kIOServiceSynchronous
;
764 terminateOptions
|= kIOServiceTerminateNeedWillTerminate
;
766 if (!service
->terminate(terminateOptions
)) {
767 IOLog("failed to terminate service %s-0x%llx\n", service
->getName(), service
->getRegistryEntryID());
768 ret
= kIOReturnUnsupported
;
773 } while (!service
&& !iter
->isValid());
780 IOCatalogue::resetAfterUserspaceReboot(void)
782 OSSharedPtr
<OSIterator
> iter
;
785 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
786 kIORegistryIterateRecursively
);
788 return kIOReturnNoMemory
;
793 while ((service
= (IOService
*)iter
->getNextObject())) {
794 service
->resetRematchProperties();
796 } while (!service
&& !iter
->isValid());
798 /* Remove all dext personalities */
799 removeDrivers(false, ^(OSDictionary
*dict
) {
800 return dict
->getObject(gIOUserServerNameKey
) != NULL
;
803 return kIOReturnSuccess
;
807 IOCatalogue::terminateDriversForModule(
808 OSString
* moduleName
,
812 OSSharedPtr
<OSDictionary
> dict
;
813 OSSharedPtr
<OSKext
> kext
;
814 bool isLoaded
= false;
817 /* Check first if the kext currently has any linkage dependents;
818 * in such a case the unload would fail so let's not terminate any
819 * IOServices (since doing so typically results in a panic when there
820 * are loaded dependencies). Note that we aren't locking the kext here
821 * so it might lose or gain dependents by the time we call unloadModule();
822 * I think that's ok, our unload can fail if a kext comes in on top of
823 * this one even after we've torn down IOService objects. Conversely,
824 * if we fail the unload here and then lose a library, the autounload
825 * thread will get us in short order.
827 if (OSKext::isKextWithIdentifierLoaded(moduleName
->getCStringNoCopy())) {
830 if (!OSKext::canUnloadKextWithIdentifier(moduleName
,
831 /* checkClasses */ false)) {
832 ret
= kOSKextReturnInUse
;
836 kext
= OSKext::lookupKextWithIdentifier(moduleName
->getCStringNoCopy());
838 isDext
= kext
->isDriverKit();
841 dict
= OSDictionary::withCapacity(1);
843 ret
= kIOReturnNoMemory
;
847 dict
->setObject(gIOModuleIdentifierKey
.get(), moduleName
);
849 ret
= terminateDrivers(dict
.get(), NULL
);
852 /* Force rematching after removing personalities. Dexts are never considered to be "loaded" (from OSKext),
853 * so we can't call unloadModule() to remove personalities and start rematching. */
854 removeDrivers(dict
.get(), true);
856 /* No goto between IOLock calls!
859 if (kIOReturnSuccess
== ret
) {
860 ret
= _removeDrivers(dict
.get());
863 // Unload the module itself.
864 if (unload
&& isLoaded
&& ret
== kIOReturnSuccess
) {
865 ret
= unloadModule(moduleName
);
867 IORWLockUnlock(lock
);
875 IOCatalogue::terminateDriversForModule(
876 const char * moduleName
,
879 OSSharedPtr
<OSString
> name
;
882 name
= OSString::withCString(moduleName
);
884 return kIOReturnNoMemory
;
887 ret
= terminateDriversForModule(name
.get(), unload
);
892 #if defined(__i386__) || defined(__x86_64__)
894 IOCatalogue::startMatching( OSDictionary
* matching
)
896 OSSharedPtr
<OSOrderedSet
> set
;
902 set
= OSOrderedSet::withCapacity(10, IOServiceOrdering
,
903 (void *)(gIOProbeScoreKey
.get()));
910 personalities
->iterateObjects(^bool (const OSSymbol
* key
, OSObject
* value
) {
915 array
= (OSArray
*) value
;
916 for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++) {
917 /* This comparison must be done with only the keys in the
918 * "matching" dict to enable general matching.
920 if (dict
->isEqualTo(matching
, matching
)) {
921 set
->setObject(dict
);
927 // Start device matching.
928 if (set
->getCount() > 0) {
929 IOService::catalogNewDrivers(set
.get());
933 IORWLockUnlock(lock
);
937 #endif /* defined(__i386__) || defined(__x86_64__) */
940 IOCatalogue::startMatching( const OSSymbol
* moduleName
)
942 OSSharedPtr
<OSOrderedSet
> set
;
943 OSSharedPtr
<OSKext
> kext
;
944 OSSharedPtr
<OSArray
> servicesToTerminate
;
950 set
= OSOrderedSet::withCapacity(10, IOServiceOrdering
,
951 (void *)(gIOProbeScoreKey
.get()));
958 kext
= OSKext::lookupKextWithIdentifier(moduleName
->getCStringNoCopy());
959 if (kext
&& kext
->isDriverKit()) {
960 /* We're here because kernelmanagerd called IOCatalogueModuleLoaded after launching a dext.
961 * Determine what providers the dext would match against. If there's something already attached
962 * to the provider, terminate it.
964 * This is only safe to do for HID dexts.
966 OSSharedPtr
<OSArray
> dextPersonalities
= kext
->copyPersonalitiesArray();
968 if (!dextPersonalities
) {
972 servicesToTerminate
= OSArray::withCapacity(1);
973 if (!servicesToTerminate
) {
977 dextPersonalities
->iterateObjects(^bool (OSObject
* obj
) {
978 OSDictionary
* personality
= OSDynamicCast(OSDictionary
, obj
);
979 OSSharedPtr
<OSIterator
> iter
;
980 IOService
* provider
;
981 OSSharedPtr
<IOService
> service
;
982 const OSSymbol
* category
;
985 category
= OSDynamicCast(OSSymbol
, personality
->getObject(gIOMatchCategoryKey
));
987 category
= gIODefaultMatchCategoryKey
;
989 iter
= IOService::getMatchingServices(personality
);
991 while (iter
&& (provider
= OSDynamicCast(IOService
, iter
->getNextObject()))) {
992 if (provider
->metaCast(gIOHIDInterfaceClassName
.get()) != NULL
) {
993 service
.reset(provider
->copyClientWithCategory(category
), OSNoRetain
);
995 servicesToTerminate
->setObject(service
);
1005 personalities
->iterateObjects(^bool (const OSSymbol
* key
, OSObject
* value
) {
1007 OSDictionary
* dict
;
1008 OSObject
* moduleIdentifierKernel
;
1009 OSObject
* moduleIdentifier
;
1012 array
= (OSArray
*) value
;
1013 for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++) {
1014 moduleIdentifierKernel
= dict
->getObject(gIOModuleIdentifierKernelKey
.get());
1015 moduleIdentifier
= dict
->getObject(gIOModuleIdentifierKey
.get());
1016 if ((moduleIdentifierKernel
&& moduleName
->isEqualTo(moduleIdentifierKernel
)) ||
1017 (moduleIdentifier
&& moduleName
->isEqualTo(moduleIdentifier
))) {
1018 set
->setObject(dict
);
1024 if (servicesToTerminate
) {
1025 servicesToTerminate
->iterateObjects(^bool (OSObject
* obj
) {
1026 IOService
* service
= OSDynamicCast(IOService
, obj
);
1028 IOOptionBits terminateOptions
= kIOServiceRequired
;
1029 if (service
->hasUserServer()) {
1030 terminateOptions
|= kIOServiceTerminateNeedWillTerminate
;
1032 if (!service
->terminate(terminateOptions
)) {
1033 IOLog("%s: failed to terminate service %s-0x%qx with options %08llx for new dext %s\n", __FUNCTION__
, service
->getName(), service
->getRegistryEntryID(), (long long)terminateOptions
, moduleName
->getCStringNoCopy());
1040 // Start device matching.
1041 if (set
->getCount() > 0) {
1042 IOService::catalogNewDrivers(set
.get());
1046 IORWLockUnlock(lock
);
1052 IOCatalogue::reset(void)
1054 IOCatalogue::resetAndAddDrivers(/* no drivers; true reset */ NULL
,
1055 /* doMatching */ false);
1060 IOCatalogue::resetAndAddDrivers(OSArray
* drivers
, bool doNubMatching
)
1062 bool result
= false;
1063 OSArray
* newPersonalities
= NULL
;// do not release
1064 const OSSymbol
* key
;
1066 OSDictionary
* thisNewPersonality
= NULL
;// do not release
1067 OSDictionary
* thisOldPersonality
= NULL
;// do not release
1068 OSSharedPtr
<OSDictionary
> myKexts
;
1069 OSSharedPtr
<OSCollectionIterator
> iter
;
1070 OSSharedPtr
<OSOrderedSet
> matchSet
;
1071 signed int idx
, newIdx
;
1074 newPersonalities
= OSDynamicCast(OSArray
, drivers
);
1075 if (!newPersonalities
) {
1079 matchSet
= OSOrderedSet::withCapacity(10, IOServiceOrdering
,
1080 (void *)(gIOProbeScoreKey
.get()));
1084 iter
= OSCollectionIterator::withCollection(personalities
.get());
1089 /* need copy of loaded kexts so we can check if for loaded modules without
1090 * taking the OSKext lock. There is a potential of deadlocking if we get
1091 * an OSKext via the normal path. See 14672140.
1093 myKexts
= OSKext::copyKexts();
1097 IOLog("Resetting IOCatalogue.\n");
1099 /* No goto finish from here to unlock.
1101 IORWLockWrite(lock
);
1103 while ((key
= (const OSSymbol
*) iter
->getNextObject())) {
1104 array
= (OSArray
*) personalities
->getObject(key
);
1110 (thisOldPersonality
= (OSDictionary
*) array
->getObject(idx
));
1112 if (thisOldPersonality
->getObject("KernelConfigTable")) {
1115 thisNewPersonality
= NULL
;
1117 if (newPersonalities
) {
1119 (thisNewPersonality
= (OSDictionary
*) newPersonalities
->getObject(newIdx
));
1121 /* Unlike in other functions, this comparison must be exact!
1122 * The catalogue must be able to contain personalities that
1123 * are proper supersets of others.
1124 * Do not compare just the properties present in one driver
1125 * personality or the other.
1127 if (OSDynamicCast(OSDictionary
, thisNewPersonality
) == NULL
) {
1128 /* skip thisNewPersonality if it is not an OSDictionary */
1131 if (thisNewPersonality
->isEqualTo(thisOldPersonality
)) {
1136 if (thisNewPersonality
) {
1138 newPersonalities
->removeObject(newIdx
);
1140 // not in new set - remove
1141 // only remove dictionary if this module in not loaded - 9953845
1142 if (isModuleLoadedNoOSKextLock(myKexts
.get(), thisOldPersonality
) == false) {
1144 matchSet
->setObject(thisOldPersonality
);
1146 array
->removeObject(idx
);
1154 if (newPersonalities
) {
1156 (thisNewPersonality
= (OSDictionary
*) newPersonalities
->getObject(newIdx
));
1158 if (OSDynamicCast(OSDictionary
, thisNewPersonality
) == NULL
) {
1159 /* skip thisNewPersonality if it is not an OSDictionary */
1163 OSKext::uniquePersonalityProperties(thisNewPersonality
);
1164 addPersonality(thisNewPersonality
);
1165 matchSet
->setObject(thisNewPersonality
);
1169 /* Finally, start device matching on all new & removed personalities.
1171 if (result
&& doNubMatching
&& (matchSet
->getCount() > 0)) {
1172 IOService::catalogNewDrivers(matchSet
.get());
1176 IORWLockUnlock(lock
);
1184 IOCatalogue::serialize(OSSerialize
* s
) const
1190 return super::serialize(s
);
1194 IOCatalogue::serializeData(IOOptionBits kind
, OSSerialize
* s
) const
1196 kern_return_t kr
= kIOReturnSuccess
;
1199 case kIOCatalogGetContents
:
1200 kr
= KERN_NOT_SUPPORTED
;
1203 case kIOCatalogGetModuleDemandList
:
1204 kr
= KERN_NOT_SUPPORTED
;
1207 case kIOCatalogGetCacheMissList
:
1208 kr
= KERN_NOT_SUPPORTED
;
1211 case kIOCatalogGetROMMkextList
:
1212 kr
= KERN_NOT_SUPPORTED
;
1216 kr
= kIOReturnBadArgument
;
1223 /* isModuleLoadedNoOSKextLock - used to check to see if a kext is loaded
1224 * without taking the OSKext lock. We use this to avoid the problem
1225 * where taking the IOCatalog lock then the OSKext lock will dealock when
1226 * a kext load or unload is happening at the same time as IOCatalog changing.
1228 * theKexts - is a dictionary of current kexts (from OSKext::copyKexts) with
1229 * key set to the kext bundle ID and value set to an OSKext object
1230 * theModuleDict - is an IOKit personality dictionary for a given module (kext)
1233 isModuleLoadedNoOSKextLock(OSDictionary
*theKexts
,
1234 OSDictionary
*theModuleDict
)
1236 bool myResult
= false;
1237 const OSString
* myBundleID
= NULL
;// do not release
1238 OSKext
* myKext
= NULL
; // do not release
1240 if (theKexts
== NULL
|| theModuleDict
== NULL
) {
1244 // gIOModuleIdentifierKey is "CFBundleIdentifier"
1245 myBundleID
= OSDynamicCast(OSString
,
1246 theModuleDict
->getObject(gIOModuleIdentifierKey
.get()));
1247 if (myBundleID
== NULL
) {
1251 myKext
= OSDynamicCast(OSKext
, theKexts
->getObject(myBundleID
->getCStringNoCopy()));
1253 myResult
= myKext
->isLoaded();
1261 #pragma mark Obsolete Kext Loading Stuff
1263 /*********************************************************************
1264 **********************************************************************
1265 *** BINARY COMPATIBILITY SECTION ***
1266 **********************************************************************
1267 **********************************************************************
1268 * These functions are no longer used are necessary for C++ binary
1269 * compatibility on i386.
1270 **********************************************************************/