]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOCatalogue.cpp
xnu-3789.51.2.tar.gz
[apple/xnu.git] / iokit / Kernel / IOCatalogue.cpp
CommitLineData
1c79356b 1/*
39236c6e 2 * Copyright (c) 1998-2012 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
b0d623f7 29 * Copyright (c) 1998 Apple Inc. All rights reserved.
1c79356b
A
30 *
31 * HISTORY
32 *
33 */
2d21ac55
A
34/*
35 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
36 * support for mandatory and extensible security protections. This notice
37 * is included in support of clause 2.2 (b) of the Apple Public License,
38 * Version 2.0.
39 */
1c79356b 40
1c79356b
A
41extern "C" {
42#include <machine/machine_routines.h>
b0d623f7 43#include <libkern/kernel_mach_header.h>
9bccf70c 44#include <kern/host.h>
2d21ac55 45#include <security/mac_data.h>
1c79356b
A
46};
47
b0d623f7
A
48#include <libkern/c++/OSContainers.h>
49#include <libkern/c++/OSUnserialize.h>
50#include <libkern/c++/OSKext.h>
51#include <libkern/OSKextLibPrivate.h>
316670eb 52#include <libkern/OSDebug.h>
1c79356b 53
b0d623f7
A
54#include <IOKit/IODeviceTreeSupport.h>
55#include <IOKit/IOService.h>
56#include <IOKit/IOCatalogue.h>
1c79356b 57
b0d623f7
A
58#include <IOKit/IOLib.h>
59#include <IOKit/assert.h>
1c79356b 60
b0d623f7
A
61#if PRAGMA_MARK
62#pragma mark Internal Declarations
63#endif
64/*********************************************************************
65*********************************************************************/
1c79356b 66
55e303ae
A
67IOCatalogue * gIOCatalogue;
68const OSSymbol * gIOClassKey;
69const OSSymbol * gIOProbeScoreKey;
70const OSSymbol * gIOModuleIdentifierKey;
316670eb 71IORWLock * gIOCatalogLock;
55e303ae 72
b0d623f7
A
73#if PRAGMA_MARK
74#pragma mark Utility functions
2d21ac55 75#endif
55e303ae 76
b0d623f7
A
77#if PRAGMA_MARK
78#pragma mark IOCatalogue class implementation
79#endif
55e303ae 80/*********************************************************************
55e303ae
A
81*********************************************************************/
82
b0d623f7
A
83#define super OSObject
84OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
55e303ae 85
fe8ab488
A
86static bool isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
87 OSDictionary *theModuleDict);
88
89
55e303ae
A
90/*********************************************************************
91*********************************************************************/
b0d623f7 92void IOCatalogue::initialize(void)
1c79356b
A
93{
94 OSArray * array;
95 OSString * errorString;
96 bool rc;
97
98 extern const char * gIOKernelConfigTables;
99
100 array = OSDynamicCast(OSArray, OSUnserialize(gIOKernelConfigTables, &errorString));
101 if (!array && errorString) {
b0d623f7
A
102 IOLog("KernelConfigTables syntax error: %s\n",
103 errorString->getCStringNoCopy());
104 errorString->release();
1c79356b
A
105 }
106
55e303ae
A
107 gIOClassKey = OSSymbol::withCStringNoCopy( kIOClassKey );
108 gIOProbeScoreKey = OSSymbol::withCStringNoCopy( kIOProbeScoreKey );
b0d623f7 109 gIOModuleIdentifierKey = OSSymbol::withCStringNoCopy( kCFBundleIdentifierKey );
55e303ae
A
110
111 assert( array && gIOClassKey && gIOProbeScoreKey
b0d623f7 112 && gIOModuleIdentifierKey);
1c79356b
A
113
114 gIOCatalogue = new IOCatalogue;
115 assert(gIOCatalogue);
116 rc = gIOCatalogue->init(array);
117 assert(rc);
118 array->release();
119}
120
316670eb
A
121/*********************************************************************
122* Initialize the IOCatalog object.
123*********************************************************************/
124OSArray * IOCatalogue::arrayForPersonality(OSDictionary * dict)
125{
126 const OSSymbol * sym;
127
128 sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
129 if (!sym) return (0);
130
131 return ((OSArray *) personalities->getObject(sym));
132}
133
134void IOCatalogue::addPersonality(OSDictionary * dict)
135{
136 const OSSymbol * sym;
137 OSArray * arr;
138
139 sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
140 if (!sym) return;
141 arr = (OSArray *) personalities->getObject(sym);
142 if (arr) arr->setObject(dict);
143 else
144 {
145 arr = OSArray::withObjects((const OSObject **)&dict, 1, 2);
146 personalities->setObject(sym, arr);
147 arr->release();
148 }
149}
150
b0d623f7
A
151/*********************************************************************
152* Initialize the IOCatalog object.
153*********************************************************************/
1c79356b
A
154bool IOCatalogue::init(OSArray * initArray)
155{
1c79356b 156 OSDictionary * dict;
316670eb
A
157 OSObject * obj;
158
1c79356b
A
159 if ( !super::init() )
160 return false;
161
162 generation = 1;
163
316670eb
A
164 personalities = OSDictionary::withCapacity(32);
165 personalities->setOptions(OSCollection::kSort, OSCollection::kSort);
166 for (unsigned int idx = 0; (obj = initArray->getObject(idx)); idx++)
167 {
168 dict = OSDynamicCast(OSDictionary, obj);
169 if (!dict) continue;
170 OSKext::uniquePersonalityProperties(dict);
1c79356b 171 if( 0 == dict->getObject( gIOClassKey ))
316670eb 172 {
1c79356b
A
173 IOLog("Missing or bad \"%s\" key\n",
174 gIOClassKey->getCStringNoCopy());
316670eb
A
175 continue;
176 }
177 dict->setObject("KernelConfigTable", kOSBooleanTrue);
178 addPersonality(dict);
1c79356b
A
179 }
180
316670eb
A
181 gIOCatalogLock = IORWLockAlloc();
182 lock = gIOCatalogLock;
1c79356b 183
1c79356b
A
184 return true;
185}
186
b0d623f7
A
187/*********************************************************************
188* Release all resources used by IOCatalogue and deallocate.
189* This will probably never be called.
190*********************************************************************/
1c79356b
A
191void IOCatalogue::free( void )
192{
316670eb 193 panic("");
1c79356b 194}
1c79356b 195
b0d623f7
A
196/*********************************************************************
197*********************************************************************/
198OSOrderedSet *
199IOCatalogue::findDrivers(
200 IOService * service,
201 SInt32 * generationCount)
1c79356b
A
202{
203 OSDictionary * nextTable;
204 OSOrderedSet * set;
316670eb
A
205 OSArray * array;
206 const OSMetaClass * meta;
207 unsigned int idx;
1c79356b
A
208
209 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
210 (void *)gIOProbeScoreKey );
211 if( !set )
212 return( 0 );
213
316670eb 214 IORWLockRead(lock);
1c79356b 215
316670eb
A
216 meta = service->getMetaClass();
217 while (meta)
218 {
219 array = (OSArray *) personalities->getObject(meta->getClassNameSymbol());
220 if (array) for (idx = 0; (nextTable = (OSDictionary *) array->getObject(idx)); idx++)
221 {
222 set->setObject(nextTable);
223 }
224 if (meta == &IOService::gMetaClass) break;
225 meta = meta->getSuperClass();
1c79356b
A
226 }
227
228 *generationCount = getGenerationCount();
229
316670eb 230 IORWLockUnlock(lock);
1c79356b
A
231
232 return( set );
233}
234
b0d623f7
A
235/*********************************************************************
236* Is personality already in the catalog?
237*********************************************************************/
238OSOrderedSet *
239IOCatalogue::findDrivers(
240 OSDictionary * matching,
241 SInt32 * generationCount)
1c79356b 242{
316670eb 243 OSCollectionIterator * iter;
1c79356b
A
244 OSDictionary * dict;
245 OSOrderedSet * set;
316670eb
A
246 OSArray * array;
247 const OSSymbol * key;
248 unsigned int idx;
1c79356b 249
6d2010ae 250 OSKext::uniquePersonalityProperties(matching);
1c79356b
A
251
252 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
253 (void *)gIOProbeScoreKey );
316670eb
A
254 if (!set) return (0);
255 iter = OSCollectionIterator::withCollection(personalities);
256 if (!iter)
257 {
258 set->release();
259 return (0);
260 }
1c79356b 261
316670eb
A
262 IORWLockRead(lock);
263 while ((key = (const OSSymbol *) iter->getNextObject()))
264 {
265 array = (OSArray *) personalities->getObject(key);
266 if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++)
267 {
268 /* This comparison must be done with only the keys in the
269 * "matching" dict to enable general searches.
270 */
271 if ( dict->isEqualTo(matching, matching) )
272 set->setObject(dict);
273 }
1c79356b
A
274 }
275 *generationCount = getGenerationCount();
316670eb 276 IORWLockUnlock(lock);
1c79356b 277
316670eb 278 iter->release();
1c79356b
A
279 return set;
280}
281
b0d623f7
A
282/*********************************************************************
283* Add driver config tables to catalog and start matching process.
284*
285* Important that existing personalities are kept (not replaced)
286* if duplicates found. Personalities can come from OSKext objects
287* or from userland kext library. We want to minimize distinct
288* copies between OSKext & IOCatalogue.
289*
290* xxx - userlib used to refuse to send personalities with IOKitDebug
291* xxx - during safe boot. That would be better implemented here.
292*********************************************************************/
316670eb 293
b0d623f7
A
294bool IOCatalogue::addDrivers(
295 OSArray * drivers,
296 bool doNubMatching)
1c79356b 297{
b0d623f7
A
298 bool result = false;
299 OSCollectionIterator * iter = NULL; // must release
300 OSOrderedSet * set = NULL; // must release
6d2010ae 301 OSObject * object = NULL; // do not release
b0d623f7 302 OSArray * persons = NULL; // do not release
316670eb 303
1c79356b 304 persons = OSDynamicCast(OSArray, drivers);
b0d623f7
A
305 if (!persons) {
306 goto finish;
307 }
1c79356b
A
308
309 set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
b0d623f7
A
310 (void *)gIOProbeScoreKey );
311 if (!set) {
312 goto finish;
1c79356b
A
313 }
314
b0d623f7
A
315 iter = OSCollectionIterator::withCollection(persons);
316 if (!iter) {
317 goto finish;
318 }
319
6d2010ae
A
320 /* Start with success; clear it on an error.
321 */
b0d623f7
A
322 result = true;
323
316670eb 324 IORWLockWrite(lock);
6d2010ae 325 while ( (object = iter->getNextObject()) ) {
55e303ae 326
b0d623f7
A
327 // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL
328
6d2010ae
A
329 OSDictionary * personality = OSDynamicCast(OSDictionary, object);
330
b0d623f7 331 SInt count;
6d2010ae
A
332
333 if (!personality) {
334 IOLog("IOCatalogue::addDrivers() encountered non-dictionary; bailing.\n");
335 result = false;
336 break;
337 }
338
339 OSKext::uniquePersonalityProperties(personality);
316670eb 340
b0d623f7 341 // Add driver personality to catalogue.
316670eb
A
342
343 OSArray * array = arrayForPersonality(personality);
344 if (!array) addPersonality(personality);
345 else
346 {
347 count = array->getCount();
348 while (count--) {
349 OSDictionary * driver;
350
351 // Be sure not to double up on personalities.
352 driver = (OSDictionary *)array->getObject(count);
353
354 /* Unlike in other functions, this comparison must be exact!
355 * The catalogue must be able to contain personalities that
356 * are proper supersets of others.
357 * Do not compare just the properties present in one driver
39236c6e 358 * personality or the other.
316670eb
A
359 */
360 if (personality->isEqualTo(driver)) {
361 break;
362 }
363 }
364 if (count >= 0) {
365 // its a dup
366 continue;
367 }
368 result = array->setObject(personality);
369 if (!result) {
370 break;
371 }
b0d623f7 372 }
316670eb
A
373
374 set->setObject(personality);
1c79356b
A
375 }
376 // Start device matching.
6d2010ae 377 if (result && doNubMatching && (set->getCount() > 0)) {
b0d623f7 378 IOService::catalogNewDrivers(set);
1c79356b
A
379 generation++;
380 }
316670eb 381 IORWLockUnlock(lock);
1c79356b 382
b0d623f7
A
383finish:
384 if (set) set->release();
385 if (iter) iter->release();
386
387 return result;
1c79356b
A
388}
389
b0d623f7
A
390/*********************************************************************
391* Remove drivers from the catalog which match the
392* properties in the matching dictionary.
393*********************************************************************/
394bool
395IOCatalogue::removeDrivers(
396 OSDictionary * matching,
397 bool doNubMatching)
1c79356b 398{
1c79356b 399 OSOrderedSet * set;
316670eb
A
400 OSCollectionIterator * iter;
401 OSDictionary * dict;
402 OSArray * array;
403 const OSSymbol * key;
404 unsigned int idx;
1c79356b
A
405
406 if ( !matching )
407 return false;
316670eb 408
1c79356b
A
409 set = OSOrderedSet::withCapacity(10,
410 IOServiceOrdering,
411 (void *)gIOProbeScoreKey);
412 if ( !set )
413 return false;
316670eb
A
414 iter = OSCollectionIterator::withCollection(personalities);
415 if (!iter)
416 {
417 set->release();
418 return (false);
1c79356b
A
419 }
420
316670eb
A
421 IORWLockWrite(lock);
422 while ((key = (const OSSymbol *) iter->getNextObject()))
423 {
424 array = (OSArray *) personalities->getObject(key);
425 if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++)
426 {
427 /* This comparison must be done with only the keys in the
428 * "matching" dict to enable general searches.
429 */
430 if ( dict->isEqualTo(matching, matching) ) {
431 set->setObject(dict);
432 array->removeObject(idx);
433 idx--;
434 }
435 }
436 // Start device matching.
437 if ( doNubMatching && (set->getCount() > 0) ) {
438 IOService::catalogNewDrivers(set);
439 generation++;
1c79356b 440 }
1c79356b 441 }
316670eb
A
442 IORWLockUnlock(lock);
443
1c79356b 444 set->release();
316670eb 445 iter->release();
1c79356b
A
446
447 return true;
448}
449
450// Return the generation count.
b0d623f7 451SInt32 IOCatalogue::getGenerationCount(void) const
1c79356b
A
452{
453 return( generation );
454}
455
b0d623f7 456bool IOCatalogue::isModuleLoaded(OSString * moduleName) const
1c79356b
A
457{
458 return isModuleLoaded(moduleName->getCStringNoCopy());
459}
460
b0d623f7 461bool IOCatalogue::isModuleLoaded(const char * moduleName) const
1c79356b 462{
b0d623f7
A
463 OSReturn ret;
464 ret = OSKext::loadKextWithIdentifier(moduleName);
465 if (kOSKextReturnDeferred == ret) {
466 // a request has been queued but the module isn't necessarily
467 // loaded yet, so stall.
468 return false;
469 }
470 // module is present or never will be
471 return true;
1c79356b
A
472}
473
474// Check to see if module has been loaded already.
b0d623f7 475bool IOCatalogue::isModuleLoaded(OSDictionary * driver) const
1c79356b
A
476{
477 OSString * moduleName = NULL;
b0d623f7 478 OSString * publisherName = NULL;
1c79356b
A
479
480 if ( !driver )
481 return false;
482
b0d623f7
A
483 /* The personalities of codeless kexts often contain the bundle ID of the
484 * kext they reference, and not the bundle ID of the codeless kext itself.
485 * The prelinked kernel needs to know the bundle ID of the codeless kext
486 * so it can include these personalities, so OSKext stores that bundle ID
487 * in the IOPersonalityPublisher key, and we record it as requested here.
488 */
489 publisherName = OSDynamicCast(OSString,
490 driver->getObject(kIOPersonalityPublisherKey));
491 OSKext::recordIdentifierRequest(publisherName);
492
55e303ae 493 moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKey));
1c79356b
A
494 if ( moduleName )
495 return isModuleLoaded(moduleName);
496
497 /* If a personality doesn't hold the "CFBundleIdentifier" key
498 * it is assumed to be an "in-kernel" driver.
499 */
500 return true;
501}
502
b0d623f7
A
503/* This function is called after a module has been loaded.
504 * Is invoked from user client call, ultimately from IOKitLib's
505 * IOCatalogueModuleLoaded(). Sent from kextd.
506 */
507void IOCatalogue::moduleHasLoaded(OSString * moduleName)
1c79356b 508{
b0d623f7 509 OSDictionary * dict;
1c79356b
A
510
511 dict = OSDictionary::withCapacity(2);
55e303ae 512 dict->setObject(gIOModuleIdentifierKey, moduleName);
1c79356b
A
513 startMatching(dict);
514 dict->release();
b0d623f7 515
316670eb
A
516 (void) OSKext::setDeferredLoadSucceeded();
517 (void) OSKext::considerRebuildOfPrelinkedKernel();
1c79356b
A
518}
519
b0d623f7 520void IOCatalogue::moduleHasLoaded(const char * moduleName)
1c79356b 521{
b0d623f7 522 OSString * name;
1c79356b
A
523
524 name = OSString::withCString(moduleName);
525 moduleHasLoaded(name);
526 name->release();
527}
528
b0d623f7
A
529// xxx - return is really OSReturn/kern_return_t
530IOReturn IOCatalogue::unloadModule(OSString * moduleName) const
1c79356b 531{
b0d623f7 532 return OSKext::removeKextWithIdentifier(moduleName->getCStringNoCopy());
1c79356b
A
533}
534
316670eb 535IOReturn IOCatalogue::_terminateDrivers(OSDictionary * matching)
1c79356b 536{
1c79356b
A
537 OSDictionary * dict;
538 OSIterator * iter;
1c79356b
A
539 IOService * service;
540 IOReturn ret;
541
542 if ( !matching )
543 return kIOReturnBadArgument;
544
545 ret = kIOReturnSuccess;
546 dict = 0;
547 iter = IORegistryIterator::iterateOver(gIOServicePlane,
548 kIORegistryIterateRecursively);
549 if ( !iter )
550 return kIOReturnNoMemory;
551
6d2010ae 552 OSKext::uniquePersonalityProperties( matching );
1c79356b 553
1c79356b
A
554 // terminate instances.
555 do {
556 iter->reset();
557 while( (service = (IOService *)iter->getNextObject()) ) {
558 dict = service->getPropertyTable();
559 if ( !dict )
560 continue;
561
9bccf70c
A
562 /* Terminate only for personalities that match the matching dictionary.
563 * This comparison must be done with only the keys in the
564 * "matching" dict to enable general matching.
565 */
1c79356b
A
566 if ( !dict->isEqualTo(matching, matching) )
567 continue;
568
569 if ( !service->terminate(kIOServiceRequired|kIOServiceSynchronous) ) {
570 ret = kIOReturnUnsupported;
571 break;
572 }
573 }
574 } while( !service && !iter->isValid());
575 iter->release();
576
91447636
A
577 return ret;
578}
579
316670eb 580IOReturn IOCatalogue::_removeDrivers(OSDictionary * matching)
91447636 581{
91447636 582 IOReturn ret = kIOReturnSuccess;
316670eb
A
583 OSCollectionIterator * iter;
584 OSDictionary * dict;
585 OSArray * array;
586 const OSSymbol * key;
587 unsigned int idx;
91447636 588
1c79356b 589 // remove configs from catalog.
1c79356b 590
316670eb
A
591 iter = OSCollectionIterator::withCollection(personalities);
592 if (!iter) return (kIOReturnNoMemory);
1c79356b 593
316670eb
A
594 while ((key = (const OSSymbol *) iter->getNextObject()))
595 {
596 array = (OSArray *) personalities->getObject(key);
597 if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++)
598 {
599
600 /* Remove from the catalogue's array any personalities
601 * that match the matching dictionary.
602 * This comparison must be done with only the keys in the
603 * "matching" dict to enable general matching.
604 */
605 if (dict->isEqualTo(matching, matching))
606 {
607 array->removeObject(idx);
608 idx--;
609 }
610 }
1c79356b 611 }
316670eb 612 iter->release();
1c79356b
A
613
614 return ret;
615}
616
b0d623f7 617IOReturn IOCatalogue::terminateDrivers(OSDictionary * matching)
1c79356b
A
618{
619 IOReturn ret;
620
91447636 621 ret = _terminateDrivers(matching);
316670eb 622 IORWLockWrite(lock);
91447636 623 if (kIOReturnSuccess == ret)
316670eb
A
624 ret = _removeDrivers(matching);
625 IORWLockUnlock(lock);
1c79356b
A
626
627 return ret;
628}
629
630IOReturn IOCatalogue::terminateDriversForModule(
b0d623f7
A
631 OSString * moduleName,
632 bool unload)
1c79356b
A
633{
634 IOReturn ret;
635 OSDictionary * dict;
b0d623f7
A
636 bool isLoaded = false;
637
638 /* Check first if the kext currently has any linkage dependents;
639 * in such a case the unload would fail so let's not terminate any
640 * IOServices (since doing so typically results in a panic when there
641 * are loaded dependencies). Note that we aren't locking the kext here
642 * so it might lose or gain dependents by the time we call unloadModule();
643 * I think that's ok, our unload can fail if a kext comes in on top of
644 * this one even after we've torn down IOService objects. Conversely,
645 * if we fail the unload here and then lose a library, the autounload
646 * thread will get us in short order.
647 */
648 if (OSKext::isKextWithIdentifierLoaded(moduleName->getCStringNoCopy())) {
649
650 isLoaded = true;
1c79356b 651
b0d623f7
A
652 if (!OSKext::canUnloadKextWithIdentifier(moduleName,
653 /* checkClasses */ false)) {
654 ret = kOSKextReturnInUse;
655 goto finish;
656 }
657 }
1c79356b 658 dict = OSDictionary::withCapacity(1);
b0d623f7
A
659 if (!dict) {
660 ret = kIOReturnNoMemory;
661 goto finish;
662 }
1c79356b 663
55e303ae 664 dict->setObject(gIOModuleIdentifierKey, moduleName);
9bccf70c 665
91447636 666 ret = _terminateDrivers(dict);
b0d623f7
A
667
668 /* No goto between IOLock calls!
669 */
316670eb 670 IORWLockWrite(lock);
b0d623f7 671 if (kIOReturnSuccess == ret) {
316670eb 672 ret = _removeDrivers(dict);
b0d623f7 673 }
1c79356b
A
674
675 // Unload the module itself.
b0d623f7 676 if (unload && isLoaded && ret == kIOReturnSuccess) {
1c79356b
A
677 ret = unloadModule(moduleName);
678 }
679
316670eb 680 IORWLockUnlock(lock);
1c79356b
A
681
682 dict->release();
683
b0d623f7 684finish:
1c79356b
A
685 return ret;
686}
687
688IOReturn IOCatalogue::terminateDriversForModule(
b0d623f7
A
689 const char * moduleName,
690 bool unload)
1c79356b
A
691{
692 OSString * name;
693 IOReturn ret;
694
695 name = OSString::withCString(moduleName);
696 if ( !name )
697 return kIOReturnNoMemory;
698
699 ret = terminateDriversForModule(name, unload);
700 name->release();
9bccf70c 701
1c79356b
A
702 return ret;
703}
704
705bool IOCatalogue::startMatching( OSDictionary * matching )
706{
316670eb 707 OSCollectionIterator * iter;
1c79356b
A
708 OSDictionary * dict;
709 OSOrderedSet * set;
316670eb
A
710 OSArray * array;
711 const OSSymbol * key;
712 unsigned int idx;
1c79356b
A
713
714 if ( !matching )
715 return false;
716
717 set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
718 (void *)gIOProbeScoreKey);
719 if ( !set )
720 return false;
721
316670eb
A
722 iter = OSCollectionIterator::withCollection(personalities);
723 if (!iter)
724 {
725 set->release();
726 return false;
727 }
1c79356b 728
316670eb 729 IORWLockRead(lock);
9bccf70c 730
316670eb
A
731 while ((key = (const OSSymbol *) iter->getNextObject()))
732 {
733 array = (OSArray *) personalities->getObject(key);
734 if (array) for (idx = 0; (dict = (OSDictionary *) array->getObject(idx)); idx++)
735 {
736 /* This comparison must be done with only the keys in the
737 * "matching" dict to enable general matching.
738 */
739 if (dict->isEqualTo(matching, matching)) {
740 set->setObject(dict);
741 }
742 }
1c79356b 743 }
316670eb 744
1c79356b
A
745 // Start device matching.
746 if ( set->getCount() > 0 ) {
747 IOService::catalogNewDrivers(set);
748 generation++;
749 }
750
316670eb 751 IORWLockUnlock(lock);
1c79356b
A
752
753 set->release();
316670eb 754 iter->release();
1c79356b
A
755
756 return true;
757}
758
759void IOCatalogue::reset(void)
760{
6d2010ae
A
761 IOCatalogue::resetAndAddDrivers(/* no drivers; true reset */ NULL,
762 /* doMatching */ false);
763 return;
764}
765
766bool IOCatalogue::resetAndAddDrivers(OSArray * drivers, bool doNubMatching)
767{
768 bool result = false;
769 OSArray * newPersonalities = NULL; // do not release
316670eb 770 OSCollectionIterator * iter = NULL; // must release
6d2010ae 771 OSOrderedSet * matchSet = NULL; // must release
316670eb
A
772 const OSSymbol * key;
773 OSArray * array;
fe8ab488
A
774 OSDictionary * thisNewPersonality = NULL; // do not release
775 OSDictionary * thisOldPersonality = NULL; // do not release
776 OSDictionary * myKexts = NULL; // must release
316670eb 777 signed int idx, newIdx;
6d2010ae
A
778
779 if (drivers) {
780 newPersonalities = OSDynamicCast(OSArray, drivers);
781 if (!newPersonalities) {
782 goto finish;
783 }
6d2010ae 784 }
fe8ab488
A
785 matchSet = OSOrderedSet::withCapacity(10, IOServiceOrdering,
786 (void *)gIOProbeScoreKey);
787 if (!matchSet) {
788 goto finish;
789 }
790 iter = OSCollectionIterator::withCollection(personalities);
791 if (!iter) {
792 goto finish;
793 }
794
795 /* need copy of loaded kexts so we can check if for loaded modules without
796 * taking the OSKext lock. There is a potential of deadlocking if we get
797 * an OSKext via the normal path. See 14672140.
798 */
799 myKexts = OSKext::copyKexts();
800
6d2010ae
A
801 result = true;
802
1c79356b 803 IOLog("Resetting IOCatalogue.\n");
6d2010ae 804
316670eb 805 /* No goto finish from here to unlock.
6d2010ae 806 */
316670eb 807 IORWLockWrite(lock);
6d2010ae 808
316670eb
A
809 while ((key = (const OSSymbol *) iter->getNextObject()))
810 {
811 array = (OSArray *) personalities->getObject(key);
812 if (!array) continue;
fe8ab488
A
813
814 for (idx = 0;
815 (thisOldPersonality = (OSDictionary *) array->getObject(idx));
816 idx++)
316670eb
A
817 {
818 if (thisOldPersonality->getObject("KernelConfigTable")) continue;
fe8ab488
A
819 thisNewPersonality = NULL;
820
821 if (newPersonalities) {
822 for (newIdx = 0;
823 (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx));
824 newIdx++)
825 {
826 /* Unlike in other functions, this comparison must be exact!
827 * The catalogue must be able to contain personalities that
828 * are proper supersets of others.
829 * Do not compare just the properties present in one driver
830 * personality or the other.
831 */
832 if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) {
833 /* skip thisNewPersonality if it is not an OSDictionary */
834 continue;
835 }
836 if (thisNewPersonality->isEqualTo(thisOldPersonality))
837 break;
39236c6e 838 }
6d2010ae 839 }
fe8ab488 840 if (thisNewPersonality) {
316670eb 841 // dup, ignore
fe8ab488 842 newPersonalities->removeObject(newIdx);
316670eb 843 }
fe8ab488 844 else {
316670eb
A
845 // not in new set - remove
846 // only remove dictionary if this module in not loaded - 9953845
fe8ab488
A
847 if ( isModuleLoadedNoOSKextLock(myKexts, thisOldPersonality) == false ) {
848 if (matchSet) {
849 matchSet->setObject(thisOldPersonality);
850 }
316670eb
A
851 array->removeObject(idx);
852 idx--;
853 }
6d2010ae 854 }
fe8ab488
A
855 } // for...
856 } // while...
6d2010ae 857
39236c6e 858 // add new
fe8ab488
A
859 if (newPersonalities) {
860 for (newIdx = 0;
861 (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx));
862 newIdx++)
863 {
864 if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) {
865 /* skip thisNewPersonality if it is not an OSDictionary */
866 continue;
867 }
868
869 OSKext::uniquePersonalityProperties(thisNewPersonality);
870 addPersonality(thisNewPersonality);
871 matchSet->setObject(thisNewPersonality);
872 }
39236c6e 873 }
316670eb
A
874
875 /* Finally, start device matching on all new & removed personalities.
876 */
877 if (result && doNubMatching && (matchSet->getCount() > 0)) {
878 IOService::catalogNewDrivers(matchSet);
879 generation++;
6d2010ae
A
880 }
881
316670eb 882 IORWLockUnlock(lock);
6d2010ae
A
883
884finish:
fe8ab488
A
885 if (matchSet) matchSet->release();
886 if (iter) iter->release();
887 if (myKexts) myKexts->release();
6d2010ae
A
888
889 return result;
1c79356b
A
890}
891
892bool IOCatalogue::serialize(OSSerialize * s) const
893{
1c79356b
A
894 if ( !s )
895 return false;
896
91447636 897 return super::serialize(s);
1c79356b
A
898}
899
55e303ae
A
900bool IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const
901{
902 kern_return_t kr = kIOReturnSuccess;
903
904 switch ( kind )
905 {
906 case kIOCatalogGetContents:
316670eb 907 kr = KERN_NOT_SUPPORTED;
55e303ae
A
908 break;
909
910 case kIOCatalogGetModuleDemandList:
b0d623f7 911 kr = KERN_NOT_SUPPORTED;
55e303ae
A
912 break;
913
914 case kIOCatalogGetCacheMissList:
b0d623f7 915 kr = KERN_NOT_SUPPORTED;
55e303ae
A
916 break;
917
918 case kIOCatalogGetROMMkextList:
b0d623f7 919 kr = KERN_NOT_SUPPORTED;
55e303ae
A
920 break;
921
922 default:
923 kr = kIOReturnBadArgument;
924 break;
925 }
926
927 return kr;
928}
929
fe8ab488
A
930/* isModuleLoadedNoOSKextLock - used to check to see if a kext is loaded
931 * without taking the OSKext lock. We use this to avoid the problem
932 * where taking the IOCatalog lock then the OSKext lock will dealock when
933 * a kext load or unload is happening at the same time as IOCatalog changing.
934 *
935 * theKexts - is a dictionary of current kexts (from OSKext::copyKexts) with
936 * key set to the kext bundle ID and value set to an OSKext object
937 * theModuleDict - is an IOKit personality dictionary for a given module (kext)
938 */
939static bool isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
940 OSDictionary *theModuleDict)
941{
942 bool myResult = false;
943 const OSString * myBundleID = NULL; // do not release
944 OSKext * myKext = NULL; // do not release
945
946 if (theKexts == NULL || theModuleDict == NULL) {
947 return( myResult );
948 }
949
950 // gIOModuleIdentifierKey is "CFBundleIdentifier"
951 myBundleID = OSDynamicCast(OSString,
952 theModuleDict->getObject(gIOModuleIdentifierKey));
953 if (myBundleID == NULL) {
954 return( myResult );
955 }
956
957 myKext = OSDynamicCast(OSKext, theKexts->getObject(myBundleID->getCStringNoCopy()));
958 if (myKext) {
959 myResult = myKext->isLoaded();
960 }
961
962 return( myResult );
963}
964
965
b0d623f7
A
966#if PRAGMA_MARK
967#pragma mark Obsolete Kext Loading Stuff
0c530ab8 968#endif
91447636 969/*********************************************************************
b0d623f7
A
970**********************************************************************
971*** BINARY COMPATIBILITY SECTION ***
972**********************************************************************
973**********************************************************************
974* These functions are no longer used are necessary for C++ binary
6d2010ae 975* compatibility on i386.
b0d623f7 976**********************************************************************/