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,
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 const OSSymbol
* gIOModuleIdentifierKernelKey
;
72 IORWLock
* gIOCatalogLock
;
75 #pragma mark Utility functions
79 #pragma mark IOCatalogue class implementation
81 /*********************************************************************
82 *********************************************************************/
84 #define super OSObject
85 OSDefineMetaClassAndStructors(IOCatalogue
, OSObject
)
87 static bool isModuleLoadedNoOSKextLock(OSDictionary
*theKexts
,
88 OSDictionary
*theModuleDict
);
91 /*********************************************************************
92 *********************************************************************/
94 IOCatalogue::initialize(void)
97 OSString
* errorString
;
100 extern const char * gIOKernelConfigTables
;
102 array
= OSDynamicCast(OSArray
, OSUnserialize(gIOKernelConfigTables
, &errorString
));
103 if (!array
&& errorString
) {
104 IOLog("KernelConfigTables syntax error: %s\n",
105 errorString
->getCStringNoCopy());
106 errorString
->release();
109 gIOClassKey
= OSSymbol::withCStringNoCopy( kIOClassKey
);
110 gIOProbeScoreKey
= OSSymbol::withCStringNoCopy( kIOProbeScoreKey
);
111 gIOModuleIdentifierKey
= OSSymbol::withCStringNoCopy( kCFBundleIdentifierKey
);
112 gIOModuleIdentifierKernelKey
= OSSymbol::withCStringNoCopy( kCFBundleIdentifierKernelKey
);
115 assert( array
&& gIOClassKey
&& gIOProbeScoreKey
116 && gIOModuleIdentifierKey
);
118 gIOCatalogue
= new IOCatalogue
;
119 assert(gIOCatalogue
);
120 rc
= gIOCatalogue
->init(array
);
125 /*********************************************************************
126 * Initialize the IOCatalog object.
127 *********************************************************************/
129 IOCatalogue::arrayForPersonality(OSDictionary
* dict
)
131 const OSSymbol
* sym
;
133 sym
= OSDynamicCast(OSSymbol
, dict
->getObject(gIOProviderClassKey
));
138 return (OSArray
*) personalities
->getObject(sym
);
142 IOCatalogue::addPersonality(OSDictionary
* dict
)
144 const OSSymbol
* sym
;
147 sym
= OSDynamicCast(OSSymbol
, dict
->getObject(gIOProviderClassKey
));
151 arr
= (OSArray
*) personalities
->getObject(sym
);
153 arr
->setObject(dict
);
155 arr
= OSArray::withObjects((const OSObject
**)&dict
, 1, 2);
156 personalities
->setObject(sym
, arr
);
161 /*********************************************************************
162 * Initialize the IOCatalog object.
163 *********************************************************************/
165 IOCatalogue::init(OSArray
* initArray
)
170 if (!super::init()) {
176 personalities
= OSDictionary::withCapacity(32);
177 personalities
->setOptions(OSCollection::kSort
, OSCollection::kSort
);
178 for (unsigned int idx
= 0; (obj
= initArray
->getObject(idx
)); idx
++) {
179 dict
= OSDynamicCast(OSDictionary
, obj
);
183 OSKext::uniquePersonalityProperties(dict
);
184 if (NULL
== dict
->getObject( gIOClassKey
)) {
185 IOLog("Missing or bad \"%s\" key\n",
186 gIOClassKey
->getCStringNoCopy());
189 dict
->setObject("KernelConfigTable", kOSBooleanTrue
);
190 addPersonality(dict
);
193 gIOCatalogLock
= IORWLockAlloc();
194 lock
= gIOCatalogLock
;
199 /*********************************************************************
200 * Release all resources used by IOCatalogue and deallocate.
201 * This will probably never be called.
202 *********************************************************************/
204 IOCatalogue::free( void )
209 /*********************************************************************
210 *********************************************************************/
212 IOCatalogue::findDrivers(
214 SInt32
* generationCount
)
216 OSDictionary
* nextTable
;
219 const OSMetaClass
* meta
;
222 set
= OSOrderedSet::withCapacity( 1, IOServiceOrdering
,
223 (void *)gIOProbeScoreKey
);
230 meta
= service
->getMetaClass();
232 array
= (OSArray
*) personalities
->getObject(meta
->getClassNameSymbol());
234 for (idx
= 0; (nextTable
= (OSDictionary
*) array
->getObject(idx
)); idx
++) {
235 set
->setObject(nextTable
);
238 if (meta
== &IOService::gMetaClass
) {
241 meta
= meta
->getSuperClass();
244 *generationCount
= getGenerationCount();
246 IORWLockUnlock(lock
);
251 /*********************************************************************
252 * Is personality already in the catalog?
253 *********************************************************************/
255 IOCatalogue::findDrivers(
256 OSDictionary
* matching
,
257 SInt32
* generationCount
)
259 OSCollectionIterator
* iter
;
263 const OSSymbol
* key
;
266 OSKext::uniquePersonalityProperties(matching
);
268 set
= OSOrderedSet::withCapacity( 1, IOServiceOrdering
,
269 (void *)gIOProbeScoreKey
);
273 iter
= OSCollectionIterator::withCollection(personalities
);
280 while ((key
= (const OSSymbol
*) iter
->getNextObject())) {
281 array
= (OSArray
*) personalities
->getObject(key
);
283 for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++) {
284 /* This comparison must be done with only the keys in the
285 * "matching" dict to enable general searches.
287 if (dict
->isEqualTo(matching
, matching
)) {
288 set
->setObject(dict
);
293 *generationCount
= getGenerationCount();
294 IORWLockUnlock(lock
);
300 /*********************************************************************
301 * Add driver config tables to catalog and start matching process.
303 * Important that existing personalities are kept (not replaced)
304 * if duplicates found. Personalities can come from OSKext objects
305 * or from userland kext library. We want to minimize distinct
306 * copies between OSKext & IOCatalogue.
308 * xxx - userlib used to refuse to send personalities with IOKitDebug
309 * xxx - during safe boot. That would be better implemented here.
310 *********************************************************************/
313 IOCatalogue::addDrivers(
318 OSCollectionIterator
* iter
= NULL
; // must release
319 OSOrderedSet
* set
= NULL
; // must release
320 OSObject
* object
= NULL
; // do not release
321 OSArray
* persons
= NULL
;// do not release
323 persons
= OSDynamicCast(OSArray
, drivers
);
328 set
= OSOrderedSet::withCapacity( 10, IOServiceOrdering
,
329 (void *)gIOProbeScoreKey
);
334 iter
= OSCollectionIterator::withCollection(persons
);
339 /* Start with success; clear it on an error.
344 while ((object
= iter
->getNextObject())) {
345 // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL
347 OSDictionary
* personality
= OSDynamicCast(OSDictionary
, object
);
352 IOLog("IOCatalogue::addDrivers() encountered non-dictionary; bailing.\n");
357 OSKext::uniquePersonalityProperties(personality
);
359 // Add driver personality to catalogue.
361 OSArray
* array
= arrayForPersonality(personality
);
363 addPersonality(personality
);
365 count
= array
->getCount();
367 OSDictionary
* driver
;
369 // Be sure not to double up on personalities.
370 driver
= (OSDictionary
*)array
->getObject(count
);
372 /* Unlike in other functions, this comparison must be exact!
373 * The catalogue must be able to contain personalities that
374 * are proper supersets of others.
375 * Do not compare just the properties present in one driver
376 * personality or the other.
378 if (personality
->isEqualTo(driver
)) {
386 result
= array
->setObject(personality
);
392 set
->setObject(personality
);
394 // Start device matching.
395 if (result
&& doNubMatching
&& (set
->getCount() > 0)) {
396 IOService::catalogNewDrivers(set
);
399 IORWLockUnlock(lock
);
412 /*********************************************************************
413 * Remove drivers from the catalog which match the
414 * properties in the matching dictionary.
415 *********************************************************************/
417 IOCatalogue::removeDrivers(
418 OSDictionary
* matching
,
422 OSCollectionIterator
* iter
;
425 const OSSymbol
* key
;
432 set
= OSOrderedSet::withCapacity(10,
434 (void *)gIOProbeScoreKey
);
438 iter
= OSCollectionIterator::withCollection(personalities
);
445 while ((key
= (const OSSymbol
*) iter
->getNextObject())) {
446 array
= (OSArray
*) personalities
->getObject(key
);
448 for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++) {
449 /* This comparison must be done with only the keys in the
450 * "matching" dict to enable general searches.
452 if (dict
->isEqualTo(matching
, matching
)) {
453 set
->setObject(dict
);
454 array
->removeObject(idx
);
459 // Start device matching.
460 if (doNubMatching
&& (set
->getCount() > 0)) {
461 IOService::catalogNewDrivers(set
);
465 IORWLockUnlock(lock
);
473 // Return the generation count.
475 IOCatalogue::getGenerationCount(void) const
480 // Check to see if kernel module has been loaded already, and request its load.
482 IOCatalogue::isModuleLoaded(OSDictionary
* driver
, OSObject
** kextRef
) const
484 OSString
* moduleName
= NULL
;
485 OSString
* publisherName
= NULL
;
495 /* The personalities of codeless kexts often contain the bundle ID of the
496 * kext they reference, and not the bundle ID of the codeless kext itself.
497 * The prelinked kernel needs to know the bundle ID of the codeless kext
498 * so it can include these personalities, so OSKext stores that bundle ID
499 * in the IOPersonalityPublisher key, and we record it as requested here.
501 publisherName
= OSDynamicCast(OSString
,
502 driver
->getObject(kIOPersonalityPublisherKey
));
503 OSKext::recordIdentifierRequest(publisherName
);
505 moduleName
= OSDynamicCast(OSString
, driver
->getObject(gIOModuleIdentifierKernelKey
));
507 ret
= OSKext::loadKextWithIdentifier(moduleName
, kextRef
);
508 if (kOSKextReturnDeferred
== ret
) {
509 // a request has been queued but the module isn't necessarily
510 // loaded yet, so stall.
513 OSString
*moduleDextName
= OSDynamicCast(OSString
, driver
->getObject(gIOModuleIdentifierKey
));
514 if (moduleDextName
&& !(moduleName
->isEqualTo(moduleDextName
))) {
515 OSObject
*dextRef
= NULL
;
516 ret
= OSKext::loadKextWithIdentifier(moduleDextName
, &dextRef
);
517 OSSafeReleaseNULL(dextRef
);
519 // module is present or never will be
523 /* If a personality doesn't hold the "CFBundleIdentifier" or "CFBundleIdentifierKernel" key
524 * it is assumed to be an "in-kernel" driver.
529 /* This function is called after a module has been loaded.
530 * Is invoked from user client call, ultimately from IOKitLib's
531 * IOCatalogueModuleLoaded(). Sent from kextd.
534 IOCatalogue::moduleHasLoaded(const OSSymbol
* moduleName
)
536 startMatching(moduleName
);
538 (void) OSKext::setDeferredLoadSucceeded();
539 (void) OSKext::considerRebuildOfPrelinkedKernel();
543 IOCatalogue::moduleHasLoaded(const char * moduleName
)
545 const OSSymbol
* name
;
547 name
= OSSymbol::withCString(moduleName
);
548 moduleHasLoaded(name
);
552 // xxx - return is really OSReturn/kern_return_t
554 IOCatalogue::unloadModule(OSString
* moduleName
) const
556 return OSKext::removeKextWithIdentifier(moduleName
->getCStringNoCopy());
560 IOCatalogue::_terminateDrivers(OSDictionary
* matching
)
568 return kIOReturnBadArgument
;
571 ret
= kIOReturnSuccess
;
573 iter
= IORegistryIterator::iterateOver(gIOServicePlane
,
574 kIORegistryIterateRecursively
);
576 return kIOReturnNoMemory
;
579 OSKext::uniquePersonalityProperties( matching
);
581 // terminate instances.
584 while ((service
= (IOService
*)iter
->getNextObject())) {
585 dict
= service
->getPropertyTable();
590 /* Terminate only for personalities that match the matching dictionary.
591 * This comparison must be done with only the keys in the
592 * "matching" dict to enable general matching.
594 if (!dict
->isEqualTo(matching
, matching
)) {
598 if (!service
->terminate(kIOServiceRequired
| kIOServiceSynchronous
)) {
599 ret
= kIOReturnUnsupported
;
603 } while (!service
&& !iter
->isValid());
610 IOCatalogue::_removeDrivers(OSDictionary
* matching
)
612 IOReturn ret
= kIOReturnSuccess
;
613 OSCollectionIterator
* iter
;
616 const OSSymbol
* key
;
619 // remove configs from catalog.
621 iter
= OSCollectionIterator::withCollection(personalities
);
623 return kIOReturnNoMemory
;
626 while ((key
= (const OSSymbol
*) iter
->getNextObject())) {
627 array
= (OSArray
*) personalities
->getObject(key
);
629 for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++) {
630 /* Remove from the catalogue's array any personalities
631 * that match the matching dictionary.
632 * This comparison must be done with only the keys in the
633 * "matching" dict to enable general matching.
635 if (dict
->isEqualTo(matching
, matching
)) {
636 array
->removeObject(idx
);
648 IOCatalogue::terminateDrivers(OSDictionary
* matching
)
652 ret
= _terminateDrivers(matching
);
654 if (kIOReturnSuccess
== ret
) {
655 ret
= _removeDrivers(matching
);
657 IORWLockUnlock(lock
);
663 IOCatalogue::terminateDriversForModule(
664 OSString
* moduleName
,
669 bool isLoaded
= false;
671 /* Check first if the kext currently has any linkage dependents;
672 * in such a case the unload would fail so let's not terminate any
673 * IOServices (since doing so typically results in a panic when there
674 * are loaded dependencies). Note that we aren't locking the kext here
675 * so it might lose or gain dependents by the time we call unloadModule();
676 * I think that's ok, our unload can fail if a kext comes in on top of
677 * this one even after we've torn down IOService objects. Conversely,
678 * if we fail the unload here and then lose a library, the autounload
679 * thread will get us in short order.
681 if (OSKext::isKextWithIdentifierLoaded(moduleName
->getCStringNoCopy())) {
684 if (!OSKext::canUnloadKextWithIdentifier(moduleName
,
685 /* checkClasses */ false)) {
686 ret
= kOSKextReturnInUse
;
690 dict
= OSDictionary::withCapacity(1);
692 ret
= kIOReturnNoMemory
;
696 dict
->setObject(gIOModuleIdentifierKey
, moduleName
);
698 ret
= _terminateDrivers(dict
);
700 /* No goto between IOLock calls!
703 if (kIOReturnSuccess
== ret
) {
704 ret
= _removeDrivers(dict
);
707 // Unload the module itself.
708 if (unload
&& isLoaded
&& ret
== kIOReturnSuccess
) {
709 ret
= unloadModule(moduleName
);
712 IORWLockUnlock(lock
);
721 IOCatalogue::terminateDriversForModule(
722 const char * moduleName
,
728 name
= OSString::withCString(moduleName
);
730 return kIOReturnNoMemory
;
733 ret
= terminateDriversForModule(name
, unload
);
739 #if defined(__i386__) || defined(__x86_64__)
741 IOCatalogue::startMatching( OSDictionary
* matching
)
749 set
= OSOrderedSet::withCapacity(10, IOServiceOrdering
,
750 (void *)gIOProbeScoreKey
);
757 personalities
->iterateObjects(^bool (const OSSymbol
* key
, OSObject
* value
) {
762 array
= (OSArray
*) value
;
763 for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++) {
764 /* This comparison must be done with only the keys in the
765 * "matching" dict to enable general matching.
767 if (dict
->isEqualTo(matching
, matching
)) {
768 set
->setObject(dict
);
774 // Start device matching.
775 if (set
->getCount() > 0) {
776 IOService::catalogNewDrivers(set
);
780 IORWLockUnlock(lock
);
786 #endif /* defined(__i386__) || defined(__x86_64__) */
789 IOCatalogue::startMatching( const OSSymbol
* moduleName
)
797 set
= OSOrderedSet::withCapacity(10, IOServiceOrdering
,
798 (void *)gIOProbeScoreKey
);
805 personalities
->iterateObjects(^bool (const OSSymbol
* key
, OSObject
* value
) {
811 array
= (OSArray
*) value
;
812 for (idx
= 0; (dict
= (OSDictionary
*) array
->getObject(idx
)); idx
++) {
813 obj
= dict
->getObject(gIOModuleIdentifierKernelKey
);
814 if (obj
&& moduleName
->isEqualTo(obj
)) {
815 set
->setObject(dict
);
821 // Start device matching.
822 if (set
->getCount() > 0) {
823 IOService::catalogNewDrivers(set
);
827 IORWLockUnlock(lock
);
835 IOCatalogue::reset(void)
837 IOCatalogue::resetAndAddDrivers(/* no drivers; true reset */ NULL
,
838 /* doMatching */ false);
843 IOCatalogue::resetAndAddDrivers(OSArray
* drivers
, bool doNubMatching
)
846 OSArray
* newPersonalities
= NULL
;// do not release
847 OSCollectionIterator
* iter
= NULL
;// must release
848 OSOrderedSet
* matchSet
= NULL
;// must release
849 const OSSymbol
* key
;
851 OSDictionary
* thisNewPersonality
= NULL
;// do not release
852 OSDictionary
* thisOldPersonality
= NULL
;// do not release
853 OSDictionary
* myKexts
= NULL
;// must release
854 signed int idx
, newIdx
;
857 newPersonalities
= OSDynamicCast(OSArray
, drivers
);
858 if (!newPersonalities
) {
862 matchSet
= OSOrderedSet::withCapacity(10, IOServiceOrdering
,
863 (void *)gIOProbeScoreKey
);
867 iter
= OSCollectionIterator::withCollection(personalities
);
872 /* need copy of loaded kexts so we can check if for loaded modules without
873 * taking the OSKext lock. There is a potential of deadlocking if we get
874 * an OSKext via the normal path. See 14672140.
876 myKexts
= OSKext::copyKexts();
880 IOLog("Resetting IOCatalogue.\n");
882 /* No goto finish from here to unlock.
886 while ((key
= (const OSSymbol
*) iter
->getNextObject())) {
887 array
= (OSArray
*) personalities
->getObject(key
);
893 (thisOldPersonality
= (OSDictionary
*) array
->getObject(idx
));
895 if (thisOldPersonality
->getObject("KernelConfigTable")) {
898 thisNewPersonality
= NULL
;
900 if (newPersonalities
) {
902 (thisNewPersonality
= (OSDictionary
*) newPersonalities
->getObject(newIdx
));
904 /* Unlike in other functions, this comparison must be exact!
905 * The catalogue must be able to contain personalities that
906 * are proper supersets of others.
907 * Do not compare just the properties present in one driver
908 * personality or the other.
910 if (OSDynamicCast(OSDictionary
, thisNewPersonality
) == NULL
) {
911 /* skip thisNewPersonality if it is not an OSDictionary */
914 if (thisNewPersonality
->isEqualTo(thisOldPersonality
)) {
919 if (thisNewPersonality
) {
921 newPersonalities
->removeObject(newIdx
);
923 // not in new set - remove
924 // only remove dictionary if this module in not loaded - 9953845
925 if (isModuleLoadedNoOSKextLock(myKexts
, thisOldPersonality
) == false) {
927 matchSet
->setObject(thisOldPersonality
);
929 array
->removeObject(idx
);
937 if (newPersonalities
) {
939 (thisNewPersonality
= (OSDictionary
*) newPersonalities
->getObject(newIdx
));
941 if (OSDynamicCast(OSDictionary
, thisNewPersonality
) == NULL
) {
942 /* skip thisNewPersonality if it is not an OSDictionary */
946 OSKext::uniquePersonalityProperties(thisNewPersonality
);
947 addPersonality(thisNewPersonality
);
948 matchSet
->setObject(thisNewPersonality
);
952 /* Finally, start device matching on all new & removed personalities.
954 if (result
&& doNubMatching
&& (matchSet
->getCount() > 0)) {
955 IOService::catalogNewDrivers(matchSet
);
959 IORWLockUnlock(lock
);
976 IOCatalogue::serialize(OSSerialize
* s
) const
982 return super::serialize(s
);
986 IOCatalogue::serializeData(IOOptionBits kind
, OSSerialize
* s
) const
988 kern_return_t kr
= kIOReturnSuccess
;
991 case kIOCatalogGetContents
:
992 kr
= KERN_NOT_SUPPORTED
;
995 case kIOCatalogGetModuleDemandList
:
996 kr
= KERN_NOT_SUPPORTED
;
999 case kIOCatalogGetCacheMissList
:
1000 kr
= KERN_NOT_SUPPORTED
;
1003 case kIOCatalogGetROMMkextList
:
1004 kr
= KERN_NOT_SUPPORTED
;
1008 kr
= kIOReturnBadArgument
;
1015 /* isModuleLoadedNoOSKextLock - used to check to see if a kext is loaded
1016 * without taking the OSKext lock. We use this to avoid the problem
1017 * where taking the IOCatalog lock then the OSKext lock will dealock when
1018 * a kext load or unload is happening at the same time as IOCatalog changing.
1020 * theKexts - is a dictionary of current kexts (from OSKext::copyKexts) with
1021 * key set to the kext bundle ID and value set to an OSKext object
1022 * theModuleDict - is an IOKit personality dictionary for a given module (kext)
1025 isModuleLoadedNoOSKextLock(OSDictionary
*theKexts
,
1026 OSDictionary
*theModuleDict
)
1028 bool myResult
= false;
1029 const OSString
* myBundleID
= NULL
;// do not release
1030 OSKext
* myKext
= NULL
; // do not release
1032 if (theKexts
== NULL
|| theModuleDict
== NULL
) {
1036 // gIOModuleIdentifierKey is "CFBundleIdentifier"
1037 myBundleID
= OSDynamicCast(OSString
,
1038 theModuleDict
->getObject(gIOModuleIdentifierKey
));
1039 if (myBundleID
== NULL
) {
1043 myKext
= OSDynamicCast(OSKext
, theKexts
->getObject(myBundleID
->getCStringNoCopy()));
1045 myResult
= myKext
->isLoaded();
1053 #pragma mark Obsolete Kext Loading Stuff
1055 /*********************************************************************
1056 **********************************************************************
1057 *** BINARY COMPATIBILITY SECTION ***
1058 **********************************************************************
1059 **********************************************************************
1060 * These functions are no longer used are necessary for C++ binary
1061 * compatibility on i386.
1062 **********************************************************************/