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>
32 #include <libkern/crypto/sha2.h>
35 #define IOKIT_ENABLE_SHARED_PTR
37 #include <libkern/version.h>
38 #include <libkern/c++/OSContainers.h>
39 #include <libkern/OSKextLibPrivate.h>
40 #include <libkern/c++/OSKext.h>
41 #include <IOKit/IOLib.h>
42 #include <IOKit/IOService.h>
43 #include <IOKit/IODeviceTreeSupport.h>
44 #include <IOKit/IOCatalogue.h>
47 #define KASLR_KEXT_DEBUG 0
51 #pragma mark Bootstrap Declarations
53 /*********************************************************************
54 * Bootstrap Declarations
56 * The ENTIRE point of the libsa/KLD segment is to isolate bootstrap
57 * code from other parts of the kernel, so function symbols are not
58 * exported; rather pointers to those functions are exported.
60 * xxx - need to think about locking for handling the 'weak' refs.
61 * xxx - do export a non-KLD function that says you've called a
62 * xxx - bootstrap function that has been removed.
64 * ALL call-ins to this segment of the kernel must be done through
65 * exported pointers. The symbols themselves are private and not to
67 *********************************************************************/
69 extern void (*record_startup_extensions_function
)(void);
70 extern void (*load_security_extensions_function
)(void);
73 static void bootstrapRecordStartupExtensions(void);
74 static void bootstrapLoadSecurityExtensions(void);
78 extern "C" bool IORamDiskBSDRoot(void);
84 /*********************************************************************
86 *********************************************************************/
87 #define CONST_STRLEN(str) (sizeof(str) - 1)
90 #pragma mark Kernel Component Kext Identifiers
92 /*********************************************************************
93 * Kernel Component Kext Identifiers
95 * We could have each kernel resource kext automatically "load" as
96 * it's created, but it's nicer to have them listed in kextstat in
97 * the order of this list. We'll walk through this after setting up
98 * all the boot kexts and have them load up.
99 *********************************************************************/
100 static const char * sKernelComponentNames
[] = {
101 // The kexts for these IDs must have a version matching 'osrelease'.
104 "com.apple.kpi.dsep",
105 "com.apple.kpi.iokit",
106 "com.apple.kpi.kasan",
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",
119 #pragma mark KLDBootstrap Class
121 /*********************************************************************
124 * We use a C++ class here so that it can be a friend of OSKext and
125 * get at private stuff. We can't hide the class itself, but we can
126 * hide the instance through which we invoke the functions.
127 *********************************************************************/
129 friend void bootstrapRecordStartupExtensions(void);
130 friend void bootstrapLoadSecurityExtensions(void);
133 void readStartupExtensions(void);
135 void readPrelinkedExtensions(kernel_mach_header_t
*mh
, kc_kind_t type
);
136 void readBooterExtensions(void);
138 OSReturn
loadKernelComponentKexts(void);
139 void loadKernelExternalComponents(void);
140 void readBuiltinPersonalities(void);
142 void loadSecurityExtensions(void);
149 LIBKERN_ALWAYS_DESTROY
static KLDBootstrap sBootstrapObject
;
151 /*********************************************************************
152 * Set the function pointers for the entry points into the bootstrap
153 * segment upon C++ static constructor invocation.
154 *********************************************************************/
155 KLDBootstrap::KLDBootstrap(void)
157 if (this != &sBootstrapObject
) {
158 panic("Attempt to access bootstrap segment.");
160 record_startup_extensions_function
= &bootstrapRecordStartupExtensions
;
161 load_security_extensions_function
= &bootstrapLoadSecurityExtensions
;
164 /*********************************************************************
165 * Clear the function pointers for the entry points into the bootstrap
166 * segment upon C++ static destructor invocation.
167 *********************************************************************/
168 KLDBootstrap::~KLDBootstrap(void)
170 if (this != &sBootstrapObject
) {
171 panic("Attempt to access bootstrap segment.");
175 record_startup_extensions_function
= NULL
;
176 load_security_extensions_function
= NULL
;
179 /*********************************************************************
180 *********************************************************************/
182 KLDBootstrap::readStartupExtensions(void)
184 kernel_section_t
* prelinkInfoSect
= NULL
; // do not free
186 OSKextLog(/* kext */ NULL
,
187 kOSKextLogProgressLevel
|
188 kOSKextLogGeneralFlag
| kOSKextLogDirectoryScanFlag
|
189 kOSKextLogKextBookkeepingFlag
,
190 "Reading startup extensions.");
192 kc_format_t kc_format
;
193 kernel_mach_header_t
*mh
= &_mh_execute_header
;
194 if (PE_get_primary_kc_format(&kc_format
) && kc_format
== KCFormatFileset
) {
195 mh
= (kernel_mach_header_t
*)PE_get_kc_header(KCKindPrimary
);
198 /* If the prelink info segment has a nonzero size, we are prelinked
199 * and won't have any individual kexts or mkexts to read.
200 * Otherwise, we need to read kexts or the mkext from what the booter
203 prelinkInfoSect
= getsectbynamefromheader(mh
, kPrelinkInfoSegment
, kPrelinkInfoSection
);
204 if (prelinkInfoSect
->size
) {
205 readPrelinkedExtensions(mh
, KCKindPrimary
);
207 readBooterExtensions();
210 kernel_mach_header_t
*akc_mh
;
211 akc_mh
= (kernel_mach_header_t
*)PE_get_kc_header(KCKindAuxiliary
);
213 readPrelinkedExtensions(akc_mh
, KCKindAuxiliary
);
216 loadKernelComponentKexts();
217 loadKernelExternalComponents();
218 readBuiltinPersonalities();
219 OSKext::sendAllKextPersonalitiesToCatalog(true);
224 /*********************************************************************
225 *********************************************************************/
227 KLDBootstrap::readPrelinkedExtensions(kernel_mach_header_t
*mh
, kc_kind_t type
)
230 OSSharedPtr
<OSData
> loaded_kcUUID
;
231 OSSharedPtr
<OSString
> errorString
;
232 OSSharedPtr
<OSObject
> parsedXML
;
233 kernel_section_t
*infoPlistSection
= NULL
;
234 OSDictionary
*infoDict
= NULL
; // do not release
236 OSKextLog(/* kext */ NULL
,
237 kOSKextLogProgressLevel
|
238 kOSKextLogDirectoryScanFlag
| kOSKextLogArchiveFlag
,
239 "Starting from prelinked kernel.");
242 * The 'infoPlistSection' should contains an XML dictionary that
243 * contains some meta data about the KC, and also describes each kext
244 * included in the kext collection. Unserialize this dictionary and
245 * then iterate over each kext.
247 infoPlistSection
= getsectbynamefromheader(mh
, kPrelinkInfoSegment
, kPrelinkInfoSection
);
248 parsedXML
= OSUnserializeXML((const char *)infoPlistSection
->addr
, errorString
);
250 infoDict
= OSDynamicCast(OSDictionary
, parsedXML
.get());
254 const char *errorCString
= "(unknown error)";
256 if (errorString
&& errorString
->getCStringNoCopy()) {
257 errorCString
= errorString
->getCStringNoCopy();
258 } else if (parsedXML
) {
259 errorCString
= "not a dictionary";
261 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
262 "Error unserializing kext info plist section: %s.", errorCString
);
266 /* Validate that the Kext Collection is prelinked to the loaded KC */
267 if (type
== KCKindAuxiliary
) {
268 if (OSKext::validateKCFileSetUUID(infoDict
, KCKindAuxiliary
) != 0) {
269 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
270 "Early boot AuxKC doesn't appear to be linked against the loaded BootKC.");
275 * Defer further processing of the AuxKC, but keep the
276 * processed info dictionary around so we can ml_static_free
279 if (!OSKext::registerDeferredKextCollection(mh
, parsedXML
, KCKindAuxiliary
)) {
280 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
281 "Error deferring AuxKC kext processing: Kexts in this collection will be unusable.");
283 goto skip_adding_kexts
;
287 * this function does all the heavy lifting of adding OSKext objects
288 * and potentially sliding them if necessary
290 ret
= OSKext::addKextsFromKextCollection(mh
, infoDict
,
291 kPrelinkTextSegment
, loaded_kcUUID
, (mh
->filetype
== MH_FILESET
) ? type
: KCKindUnknown
);
294 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
295 "Error loading kext info from prelinked primary KC");
299 /* Copy in the kernelcache UUID */
300 if (!loaded_kcUUID
) {
301 OSKextLog(/* kext */ NULL
, kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
302 "WARNING: did not find UUID in %s KC!", (type
== KCKindAuxiliary
) ? "Aux" : "Primary");
303 } else if (type
!= KCKindAuxiliary
) {
304 kernelcache_uuid_valid
= TRUE
;
305 memcpy((void *)&kernelcache_uuid
, (const void *)loaded_kcUUID
->getBytesNoCopy(), loaded_kcUUID
->getLength());
306 uuid_unparse_upper(kernelcache_uuid
, kernelcache_uuid_string
);
308 auxkc_uuid_valid
= TRUE
;
309 memcpy((void *)&auxkc_uuid
, (const void *)loaded_kcUUID
->getBytesNoCopy(), loaded_kcUUID
->getLength());
310 uuid_unparse_upper(auxkc_uuid
, auxkc_uuid_string
);
314 #if CONFIG_KEXT_BASEMENT
315 if (mh
->filetype
!= MH_FILESET
) {
317 * On CONFIG_KEXT_BASEMENT systems which do _not_ boot the new
318 * MH_FILESET kext collection, kexts are copied to their own
319 * special VM region during OSKext init time, so we can free
320 * the whole segment now.
322 kernel_segment_command_t
*prelinkTextSegment
= NULL
;
323 prelinkTextSegment
= getsegbyname(kPrelinkTextSegment
);
324 if (!prelinkTextSegment
) {
325 OSKextLog(/* kext */ NULL
,
326 kOSKextLogErrorLevel
| kOSKextLogArchiveFlag
,
327 "Can't find prelinked kexts' text segment.");
331 ml_static_mfree((vm_offset_t
)prelinkTextSegment
->vmaddr
, prelinkTextSegment
->vmsize
);
333 #endif /* CONFIG_KEXT_BASEMENT */
336 * Free the prelink info segment, we're done with it.
338 kernel_segment_command_t
*prelinkInfoSegment
= NULL
;
339 prelinkInfoSegment
= getsegbyname(kPrelinkInfoSegment
);
340 if (prelinkInfoSegment
) {
341 ml_static_mfree((vm_offset_t
)prelinkInfoSegment
->vmaddr
,
342 (vm_size_t
)prelinkInfoSegment
->vmsize
);
349 /*********************************************************************
350 *********************************************************************/
351 #define BOOTER_KEXT_PREFIX "Driver-"
353 typedef struct _DeviceTreeBuffer
{
359 KLDBootstrap::readBooterExtensions(void)
361 OSSharedPtr
<IORegistryEntry
> booterMemoryMap
;
362 OSSharedPtr
<OSDictionary
> propertyDict
;
363 OSSharedPtr
<OSCollectionIterator
> keyIterator
;
364 OSString
* deviceTreeName
= NULL
;// do not release
366 const _DeviceTreeBuffer
* deviceTreeBuffer
= NULL
;// do not free
367 char * booterDataPtr
= NULL
;// do not free
368 OSSharedPtr
<OSData
> booterData
;
369 OSSharedPtr
<OSKext
> aKext
;
371 OSKextLog(/* kext */ NULL
,
372 kOSKextLogProgressLevel
|
373 kOSKextLogDirectoryScanFlag
| kOSKextLogKextBookkeepingFlag
,
374 "Reading startup extensions from booter memory.");
376 booterMemoryMap
= IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane
);
378 if (!booterMemoryMap
) {
379 OSKextLog(/* kext */ NULL
,
380 kOSKextLogErrorLevel
|
381 kOSKextLogGeneralFlag
| kOSKextLogDirectoryScanFlag
,
382 "Can't read booter memory map.");
386 propertyDict
= booterMemoryMap
->dictionaryWithProperties();
388 OSKextLog(/* kext */ NULL
,
389 kOSKextLogErrorLevel
|
390 kOSKextLogDirectoryScanFlag
,
391 "Can't get property dictionary from memory map.");
395 keyIterator
= OSCollectionIterator::withCollection(propertyDict
.get());
397 OSKextLog(/* kext */ NULL
,
398 kOSKextLogErrorLevel
|
399 kOSKextLogGeneralFlag
,
400 "Can't allocate iterator for driver images.");
404 /* Create dictionary of excluded kexts
406 #ifndef CONFIG_EMBEDDED
407 OSKext::createExcludeListFromBooterData(propertyDict
.get(), keyIterator
.get());
409 // !! reset the iterator, not the pointer
410 keyIterator
->reset();
412 while ((deviceTreeName
=
413 OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
414 const char * devTreeNameCString
= deviceTreeName
->getCStringNoCopy();
415 OSData
* deviceTreeEntry
= OSDynamicCast(OSData
,
416 propertyDict
->getObject(deviceTreeName
));
418 /* If there is no entry for the name, we can't do much with it. */
419 if (!deviceTreeEntry
) {
423 /* Make sure it is a kext */
424 if (strncmp(devTreeNameCString
,
426 CONST_STRLEN(BOOTER_KEXT_PREFIX
))) {
430 deviceTreeBuffer
= (const _DeviceTreeBuffer
*)
431 deviceTreeEntry
->getBytesNoCopy(0, sizeof(deviceTreeBuffer
));
432 if (!deviceTreeBuffer
) {
433 /* We can't get to the data, so we can't do anything,
434 * not even free it from physical memory (if it's there).
436 OSKextLog(/* kext */ NULL
,
437 kOSKextLogErrorLevel
|
438 kOSKextLogDirectoryScanFlag
,
439 "Device tree entry %s has NULL pointer.",
441 goto finish
; // xxx - continue, panic?
444 booterDataPtr
= (char *)ml_static_ptovirt(deviceTreeBuffer
->paddr
);
445 if (!booterDataPtr
) {
446 OSKextLog(/* kext */ NULL
,
447 kOSKextLogErrorLevel
|
448 kOSKextLogDirectoryScanFlag
,
449 "Can't get virtual address for device tree entry %s.",
454 /* Wrap the booter data buffer in an OSData and set a dealloc function
455 * so it will take care of the physical memory when freed. Kexts will
456 * retain the booterData for as long as they need it. Remove the entry
457 * from the booter memory map after this is done.
459 booterData
= OSData::withBytesNoCopy(booterDataPtr
,
460 deviceTreeBuffer
->length
);
462 OSKextLog(/* kext */ NULL
,
463 kOSKextLogErrorLevel
|
464 kOSKextLogGeneralFlag
,
465 "Error - Can't allocate OSData wrapper for device tree entry %s.",
469 booterData
->setDeallocFunction(osdata_phys_free
);
471 /* Create the kext for the entry, then release it, because the
472 * kext system keeps them around until explicitly removed.
473 * Any creation/registration failures are already logged for us.
475 OSSharedPtr
<OSKext
> newKext
= OSKext::withBooterData(deviceTreeName
, booterData
.get());
477 booterMemoryMap
->removeProperty(deviceTreeName
);
478 } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */
484 /*********************************************************************
485 *********************************************************************/
486 #define COM_APPLE "com.apple."
489 KLDBootstrap::loadSecurityExtensions(void)
491 OSSharedPtr
<OSDictionary
> extensionsDict
;
492 OSSharedPtr
<OSCollectionIterator
> keyIterator
;
493 OSString
* bundleID
= NULL
;// don't release
494 OSKext
* theKext
= NULL
;// don't release
496 OSKextLog(/* kext */ NULL
,
497 kOSKextLogStepLevel
|
499 "Loading security extensions.");
501 extensionsDict
= OSKext::copyKexts();
502 if (!extensionsDict
) {
506 keyIterator
= OSCollectionIterator::withCollection(extensionsDict
.get());
508 OSKextLog(/* kext */ NULL
,
509 kOSKextLogErrorLevel
|
510 kOSKextLogGeneralFlag
,
511 "Failed to allocate iterator for security extensions.");
515 while ((bundleID
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
516 const char * bundle_id
= bundleID
->getCStringNoCopy();
518 /* Skip extensions whose bundle IDs don't start with "com.apple.".
521 (strncmp(bundle_id
, COM_APPLE
, CONST_STRLEN(COM_APPLE
)) != 0)) {
525 theKext
= OSDynamicCast(OSKext
, extensionsDict
->getObject(bundleID
));
530 if (kOSBooleanTrue
== theKext
->getPropertyForHostArch(kAppleSecurityExtensionKey
)) {
531 OSKextLog(/* kext */ NULL
,
532 kOSKextLogStepLevel
|
534 "Loading security extension %s.", bundleID
->getCStringNoCopy());
535 OSKext::loadKextWithIdentifier(bundleID
->getCStringNoCopy(),
536 /* allowDefer */ false);
544 /*********************************************************************
545 * We used to require that all listed kernel components load, but
546 * nowadays we can get them from userland so we only try to load the
547 * ones we have. If an error occurs later, such is life.
549 * Note that we look the kexts up first, so we can avoid spurious
550 * (in this context, anyhow) log messages about kexts not being found.
552 * xxx - do we even need to do this any more? Check if the kernel
553 * xxx - compoonents just load in the regular paths
554 *********************************************************************/
556 KLDBootstrap::loadKernelComponentKexts(void)
558 OSReturn result
= kOSReturnSuccess
;// optimistic
559 OSSharedPtr
<OSKext
> theKext
;
560 const char ** kextIDPtr
= NULL
; // do not release
562 for (kextIDPtr
= &sKernelComponentNames
[0]; *kextIDPtr
; kextIDPtr
++) {
563 theKext
= OSKext::lookupKextWithIdentifier(*kextIDPtr
);
566 if (kOSReturnSuccess
!= OSKext::loadKextWithIdentifier(
567 *kextIDPtr
, /* allowDefer */ false)) {
568 // xxx - check KextBookkeeping, might be redundant
569 OSKextLog(/* kext */ NULL
,
570 kOSKextLogErrorLevel
|
571 kOSKextLogDirectoryScanFlag
| kOSKextLogKextBookkeepingFlag
,
572 "Failed to initialize kernel component %s.", *kextIDPtr
);
573 result
= kOSReturnError
;
581 /*********************************************************************
582 * Ensure that Kernel External Components are loaded early in boot,
583 * before other kext personalities get sent to the IOCatalogue. These
584 * kexts are treated specially because they may provide the implementation
585 * for kernel-vended KPI, so they must register themselves before
586 * general purpose IOKit probing begins.
587 *********************************************************************/
589 #define COM_APPLE_KEC "com.apple.kec."
592 KLDBootstrap::loadKernelExternalComponents(void)
594 OSSharedPtr
<OSDictionary
> extensionsDict
;
595 OSSharedPtr
<OSCollectionIterator
> keyIterator
;
596 OSString
* bundleID
= NULL
;// don't release
597 OSKext
* theKext
= NULL
;// don't release
598 OSBoolean
* isKernelExternalComponent
= NULL
;// don't release
600 OSKextLog(/* kext */ NULL
,
601 kOSKextLogStepLevel
|
603 "Loading Kernel External Components.");
605 extensionsDict
= OSKext::copyKexts();
606 if (!extensionsDict
) {
610 keyIterator
= OSCollectionIterator::withCollection(extensionsDict
.get());
612 OSKextLog(/* kext */ NULL
,
613 kOSKextLogErrorLevel
|
614 kOSKextLogGeneralFlag
,
615 "Failed to allocate iterator for Kernel External Components.");
619 while ((bundleID
= OSDynamicCast(OSString
, keyIterator
->getNextObject()))) {
620 const char * bundle_id
= bundleID
->getCStringNoCopy();
622 /* Skip extensions whose bundle IDs don't start with "com.apple.kec.".
625 (strncmp(bundle_id
, COM_APPLE_KEC
, CONST_STRLEN(COM_APPLE_KEC
)) != 0)) {
629 theKext
= OSDynamicCast(OSKext
, extensionsDict
->getObject(bundleID
));
634 isKernelExternalComponent
= OSDynamicCast(OSBoolean
,
635 theKext
->getPropertyForHostArch(kAppleKernelExternalComponentKey
));
636 if (isKernelExternalComponent
&& isKernelExternalComponent
->isTrue()) {
637 OSKextLog(/* kext */ NULL
,
638 kOSKextLogStepLevel
|
640 "Loading kernel external component %s.", bundleID
->getCStringNoCopy());
641 OSKext::loadKextWithIdentifier(bundleID
->getCStringNoCopy(),
642 /* allowDefer */ false);
650 /*********************************************************************
651 *********************************************************************/
653 KLDBootstrap::readBuiltinPersonalities(void)
655 OSSharedPtr
<OSObject
> parsedXML
;
656 OSArray
* builtinExtensions
= NULL
;// do not release
657 OSSharedPtr
<OSArray
> allPersonalities
;
658 OSSharedPtr
<OSString
> errorString
;
659 kernel_section_t
* infosect
= NULL
;// do not free
660 OSSharedPtr
<OSCollectionIterator
> personalitiesIterator
;
661 unsigned int count
, i
;
663 OSKextLog(/* kext */ NULL
,
664 kOSKextLogStepLevel
|
666 "Reading built-in kernel personalities for I/O Kit drivers.");
668 /* Look in the __BUILTIN __info segment for an array of Info.plist
669 * entries. For each one, extract the personalities dictionary, add
670 * it to our array, then push them all (without matching) to
671 * the IOCatalogue. This can be used to augment the personalities
672 * in gIOKernelConfigTables, especially when linking entire kexts into
673 * the mach_kernel image.
675 infosect
= getsectbyname("__BUILTIN", "__info");
681 parsedXML
= OSUnserializeXML((const char *) (uintptr_t)infosect
->addr
,
684 builtinExtensions
= OSDynamicCast(OSArray
, parsedXML
.get());
686 if (!builtinExtensions
) {
687 const char * errorCString
= "(unknown error)";
689 if (errorString
&& errorString
->getCStringNoCopy()) {
690 errorCString
= errorString
->getCStringNoCopy();
691 } else if (parsedXML
) {
692 errorCString
= "not an array";
694 OSKextLog(/* kext */ NULL
,
695 kOSKextLogErrorLevel
|
697 "Error unserializing built-in personalities: %s.", errorCString
);
701 // estimate 3 personalities per Info.plist/kext
702 count
= builtinExtensions
->getCount();
703 allPersonalities
= OSArray::withCapacity(count
* 3);
705 for (i
= 0; i
< count
; i
++) {
706 OSDictionary
* infoDict
= NULL
;// do not release
707 OSString
* moduleName
= NULL
;// do not release
708 OSDictionary
* personalities
;// do not release
709 OSString
* personalityName
;// do not release
711 infoDict
= OSDynamicCast(OSDictionary
,
712 builtinExtensions
->getObject(i
));
717 moduleName
= OSDynamicCast(OSString
,
718 infoDict
->getObject(kCFBundleIdentifierKey
));
723 OSKextLog(/* kext */ NULL
,
724 kOSKextLogStepLevel
|
726 "Adding personalities for built-in driver %s:",
727 moduleName
->getCStringNoCopy());
729 personalities
= OSDynamicCast(OSDictionary
,
730 infoDict
->getObject("IOKitPersonalities"));
731 if (!personalities
) {
735 personalitiesIterator
= OSCollectionIterator::withCollection(personalities
);
736 if (!personalitiesIterator
) {
737 continue; // xxx - well really, what can we do? should we panic?
740 while ((personalityName
= OSDynamicCast(OSString
,
741 personalitiesIterator
->getNextObject()))) {
742 OSDictionary
* personality
= OSDynamicCast(OSDictionary
,
743 personalities
->getObject(personalityName
));
745 OSKextLog(/* kext */ NULL
,
746 kOSKextLogDetailLevel
|
748 "Adding built-in driver personality %s.",
749 personalityName
->getCStringNoCopy());
751 if (personality
&& !personality
->getObject(kCFBundleIdentifierKey
)) {
752 personality
->setObject(kCFBundleIdentifierKey
, moduleName
);
754 allPersonalities
->setObject(personality
);
758 gIOCatalogue
->addDrivers(allPersonalities
.get(), false);
765 #pragma mark Bootstrap Functions
767 /*********************************************************************
768 * Bootstrap Functions
769 *********************************************************************/
771 bootstrapRecordStartupExtensions(void)
773 sBootstrapObject
.readStartupExtensions();
778 bootstrapLoadSecurityExtensions(void)
780 sBootstrapObject
.loadSecurityExtensions();