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