]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOCatalogue.cpp
xnu-517.9.4.tar.gz
[apple/xnu.git] / iokit / Kernel / IOCatalogue.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
e5568f75
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
24 *
25 * HISTORY
26 *
27 */
28
29#include <IOKit/IODeviceTreeSupport.h>
30#include <IOKit/IOService.h>
31#include <libkern/c++/OSContainers.h>
32#include <IOKit/IOCatalogue.h>
33#include <libkern/c++/OSUnserialize.h>
34extern "C" {
35#include <machine/machine_routines.h>
36#include <mach/kmod.h>
37#include <mach-o/mach_header.h>
9bccf70c 38#include <kern/host.h>
1c79356b
A
39};
40
41#include <IOKit/IOLib.h>
42
43#include <IOKit/assert.h>
44
45
46extern "C" {
47int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize );
48extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize );
49extern 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 */
62extern "C" {
63kern_return_t (*kmod_load_function)(char *extension_name) =
64 &kmod_load_extension;
65bool (*record_startup_extensions_function)(void) = 0;
66bool (*add_from_mkext_function)(OSData * mkext) = 0;
67void (*remove_startup_extension_function)(const char * name) = 0;
68};
69
70
71/*****
72 * A few parts of IOCatalogue require knowledge of
73 * whether the in-kernel linker is present. This
74 * variable is set by libsa's bootstrap code.
75 */
76int kernelLinkerPresent = 0;
77
1c79356b
A
78#define kModuleKey "CFBundleIdentifier"
79
55e303ae 80#define super OSObject
1c79356b
A
81OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
82
83#define CATALOGTEST 0
84
55e303ae
A
85IOCatalogue * gIOCatalogue;
86const OSSymbol * gIOClassKey;
87const OSSymbol * gIOProbeScoreKey;
88const OSSymbol * gIOModuleIdentifierKey;
89OSSet * gIOCatalogModuleRequests;
90OSSet * gIOCatalogCacheMisses;
91OSSet * gIOCatalogROMMkexts;
92IOLock * gIOCatalogLock;
93IOLock * gIOKLDLock;
94
95/*********************************************************************
96*********************************************************************/
97
98OSArray * gIOPrelinkedModules = 0;
99
100extern "C" kern_return_t
101kmod_create_internal(
102 kmod_info_t *info,
103 kmod_t *id);
104
105extern "C" kern_return_t
106kmod_destroy_internal(kmod_t id);
107
108extern "C" kern_return_t
109kmod_start_or_stop(
110 kmod_t id,
111 int start,
112 kmod_args_t *data,
113 mach_msg_type_number_t *dataCount);
114
115extern "C" kern_return_t kmod_retain(kmod_t id);
116extern "C" kern_return_t kmod_release(kmod_t id);
117
118static
119kern_return_t start_prelink_module(UInt32 moduleIndex)
120{
121 kern_return_t kr = KERN_SUCCESS;
122 UInt32 * togo;
123 SInt32 count, where, end;
124 UInt32 * prelink;
125 SInt32 next, lastDep;
126 OSData * data;
127 OSString * str;
128 OSDictionary * dict;
129
130 OSArray *
131 prelinkedModules = gIOPrelinkedModules;
132
133 togo = IONew(UInt32, prelinkedModules->getCount());
134 togo[0] = moduleIndex;
135 count = 1;
136
137 for (next = 0; next < count; next++)
138 {
139 dict = (OSDictionary *) prelinkedModules->getObject(togo[next]);
140
141 data = OSDynamicCast(OSData, dict->getObject("OSBundlePrelink"));
142 if (!data)
143 {
144 // already started or no code
145 if (togo[next] == moduleIndex)
146 {
147 kr = KERN_FAILURE;
148 break;
149 }
150 continue;
151 }
152 prelink = (UInt32 *) data->getBytesNoCopy();
153 lastDep = OSReadBigInt32(prelink, 12);
154 for (SInt32 idx = OSReadBigInt32(prelink, 8); idx < lastDep; idx += sizeof(UInt32))
155 {
156 UInt32 depIdx = OSReadBigInt32(prelink, idx) - 1;
157
158 for (where = next + 1;
159 (where < count) && (togo[where] > depIdx);
160 where++) {}
161
162 if (where != count)
163 {
164 if (togo[where] == depIdx)
165 continue;
166 for (end = count; end != where; end--)
167 togo[end] = togo[end - 1];
168 }
169 count++;
170 togo[where] = depIdx;
171 }
172 }
173
174 if (KERN_SUCCESS != kr)
175 return kr;
176
177 for (next = (count - 1); next >= 0; next--)
178 {
179 dict = (OSDictionary *) prelinkedModules->getObject(togo[next]);
180
181 data = OSDynamicCast(OSData, dict->getObject("OSBundlePrelink"));
182 if (!data)
183 continue;
184 prelink = (UInt32 *) data->getBytesNoCopy();
185
186 kmod_t id;
187 kmod_info_t * kmod_info = (kmod_info_t *) OSReadBigInt32(prelink, 0);
188
189 kr = kmod_create_internal(kmod_info, &id);
190 if (KERN_SUCCESS != kr)
191 break;
192
193 lastDep = OSReadBigInt32(prelink, 12);
194 for (SInt32 idx = OSReadBigInt32(prelink, 8); idx < lastDep; idx += sizeof(UInt32))
195 {
196 OSDictionary * depDict;
197 kmod_info_t * depInfo;
198
199 depDict = (OSDictionary *) prelinkedModules->getObject(OSReadBigInt32(prelink, idx) - 1);
200 str = OSDynamicCast(OSString, depDict->getObject(kModuleKey));
201 depInfo = kmod_lookupbyname_locked(str->getCStringNoCopy());
202 if (depInfo)
203 {
204 kr = kmod_retain(KMOD_PACK_IDS(id, depInfo->id));
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
224static
225kern_return_t kmod_load_from_cache_sym(const OSSymbol * kmod_name)
226{
227 OSArray * prelinkedModules = gIOPrelinkedModules;
228 kern_return_t result = KERN_FAILURE;
229 OSDictionary * dict;
230 OSObject * ident;
231 UInt32 idx;
232
233 if (!gIOPrelinkedModules)
234 return KERN_FAILURE;
235
236 for (idx = 0;
237 (dict = (OSDictionary *) prelinkedModules->getObject(idx));
238 idx++)
239 {
240 if ((ident = dict->getObject(kModuleKey))
241 && kmod_name->isEqualTo(ident))
242 break;
243 }
244 if (dict)
245 {
246 if (kernelLinkerPresent && dict->getObject("OSBundleDefer"))
247 {
248 kmod_load_extension((char *) kmod_name->getCStringNoCopy());
249 result = kIOReturnOffline;
250 }
251 else
252 result = start_prelink_module(idx);
253 }
254
255 return result;
256}
257
258extern "C" Boolean kmod_load_request(const char * moduleName, Boolean make_request)
259{
260 bool ret, cacheMiss = false;
261 kern_return_t kr;
262 const OSSymbol * sym = 0;
263 kmod_info_t * kmod_info;
264
265 if (!moduleName)
266 return false;
267
268 /* To make sure this operation completes even if a bad extension needs
269 * to be removed, take the kld lock for this whole block, spanning the
270 * kmod_load_function() and remove_startup_extension_function() calls.
271 */
272 IOLockLock(gIOKLDLock);
273 do
274 {
275 // Is the module already loaded?
276 ret = (0 != (kmod_info = kmod_lookupbyname_locked((char *)moduleName)));
277 if (ret) {
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
343extern "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
381extern "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*********************************************************************/
1c79356b
A
399
400static 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
421void 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
55e303ae
A
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);
1c79356b
A
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.
454bool 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
55e303ae
A
468 gIOCatalogLock = IOLockAlloc();
469 gIOKLDLock = IOLockAlloc();
470
471 lock = gIOCatalogLock;
472 kld_lock = gIOKLDLock;
1c79356b
A
473
474 kernelTables->reset();
475 while( (dict = (OSDictionary *) kernelTables->getNextObject())) {
476 UniqueProperties(dict);
477 if( 0 == dict->getObject( gIOClassKey ))
478 IOLog("Missing or bad \"%s\" key\n",
479 gIOClassKey->getCStringNoCopy());
480 }
481
482#if CATALOGTEST
483 AbsoluteTime deadline;
484 clock_interval_to_deadline( 1000, kMillisecondScale );
485 thread_call_func_delayed( ping, this, deadline );
486#endif
487
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.
497void 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
510static int hackLimit;
511
512enum { kDriversPerIter = 4 };
513
514void 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
55e303ae 523 IOLockLock( &self->lock );
1c79356b
A
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
55e303ae 545 IOLockUnlock( &self->lock );
1c79356b
A
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
555OSOrderedSet * 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
55e303ae 567 IOLockLock( lock );
1c79356b
A
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
55e303ae 586 IOLockUnlock( lock );
1c79356b
A
587
588 return( set );
589}
590
591// Is personality already in the catalog?
592OSOrderedSet * 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
55e303ae 603 IOLockLock( lock );
1c79356b
A
604 kernelTables->reset();
605 while ( (dict = (OSDictionary *) kernelTables->getNextObject()) ) {
9bccf70c
A
606
607 /* This comparison must be done with only the keys in the
608 * "matching" dict to enable general searches.
609 */
1c79356b
A
610 if ( dict->isEqualTo(matching, matching) )
611 set->setObject(dict);
612 }
613 *generationCount = getGenerationCount();
55e303ae 614 IOLockUnlock( lock );
1c79356b
A
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
623static void AddNewImports( OSOrderedSet * set, OSDictionary * dict )
624{
625 set->setObject(dict);
626}
627
628// Add driver config tables to catalog and start matching process.
629bool IOCatalogue::addDrivers(OSArray * drivers,
55e303ae 630 bool doNubMatching )
1c79356b
A
631{
632 OSCollectionIterator * iter;
633 OSDictionary * dict;
634 OSOrderedSet * set;
635 OSArray * persons;
55e303ae 636 OSString * moduleName;
1c79356b
A
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
55e303ae
A
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 }
1c79356b
A
698 }
699 // Start device matching.
55e303ae 700 if (doNubMatching && (set->getCount() > 0)) {
1c79356b
A
701 IOService::catalogNewDrivers( set );
702 generation++;
703 }
55e303ae 704 IOLockUnlock( lock );
1c79356b 705
1c79356b
A
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.
714bool IOCatalogue::removeDrivers( OSDictionary * matching,
55e303ae 715 bool doNubMatching)
1c79356b
A
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
55e303ae 746 IOLockLock( lock );
1c79356b
A
747 kernelTables->reset();
748 arrayCopy->merge(array);
749 array->flushCollection();
750 tables->reset();
751 while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
9bccf70c
A
752
753 /* This comparison must be done with only the keys in the
754 * "matching" dict to enable general searches.
755 */
1c79356b
A
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 }
55e303ae 768 IOLockUnlock( lock );
1c79356b
A
769
770 set->release();
771 tables->release();
772
773 return true;
774}
775
776// Return the generation count.
777SInt32 IOCatalogue::getGenerationCount( void ) const
778{
779 return( generation );
780}
781
782bool IOCatalogue::isModuleLoaded( OSString * moduleName ) const
783{
784 return isModuleLoaded(moduleName->getCStringNoCopy());
785}
786
787bool IOCatalogue::isModuleLoaded( const char * moduleName ) const
788{
55e303ae 789 return (kmod_load_request(moduleName, true));
1c79356b
A
790}
791
792// Check to see if module has been loaded already.
793bool IOCatalogue::isModuleLoaded( OSDictionary * driver ) const
794{
795 OSString * moduleName = NULL;
796
797 if ( !driver )
798 return false;
799
55e303ae 800 moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKey));
1c79356b
A
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.
811void IOCatalogue::moduleHasLoaded( OSString * moduleName )
812{
813 OSDictionary * dict;
814
815 dict = OSDictionary::withCapacity(2);
55e303ae 816 dict->setObject(gIOModuleIdentifierKey, moduleName);
1c79356b
A
817 startMatching(dict);
818 dict->release();
819}
820
821void IOCatalogue::moduleHasLoaded( const char * moduleName )
822{
823 OSString * name;
824
825 name = OSString::withCString(moduleName);
826 moduleHasLoaded(name);
827 name->release();
828}
829
830IOReturn IOCatalogue::unloadModule( OSString * moduleName ) const
831{
9bccf70c 832 kmod_info_t * k_info = 0;
1c79356b
A
833 kern_return_t ret;
834 const char * name;
835
836 ret = kIOReturnBadArgument;
837 if ( moduleName ) {
838 name = moduleName->getCStringNoCopy();
9bccf70c 839 k_info = kmod_lookupbyname_locked((char *)name);
1c79356b
A
840 if ( k_info && (k_info->reference_count < 1) ) {
841 if ( k_info->stop &&
9bccf70c
A
842 !((ret = k_info->stop(k_info, 0)) == kIOReturnSuccess) ) {
843
55e303ae 844 kfree((vm_offset_t) k_info, sizeof(kmod_info_t));
1c79356b 845 return ret;
9bccf70c 846 }
1c79356b
A
847
848 ret = kmod_destroy(host_priv_self(), k_info->id);
849 }
850 }
9bccf70c
A
851
852 if (k_info) {
55e303ae 853 kfree((vm_offset_t) k_info, sizeof(kmod_info_t));
9bccf70c 854 }
1c79356b
A
855
856 return ret;
857}
858
859static IOReturn _terminateDrivers( OSArray * array, OSDictionary * matching )
860{
861 OSCollectionIterator * tables;
1c79356b
A
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
1c79356b
A
880 // terminate instances.
881 do {
882 iter->reset();
883 while( (service = (IOService *)iter->getNextObject()) ) {
884 dict = service->getPropertyTable();
885 if ( !dict )
886 continue;
887
9bccf70c
A
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 */
1c79356b
A
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()) ) {
9bccf70c
A
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 */
1c79356b
A
926 if ( dict->isEqualTo(matching, matching) )
927 continue;
928
929 array->setObject(dict);
930 }
931
932 tables->release();
933
934 return ret;
935}
936
937IOReturn IOCatalogue::terminateDrivers( OSDictionary * matching )
938{
939 IOReturn ret;
940
941 ret = kIOReturnSuccess;
55e303ae 942 IOLockLock( lock );
1c79356b
A
943 ret = _terminateDrivers(array, matching);
944 kernelTables->reset();
55e303ae 945 IOLockUnlock( lock );
1c79356b
A
946
947 return ret;
948}
949
950IOReturn 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
55e303ae 961 dict->setObject(gIOModuleIdentifierKey, moduleName);
9bccf70c 962
55e303ae 963 IOLockLock( lock );
1c79356b
A
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
55e303ae 974 IOLockUnlock( lock );
1c79356b
A
975
976 dict->release();
977
978 return ret;
979}
980
981IOReturn 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();
9bccf70c 994
1c79356b
A
995 return ret;
996}
997
998bool 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
55e303ae 1011 IOLockLock( lock );
1c79356b
A
1012 kernelTables->reset();
1013
1014 while ( (dict = (OSDictionary *)kernelTables->getNextObject()) ) {
9bccf70c
A
1015
1016 /* This comparison must be done with only the keys in the
1017 * "matching" dict to enable general matching.
1018 */
1c79356b
A
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
55e303ae 1028 IOLockUnlock( lock );
1c79356b
A
1029
1030 set->release();
1031
1032 return true;
1033}
1034
1035void IOCatalogue::reset(void)
1036{
1c79356b 1037 IOLog("Resetting IOCatalogue.\n");
1c79356b
A
1038}
1039
1040bool IOCatalogue::serialize(OSSerialize * s) const
1041{
55e303ae 1042 bool ret;
1c79356b
A
1043
1044 if ( !s )
1045 return false;
1046
55e303ae
A
1047 IOLockLock( lock );
1048
1c79356b 1049 ret = array->serialize(s);
55e303ae
A
1050
1051 IOLockUnlock( lock );
1c79356b
A
1052
1053 return ret;
1054}
1055
55e303ae
A
1056bool 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
1c79356b
A
1106
1107bool IOCatalogue::recordStartupExtensions(void) {
1108 bool result = false;
1109
0b4e3aa0
A
1110 IOLockLock(kld_lock);
1111 if (kernelLinkerPresent && record_startup_extensions_function) {
1c79356b
A
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 }
0b4e3aa0 1118 IOLockUnlock(kld_lock);
1c79356b
A
1119
1120 return result;
1121}
1122
1123
1124/*********************************************************************
1125*********************************************************************/
55e303ae
A
1126bool IOCatalogue::addExtensionsFromArchive(OSData * mkext)
1127{
1128 OSData * copyData;
1c79356b 1129 bool result = false;
55e303ae 1130 bool prelinked;
1c79356b 1131
55e303ae
A
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();
1c79356b
A
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*********************************************************************/
1173kern_return_t IOCatalogue::removeKernelLinker(void) {
1174 kern_return_t result = KERN_SUCCESS;
1c79356b
A
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 */
0b4e3aa0 1182 IOLockLock(kld_lock);
1c79356b
A
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 */
55e303ae 1212 segment = getsegbyname("__KLD");
1c79356b 1213 if (!segment) {
55e303ae
A
1214 IOLog("error removing kernel linker: can't find %s segment\n",
1215 "__KLD");
1c79356b
A
1216 result = KERN_FAILURE;
1217 goto finish;
1218 }
1219 OSRuntimeUnloadCPPForSegment(segment);
1220
55e303ae 1221 segment = getsegbyname("__LINKEDIT");
1c79356b 1222 if (!segment) {
55e303ae
A
1223 IOLog("error removing kernel linker: can't find %s segment\n",
1224 "__LINKEDIT");
1c79356b
A
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
55e303ae
A
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 }
1c79356b
A
1255
1256finish:
1257
1258 /* This must be the very last thing done before returning.
1259 */
0b4e3aa0 1260 IOLockUnlock(kld_lock);
1c79356b
A
1261
1262 return result;
1263}