2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <mach/kmod.h>
30 #include <libkern/kernel_mach_header.h>
31 #include <libkern/prelink.h>
34 #include <libkern/version.h>
35 #include <libkern/c++/OSContainers.h>
36 #include <libkern/OSKextLibPrivate.h>
37 #include <libkern/c++/OSKext.h>
38 #include <IOKit/IOLib.h>
39 #include <IOKit/IOService.h>
40 #include <IOKit/IODeviceTreeSupport.h>
41 #include <IOKit/IOCatalogue.h>
44 #define KASLR_KEXT_DEBUG 0
48 #pragma mark Bootstrap Declarations
50 /*********************************************************************
51 * Bootstrap Declarations
53 * The ENTIRE point of the libsa/KLD segment is to isolate bootstrap
54 * code from other parts of the kernel, so function symbols are not
55 * exported; rather pointers to those functions are exported.
57 * xxx - need to think about locking for handling the 'weak' refs.
58 * xxx - do export a non-KLD function that says you've called a
59 * xxx - bootstrap function that has been removed.
61 * ALL call-ins to this segment of the kernel must be done through
62 * exported pointers. The symbols themselves are private and not to
64 *********************************************************************/
66 extern void (*record_startup_extensions_function
)(void);
67 extern void (*load_security_extensions_function
)(void);
70 static void bootstrapRecordStartupExtensions(void);
71 static void bootstrapLoadSecurityExtensions(void);
75 extern "C" bool IORamDiskBSDRoot(void);
81 /*********************************************************************
83 *********************************************************************/
84 #define CONST_STRLEN(str) (sizeof(str) - 1)
87 #pragma mark Kernel Component Kext Identifiers
89 /*********************************************************************
90 * Kernel Component Kext Identifiers
92 * We could have each kernel resource kext automatically "load" as
93 * it's created, but it's nicer to have them listed in kextstat in
94 * the order of this list. We'll walk through this after setting up
95 * all the boot kexts and have them load up.
96 *********************************************************************/
97 static const char * sKernelComponentNames
[] = {
98 // The kexts for these IDs must have a version matching 'osrelease'.
101 "com.apple.kpi.dsep",
102 "com.apple.kpi.iokit",
103 "com.apple.kpi.kasan",
104 "com.apple.kpi.libkern",
105 "com.apple.kpi.mach",
106 "com.apple.kpi.private",
107 "com.apple.kpi.unsupported",
108 "com.apple.iokit.IONVRAMFamily",
109 "com.apple.driver.AppleNMI",
110 "com.apple.iokit.IOSystemManagementFamily",
111 "com.apple.iokit.ApplePlatformFamily",
115 static int __whereIsAddr(vm_offset_t theAddr
, unsigned long * segSizes
, vm_offset_t
*segAddrs
, int segCount
);
117 #define PLK_SEGMENTS 12
119 static const char * plk_segNames
[] = {
136 #pragma mark KLDBootstrap Class
138 /*********************************************************************
141 * We use a C++ class here so that it can be a friend of OSKext and
142 * get at private stuff. We can't hide the class itself, but we can
143 * hide the instance through which we invoke the functions.
144 *********************************************************************/
146 friend void bootstrapRecordStartupExtensions(void);
147 friend void bootstrapLoadSecurityExtensions(void);
150 void readStartupExtensions(void);
152 void readPrelinkedExtensions(
153 kernel_section_t
* prelinkInfoSect
);
154 void readBooterExtensions(void);
156 OSReturn
loadKernelComponentKexts(void);
157 void loadKernelExternalComponents(void);
158 void readBuiltinPersonalities(void);
160 void loadSecurityExtensions(void);
167 static KLDBootstrap sBootstrapObject
;
169 /*********************************************************************
170 * Set the function pointers for the entry points into the bootstrap
171 * segment upon C++ static constructor invocation.
172 *********************************************************************/
173 KLDBootstrap::KLDBootstrap(void)
175 if (this != &sBootstrapObject
) {
176 panic("Attempt to access bootstrap segment.");
178 record_startup_extensions_function
= &bootstrapRecordStartupExtensions
;
179 load_security_extensions_function
= &bootstrapLoadSecurityExtensions
;
182 /*********************************************************************
183 * Clear the function pointers for the entry points into the bootstrap
184 * segment upon C++ static destructor invocation.
185 *********************************************************************/
186 KLDBootstrap::~KLDBootstrap(void)
188 if (this != &sBootstrapObject
) {
189 panic("Attempt to access bootstrap segment.");
193 record_startup_extensions_function
= 0;
194 load_security_extensions_function
= 0;
197 /*********************************************************************
198 *********************************************************************/
200 KLDBootstrap::readStartupExtensions(void)
202 kernel_section_t
* prelinkInfoSect
= NULL
; // do not free
204 OSKextLog(/* kext */ NULL
,
205 kOSKextLogProgressLevel
|
206 kOSKextLogGeneralFlag
| kOSKextLogDirectoryScanFlag
|
207 kOSKextLogKextBookkeepingFlag
,
208 "Reading startup extensions.");
210 /* If the prelink info segment has a nonzero size, we are prelinked
211 * and won't have any individual kexts or mkexts to read.
212 * Otherwise, we need to read kexts or the mkext from what the booter
215 prelinkInfoSect
= getsectbyname(kPrelinkInfoSegment
, kPrelinkInfoSection
);
216 if (prelinkInfoSect
->size
) {
217 readPrelinkedExtensions(prelinkInfoSect
);
219 readBooterExtensions();
222 loadKernelComponentKexts();
223 loadKernelExternalComponents();
224 readBuiltinPersonalities();
225 OSKext::sendAllKextPersonalitiesToCatalog();
230 typedef struct kaslrPackedOffsets
{
231 uint32_t count
; /* number of offsets */
232 uint32_t offsetsArray
[]; /* offsets to slide */
233 } kaslrPackedOffsets
;
235 /*********************************************************************
236 *********************************************************************/
238 KLDBootstrap::readPrelinkedExtensions(
239 kernel_section_t
* prelinkInfoSect
)
241 OSArray
* infoDictArray
= NULL
; // do not release
242 OSObject
* parsedXML
= NULL
; // must release
243 OSDictionary
* prelinkInfoDict
= NULL
; // do not release
244 OSString
* errorString
= NULL
; // must release
245 OSKext
* theKernel
= NULL
; // must release
246 OSData
* kernelcacheUUID
= NULL
; // do not release
248 kernel_segment_command_t
* prelinkTextSegment
= NULL
; // see code
249 kernel_segment_command_t
* prelinkInfoSegment
= NULL
; // see code
251 /* We make some copies of data, but if anything fails we're basically
252 * going to fail the boot, so these won't be cleaned up on error.
254 void * prelinkData
= NULL
; // see code
255 vm_size_t prelinkLength
= 0;
258 OSDictionary
* infoDict
= NULL
; // do not release
260 IORegistryEntry
* registryRoot
= NULL
; // do not release
261 OSNumber
* prelinkCountObj
= NULL
; // must release
266 bool developerDevice
;
269 OSData
* kaslrOffsets
= NULL
;
270 unsigned long plk_segSizes
[PLK_SEGMENTS
];
271 vm_offset_t plk_segAddrs
[PLK_SEGMENTS
];
273 OSKextLog(/* kext */ NULL
,
274 kOSKextLogProgressLevel
|
275 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
276 "Starting from prelinked kernel.");
278 prelinkTextSegment
= getsegbyname(kPrelinkTextSegment
);
279 if (!prelinkTextSegment
) {
280 OSKextLog(/* kext */ NULL
,
281 kOSKextLogErrorLevel
|
282 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
283 "Can't find prelinked kexts' text segment.");
288 unsigned long scratchSize
;
289 vm_offset_t scratchAddr
;
291 IOLog("kaslr: prelinked kernel address info: \n");
293 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__TEXT", &scratchSize
);
294 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __TEXT \n",
295 (unsigned long)scratchAddr
,
296 (unsigned long)(scratchAddr
+ scratchSize
),
299 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__DATA", &scratchSize
);
300 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __DATA \n",
301 (unsigned long)scratchAddr
,
302 (unsigned long)(scratchAddr
+ scratchSize
),
305 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__LINKEDIT", &scratchSize
);
306 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __LINKEDIT \n",
307 (unsigned long)scratchAddr
,
308 (unsigned long)(scratchAddr
+ scratchSize
),
311 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__KLD", &scratchSize
);
312 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __KLD \n",
313 (unsigned long)scratchAddr
,
314 (unsigned long)(scratchAddr
+ scratchSize
),
317 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__PRELINK_TEXT", &scratchSize
);
318 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_TEXT \n",
319 (unsigned long)scratchAddr
,
320 (unsigned long)(scratchAddr
+ scratchSize
),
323 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__PRELINK_INFO", &scratchSize
);
324 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_INFO \n",
325 (unsigned long)scratchAddr
,
326 (unsigned long)(scratchAddr
+ scratchSize
),
330 prelinkData
= (void *) prelinkTextSegment
->vmaddr
;
331 prelinkLength
= prelinkTextSegment
->vmsize
;
333 /* build arrays of plk info for later use */
334 const char ** segNamePtr
;
336 for (segNamePtr
= &plk_segNames
[0], i
= 0; *segNamePtr
&& i
< PLK_SEGMENTS
; segNamePtr
++, i
++) {
338 plk_segAddrs
[i
] = (vm_offset_t
)getsegdatafromheader(&_mh_execute_header
, *segNamePtr
, &plk_segSizes
[i
]);
342 /* Unserialize the info dictionary from the prelink info section.
344 parsedXML
= OSUnserializeXML((const char *)prelinkInfoSect
->addr
,
347 prelinkInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
349 if (!prelinkInfoDict
) {
350 const char * errorCString
= "(unknown error)";
352 if (errorString
&& errorString
->getCStringNoCopy()) {
353 errorCString
= errorString
->getCStringNoCopy();
354 } else if (parsedXML
) {
355 errorCString
= "not a dictionary";
357 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
358 "Error unserializing prelink plist: %s.", errorCString
);
363 /* Check if we should keep developer kexts around.
364 * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201>
366 developerDevice
= true;
367 PE_parse_boot_argn("developer", &developerDevice
, sizeof(developerDevice
));
369 ramDiskBoot
= IORamDiskBSDRoot();
370 #endif /* NO_KEXTD */
372 /* Copy in the kernelcache UUID */
373 kernelcacheUUID
= OSDynamicCast(OSData
,
374 prelinkInfoDict
->getObject(kPrelinkInfoKCIDKey
));
375 if (kernelcacheUUID
) {
376 if (kernelcacheUUID
->getLength() != sizeof(kernelcache_uuid
)) {
377 panic("kernelcacheUUID length is %d, expected %lu", kernelcacheUUID
->getLength(),
378 sizeof(kernelcache_uuid
));
380 kernelcache_uuid_valid
= TRUE
;
381 memcpy((void *)&kernelcache_uuid
, (const void *)kernelcacheUUID
->getBytesNoCopy(), kernelcacheUUID
->getLength());
382 uuid_unparse_upper(kernelcache_uuid
, kernelcache_uuid_string
);
386 infoDictArray
= OSDynamicCast(OSArray
,
387 prelinkInfoDict
->getObject(kPrelinkInfoDictionaryKey
));
388 if (!infoDictArray
) {
389 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
390 "The prelinked kernel has no kext info dictionaries");
394 /* kaslrOffsets are available use them to slide local relocations */
395 kaslrOffsets
= OSDynamicCast(OSData
,
396 prelinkInfoDict
->getObject(kPrelinkLinkKASLROffsetsKey
));
398 /* Create dictionary of excluded kexts
400 #ifndef CONFIG_EMBEDDED
401 OSKext::createExcludeListFromPrelinkInfo(infoDictArray
);
403 /* Create OSKext objects for each info dictionary.
405 for (i
= 0; i
< infoDictArray
->getCount(); ++i
) {
406 infoDict
= OSDynamicCast(OSDictionary
, infoDictArray
->getObject(i
));
408 OSKextLog(/* kext */ NULL
,
409 kOSKextLogErrorLevel
|
410 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
411 "Can't find info dictionary for prelinked kext #%d.", i
);
418 /* If we're not on a developer device, skip and free developer kexts.
420 if (developerDevice
== false) {
421 OSBoolean
*devOnlyBool
= OSDynamicCast(OSBoolean
,
422 infoDict
->getObject(kOSBundleDeveloperOnlyKey
));
423 if (devOnlyBool
== kOSBooleanTrue
) {
428 /* Skip and free kexts that are only needed when booted from a ram disk.
430 if (ramDiskBoot
== false) {
431 OSBoolean
*ramDiskOnlyBool
= OSDynamicCast(OSBoolean
,
432 infoDict
->getObject(kOSBundleRamDiskOnlyKey
));
433 if (ramDiskOnlyBool
== kOSBooleanTrue
) {
438 if (dontLoad
== true) {
439 OSString
*bundleID
= OSDynamicCast(OSString
,
440 infoDict
->getObject(kCFBundleIdentifierKey
));
442 OSKextLog(NULL
, kOSKextLogWarningLevel
| kOSKextLogGeneralFlag
,
443 "Kext %s not loading.", bundleID
->getCStringNoCopy());
446 OSNumber
*addressNum
= OSDynamicCast(OSNumber
,
447 infoDict
->getObject(kPrelinkExecutableLoadKey
));
448 OSNumber
*lengthNum
= OSDynamicCast(OSNumber
,
449 infoDict
->getObject(kPrelinkExecutableSizeKey
));
450 if (addressNum
&& lengthNum
) {
451 #if __arm__ || __arm64__
452 vm_offset_t data
= ml_static_slide(addressNum
->unsigned64BitValue());
453 vm_size_t length
= (vm_size_t
) (lengthNum
->unsigned32BitValue());
454 ml_static_mfree(data
, length
);
456 #error Pick the right way to free prelinked data on this arch
460 infoDictArray
->removeObject(i
--);
463 #endif /* NO_KEXTD */
465 /* Create the kext for the entry, then release it, because the
466 * kext system keeps them around until explicitly removed.
467 * Any creation/registration failures are already logged for us.
469 OSKext
* newKext
= OSKext::withPrelinkedInfoDict(infoDict
, (kaslrOffsets
? TRUE
: FALSE
));
470 OSSafeReleaseNULL(newKext
);
473 /* slide kxld relocations */
474 if (kaslrOffsets
&& vm_kernel_slide
> 0) {
475 int slidKextAddrCount
= 0;
476 int badSlideAddr
= 0;
477 int badSlideTarget
= 0;
479 const kaslrPackedOffsets
* myOffsets
= NULL
;
480 myOffsets
= (const kaslrPackedOffsets
*) kaslrOffsets
->getBytesNoCopy();
482 for (uint32_t j
= 0; j
< myOffsets
->count
; j
++) {
484 uint64_t slideOffset
= (uint64_t) myOffsets
->offsetsArray
[j
];
485 uintptr_t * slideAddr
= (uintptr_t *) ((uint64_t)prelinkData
+ slideOffset
);
486 int slideAddrSegIndex
= -1;
487 int addrToSlideSegIndex
= -1;
489 slideAddrSegIndex
= __whereIsAddr( (vm_offset_t
)slideAddr
, &plk_segSizes
[0], &plk_segAddrs
[0], PLK_SEGMENTS
);
490 if (slideAddrSegIndex
>= 0) {
491 addrToSlideSegIndex
= __whereIsAddr(ml_static_slide((vm_offset_t
)(*slideAddr
)), &plk_segSizes
[0], &plk_segAddrs
[0], PLK_SEGMENTS
);
492 if (addrToSlideSegIndex
< 0) {
503 *slideAddr
= ml_static_slide(*slideAddr
);
506 /* All kexts are now slid, set VM protections for them */
507 OSKext::setAllVMAttributes();
510 /* Store the number of prelinked kexts in the registry so we can tell
511 * when the system has been started from a prelinked kernel.
513 registryRoot
= IORegistryEntry::getRegistryRoot();
514 assert(registryRoot
);
516 prelinkCountObj
= OSNumber::withNumber(
517 (unsigned long long)infoDictArray
->getCount(),
518 8 * sizeof(uint32_t));
519 assert(prelinkCountObj
);
520 if (prelinkCountObj
) {
521 registryRoot
->setProperty(kOSPrelinkKextCountKey
, prelinkCountObj
);
524 OSKextLog(/* kext */ NULL
,
525 kOSKextLogProgressLevel
|
526 kOSKextLogGeneralFlag
| kOSKextLogKextBookkeepingFlag
|
527 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
528 "%u prelinked kexts",
529 infoDictArray
->getCount());
531 #if CONFIG_KEXT_BASEMENT
532 /* On CONFIG_KEXT_BASEMENT systems, kexts are copied to their own
533 * special VM region during OSKext init time, so we can free the whole
536 ml_static_mfree((vm_offset_t
) prelinkData
, prelinkLength
);
537 #endif /* __x86_64__ */
539 /* Free the prelink info segment, we're done with it.
541 prelinkInfoSegment
= getsegbyname(kPrelinkInfoSegment
);
542 if (prelinkInfoSegment
) {
543 ml_static_mfree((vm_offset_t
)prelinkInfoSegment
->vmaddr
,
544 (vm_size_t
)prelinkInfoSegment
->vmsize
);
548 OSSafeReleaseNULL(errorString
);
549 OSSafeReleaseNULL(parsedXML
);
550 OSSafeReleaseNULL(theKernel
);
551 OSSafeReleaseNULL(prelinkCountObj
);
555 static int __whereIsAddr(vm_offset_t theAddr
, unsigned long * segSizes
, vm_offset_t
*segAddrs
, int segCount
)
559 for (i
= 0; i
< segCount
; i
++) {
560 vm_offset_t myAddr
= *(segAddrs
+ i
);
561 unsigned long mySize
= *(segSizes
+ i
);
563 if (theAddr
>= myAddr
&& theAddr
< (myAddr
+ mySize
)) {
572 /*********************************************************************
573 *********************************************************************/
574 #define BOOTER_KEXT_PREFIX "Driver-"
576 typedef struct _DeviceTreeBuffer
{
582 KLDBootstrap::readBooterExtensions(void)
584 IORegistryEntry
* booterMemoryMap
= NULL
; // must release
585 OSDictionary
* propertyDict
= NULL
; // must release
586 OSCollectionIterator
* keyIterator
= NULL
; // must release
587 OSString
* deviceTreeName
= NULL
; // do not release
589 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
; // do not free
590 char * booterDataPtr
= NULL
; // do not free
591 OSData
* booterData
= NULL
; // must release
593 OSKext
* aKext
= NULL
; // must release
595 OSKextLog(/* kext */ NULL
,
596 kOSKextLogProgressLevel
|
597 kOSKextLogDirectoryScanFlag
| kOSKextLogKextBookkeepingFlag
,
598 "Reading startup extensions from booter memory.");
600 booterMemoryMap
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
);
602 if (!booterMemoryMap
) {
603 OSKextLog(/* kext */ NULL
,
604 kOSKextLogErrorLevel
|
605 kOSKextLogGeneralFlag
| kOSKextLogDirectoryScanFlag
,
606 "Can't read booter memory map.");
610 propertyDict
= booterMemoryMap
->dictionaryWithProperties();
612 OSKextLog(/* kext */ NULL
,
613 kOSKextLogErrorLevel
|
614 kOSKextLogDirectoryScanFlag
,
615 "Can't get property dictionary from memory map.");
619 keyIterator
= OSCollectionIterator::withCollection(propertyDict
);
621 OSKextLog(/* kext */ NULL
,
622 kOSKextLogErrorLevel
|
623 kOSKextLogGeneralFlag
,
624 "Can't allocate iterator for driver images.");
628 /* Create dictionary of excluded kexts
630 #ifndef CONFIG_EMBEDDED
631 OSKext::createExcludeListFromBooterData(propertyDict
, keyIterator
);
633 keyIterator
->reset();
635 while ( ( deviceTreeName
=
636 OSDynamicCast(OSString
, keyIterator
->getNextObject() ))) {
638 const char * devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
639 OSData
* deviceTreeEntry
= OSDynamicCast(OSData
,
640 propertyDict
->getObject(deviceTreeName
));
642 /* Clear out the booterData from the prior iteration.
644 OSSafeReleaseNULL(booterData
);
646 /* If there is no entry for the name, we can't do much with it. */
647 if (!deviceTreeEntry
) {
651 /* Make sure it is a kext */
652 if (strncmp(devTreeNameCString
,
654 CONST_STRLEN(BOOTER_KEXT_PREFIX
))) {
658 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
659 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
660 if (!deviceTreeBuffer
) {
661 /* We can't get to the data, so we can't do anything,
662 * not even free it from physical memory (if it's there).
664 OSKextLog(/* kext */ NULL
,
665 kOSKextLogErrorLevel
|
666 kOSKextLogDirectoryScanFlag
,
667 "Device tree entry %s has NULL pointer.",
669 goto finish
; // xxx - continue, panic?
672 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
673 if (!booterDataPtr
) {
674 OSKextLog(/* kext */ NULL
,
675 kOSKextLogErrorLevel
|
676 kOSKextLogDirectoryScanFlag
,
677 "Can't get virtual address for device tree entry %s.",
682 /* Wrap the booter data buffer in an OSData and set a dealloc function
683 * so it will take care of the physical memory when freed. Kexts will
684 * retain the booterData for as long as they need it. Remove the entry
685 * from the booter memory map after this is done.
687 booterData
= OSData::withBytesNoCopy(booterDataPtr
,
688 deviceTreeBuffer
->length
);
690 OSKextLog(/* kext */ NULL
,
691 kOSKextLogErrorLevel
|
692 kOSKextLogGeneralFlag
,
693 "Error - Can't allocate OSData wrapper for device tree entry %s.",
697 booterData
->setDeallocFunction(osdata_phys_free
);
699 /* Create the kext for the entry, then release it, because the
700 * kext system keeps them around until explicitly removed.
701 * Any creation/registration failures are already logged for us.
703 OSKext
* newKext
= OSKext::withBooterData(deviceTreeName
, booterData
);
704 OSSafeReleaseNULL(newKext
);
706 booterMemoryMap
->removeProperty(deviceTreeName
);
708 } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */
712 OSSafeReleaseNULL(booterMemoryMap
);
713 OSSafeReleaseNULL(propertyDict
);
714 OSSafeReleaseNULL(keyIterator
);
715 OSSafeReleaseNULL(booterData
);
716 OSSafeReleaseNULL(aKext
);
720 /*********************************************************************
721 *********************************************************************/
722 #define COM_APPLE "com.apple."
725 KLDBootstrap::loadSecurityExtensions(void)
727 OSDictionary
* extensionsDict
= NULL
; // must release
728 OSCollectionIterator
* keyIterator
= NULL
; // must release
729 OSString
* bundleID
= NULL
; // don't release
730 OSKext
* theKext
= NULL
; // don't release
731 OSBoolean
* isSecurityKext
= NULL
; // don't release
733 OSKextLog(/* kext */ NULL
,
734 kOSKextLogStepLevel
|
736 "Loading security extensions.");
738 extensionsDict
= OSKext::copyKexts();
739 if (!extensionsDict
) {
743 keyIterator
= OSCollectionIterator::withCollection(extensionsDict
);
745 OSKextLog(/* kext */ NULL
,
746 kOSKextLogErrorLevel
|
747 kOSKextLogGeneralFlag
,
748 "Failed to allocate iterator for security extensions.");
752 while ((bundleID
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
754 const char * bundle_id
= bundleID
->getCStringNoCopy();
756 /* Skip extensions whose bundle IDs don't start with "com.apple.".
759 (strncmp(bundle_id
, COM_APPLE
, CONST_STRLEN(COM_APPLE
)) != 0)) {
764 theKext
= OSDynamicCast(OSKext
, extensionsDict
->getObject(bundleID
));
769 isSecurityKext
= OSDynamicCast(OSBoolean
,
770 theKext
->getPropertyForHostArch(kAppleSecurityExtensionKey
));
771 if (isSecurityKext
&& isSecurityKext
->isTrue()) {
772 OSKextLog(/* kext */ NULL
,
773 kOSKextLogStepLevel
|
775 "Loading security extension %s.", bundleID
->getCStringNoCopy());
776 OSKext::loadKextWithIdentifier(bundleID
->getCStringNoCopy(),
777 /* allowDefer */ false);
782 OSSafeReleaseNULL(keyIterator
);
783 OSSafeReleaseNULL(extensionsDict
);
788 /*********************************************************************
789 * We used to require that all listed kernel components load, but
790 * nowadays we can get them from userland so we only try to load the
791 * ones we have. If an error occurs later, such is life.
793 * Note that we look the kexts up first, so we can avoid spurious
794 * (in this context, anyhow) log messages about kexts not being found.
796 * xxx - do we even need to do this any more? Check if the kernel
797 * xxx - compoonents just load in the regular paths
798 *********************************************************************/
800 KLDBootstrap::loadKernelComponentKexts(void)
802 OSReturn result
= kOSReturnSuccess
; // optimistic
803 OSKext
* theKext
= NULL
; // must release
804 const char ** kextIDPtr
= NULL
; // do not release
806 for (kextIDPtr
= &sKernelComponentNames
[0]; *kextIDPtr
; kextIDPtr
++) {
808 OSSafeReleaseNULL(theKext
);
809 theKext
= OSKext::lookupKextWithIdentifier(*kextIDPtr
);
812 if (kOSReturnSuccess
!= OSKext::loadKextWithIdentifier(
813 *kextIDPtr
, /* allowDefer */ false)) {
815 // xxx - check KextBookkeeping, might be redundant
816 OSKextLog(/* kext */ NULL
,
817 kOSKextLogErrorLevel
|
818 kOSKextLogDirectoryScanFlag
| kOSKextLogKextBookkeepingFlag
,
819 "Failed to initialize kernel component %s.", *kextIDPtr
);
820 result
= kOSReturnError
;
825 OSSafeReleaseNULL(theKext
);
829 /*********************************************************************
830 * Ensure that Kernel External Components are loaded early in boot,
831 * before other kext personalities get sent to the IOCatalogue. These
832 * kexts are treated specially because they may provide the implementation
833 * for kernel-vended KPI, so they must register themselves before
834 * general purpose IOKit probing begins.
835 *********************************************************************/
837 #define COM_APPLE_KEC "com.apple.kec."
840 KLDBootstrap::loadKernelExternalComponents(void)
842 OSDictionary
* extensionsDict
= NULL
; // must release
843 OSCollectionIterator
* keyIterator
= NULL
; // must release
844 OSString
* bundleID
= NULL
; // don't release
845 OSKext
* theKext
= NULL
; // don't release
846 OSBoolean
* isKernelExternalComponent
= NULL
; // don't release
848 OSKextLog(/* kext */ NULL
,
849 kOSKextLogStepLevel
|
851 "Loading Kernel External Components.");
853 extensionsDict
= OSKext::copyKexts();
854 if (!extensionsDict
) {
858 keyIterator
= OSCollectionIterator::withCollection(extensionsDict
);
860 OSKextLog(/* kext */ NULL
,
861 kOSKextLogErrorLevel
|
862 kOSKextLogGeneralFlag
,
863 "Failed to allocate iterator for Kernel External Components.");
867 while ((bundleID
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
869 const char * bundle_id
= bundleID
->getCStringNoCopy();
871 /* Skip extensions whose bundle IDs don't start with "com.apple.kec.".
874 (strncmp(bundle_id
, COM_APPLE_KEC
, CONST_STRLEN(COM_APPLE_KEC
)) != 0)) {
879 theKext
= OSDynamicCast(OSKext
, extensionsDict
->getObject(bundleID
));
884 isKernelExternalComponent
= OSDynamicCast(OSBoolean
,
885 theKext
->getPropertyForHostArch(kAppleKernelExternalComponentKey
));
886 if (isKernelExternalComponent
&& isKernelExternalComponent
->isTrue()) {
887 OSKextLog(/* kext */ NULL
,
888 kOSKextLogStepLevel
|
890 "Loading kernel external component %s.", bundleID
->getCStringNoCopy());
891 OSKext::loadKextWithIdentifier(bundleID
->getCStringNoCopy(),
892 /* allowDefer */ false);
897 OSSafeReleaseNULL(keyIterator
);
898 OSSafeReleaseNULL(extensionsDict
);
903 /*********************************************************************
904 *********************************************************************/
906 KLDBootstrap::readBuiltinPersonalities(void)
908 OSObject
* parsedXML
= NULL
; // must release
909 OSArray
* builtinExtensions
= NULL
; // do not release
910 OSArray
* allPersonalities
= NULL
; // must release
911 OSString
* errorString
= NULL
; // must release
912 kernel_section_t
* infosect
= NULL
; // do not free
913 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
914 unsigned int count
, i
;
916 OSKextLog(/* kext */ NULL
,
917 kOSKextLogStepLevel
|
919 "Reading built-in kernel personalities for I/O Kit drivers.");
921 /* Look in the __BUILTIN __info segment for an array of Info.plist
922 * entries. For each one, extract the personalities dictionary, add
923 * it to our array, then push them all (without matching) to
924 * the IOCatalogue. This can be used to augment the personalities
925 * in gIOKernelConfigTables, especially when linking entire kexts into
926 * the mach_kernel image.
928 infosect
= getsectbyname("__BUILTIN", "__info");
934 parsedXML
= OSUnserializeXML((const char *) (uintptr_t)infosect
->addr
,
937 builtinExtensions
= OSDynamicCast(OSArray
, parsedXML
);
939 if (!builtinExtensions
) {
940 const char * errorCString
= "(unknown error)";
942 if (errorString
&& errorString
->getCStringNoCopy()) {
943 errorCString
= errorString
->getCStringNoCopy();
944 } else if (parsedXML
) {
945 errorCString
= "not an array";
947 OSKextLog(/* kext */ NULL
,
948 kOSKextLogErrorLevel
|
950 "Error unserializing built-in personalities: %s.", errorCString
);
954 // estimate 3 personalities per Info.plist/kext
955 count
= builtinExtensions
->getCount();
956 allPersonalities
= OSArray::withCapacity(count
* 3);
958 for (i
= 0; i
< count
; i
++) {
959 OSDictionary
* infoDict
= NULL
; // do not release
960 OSString
* moduleName
= NULL
; // do not release
961 OSDictionary
* personalities
; // do not release
962 OSString
* personalityName
; // do not release
964 OSSafeReleaseNULL(personalitiesIterator
);
966 infoDict
= OSDynamicCast(OSDictionary
,
967 builtinExtensions
->getObject(i
));
972 moduleName
= OSDynamicCast(OSString
,
973 infoDict
->getObject(kCFBundleIdentifierKey
));
978 OSKextLog(/* kext */ NULL
,
979 kOSKextLogStepLevel
|
981 "Adding personalities for built-in driver %s:",
982 moduleName
->getCStringNoCopy());
984 personalities
= OSDynamicCast(OSDictionary
,
985 infoDict
->getObject("IOKitPersonalities"));
986 if (!personalities
) {
990 personalitiesIterator
= OSCollectionIterator::withCollection(personalities
);
991 if (!personalitiesIterator
) {
992 continue; // xxx - well really, what can we do? should we panic?
995 while ((personalityName
= OSDynamicCast(OSString
,
996 personalitiesIterator
->getNextObject()))) {
998 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
999 personalities
->getObject(personalityName
));
1001 OSKextLog(/* kext */ NULL
,
1002 kOSKextLogDetailLevel
|
1004 "Adding built-in driver personality %s.",
1005 personalityName
->getCStringNoCopy());
1007 if (personality
&& !personality
->getObject(kCFBundleIdentifierKey
)) {
1008 personality
->setObject(kCFBundleIdentifierKey
, moduleName
);
1010 allPersonalities
->setObject(personality
);
1014 gIOCatalogue
->addDrivers(allPersonalities
, false);
1017 OSSafeReleaseNULL(parsedXML
);
1018 OSSafeReleaseNULL(allPersonalities
);
1019 OSSafeReleaseNULL(errorString
);
1020 OSSafeReleaseNULL(personalitiesIterator
);
1025 #pragma mark Bootstrap Functions
1027 /*********************************************************************
1028 * Bootstrap Functions
1029 *********************************************************************/
1030 static void bootstrapRecordStartupExtensions(void)
1032 sBootstrapObject
.readStartupExtensions();
1036 static void bootstrapLoadSecurityExtensions(void)
1038 sBootstrapObject
.loadSecurityExtensions();