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