]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOCatalogue.cpp
xnu-6153.61.1.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@
0a7de745 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.
0a7de745 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.
0a7de745 17 *
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
0a7de745 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;
cb323159
A
71const OSSymbol * gIOModuleIdentifierKernelKey;
72IORWLock * gIOCatalogLock;
55e303ae 73
b0d623f7
A
74#if PRAGMA_MARK
75#pragma mark Utility functions
2d21ac55 76#endif
55e303ae 77
b0d623f7
A
78#if PRAGMA_MARK
79#pragma mark IOCatalogue class implementation
80#endif
55e303ae 81/*********************************************************************
55e303ae
A
82*********************************************************************/
83
b0d623f7
A
84#define super OSObject
85OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
55e303ae 86
fe8ab488 87static bool isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
0a7de745 88 OSDictionary *theModuleDict);
fe8ab488
A
89
90
55e303ae
A
91/*********************************************************************
92*********************************************************************/
0a7de745
A
93void
94IOCatalogue::initialize(void)
1c79356b 95{
0a7de745
A
96 OSArray * array;
97 OSString * errorString;
98 bool rc;
1c79356b 99
0a7de745 100 extern const char * gIOKernelConfigTables;
1c79356b 101
0a7de745
A
102 array = OSDynamicCast(OSArray, OSUnserialize(gIOKernelConfigTables, &errorString));
103 if (!array && errorString) {
104 IOLog("KernelConfigTables syntax error: %s\n",
105 errorString->getCStringNoCopy());
106 errorString->release();
107 }
1c79356b 108
cb323159
A
109 gIOClassKey = OSSymbol::withCStringNoCopy( kIOClassKey );
110 gIOProbeScoreKey = OSSymbol::withCStringNoCopy( kIOProbeScoreKey );
111 gIOModuleIdentifierKey = OSSymbol::withCStringNoCopy( kCFBundleIdentifierKey );
112 gIOModuleIdentifierKernelKey = OSSymbol::withCStringNoCopy( kCFBundleIdentifierKernelKey );
113
55e303ae 114
0a7de745 115 assert( array && gIOClassKey && gIOProbeScoreKey
b0d623f7 116 && gIOModuleIdentifierKey);
1c79356b 117
0a7de745
A
118 gIOCatalogue = new IOCatalogue;
119 assert(gIOCatalogue);
120 rc = gIOCatalogue->init(array);
121 assert(rc);
122 array->release();
1c79356b
A
123}
124
316670eb
A
125/*********************************************************************
126* Initialize the IOCatalog object.
127*********************************************************************/
0a7de745
A
128OSArray *
129IOCatalogue::arrayForPersonality(OSDictionary * dict)
316670eb 130{
0a7de745 131 const OSSymbol * sym;
316670eb 132
0a7de745
A
133 sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
134 if (!sym) {
cb323159 135 return NULL;
0a7de745 136 }
316670eb 137
0a7de745 138 return (OSArray *) personalities->getObject(sym);
316670eb
A
139}
140
0a7de745
A
141void
142IOCatalogue::addPersonality(OSDictionary * dict)
316670eb 143{
0a7de745
A
144 const OSSymbol * sym;
145 OSArray * arr;
146
147 sym = OSDynamicCast(OSSymbol, dict->getObject(gIOProviderClassKey));
148 if (!sym) {
149 return;
150 }
151 arr = (OSArray *) personalities->getObject(sym);
152 if (arr) {
153 arr->setObject(dict);
154 } else {
155 arr = OSArray::withObjects((const OSObject **)&dict, 1, 2);
156 personalities->setObject(sym, arr);
157 arr->release();
158 }
316670eb
A
159}
160
b0d623f7
A
161/*********************************************************************
162* Initialize the IOCatalog object.
163*********************************************************************/
0a7de745
A
164bool
165IOCatalogue::init(OSArray * initArray)
1c79356b 166{
0a7de745
A
167 OSDictionary * dict;
168 OSObject * obj;
169
170 if (!super::init()) {
171 return false;
172 }
173
174 generation = 1;
175
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);
180 if (!dict) {
181 continue;
182 }
183 OSKext::uniquePersonalityProperties(dict);
cb323159 184 if (NULL == dict->getObject( gIOClassKey )) {
0a7de745
A
185 IOLog("Missing or bad \"%s\" key\n",
186 gIOClassKey->getCStringNoCopy());
187 continue;
188 }
189 dict->setObject("KernelConfigTable", kOSBooleanTrue);
190 addPersonality(dict);
191 }
192
193 gIOCatalogLock = IORWLockAlloc();
194 lock = gIOCatalogLock;
195
196 return true;
1c79356b
A
197}
198
b0d623f7
A
199/*********************************************************************
200* Release all resources used by IOCatalogue and deallocate.
201* This will probably never be called.
202*********************************************************************/
0a7de745
A
203void
204IOCatalogue::free( void )
1c79356b 205{
0a7de745 206 panic("");
1c79356b 207}
1c79356b 208
b0d623f7
A
209/*********************************************************************
210*********************************************************************/
211OSOrderedSet *
212IOCatalogue::findDrivers(
0a7de745
A
213 IOService * service,
214 SInt32 * generationCount)
1c79356b 215{
0a7de745
A
216 OSDictionary * nextTable;
217 OSOrderedSet * set;
218 OSArray * array;
219 const OSMetaClass * meta;
220 unsigned int idx;
221
222 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
223 (void *)gIOProbeScoreKey );
224 if (!set) {
cb323159 225 return NULL;
0a7de745 226 }
1c79356b 227
0a7de745 228 IORWLockRead(lock);
1c79356b 229
0a7de745
A
230 meta = service->getMetaClass();
231 while (meta) {
232 array = (OSArray *) personalities->getObject(meta->getClassNameSymbol());
233 if (array) {
234 for (idx = 0; (nextTable = (OSDictionary *) array->getObject(idx)); idx++) {
235 set->setObject(nextTable);
236 }
237 }
238 if (meta == &IOService::gMetaClass) {
239 break;
240 }
241 meta = meta->getSuperClass();
316670eb 242 }
1c79356b 243
0a7de745 244 *generationCount = getGenerationCount();
1c79356b 245
0a7de745 246 IORWLockUnlock(lock);
1c79356b 247
0a7de745 248 return set;
1c79356b
A
249}
250
b0d623f7
A
251/*********************************************************************
252* Is personality already in the catalog?
253*********************************************************************/
254OSOrderedSet *
255IOCatalogue::findDrivers(
0a7de745
A
256 OSDictionary * matching,
257 SInt32 * generationCount)
1c79356b 258{
0a7de745
A
259 OSCollectionIterator * iter;
260 OSDictionary * dict;
261 OSOrderedSet * set;
262 OSArray * array;
263 const OSSymbol * key;
264 unsigned int idx;
265
266 OSKext::uniquePersonalityProperties(matching);
267
268 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
269 (void *)gIOProbeScoreKey );
270 if (!set) {
cb323159 271 return NULL;
0a7de745
A
272 }
273 iter = OSCollectionIterator::withCollection(personalities);
274 if (!iter) {
275 set->release();
cb323159 276 return NULL;
0a7de745
A
277 }
278
279 IORWLockRead(lock);
280 while ((key = (const OSSymbol *) iter->getNextObject())) {
281 array = (OSArray *) personalities->getObject(key);
282 if (array) {
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.
286 */
287 if (dict->isEqualTo(matching, matching)) {
288 set->setObject(dict);
289 }
290 }
291 }
292 }
293 *generationCount = getGenerationCount();
294 IORWLockUnlock(lock);
295
296 iter->release();
297 return set;
1c79356b
A
298}
299
b0d623f7
A
300/*********************************************************************
301* Add driver config tables to catalog and start matching process.
302*
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.
307*
308* xxx - userlib used to refuse to send personalities with IOKitDebug
309* xxx - during safe boot. That would be better implemented here.
310*********************************************************************/
316670eb 311
0a7de745
A
312bool
313IOCatalogue::addDrivers(
314 OSArray * drivers,
315 bool doNubMatching)
1c79356b 316{
0a7de745
A
317 bool result = false;
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
322
323 persons = OSDynamicCast(OSArray, drivers);
324 if (!persons) {
325 goto finish;
326 }
327
328 set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
329 (void *)gIOProbeScoreKey );
330 if (!set) {
331 goto finish;
332 }
333
334 iter = OSCollectionIterator::withCollection(persons);
335 if (!iter) {
336 goto finish;
337 }
338
339 /* Start with success; clear it on an error.
340 */
341 result = true;
342
343 IORWLockWrite(lock);
344 while ((object = iter->getNextObject())) {
345 // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL
346
347 OSDictionary * personality = OSDynamicCast(OSDictionary, object);
348
349 SInt count;
350
351 if (!personality) {
352 IOLog("IOCatalogue::addDrivers() encountered non-dictionary; bailing.\n");
353 result = false;
354 break;
316670eb 355 }
0a7de745
A
356
357 OSKext::uniquePersonalityProperties(personality);
358
359 // Add driver personality to catalogue.
360
361 OSArray * array = arrayForPersonality(personality);
362 if (!array) {
363 addPersonality(personality);
364 } else {
365 count = array->getCount();
366 while (count--) {
367 OSDictionary * driver;
368
369 // Be sure not to double up on personalities.
370 driver = (OSDictionary *)array->getObject(count);
371
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.
377 */
378 if (personality->isEqualTo(driver)) {
379 break;
380 }
381 }
382 if (count >= 0) {
383 // its a dup
384 continue;
385 }
386 result = array->setObject(personality);
387 if (!result) {
388 break;
389 }
390 }
391
392 set->setObject(personality);
393 }
394 // Start device matching.
395 if (result && doNubMatching && (set->getCount() > 0)) {
396 IOService::catalogNewDrivers(set);
397 generation++;
398 }
399 IORWLockUnlock(lock);
1c79356b 400
b0d623f7 401finish:
0a7de745
A
402 if (set) {
403 set->release();
404 }
405 if (iter) {
406 iter->release();
407 }
b0d623f7 408
0a7de745 409 return result;
1c79356b
A
410}
411
b0d623f7
A
412/*********************************************************************
413* Remove drivers from the catalog which match the
414* properties in the matching dictionary.
415*********************************************************************/
416bool
417IOCatalogue::removeDrivers(
0a7de745
A
418 OSDictionary * matching,
419 bool doNubMatching)
1c79356b 420{
0a7de745
A
421 OSOrderedSet * set;
422 OSCollectionIterator * iter;
423 OSDictionary * dict;
424 OSArray * array;
425 const OSSymbol * key;
426 unsigned int idx;
427
428 if (!matching) {
429 return false;
430 }
431
432 set = OSOrderedSet::withCapacity(10,
433 IOServiceOrdering,
434 (void *)gIOProbeScoreKey);
435 if (!set) {
436 return false;
437 }
438 iter = OSCollectionIterator::withCollection(personalities);
439 if (!iter) {
440 set->release();
441 return false;
442 }
443
444 IORWLockWrite(lock);
445 while ((key = (const OSSymbol *) iter->getNextObject())) {
446 array = (OSArray *) personalities->getObject(key);
447 if (array) {
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.
451 */
452 if (dict->isEqualTo(matching, matching)) {
453 set->setObject(dict);
454 array->removeObject(idx);
455 idx--;
456 }
457 }
458 }
459 // Start device matching.
460 if (doNubMatching && (set->getCount() > 0)) {
461 IOService::catalogNewDrivers(set);
462 generation++;
463 }
464 }
465 IORWLockUnlock(lock);
466
467 set->release();
468 iter->release();
469
470 return true;
1c79356b
A
471}
472
473// Return the generation count.
0a7de745
A
474SInt32
475IOCatalogue::getGenerationCount(void) const
1c79356b 476{
0a7de745 477 return generation;
1c79356b
A
478}
479
cb323159 480// Check to see if kernel module has been loaded already, and request its load.
0a7de745 481bool
cb323159 482IOCatalogue::isModuleLoaded(OSDictionary * driver, OSObject ** kextRef) const
1c79356b 483{
cb323159
A
484 OSString * moduleName = NULL;
485 OSString * publisherName = NULL;
486 OSReturn ret;
1c79356b 487
cb323159
A
488 if (kextRef) {
489 *kextRef = NULL;
0a7de745 490 }
0a7de745
A
491 if (!driver) {
492 return false;
493 }
494
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.
500 */
501 publisherName = OSDynamicCast(OSString,
502 driver->getObject(kIOPersonalityPublisherKey));
503 OSKext::recordIdentifierRequest(publisherName);
504
cb323159 505 moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKernelKey));
0a7de745 506 if (moduleName) {
cb323159
A
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.
511 return false;
512 }
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);
518 }
519 // module is present or never will be
520 return true;
0a7de745
A
521 }
522
cb323159 523 /* If a personality doesn't hold the "CFBundleIdentifier" or "CFBundleIdentifierKernel" key
0a7de745
A
524 * it is assumed to be an "in-kernel" driver.
525 */
526 return true;
1c79356b
A
527}
528
b0d623f7
A
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.
532 */
0a7de745 533void
cb323159 534IOCatalogue::moduleHasLoaded(const OSSymbol * moduleName)
1c79356b 535{
cb323159 536 startMatching(moduleName);
b0d623f7 537
0a7de745
A
538 (void) OSKext::setDeferredLoadSucceeded();
539 (void) OSKext::considerRebuildOfPrelinkedKernel();
1c79356b
A
540}
541
0a7de745
A
542void
543IOCatalogue::moduleHasLoaded(const char * moduleName)
1c79356b 544{
cb323159 545 const OSSymbol * name;
1c79356b 546
cb323159 547 name = OSSymbol::withCString(moduleName);
0a7de745
A
548 moduleHasLoaded(name);
549 name->release();
1c79356b
A
550}
551
b0d623f7 552// xxx - return is really OSReturn/kern_return_t
0a7de745
A
553IOReturn
554IOCatalogue::unloadModule(OSString * moduleName) const
1c79356b 555{
0a7de745 556 return OSKext::removeKextWithIdentifier(moduleName->getCStringNoCopy());
1c79356b
A
557}
558
0a7de745
A
559IOReturn
560IOCatalogue::_terminateDrivers(OSDictionary * matching)
1c79356b 561{
0a7de745
A
562 OSDictionary * dict;
563 OSIterator * iter;
564 IOService * service;
565 IOReturn ret;
566
567 if (!matching) {
568 return kIOReturnBadArgument;
569 }
570
571 ret = kIOReturnSuccess;
cb323159 572 dict = NULL;
0a7de745
A
573 iter = IORegistryIterator::iterateOver(gIOServicePlane,
574 kIORegistryIterateRecursively);
575 if (!iter) {
576 return kIOReturnNoMemory;
577 }
578
579 OSKext::uniquePersonalityProperties( matching );
580
581 // terminate instances.
582 do {
583 iter->reset();
584 while ((service = (IOService *)iter->getNextObject())) {
585 dict = service->getPropertyTable();
586 if (!dict) {
587 continue;
588 }
589
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.
593 */
594 if (!dict->isEqualTo(matching, matching)) {
595 continue;
596 }
597
598 if (!service->terminate(kIOServiceRequired | kIOServiceSynchronous)) {
599 ret = kIOReturnUnsupported;
600 break;
601 }
602 }
603 } while (!service && !iter->isValid());
604 iter->release();
605
606 return ret;
91447636
A
607}
608
0a7de745
A
609IOReturn
610IOCatalogue::_removeDrivers(OSDictionary * matching)
91447636 611{
0a7de745
A
612 IOReturn ret = kIOReturnSuccess;
613 OSCollectionIterator * iter;
614 OSDictionary * dict;
615 OSArray * array;
616 const OSSymbol * key;
617 unsigned int idx;
618
619 // remove configs from catalog.
620
621 iter = OSCollectionIterator::withCollection(personalities);
622 if (!iter) {
623 return kIOReturnNoMemory;
624 }
625
626 while ((key = (const OSSymbol *) iter->getNextObject())) {
627 array = (OSArray *) personalities->getObject(key);
628 if (array) {
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.
634 */
635 if (dict->isEqualTo(matching, matching)) {
636 array->removeObject(idx);
637 idx--;
638 }
639 }
640 }
641 }
642 iter->release();
643
644 return ret;
1c79356b
A
645}
646
0a7de745
A
647IOReturn
648IOCatalogue::terminateDrivers(OSDictionary * matching)
1c79356b 649{
0a7de745 650 IOReturn ret;
1c79356b 651
0a7de745
A
652 ret = _terminateDrivers(matching);
653 IORWLockWrite(lock);
654 if (kIOReturnSuccess == ret) {
655 ret = _removeDrivers(matching);
656 }
657 IORWLockUnlock(lock);
1c79356b 658
0a7de745 659 return ret;
1c79356b
A
660}
661
0a7de745
A
662IOReturn
663IOCatalogue::terminateDriversForModule(
664 OSString * moduleName,
665 bool unload)
1c79356b 666{
0a7de745
A
667 IOReturn ret;
668 OSDictionary * dict;
669 bool isLoaded = false;
670
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.
680 */
681 if (OSKext::isKextWithIdentifierLoaded(moduleName->getCStringNoCopy())) {
682 isLoaded = true;
683
684 if (!OSKext::canUnloadKextWithIdentifier(moduleName,
685 /* checkClasses */ false)) {
686 ret = kOSKextReturnInUse;
687 goto finish;
688 }
689 }
690 dict = OSDictionary::withCapacity(1);
691 if (!dict) {
692 ret = kIOReturnNoMemory;
693 goto finish;
694 }
695
696 dict->setObject(gIOModuleIdentifierKey, moduleName);
697
698 ret = _terminateDrivers(dict);
699
700 /* No goto between IOLock calls!
701 */
702 IORWLockWrite(lock);
703 if (kIOReturnSuccess == ret) {
704 ret = _removeDrivers(dict);
705 }
706
707 // Unload the module itself.
708 if (unload && isLoaded && ret == kIOReturnSuccess) {
709 ret = unloadModule(moduleName);
710 }
711
712 IORWLockUnlock(lock);
713
714 dict->release();
1c79356b 715
b0d623f7 716finish:
0a7de745 717 return ret;
1c79356b
A
718}
719
0a7de745
A
720IOReturn
721IOCatalogue::terminateDriversForModule(
722 const char * moduleName,
723 bool unload)
1c79356b 724{
0a7de745
A
725 OSString * name;
726 IOReturn ret;
1c79356b 727
0a7de745
A
728 name = OSString::withCString(moduleName);
729 if (!name) {
730 return kIOReturnNoMemory;
731 }
1c79356b 732
0a7de745
A
733 ret = terminateDriversForModule(name, unload);
734 name->release();
9bccf70c 735
0a7de745 736 return ret;
1c79356b
A
737}
738
cb323159 739#if defined(__i386__) || defined(__x86_64__)
0a7de745
A
740bool
741IOCatalogue::startMatching( OSDictionary * matching )
1c79356b 742{
0a7de745 743 OSOrderedSet * set;
0a7de745
A
744
745 if (!matching) {
746 return false;
747 }
748
749 set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
750 (void *)gIOProbeScoreKey);
751 if (!set) {
752 return false;
753 }
754
cb323159
A
755 IORWLockRead(lock);
756
757 personalities->iterateObjects(^bool (const OSSymbol * key, OSObject * value) {
758 OSArray * array;
759 OSDictionary * dict;
760 unsigned int idx;
761
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.
766 */
767 if (dict->isEqualTo(matching, matching)) {
768 set->setObject(dict);
769 }
770 }
771 return false;
772 });
773
774 // Start device matching.
775 if (set->getCount() > 0) {
776 IOService::catalogNewDrivers(set);
777 generation++;
778 }
779
780 IORWLockUnlock(lock);
781
782 set->release();
783
784 return true;
785}
786#endif /* defined(__i386__) || defined(__x86_64__) */
787
788bool
789IOCatalogue::startMatching( const OSSymbol * moduleName )
790{
791 OSOrderedSet * set;
792
793 if (!moduleName) {
794 return false;
795 }
796
797 set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
798 (void *)gIOProbeScoreKey);
799 if (!set) {
0a7de745
A
800 return false;
801 }
802
803 IORWLockRead(lock);
804
cb323159
A
805 personalities->iterateObjects(^bool (const OSSymbol * key, OSObject * value) {
806 OSArray * array;
807 OSDictionary * dict;
808 OSObject * obj;
809 unsigned int idx;
810
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);
0a7de745
A
816 }
817 }
cb323159
A
818 return false;
819 });
0a7de745
A
820
821 // Start device matching.
822 if (set->getCount() > 0) {
823 IOService::catalogNewDrivers(set);
824 generation++;
825 }
826
827 IORWLockUnlock(lock);
828
829 set->release();
0a7de745
A
830
831 return true;
1c79356b
A
832}
833
0a7de745
A
834void
835IOCatalogue::reset(void)
1c79356b 836{
0a7de745
A
837 IOCatalogue::resetAndAddDrivers(/* no drivers; true reset */ NULL,
838 /* doMatching */ false);
839 return;
6d2010ae
A
840}
841
0a7de745
A
842bool
843IOCatalogue::resetAndAddDrivers(OSArray * drivers, bool doNubMatching)
6d2010ae 844{
0a7de745
A
845 bool result = false;
846 OSArray * newPersonalities = NULL;// do not release
847 OSCollectionIterator * iter = NULL;// must release
848 OSOrderedSet * matchSet = NULL;// must release
849 const OSSymbol * key;
850 OSArray * array;
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;
855
856 if (drivers) {
857 newPersonalities = OSDynamicCast(OSArray, drivers);
858 if (!newPersonalities) {
859 goto finish;
860 }
861 }
862 matchSet = OSOrderedSet::withCapacity(10, IOServiceOrdering,
863 (void *)gIOProbeScoreKey);
864 if (!matchSet) {
865 goto finish;
866 }
867 iter = OSCollectionIterator::withCollection(personalities);
868 if (!iter) {
869 goto finish;
870 }
871
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.
875 */
876 myKexts = OSKext::copyKexts();
877
878 result = true;
879
880 IOLog("Resetting IOCatalogue.\n");
881
882 /* No goto finish from here to unlock.
883 */
884 IORWLockWrite(lock);
885
886 while ((key = (const OSSymbol *) iter->getNextObject())) {
887 array = (OSArray *) personalities->getObject(key);
888 if (!array) {
889 continue;
890 }
891
892 for (idx = 0;
893 (thisOldPersonality = (OSDictionary *) array->getObject(idx));
894 idx++) {
895 if (thisOldPersonality->getObject("KernelConfigTable")) {
896 continue;
897 }
898 thisNewPersonality = NULL;
899
900 if (newPersonalities) {
901 for (newIdx = 0;
902 (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx));
903 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.
909 */
910 if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) {
911 /* skip thisNewPersonality if it is not an OSDictionary */
912 continue;
913 }
914 if (thisNewPersonality->isEqualTo(thisOldPersonality)) {
915 break;
916 }
917 }
918 }
919 if (thisNewPersonality) {
920 // dup, ignore
921 newPersonalities->removeObject(newIdx);
922 } else {
923 // not in new set - remove
924 // only remove dictionary if this module in not loaded - 9953845
925 if (isModuleLoadedNoOSKextLock(myKexts, thisOldPersonality) == false) {
926 if (matchSet) {
927 matchSet->setObject(thisOldPersonality);
928 }
929 array->removeObject(idx);
930 idx--;
931 }
932 }
933 } // for...
934 } // while...
935
936 // add new
937 if (newPersonalities) {
938 for (newIdx = 0;
939 (thisNewPersonality = (OSDictionary *) newPersonalities->getObject(newIdx));
940 newIdx++) {
941 if (OSDynamicCast(OSDictionary, thisNewPersonality) == NULL) {
942 /* skip thisNewPersonality if it is not an OSDictionary */
943 continue;
944 }
945
946 OSKext::uniquePersonalityProperties(thisNewPersonality);
947 addPersonality(thisNewPersonality);
948 matchSet->setObject(thisNewPersonality);
949 }
950 }
951
952 /* Finally, start device matching on all new & removed personalities.
953 */
954 if (result && doNubMatching && (matchSet->getCount() > 0)) {
955 IOService::catalogNewDrivers(matchSet);
956 generation++;
957 }
958
959 IORWLockUnlock(lock);
6d2010ae
A
960
961finish:
0a7de745
A
962 if (matchSet) {
963 matchSet->release();
964 }
965 if (iter) {
966 iter->release();
967 }
968 if (myKexts) {
969 myKexts->release();
970 }
6d2010ae 971
0a7de745 972 return result;
1c79356b
A
973}
974
0a7de745
A
975bool
976IOCatalogue::serialize(OSSerialize * s) const
1c79356b 977{
0a7de745
A
978 if (!s) {
979 return false;
980 }
1c79356b 981
0a7de745 982 return super::serialize(s);
1c79356b
A
983}
984
0a7de745
A
985bool
986IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const
55e303ae 987{
0a7de745 988 kern_return_t kr = kIOReturnSuccess;
55e303ae 989
0a7de745
A
990 switch (kind) {
991 case kIOCatalogGetContents:
992 kr = KERN_NOT_SUPPORTED;
993 break;
55e303ae 994
0a7de745
A
995 case kIOCatalogGetModuleDemandList:
996 kr = KERN_NOT_SUPPORTED;
997 break;
55e303ae 998
0a7de745
A
999 case kIOCatalogGetCacheMissList:
1000 kr = KERN_NOT_SUPPORTED;
1001 break;
55e303ae 1002
0a7de745
A
1003 case kIOCatalogGetROMMkextList:
1004 kr = KERN_NOT_SUPPORTED;
1005 break;
55e303ae 1006
0a7de745
A
1007 default:
1008 kr = kIOReturnBadArgument;
1009 break;
1010 }
55e303ae 1011
0a7de745 1012 return kr;
55e303ae
A
1013}
1014
0a7de745 1015/* isModuleLoadedNoOSKextLock - used to check to see if a kext is loaded
fe8ab488
A
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.
1019 *
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)
1023 */
0a7de745
A
1024static bool
1025isModuleLoadedNoOSKextLock(OSDictionary *theKexts,
1026 OSDictionary *theModuleDict)
fe8ab488 1027{
0a7de745
A
1028 bool myResult = false;
1029 const OSString * myBundleID = NULL;// do not release
1030 OSKext * myKext = NULL; // do not release
1031
1032 if (theKexts == NULL || theModuleDict == NULL) {
1033 return myResult;
1034 }
1035
1036 // gIOModuleIdentifierKey is "CFBundleIdentifier"
1037 myBundleID = OSDynamicCast(OSString,
1038 theModuleDict->getObject(gIOModuleIdentifierKey));
1039 if (myBundleID == NULL) {
1040 return myResult;
1041 }
1042
1043 myKext = OSDynamicCast(OSKext, theKexts->getObject(myBundleID->getCStringNoCopy()));
1044 if (myKext) {
1045 myResult = myKext->isLoaded();
1046 }
1047
1048 return myResult;
fe8ab488
A
1049}
1050
1051
b0d623f7
A
1052#if PRAGMA_MARK
1053#pragma mark Obsolete Kext Loading Stuff
0c530ab8 1054#endif
91447636 1055/*********************************************************************
0a7de745
A
1056 **********************************************************************
1057 *** BINARY COMPATIBILITY SECTION ***
1058 **********************************************************************
1059 **********************************************************************
1060 * These functions are no longer used are necessary for C++ binary
1061 * compatibility on i386.
1062 **********************************************************************/