]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOCatalogue.cpp
xnu-792.18.15.tar.gz
[apple/xnu.git] / iokit / Kernel / IOCatalogue.cpp
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
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
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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>
40extern "C" {
41#include <machine/machine_routines.h>
42#include <mach/kmod.h>
43#include <mach-o/mach_header.h>
9bccf70c 44#include <kern/host.h>
1c79356b
A
45};
46
47#include <IOKit/IOLib.h>
48
49#include <IOKit/assert.h>
50
51
52extern "C" {
53int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize );
54extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize );
91447636
A
55/* operates on 32 bit segments */
56extern void OSRuntimeUnloadCPPForSegment(struct segment_command * segment);
1c79356b
A
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 */
68extern "C" {
69kern_return_t (*kmod_load_function)(char *extension_name) =
70 &kmod_load_extension;
71bool (*record_startup_extensions_function)(void) = 0;
72bool (*add_from_mkext_function)(OSData * mkext) = 0;
73void (*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 */
82int kernelLinkerPresent = 0;
83
1c79356b
A
84#define kModuleKey "CFBundleIdentifier"
85
55e303ae 86#define super OSObject
1c79356b
A
87OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
88
89#define CATALOGTEST 0
90
55e303ae
A
91IOCatalogue * gIOCatalogue;
92const OSSymbol * gIOClassKey;
93const OSSymbol * gIOProbeScoreKey;
94const OSSymbol * gIOModuleIdentifierKey;
95OSSet * gIOCatalogModuleRequests;
96OSSet * gIOCatalogCacheMisses;
97OSSet * gIOCatalogROMMkexts;
98IOLock * gIOCatalogLock;
99IOLock * gIOKLDLock;
100
101/*********************************************************************
102*********************************************************************/
103
104OSArray * gIOPrelinkedModules = 0;
105
106extern "C" kern_return_t
107kmod_create_internal(
108 kmod_info_t *info,
109 kmod_t *id);
110
111extern "C" kern_return_t
112kmod_destroy_internal(kmod_t id);
113
114extern "C" kern_return_t
115kmod_start_or_stop(
116 kmod_t id,
117 int start,
118 kmod_args_t *data,
119 mach_msg_type_number_t *dataCount);
120
121extern "C" kern_return_t kmod_retain(kmod_t id);
122extern "C" kern_return_t kmod_release(kmod_t id);
123
124static
125kern_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));
91447636 211 kfree(depInfo, sizeof(kmod_info_t));
55e303ae
A
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
230static
231kern_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
264extern "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) {
91447636 284 kfree(kmod_info, sizeof(kmod_info_t));
55e303ae
A
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);
91447636 304 ret = true;
55e303ae
A
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
350extern "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
388extern "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*********************************************************************/
1c79356b
A
406
407static 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
428void 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
55e303ae
A
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);
1c79356b
A
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.
461bool IOCatalogue::init(OSArray * initArray)
462{
1c79356b
A
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
55e303ae
A
474 gIOCatalogLock = IOLockAlloc();
475 gIOKLDLock = IOLockAlloc();
476
477 lock = gIOCatalogLock;
478 kld_lock = gIOKLDLock;
1c79356b
A
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
1c79356b
A
494 return true;
495}
496
497// Release all resources used by IOCatalogue and deallocate.
498// This will probably never be called.
499void 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
512static int hackLimit;
513
514enum { kDriversPerIter = 4 };
515
516void 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
55e303ae 525 IOLockLock( &self->lock );
1c79356b
A
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
55e303ae 547 IOLockUnlock( &self->lock );
1c79356b
A
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
557OSOrderedSet * 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
55e303ae 569 IOLockLock( lock );
1c79356b
A
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
55e303ae 588 IOLockUnlock( lock );
1c79356b
A
589
590 return( set );
591}
592
593// Is personality already in the catalog?
594OSOrderedSet * 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
55e303ae 605 IOLockLock( lock );
1c79356b
A
606 kernelTables->reset();
607 while ( (dict = (OSDictionary *) kernelTables->getNextObject()) ) {
9bccf70c
A
608
609 /* This comparison must be done with only the keys in the
610 * "matching" dict to enable general searches.
611 */
1c79356b
A
612 if ( dict->isEqualTo(matching, matching) )
613 set->setObject(dict);
614 }
615 *generationCount = getGenerationCount();
55e303ae 616 IOLockUnlock( lock );
1c79356b
A
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
625static void AddNewImports( OSOrderedSet * set, OSDictionary * dict )
626{
627 set->setObject(dict);
628}
629
630// Add driver config tables to catalog and start matching process.
631bool IOCatalogue::addDrivers(OSArray * drivers,
55e303ae 632 bool doNubMatching )
1c79356b
A
633{
634 OSCollectionIterator * iter;
635 OSDictionary * dict;
636 OSOrderedSet * set;
637 OSArray * persons;
55e303ae 638 OSString * moduleName;
1c79356b
A
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
55e303ae
A
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 }
1c79356b
A
700 }
701 // Start device matching.
55e303ae 702 if (doNubMatching && (set->getCount() > 0)) {
1c79356b
A
703 IOService::catalogNewDrivers( set );
704 generation++;
705 }
55e303ae 706 IOLockUnlock( lock );
1c79356b 707
1c79356b
A
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.
716bool IOCatalogue::removeDrivers( OSDictionary * matching,
55e303ae 717 bool doNubMatching)
1c79356b
A
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
55e303ae 748 IOLockLock( lock );
1c79356b
A
749 kernelTables->reset();
750 arrayCopy->merge(array);
751 array->flushCollection();
752 tables->reset();
753 while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
9bccf70c
A
754
755 /* This comparison must be done with only the keys in the
756 * "matching" dict to enable general searches.
757 */
1c79356b
A
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 }
55e303ae 770 IOLockUnlock( lock );
1c79356b
A
771
772 set->release();
773 tables->release();
774
775 return true;
776}
777
778// Return the generation count.
779SInt32 IOCatalogue::getGenerationCount( void ) const
780{
781 return( generation );
782}
783
784bool IOCatalogue::isModuleLoaded( OSString * moduleName ) const
785{
786 return isModuleLoaded(moduleName->getCStringNoCopy());
787}
788
789bool IOCatalogue::isModuleLoaded( const char * moduleName ) const
790{
55e303ae 791 return (kmod_load_request(moduleName, true));
1c79356b
A
792}
793
794// Check to see if module has been loaded already.
795bool IOCatalogue::isModuleLoaded( OSDictionary * driver ) const
796{
797 OSString * moduleName = NULL;
798
799 if ( !driver )
800 return false;
801
55e303ae 802 moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKey));
1c79356b
A
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.
813void IOCatalogue::moduleHasLoaded( OSString * moduleName )
814{
815 OSDictionary * dict;
816
817 dict = OSDictionary::withCapacity(2);
55e303ae 818 dict->setObject(gIOModuleIdentifierKey, moduleName);
1c79356b
A
819 startMatching(dict);
820 dict->release();
821}
822
823void IOCatalogue::moduleHasLoaded( const char * moduleName )
824{
825 OSString * name;
826
827 name = OSString::withCString(moduleName);
828 moduleHasLoaded(name);
829 name->release();
830}
831
832IOReturn IOCatalogue::unloadModule( OSString * moduleName ) const
833{
9bccf70c 834 kmod_info_t * k_info = 0;
1c79356b
A
835 kern_return_t ret;
836 const char * name;
837
838 ret = kIOReturnBadArgument;
839 if ( moduleName ) {
840 name = moduleName->getCStringNoCopy();
9bccf70c 841 k_info = kmod_lookupbyname_locked((char *)name);
1c79356b
A
842 if ( k_info && (k_info->reference_count < 1) ) {
843 if ( k_info->stop &&
9bccf70c
A
844 !((ret = k_info->stop(k_info, 0)) == kIOReturnSuccess) ) {
845
91447636 846 kfree(k_info, sizeof(kmod_info_t));
1c79356b 847 return ret;
9bccf70c 848 }
1c79356b
A
849
850 ret = kmod_destroy(host_priv_self(), k_info->id);
851 }
852 }
9bccf70c
A
853
854 if (k_info) {
91447636 855 kfree(k_info, sizeof(kmod_info_t));
9bccf70c 856 }
1c79356b
A
857
858 return ret;
859}
860
91447636 861static IOReturn _terminateDrivers( OSDictionary * matching )
1c79356b 862{
1c79356b
A
863 OSDictionary * dict;
864 OSIterator * iter;
1c79356b
A
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
91447636
A
903 return ret;
904}
905
906static IOReturn _removeDrivers( OSArray * array, OSDictionary * matching )
907{
908 OSCollectionIterator * tables;
909 OSDictionary * dict;
910 OSArray * arrayCopy;
911 IOReturn ret = kIOReturnSuccess;
912
1c79356b 913 // remove configs from catalog.
1c79356b
A
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()) ) {
9bccf70c
A
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 */
1c79356b
A
934 if ( dict->isEqualTo(matching, matching) )
935 continue;
936
937 array->setObject(dict);
938 }
939
940 tables->release();
941
942 return ret;
943}
944
945IOReturn IOCatalogue::terminateDrivers( OSDictionary * matching )
946{
947 IOReturn ret;
948
91447636 949 ret = _terminateDrivers(matching);
55e303ae 950 IOLockLock( lock );
91447636
A
951 if (kIOReturnSuccess == ret)
952 ret = _removeDrivers(array, matching);
1c79356b 953 kernelTables->reset();
55e303ae 954 IOLockUnlock( lock );
1c79356b
A
955
956 return ret;
957}
958
959IOReturn 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
55e303ae 970 dict->setObject(gIOModuleIdentifierKey, moduleName);
9bccf70c 971
91447636 972 ret = _terminateDrivers(dict);
55e303ae 973 IOLockLock( lock );
91447636
A
974 if (kIOReturnSuccess == ret)
975 ret = _removeDrivers(array, dict);
1c79356b
A
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
55e303ae 984 IOLockUnlock( lock );
1c79356b
A
985
986 dict->release();
987
988 return ret;
989}
990
991IOReturn 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();
9bccf70c 1004
1c79356b
A
1005 return ret;
1006}
1007
1008bool 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
55e303ae 1021 IOLockLock( lock );
1c79356b
A
1022 kernelTables->reset();
1023
1024 while ( (dict = (OSDictionary *)kernelTables->getNextObject()) ) {
9bccf70c
A
1025
1026 /* This comparison must be done with only the keys in the
1027 * "matching" dict to enable general matching.
1028 */
1c79356b
A
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
55e303ae 1038 IOLockUnlock( lock );
1c79356b
A
1039
1040 set->release();
1041
1042 return true;
1043}
1044
1045void IOCatalogue::reset(void)
1046{
1c79356b 1047 IOLog("Resetting IOCatalogue.\n");
1c79356b
A
1048}
1049
1050bool IOCatalogue::serialize(OSSerialize * s) const
1051{
1c79356b
A
1052 if ( !s )
1053 return false;
1054
91447636 1055 return super::serialize(s);
1c79356b
A
1056}
1057
55e303ae
A
1058bool 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
1c79356b
A
1108
1109bool IOCatalogue::recordStartupExtensions(void) {
1110 bool result = false;
1111
0b4e3aa0
A
1112 IOLockLock(kld_lock);
1113 if (kernelLinkerPresent && record_startup_extensions_function) {
1c79356b
A
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 }
0b4e3aa0 1120 IOLockUnlock(kld_lock);
1c79356b
A
1121
1122 return result;
1123}
1124
1125
1126/*********************************************************************
91447636
A
1127* This function operates on sections retrieved from the currently running
1128* 32 bit mach kernel.
1c79356b 1129*********************************************************************/
55e303ae
A
1130bool IOCatalogue::addExtensionsFromArchive(OSData * mkext)
1131{
1132 OSData * copyData;
1c79356b 1133 bool result = false;
55e303ae 1134 bool prelinked;
1c79356b 1135
55e303ae
A
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();
1c79356b
A
1166 }
1167
1168 return result;
1169}
1170
1c79356b
A
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.
91447636
A
1175*
1176* The segments it operates on are strictly 32 bit segments.
1c79356b
A
1177*********************************************************************/
1178kern_return_t IOCatalogue::removeKernelLinker(void) {
1179 kern_return_t result = KERN_SUCCESS;
89b3af67
A
1180 struct segment_command * segmentLE, *segmentKLD;
1181 boolean_t keepsyms = FALSE;
1182#if __ppc__
1c79356b
A
1183 char * dt_segment_name;
1184 void * segment_paddress;
1185 int segment_size;
89b3af67 1186#endif
1c79356b
A
1187
1188 /* This must be the very first thing done by this function.
1189 */
0b4e3aa0 1190 IOLockLock(kld_lock);
1c79356b
A
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
89b3af67
A
1201 PE_parse_boot_arg("keepsyms", &keepsyms);
1202
1c79356b
A
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 */
89b3af67
A
1222 segmentKLD = getsegbyname("__KLD");
1223 if (!segmentKLD) {
55e303ae
A
1224 IOLog("error removing kernel linker: can't find %s segment\n",
1225 "__KLD");
1c79356b
A
1226 result = KERN_FAILURE;
1227 goto finish;
1228 }
89b3af67 1229 OSRuntimeUnloadCPPForSegment(segmentKLD);
1c79356b 1230
89b3af67
A
1231 segmentLE = getsegbyname("__LINKEDIT");
1232 if (!segmentLE) {
55e303ae
A
1233 IOLog("error removing kernel linker: can't find %s segment\n",
1234 "__LINKEDIT");
1c79356b
A
1235 result = KERN_FAILURE;
1236 goto finish;
1237 }
89b3af67
A
1238 OSRuntimeUnloadCPPForSegment(segmentLE);
1239#if __ppc__
1c79356b
A
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 }
89b3af67
A
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__
1c79356b
A
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 }
89b3af67
A
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
1c79356b 1270
55e303ae
A
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 }
1c79356b
A
1281
1282finish:
1283
1284 /* This must be the very last thing done before returning.
1285 */
0b4e3aa0 1286 IOLockUnlock(kld_lock);
1c79356b
A
1287
1288 return result;
1289}
91447636
A
1290
1291/*********************************************************************
1292* This function stops the catalogue from making kextd requests during
1293* shutdown.
1294*********************************************************************/
1295void 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