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