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