]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOCatalogue.cpp
xnu-1504.9.17.tar.gz
[apple/xnu.git] / iokit / Kernel / IOCatalogue.cpp
1 /*
2 * Copyright (c) 1998-2006 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1998 Apple Inc. All rights reserved.
30 *
31 * HISTORY
32 *
33 */
34 /*
35 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
36 * support for mandatory and extensible security protections. This notice
37 * is included in support of clause 2.2 (b) of the Apple Public License,
38 * Version 2.0.
39 */
40
41 extern "C" {
42 #include <machine/machine_routines.h>
43 #include <libkern/kernel_mach_header.h>
44 #include <kern/host.h>
45 #include <security/mac_data.h>
46 };
47
48 #include <libkern/c++/OSContainers.h>
49 #include <libkern/c++/OSUnserialize.h>
50 #include <libkern/c++/OSKext.h>
51 #include <libkern/OSKextLibPrivate.h>
52
53 #include <IOKit/IODeviceTreeSupport.h>
54 #include <IOKit/IOService.h>
55 #include <IOKit/IOCatalogue.h>
56
57 #include <IOKit/IOLib.h>
58 #include <IOKit/assert.h>
59
60 #if PRAGMA_MARK
61 #pragma mark Internal Declarations
62 #endif
63 /*********************************************************************
64 *********************************************************************/
65
66 #define CATALOGTEST 0
67
68 IOCatalogue * gIOCatalogue;
69 const OSSymbol * gIOClassKey;
70 const OSSymbol * gIOProbeScoreKey;
71 const OSSymbol * gIOModuleIdentifierKey;
72 IOLock * gIOCatalogLock;
73
74 #if PRAGMA_MARK
75 #pragma mark Utility functions
76 #endif
77 /*********************************************************************
78 *********************************************************************/
79 static void
80 UniqueProperties(OSDictionary * dict)
81 {
82 OSString * data;
83
84 data = OSDynamicCast(OSString, dict->getObject(gIOClassKey));
85 if (data) {
86 const OSSymbol *classSymbol = OSSymbol::withString(data);
87
88 dict->setObject( gIOClassKey, (OSSymbol *) classSymbol);
89 classSymbol->release();
90 }
91
92 data = OSDynamicCast(OSString, dict->getObject(gIOMatchCategoryKey));
93 if (data) {
94 const OSSymbol *classSymbol = OSSymbol::withString(data);
95
96 dict->setObject(gIOMatchCategoryKey, (OSSymbol *) classSymbol);
97 classSymbol->release();
98 }
99 return;
100 }
101
102 /*********************************************************************
103 * Add a new personality to the set if it has a unique IOResourceMatchKey value.
104 * XXX -- svail: This should be optimized.
105 * esb - There doesn't seem like any reason to do this - it causes problems
106 * esb - when there are more than one loadable driver matching on the same provider class
107 *********************************************************************/
108 static void
109 AddNewImports(OSOrderedSet * set, OSDictionary * dict)
110 {
111 set->setObject(dict);
112 }
113
114 #if PRAGMA_MARK
115 #pragma mark IOCatalogue class implementation
116 #endif
117 /*********************************************************************
118 *********************************************************************/
119
120 #define super OSObject
121 OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
122
123 /*********************************************************************
124 *********************************************************************/
125 void IOCatalogue::initialize(void)
126 {
127 OSArray * array;
128 OSString * errorString;
129 bool rc;
130
131 extern const char * gIOKernelConfigTables;
132
133 array = OSDynamicCast(OSArray, OSUnserialize(gIOKernelConfigTables, &errorString));
134 if (!array && errorString) {
135 IOLog("KernelConfigTables syntax error: %s\n",
136 errorString->getCStringNoCopy());
137 errorString->release();
138 }
139
140 gIOClassKey = OSSymbol::withCStringNoCopy( kIOClassKey );
141 gIOProbeScoreKey = OSSymbol::withCStringNoCopy( kIOProbeScoreKey );
142 gIOModuleIdentifierKey = OSSymbol::withCStringNoCopy( kCFBundleIdentifierKey );
143
144 assert( array && gIOClassKey && gIOProbeScoreKey
145 && gIOModuleIdentifierKey);
146
147 gIOCatalogue = new IOCatalogue;
148 assert(gIOCatalogue);
149 rc = gIOCatalogue->init(array);
150 assert(rc);
151 array->release();
152 }
153
154 /*********************************************************************
155 * Initialize the IOCatalog object.
156 *********************************************************************/
157 bool IOCatalogue::init(OSArray * initArray)
158 {
159 OSDictionary * dict;
160
161 if ( !super::init() )
162 return false;
163
164 generation = 1;
165
166 array = initArray;
167 array->retain();
168 kernelTables = OSCollectionIterator::withCollection( array );
169
170 gIOCatalogLock = IOLockAlloc();
171
172 lock = gIOCatalogLock;
173 #if __ppc__ || __i386__
174 kld_lock = NULL;
175 #endif /* __ppc__ || __i386__ */
176
177 kernelTables->reset();
178 while( (dict = (OSDictionary *) kernelTables->getNextObject())) {
179 UniqueProperties(dict);
180 if( 0 == dict->getObject( gIOClassKey ))
181 IOLog("Missing or bad \"%s\" key\n",
182 gIOClassKey->getCStringNoCopy());
183 }
184
185 #if CATALOGTEST
186 AbsoluteTime deadline;
187 clock_interval_to_deadline( 1000, kMillisecondScale );
188 thread_call_func_delayed( ping, this, deadline );
189 #endif
190
191 return true;
192 }
193
194 /*********************************************************************
195 * Release all resources used by IOCatalogue and deallocate.
196 * This will probably never be called.
197 *********************************************************************/
198 void IOCatalogue::free( void )
199 {
200 if ( array )
201 array->release();
202
203 if ( kernelTables )
204 kernelTables->release();
205
206 super::free();
207 }
208
209 /*********************************************************************
210 *********************************************************************/
211 #if CATALOGTEST
212
213 static int hackLimit;
214 enum { kDriversPerIter = 4 };
215
216 void
217 IOCatalogue::ping(thread_call_param_t arg, thread_call_param_t)
218 {
219 IOCatalogue * self = (IOCatalogue *) arg;
220 OSOrderedSet * set;
221 OSDictionary * table;
222 int newLimit;
223
224 set = OSOrderedSet::withCapacity( 1 );
225
226 IOLockLock( &self->lock );
227
228 for( newLimit = 0; newLimit < kDriversPerIter; newLimit++) {
229 table = (OSDictionary *) self->array->getObject(
230 hackLimit + newLimit );
231 if( table) {
232 set->setLastObject( table );
233
234 OSSymbol * sym = (OSSymbol *) table->getObject(gIOClassKey);
235 kprintf("enabling %s\n", sym->getCStringNoCopy());
236
237 } else {
238 newLimit--;
239 break;
240 }
241 }
242
243 IOService::catalogNewDrivers( set );
244
245 hackLimit += newLimit;
246 self->generation++;
247
248 IOLockUnlock( &self->lock );
249
250 if( kDriversPerIter == newLimit) {
251 AbsoluteTime deadline;
252 clock_interval_to_deadline(500, kMillisecondScale);
253 thread_call_func_delayed(ping, this, deadline);
254 }
255 }
256 #endif
257
258 /*********************************************************************
259 *********************************************************************/
260 OSOrderedSet *
261 IOCatalogue::findDrivers(
262 IOService * service,
263 SInt32 * generationCount)
264 {
265 OSDictionary * nextTable;
266 OSOrderedSet * set;
267 OSString * imports;
268
269 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
270 (void *)gIOProbeScoreKey );
271 if( !set )
272 return( 0 );
273
274 IOLockLock(lock);
275 kernelTables->reset();
276
277 #if CATALOGTEST
278 int hackIndex = 0;
279 #endif
280 while( (nextTable = (OSDictionary *) kernelTables->getNextObject())) {
281 #if CATALOGTEST
282 if( hackIndex++ > hackLimit)
283 break;
284 #endif
285 imports = OSDynamicCast( OSString,
286 nextTable->getObject( gIOProviderClassKey ));
287 if( imports && service->metaCast( imports ))
288 set->setObject( nextTable );
289 }
290
291 *generationCount = getGenerationCount();
292
293 IOLockUnlock(lock);
294
295 return( set );
296 }
297
298 /*********************************************************************
299 * Is personality already in the catalog?
300 *********************************************************************/
301 OSOrderedSet *
302 IOCatalogue::findDrivers(
303 OSDictionary * matching,
304 SInt32 * generationCount)
305 {
306 OSDictionary * dict;
307 OSOrderedSet * set;
308
309 UniqueProperties(matching);
310
311 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
312 (void *)gIOProbeScoreKey );
313
314 IOLockLock(lock);
315 kernelTables->reset();
316 while ( (dict = (OSDictionary *) kernelTables->getNextObject()) ) {
317
318 /* This comparison must be done with only the keys in the
319 * "matching" dict to enable general searches.
320 */
321 if ( dict->isEqualTo(matching, matching) )
322 set->setObject(dict);
323 }
324 *generationCount = getGenerationCount();
325 IOLockUnlock(lock);
326
327 return set;
328 }
329
330 /*********************************************************************
331 * Add driver config tables to catalog and start matching process.
332 *
333 * Important that existing personalities are kept (not replaced)
334 * if duplicates found. Personalities can come from OSKext objects
335 * or from userland kext library. We want to minimize distinct
336 * copies between OSKext & IOCatalogue.
337 *
338 * xxx - userlib used to refuse to send personalities with IOKitDebug
339 * xxx - during safe boot. That would be better implemented here.
340 *********************************************************************/
341 bool IOCatalogue::addDrivers(
342 OSArray * drivers,
343 bool doNubMatching)
344 {
345 bool result = false;
346 OSCollectionIterator * iter = NULL; // must release
347 OSOrderedSet * set = NULL; // must release
348 OSDictionary * dict = NULL; // do not release
349 OSArray * persons = NULL; // do not release
350
351 persons = OSDynamicCast(OSArray, drivers);
352 if (!persons) {
353 goto finish;
354 }
355
356 set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
357 (void *)gIOProbeScoreKey );
358 if (!set) {
359 goto finish;
360 }
361
362 iter = OSCollectionIterator::withCollection(persons);
363 if (!iter) {
364 goto finish;
365 }
366
367 result = true;
368
369 IOLockLock(lock);
370 while ( (dict = (OSDictionary *) iter->getNextObject()) ) {
371
372 // xxx Deleted OSBundleModuleDemand check; will handle in other ways for SL
373
374 SInt count;
375
376 UniqueProperties(dict);
377
378 // Add driver personality to catalogue.
379 count = array->getCount();
380 while (count--) {
381 OSDictionary * driver;
382
383 // Be sure not to double up on personalities.
384 driver = (OSDictionary *)array->getObject(count);
385
386 /* Unlike in other functions, this comparison must be exact!
387 * The catalogue must be able to contain personalities that
388 * are proper supersets of others.
389 * Do not compare just the properties present in one driver
390 * pesonality or the other.
391 */
392 if (dict->isEqualTo(driver)) {
393 break;
394 }
395 }
396 if (count >= 0) {
397 // its a dup
398 continue;
399 }
400
401 result = array->setObject(dict);
402 if (!result) {
403 break;
404 }
405
406 AddNewImports(set, dict);
407 }
408 // Start device matching.
409 if (doNubMatching && (set->getCount() > 0)) {
410 IOService::catalogNewDrivers(set);
411 generation++;
412 }
413 IOLockUnlock(lock);
414
415 finish:
416 if (set) set->release();
417 if (iter) iter->release();
418
419 return result;
420 }
421
422 /*********************************************************************
423 * Remove drivers from the catalog which match the
424 * properties in the matching dictionary.
425 *********************************************************************/
426 bool
427 IOCatalogue::removeDrivers(
428 OSDictionary * matching,
429 bool doNubMatching)
430 {
431 OSCollectionIterator * tables;
432 OSDictionary * dict;
433 OSOrderedSet * set;
434 OSArray * arrayCopy;
435
436 if ( !matching )
437 return false;
438
439 set = OSOrderedSet::withCapacity(10,
440 IOServiceOrdering,
441 (void *)gIOProbeScoreKey);
442 if ( !set )
443 return false;
444
445 arrayCopy = OSArray::withCapacity(100);
446 if ( !arrayCopy ) {
447 set->release();
448 return false;
449 }
450
451 tables = OSCollectionIterator::withCollection(arrayCopy);
452 arrayCopy->release();
453 if ( !tables ) {
454 set->release();
455 return false;
456 }
457
458 UniqueProperties( matching );
459
460 IOLockLock(lock);
461 kernelTables->reset();
462 arrayCopy->merge(array);
463 array->flushCollection();
464 tables->reset();
465 while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
466
467 /* This comparison must be done with only the keys in the
468 * "matching" dict to enable general searches.
469 */
470 if ( dict->isEqualTo(matching, matching) ) {
471 AddNewImports( set, dict );
472 continue;
473 }
474
475 array->setObject(dict);
476 }
477 // Start device matching.
478 if ( doNubMatching && (set->getCount() > 0) ) {
479 IOService::catalogNewDrivers(set);
480 generation++;
481 }
482 IOLockUnlock(lock);
483
484 set->release();
485 tables->release();
486
487 return true;
488 }
489
490 // Return the generation count.
491 SInt32 IOCatalogue::getGenerationCount(void) const
492 {
493 return( generation );
494 }
495
496 bool IOCatalogue::isModuleLoaded(OSString * moduleName) const
497 {
498 return isModuleLoaded(moduleName->getCStringNoCopy());
499 }
500
501 bool IOCatalogue::isModuleLoaded(const char * moduleName) const
502 {
503 OSReturn ret;
504 ret = OSKext::loadKextWithIdentifier(moduleName);
505 if (kOSKextReturnDeferred == ret) {
506 // a request has been queued but the module isn't necessarily
507 // loaded yet, so stall.
508 return false;
509 }
510 // module is present or never will be
511 return true;
512 }
513
514 // Check to see if module has been loaded already.
515 bool IOCatalogue::isModuleLoaded(OSDictionary * driver) const
516 {
517 OSString * moduleName = NULL;
518 OSString * publisherName = NULL;
519
520 if ( !driver )
521 return false;
522
523 /* The personalities of codeless kexts often contain the bundle ID of the
524 * kext they reference, and not the bundle ID of the codeless kext itself.
525 * The prelinked kernel needs to know the bundle ID of the codeless kext
526 * so it can include these personalities, so OSKext stores that bundle ID
527 * in the IOPersonalityPublisher key, and we record it as requested here.
528 */
529 publisherName = OSDynamicCast(OSString,
530 driver->getObject(kIOPersonalityPublisherKey));
531 OSKext::recordIdentifierRequest(publisherName);
532
533 moduleName = OSDynamicCast(OSString, driver->getObject(gIOModuleIdentifierKey));
534 if ( moduleName )
535 return isModuleLoaded(moduleName);
536
537 /* If a personality doesn't hold the "CFBundleIdentifier" key
538 * it is assumed to be an "in-kernel" driver.
539 */
540 return true;
541 }
542
543 /* This function is called after a module has been loaded.
544 * Is invoked from user client call, ultimately from IOKitLib's
545 * IOCatalogueModuleLoaded(). Sent from kextd.
546 */
547 void IOCatalogue::moduleHasLoaded(OSString * moduleName)
548 {
549 OSDictionary * dict;
550
551 dict = OSDictionary::withCapacity(2);
552 dict->setObject(gIOModuleIdentifierKey, moduleName);
553 startMatching(dict);
554 dict->release();
555
556 (void) OSKext::setDeferredLoadSucceeded();
557 (void) OSKext::considerRebuildOfPrelinkedKernel();
558 }
559
560 void IOCatalogue::moduleHasLoaded(const char * moduleName)
561 {
562 OSString * name;
563
564 name = OSString::withCString(moduleName);
565 moduleHasLoaded(name);
566 name->release();
567 }
568
569 // xxx - return is really OSReturn/kern_return_t
570 IOReturn IOCatalogue::unloadModule(OSString * moduleName) const
571 {
572 return OSKext::removeKextWithIdentifier(moduleName->getCStringNoCopy());
573 }
574
575 static IOReturn _terminateDrivers(OSDictionary * matching)
576 {
577 OSDictionary * dict;
578 OSIterator * iter;
579 IOService * service;
580 IOReturn ret;
581
582 if ( !matching )
583 return kIOReturnBadArgument;
584
585 ret = kIOReturnSuccess;
586 dict = 0;
587 iter = IORegistryIterator::iterateOver(gIOServicePlane,
588 kIORegistryIterateRecursively);
589 if ( !iter )
590 return kIOReturnNoMemory;
591
592 UniqueProperties( matching );
593
594 // terminate instances.
595 do {
596 iter->reset();
597 while( (service = (IOService *)iter->getNextObject()) ) {
598 dict = service->getPropertyTable();
599 if ( !dict )
600 continue;
601
602 /* Terminate only for personalities that match the matching dictionary.
603 * This comparison must be done with only the keys in the
604 * "matching" dict to enable general matching.
605 */
606 if ( !dict->isEqualTo(matching, matching) )
607 continue;
608
609 if ( !service->terminate(kIOServiceRequired|kIOServiceSynchronous) ) {
610 ret = kIOReturnUnsupported;
611 break;
612 }
613 }
614 } while( !service && !iter->isValid());
615 iter->release();
616
617 return ret;
618 }
619
620 static IOReturn _removeDrivers( OSArray * array, OSDictionary * matching )
621 {
622 OSCollectionIterator * tables;
623 OSDictionary * dict;
624 OSArray * arrayCopy;
625 IOReturn ret = kIOReturnSuccess;
626
627 // remove configs from catalog.
628
629 arrayCopy = OSArray::withCapacity(100);
630 if ( !arrayCopy )
631 return kIOReturnNoMemory;
632
633 tables = OSCollectionIterator::withCollection(arrayCopy);
634 arrayCopy->release();
635 if ( !tables )
636 return kIOReturnNoMemory;
637
638 arrayCopy->merge(array);
639 array->flushCollection();
640 tables->reset();
641 while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
642
643 /* Remove from the catalogue's array any personalities
644 * that match the matching dictionary.
645 * This comparison must be done with only the keys in the
646 * "matching" dict to enable general matching.
647 */
648 if ( dict->isEqualTo(matching, matching) )
649 continue;
650
651 array->setObject(dict);
652 }
653
654 tables->release();
655
656 return ret;
657 }
658
659 IOReturn IOCatalogue::terminateDrivers(OSDictionary * matching)
660 {
661 IOReturn ret;
662
663 ret = _terminateDrivers(matching);
664 IOLockLock(lock);
665 if (kIOReturnSuccess == ret)
666 ret = _removeDrivers(array, matching);
667 kernelTables->reset();
668 IOLockUnlock(lock);
669
670 return ret;
671 }
672
673 IOReturn IOCatalogue::terminateDriversForModule(
674 OSString * moduleName,
675 bool unload)
676 {
677 IOReturn ret;
678 OSDictionary * dict;
679 bool isLoaded = false;
680
681 /* Check first if the kext currently has any linkage dependents;
682 * in such a case the unload would fail so let's not terminate any
683 * IOServices (since doing so typically results in a panic when there
684 * are loaded dependencies). Note that we aren't locking the kext here
685 * so it might lose or gain dependents by the time we call unloadModule();
686 * I think that's ok, our unload can fail if a kext comes in on top of
687 * this one even after we've torn down IOService objects. Conversely,
688 * if we fail the unload here and then lose a library, the autounload
689 * thread will get us in short order.
690 */
691 if (OSKext::isKextWithIdentifierLoaded(moduleName->getCStringNoCopy())) {
692
693 isLoaded = true;
694
695 if (!OSKext::canUnloadKextWithIdentifier(moduleName,
696 /* checkClasses */ false)) {
697 ret = kOSKextReturnInUse;
698 goto finish;
699 }
700 }
701 dict = OSDictionary::withCapacity(1);
702 if (!dict) {
703 ret = kIOReturnNoMemory;
704 goto finish;
705 }
706
707 dict->setObject(gIOModuleIdentifierKey, moduleName);
708
709 ret = _terminateDrivers(dict);
710
711 /* No goto between IOLock calls!
712 */
713 IOLockLock(lock);
714 if (kIOReturnSuccess == ret) {
715 ret = _removeDrivers(array, dict);
716 }
717 kernelTables->reset();
718
719 // Unload the module itself.
720 if (unload && isLoaded && ret == kIOReturnSuccess) {
721 ret = unloadModule(moduleName);
722 }
723
724 IOLockUnlock(lock);
725
726 dict->release();
727
728 finish:
729 return ret;
730 }
731
732 IOReturn IOCatalogue::terminateDriversForModule(
733 const char * moduleName,
734 bool unload)
735 {
736 OSString * name;
737 IOReturn ret;
738
739 name = OSString::withCString(moduleName);
740 if ( !name )
741 return kIOReturnNoMemory;
742
743 ret = terminateDriversForModule(name, unload);
744 name->release();
745
746 return ret;
747 }
748
749 bool IOCatalogue::startMatching( OSDictionary * matching )
750 {
751 OSDictionary * dict;
752 OSOrderedSet * set;
753
754 if ( !matching )
755 return false;
756
757 set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
758 (void *)gIOProbeScoreKey);
759 if ( !set )
760 return false;
761
762 IOLockLock(lock);
763 kernelTables->reset();
764
765 while ( (dict = (OSDictionary *)kernelTables->getNextObject()) ) {
766
767 /* This comparison must be done with only the keys in the
768 * "matching" dict to enable general matching.
769 */
770 if ( dict->isEqualTo(matching, matching) )
771 AddNewImports(set, dict);
772 }
773 // Start device matching.
774 if ( set->getCount() > 0 ) {
775 IOService::catalogNewDrivers(set);
776 generation++;
777 }
778
779 IOLockUnlock(lock);
780
781 set->release();
782
783 return true;
784 }
785
786 void IOCatalogue::reset(void)
787 {
788 IOLog("Resetting IOCatalogue.\n");
789 }
790
791 bool IOCatalogue::serialize(OSSerialize * s) const
792 {
793 if ( !s )
794 return false;
795
796 return super::serialize(s);
797 }
798
799 bool IOCatalogue::serializeData(IOOptionBits kind, OSSerialize * s) const
800 {
801 kern_return_t kr = kIOReturnSuccess;
802
803 switch ( kind )
804 {
805 case kIOCatalogGetContents:
806 if (!array->serialize(s))
807 kr = kIOReturnNoMemory;
808 break;
809
810 case kIOCatalogGetModuleDemandList:
811 kr = KERN_NOT_SUPPORTED;
812 break;
813
814 case kIOCatalogGetCacheMissList:
815 kr = KERN_NOT_SUPPORTED;
816 break;
817
818 case kIOCatalogGetROMMkextList:
819 kr = KERN_NOT_SUPPORTED;
820 break;
821
822 default:
823 kr = kIOReturnBadArgument;
824 break;
825 }
826
827 return kr;
828 }
829
830
831 #if PRAGMA_MARK
832 #pragma mark Obsolete Kext Loading Stuff
833 #endif
834 /*********************************************************************
835 **********************************************************************
836 *** BINARY COMPATIBILITY SECTION ***
837 **********************************************************************
838 **********************************************************************
839 * These functions are no longer used are necessary for C++ binary
840 * compatibility on ppc/i386.
841 **********************************************************************/
842 #if __ppc__ || __i386__
843
844 bool IOCatalogue::recordStartupExtensions(void)
845 { return false; }
846
847 bool IOCatalogue::addExtensionsFromArchive(OSData * mkext)
848 { return KERN_NOT_SUPPORTED; }
849
850 kern_return_t IOCatalogue::removeKernelLinker(void)
851 { return KERN_NOT_SUPPORTED; }
852
853 #endif /* __ppc__ || __i386__ */