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