2 * Copyright (c) 2000 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/IORegistryEntry.h>
40 #include <IOKit/IODeviceTreeSupport.h>
41 #include <IOKit/IOCatalogue.h>
44 #pragma mark Bootstrap Declarations
46 /*********************************************************************
47 * Bootstrap Declarations
49 * The ENTIRE point of the libsa/KLD segment is to isolate bootstrap
50 * code from other parts of the kernel, so function symbols are not
51 * exported; rather pointers to those functions are exported.
53 * xxx - need to think about locking for handling the 'weak' refs.
54 * xxx - do export a non-KLD function that says you've called a
55 * xxx - bootstrap function that has been removed.
57 * ALL call-ins to this segment of the kernel must be done through
58 * exported pointers. The symbols themselves are private and not to
60 *********************************************************************/
62 extern void (*record_startup_extensions_function
)(void);
63 extern void (*load_security_extensions_function
)(void);
66 static void bootstrapRecordStartupExtensions(void);
67 static void bootstrapLoadSecurityExtensions(void);
72 /*********************************************************************
74 *********************************************************************/
75 #define CONST_STRLEN(str) (sizeof(str) - 1)
78 #pragma mark Kernel Component Kext Identifiers
80 /*********************************************************************
81 * Kernel Component Kext Identifiers
83 * We could have each kernel resource kext automatically "load" as
84 * it's created, but it's nicer to have them listed in kextstat in
85 * the order of this list. We'll walk through this after setting up
86 * all the boot kexts and have them load up.
87 *********************************************************************/
88 static const char * sKernelComponentNames
[] = {
89 // The kexts for these IDs must have a version matching 'osrelease'.
93 "com.apple.kpi.iokit",
94 "com.apple.kpi.libkern",
96 "com.apple.kpi.private",
97 "com.apple.kpi.unsupported",
98 "com.apple.iokit.IONVRAMFamily",
99 "com.apple.driver.AppleNMI",
100 "com.apple.iokit.IOSystemManagementFamily",
101 "com.apple.iokit.ApplePlatformFamily",
103 #if defined(__ppc__) || defined(__i386__) || defined(__arm__)
104 /* These ones are not supported on x86_64 or any newer platforms.
105 * They must be version 7.9.9; check by "com.apple.kernel.", with
106 * the trailing period; "com.apple.kernel" always represents the
107 * current kernel version.
109 "com.apple.kernel.6.0",
110 "com.apple.kernel.bsd",
111 "com.apple.kernel.iokit",
112 "com.apple.kernel.libkern",
113 "com.apple.kernel.mach",
120 #pragma mark KLDBootstrap Class
122 /*********************************************************************
125 * We use a C++ class here so that it can be a friend of OSKext and
126 * get at private stuff. We can't hide the class itself, but we can
127 * hide the instance through which we invoke the functions.
128 *********************************************************************/
130 friend void bootstrapRecordStartupExtensions(void);
131 friend void bootstrapLoadSecurityExtensions(void);
134 void readStartupExtensions(void);
136 void readPrelinkedExtensions(
137 kernel_section_t
* prelinkInfoSect
);
138 void readBooterExtensions(void);
139 OSReturn
readMkextExtensions(
140 OSString
* deviceTreeName
,
141 OSData
* deviceTreeData
);
143 OSReturn
loadKernelComponentKexts(void);
144 void readBuiltinPersonalities(void);
146 void loadSecurityExtensions(void);
153 static KLDBootstrap sBootstrapObject
;
155 /*********************************************************************
156 * Set the function pointers for the entry points into the bootstrap
157 * segment upon C++ static constructor invocation.
158 *********************************************************************/
159 KLDBootstrap::KLDBootstrap(void)
161 if (this != &sBootstrapObject
) {
162 panic("Attempt to access bootstrap segment.");
164 record_startup_extensions_function
= &bootstrapRecordStartupExtensions
;
165 load_security_extensions_function
= &bootstrapLoadSecurityExtensions
;
166 OSKext::initialize();
169 /*********************************************************************
170 * Clear the function pointers for the entry points into the bootstrap
171 * segment upon C++ static destructor invocation.
172 *********************************************************************/
173 KLDBootstrap::~KLDBootstrap(void)
175 if (this != &sBootstrapObject
) {
176 panic("Attempt to access bootstrap segment.");
178 record_startup_extensions_function
= 0;
179 load_security_extensions_function
= 0;
182 /*********************************************************************
183 *********************************************************************/
185 KLDBootstrap::readStartupExtensions(void)
187 kernel_section_t
* prelinkInfoSect
= NULL
; // do not free
189 OSKextLog(/* kext */ NULL
,
190 kOSKextLogProgressLevel
|
191 kOSKextLogGeneralFlag
| kOSKextLogDirectoryScanFlag
|
192 kOSKextLogKextBookkeepingFlag
,
193 "Reading startup extensions.");
195 /* If the prelink info segment has a nonzero size, we are prelinked
196 * and won't have any individual kexts or mkexts to read.
197 * Otherwise, we need to read kexts or the mkext from what the booter
200 prelinkInfoSect
= getsectbyname(kPrelinkInfoSegment
, kPrelinkInfoSection
);
201 if (prelinkInfoSect
->size
) {
202 readPrelinkedExtensions(prelinkInfoSect
);
204 readBooterExtensions();
207 loadKernelComponentKexts();
208 readBuiltinPersonalities();
209 OSKext::sendAllKextPersonalitiesToCatalog();
214 /*********************************************************************
215 *********************************************************************/
217 KLDBootstrap::readPrelinkedExtensions(
218 kernel_section_t
* prelinkInfoSect
)
220 OSArray
* infoDictArray
= NULL
; // do not release
221 OSArray
* personalitiesArray
= NULL
; // do not release
222 OSObject
* parsedXML
= NULL
; // must release
223 OSDictionary
* prelinkInfoDict
= NULL
; // do not release
224 OSString
* errorString
= NULL
; // must release
225 OSKext
* theKernel
= NULL
; // must release
228 kernel_section_t
* kernelLinkStateSection
= NULL
; // see code
230 kernel_segment_command_t
* prelinkLinkStateSegment
= NULL
; // see code
231 kernel_segment_command_t
* prelinkTextSegment
= NULL
; // see code
232 kernel_segment_command_t
* prelinkInfoSegment
= NULL
; // see code
234 /* We make some copies of data, but if anything fails we're basically
235 * going to fail the boot, so these won't be cleaned up on error.
237 void * prelinkData
= NULL
; // see code
238 void * prelinkCopy
= NULL
; // see code
239 vm_size_t prelinkLength
= 0;
240 #if !__LP64__ && !defined(__arm__)
241 vm_map_offset_t prelinkDataMapOffset
= 0;
244 kern_return_t mem_result
= KERN_SUCCESS
;
246 OSDictionary
* infoDict
= NULL
; // do not release
248 IORegistryEntry
* registryRoot
= NULL
; // do not release
249 OSNumber
* prelinkCountObj
= NULL
; // must release
253 OSKextLog(/* kext */ NULL
,
254 kOSKextLogProgressLevel
|
255 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
256 "Starting from prelinked kernel.");
259 * Wrap the kernel link state in-place in an OSData.
260 * This is unnecessary (and the link state may not be present) if the kernel
261 * does not have kxld support because this information is only used for
265 kernelLinkStateSection
= getsectbyname(kPrelinkLinkStateSegment
,
266 kPrelinkKernelLinkStateSection
);
267 if (!kernelLinkStateSection
) {
268 OSKextLog(/* kext */ NULL
,
269 kOSKextLogErrorLevel
|
270 kOSKextLogArchiveFlag
,
271 "Can't find prelinked kernel link state.");
275 theKernel
= OSKext::lookupKextWithIdentifier(kOSKextKernelIdentifier
);
277 OSKextLog(/* kext */ NULL
,
278 kOSKextLogErrorLevel
|
279 kOSKextLogArchiveFlag
,
280 "Can't find kernel kext object in prelinked kernel.");
284 prelinkData
= (void *) kernelLinkStateSection
->addr
;
285 prelinkLength
= kernelLinkStateSection
->size
;
287 mem_result
= kmem_alloc_pageable(kernel_map
,
288 (vm_offset_t
*) &prelinkCopy
, prelinkLength
);
289 if (mem_result
!= KERN_SUCCESS
) {
290 OSKextLog(/* kext */ NULL
,
291 kOSKextLogErrorLevel
|
292 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
293 "Can't copy prelinked kernel link state.");
296 memcpy(prelinkCopy
, prelinkData
, prelinkLength
);
298 theKernel
->linkState
= OSData::withBytesNoCopy(prelinkCopy
, prelinkLength
);
299 if (!theKernel
->linkState
) {
300 OSKextLog(/* kext */ NULL
,
301 kOSKextLogErrorLevel
|
302 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
303 "Can't create prelinked kernel link state wrapper.");
306 theKernel
->linkState
->setDeallocFunction(osdata_kmem_free
);
309 prelinkTextSegment
= getsegbyname(kPrelinkTextSegment
);
310 if (!prelinkTextSegment
) {
311 OSKextLog(/* kext */ NULL
,
312 kOSKextLogErrorLevel
|
313 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
314 "Can't find prelinked kexts' text segment.");
318 prelinkData
= (void *) prelinkTextSegment
->vmaddr
;
319 prelinkLength
= prelinkTextSegment
->vmsize
;
322 /* To enable paging and write/execute protections on the kext
323 * executables, we need to copy them out of the booter-created
324 * memory, reallocate that space with VM, then prelinkCopy them back in.
325 * This isn't necessary on LP64 because kexts have their own VM
326 * region on that architecture model.
329 mem_result
= kmem_alloc(kernel_map
, (vm_offset_t
*)&prelinkCopy
,
331 if (mem_result
!= KERN_SUCCESS
) {
332 OSKextLog(/* kext */ NULL
,
333 kOSKextLogErrorLevel
|
334 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
335 "Can't copy prelinked kexts' text for VM reassign.");
341 memcpy(prelinkCopy
, prelinkData
, prelinkLength
);
343 /* Dump the booter memory.
345 ml_static_mfree((vm_offset_t
)prelinkData
, prelinkLength
);
347 /* Set up the VM region.
349 prelinkDataMapOffset
= (vm_map_offset_t
)(uintptr_t)prelinkData
;
350 mem_result
= vm_map_enter_mem_object(
352 &prelinkDataMapOffset
,
353 prelinkLength
, /* mask */ 0,
354 VM_FLAGS_FIXED
| VM_FLAGS_OVERWRITE
,
356 (vm_object_offset_t
) 0,
358 /* cur_protection */ VM_PROT_ALL
,
359 /* max_protection */ VM_PROT_ALL
,
360 /* inheritance */ VM_INHERIT_DEFAULT
);
361 if ((mem_result
!= KERN_SUCCESS
) ||
362 (prelinkTextSegment
->vmaddr
!= prelinkDataMapOffset
))
364 OSKextLog(/* kext */ NULL
,
365 kOSKextLogErrorLevel
|
366 kOSKextLogGeneralFlag
| kOSKextLogArchiveFlag
,
367 "Can't create kexts' text VM entry at 0x%llx, length 0x%x (error 0x%x).",
368 (unsigned long long) prelinkDataMapOffset
, prelinkLength
, mem_result
);
371 prelinkData
= (void *)(uintptr_t)prelinkDataMapOffset
;
375 memcpy(prelinkData
, prelinkCopy
, prelinkLength
);
377 kmem_free(kernel_map
, (vm_offset_t
)prelinkCopy
, prelinkLength
);
378 #endif /* !__LP64__ */
380 /* Unserialize the info dictionary from the prelink info section.
382 parsedXML
= OSUnserializeXML((const char *)prelinkInfoSect
->addr
,
385 prelinkInfoDict
= OSDynamicCast(OSDictionary
, parsedXML
);
387 if (!prelinkInfoDict
) {
388 const char * errorCString
= "(unknown error)";
390 if (errorString
&& errorString
->getCStringNoCopy()) {
391 errorCString
= errorString
->getCStringNoCopy();
392 } else if (parsedXML
) {
393 errorCString
= "not a dictionary";
395 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
396 "Error unserializing prelink plist: %s.", errorCString
);
400 infoDictArray
= OSDynamicCast(OSArray
,
401 prelinkInfoDict
->getObject(kPrelinkInfoDictionaryKey
));
402 if (!infoDictArray
) {
403 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
404 "The prelinked kernel has no kext info dictionaries");
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
);
420 /* Create the kext for the entry, then release it, because the
421 * kext system keeps them around until explicitly removed.
422 * Any creation/registration failures are already logged for us.
424 OSKext
* newKext
= OSKext::withPrelinkedInfoDict(infoDict
);
425 OSSafeReleaseNULL(newKext
);
428 /* Get all of the personalities for kexts that were not prelinked and
429 * add them to the catalogue.
431 personalitiesArray
= OSDynamicCast(OSArray
,
432 prelinkInfoDict
->getObject(kPrelinkPersonalitiesKey
));
433 if (!personalitiesArray
) {
434 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
435 "The prelinked kernel has no personalities array");
439 if (personalitiesArray
->getCount()) {
440 gIOCatalogue
->addDrivers(personalitiesArray
);
443 /* Store the number of prelinked kexts in the registry so we can tell
444 * when the system has been started from a prelinked kernel.
446 registryRoot
= IORegistryEntry::getRegistryRoot();
447 assert(registryRoot
);
449 prelinkCountObj
= OSNumber::withNumber(
450 (unsigned long long)infoDictArray
->getCount(),
451 8 * sizeof(uint32_t));
452 assert(prelinkCountObj
);
453 if (prelinkCountObj
) {
454 registryRoot
->setProperty(kOSPrelinkKextCountKey
, prelinkCountObj
);
457 OSSafeReleaseNULL(prelinkCountObj
);
458 prelinkCountObj
= OSNumber::withNumber(
459 (unsigned long long)personalitiesArray
->getCount(),
460 8 * sizeof(uint32_t));
461 assert(prelinkCountObj
);
462 if (prelinkCountObj
) {
463 registryRoot
->setProperty(kOSPrelinkPersonalityCountKey
, prelinkCountObj
);
466 OSKextLog(/* kext */ NULL
,
467 kOSKextLogProgressLevel
|
468 kOSKextLogGeneralFlag
| kOSKextLogKextBookkeepingFlag
|
469 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
470 "%u prelinked kexts, and %u additional personalities.",
471 infoDictArray
->getCount(), personalitiesArray
->getCount());
474 /* On LP64 systems, kexts are copied to their own special VM region
475 * during OSKext init time, so we can free the whole segment now.
477 ml_static_mfree((vm_offset_t
) prelinkData
, prelinkLength
);
478 #endif /* __LP64__ */
480 /* Free the link state segment, kexts have copied out what they need.
482 prelinkLinkStateSegment
= getsegbyname(kPrelinkLinkStateSegment
);
483 if (prelinkLinkStateSegment
) {
484 ml_static_mfree((vm_offset_t
)prelinkLinkStateSegment
->vmaddr
,
485 (vm_size_t
)prelinkLinkStateSegment
->vmsize
);
488 /* Free the prelink info segment, we're done with it.
490 prelinkInfoSegment
= getsegbyname(kPrelinkInfoSegment
);
491 if (prelinkInfoSegment
) {
492 ml_static_mfree((vm_offset_t
)prelinkInfoSegment
->vmaddr
,
493 (vm_size_t
)prelinkInfoSegment
->vmsize
);
497 OSSafeRelease(errorString
);
498 OSSafeRelease(parsedXML
);
499 OSSafeRelease(theKernel
);
500 OSSafeRelease(prelinkCountObj
);
504 /*********************************************************************
505 *********************************************************************/
506 #define BOOTER_KEXT_PREFIX "Driver-"
507 #define BOOTER_MKEXT_PREFIX "DriversPackage-"
509 typedef struct _DeviceTreeBuffer
{
515 KLDBootstrap::readBooterExtensions(void)
517 IORegistryEntry
* booterMemoryMap
= NULL
; // must release
518 OSDictionary
* propertyDict
= NULL
; // must release
519 OSCollectionIterator
* keyIterator
= NULL
; // must release
520 OSString
* deviceTreeName
= NULL
; // do not release
522 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
; // do not free
523 char * booterDataPtr
= NULL
; // do not free
524 OSData
* booterData
= NULL
; // must release
526 OSKext
* aKext
= NULL
; // must release
528 OSKextLog(/* kext */ NULL
,
529 kOSKextLogProgressLevel
|
530 kOSKextLogDirectoryScanFlag
| kOSKextLogKextBookkeepingFlag
,
531 "Reading startup extensions/mkexts from booter memory.");
533 booterMemoryMap
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
);
535 if (!booterMemoryMap
) {
536 OSKextLog(/* kext */ NULL
,
537 kOSKextLogErrorLevel
|
538 kOSKextLogGeneralFlag
| kOSKextLogDirectoryScanFlag
,
539 "Can't read booter memory map.");
543 propertyDict
= booterMemoryMap
->dictionaryWithProperties();
545 OSKextLog(/* kext */ NULL
,
546 kOSKextLogErrorLevel
|
547 kOSKextLogDirectoryScanFlag
,
548 "Can't get property dictionary from memory map.");
552 keyIterator
= OSCollectionIterator::withCollection(propertyDict
);
554 OSKextLog(/* kext */ NULL
,
555 kOSKextLogErrorLevel
|
556 kOSKextLogGeneralFlag
,
557 "Can't allocate iterator for driver images.");
561 while ( ( deviceTreeName
=
562 OSDynamicCast(OSString
, keyIterator
->getNextObject() ))) {
564 boolean_t isMkext
= FALSE
;
565 const char * devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
566 OSData
* deviceTreeEntry
= OSDynamicCast(OSData
,
567 propertyDict
->getObject(deviceTreeName
));
569 /* Clear out the booterData from the prior iteration.
571 OSSafeReleaseNULL(booterData
);
573 /* If there is no entry for the name, we can't do much with it. */
574 if (!deviceTreeEntry
) {
578 /* Make sure it is either a kext or an mkext */
579 if (!strncmp(devTreeNameCString
, BOOTER_KEXT_PREFIX
,
580 CONST_STRLEN(BOOTER_KEXT_PREFIX
))) {
584 } else if (!strncmp(devTreeNameCString
, BOOTER_MKEXT_PREFIX
,
585 CONST_STRLEN(BOOTER_MKEXT_PREFIX
))) {
593 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
594 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
595 if (!deviceTreeBuffer
) {
596 /* We can't get to the data, so we can't do anything,
597 * not even free it from physical memory (if it's there).
599 OSKextLog(/* kext */ NULL
,
600 kOSKextLogErrorLevel
|
601 kOSKextLogDirectoryScanFlag
,
602 "Device tree entry %s has NULL pointer.",
604 goto finish
; // xxx - continue, panic?
607 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
608 if (!booterDataPtr
) {
609 OSKextLog(/* kext */ NULL
,
610 kOSKextLogErrorLevel
|
611 kOSKextLogDirectoryScanFlag
,
612 "Can't get virtual address for device tree mkext entry %s.",
617 /* Wrap the booter data buffer in an OSData and set a dealloc function
618 * so it will take care of the physical memory when freed. Kexts will
619 * retain the booterData for as long as they need it. Remove the entry
620 * from the booter memory map after this is done.
622 booterData
= OSData::withBytesNoCopy(booterDataPtr
,
623 deviceTreeBuffer
->length
);
625 OSKextLog(/* kext */ NULL
,
626 kOSKextLogErrorLevel
|
627 kOSKextLogGeneralFlag
,
628 "Error - Can't allocate OSData wrapper for device tree entry %s.",
632 booterData
->setDeallocFunction(osdata_phys_free
);
635 readMkextExtensions(deviceTreeName
, booterData
);
637 /* Create the kext for the entry, then release it, because the
638 * kext system keeps them around until explicitly removed.
639 * Any creation/registration failures are already logged for us.
641 OSKext
* newKext
= OSKext::withBooterData(deviceTreeName
, booterData
);
642 OSSafeRelease(newKext
);
645 booterMemoryMap
->removeProperty(deviceTreeName
);
647 } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */
651 OSSafeRelease(booterMemoryMap
);
652 OSSafeRelease(propertyDict
);
653 OSSafeRelease(keyIterator
);
654 OSSafeRelease(booterData
);
655 OSSafeRelease(aKext
);
659 /*********************************************************************
660 *********************************************************************/
662 KLDBootstrap::readMkextExtensions(
663 OSString
* deviceTreeName
,
666 OSReturn result
= kOSReturnError
;
669 IORegistryEntry
* registryRoot
= NULL
; // do not release
670 OSData
* checksumObj
= NULL
; // must release
672 OSKextLog(/* kext */ NULL
,
673 kOSKextLogStepLevel
|
674 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
675 "Reading startup mkext archive from device tree entry %s.",
676 deviceTreeName
->getCStringNoCopy());
678 /* If we successfully read the archive,
679 * then save the mkext's checksum in the IORegistry.
680 * assumes we'll only ever have one mkext to boot
682 result
= OSKext::readMkextArchive(booterData
, &checksum
);
683 if (result
== kOSReturnSuccess
) {
685 OSKextLog(/* kext */ NULL
,
686 kOSKextLogProgressLevel
|
687 kOSKextLogArchiveFlag
,
688 "Startup mkext archive has checksum 0x%x.", (int)checksum
);
690 registryRoot
= IORegistryEntry::getRegistryRoot();
691 assert(registryRoot
);
692 checksumObj
= OSData::withBytes((void *)&checksum
, sizeof(checksum
));
695 registryRoot
->setProperty(kOSStartupMkextCRC
, checksumObj
);
702 /*********************************************************************
703 *********************************************************************/
704 #define COM_APPLE "com.apple."
707 KLDBootstrap::loadSecurityExtensions(void)
709 OSDictionary
* extensionsDict
= NULL
; // must release
710 OSCollectionIterator
* keyIterator
= NULL
; // must release
711 OSString
* bundleID
= NULL
; // don't release
712 OSKext
* theKext
= NULL
; // don't release
713 OSBoolean
* isSecurityKext
= NULL
; // don't release
715 OSKextLog(/* kext */ NULL
,
716 kOSKextLogStepLevel
|
718 "Loading security extensions.");
720 extensionsDict
= OSKext::copyKexts();
721 if (!extensionsDict
) {
725 keyIterator
= OSCollectionIterator::withCollection(extensionsDict
);
727 OSKextLog(/* kext */ NULL
,
728 kOSKextLogErrorLevel
|
729 kOSKextLogGeneralFlag
,
730 "Failed to allocate iterator for security extensions.");
734 while ((bundleID
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
736 const char * bundle_id
= bundleID
->getCStringNoCopy();
738 /* Skip extensions whose bundle IDs don't start with "com.apple.".
741 (strncmp(bundle_id
, COM_APPLE
, CONST_STRLEN(COM_APPLE
)) != 0)) {
746 theKext
= OSDynamicCast(OSKext
, extensionsDict
->getObject(bundleID
));
751 isSecurityKext
= OSDynamicCast(OSBoolean
,
752 theKext
->getPropertyForHostArch("AppleSecurityExtension"));
753 if (isSecurityKext
&& isSecurityKext
->isTrue()) {
754 OSKextLog(/* kext */ NULL
,
755 kOSKextLogStepLevel
|
757 "Loading security extension %s.", bundleID
->getCStringNoCopy());
758 OSKext::loadKextWithIdentifier(bundleID
->getCStringNoCopy(),
759 /* allowDefer */ false);
764 OSSafeRelease(keyIterator
);
765 OSSafeRelease(extensionsDict
);
770 /*********************************************************************
771 * We used to require that all listed kernel components load, but
772 * nowadays we can get them from userland so we only try to load the
773 * ones we have. If an error occurs later, such is life.
775 * Note that we look the kexts up first, so we can avoid spurious
776 * (in this context, anyhow) log messages about kexts not being found.
778 * xxx - do we even need to do this any more? Check if the kernel
779 * xxx - compoonents just load in the regular paths
780 *********************************************************************/
782 KLDBootstrap::loadKernelComponentKexts(void)
784 OSReturn result
= kOSReturnSuccess
; // optimistic
785 OSKext
* theKext
= NULL
; // must release
786 const char ** kextIDPtr
= NULL
; // do not release
788 for (kextIDPtr
= &sKernelComponentNames
[0]; *kextIDPtr
; kextIDPtr
++) {
790 OSSafeReleaseNULL(theKext
);
791 theKext
= OSKext::lookupKextWithIdentifier(*kextIDPtr
);
794 if (kOSReturnSuccess
!= OSKext::loadKextWithIdentifier(
795 *kextIDPtr
, /* allowDefer */ false)) {
797 // xxx - check KextBookkeeping, might be redundant
798 OSKextLog(/* kext */ NULL
,
799 kOSKextLogErrorLevel
|
800 kOSKextLogDirectoryScanFlag
| kOSKextLogKextBookkeepingFlag
,
801 "Failed to initialize kernel component %s.", *kextIDPtr
);
802 result
= kOSReturnError
;
807 OSSafeRelease(theKext
);
811 /*********************************************************************
812 *********************************************************************/
814 KLDBootstrap::readBuiltinPersonalities(void)
816 OSObject
* parsedXML
= NULL
; // must release
817 OSArray
* builtinExtensions
= NULL
; // do not release
818 OSArray
* allPersonalities
= NULL
; // must release
819 OSString
* errorString
= NULL
; // must release
820 kernel_section_t
* infosect
= NULL
; // do not free
821 OSCollectionIterator
* personalitiesIterator
= NULL
; // must release
822 unsigned int count
, i
;
824 OSKextLog(/* kext */ NULL
,
825 kOSKextLogStepLevel
|
827 "Reading built-in kernel personalities for I/O Kit drivers.");
829 /* Look in the __BUILTIN __info segment for an array of Info.plist
830 * entries. For each one, extract the personalities dictionary, add
831 * it to our array, then push them all (without matching) to
832 * the IOCatalogue. This can be used to augment the personalities
833 * in gIOKernelConfigTables, especially when linking entire kexts into
834 * the mach_kernel image.
836 infosect
= getsectbyname("__BUILTIN", "__info");
842 parsedXML
= OSUnserializeXML((const char *) (uintptr_t)infosect
->addr
,
845 builtinExtensions
= OSDynamicCast(OSArray
, parsedXML
);
847 if (!builtinExtensions
) {
848 const char * errorCString
= "(unknown error)";
850 if (errorString
&& errorString
->getCStringNoCopy()) {
851 errorCString
= errorString
->getCStringNoCopy();
852 } else if (parsedXML
) {
853 errorCString
= "not an array";
855 OSKextLog(/* kext */ NULL
,
856 kOSKextLogErrorLevel
|
858 "Error unserializing built-in personalities: %s.", errorCString
);
862 // estimate 3 personalities per Info.plist/kext
863 count
= builtinExtensions
->getCount();
864 allPersonalities
= OSArray::withCapacity(count
* 3);
866 for (i
= 0; i
< count
; i
++) {
867 OSDictionary
* infoDict
= NULL
; // do not release
868 OSString
* moduleName
= NULL
; // do not release
869 OSDictionary
* personalities
; // do not release
870 OSString
* personalityName
; // do not release
872 OSSafeReleaseNULL(personalitiesIterator
);
874 infoDict
= OSDynamicCast(OSDictionary
,
875 builtinExtensions
->getObject(i
));
880 moduleName
= OSDynamicCast(OSString
,
881 infoDict
->getObject(kCFBundleIdentifierKey
));
886 OSKextLog(/* kext */ NULL
,
887 kOSKextLogStepLevel
|
889 "Adding personalities for built-in driver %s:",
890 moduleName
->getCStringNoCopy());
892 personalities
= OSDynamicCast(OSDictionary
,
893 infoDict
->getObject("IOKitPersonalities"));
894 if (!personalities
) {
898 personalitiesIterator
= OSCollectionIterator::withCollection(personalities
);
899 if (!personalitiesIterator
) {
900 continue; // xxx - well really, what can we do? should we panic?
903 while ((personalityName
= OSDynamicCast(OSString
,
904 personalitiesIterator
->getNextObject()))) {
906 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
907 personalities
->getObject(personalityName
));
909 OSKextLog(/* kext */ NULL
,
910 kOSKextLogDetailLevel
|
912 "Adding built-in driver personality %s.",
913 personalityName
->getCStringNoCopy());
915 if (personality
&& !personality
->getObject(kCFBundleIdentifierKey
)) {
916 personality
->setObject(kCFBundleIdentifierKey
, moduleName
);
918 allPersonalities
->setObject(personality
);
922 gIOCatalogue
->addDrivers(allPersonalities
, false);
925 OSSafeRelease(parsedXML
);
926 OSSafeRelease(allPersonalities
);
927 OSSafeRelease(errorString
);
928 OSSafeRelease(personalitiesIterator
);
933 #pragma mark Bootstrap Functions
935 /*********************************************************************
936 * Bootstrap Functions
937 *********************************************************************/
938 static void bootstrapRecordStartupExtensions(void)
940 sBootstrapObject
.readStartupExtensions();
944 static void bootstrapLoadSecurityExtensions(void)
946 sBootstrapObject
.loadSecurityExtensions();