]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOCatalogue.cpp
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / Kernel / IOCatalogue.cpp
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
24 *
25 * HISTORY
26 *
27 */
28
29 #include <IOKit/IODeviceTreeSupport.h>
30 #include <IOKit/IOService.h>
31 #include <libkern/c++/OSContainers.h>
32 #include <IOKit/IOCatalogue.h>
33 #include <libkern/c++/OSUnserialize.h>
34 extern "C" {
35 #include <machine/machine_routines.h>
36 #include <mach/kmod.h>
37 #include <mach-o/mach_header.h>
38 };
39
40 #include <IOKit/IOLib.h>
41
42 #include <IOKit/assert.h>
43
44
45 extern "C" {
46 int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize );
47 extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize );
48 extern void OSRuntimeUnloadCPPForSegment(
49 struct segment_command * segment);
50 };
51
52
53 /*****
54 * At startup these function pointers are set to use the libsa in-kernel
55 * linker for recording and loading kmods. Once the root filesystem
56 * is available, the kmod_load_function pointer gets switched to point
57 * at the kmod_load_extension() function built into the kernel, and the
58 * others are set to zero. Those two functions must *always* be checked
59 * before being invoked.
60 */
61 extern "C" {
62 kern_return_t (*kmod_load_function)(char *extension_name) =
63 &kmod_load_extension;
64 bool (*record_startup_extensions_function)(void) = 0;
65 bool (*add_from_mkext_function)(OSData * mkext) = 0;
66 void (*remove_startup_extension_function)(const char * name) = 0;
67 };
68
69
70 /*****
71 * A few parts of IOCatalogue require knowledge of
72 * whether the in-kernel linker is present. This
73 * variable is set by libsa's bootstrap code.
74 */
75 int kernelLinkerPresent = 0;
76
77
78 #define super OSObject
79 #define kModuleKey "CFBundleIdentifier"
80
81 OSDefineMetaClassAndStructors(IOCatalogue, OSObject)
82
83 #define CATALOGTEST 0
84
85 IOCatalogue * gIOCatalogue;
86 const OSSymbol * gIOClassKey;
87 const OSSymbol * gIOProbeScoreKey;
88
89 static void UniqueProperties( OSDictionary * dict )
90 {
91 OSString * data;
92
93 data = OSDynamicCast( OSString, dict->getObject( gIOClassKey ));
94 if( data) {
95 const OSSymbol *classSymbol = OSSymbol::withString(data);
96
97 dict->setObject( gIOClassKey, (OSSymbol *) classSymbol);
98 classSymbol->release();
99 }
100
101 data = OSDynamicCast( OSString, dict->getObject( gIOMatchCategoryKey ));
102 if( data) {
103 const OSSymbol *classSymbol = OSSymbol::withString(data);
104
105 dict->setObject( gIOMatchCategoryKey, (OSSymbol *) classSymbol);
106 classSymbol->release();
107 }
108 }
109
110 void IOCatalogue::initialize( void )
111 {
112 OSArray * array;
113 OSString * errorString;
114 bool rc;
115
116 extern const char * gIOKernelConfigTables;
117
118 array = OSDynamicCast(OSArray, OSUnserialize(gIOKernelConfigTables, &errorString));
119 if (!array && errorString) {
120 IOLog("KernelConfigTables syntax error: %s\n",
121 errorString->getCStringNoCopy());
122 errorString->release();
123 }
124
125 gIOClassKey = OSSymbol::withCStringNoCopy( kIOClassKey );
126 gIOProbeScoreKey = OSSymbol::withCStringNoCopy( kIOProbeScoreKey );
127 assert( array && gIOClassKey && gIOProbeScoreKey);
128
129 gIOCatalogue = new IOCatalogue;
130 assert(gIOCatalogue);
131 rc = gIOCatalogue->init(array);
132 assert(rc);
133 array->release();
134 }
135
136 // Initialize the IOCatalog object.
137 bool IOCatalogue::init(OSArray * initArray)
138 {
139 IORegistryEntry * entry;
140 OSDictionary * dict;
141
142 if ( !super::init() )
143 return false;
144
145 generation = 1;
146
147 array = initArray;
148 array->retain();
149 kernelTables = OSCollectionIterator::withCollection( array );
150
151 lock = IOLockAlloc();
152
153 kernelTables->reset();
154 while( (dict = (OSDictionary *) kernelTables->getNextObject())) {
155 UniqueProperties(dict);
156 if( 0 == dict->getObject( gIOClassKey ))
157 IOLog("Missing or bad \"%s\" key\n",
158 gIOClassKey->getCStringNoCopy());
159 }
160
161 #if CATALOGTEST
162 AbsoluteTime deadline;
163 clock_interval_to_deadline( 1000, kMillisecondScale );
164 thread_call_func_delayed( ping, this, deadline );
165 #endif
166
167 entry = IORegistryEntry::getRegistryRoot();
168 if ( entry )
169 entry->setProperty(kIOCatalogueKey, this);
170
171 return true;
172 }
173
174 // Release all resources used by IOCatalogue and deallocate.
175 // This will probably never be called.
176 void IOCatalogue::free( void )
177 {
178 if ( array )
179 array->release();
180
181 if ( kernelTables )
182 kernelTables->release();
183
184 super::free();
185 }
186
187 #if CATALOGTEST
188
189 static int hackLimit;
190
191 enum { kDriversPerIter = 4 };
192
193 void IOCatalogue::ping( thread_call_param_t arg, thread_call_param_t)
194 {
195 IOCatalogue * self = (IOCatalogue *) arg;
196 OSOrderedSet * set;
197 OSDictionary * table;
198 int newLimit;
199
200 set = OSOrderedSet::withCapacity( 1 );
201
202 IOTakeLock( &self->lock );
203
204 for( newLimit = 0; newLimit < kDriversPerIter; newLimit++) {
205 table = (OSDictionary *) self->array->getObject(
206 hackLimit + newLimit );
207 if( table) {
208 set->setLastObject( table );
209
210 OSSymbol * sym = (OSSymbol *) table->getObject( gIOClassKey );
211 kprintf("enabling %s\n", sym->getCStringNoCopy());
212
213 } else {
214 newLimit--;
215 break;
216 }
217 }
218
219 IOService::catalogNewDrivers( set );
220
221 hackLimit += newLimit;
222 self->generation++;
223
224 IOUnlock( &self->lock );
225
226 if( kDriversPerIter == newLimit) {
227 AbsoluteTime deadline;
228 clock_interval_to_deadline( 500, kMillisecondScale );
229 thread_call_func_delayed( ping, this, deadline );
230 }
231 }
232 #endif
233
234 OSOrderedSet * IOCatalogue::findDrivers( IOService * service,
235 SInt32 * generationCount )
236 {
237 OSDictionary * nextTable;
238 OSOrderedSet * set;
239 OSString * imports;
240
241 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
242 (void *)gIOProbeScoreKey );
243 if( !set )
244 return( 0 );
245
246 IOTakeLock( lock );
247 kernelTables->reset();
248
249 #if CATALOGTEST
250 int hackIndex = 0;
251 #endif
252 while( (nextTable = (OSDictionary *) kernelTables->getNextObject())) {
253 #if CATALOGTEST
254 if( hackIndex++ > hackLimit)
255 break;
256 #endif
257 imports = OSDynamicCast( OSString,
258 nextTable->getObject( gIOProviderClassKey ));
259 if( imports && service->metaCast( imports ))
260 set->setObject( nextTable );
261 }
262
263 *generationCount = getGenerationCount();
264
265 IOUnlock( lock );
266
267 return( set );
268 }
269
270 // Is personality already in the catalog?
271 OSOrderedSet * IOCatalogue::findDrivers( OSDictionary * matching,
272 SInt32 * generationCount)
273 {
274 OSDictionary * dict;
275 OSOrderedSet * set;
276
277 UniqueProperties(matching);
278
279 set = OSOrderedSet::withCapacity( 1, IOServiceOrdering,
280 (void *)gIOProbeScoreKey );
281
282 IOTakeLock( lock );
283 kernelTables->reset();
284 while ( (dict = (OSDictionary *) kernelTables->getNextObject()) ) {
285 if ( dict->isEqualTo(matching, matching) )
286 set->setObject(dict);
287 }
288 *generationCount = getGenerationCount();
289 IOUnlock( lock );
290
291 return set;
292 }
293
294 // Add a new personality to the set if it has a unique IOResourceMatchKey value.
295 // XXX -- svail: This should be optimized.
296 // esb - There doesn't seem like any reason to do this - it causes problems
297 // esb - when there are more than one loadable driver matching on the same provider class
298 static void AddNewImports( OSOrderedSet * set, OSDictionary * dict )
299 {
300 set->setObject(dict);
301 }
302
303 // Add driver config tables to catalog and start matching process.
304 bool IOCatalogue::addDrivers(OSArray * drivers,
305 bool doNubMatching = true )
306 {
307 OSCollectionIterator * iter;
308 OSDictionary * dict;
309 OSOrderedSet * set;
310 OSArray * persons;
311 bool ret;
312
313 ret = true;
314 persons = OSDynamicCast(OSArray, drivers);
315 if ( !persons )
316 return false;
317
318 iter = OSCollectionIterator::withCollection( persons );
319 if (!iter )
320 return false;
321
322 set = OSOrderedSet::withCapacity( 10, IOServiceOrdering,
323 (void *)gIOProbeScoreKey );
324 if ( !set ) {
325 iter->release();
326 return false;
327 }
328
329 IOTakeLock( lock );
330 while ( (dict = (OSDictionary *) iter->getNextObject()) ) {
331 UInt count;
332
333 UniqueProperties( dict );
334
335 // Add driver personality to catalogue.
336 count = array->getCount();
337 while ( count-- ) {
338 OSDictionary * driver;
339
340 // Be sure not to double up on personalities.
341 driver = (OSDictionary *)array->getObject(count);
342 if ( dict->isEqualTo(driver, driver) ) {
343 array->removeObject(count);
344 break;
345 }
346 }
347
348 ret = array->setObject( dict );
349 if ( !ret )
350 break;
351
352 AddNewImports( set, dict );
353 }
354 // Start device matching.
355 if ( doNubMatching && (set->getCount() > 0) ) {
356 IOService::catalogNewDrivers( set );
357 generation++;
358 }
359 IOUnlock( lock );
360
361 if ( doNubMatching ) {
362 (IOService::getServiceRoot())->waitQuiet();
363 kmod_send_generic( kIOCatalogMatchIdle, 0, 0 );
364 }
365
366 set->release();
367 iter->release();
368
369 return ret;
370 }
371
372 // Remove drivers from the catalog which match the
373 // properties in the matching dictionary.
374 bool IOCatalogue::removeDrivers( OSDictionary * matching,
375 bool doNubMatching = true)
376 {
377 OSCollectionIterator * tables;
378 OSDictionary * dict;
379 OSOrderedSet * set;
380 OSArray * arrayCopy;
381
382 if ( !matching )
383 return false;
384
385 set = OSOrderedSet::withCapacity(10,
386 IOServiceOrdering,
387 (void *)gIOProbeScoreKey);
388 if ( !set )
389 return false;
390
391 arrayCopy = OSArray::withCapacity(100);
392 if ( !arrayCopy ) {
393 set->release();
394 return false;
395 }
396
397 tables = OSCollectionIterator::withCollection(arrayCopy);
398 arrayCopy->release();
399 if ( !tables ) {
400 set->release();
401 return false;
402 }
403
404 UniqueProperties( matching );
405
406 IOTakeLock( lock );
407 kernelTables->reset();
408 arrayCopy->merge(array);
409 array->flushCollection();
410 tables->reset();
411 while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
412 if ( dict->isEqualTo(matching, matching) ) {
413 AddNewImports( set, dict );
414 continue;
415 }
416
417 array->setObject(dict);
418 }
419 // Start device matching.
420 if ( doNubMatching && (set->getCount() > 0) ) {
421 IOService::catalogNewDrivers(set);
422 generation++;
423 }
424 IOUnlock( lock );
425
426 set->release();
427 tables->release();
428
429 return true;
430 }
431
432 // Return the generation count.
433 SInt32 IOCatalogue::getGenerationCount( void ) const
434 {
435 return( generation );
436 }
437
438 bool IOCatalogue::isModuleLoaded( OSString * moduleName ) const
439 {
440 return isModuleLoaded(moduleName->getCStringNoCopy());
441 }
442
443 bool IOCatalogue::isModuleLoaded( const char * moduleName ) const
444 {
445 kmod_info_t * k_info;
446
447 if ( !moduleName )
448 return false;
449
450 // Is the module already loaded?
451 k_info = kmod_lookupbyname((char *)moduleName);
452 if ( !k_info ) {
453 kern_return_t ret;
454
455 // If the module hasn't been loaded, then load it.
456 if (kmod_load_function != 0) {
457 ret = kmod_load_function((char *)moduleName);
458 if ( ret != kIOReturnSuccess ) {
459 IOLog("IOCatalogue: %s cannot be loaded.\n", moduleName);
460
461 /* If the extension couldn't be loaded this time,
462 * make it unavailable so that no more requests are
463 * made in vain. This also enables other matching
464 * extensions to have a chance.
465 */
466 if (kernelLinkerPresent && remove_startup_extension_function) {
467 (*remove_startup_extension_function)(moduleName);
468 }
469 return false;
470 } else if (kernelLinkerPresent) {
471 // If kern linker is here, the driver is actually loaded,
472 // so return true.
473 return true;
474 } else {
475 // kern linker isn't here, a request has been queued
476 // but the module isn't necessarily loaded yet, so stall.
477 return false;
478 }
479 } else {
480 IOLog("IOCatalogue: %s cannot be loaded "
481 "(kmod load function not set).\n",
482 moduleName);
483 }
484
485 return false;
486 }
487
488 return true;
489 }
490
491 // Check to see if module has been loaded already.
492 bool IOCatalogue::isModuleLoaded( OSDictionary * driver ) const
493 {
494 OSString * moduleName = NULL;
495
496 if ( !driver )
497 return false;
498
499 moduleName = OSDynamicCast(OSString, driver->getObject(kModuleKey));
500 if ( moduleName )
501 return isModuleLoaded(moduleName);
502
503 /* If a personality doesn't hold the "CFBundleIdentifier" key
504 * it is assumed to be an "in-kernel" driver.
505 */
506 return true;
507 }
508
509 // This function is called after a module has been loaded.
510 void IOCatalogue::moduleHasLoaded( OSString * moduleName )
511 {
512 OSDictionary * dict;
513
514 dict = OSDictionary::withCapacity(2);
515 dict->setObject(kModuleKey, moduleName);
516 startMatching(dict);
517 dict->release();
518 }
519
520 void IOCatalogue::moduleHasLoaded( const char * moduleName )
521 {
522 OSString * name;
523
524 name = OSString::withCString(moduleName);
525 moduleHasLoaded(name);
526 name->release();
527 }
528
529 IOReturn IOCatalogue::unloadModule( OSString * moduleName ) const
530 {
531 kmod_info_t * k_info;
532 kern_return_t ret;
533 const char * name;
534
535 ret = kIOReturnBadArgument;
536 if ( moduleName ) {
537 name = moduleName->getCStringNoCopy();
538 k_info = kmod_lookupbyname((char *)name);
539 if ( k_info && (k_info->reference_count < 1) ) {
540 if ( k_info->stop &&
541 !((ret = k_info->stop(k_info, 0)) == kIOReturnSuccess) )
542 return ret;
543
544 ret = kmod_destroy(host_priv_self(), k_info->id);
545 }
546 }
547
548 return ret;
549 }
550
551 static IOReturn _terminateDrivers( OSArray * array, OSDictionary * matching )
552 {
553 OSCollectionIterator * tables;
554 OSCollectionIterator * props;
555 OSDictionary * dict;
556 OSIterator * iter;
557 OSArray * arrayCopy;
558 IOService * service;
559 IOReturn ret;
560
561 if ( !matching )
562 return kIOReturnBadArgument;
563
564 ret = kIOReturnSuccess;
565 dict = 0;
566 iter = IORegistryIterator::iterateOver(gIOServicePlane,
567 kIORegistryIterateRecursively);
568 if ( !iter )
569 return kIOReturnNoMemory;
570
571 UniqueProperties( matching );
572
573 props = OSCollectionIterator::withCollection(matching);
574 if ( !props ) {
575 iter->release();
576 return kIOReturnNoMemory;
577 }
578
579 // terminate instances.
580 do {
581 iter->reset();
582 while( (service = (IOService *)iter->getNextObject()) ) {
583 dict = service->getPropertyTable();
584 if ( !dict )
585 continue;
586
587 if ( !dict->isEqualTo(matching, matching) )
588 continue;
589
590 if ( !service->terminate(kIOServiceRequired|kIOServiceSynchronous) ) {
591 ret = kIOReturnUnsupported;
592 break;
593 }
594 }
595 } while( !service && !iter->isValid());
596 iter->release();
597
598 // remove configs from catalog.
599 if ( ret != kIOReturnSuccess )
600 return ret;
601
602 arrayCopy = OSArray::withCapacity(100);
603 if ( !arrayCopy )
604 return kIOReturnNoMemory;
605
606 tables = OSCollectionIterator::withCollection(arrayCopy);
607 arrayCopy->release();
608 if ( !tables )
609 return kIOReturnNoMemory;
610
611 arrayCopy->merge(array);
612 array->flushCollection();
613 tables->reset();
614 while ( (dict = (OSDictionary *)tables->getNextObject()) ) {
615 if ( dict->isEqualTo(matching, matching) )
616 continue;
617
618 array->setObject(dict);
619 }
620
621 tables->release();
622
623 return ret;
624 }
625
626 IOReturn IOCatalogue::terminateDrivers( OSDictionary * matching )
627 {
628 IOReturn ret;
629
630 ret = kIOReturnSuccess;
631 IOTakeLock( lock );
632 ret = _terminateDrivers(array, matching);
633 kernelTables->reset();
634 IOUnlock( lock );
635
636 return ret;
637 }
638
639 IOReturn IOCatalogue::terminateDriversForModule(
640 OSString * moduleName,
641 bool unload )
642 {
643 IOReturn ret;
644 OSDictionary * dict;
645
646 dict = OSDictionary::withCapacity(1);
647 if ( !dict )
648 return kIOReturnNoMemory;
649
650 dict->setObject(kModuleKey, moduleName);
651
652 IOTakeLock( lock );
653
654 ret = _terminateDrivers(array, dict);
655 kernelTables->reset();
656
657 // Unload the module itself.
658 if ( unload && ret == kIOReturnSuccess ) {
659 // Do kmod stop first.
660 ret = unloadModule(moduleName);
661 }
662
663 IOUnlock( lock );
664
665 dict->release();
666
667 return ret;
668 }
669
670 IOReturn IOCatalogue::terminateDriversForModule(
671 const char * moduleName,
672 bool unload )
673 {
674 OSString * name;
675 IOReturn ret;
676
677 name = OSString::withCString(moduleName);
678 if ( !name )
679 return kIOReturnNoMemory;
680
681 ret = terminateDriversForModule(name, unload);
682 name->release();
683
684 return ret;
685 }
686
687 bool IOCatalogue::startMatching( OSDictionary * matching )
688 {
689 OSDictionary * dict;
690 OSOrderedSet * set;
691
692 if ( !matching )
693 return false;
694
695 set = OSOrderedSet::withCapacity(10, IOServiceOrdering,
696 (void *)gIOProbeScoreKey);
697 if ( !set )
698 return false;
699
700 IOTakeLock( lock );
701 kernelTables->reset();
702
703 while ( (dict = (OSDictionary *)kernelTables->getNextObject()) ) {
704 if ( dict->isEqualTo(matching, matching) )
705 AddNewImports(set, dict);
706 }
707 // Start device matching.
708 if ( set->getCount() > 0 ) {
709 IOService::catalogNewDrivers(set);
710 generation++;
711 }
712
713 IOUnlock( lock );
714
715 set->release();
716
717 return true;
718 }
719
720 void IOCatalogue::reset(void)
721 {
722 OSArray * tables;
723 OSDictionary * entry;
724 unsigned int count;
725
726 IOLog("Resetting IOCatalogue.\n");
727
728 IOTakeLock( lock );
729 tables = OSArray::withArray(array);
730 array->flushCollection();
731
732 count = tables->getCount();
733 while ( count-- ) {
734 entry = (OSDictionary *)tables->getObject(count);
735 if ( entry && !entry->getObject(kModuleKey) ) {
736 array->setObject(entry);
737 }
738 }
739
740 kernelTables->reset();
741 IOUnlock( lock );
742
743 tables->release();
744 }
745
746 bool IOCatalogue::serialize(OSSerialize * s) const
747 {
748 bool ret;
749
750 if ( !s )
751 return false;
752
753 IOTakeLock( lock );
754 ret = array->serialize(s);
755 IOUnlock( lock );
756
757 return ret;
758 }
759
760
761 bool IOCatalogue::recordStartupExtensions(void) {
762 bool result = false;
763
764 if (record_startup_extensions_function) {
765 result = (*record_startup_extensions_function)();
766 } else {
767 IOLog("Can't record startup extensions; "
768 "kernel linker is not present.\n");
769 result = false;
770 }
771
772 return result;
773 }
774
775
776 /*********************************************************************
777 *********************************************************************/
778 bool IOCatalogue::addExtensionsFromArchive(OSData * mkext) {
779 bool result = false;
780
781 if (add_from_mkext_function) {
782 result = (*add_from_mkext_function)(mkext);
783 } else {
784 IOLog("Can't add startup extensions from archive; "
785 "kernel linker is not present.\n");
786 result = false;
787 }
788
789 return result;
790 }
791
792
793 /*********************************************************************
794 * This function clears out all references to the in-kernel linker,
795 * frees the list of startup extensions in extensionDict, and
796 * deallocates the kernel's __KLD segment to reclaim that memory.
797 *********************************************************************/
798 kern_return_t IOCatalogue::removeKernelLinker(void) {
799 kern_return_t result = KERN_SUCCESS;
800 extern struct mach_header _mh_execute_header;
801 struct segment_command * segment;
802 char * dt_segment_name;
803 void * segment_paddress;
804 int segment_size;
805
806 /* This must be the very first thing done by this function.
807 */
808 IOTakeLock(lock);
809
810
811 /* If the kernel linker isn't here, that's automatically
812 * a success.
813 */
814 if (!kernelLinkerPresent) {
815 result = KERN_SUCCESS;
816 goto finish;
817 }
818
819 IOLog("Jettisoning kernel linker.\n");
820
821 kernelLinkerPresent = 0;
822
823 /* Set the kmod_load_extension function as the means for loading
824 * a kernel extension.
825 */
826 kmod_load_function = &kmod_load_extension;
827
828 record_startup_extensions_function = 0;
829 add_from_mkext_function = 0;
830 remove_startup_extension_function = 0;
831
832
833 /* Invoke destructors for the __KLD and __LINKEDIT segments.
834 * Do this for all segments before actually freeing their
835 * memory so that any cross-dependencies (not that there
836 * should be any) are handled.
837 */
838 segment = getsegbynamefromheader(
839 &_mh_execute_header, "__KLD");
840 if (!segment) {
841 result = KERN_FAILURE;
842 goto finish;
843 }
844 OSRuntimeUnloadCPPForSegment(segment);
845
846 segment = getsegbynamefromheader(
847 &_mh_execute_header, "__LINKEDIT");
848 if (!segment) {
849 result = KERN_FAILURE;
850 goto finish;
851 }
852 OSRuntimeUnloadCPPForSegment(segment);
853
854
855 /* Free the memory that was set up by bootx.
856 */
857 dt_segment_name = "Kernel-__KLD";
858 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
859 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
860 (int)segment_size);
861 }
862
863 dt_segment_name = "Kernel-__LINKEDIT";
864 if (0 == IODTGetLoaderInfo(dt_segment_name, &segment_paddress, &segment_size)) {
865 IODTFreeLoaderInfo(dt_segment_name, (void *)segment_paddress,
866 (int)segment_size);
867 }
868
869
870 finish:
871
872 /* This must be the very last thing done before returning.
873 */
874 IOUnlock(lock);
875
876 return result;
877 }