]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOCatalogue.cpp
xnu-517.9.4.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 * 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.
11 *
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
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>
34 extern "C" {
35 #include <machine/machine_routines.h>
36 #include <mach/kmod.h>
37 #include <mach-o/mach_header.h>
38 #include <kern/host.h>
39 };
40
41 #include <IOKit/IOLib.h>
42
43 #include <IOKit/assert.h>
44
45
46 extern "C" {
47 int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize );
48 extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize );
49 extern void OSRuntimeUnloadCPPForSegment(
50 struct segment_command * segment);
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 */
62 extern "C" {
63 kern_return_t (*kmod_load_function)(char *extension_name) =
64 &kmod_load_extension;
65 bool (*record_startup_extensions_function)(void) = 0;
66 bool (*add_from_mkext_function)(OSData * mkext) = 0;
67 void (*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 */
76 int kernelLinkerPresent = 0;
77
78 #define kModuleKey "CFBundleIdentifier"
79
80 #define super OSObject
81 OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
82
83 #define CATALOGTEST 0
84
85 IOCatalogue * gIOCatalogue;
86 const OSSymbol * gIOClassKey;
87 const OSSymbol * gIOProbeScoreKey;
88 const OSSymbol * gIOModuleIdentifierKey;
89 OSSet * gIOCatalogModuleRequests;
90 OSSet * gIOCatalogCacheMisses;
91 OSSet * gIOCatalogROMMkexts;
92 IOLock * gIOCatalogLock;
93 IOLock * gIOKLDLock;
94
95 /*********************************************************************
96 *********************************************************************/
97
98 OSArray * gIOPrelinkedModules = 0;
99
100 extern "C" kern_return_t
101 kmod_create_internal(
102 kmod_info_t *info,
103 kmod_t *id);
104
105 extern "C" kern_return_t
106 kmod_destroy_internal(kmod_t id);
107
108 extern "C" kern_return_t
109 kmod_start_or_stop(
110 kmod_t id,
111 int start,
112 kmod_args_t *data,
113 mach_msg_type_number_t *dataCount);
114
115 extern "C" kern_return_t kmod_retain(kmod_t id);
116 extern "C" kern_return_t kmod_release(kmod_t id);
117
118 static
119 kern_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));
205 kfree((vm_offset_t) depInfo, sizeof(kmod_info_t));
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
224 static
225 kern_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
258 extern "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) {
278 kfree((vm_offset_t) kmod_info, sizeof(kmod_info_t));
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);
298 break;
299 }
300
301 kr = kmod_load_function((char *)moduleName);
302
303 if (ret != kIOReturnSuccess) {
304 IOLog("IOCatalogue: %s cannot be loaded.\n", moduleName);
305
306 /* If the extension couldn't be loaded this time,
307 * make it unavailable so that no more requests are
308 * made in vain. This also enables other matching
309 * extensions to have a chance.
310 */
311 if (kernelLinkerPresent && remove_startup_extension_function) {
312 (*remove_startup_extension_function)(moduleName);
313 }
314 ret = false;
315
316 } else if (kernelLinkerPresent) {
317 // If kern linker is here, the driver is actually loaded,
318 // so return true.
319 ret = true;
320
321 } else {
322 // kern linker isn't here, a request has been queued
323 // but the module isn't necessarily loaded yet, so stall.
324 ret = false;
325 }
326 }
327 while (false);
328
329 IOLockUnlock(gIOKLDLock);
330
331 if (sym)
332 {
333 IOLockLock(gIOCatalogLock);
334 gIOCatalogModuleRequests->setObject(sym);
335 if (cacheMiss)
336 gIOCatalogCacheMisses->setObject(sym);
337 IOLockUnlock(gIOCatalogLock);
338 }
339
340 return ret;
341 }
342
343 extern "C" kern_return_t kmod_unload_cache(void)
344 {
345 OSArray * prelinkedModules = gIOPrelinkedModules;
346 kern_return_t result = KERN_FAILURE;
347 OSDictionary * dict;
348 UInt32 idx;
349 UInt32 * prelink;
350 OSData * data;
351
352 if (!gIOPrelinkedModules)
353 return KERN_SUCCESS;
354
355 IOLockLock(gIOKLDLock);
356 for (idx = 0;
357 (dict = (OSDictionary *) prelinkedModules->getObject(idx));
358 idx++)
359 {
360 data = OSDynamicCast(OSData, dict->getObject("OSBundlePrelink"));
361 if (!data)
362 continue;
363 prelink = (UInt32 *) data->getBytesNoCopy();
364
365 kmod_info_t * kmod_info = (kmod_info_t *) OSReadBigInt32(prelink, 0);
366 vm_offset_t
367 virt = ml_static_ptovirt(kmod_info->address);
368 if( virt) {
369 ml_static_mfree(virt, kmod_info->size);
370 }
371 }
372
373 gIOPrelinkedModules->release();
374 gIOPrelinkedModules = 0;
375
376 IOLockUnlock(gIOKLDLock);
377
378 return result;
379 }
380
381 extern "C" kern_return_t kmod_load_from_cache(const char * kmod_name)
382 {
383 kern_return_t kr;
384 const OSSymbol * sym = OSSymbol::withCStringNoCopy(kmod_name);
385
386 if (sym)
387 {
388 kr = kmod_load_from_cache_sym(sym);
389 sym->release();
390 }
391 else
392 kr = kIOReturnNoMemory;
393
394 return kr;
395 }
396
397 /*********************************************************************
398 *********************************************************************/
399
400 static void UniqueProperties( OSDictionary * dict )
401 {
402 OSString * data;
403
404 data = OSDynamicCast( OSString, dict->getObject( gIOClassKey ));
405 if( data) {
406 const OSSymbol *classSymbol = OSSymbol::withString(data);
407
408 dict->setObject( gIOClassKey, (OSSymbol *) classSymbol);
409 classSymbol->release();
410 }
411
412 data = OSDynamicCast( OSString, dict->getObject( gIOMatchCategoryKey ));
413 if( data) {
414 const OSSymbol *classSymbol = OSSymbol::withString(data);
415
416 dict->setObject( gIOMatchCategoryKey, (OSSymbol *) classSymbol);
417 classSymbol->release();
418 }
419 }
420
421 void IOCatalogue::initialize( void )
422 {
423 OSArray * array;
424 OSString * errorString;
425 bool rc;
426
427 extern const char * gIOKernelConfigTables;
428
429 array = OSDynamicCast(OSArray, OSUnserialize(gIOKernelConfigTables, &errorString));
430 if (!array && errorString) {
431 IOLog("KernelConfigTables syntax error: %s\n",
432 errorString->getCStringNoCopy());
433 errorString->release();
434 }
435
436 gIOClassKey = OSSymbol::withCStringNoCopy( kIOClassKey );
437 gIOProbeScoreKey = OSSymbol::withCStringNoCopy( kIOProbeScoreKey );
438 gIOModuleIdentifierKey = OSSymbol::withCStringNoCopy( kModuleKey );
439 gIOCatalogModuleRequests = OSSet::withCapacity(16);
440 gIOCatalogCacheMisses = OSSet::withCapacity(16);
441 gIOCatalogROMMkexts = OSSet::withCapacity(4);
442
443 assert( array && gIOClassKey && gIOProbeScoreKey
444 && gIOModuleIdentifierKey && gIOCatalogModuleRequests);
445
446 gIOCatalogue = new IOCatalogue;
447 assert(gIOCatalogue);
448 rc = gIOCatalogue->init(array);
449 assert(rc);
450 array->release();
451 }
452
453 // Initialize the IOCatalog object.
454 bool IOCatalogue::init(OSArray * initArray)
455 {
456 IORegistryEntry * entry;
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
468 gIOCatalogLock = IOLockAlloc();
469 gIOKLDLock = IOLockAlloc();
470
471 lock = gIOCatalogLock;
472 kld_lock = gIOKLDLock;
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
488 entry = IORegistryEntry::getRegistryRoot();
489 if ( entry )
490 entry->setProperty(kIOCatalogueKey, this);
491
492 return true;
493 }
494
495 // Release all resources used by IOCatalogue and deallocate.
496 // This will probably never be called.
497 void IOCatalogue::free( void )
498 {
499 if ( array )
500 array->release();
501
502 if ( kernelTables )
503 kernelTables->release();
504
505 super::free();
506 }
507
508 #if CATALOGTEST
509
510 static int hackLimit;
511
512 enum { kDriversPerIter = 4 };
513
514 void IOCatalogue::ping( thread_call_param_t arg, thread_call_param_t)
515 {
516 IOCatalogue * self = (IOCatalogue *) arg;
517 OSOrderedSet * set;
518 OSDictionary * table;
519 int newLimit;
520
521 set = OSOrderedSet::withCapacity( 1 );
522
523 IOLockLock( &self->lock );
524
525 for( newLimit = 0; newLimit < kDriversPerIter; newLimit++) {
526 table = (OSDictionary *) self->array->getObject(
527 hackLimit + newLimit );
528 if( table) {
529 set->setLastObject( table );
530
531 OSSymbol * sym = (OSSymbol *) table->getObject( gIOClassKey );
532 kprintf("enabling %s\n", sym->getCStringNoCopy());
533
534 } else {
535 newLimit--;
536 break;
537 }
538 }
539
540 IOService::catalogNewDrivers( set );
541
542 hackLimit += newLimit;
543 self->generation++;
544
545 IOLockUnlock( &self->lock );
546
547 if( kDriversPerIter == newLimit) {
548 AbsoluteTime deadline;
549 clock_interval_to_deadline( 500, kMillisecondScale );
550 thread_call_func_delayed( ping, this, deadline );
551 }
552 }
553 #endif
554
555 OSOrderedSet * IOCatalogue::findDrivers( IOService * service,
556 SInt32 * generationCount )
557 {
558 OSDictionary * nextTable;
559 OSOrderedSet * set;
560 OSString * imports;
561
562 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
563 (void *)gIOProbeScoreKey );
564 if( !set )
565 return( 0 );
566
567 IOLockLock( lock );
568 kernelTables->reset();
569
570 #if CATALOGTEST
571 int hackIndex = 0;
572 #endif
573 while( (nextTable = (OSDictionary *) kernelTables->getNextObject())) {
574 #if CATALOGTEST
575 if( hackIndex++ > hackLimit)
576 break;
577 #endif
578 imports = OSDynamicCast( OSString,
579 nextTable->getObject( gIOProviderClassKey ));
580 if( imports && service->metaCast( imports ))
581 set->setObject( nextTable );
582 }
583
584 *generationCount = getGenerationCount();
585
586 IOLockUnlock( lock );
587
588 return( set );
589 }
590
591 // Is personality already in the catalog?
592 OSOrderedSet * IOCatalogue::findDrivers( OSDictionary * matching,
593 SInt32 * generationCount)
594 {
595 OSDictionary * dict;
596 OSOrderedSet * set;
597
598 UniqueProperties(matching);
599
600 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
601 (void *)gIOProbeScoreKey );
602
603 IOLockLock( lock );
604 kernelTables->reset();
605 while ( (dict = (OSDictionary *) kernelTables->getNextObject()) ) {
606
607 /* This comparison must be done with only the keys in the
608 * "matching" dict to enable general searches.
609 */
610 if ( dict->isEqualTo(matching, matching) )
611 set->setObject(dict);
612 }
613 *generationCount = getGenerationCount();
614 IOLockUnlock( lock );
615
616 return set;
617 }
618
619 // Add a new personality to the set if it has a unique IOResourceMatchKey value.
620 // XXX -- svail: This should be optimized.
621 // esb - There doesn't seem like any reason to do this - it causes problems
622 // esb - when there are more than one loadable driver matching on the same provider class
623 static void AddNewImports( OSOrderedSet * set, OSDictionary * dict )
624 {
625 set->setObject(dict);
626 }
627
628 // Add driver config tables to catalog and start matching process.
629 bool IOCatalogue::addDrivers(OSArray * drivers,
630 bool doNubMatching )
631 {
632 OSCollectionIterator * iter;
633 OSDictionary * dict;
634 OSOrderedSet * set;
635 OSArray * persons;
636 OSString * moduleName;
637 bool ret;
638
639 ret = true;
640 persons = OSDynamicCast(OSArray, drivers);
641 if ( !persons )
642 return false;
643
644 iter = OSCollectionIterator::withCollection( persons );
645 if (!iter )
646 return false;
647
648 set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
649 (void *)gIOProbeScoreKey );
650 if ( !set ) {
651 iter->release();
652 return false;
653 }
654
655 IOLockLock( lock );
656 while ( (dict = (OSDictionary *) iter->getNextObject()) )
657 {
658 if ((moduleName = OSDynamicCast(OSString, dict->getObject("OSBundleModuleDemand"))))
659 {
660 IOLockUnlock( lock );
661 ret = kmod_load_request(moduleName->getCStringNoCopy(), false);
662 IOLockLock( lock );
663 ret = true;
664 }
665 else
666 {
667 SInt count;
668
669 UniqueProperties( dict );
670
671 // Add driver personality to catalogue.
672 count = array->getCount();
673 while ( count-- ) {
674 OSDictionary * driver;
675
676 // Be sure not to double up on personalities.
677 driver = (OSDictionary *)array->getObject(count);
678
679 /* Unlike in other functions, this comparison must be exact!
680 * The catalogue must be able to contain personalities that
681 * are proper supersets of others.
682 * Do not compare just the properties present in one driver
683 * pesonality or the other.
684 */
685 if (dict->isEqualTo(driver))
686 break;
687 }
688 if (count >= 0)
689 // its a dup
690 continue;
691
692 ret = array->setObject( dict );
693 if (!ret)
694 break;
695
696 AddNewImports( set, dict );
697 }
698 }
699 // Start device matching.
700 if (doNubMatching && (set->getCount() > 0)) {
701 IOService::catalogNewDrivers( set );
702 generation++;
703 }
704 IOLockUnlock( lock );
705
706 set->release();
707 iter->release();
708
709 return ret;
710 }
711
712 // Remove drivers from the catalog which match the
713 // properties in the matching dictionary.
714 bool IOCatalogue::removeDrivers( OSDictionary * matching,
715 bool doNubMatching)
716 {
717 OSCollectionIterator * tables;
718 OSDictionary * dict;
719 OSOrderedSet * set;
720 OSArray * arrayCopy;
721
722 if ( !matching )
723 return false;
724
725 set = OSOrderedSet::withCapacity(10,
726 IOServiceOrdering,
727 (void *)gIOProbeScoreKey);
728 if ( !set )
729 return false;
730
731 arrayCopy = OSArray::withCapacity(100);
732 if ( !arrayCopy ) {
733 set->release();
734 return false;
735 }
736
737 tables = OSCollectionIterator::withCollection(arrayCopy);
738 arrayCopy->release();
739 if ( !tables ) {
740 set->release();
741 return false;
742 }
743
744 UniqueProperties( matching );
745
746 IOLockLock( lock );
747 kernelTables->reset();
748 arrayCopy->merge(array);
749 array->flushCollection();
750 tables->reset();
751 while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
752
753 /* This comparison must be done with only the keys in the
754 * "matching" dict to enable general searches.
755 */
756 if ( dict->isEqualTo(matching, matching) ) {
757 AddNewImports( set, dict );
758 continue;
759 }
760
761 array->setObject(dict);
762 }
763 // Start device matching.
764 if ( doNubMatching && (set->getCount() > 0) ) {
765 IOService::catalogNewDrivers(set);
766 generation++;
767 }
768 IOLockUnlock( lock );
769
770 set->release();
771 tables->release();
772
773 return true;
774 }
775
776 // Return the generation count.
777 SInt32 IOCatalogue::getGenerationCount( void ) const
778 {
779 return( generation );
780 }
781
782 bool IOCatalogue::isModuleLoaded( OSString * moduleName ) const
783 {
784 return isModuleLoaded(moduleName->getCStringNoCopy());
785 }
786
787 bool IOCatalogue::isModuleLoaded( const char * moduleName ) const
788 {
789 return (kmod_load_request(moduleName, true));
790 }
791
792 // Check to see if module has been loaded already.
793 bool IOCatalogue::isModuleLoaded( OSDictionary * driver ) const
794 {
795 OSString * moduleName = NULL;
796
797 if ( !driver )
798 return false;
799
800 moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKey));
801 if ( moduleName )
802 return isModuleLoaded(moduleName);
803
804 /* If a personality doesn't hold the "CFBundleIdentifier" key
805 * it is assumed to be an "in-kernel" driver.
806 */
807 return true;
808 }
809
810 // This function is called after a module has been loaded.
811 void IOCatalogue::moduleHasLoaded( OSString * moduleName )
812 {
813 OSDictionary * dict;
814
815 dict = OSDictionary::withCapacity(2);
816 dict->setObject(gIOModuleIdentifierKey, moduleName);
817 startMatching(dict);
818 dict->release();
819 }
820
821 void IOCatalogue::moduleHasLoaded( const char * moduleName )
822 {
823 OSString * name;
824
825 name = OSString::withCString(moduleName);
826 moduleHasLoaded(name);
827 name->release();
828 }
829
830 IOReturn IOCatalogue::unloadModule( OSString * moduleName ) const
831 {
832 kmod_info_t * k_info = 0;
833 kern_return_t ret;
834 const char * name;
835
836 ret = kIOReturnBadArgument;
837 if ( moduleName ) {
838 name = moduleName->getCStringNoCopy();
839 k_info = kmod_lookupbyname_locked((char *)name);
840 if ( k_info && (k_info->reference_count < 1) ) {
841 if ( k_info->stop &&
842 !((ret = k_info->stop(k_info, 0)) == kIOReturnSuccess) ) {
843
844 kfree((vm_offset_t) k_info, sizeof(kmod_info_t));
845 return ret;
846 }
847
848 ret = kmod_destroy(host_priv_self(), k_info->id);
849 }
850 }
851
852 if (k_info) {
853 kfree((vm_offset_t) k_info, sizeof(kmod_info_t));
854 }
855
856 return ret;
857 }
858
859 static IOReturn _terminateDrivers( OSArray * array, OSDictionary * matching )
860 {
861 OSCollectionIterator * tables;
862 OSDictionary * dict;
863 OSIterator * iter;
864 OSArray * arrayCopy;
865 IOService * service;
866 IOReturn ret;
867
868 if ( !matching )
869 return kIOReturnBadArgument;
870
871 ret = kIOReturnSuccess;
872 dict = 0;
873 iter = IORegistryIterator::iterateOver(gIOServicePlane,
874 kIORegistryIterateRecursively);
875 if ( !iter )
876 return kIOReturnNoMemory;
877
878 UniqueProperties( matching );
879
880 // terminate instances.
881 do {
882 iter->reset();
883 while( (service = (IOService *)iter->getNextObject()) ) {
884 dict = service->getPropertyTable();
885 if ( !dict )
886 continue;
887
888 /* Terminate only for personalities that match the matching dictionary.
889 * This comparison must be done with only the keys in the
890 * "matching" dict to enable general matching.
891 */
892 if ( !dict->isEqualTo(matching, matching) )
893 continue;
894
895 if ( !service->terminate(kIOServiceRequired|kIOServiceSynchronous) ) {
896 ret = kIOReturnUnsupported;
897 break;
898 }
899 }
900 } while( !service && !iter->isValid());
901 iter->release();
902
903 // remove configs from catalog.
904 if ( ret != kIOReturnSuccess )
905 return ret;
906
907 arrayCopy = OSArray::withCapacity(100);
908 if ( !arrayCopy )
909 return kIOReturnNoMemory;
910
911 tables = OSCollectionIterator::withCollection(arrayCopy);
912 arrayCopy->release();
913 if ( !tables )
914 return kIOReturnNoMemory;
915
916 arrayCopy->merge(array);
917 array->flushCollection();
918 tables->reset();
919 while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
920
921 /* Remove from the catalogue's array any personalities
922 * that match the matching dictionary.
923 * This comparison must be done with only the keys in the
924 * "matching" dict to enable general matching.
925 */
926 if ( dict->isEqualTo(matching, matching) )
927 continue;
928
929 array->setObject(dict);
930 }
931
932 tables->release();
933
934 return ret;
935 }
936
937 IOReturn IOCatalogue::terminateDrivers( OSDictionary * matching )
938 {
939 IOReturn ret;
940
941 ret = kIOReturnSuccess;
942 IOLockLock( lock );
943 ret = _terminateDrivers(array, matching);
944 kernelTables->reset();
945 IOLockUnlock( lock );
946
947 return ret;
948 }
949
950 IOReturn IOCatalogue::terminateDriversForModule(
951 OSString * moduleName,
952 bool unload )
953 {
954 IOReturn ret;
955 OSDictionary * dict;
956
957 dict = OSDictionary::withCapacity(1);
958 if ( !dict )
959 return kIOReturnNoMemory;
960
961 dict->setObject(gIOModuleIdentifierKey, moduleName);
962
963 IOLockLock( lock );
964
965 ret = _terminateDrivers(array, dict);
966 kernelTables->reset();
967
968 // Unload the module itself.
969 if ( unload && ret == kIOReturnSuccess ) {
970 // Do kmod stop first.
971 ret = unloadModule(moduleName);
972 }
973
974 IOLockUnlock( lock );
975
976 dict->release();
977
978 return ret;
979 }
980
981 IOReturn IOCatalogue::terminateDriversForModule(
982 const char * moduleName,
983 bool unload )
984 {
985 OSString * name;
986 IOReturn ret;
987
988 name = OSString::withCString(moduleName);
989 if ( !name )
990 return kIOReturnNoMemory;
991
992 ret = terminateDriversForModule(name, unload);
993 name->release();
994
995 return ret;
996 }
997
998 bool IOCatalogue::startMatching( OSDictionary * matching )
999 {
1000 OSDictionary * dict;
1001 OSOrderedSet * set;
1002
1003 if ( !matching )
1004 return false;
1005
1006 set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
1007 (void *)gIOProbeScoreKey);
1008 if ( !set )
1009 return false;
1010
1011 IOLockLock( lock );
1012 kernelTables->reset();
1013
1014 while ( (dict = (OSDictionary *)kernelTables->getNextObject()) ) {
1015
1016 /* This comparison must be done with only the keys in the
1017 * "matching" dict to enable general matching.
1018 */
1019 if ( dict->isEqualTo(matching, matching) )
1020 AddNewImports(set, dict);
1021 }
1022 // Start device matching.
1023 if ( set->getCount() > 0 ) {
1024 IOService::catalogNewDrivers(set);
1025 generation++;
1026 }
1027
1028 IOLockUnlock( lock );
1029
1030 set->release();
1031
1032 return true;
1033 }
1034
1035 void IOCatalogue::reset(void)
1036 {
1037 IOLog("Resetting IOCatalogue.\n");
1038 }
1039
1040 bool IOCatalogue::serialize(OSSerialize * s) const
1041 {
1042 bool ret;
1043
1044 if ( !s )
1045 return false;
1046
1047 IOLockLock( lock );
1048
1049 ret = array->serialize(s);
1050
1051 IOLockUnlock( lock );
1052
1053 return ret;
1054 }
1055
1056 bool IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const
1057 {
1058 kern_return_t kr = kIOReturnSuccess;
1059
1060 switch ( kind )
1061 {
1062 case kIOCatalogGetContents:
1063 if (!serialize(s))
1064 kr = kIOReturnNoMemory;
1065 break;
1066
1067 case kIOCatalogGetModuleDemandList:
1068 IOLockLock( lock );
1069 if (!gIOCatalogModuleRequests->serialize(s))
1070 kr = kIOReturnNoMemory;
1071 IOLockUnlock( lock );
1072 break;
1073
1074 case kIOCatalogGetCacheMissList:
1075 IOLockLock( lock );
1076 if (!gIOCatalogCacheMisses->serialize(s))
1077 kr = kIOReturnNoMemory;
1078 IOLockUnlock( lock );
1079 break;
1080
1081 case kIOCatalogGetROMMkextList:
1082 IOLockLock( lock );
1083
1084 if (!gIOCatalogROMMkexts || !gIOCatalogROMMkexts->getCount())
1085 kr = kIOReturnNoResources;
1086 else if (!gIOCatalogROMMkexts->serialize(s))
1087 kr = kIOReturnNoMemory;
1088
1089 if (gIOCatalogROMMkexts)
1090 {
1091 gIOCatalogROMMkexts->release();
1092 gIOCatalogROMMkexts = 0;
1093 }
1094
1095 IOLockUnlock( lock );
1096 break;
1097
1098 default:
1099 kr = kIOReturnBadArgument;
1100 break;
1101 }
1102
1103 return kr;
1104 }
1105
1106
1107 bool IOCatalogue::recordStartupExtensions(void) {
1108 bool result = false;
1109
1110 IOLockLock(kld_lock);
1111 if (kernelLinkerPresent && record_startup_extensions_function) {
1112 result = (*record_startup_extensions_function)();
1113 } else {
1114 IOLog("Can't record startup extensions; "
1115 "kernel linker is not present.\n");
1116 result = false;
1117 }
1118 IOLockUnlock(kld_lock);
1119
1120 return result;
1121 }
1122
1123
1124 /*********************************************************************
1125 *********************************************************************/
1126 bool IOCatalogue::addExtensionsFromArchive(OSData * mkext)
1127 {
1128 OSData * copyData;
1129 bool result = false;
1130 bool prelinked;
1131
1132 /* The mkext we've been handed (or the data it references) can go away,
1133 * so we need to make a local copy to keep around as long as it might
1134 * be needed.
1135 */
1136 copyData = OSData::withData(mkext);
1137 if (copyData)
1138 {
1139 struct section * infosect;
1140
1141 infosect = getsectbyname("__PRELINK", "__info");
1142 prelinked = (infosect && infosect->addr && infosect->size);
1143
1144 IOLockLock(kld_lock);
1145
1146 if (gIOCatalogROMMkexts)
1147 gIOCatalogROMMkexts->setObject(copyData);
1148
1149 if (prelinked) {
1150 result = true;
1151 } else if (kernelLinkerPresent && add_from_mkext_function) {
1152 result = (*add_from_mkext_function)(copyData);
1153 } else {
1154 IOLog("Can't add startup extensions from archive; "
1155 "kernel linker is not present.\n");
1156 result = false;
1157 }
1158
1159 IOLockUnlock(kld_lock);
1160
1161 copyData->release();
1162 }
1163
1164 return result;
1165 }
1166
1167
1168 /*********************************************************************
1169 * This function clears out all references to the in-kernel linker,
1170 * frees the list of startup extensions in extensionDict, and
1171 * deallocates the kernel's __KLD segment to reclaim that memory.
1172 *********************************************************************/
1173 kern_return_t IOCatalogue::removeKernelLinker(void) {
1174 kern_return_t result = KERN_SUCCESS;
1175 struct segment_command * segment;
1176 char * dt_segment_name;
1177 void * segment_paddress;
1178 int segment_size;
1179
1180 /* This must be the very first thing done by this function.
1181 */
1182 IOLockLock(kld_lock);
1183
1184
1185 /* If the kernel linker isn't here, that's automatically
1186 * a success.
1187 */
1188 if (!kernelLinkerPresent) {
1189 result = KERN_SUCCESS;
1190 goto finish;
1191 }
1192
1193 IOLog("Jettisoning kernel linker.\n");
1194
1195 kernelLinkerPresent = 0;
1196
1197 /* Set the kmod_load_extension function as the means for loading
1198 * a kernel extension.
1199 */
1200 kmod_load_function = &kmod_load_extension;
1201
1202 record_startup_extensions_function = 0;
1203 add_from_mkext_function = 0;
1204 remove_startup_extension_function = 0;
1205
1206
1207 /* Invoke destructors for the __KLD and __LINKEDIT segments.
1208 * Do this for all segments before actually freeing their
1209 * memory so that any cross-dependencies (not that there
1210 * should be any) are handled.
1211 */
1212 segment = getsegbyname("__KLD");
1213 if (!segment) {
1214 IOLog("error removing kernel linker: can't find %s segment\n",
1215 "__KLD");
1216 result = KERN_FAILURE;
1217 goto finish;
1218 }
1219 OSRuntimeUnloadCPPForSegment(segment);
1220
1221 segment = getsegbyname("__LINKEDIT");
1222 if (!segment) {
1223 IOLog("error removing kernel linker: can't find %s segment\n",
1224 "__LINKEDIT");
1225 result = KERN_FAILURE;
1226 goto finish;
1227 }
1228 OSRuntimeUnloadCPPForSegment(segment);
1229
1230
1231 /* Free the memory that was set up by bootx.
1232 */
1233 dt_segment_name = "Kernel-__KLD";
1234 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1235 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1236 (int)segment_size);
1237 }
1238
1239 dt_segment_name = "Kernel-__LINKEDIT";
1240 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
1241 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
1242 (int)segment_size);
1243 }
1244
1245 struct section * sect;
1246 sect = getsectbyname("__PRELINK", "__symtab");
1247 if (sect && sect->addr)
1248 {
1249 vm_offset_t
1250 virt = ml_static_ptovirt(sect->addr);
1251 if( virt) {
1252 ml_static_mfree(virt, sect->size);
1253 }
1254 }
1255
1256 finish:
1257
1258 /* This must be the very last thing done before returning.
1259 */
1260 IOLockUnlock(kld_lock);
1261
1262 return result;
1263 }