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 extern uuid_t kernelcache_uuid
;
38 #include <libkern/version.h>
39 #include <libkern/c++/OSContainers.h>
40 #include <libkern/OSKextLibPrivate.h>
41 #include <libkern/c++/OSKext.h>
42 #include <IOKit/IOLib.h>
43 #include <IOKit/IOService.h>
44 #include <IOKit/IODeviceTreeSupport.h>
45 #include <IOKit/IOCatalogue.h>
48 #define KASLR_KEXT_DEBUG 0
52 #pragma mark Bootstrap Declarations
54 /*********************************************************************
55 * Bootstrap Declarations
57 * The ENTIRE point of the libsa/KLD segment is to isolate bootstrap
58 * code from other parts of the kernel, so function symbols are not
59 * exported; rather pointers to those functions are exported.
61 * xxx - need to think about locking for handling the 'weak' refs.
62 * xxx - do export a non-KLD function that says you've called a
63 * xxx - bootstrap function that has been removed.
65 * ALL call-ins to this segment of the kernel must be done through
66 * exported pointers. The symbols themselves are private and not to
68 *********************************************************************/
70 extern void (*record_startup_extensions_function
)(void);
71 extern void (*load_security_extensions_function
)(void);
74 static void bootstrapRecordStartupExtensions(void);
75 static void bootstrapLoadSecurityExtensions(void);
79 extern "C" bool IORamDiskBSDRoot(void);
85 /*********************************************************************
87 *********************************************************************/
88 #define CONST_STRLEN(str) (sizeof(str) - 1)
91 #pragma mark Kernel Component Kext Identifiers
93 /*********************************************************************
94 * Kernel Component Kext Identifiers
96 * We could have each kernel resource kext automatically "load" as
97 * it's created, but it's nicer to have them listed in kextstat in
98 * the order of this list. We'll walk through this after setting up
99 * all the boot kexts and have them load up.
100 *********************************************************************/
101 static const char * sKernelComponentNames
[] = {
102 // The kexts for these IDs must have a version matching 'osrelease'.
105 "com.apple.kpi.dsep",
106 "com.apple.kpi.iokit",
107 "com.apple.kpi.libkern",
108 "com.apple.kpi.mach",
109 "com.apple.kpi.private",
110 "com.apple.kpi.unsupported",
111 "com.apple.iokit.IONVRAMFamily",
112 "com.apple.driver.AppleNMI",
113 "com.apple.iokit.IOSystemManagementFamily",
114 "com.apple.iokit.ApplePlatformFamily",
118 static int __whereIsAddr(vm_offset_t theAddr
, unsigned long * segSizes
, vm_offset_t
*segAddrs
, int segCount
);
120 #define PLK_SEGMENTS 12
122 static const char * plk_segNames
[] = {
139 #pragma mark KLDBootstrap Class
141 /*********************************************************************
144 * We use a C++ class here so that it can be a friend of OSKext and
145 * get at private stuff. We can't hide the class itself, but we can
146 * hide the instance through which we invoke the functions.
147 *********************************************************************/
149 friend void bootstrapRecordStartupExtensions(void);
150 friend void bootstrapLoadSecurityExtensions(void);
153 void readStartupExtensions(void);
155 void readPrelinkedExtensions(
156 kernel_section_t
* prelinkInfoSect
);
157 void readBooterExtensions(void);
159 OSReturn
loadKernelComponentKexts(void);
160 void loadKernelExternalComponents(void);
161 void readBuiltinPersonalities(void);
163 void loadSecurityExtensions(void);
170 static KLDBootstrap sBootstrapObject
;
172 /*********************************************************************
173 * Set the function pointers for the entry points into the bootstrap
174 * segment upon C++ static constructor invocation.
175 *********************************************************************/
176 KLDBootstrap::KLDBootstrap(void)
178 if (this != &sBootstrapObject
) {
179 panic("Attempt to access bootstrap segment.");
181 record_startup_extensions_function
= &bootstrapRecordStartupExtensions
;
182 load_security_extensions_function
= &bootstrapLoadSecurityExtensions
;
185 /*********************************************************************
186 * Clear the function pointers for the entry points into the bootstrap
187 * segment upon C++ static destructor invocation.
188 *********************************************************************/
189 KLDBootstrap::~KLDBootstrap(void)
191 if (this != &sBootstrapObject
) {
192 panic("Attempt to access bootstrap segment.");
196 record_startup_extensions_function
= 0;
197 load_security_extensions_function
= 0;
200 /*********************************************************************
201 *********************************************************************/
203 KLDBootstrap::readStartupExtensions(void)
205 kernel_section_t
* prelinkInfoSect
= NULL
; // do not free
207 OSKextLog(/* kext */ NULL
,
208 kOSKextLogProgressLevel
|
209 kOSKextLogGeneralFlag
| kOSKextLogDirectoryScanFlag
|
210 kOSKextLogKextBookkeepingFlag
,
211 "Reading startup extensions.");
213 /* If the prelink info segment has a nonzero size, we are prelinked
214 * and won't have any individual kexts or mkexts to read.
215 * Otherwise, we need to read kexts or the mkext from what the booter
218 prelinkInfoSect
= getsectbyname(kPrelinkInfoSegment
, kPrelinkInfoSection
);
219 if (prelinkInfoSect
->size
) {
220 readPrelinkedExtensions(prelinkInfoSect
);
222 readBooterExtensions();
225 loadKernelComponentKexts();
226 loadKernelExternalComponents();
227 readBuiltinPersonalities();
228 OSKext::sendAllKextPersonalitiesToCatalog();
233 typedef struct kaslrPackedOffsets
{
234 uint32_t count
; /* number of offsets */
235 uint32_t offsetsArray
[]; /* offsets to slide */
236 } kaslrPackedOffsets
;
238 /*********************************************************************
239 *********************************************************************/
241 KLDBootstrap::readPrelinkedExtensions(
242 kernel_section_t
* prelinkInfoSect
)
244 OSArray
* infoDictArray
= NULL
; // do not release
245 OSObject
* parsedXML
= NULL
; // must release
246 OSDictionary
* prelinkInfoDict
= NULL
; // do not release
247 OSString
* errorString
= NULL
; // must release
248 OSKext
* theKernel
= NULL
; // must release
250 OSData
* kernelcacheUUID
= NULL
; // do not release
253 kernel_segment_command_t
* prelinkTextSegment
= NULL
; // see code
254 kernel_segment_command_t
* prelinkInfoSegment
= NULL
; // see code
256 /* We make some copies of data, but if anything fails we're basically
257 * going to fail the boot, so these won't be cleaned up on error.
259 void * prelinkData
= NULL
; // see code
260 vm_size_t prelinkLength
= 0;
263 OSDictionary
* infoDict
= NULL
; // do not release
265 IORegistryEntry
* registryRoot
= NULL
; // do not release
266 OSNumber
* prelinkCountObj
= NULL
; // must release
271 bool developerDevice
;
274 OSData
* kaslrOffsets
= NULL
;
275 unsigned long plk_segSizes
[PLK_SEGMENTS
];
276 vm_offset_t plk_segAddrs
[PLK_SEGMENTS
];
278 OSKextLog(/* kext */ NULL
,
279 kOSKextLogProgressLevel
|
280 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
281 "Starting from prelinked kernel.");
283 prelinkTextSegment
= getsegbyname(kPrelinkTextSegment
);
284 if (!prelinkTextSegment
) {
285 OSKextLog(/* kext */ NULL
,
286 kOSKextLogErrorLevel
|
287 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
288 "Can't find prelinked kexts' text segment.");
293 unsigned long scratchSize
;
294 vm_offset_t scratchAddr
;
296 IOLog("kaslr: prelinked kernel address info: \n");
298 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__TEXT", &scratchSize
);
299 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __TEXT \n",
300 (unsigned long)scratchAddr
,
301 (unsigned long)(scratchAddr
+ scratchSize
),
304 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__DATA", &scratchSize
);
305 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __DATA \n",
306 (unsigned long)scratchAddr
,
307 (unsigned long)(scratchAddr
+ scratchSize
),
310 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__LINKEDIT", &scratchSize
);
311 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __LINKEDIT \n",
312 (unsigned long)scratchAddr
,
313 (unsigned long)(scratchAddr
+ scratchSize
),
316 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__KLD", &scratchSize
);
317 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __KLD \n",
318 (unsigned long)scratchAddr
,
319 (unsigned long)(scratchAddr
+ scratchSize
),
322 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__PRELINK_TEXT", &scratchSize
);
323 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_TEXT \n",
324 (unsigned long)scratchAddr
,
325 (unsigned long)(scratchAddr
+ scratchSize
),
328 scratchAddr
= (vm_offset_t
) getsegdatafromheader(&_mh_execute_header
, "__PRELINK_INFO", &scratchSize
);
329 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_INFO \n",
330 (unsigned long)scratchAddr
,
331 (unsigned long)(scratchAddr
+ scratchSize
),
335 prelinkData
= (void *) prelinkTextSegment
->vmaddr
;
336 prelinkLength
= prelinkTextSegment
->vmsize
;
338 /* build arrays of plk info for later use */
339 const char ** segNamePtr
;
341 for (segNamePtr
= &plk_segNames
[0], i
= 0; *segNamePtr
&& i
< PLK_SEGMENTS
; segNamePtr
++, i
++) {
343 plk_segAddrs
[i
] = (vm_offset_t
)getsegdatafromheader(&_mh_execute_header
, *segNamePtr
, &plk_segSizes
[i
]);
347 /* Unserialize the info dictionary from the prelink info section.
349 parsedXML
= OSUnserializeXML((const char *)prelinkInfoSect
->addr
,
352 prelinkInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
354 if (!prelinkInfoDict
) {
355 const char * errorCString
= "(unknown error)";
357 if (errorString
&& errorString
->getCStringNoCopy()) {
358 errorCString
= errorString
->getCStringNoCopy();
359 } else if (parsedXML
) {
360 errorCString
= "not a dictionary";
362 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
363 "Error unserializing prelink plist: %s.", errorCString
);
368 /* Check if we should keep developer kexts around.
369 * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201>
371 developerDevice
= true;
372 PE_parse_boot_argn("developer", &developerDevice
, sizeof(developerDevice
));
374 ramDiskBoot
= IORamDiskBSDRoot();
375 #endif /* NO_KEXTD */
378 /* Copy in the kernelcache UUID */
379 kernelcacheUUID
= OSDynamicCast(OSData
,
380 prelinkInfoDict
->getObject(kPrelinkInfoKCIDKey
));
381 if (!kernelcacheUUID
) {
382 bzero(&kernelcache_uuid
, sizeof(kernelcache_uuid
));
383 } else if (kernelcacheUUID
->getLength() != sizeof(kernelcache_uuid
)) {
384 panic("kernelcacheUUID length is %d, expected %lu", kernelcacheUUID
->getLength(),
385 sizeof(kernelcache_uuid
));
387 memcpy((void *)&kernelcache_uuid
, (const void *)kernelcacheUUID
->getBytesNoCopy(), kernelcacheUUID
->getLength());
389 #endif /* CONFIG_EMBEDDED */
391 infoDictArray
= OSDynamicCast(OSArray
,
392 prelinkInfoDict
->getObject(kPrelinkInfoDictionaryKey
));
393 if (!infoDictArray
) {
394 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
395 "The prelinked kernel has no kext info dictionaries");
399 /* kaslrOffsets are available use them to slide local relocations */
400 kaslrOffsets
= OSDynamicCast(OSData
,
401 prelinkInfoDict
->getObject(kPrelinkLinkKASLROffsetsKey
));
403 /* Create dictionary of excluded kexts
405 #ifndef CONFIG_EMBEDDED
406 OSKext::createExcludeListFromPrelinkInfo(infoDictArray
);
408 /* Create OSKext objects for each info dictionary.
410 for (i
= 0; i
< infoDictArray
->getCount(); ++i
) {
411 infoDict
= OSDynamicCast(OSDictionary
, infoDictArray
->getObject(i
));
413 OSKextLog(/* kext */ NULL
,
414 kOSKextLogErrorLevel
|
415 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
416 "Can't find info dictionary for prelinked kext #%d.", i
);
423 /* If we're not on a developer device, skip and free developer kexts.
425 if (developerDevice
== false) {
426 OSBoolean
*devOnlyBool
= OSDynamicCast(OSBoolean
,
427 infoDict
->getObject(kOSBundleDeveloperOnlyKey
));
428 if (devOnlyBool
== kOSBooleanTrue
) {
433 /* Skip and free kexts that are only needed when booted from a ram disk.
435 if (ramDiskBoot
== false) {
436 OSBoolean
*ramDiskOnlyBool
= OSDynamicCast(OSBoolean
,
437 infoDict
->getObject(kOSBundleRamDiskOnlyKey
));
438 if (ramDiskOnlyBool
== kOSBooleanTrue
) {
443 if (dontLoad
== true) {
444 OSString
*bundleID
= OSDynamicCast(OSString
,
445 infoDict
->getObject(kCFBundleIdentifierKey
));
447 OSKextLog(NULL
, kOSKextLogWarningLevel
| kOSKextLogGeneralFlag
,
448 "Kext %s not loading.", bundleID
->getCStringNoCopy());
451 OSNumber
*addressNum
= OSDynamicCast(OSNumber
,
452 infoDict
->getObject(kPrelinkExecutableLoadKey
));
453 OSNumber
*lengthNum
= OSDynamicCast(OSNumber
,
454 infoDict
->getObject(kPrelinkExecutableSizeKey
));
455 if (addressNum
&& lengthNum
) {
456 #if __arm__ || __arm64__
457 vm_offset_t data
= (vm_offset_t
) ((addressNum
->unsigned64BitValue()) + vm_kernel_slide
);
458 vm_size_t length
= (vm_size_t
) (lengthNum
->unsigned32BitValue());
459 ml_static_mfree(data
, length
);
461 #error Pick the right way to free prelinked data on this arch
465 infoDictArray
->removeObject(i
--);
468 #endif /* NO_KEXTD */
470 /* Create the kext for the entry, then release it, because the
471 * kext system keeps them around until explicitly removed.
472 * Any creation/registration failures are already logged for us.
474 OSKext
* newKext
= OSKext::withPrelinkedInfoDict(infoDict
, (kaslrOffsets
? TRUE
: FALSE
));
475 OSSafeReleaseNULL(newKext
);
478 /* slide kxld relocations */
479 if (kaslrOffsets
&& vm_kernel_slide
> 0) {
480 int slidKextAddrCount
= 0;
481 int badSlideAddr
= 0;
482 int badSlideTarget
= 0;
484 const kaslrPackedOffsets
* myOffsets
= NULL
;
485 myOffsets
= (const kaslrPackedOffsets
*) kaslrOffsets
->getBytesNoCopy();
487 for (uint32_t j
= 0; j
< myOffsets
->count
; j
++) {
489 uint64_t slideOffset
= (uint64_t) myOffsets
->offsetsArray
[j
];
490 uintptr_t * slideAddr
= (uintptr_t *) ((uint64_t)prelinkData
+ slideOffset
);
491 int slideAddrSegIndex
= -1;
492 int addrToSlideSegIndex
= -1;
494 slideAddrSegIndex
= __whereIsAddr( (vm_offset_t
)slideAddr
, &plk_segSizes
[0], &plk_segAddrs
[0], PLK_SEGMENTS
);
495 if (slideAddrSegIndex
>= 0) {
496 addrToSlideSegIndex
= __whereIsAddr( (vm_offset_t
)(*slideAddr
+ vm_kernel_slide
), &plk_segSizes
[0], &plk_segAddrs
[0], PLK_SEGMENTS
);
497 if (addrToSlideSegIndex
< 0) {
508 *(slideAddr
) += vm_kernel_slide
;
511 /* All kexts are now slid, set VM protections for them */
512 OSKext::setAllVMAttributes();
515 /* Store the number of prelinked kexts in the registry so we can tell
516 * when the system has been started from a prelinked kernel.
518 registryRoot
= IORegistryEntry::getRegistryRoot();
519 assert(registryRoot
);
521 prelinkCountObj
= OSNumber::withNumber(
522 (unsigned long long)infoDictArray
->getCount(),
523 8 * sizeof(uint32_t));
524 assert(prelinkCountObj
);
525 if (prelinkCountObj
) {
526 registryRoot
->setProperty(kOSPrelinkKextCountKey
, prelinkCountObj
);
529 OSKextLog(/* kext */ NULL
,
530 kOSKextLogProgressLevel
|
531 kOSKextLogGeneralFlag
| kOSKextLogKextBookkeepingFlag
|
532 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
533 "%u prelinked kexts",
534 infoDictArray
->getCount());
536 #if CONFIG_KEXT_BASEMENT
537 /* On CONFIG_KEXT_BASEMENT systems, kexts are copied to their own
538 * special VM region during OSKext init time, so we can free the whole
541 ml_static_mfree((vm_offset_t
) prelinkData
, prelinkLength
);
542 #endif /* __x86_64__ */
544 /* Free the prelink info segment, we're done with it.
546 prelinkInfoSegment
= getsegbyname(kPrelinkInfoSegment
);
547 if (prelinkInfoSegment
) {
548 ml_static_mfree((vm_offset_t
)prelinkInfoSegment
->vmaddr
,
549 (vm_size_t
)prelinkInfoSegment
->vmsize
);
553 OSSafeReleaseNULL(errorString
);
554 OSSafeReleaseNULL(parsedXML
);
555 OSSafeReleaseNULL(theKernel
);
556 OSSafeReleaseNULL(prelinkCountObj
);
560 static int __whereIsAddr(vm_offset_t theAddr
, unsigned long * segSizes
, vm_offset_t
*segAddrs
, int segCount
)
564 for (i
= 0; i
< segCount
; i
++) {
565 vm_offset_t myAddr
= *(segAddrs
+ i
);
566 unsigned long mySize
= *(segSizes
+ i
);
568 if (theAddr
>= myAddr
&& theAddr
< (myAddr
+ mySize
)) {
577 /*********************************************************************
578 *********************************************************************/
579 #define BOOTER_KEXT_PREFIX "Driver-"
581 typedef struct _DeviceTreeBuffer
{
587 KLDBootstrap::readBooterExtensions(void)
589 IORegistryEntry
* booterMemoryMap
= NULL
; // must release
590 OSDictionary
* propertyDict
= NULL
; // must release
591 OSCollectionIterator
* keyIterator
= NULL
; // must release
592 OSString
* deviceTreeName
= NULL
; // do not release
594 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
; // do not free
595 char * booterDataPtr
= NULL
; // do not free
596 OSData
* booterData
= NULL
; // must release
598 OSKext
* aKext
= NULL
; // must release
600 OSKextLog(/* kext */ NULL
,
601 kOSKextLogProgressLevel
|
602 kOSKextLogDirectoryScanFlag
| kOSKextLogKextBookkeepingFlag
,
603 "Reading startup extensions from booter memory.");
605 booterMemoryMap
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
);
607 if (!booterMemoryMap
) {
608 OSKextLog(/* kext */ NULL
,
609 kOSKextLogErrorLevel
|
610 kOSKextLogGeneralFlag
| kOSKextLogDirectoryScanFlag
,
611 "Can't read booter memory map.");
615 propertyDict
= booterMemoryMap
->dictionaryWithProperties();
617 OSKextLog(/* kext */ NULL
,
618 kOSKextLogErrorLevel
|
619 kOSKextLogDirectoryScanFlag
,
620 "Can't get property dictionary from memory map.");
624 keyIterator
= OSCollectionIterator::withCollection(propertyDict
);
626 OSKextLog(/* kext */ NULL
,
627 kOSKextLogErrorLevel
|
628 kOSKextLogGeneralFlag
,
629 "Can't allocate iterator for driver images.");
633 /* Create dictionary of excluded kexts
635 #ifndef CONFIG_EMBEDDED
636 OSKext::createExcludeListFromBooterData(propertyDict
, keyIterator
);
638 keyIterator
->reset();
640 while ( ( deviceTreeName
=
641 OSDynamicCast(OSString
, keyIterator
->getNextObject() ))) {
643 const char * devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
644 OSData
* deviceTreeEntry
= OSDynamicCast(OSData
,
645 propertyDict
->getObject(deviceTreeName
));
647 /* Clear out the booterData from the prior iteration.
649 OSSafeReleaseNULL(booterData
);
651 /* If there is no entry for the name, we can't do much with it. */
652 if (!deviceTreeEntry
) {
656 /* Make sure it is a kext */
657 if (strncmp(devTreeNameCString
,
659 CONST_STRLEN(BOOTER_KEXT_PREFIX
))) {
663 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
664 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
665 if (!deviceTreeBuffer
) {
666 /* We can't get to the data, so we can't do anything,
667 * not even free it from physical memory (if it's there).
669 OSKextLog(/* kext */ NULL
,
670 kOSKextLogErrorLevel
|
671 kOSKextLogDirectoryScanFlag
,
672 "Device tree entry %s has NULL pointer.",
674 goto finish
; // xxx - continue, panic?
677 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
678 if (!booterDataPtr
) {
679 OSKextLog(/* kext */ NULL
,
680 kOSKextLogErrorLevel
|
681 kOSKextLogDirectoryScanFlag
,
682 "Can't get virtual address for device tree entry %s.",
687 /* Wrap the booter data buffer in an OSData and set a dealloc function
688 * so it will take care of the physical memory when freed. Kexts will
689 * retain the booterData for as long as they need it. Remove the entry
690 * from the booter memory map after this is done.
692 booterData
= OSData::withBytesNoCopy(booterDataPtr
,
693 deviceTreeBuffer
->length
);
695 OSKextLog(/* kext */ NULL
,
696 kOSKextLogErrorLevel
|
697 kOSKextLogGeneralFlag
,
698 "Error - Can't allocate OSData wrapper for device tree entry %s.",
702 booterData
->setDeallocFunction(osdata_phys_free
);
704 /* Create the kext for the entry, then release it, because the
705 * kext system keeps them around until explicitly removed.
706 * Any creation/registration failures are already logged for us.
708 OSKext
* newKext
= OSKext::withBooterData(deviceTreeName
, booterData
);
709 OSSafeReleaseNULL(newKext
);
711 booterMemoryMap
->removeProperty(deviceTreeName
);
713 } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */
717 OSSafeReleaseNULL(booterMemoryMap
);
718 OSSafeReleaseNULL(propertyDict
);
719 OSSafeReleaseNULL(keyIterator
);
720 OSSafeReleaseNULL(booterData
);
721 OSSafeReleaseNULL(aKext
);
725 /*********************************************************************
726 *********************************************************************/
727 #define COM_APPLE "com.apple."
730 KLDBootstrap::loadSecurityExtensions(void)
732 OSDictionary
* extensionsDict
= NULL
; // must release
733 OSCollectionIterator
* keyIterator
= NULL
; // must release
734 OSString
* bundleID
= NULL
; // don't release
735 OSKext
* theKext
= NULL
; // don't release
736 OSBoolean
* isSecurityKext
= NULL
; // don't release
738 OSKextLog(/* kext */ NULL
,
739 kOSKextLogStepLevel
|
741 "Loading security extensions.");
743 extensionsDict
= OSKext::copyKexts();
744 if (!extensionsDict
) {
748 keyIterator
= OSCollectionIterator::withCollection(extensionsDict
);
750 OSKextLog(/* kext */ NULL
,
751 kOSKextLogErrorLevel
|
752 kOSKextLogGeneralFlag
,
753 "Failed to allocate iterator for security extensions.");
757 while ((bundleID
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
759 const char * bundle_id
= bundleID
->getCStringNoCopy();
761 /* Skip extensions whose bundle IDs don't start with "com.apple.".
764 (strncmp(bundle_id
, COM_APPLE
, CONST_STRLEN(COM_APPLE
)) != 0)) {
769 theKext
= OSDynamicCast(OSKext
, extensionsDict
->getObject(bundleID
));
774 isSecurityKext
= OSDynamicCast(OSBoolean
,
775 theKext
->getPropertyForHostArch(kAppleSecurityExtensionKey
));
776 if (isSecurityKext
&& isSecurityKext
->isTrue()) {
777 OSKextLog(/* kext */ NULL
,
778 kOSKextLogStepLevel
|
780 "Loading security extension %s.", bundleID
->getCStringNoCopy());
781 OSKext::loadKextWithIdentifier(bundleID
->getCStringNoCopy(),
782 /* allowDefer */ false);
787 OSSafeReleaseNULL(keyIterator
);
788 OSSafeReleaseNULL(extensionsDict
);
793 /*********************************************************************
794 * We used to require that all listed kernel components load, but
795 * nowadays we can get them from userland so we only try to load the
796 * ones we have. If an error occurs later, such is life.
798 * Note that we look the kexts up first, so we can avoid spurious
799 * (in this context, anyhow) log messages about kexts not being found.
801 * xxx - do we even need to do this any more? Check if the kernel
802 * xxx - compoonents just load in the regular paths
803 *********************************************************************/
805 KLDBootstrap::loadKernelComponentKexts(void)
807 OSReturn result
= kOSReturnSuccess
; // optimistic
808 OSKext
* theKext
= NULL
; // must release
809 const char ** kextIDPtr
= NULL
; // do not release
811 for (kextIDPtr
= &sKernelComponentNames
[0]; *kextIDPtr
; kextIDPtr
++) {
813 OSSafeReleaseNULL(theKext
);
814 theKext
= OSKext::lookupKextWithIdentifier(*kextIDPtr
);
817 if (kOSReturnSuccess
!= OSKext::loadKextWithIdentifier(
818 *kextIDPtr
, /* allowDefer */ false)) {
820 // xxx - check KextBookkeeping, might be redundant
821 OSKextLog(/* kext */ NULL
,
822 kOSKextLogErrorLevel
|
823 kOSKextLogDirectoryScanFlag
| kOSKextLogKextBookkeepingFlag
,
824 "Failed to initialize kernel component %s.", *kextIDPtr
);
825 result
= kOSReturnError
;
830 OSSafeReleaseNULL(theKext
);
834 /*********************************************************************
835 * Ensure that Kernel External Components are loaded early in boot,
836 * before other kext personalities get sent to the IOCatalogue. These
837 * kexts are treated specially because they may provide the implementation
838 * for kernel-vended KPI, so they must register themselves before
839 * general purpose IOKit probing begins.
840 *********************************************************************/
842 #define COM_APPLE_KEC "com.apple.kec."
845 KLDBootstrap::loadKernelExternalComponents(void)
847 OSDictionary
* extensionsDict
= NULL
; // must release
848 OSCollectionIterator
* keyIterator
= NULL
; // must release
849 OSString
* bundleID
= NULL
; // don't release
850 OSKext
* theKext
= NULL
; // don't release
851 OSBoolean
* isKernelExternalComponent
= NULL
; // don't release
853 OSKextLog(/* kext */ NULL
,
854 kOSKextLogStepLevel
|
856 "Loading Kernel External Components.");
858 extensionsDict
= OSKext::copyKexts();
859 if (!extensionsDict
) {
863 keyIterator
= OSCollectionIterator::withCollection(extensionsDict
);
865 OSKextLog(/* kext */ NULL
,
866 kOSKextLogErrorLevel
|
867 kOSKextLogGeneralFlag
,
868 "Failed to allocate iterator for Kernel External Components.");
872 while ((bundleID
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
874 const char * bundle_id
= bundleID
->getCStringNoCopy();
876 /* Skip extensions whose bundle IDs don't start with "com.apple.kec.".
879 (strncmp(bundle_id
, COM_APPLE_KEC
, CONST_STRLEN(COM_APPLE_KEC
)) != 0)) {
884 theKext
= OSDynamicCast(OSKext
, extensionsDict
->getObject(bundleID
));
889 isKernelExternalComponent
= OSDynamicCast(OSBoolean
,
890 theKext
->getPropertyForHostArch(kAppleKernelExternalComponentKey
));
891 if (isKernelExternalComponent
&& isKernelExternalComponent
->isTrue()) {
892 OSKextLog(/* kext */ NULL
,
893 kOSKextLogStepLevel
|
895 "Loading kernel external component %s.", bundleID
->getCStringNoCopy());
896 OSKext::loadKextWithIdentifier(bundleID
->getCStringNoCopy(),
897 /* allowDefer */ false);
902 OSSafeReleaseNULL(keyIterator
);
903 OSSafeReleaseNULL(extensionsDict
);
908 /*********************************************************************
909 *********************************************************************/
911 KLDBootstrap::readBuiltinPersonalities(void)
913 OSObject
* parsedXML
= NULL
; // must release
914 OSArray
* builtinExtensions
= NULL
; // do not release
915 OSArray
* allPersonalities
= NULL
; // must release
916 OSString
* errorString
= NULL
; // must release
917 kernel_section_t
* infosect
= NULL
; // do not free
918 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
919 unsigned int count
, i
;
921 OSKextLog(/* kext */ NULL
,
922 kOSKextLogStepLevel
|
924 "Reading built-in kernel personalities for I/O Kit drivers.");
926 /* Look in the __BUILTIN __info segment for an array of Info.plist
927 * entries. For each one, extract the personalities dictionary, add
928 * it to our array, then push them all (without matching) to
929 * the IOCatalogue. This can be used to augment the personalities
930 * in gIOKernelConfigTables, especially when linking entire kexts into
931 * the mach_kernel image.
933 infosect
= getsectbyname("__BUILTIN", "__info");
939 parsedXML
= OSUnserializeXML((const char *) (uintptr_t)infosect
->addr
,
942 builtinExtensions
= OSDynamicCast(OSArray
, parsedXML
);
944 if (!builtinExtensions
) {
945 const char * errorCString
= "(unknown error)";
947 if (errorString
&& errorString
->getCStringNoCopy()) {
948 errorCString
= errorString
->getCStringNoCopy();
949 } else if (parsedXML
) {
950 errorCString
= "not an array";
952 OSKextLog(/* kext */ NULL
,
953 kOSKextLogErrorLevel
|
955 "Error unserializing built-in personalities: %s.", errorCString
);
959 // estimate 3 personalities per Info.plist/kext
960 count
= builtinExtensions
->getCount();
961 allPersonalities
= OSArray::withCapacity(count
* 3);
963 for (i
= 0; i
< count
; i
++) {
964 OSDictionary
* infoDict
= NULL
; // do not release
965 OSString
* moduleName
= NULL
; // do not release
966 OSDictionary
* personalities
; // do not release
967 OSString
* personalityName
; // do not release
969 OSSafeReleaseNULL(personalitiesIterator
);
971 infoDict
= OSDynamicCast(OSDictionary
,
972 builtinExtensions
->getObject(i
));
977 moduleName
= OSDynamicCast(OSString
,
978 infoDict
->getObject(kCFBundleIdentifierKey
));
983 OSKextLog(/* kext */ NULL
,
984 kOSKextLogStepLevel
|
986 "Adding personalities for built-in driver %s:",
987 moduleName
->getCStringNoCopy());
989 personalities
= OSDynamicCast(OSDictionary
,
990 infoDict
->getObject("IOKitPersonalities"));
991 if (!personalities
) {
995 personalitiesIterator
= OSCollectionIterator::withCollection(personalities
);
996 if (!personalitiesIterator
) {
997 continue; // xxx - well really, what can we do? should we panic?
1000 while ((personalityName
= OSDynamicCast(OSString
,
1001 personalitiesIterator
->getNextObject()))) {
1003 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
1004 personalities
->getObject(personalityName
));
1006 OSKextLog(/* kext */ NULL
,
1007 kOSKextLogDetailLevel
|
1009 "Adding built-in driver personality %s.",
1010 personalityName
->getCStringNoCopy());
1012 if (personality
&& !personality
->getObject(kCFBundleIdentifierKey
)) {
1013 personality
->setObject(kCFBundleIdentifierKey
, moduleName
);
1015 allPersonalities
->setObject(personality
);
1019 gIOCatalogue
->addDrivers(allPersonalities
, false);
1022 OSSafeReleaseNULL(parsedXML
);
1023 OSSafeReleaseNULL(allPersonalities
);
1024 OSSafeReleaseNULL(errorString
);
1025 OSSafeReleaseNULL(personalitiesIterator
);
1030 #pragma mark Bootstrap Functions
1032 /*********************************************************************
1033 * Bootstrap Functions
1034 *********************************************************************/
1035 static void bootstrapRecordStartupExtensions(void)
1037 sBootstrapObject
.readStartupExtensions();
1041 static void bootstrapLoadSecurityExtensions(void)
1043 sBootstrapObject
.loadSecurityExtensions();