]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOCatalogue.cpp
xnu-792.10.96.tar.gz
[apple/xnu.git] / iokit / Kernel / IOCatalogue.cpp
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
37839358
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
37839358
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
37839358
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
24 *
25 * HISTORY
26 *
27 */
28
29#include <IOKit/IODeviceTreeSupport.h>
30#include <IOKit/IOService.h>
31#include <libkern/c++/OSContainers.h>
32#include <IOKit/IOCatalogue.h>
33#include <libkern/c++/OSUnserialize.h>
34extern "C" {
35#include <machine/machine_routines.h>
36#include <mach/kmod.h>
37#include <mach-o/mach_header.h>
9bccf70c 38#include <kern/host.h>
1c79356b
A
39};
40
41#include <IOKit/IOLib.h>
42
43#include <IOKit/assert.h>
44
45
46extern "C" {
47int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize );
48extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize );
91447636
A
49/* operates on 32 bit segments */
50extern void OSRuntimeUnloadCPPForSegment(struct segment_command * segment);
1c79356b
A
51};
52
53
54/*****
55 * At startup these function pointers are set to use the libsa in-kernel
56 * linker for recording and loading kmods. Once the root filesystem
57 * is available, the kmod_load_function pointer gets switched to point
58 * at the kmod_load_extension() function built into the kernel, and the
59 * others are set to zero. Those two functions must *always* be checked
60 * before being invoked.
61 */
62extern "C" {
63kern_return_t (*kmod_load_function)(char *extension_name) =
64 &kmod_load_extension;
65bool (*record_startup_extensions_function)(void) = 0;
66bool (*add_from_mkext_function)(OSData * mkext) = 0;
67void (*remove_startup_extension_function)(const char * name) = 0;
68};
69
70
71/*****
72 * A few parts of IOCatalogue require knowledge of
73 * whether the in-kernel linker is present. This
74 * variable is set by libsa's bootstrap code.
75 */
76int kernelLinkerPresent = 0;
77
1c79356b
A
78#define kModuleKey "CFBundleIdentifier"
79
55e303ae 80#define super OSObject
1c79356b
A
81OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
82
83#define CATALOGTEST 0
84
55e303ae
A
85IOCatalogue * gIOCatalogue;
86const OSSymbol * gIOClassKey;
87const OSSymbol * gIOProbeScoreKey;
88const OSSymbol * gIOModuleIdentifierKey;
89OSSet * gIOCatalogModuleRequests;
90OSSet * gIOCatalogCacheMisses;
91OSSet * gIOCatalogROMMkexts;
92IOLock * gIOCatalogLock;
93IOLock * gIOKLDLock;
94
95/*********************************************************************
96*********************************************************************/
97
98OSArray * gIOPrelinkedModules = 0;
99
100extern "C" kern_return_t
101kmod_create_internal(
102 kmod_info_t *info,
103 kmod_t *id);
104
105extern "C" kern_return_t
106kmod_destroy_internal(kmod_t id);
107
108extern "C" kern_return_t
109kmod_start_or_stop(
110 kmod_t id,
111 int start,
112 kmod_args_t *data,
113 mach_msg_type_number_t *dataCount);
114
115extern "C" kern_return_t kmod_retain(kmod_t id);
116extern "C" kern_return_t kmod_release(kmod_t id);
117
118static
119kern_return_t start_prelink_module(UInt32 moduleIndex)
120{
121 kern_return_t kr = KERN_SUCCESS;
122 UInt32 * togo;
123 SInt32 count, where, end;
124 UInt32 * prelink;
125 SInt32 next, lastDep;
126 OSData * data;
127 OSString * str;
128 OSDictionary * dict;
129
130 OSArray *
131 prelinkedModules = gIOPrelinkedModules;
132
133 togo = IONew(UInt32, prelinkedModules->getCount());
134 togo[0] = moduleIndex;
135 count = 1;
136
137 for (next = 0; next < count; next++)
138 {
139 dict = (OSDictionary *) prelinkedModules->getObject(togo[next]);
140
141 data = OSDynamicCast(OSData, dict->getObject("OSBundlePrelink"));
142 if (!data)
143 {
144 // already started or no code
145 if (togo[next] == moduleIndex)
146 {
147 kr = KERN_FAILURE;
148 break;
149 }
150 continue;
151 }
152 prelink = (UInt32 *) data->getBytesNoCopy();
153 lastDep = OSReadBigInt32(prelink, 12);
154 for (SInt32 idx = OSReadBigInt32(prelink, 8); idx < lastDep; idx += sizeof(UInt32))
155 {
156 UInt32 depIdx = OSReadBigInt32(prelink, idx) - 1;
157
158 for (where = next + 1;
159 (where < count) && (togo[where] > depIdx);
160 where++) {}
161
162 if (where != count)
163 {
164 if (togo[where] == depIdx)
165 continue;
166 for (end = count; end != where; end--)
167 togo[end] = togo[end - 1];
168 }
169 count++;
170 togo[where] = depIdx;
171 }
172 }
173
174 if (KERN_SUCCESS != kr)
175 return kr;
176
177 for (next = (count - 1); next >= 0; next--)
178 {
179 dict = (OSDictionary *) prelinkedModules->getObject(togo[next]);
180
181 data = OSDynamicCast(OSData, dict->getObject("OSBundlePrelink"));
182 if (!data)
183 continue;
184 prelink = (UInt32 *) data->getBytesNoCopy();
185
186 kmod_t id;
187 kmod_info_t * kmod_info = (kmod_info_t *) OSReadBigInt32(prelink, 0);
188
189 kr = kmod_create_internal(kmod_info, &id);
190 if (KERN_SUCCESS != kr)
191 break;
192
193 lastDep = OSReadBigInt32(prelink, 12);
194 for (SInt32 idx = OSReadBigInt32(prelink, 8); idx < lastDep; idx += sizeof(UInt32))
195 {
196 OSDictionary * depDict;
197 kmod_info_t * depInfo;
198
199 depDict = (OSDictionary *) prelinkedModules->getObject(OSReadBigInt32(prelink, idx) - 1);
200 str = OSDynamicCast(OSString, depDict->getObject(kModuleKey));
201 depInfo = kmod_lookupbyname_locked(str->getCStringNoCopy());
202 if (depInfo)
203 {
204 kr = kmod_retain(KMOD_PACK_IDS(id, depInfo->id));
91447636 205 kfree(depInfo, sizeof(kmod_info_t));
55e303ae
A
206 } else
207 IOLog("%s: NO DEP %s\n", kmod_info->name, str->getCStringNoCopy());
208 }
209 dict->removeObject("OSBundlePrelink");
210
211 if (kmod_info->start)
212 kr = kmod_start_or_stop(kmod_info->id, 1, 0, 0);
213 }
214
215 IODelete(togo, UInt32, prelinkedModules->getCount());
216
217 return kr;
218}
219
220/*********************************************************************
221* This is a function that IOCatalogue calls in order to load a kmod.
222*********************************************************************/
223
224static
225kern_return_t kmod_load_from_cache_sym(const OSSymbol * kmod_name)
226{
227 OSArray * prelinkedModules = gIOPrelinkedModules;
228 kern_return_t result = KERN_FAILURE;
229 OSDictionary * dict;
230 OSObject * ident;
231 UInt32 idx;
232
233 if (!gIOPrelinkedModules)
234 return KERN_FAILURE;
235
236 for (idx = 0;
237 (dict = (OSDictionary *) prelinkedModules->getObject(idx));
238 idx++)
239 {
240 if ((ident = dict->getObject(kModuleKey))
241 && kmod_name->isEqualTo(ident))
242 break;
243 }
244 if (dict)
245 {
246 if (kernelLinkerPresent && dict->getObject("OSBundleDefer"))
247 {
248 kmod_load_extension((char *) kmod_name->getCStringNoCopy());
249 result = kIOReturnOffline;
250 }
251 else
252 result = start_prelink_module(idx);
253 }
254
255 return result;
256}
257
258extern "C" Boolean kmod_load_request(const char * moduleName, Boolean make_request)
259{
260 bool ret, cacheMiss = false;
261 kern_return_t kr;
262 const OSSymbol * sym = 0;
263 kmod_info_t * kmod_info;
264
265 if (!moduleName)
266 return false;
267
268 /* To make sure this operation completes even if a bad extension needs
269 * to be removed, take the kld lock for this whole block, spanning the
270 * kmod_load_function() and remove_startup_extension_function() calls.
271 */
272 IOLockLock(gIOKLDLock);
273 do
274 {
275 // Is the module already loaded?
276 ret = (0 != (kmod_info = kmod_lookupbyname_locked((char *)moduleName)));
277 if (ret) {
91447636 278 kfree(kmod_info, sizeof(kmod_info_t));
55e303ae
A
279 break;
280 }
281 sym = OSSymbol::withCString(moduleName);
282 if (!sym) {
283 ret = false;
284 break;
285 }
286
287 kr = kmod_load_from_cache_sym(sym);
288 ret = (kIOReturnSuccess == kr);
289 cacheMiss = !ret;
290 if (ret || !make_request || (kr == kIOReturnOffline))
291 break;
292
293 // If the module hasn't been loaded, then load it.
294 if (!kmod_load_function) {
295 IOLog("IOCatalogue: %s cannot be loaded "
296 "(kmod load function not set).\n",
297 moduleName);
91447636 298 ret = true;
55e303ae
A
299 break;
300 }
301
302 kr = kmod_load_function((char *)moduleName);
303
304 if (ret != kIOReturnSuccess) {
305 IOLog("IOCatalogue: %s cannot be loaded.\n", moduleName);
306
307 /* If the extension couldn't be loaded this time,
308 * make it unavailable so that no more requests are
309 * made in vain. This also enables other matching
310 * extensions to have a chance.
311 */
312 if (kernelLinkerPresent && remove_startup_extension_function) {
313 (*remove_startup_extension_function)(moduleName);
314 }
315 ret = false;
316
317 } else if (kernelLinkerPresent) {
318 // If kern linker is here, the driver is actually loaded,
319 // so return true.
320 ret = true;
321
322 } else {
323 // kern linker isn't here, a request has been queued
324 // but the module isn't necessarily loaded yet, so stall.
325 ret = false;
326 }
327 }
328 while (false);
329
330 IOLockUnlock(gIOKLDLock);
331
332 if (sym)
333 {
334 IOLockLock(gIOCatalogLock);
335 gIOCatalogModuleRequests->setObject(sym);
336 if (cacheMiss)
337 gIOCatalogCacheMisses->setObject(sym);
338 IOLockUnlock(gIOCatalogLock);
339 }
340
341 return ret;
342}
343
344extern "C" kern_return_t kmod_unload_cache(void)
345{
346 OSArray * prelinkedModules = gIOPrelinkedModules;
347 kern_return_t result = KERN_FAILURE;
348 OSDictionary * dict;
349 UInt32 idx;
350 UInt32 * prelink;
351 OSData * data;
352
353 if (!gIOPrelinkedModules)
354 return KERN_SUCCESS;
355
356 IOLockLock(gIOKLDLock);
357 for (idx = 0;
358 (dict = (OSDictionary *) prelinkedModules->getObject(idx));
359 idx++)
360 {
361 data = OSDynamicCast(OSData, dict->getObject("OSBundlePrelink"));
362 if (!data)
363 continue;
364 prelink = (UInt32 *) data->getBytesNoCopy();
365
366 kmod_info_t * kmod_info = (kmod_info_t *) OSReadBigInt32(prelink, 0);
367 vm_offset_t
368 virt = ml_static_ptovirt(kmod_info->address);
369 if( virt) {
370 ml_static_mfree(virt, kmod_info->size);
371 }
372 }
373
374 gIOPrelinkedModules->release();
375 gIOPrelinkedModules = 0;
376
377 IOLockUnlock(gIOKLDLock);
378
379 return result;
380}
381
382extern "C" kern_return_t kmod_load_from_cache(const char * kmod_name)
383{
384 kern_return_t kr;
385 const OSSymbol * sym = OSSymbol::withCStringNoCopy(kmod_name);
386
387 if (sym)
388 {
389 kr = kmod_load_from_cache_sym(sym);
390 sym->release();
391 }
392 else
393 kr = kIOReturnNoMemory;
394
395 return kr;
396}
397
398/*********************************************************************
399*********************************************************************/
1c79356b
A
400
401static void UniqueProperties( OSDictionary * dict )
402{
403 OSString * data;
404
405 data = OSDynamicCast( OSString, dict->getObject( gIOClassKey ));
406 if( data) {
407 const OSSymbol *classSymbol = OSSymbol::withString(data);
408
409 dict->setObject( gIOClassKey, (OSSymbol *) classSymbol);
410 classSymbol->release();
411 }
412
413 data = OSDynamicCast( OSString, dict->getObject( gIOMatchCategoryKey ));
414 if( data) {
415 const OSSymbol *classSymbol = OSSymbol::withString(data);
416
417 dict->setObject( gIOMatchCategoryKey, (OSSymbol *) classSymbol);
418 classSymbol->release();
419 }
420}
421
422void IOCatalogue::initialize( void )
423{
424 OSArray * array;
425 OSString * errorString;
426 bool rc;
427
428 extern const char * gIOKernelConfigTables;
429
430 array = OSDynamicCast(OSArray, OSUnserialize(gIOKernelConfigTables, &errorString));
431 if (!array && errorString) {
432 IOLog("KernelConfigTables syntax error: %s\n",
433 errorString->getCStringNoCopy());
434 errorString->release();
435 }
436
55e303ae
A
437 gIOClassKey = OSSymbol::withCStringNoCopy( kIOClassKey );
438 gIOProbeScoreKey = OSSymbol::withCStringNoCopy( kIOProbeScoreKey );
439 gIOModuleIdentifierKey = OSSymbol::withCStringNoCopy( kModuleKey );
440 gIOCatalogModuleRequests = OSSet::withCapacity(16);
441 gIOCatalogCacheMisses = OSSet::withCapacity(16);
442 gIOCatalogROMMkexts = OSSet::withCapacity(4);
443
444 assert( array && gIOClassKey && gIOProbeScoreKey
445 && gIOModuleIdentifierKey && gIOCatalogModuleRequests);
1c79356b
A
446
447 gIOCatalogue = new IOCatalogue;
448 assert(gIOCatalogue);
449 rc = gIOCatalogue->init(array);
450 assert(rc);
451 array->release();
452}
453
454// Initialize the IOCatalog object.
455bool IOCatalogue::init(OSArray * initArray)
456{
1c79356b
A
457 OSDictionary * dict;
458
459 if ( !super::init() )
460 return false;
461
462 generation = 1;
463
464 array = initArray;
465 array->retain();
466 kernelTables = OSCollectionIterator::withCollection( array );
467
55e303ae
A
468 gIOCatalogLock = IOLockAlloc();
469 gIOKLDLock = IOLockAlloc();
470
471 lock = gIOCatalogLock;
472 kld_lock = gIOKLDLock;
1c79356b
A
473
474 kernelTables->reset();
475 while( (dict = (OSDictionary *) kernelTables->getNextObject())) {
476 UniqueProperties(dict);
477 if( 0 == dict->getObject( gIOClassKey ))
478 IOLog("Missing or bad \"%s\" key\n",
479 gIOClassKey->getCStringNoCopy());
480 }
481
482#if CATALOGTEST
483 AbsoluteTime deadline;
484 clock_interval_to_deadline( 1000, kMillisecondScale );
485 thread_call_func_delayed( ping, this, deadline );
486#endif
487
1c79356b
A
488 return true;
489}
490
491// Release all resources used by IOCatalogue and deallocate.
492// This will probably never be called.
493void IOCatalogue::free( void )
494{
495 if ( array )
496 array->release();
497
498 if ( kernelTables )
499 kernelTables->release();
500
501 super::free();
502}
503
504#if CATALOGTEST
505
506static int hackLimit;
507
508enum { kDriversPerIter = 4 };
509
510void IOCatalogue::ping( thread_call_param_t arg, thread_call_param_t)
511{
512 IOCatalogue * self = (IOCatalogue *) arg;
513 OSOrderedSet * set;
514 OSDictionary * table;
515 int newLimit;
516
517 set = OSOrderedSet::withCapacity( 1 );
518
55e303ae 519 IOLockLock( &self->lock );
1c79356b
A
520
521 for( newLimit = 0; newLimit < kDriversPerIter; newLimit++) {
522 table = (OSDictionary *) self->array->getObject(
523 hackLimit + newLimit );
524 if( table) {
525 set->setLastObject( table );
526
527 OSSymbol * sym = (OSSymbol *) table->getObject( gIOClassKey );
528 kprintf("enabling %s\n", sym->getCStringNoCopy());
529
530 } else {
531 newLimit--;
532 break;
533 }
534 }
535
536 IOService::catalogNewDrivers( set );
537
538 hackLimit += newLimit;
539 self->generation++;
540
55e303ae 541 IOLockUnlock( &self->lock );
1c79356b
A
542
543 if( kDriversPerIter == newLimit) {
544 AbsoluteTime deadline;
545 clock_interval_to_deadline( 500, kMillisecondScale );
546 thread_call_func_delayed( ping, this, deadline );
547 }
548}
549#endif
550
551OSOrderedSet * IOCatalogue::findDrivers( IOService * service,
552 SInt32 * generationCount )
553{
554 OSDictionary * nextTable;
555 OSOrderedSet * set;
556 OSString * imports;
557
558 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
559 (void *)gIOProbeScoreKey );
560 if( !set )
561 return( 0 );
562
55e303ae 563 IOLockLock( lock );
1c79356b
A
564 kernelTables->reset();
565
566#if CATALOGTEST
567 int hackIndex = 0;
568#endif
569 while( (nextTable = (OSDictionary *) kernelTables->getNextObject())) {
570#if CATALOGTEST
571 if( hackIndex++ > hackLimit)
572 break;
573#endif
574 imports = OSDynamicCast( OSString,
575 nextTable->getObject( gIOProviderClassKey ));
576 if( imports && service->metaCast( imports ))
577 set->setObject( nextTable );
578 }
579
580 *generationCount = getGenerationCount();
581
55e303ae 582 IOLockUnlock( lock );
1c79356b
A
583
584 return( set );
585}
586
587// Is personality already in the catalog?
588OSOrderedSet * IOCatalogue::findDrivers( OSDictionary * matching,
589 SInt32 * generationCount)
590{
591 OSDictionary * dict;
592 OSOrderedSet * set;
593
594 UniqueProperties(matching);
595
596 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
597 (void *)gIOProbeScoreKey );
598
55e303ae 599 IOLockLock( lock );
1c79356b
A
600 kernelTables->reset();
601 while ( (dict = (OSDictionary *) kernelTables->getNextObject()) ) {
9bccf70c
A
602
603 /* This comparison must be done with only the keys in the
604 * "matching" dict to enable general searches.
605 */
1c79356b
A
606 if ( dict->isEqualTo(matching, matching) )
607 set->setObject(dict);
608 }
609 *generationCount = getGenerationCount();
55e303ae 610 IOLockUnlock( lock );
1c79356b
A
611
612 return set;
613}
614
615// Add a new personality to the set if it has a unique IOResourceMatchKey value.
616// XXX -- svail: This should be optimized.
617// esb - There doesn't seem like any reason to do this - it causes problems
618// esb - when there are more than one loadable driver matching on the same provider class
619static void AddNewImports( OSOrderedSet * set, OSDictionary * dict )
620{
621 set->setObject(dict);
622}
623
624// Add driver config tables to catalog and start matching process.
625bool IOCatalogue::addDrivers(OSArray * drivers,
55e303ae 626 bool doNubMatching )
1c79356b
A
627{
628 OSCollectionIterator * iter;
629 OSDictionary * dict;
630 OSOrderedSet * set;
631 OSArray * persons;
55e303ae 632 OSString * moduleName;
1c79356b
A
633 bool ret;
634
635 ret = true;
636 persons = OSDynamicCast(OSArray, drivers);
637 if ( !persons )
638 return false;
639
640 iter = OSCollectionIterator::withCollection( persons );
641 if (!iter )
642 return false;
643
644 set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
645 (void *)gIOProbeScoreKey );
646 if ( !set ) {
647 iter->release();
648 return false;
649 }
650
55e303ae
A
651 IOLockLock( lock );
652 while ( (dict = (OSDictionary *) iter->getNextObject()) )
653 {
654 if ((moduleName = OSDynamicCast(OSString, dict->getObject("OSBundleModuleDemand"))))
655 {
656 IOLockUnlock( lock );
657 ret = kmod_load_request(moduleName->getCStringNoCopy(), false);
658 IOLockLock( lock );
659 ret = true;
660 }
661 else
662 {
663 SInt count;
664
665 UniqueProperties( dict );
666
667 // Add driver personality to catalogue.
668 count = array->getCount();
669 while ( count-- ) {
670 OSDictionary * driver;
671
672 // Be sure not to double up on personalities.
673 driver = (OSDictionary *)array->getObject(count);
674
675 /* Unlike in other functions, this comparison must be exact!
676 * The catalogue must be able to contain personalities that
677 * are proper supersets of others.
678 * Do not compare just the properties present in one driver
679 * pesonality or the other.
680 */
681 if (dict->isEqualTo(driver))
682 break;
683 }
684 if (count >= 0)
685 // its a dup
686 continue;
687
688 ret = array->setObject( dict );
689 if (!ret)
690 break;
691
692 AddNewImports( set, dict );
693 }
1c79356b
A
694 }
695 // Start device matching.
55e303ae 696 if (doNubMatching && (set->getCount() > 0)) {
1c79356b
A
697 IOService::catalogNewDrivers( set );
698 generation++;
699 }
55e303ae 700 IOLockUnlock( lock );
1c79356b 701
1c79356b
A
702 set->release();
703 iter->release();
704
705 return ret;
706}
707
708// Remove drivers from the catalog which match the
709// properties in the matching dictionary.
710bool IOCatalogue::removeDrivers( OSDictionary * matching,
55e303ae 711 bool doNubMatching)
1c79356b
A
712{
713 OSCollectionIterator * tables;
714 OSDictionary * dict;
715 OSOrderedSet * set;
716 OSArray * arrayCopy;
717
718 if ( !matching )
719 return false;
720
721 set = OSOrderedSet::withCapacity(10,
722 IOServiceOrdering,
723 (void *)gIOProbeScoreKey);
724 if ( !set )
725 return false;
726
727 arrayCopy = OSArray::withCapacity(100);
728 if ( !arrayCopy ) {
729 set->release();
730 return false;
731 }
732
733 tables = OSCollectionIterator::withCollection(arrayCopy);
734 arrayCopy->release();
735 if ( !tables ) {
736 set->release();
737 return false;
738 }
739
740 UniqueProperties( matching );
741
55e303ae 742 IOLockLock( lock );
1c79356b
A
743 kernelTables->reset();
744 arrayCopy->merge(array);
745 array->flushCollection();
746 tables->reset();
747 while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
9bccf70c
A
748
749 /* This comparison must be done with only the keys in the
750 * "matching" dict to enable general searches.
751 */
1c79356b
A
752 if ( dict->isEqualTo(matching, matching) ) {
753 AddNewImports( set, dict );
754 continue;
755 }
756
757 array->setObject(dict);
758 }
759 // Start device matching.
760 if ( doNubMatching && (set->getCount() > 0) ) {
761 IOService::catalogNewDrivers(set);
762 generation++;
763 }
55e303ae 764 IOLockUnlock( lock );
1c79356b
A
765
766 set->release();
767 tables->release();
768
769 return true;
770}
771
772// Return the generation count.
773SInt32 IOCatalogue::getGenerationCount( void ) const
774{
775 return( generation );
776}
777
778bool IOCatalogue::isModuleLoaded( OSString * moduleName ) const
779{
780 return isModuleLoaded(moduleName->getCStringNoCopy());
781}
782
783bool IOCatalogue::isModuleLoaded( const char * moduleName ) const
784{
55e303ae 785 return (kmod_load_request(moduleName, true));
1c79356b
A
786}
787
788// Check to see if module has been loaded already.
789bool IOCatalogue::isModuleLoaded( OSDictionary * driver ) const
790{
791 OSString * moduleName = NULL;
792
793 if ( !driver )
794 return false;
795
55e303ae 796 moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKey));
1c79356b
A
797 if ( moduleName )
798 return isModuleLoaded(moduleName);
799
800 /* If a personality doesn't hold the "CFBundleIdentifier" key
801 * it is assumed to be an "in-kernel" driver.
802 */
803 return true;
804}
805
806// This function is called after a module has been loaded.
807void IOCatalogue::moduleHasLoaded( OSString * moduleName )
808{
809 OSDictionary * dict;
810
811 dict = OSDictionary::withCapacity(2);
55e303ae 812 dict->setObject(gIOModuleIdentifierKey, moduleName);
1c79356b
A
813 startMatching(dict);
814 dict->release();
815}
816
817void IOCatalogue::moduleHasLoaded( const char * moduleName )
818{
819 OSString * name;
820
821 name = OSString::withCString(moduleName);
822 moduleHasLoaded(name);
823 name->release();
824}
825
826IOReturn IOCatalogue::unloadModule( OSString * moduleName ) const
827{
9bccf70c 828 kmod_info_t * k_info = 0;
1c79356b
A
829 kern_return_t ret;
830 const char * name;
831
832 ret = kIOReturnBadArgument;
833 if ( moduleName ) {
834 name = moduleName->getCStringNoCopy();
9bccf70c 835 k_info = kmod_lookupbyname_locked((char *)name);
1c79356b
A
836 if ( k_info && (k_info->reference_count < 1) ) {
837 if ( k_info->stop &&
9bccf70c
A
838 !((ret = k_info->stop(k_info, 0)) == kIOReturnSuccess) ) {
839
91447636 840 kfree(k_info, sizeof(kmod_info_t));
1c79356b 841 return ret;
9bccf70c 842 }
1c79356b
A
843
844 ret = kmod_destroy(host_priv_self(), k_info->id);
845 }
846 }
9bccf70c
A
847
848 if (k_info) {
91447636 849 kfree(k_info, sizeof(kmod_info_t));
9bccf70c 850 }
1c79356b
A
851
852 return ret;
853}
854
91447636 855static IOReturn _terminateDrivers( OSDictionary * matching )
1c79356b 856{
1c79356b
A
857 OSDictionary * dict;
858 OSIterator * iter;
1c79356b
A
859 IOService * service;
860 IOReturn ret;
861
862 if ( !matching )
863 return kIOReturnBadArgument;
864
865 ret = kIOReturnSuccess;
866 dict = 0;
867 iter = IORegistryIterator::iterateOver(gIOServicePlane,
868 kIORegistryIterateRecursively);
869 if ( !iter )
870 return kIOReturnNoMemory;
871
872 UniqueProperties( matching );
873
1c79356b
A
874 // terminate instances.
875 do {
876 iter->reset();
877 while( (service = (IOService *)iter->getNextObject()) ) {
878 dict = service->getPropertyTable();
879 if ( !dict )
880 continue;
881
9bccf70c
A
882 /* Terminate only for personalities that match the matching dictionary.
883 * This comparison must be done with only the keys in the
884 * "matching" dict to enable general matching.
885 */
1c79356b
A
886 if ( !dict->isEqualTo(matching, matching) )
887 continue;
888
889 if ( !service->terminate(kIOServiceRequired|kIOServiceSynchronous) ) {
890 ret = kIOReturnUnsupported;
891 break;
892 }
893 }
894 } while( !service && !iter->isValid());
895 iter->release();
896
91447636
A
897 return ret;
898}
899
900static IOReturn _removeDrivers( OSArray * array, OSDictionary * matching )
901{
902 OSCollectionIterator * tables;
903 OSDictionary * dict;
904 OSArray * arrayCopy;
905 IOReturn ret = kIOReturnSuccess;
906
1c79356b 907 // remove configs from catalog.
1c79356b
A
908
909 arrayCopy = OSArray::withCapacity(100);
910 if ( !arrayCopy )
911 return kIOReturnNoMemory;
912
913 tables = OSCollectionIterator::withCollection(arrayCopy);
914 arrayCopy->release();
915 if ( !tables )
916 return kIOReturnNoMemory;
917
918 arrayCopy->merge(array);
919 array->flushCollection();
920 tables->reset();
921 while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
9bccf70c
A
922
923 /* Remove from the catalogue's array any personalities
924 * that match the matching dictionary.
925 * This comparison must be done with only the keys in the
926 * "matching" dict to enable general matching.
927 */
1c79356b
A
928 if ( dict->isEqualTo(matching, matching) )
929 continue;
930
931 array->setObject(dict);
932 }
933
934 tables->release();
935
936 return ret;
937}
938
939IOReturn IOCatalogue::terminateDrivers( OSDictionary * matching )
940{
941 IOReturn ret;
942
91447636 943 ret = _terminateDrivers(matching);
55e303ae 944 IOLockLock( lock );
91447636
A
945 if (kIOReturnSuccess == ret)
946 ret = _removeDrivers(array, matching);
1c79356b 947 kernelTables->reset();
55e303ae 948 IOLockUnlock( lock );
1c79356b
A
949
950 return ret;
951}
952
953IOReturn IOCatalogue::terminateDriversForModule(
954 OSString * moduleName,
955 bool unload )
956{
957 IOReturn ret;
958 OSDictionary * dict;
959
960 dict = OSDictionary::withCapacity(1);
961 if ( !dict )
962 return kIOReturnNoMemory;
963
55e303ae 964 dict->setObject(gIOModuleIdentifierKey, moduleName);
9bccf70c 965
91447636 966 ret = _terminateDrivers(dict);
55e303ae 967 IOLockLock( lock );
91447636
A
968 if (kIOReturnSuccess == ret)
969 ret = _removeDrivers(array, dict);
1c79356b
A
970 kernelTables->reset();
971
972 // Unload the module itself.
973 if ( unload && ret == kIOReturnSuccess ) {
974 // Do kmod stop first.
975 ret = unloadModule(moduleName);
976 }
977
55e303ae 978 IOLockUnlock( lock );
1c79356b
A
979
980 dict->release();
981
982 return ret;
983}
984
985IOReturn IOCatalogue::terminateDriversForModule(
986 const char * moduleName,
987 bool unload )
988{
989 OSString * name;
990 IOReturn ret;
991
992 name = OSString::withCString(moduleName);
993 if ( !name )
994 return kIOReturnNoMemory;
995
996 ret = terminateDriversForModule(name, unload);
997 name->release();
9bccf70c 998
1c79356b
A
999 return ret;
1000}
1001
1002bool IOCatalogue::startMatching( OSDictionary * matching )
1003{
1004 OSDictionary * dict;
1005 OSOrderedSet * set;
1006
1007 if ( !matching )
1008 return false;
1009
1010 set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
1011 (void *)gIOProbeScoreKey);
1012 if ( !set )
1013 return false;
1014
55e303ae 1015 IOLockLock( lock );
1c79356b
A
1016 kernelTables->reset();
1017
1018 while ( (dict = (OSDictionary *)kernelTables->getNextObject()) ) {
9bccf70c
A
1019
1020 /* This comparison must be done with only the keys in the
1021 * "matching" dict to enable general matching.
1022 */
1c79356b
A
1023 if ( dict->isEqualTo(matching, matching) )
1024 AddNewImports(set, dict);
1025 }
1026 // Start device matching.
1027 if ( set->getCount() > 0 ) {
1028 IOService::catalogNewDrivers(set);
1029 generation++;
1030 }
1031
55e303ae 1032 IOLockUnlock( lock );
1c79356b
A
1033
1034 set->release();
1035
1036 return true;
1037}
1038
1039void IOCatalogue::reset(void)
1040{
1c79356b 1041 IOLog("Resetting IOCatalogue.\n");
1c79356b
A
1042}
1043
1044bool IOCatalogue::serialize(OSSerialize * s) const
1045{
1c79356b
A
1046 if ( !s )
1047 return false;
1048
91447636 1049 return super::serialize(s);
1c79356b
A
1050}
1051
55e303ae
A
1052bool IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const
1053{
1054 kern_return_t kr = kIOReturnSuccess;
1055
1056 switch ( kind )
1057 {
1058 case kIOCatalogGetContents:
1059 if (!serialize(s))
1060 kr = kIOReturnNoMemory;
1061 break;
1062
1063 case kIOCatalogGetModuleDemandList:
1064 IOLockLock( lock );
1065 if (!gIOCatalogModuleRequests->serialize(s))
1066 kr = kIOReturnNoMemory;
1067 IOLockUnlock( lock );
1068 break;
1069
1070 case kIOCatalogGetCacheMissList:
1071 IOLockLock( lock );
1072 if (!gIOCatalogCacheMisses->serialize(s))
1073 kr = kIOReturnNoMemory;
1074 IOLockUnlock( lock );
1075 break;
1076
1077 case kIOCatalogGetROMMkextList:
1078 IOLockLock( lock );
1079
1080 if (!gIOCatalogROMMkexts || !gIOCatalogROMMkexts->getCount())
1081 kr = kIOReturnNoResources;
1082 else if (!gIOCatalogROMMkexts->serialize(s))
1083 kr = kIOReturnNoMemory;
1084
1085 if (gIOCatalogROMMkexts)
1086 {
1087 gIOCatalogROMMkexts->release();
1088 gIOCatalogROMMkexts = 0;
1089 }
1090
1091 IOLockUnlock( lock );
1092 break;
1093
1094 default:
1095 kr = kIOReturnBadArgument;
1096 break;
1097 }
1098
1099 return kr;
1100}
1101
1c79356b
A
1102
1103bool IOCatalogue::recordStartupExtensions(void) {
1104 bool result = false;
1105
0b4e3aa0
A
1106 IOLockLock(kld_lock);
1107 if (kernelLinkerPresent && record_startup_extensions_function) {
1c79356b
A
1108 result = (*record_startup_extensions_function)();
1109 } else {
1110 IOLog("Can't record startup extensions; "
1111 "kernel linker is not present.\n");
1112 result = false;
1113 }
0b4e3aa0 1114 IOLockUnlock(kld_lock);
1c79356b
A
1115
1116 return result;
1117}
1118
1119
1120/*********************************************************************
91447636
A
1121* This function operates on sections retrieved from the currently running
1122* 32 bit mach kernel.
1c79356b 1123*********************************************************************/
55e303ae
A
1124bool IOCatalogue::addExtensionsFromArchive(OSData * mkext)
1125{
1126 OSData * copyData;
1c79356b 1127 bool result = false;
55e303ae 1128 bool prelinked;
1c79356b 1129
55e303ae
A
1130 /* The mkext we've been handed (or the data it references) can go away,
1131 * so we need to make a local copy to keep around as long as it might
1132 * be needed.
1133 */
1134 copyData = OSData::withData(mkext);
1135 if (copyData)
1136 {
1137 struct section * infosect;
1138
1139 infosect = getsectbyname("__PRELINK", "__info");
1140 prelinked = (infosect && infosect->addr && infosect->size);
1141
1142 IOLockLock(kld_lock);
1143
1144 if (gIOCatalogROMMkexts)
1145 gIOCatalogROMMkexts->setObject(copyData);
1146
1147 if (prelinked) {
1148 result = true;
1149 } else if (kernelLinkerPresent && add_from_mkext_function) {
1150 result = (*add_from_mkext_function)(copyData);
1151 } else {
1152 IOLog("Can't add startup extensions from archive; "
1153 "kernel linker is not present.\n");
1154 result = false;
1155 }
1156
1157 IOLockUnlock(kld_lock);
1158
1159 copyData->release();
1c79356b
A
1160 }
1161
1162 return result;
1163}
1164
1c79356b
A
1165/*********************************************************************
1166* This function clears out all references to the in-kernel linker,
1167* frees the list of startup extensions in extensionDict, and
1168* deallocates the kernel's __KLD segment to reclaim that memory.
91447636
A
1169*
1170* The segments it operates on are strictly 32 bit segments.
1c79356b
A
1171*********************************************************************/
1172kern_return_t IOCatalogue::removeKernelLinker(void) {
1173 kern_return_t result = KERN_SUCCESS;
c0fea474
A
1174 struct segment_command * segmentLE, *segmentKLD;
1175 boolean_t keepsyms = FALSE;
1176#if __ppc__
1c79356b
A
1177 char * dt_segment_name;
1178 void * segment_paddress;
1179 int segment_size;
c0fea474 1180#endif
1c79356b
A
1181
1182 /* This must be the very first thing done by this function.
1183 */
0b4e3aa0 1184 IOLockLock(kld_lock);
1c79356b
A
1185
1186
1187 /* If the kernel linker isn't here, that's automatically
1188 * a success.
1189 */
1190 if (!kernelLinkerPresent) {
1191 result = KERN_SUCCESS;
1192 goto finish;
1193 }
1194
c0fea474
A
1195 PE_parse_boot_arg("keepsyms", &keepsyms);
1196
1c79356b
A
1197 IOLog("Jettisoning kernel linker.\n");
1198
1199 kernelLinkerPresent = 0;
1200
1201 /* Set the kmod_load_extension function as the means for loading
1202 * a kernel extension.
1203 */
1204 kmod_load_function = &kmod_load_extension;
1205
1206 record_startup_extensions_function = 0;
1207 add_from_mkext_function = 0;
1208 remove_startup_extension_function = 0;
1209
1210
1211 /* Invoke destructors for the __KLD and __LINKEDIT segments.
1212 * Do this for all segments before actually freeing their
1213 * memory so that any cross-dependencies (not that there
1214 * should be any) are handled.
1215 */
c0fea474
A
1216 segmentKLD = getsegbyname("__KLD");
1217 if (!segmentKLD) {
55e303ae
A
1218 IOLog("error removing kernel linker: can't find %s segment\n",
1219 "__KLD");
1c79356b
A
1220 result = KERN_FAILURE;
1221 goto finish;
1222 }
c0fea474 1223 OSRuntimeUnloadCPPForSegment(segmentKLD);
1c79356b 1224
c0fea474
A
1225 segmentLE = getsegbyname("__LINKEDIT");
1226 if (!segmentLE) {
55e303ae
A
1227 IOLog("error removing kernel linker: can't find %s segment\n",
1228 "__LINKEDIT");
1c79356b
A
1229 result = KERN_FAILURE;
1230 goto finish;
1231 }
c0fea474
A
1232 OSRuntimeUnloadCPPForSegment(segmentLE);
1233#if __ppc__
1c79356b
A
1234 /* Free the memory that was set up by bootx.
1235 */
1236 dt_segment_name = "Kernel-__KLD";
1237 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1238 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1239 (int)segment_size);
1240 }
c0fea474
A
1241#elif __i386__
1242 /* On x86, use the mapping data from the segment load command to
1243 * unload KLD and LINKEDIT directly, unless the keepsyms boot-arg
1244 * was enabled. This may invalidate any assumptions about
1245 * "avail_start" defining the lower bound for valid physical addresses.
1246 */
1247 if (!keepsyms && segmentKLD->vmaddr && segmentKLD->vmsize)
1248 ml_static_mfree(segmentKLD->vmaddr, segmentKLD->vmsize);
1249#else
1250#error arch
1251#endif
1252#if __ppc__
1c79356b
A
1253 dt_segment_name = "Kernel-__LINKEDIT";
1254 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1255 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1256 (int)segment_size);
1257 }
c0fea474
A
1258#elif __i386__
1259 if (!keepsyms && segmentLE->vmaddr && segmentLE->vmsize)
1260 ml_static_mfree(segmentLE->vmaddr, segmentLE->vmsize);
1261#else
1262#error arch
1263#endif
1c79356b 1264
55e303ae
A
1265 struct section * sect;
1266 sect = getsectbyname("__PRELINK", "__symtab");
1267 if (sect && sect->addr)
1268 {
1269 vm_offset_t
1270 virt = ml_static_ptovirt(sect->addr);
1271 if( virt) {
1272 ml_static_mfree(virt, sect->size);
1273 }
1274 }
1c79356b
A
1275
1276finish:
1277
1278 /* This must be the very last thing done before returning.
1279 */
0b4e3aa0 1280 IOLockUnlock(kld_lock);
1c79356b
A
1281
1282 return result;
1283}
91447636
A
1284
1285/*********************************************************************
1286* This function stops the catalogue from making kextd requests during
1287* shutdown.
1288*********************************************************************/
1289void IOCatalogue::disableExternalLinker(void) {
1290 IOLockLock(gIOKLDLock);
1291 /* If kmod_load_extension (the kextd requester function) is in use,
1292 * disable new module requests.
1293 */
1294 if (kmod_load_function == &kmod_load_extension) {
1295 kmod_load_function = NULL;
1296 }
1297
1298 IOLockUnlock(gIOKLDLock);
1299}
1300