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