]> git.saurik.com Git - apple/xnu.git/blame_incremental - libsa/bootstrap.cpp
xnu-3789.70.16.tar.gz
[apple/xnu.git] / libsa / bootstrap.cpp
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28extern "C" {
29#include <mach/kmod.h>
30#include <libkern/kernel_mach_header.h>
31#include <libkern/prelink.h>
32
33}
34
35#include <libkern/version.h>
36#include <libkern/c++/OSContainers.h>
37#include <libkern/OSKextLibPrivate.h>
38#include <libkern/c++/OSKext.h>
39#include <IOKit/IOLib.h>
40#include <IOKit/IOService.h>
41#include <IOKit/IODeviceTreeSupport.h>
42#include <IOKit/IOCatalogue.h>
43
44#if __x86_64__
45#define KASLR_KEXT_DEBUG 0
46#endif
47
48#if PRAGMA_MARK
49#pragma mark Bootstrap Declarations
50#endif
51/*********************************************************************
52* Bootstrap Declarations
53*
54* The ENTIRE point of the libsa/KLD segment is to isolate bootstrap
55* code from other parts of the kernel, so function symbols are not
56* exported; rather pointers to those functions are exported.
57*
58* xxx - need to think about locking for handling the 'weak' refs.
59* xxx - do export a non-KLD function that says you've called a
60* xxx - bootstrap function that has been removed.
61*
62* ALL call-ins to this segment of the kernel must be done through
63* exported pointers. The symbols themselves are private and not to
64* be linked against.
65*********************************************************************/
66extern "C" {
67 extern void (*record_startup_extensions_function)(void);
68 extern void (*load_security_extensions_function)(void);
69};
70
71static void bootstrapRecordStartupExtensions(void);
72static void bootstrapLoadSecurityExtensions(void);
73
74
75#if NO_KEXTD
76extern "C" bool IORamDiskBSDRoot(void);
77#endif
78
79#if PRAGMA_MARK
80#pragma mark Macros
81#endif
82/*********************************************************************
83* Macros
84*********************************************************************/
85#define CONST_STRLEN(str) (sizeof(str) - 1)
86
87#if PRAGMA_MARK
88#pragma mark Kernel Component Kext Identifiers
89#endif
90/*********************************************************************
91* Kernel Component Kext Identifiers
92*
93* We could have each kernel resource kext automatically "load" as
94* it's created, but it's nicer to have them listed in kextstat in
95* the order of this list. We'll walk through this after setting up
96* all the boot kexts and have them load up.
97*********************************************************************/
98static const char * sKernelComponentNames[] = {
99 // The kexts for these IDs must have a version matching 'osrelease'.
100 "com.apple.kernel",
101 "com.apple.kpi.bsd",
102 "com.apple.kpi.dsep",
103 "com.apple.kpi.iokit",
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",
112 NULL
113};
114
115static int __whereIsAddr(vm_offset_t theAddr, unsigned long * segSizes, vm_offset_t *segAddrs, int segCount );
116
117#define PLK_SEGMENTS 12
118
119static const char * plk_segNames[] = {
120 "__TEXT",
121 "__TEXT_EXEC",
122 "__DATA",
123 "__DATA_CONST",
124 "__LINKEDIT",
125 "__PRELINK_TEXT",
126 "__PLK_TEXT_EXEC",
127 "__PRELINK_DATA",
128 "__PLK_DATA_CONST",
129 "__PLK_LLVM_COV",
130 "__PLK_LINKEDIT",
131 "__PRELINK_INFO",
132 NULL
133};
134
135#if PRAGMA_MARK
136#pragma mark KLDBootstrap Class
137#endif
138/*********************************************************************
139* KLDBootstrap Class
140*
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*********************************************************************/
145class KLDBootstrap {
146 friend void bootstrapRecordStartupExtensions(void);
147 friend void bootstrapLoadSecurityExtensions(void);
148
149private:
150 void readStartupExtensions(void);
151
152 void readPrelinkedExtensions(
153 kernel_section_t * prelinkInfoSect);
154 void readBooterExtensions(void);
155
156 OSReturn loadKernelComponentKexts(void);
157 void loadKernelExternalComponents(void);
158 void readBuiltinPersonalities(void);
159
160 void loadSecurityExtensions(void);
161
162public:
163 KLDBootstrap(void);
164 ~KLDBootstrap(void);
165};
166
167static KLDBootstrap sBootstrapObject;
168
169/*********************************************************************
170* Set the function pointers for the entry points into the bootstrap
171* segment upon C++ static constructor invocation.
172*********************************************************************/
173KLDBootstrap::KLDBootstrap(void)
174{
175 if (this != &sBootstrapObject) {
176 panic("Attempt to access bootstrap segment.");
177 }
178 record_startup_extensions_function = &bootstrapRecordStartupExtensions;
179 load_security_extensions_function = &bootstrapLoadSecurityExtensions;
180}
181
182/*********************************************************************
183* Clear the function pointers for the entry points into the bootstrap
184* segment upon C++ static destructor invocation.
185*********************************************************************/
186KLDBootstrap::~KLDBootstrap(void)
187{
188 if (this != &sBootstrapObject) {
189 panic("Attempt to access bootstrap segment.");
190 }
191
192
193 record_startup_extensions_function = 0;
194 load_security_extensions_function = 0;
195}
196
197/*********************************************************************
198*********************************************************************/
199void
200KLDBootstrap::readStartupExtensions(void)
201{
202 kernel_section_t * prelinkInfoSect = NULL; // do not free
203
204 OSKextLog(/* kext */ NULL,
205 kOSKextLogProgressLevel |
206 kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag |
207 kOSKextLogKextBookkeepingFlag,
208 "Reading startup extensions.");
209
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
213 * has handed us.
214 */
215 prelinkInfoSect = getsectbyname(kPrelinkInfoSegment, kPrelinkInfoSection);
216 if (prelinkInfoSect->size) {
217 readPrelinkedExtensions(prelinkInfoSect);
218 } else {
219 readBooterExtensions();
220 }
221
222 loadKernelComponentKexts();
223 loadKernelExternalComponents();
224 readBuiltinPersonalities();
225 OSKext::sendAllKextPersonalitiesToCatalog();
226
227 return;
228}
229
230typedef struct kaslrPackedOffsets {
231 uint32_t count; /* number of offsets */
232 uint32_t offsetsArray[]; /* offsets to slide */
233} kaslrPackedOffsets;
234
235/*********************************************************************
236*********************************************************************/
237void
238KLDBootstrap::readPrelinkedExtensions(
239 kernel_section_t * prelinkInfoSect)
240{
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
247 kernel_segment_command_t * prelinkTextSegment = NULL; // see code
248 kernel_segment_command_t * prelinkInfoSegment = NULL; // see code
249
250 /* We make some copies of data, but if anything fails we're basically
251 * going to fail the boot, so these won't be cleaned up on error.
252 */
253 void * prelinkData = NULL; // see code
254 vm_size_t prelinkLength = 0;
255
256
257 OSDictionary * infoDict = NULL; // do not release
258
259 IORegistryEntry * registryRoot = NULL; // do not release
260 OSNumber * prelinkCountObj = NULL; // must release
261
262 u_int i = 0;
263#if NO_KEXTD
264 bool ramDiskBoot;
265 bool developerDevice;
266 bool dontLoad;
267#endif
268 OSData * kaslrOffsets = NULL;
269 unsigned long plk_segSizes[PLK_SEGMENTS];
270 vm_offset_t plk_segAddrs[PLK_SEGMENTS];
271
272 OSKextLog(/* kext */ NULL,
273 kOSKextLogProgressLevel |
274 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
275 "Starting from prelinked kernel.");
276
277 prelinkTextSegment = getsegbyname(kPrelinkTextSegment);
278 if (!prelinkTextSegment) {
279 OSKextLog(/* kext */ NULL,
280 kOSKextLogErrorLevel |
281 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
282 "Can't find prelinked kexts' text segment.");
283 goto finish;
284 }
285
286#if KASLR_KEXT_DEBUG
287 unsigned long scratchSize;
288 vm_offset_t scratchAddr;
289
290 IOLog("kaslr: prelinked kernel address info: \n");
291
292 scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__TEXT", &scratchSize);
293 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __TEXT \n",
294 (unsigned long)scratchAddr,
295 (unsigned long)(scratchAddr + scratchSize),
296 scratchSize);
297
298 scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__DATA", &scratchSize);
299 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __DATA \n",
300 (unsigned long)scratchAddr,
301 (unsigned long)(scratchAddr + scratchSize),
302 scratchSize);
303
304 scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__LINKEDIT", &scratchSize);
305 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __LINKEDIT \n",
306 (unsigned long)scratchAddr,
307 (unsigned long)(scratchAddr + scratchSize),
308 scratchSize);
309
310 scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__KLD", &scratchSize);
311 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __KLD \n",
312 (unsigned long)scratchAddr,
313 (unsigned long)(scratchAddr + scratchSize),
314 scratchSize);
315
316 scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_TEXT", &scratchSize);
317 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_TEXT \n",
318 (unsigned long)scratchAddr,
319 (unsigned long)(scratchAddr + scratchSize),
320 scratchSize);
321
322 scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_INFO", &scratchSize);
323 IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_INFO \n",
324 (unsigned long)scratchAddr,
325 (unsigned long)(scratchAddr + scratchSize),
326 scratchSize);
327#endif
328
329 prelinkData = (void *) prelinkTextSegment->vmaddr;
330 prelinkLength = prelinkTextSegment->vmsize;
331
332 /* build arrays of plk info for later use */
333 const char ** segNamePtr;
334
335 for (segNamePtr = &plk_segNames[0], i = 0; *segNamePtr && i < PLK_SEGMENTS; segNamePtr++, i++) {
336 plk_segSizes[i] = 0;
337 plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(&_mh_execute_header, *segNamePtr, &plk_segSizes[i]);
338 }
339
340
341 /* Unserialize the info dictionary from the prelink info section.
342 */
343 parsedXML = OSUnserializeXML((const char *)prelinkInfoSect->addr,
344 &errorString);
345 if (parsedXML) {
346 prelinkInfoDict = OSDynamicCast(OSDictionary, parsedXML);
347 }
348 if (!prelinkInfoDict) {
349 const char * errorCString = "(unknown error)";
350
351 if (errorString && errorString->getCStringNoCopy()) {
352 errorCString = errorString->getCStringNoCopy();
353 } else if (parsedXML) {
354 errorCString = "not a dictionary";
355 }
356 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
357 "Error unserializing prelink plist: %s.", errorCString);
358 goto finish;
359 }
360
361#if NO_KEXTD
362 /* Check if we should keep developer kexts around.
363 * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201>
364 */
365 developerDevice = true;
366 PE_parse_boot_argn("developer", &developerDevice, sizeof(developerDevice));
367
368 ramDiskBoot = IORamDiskBSDRoot();
369#endif /* NO_KEXTD */
370
371
372 infoDictArray = OSDynamicCast(OSArray,
373 prelinkInfoDict->getObject(kPrelinkInfoDictionaryKey));
374 if (!infoDictArray) {
375 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
376 "The prelinked kernel has no kext info dictionaries");
377 goto finish;
378 }
379
380 /* kaslrOffsets are available use them to slide local relocations */
381 kaslrOffsets = OSDynamicCast(OSData,
382 prelinkInfoDict->getObject(kPrelinkLinkKASLROffsetsKey));
383
384 /* Create dictionary of excluded kexts
385 */
386 OSKext::createExcludeListFromPrelinkInfo(infoDictArray);
387 /* Create OSKext objects for each info dictionary.
388 */
389 for (i = 0; i < infoDictArray->getCount(); ++i) {
390 infoDict = OSDynamicCast(OSDictionary, infoDictArray->getObject(i));
391 if (!infoDict) {
392 OSKextLog(/* kext */ NULL,
393 kOSKextLogErrorLevel |
394 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
395 "Can't find info dictionary for prelinked kext #%d.", i);
396 continue;
397 }
398
399#if NO_KEXTD
400 dontLoad = false;
401
402 /* If we're not on a developer device, skip and free developer kexts.
403 */
404 if (developerDevice == false) {
405 OSBoolean *devOnlyBool = OSDynamicCast(OSBoolean,
406 infoDict->getObject(kOSBundleDeveloperOnlyKey));
407 if (devOnlyBool == kOSBooleanTrue) {
408 dontLoad = true;
409 }
410 }
411
412 /* Skip and free kexts that are only needed when booted from a ram disk.
413 */
414 if (ramDiskBoot == false) {
415 OSBoolean *ramDiskOnlyBool = OSDynamicCast(OSBoolean,
416 infoDict->getObject(kOSBundleRamDiskOnlyKey));
417 if (ramDiskOnlyBool == kOSBooleanTrue) {
418 dontLoad = true;
419 }
420 }
421
422 if (dontLoad == true) {
423 OSString *bundleID = OSDynamicCast(OSString,
424 infoDict->getObject(kCFBundleIdentifierKey));
425 if (bundleID) {
426 OSKextLog(NULL, kOSKextLogWarningLevel | kOSKextLogGeneralFlag,
427 "Kext %s not loading.", bundleID->getCStringNoCopy());
428 }
429
430 OSNumber *addressNum = OSDynamicCast(OSNumber,
431 infoDict->getObject(kPrelinkExecutableLoadKey));
432 OSNumber *lengthNum = OSDynamicCast(OSNumber,
433 infoDict->getObject(kPrelinkExecutableSizeKey));
434 if (addressNum && lengthNum) {
435#error Pick the right way to free prelinked data on this arch
436 }
437
438 infoDictArray->removeObject(i--);
439 continue;
440 }
441#endif /* NO_KEXTD */
442
443 /* Create the kext for the entry, then release it, because the
444 * kext system keeps them around until explicitly removed.
445 * Any creation/registration failures are already logged for us.
446 */
447 OSKext * newKext = OSKext::withPrelinkedInfoDict(infoDict, (kaslrOffsets ? TRUE : FALSE));
448 OSSafeReleaseNULL(newKext);
449 }
450
451 /* slide kxld relocations */
452 if (kaslrOffsets && vm_kernel_slide > 0) {
453 int slidKextAddrCount = 0;
454 int badSlideAddr = 0;
455 int badSlideTarget = 0;
456
457 kaslrPackedOffsets * myOffsets = NULL;
458 myOffsets = (kaslrPackedOffsets *) kaslrOffsets->getBytesNoCopy();
459
460 for (uint32_t j = 0; j < myOffsets->count; j++) {
461
462 uint64_t slideOffset = (uint64_t) myOffsets->offsetsArray[j];
463 uintptr_t * slideAddr = (uintptr_t *) ((uint64_t)prelinkData + slideOffset);
464 int slideAddrSegIndex = -1;
465 int addrToSlideSegIndex = -1;
466
467 slideAddrSegIndex = __whereIsAddr( (vm_offset_t)slideAddr, &plk_segSizes[0], &plk_segAddrs[0], PLK_SEGMENTS );
468 if (slideAddrSegIndex >= 0) {
469 addrToSlideSegIndex = __whereIsAddr( (vm_offset_t)(*slideAddr + vm_kernel_slide), &plk_segSizes[0], &plk_segAddrs[0], PLK_SEGMENTS );
470 if (addrToSlideSegIndex < 0) {
471 badSlideTarget++;
472 continue;
473 }
474 }
475 else {
476 badSlideAddr++;
477 continue;
478 }
479
480 slidKextAddrCount++;
481 *(slideAddr) += vm_kernel_slide;
482 } // for ...
483
484 /* All kexts are now slid, set VM protections for them */
485 OSKext::setAllVMAttributes();
486 }
487
488 /* Store the number of prelinked kexts in the registry so we can tell
489 * when the system has been started from a prelinked kernel.
490 */
491 registryRoot = IORegistryEntry::getRegistryRoot();
492 assert(registryRoot);
493
494 prelinkCountObj = OSNumber::withNumber(
495 (unsigned long long)infoDictArray->getCount(),
496 8 * sizeof(uint32_t));
497 assert(prelinkCountObj);
498 if (prelinkCountObj) {
499 registryRoot->setProperty(kOSPrelinkKextCountKey, prelinkCountObj);
500 }
501
502 OSKextLog(/* kext */ NULL,
503 kOSKextLogProgressLevel |
504 kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
505 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
506 "%u prelinked kexts",
507 infoDictArray->getCount());
508
509#if CONFIG_KEXT_BASEMENT
510 /* On CONFIG_KEXT_BASEMENT systems, kexts are copied to their own
511 * special VM region during OSKext init time, so we can free the whole
512 * segment now.
513 */
514 ml_static_mfree((vm_offset_t) prelinkData, prelinkLength);
515#endif /* __x86_64__ */
516
517 /* Free the prelink info segment, we're done with it.
518 */
519 prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment);
520 if (prelinkInfoSegment) {
521 ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr,
522 (vm_size_t)prelinkInfoSegment->vmsize);
523 }
524
525finish:
526 OSSafeReleaseNULL(errorString);
527 OSSafeReleaseNULL(parsedXML);
528 OSSafeReleaseNULL(theKernel);
529 OSSafeReleaseNULL(prelinkCountObj);
530 return;
531}
532
533static int __whereIsAddr(vm_offset_t theAddr, unsigned long * segSizes, vm_offset_t *segAddrs, int segCount)
534{
535 int i;
536
537 for (i = 0; i < segCount; i++) {
538 vm_offset_t myAddr = *(segAddrs + i);
539 unsigned long mySize = *(segSizes + i);
540
541 if (theAddr >= myAddr && theAddr < (myAddr + mySize)) {
542 return i;
543 }
544 }
545
546 return -1;
547}
548
549
550/*********************************************************************
551*********************************************************************/
552#define BOOTER_KEXT_PREFIX "Driver-"
553
554typedef struct _DeviceTreeBuffer {
555 uint32_t paddr;
556 uint32_t length;
557} _DeviceTreeBuffer;
558
559void
560KLDBootstrap::readBooterExtensions(void)
561{
562 IORegistryEntry * booterMemoryMap = NULL; // must release
563 OSDictionary * propertyDict = NULL; // must release
564 OSCollectionIterator * keyIterator = NULL; // must release
565 OSString * deviceTreeName = NULL; // do not release
566
567 const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not free
568 char * booterDataPtr = NULL; // do not free
569 OSData * booterData = NULL; // must release
570
571 OSKext * aKext = NULL; // must release
572
573 OSKextLog(/* kext */ NULL,
574 kOSKextLogProgressLevel |
575 kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag,
576 "Reading startup extensions from booter memory.");
577
578 booterMemoryMap = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane);
579
580 if (!booterMemoryMap) {
581 OSKextLog(/* kext */ NULL,
582 kOSKextLogErrorLevel |
583 kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag,
584 "Can't read booter memory map.");
585 goto finish;
586 }
587
588 propertyDict = booterMemoryMap->dictionaryWithProperties();
589 if (!propertyDict) {
590 OSKextLog(/* kext */ NULL,
591 kOSKextLogErrorLevel |
592 kOSKextLogDirectoryScanFlag,
593 "Can't get property dictionary from memory map.");
594 goto finish;
595 }
596
597 keyIterator = OSCollectionIterator::withCollection(propertyDict);
598 if (!keyIterator) {
599 OSKextLog(/* kext */ NULL,
600 kOSKextLogErrorLevel |
601 kOSKextLogGeneralFlag,
602 "Can't allocate iterator for driver images.");
603 goto finish;
604 }
605
606 /* Create dictionary of excluded kexts
607 */
608 OSKext::createExcludeListFromBooterData(propertyDict, keyIterator);
609 keyIterator->reset();
610
611 while ( ( deviceTreeName =
612 OSDynamicCast(OSString, keyIterator->getNextObject() ))) {
613
614 const char * devTreeNameCString = deviceTreeName->getCStringNoCopy();
615 OSData * deviceTreeEntry = OSDynamicCast(OSData,
616 propertyDict->getObject(deviceTreeName));
617
618 /* Clear out the booterData from the prior iteration.
619 */
620 OSSafeReleaseNULL(booterData);
621
622 /* If there is no entry for the name, we can't do much with it. */
623 if (!deviceTreeEntry) {
624 continue;
625 }
626
627 /* Make sure it is a kext */
628 if (strncmp(devTreeNameCString,
629 BOOTER_KEXT_PREFIX,
630 CONST_STRLEN(BOOTER_KEXT_PREFIX))) {
631 continue;
632 }
633
634 deviceTreeBuffer = (const _DeviceTreeBuffer *)
635 deviceTreeEntry->getBytesNoCopy(0, sizeof(deviceTreeBuffer));
636 if (!deviceTreeBuffer) {
637 /* We can't get to the data, so we can't do anything,
638 * not even free it from physical memory (if it's there).
639 */
640 OSKextLog(/* kext */ NULL,
641 kOSKextLogErrorLevel |
642 kOSKextLogDirectoryScanFlag,
643 "Device tree entry %s has NULL pointer.",
644 devTreeNameCString);
645 goto finish; // xxx - continue, panic?
646 }
647
648 booterDataPtr = (char *)ml_static_ptovirt(deviceTreeBuffer->paddr);
649 if (!booterDataPtr) {
650 OSKextLog(/* kext */ NULL,
651 kOSKextLogErrorLevel |
652 kOSKextLogDirectoryScanFlag,
653 "Can't get virtual address for device tree entry %s.",
654 devTreeNameCString);
655 goto finish;
656 }
657
658 /* Wrap the booter data buffer in an OSData and set a dealloc function
659 * so it will take care of the physical memory when freed. Kexts will
660 * retain the booterData for as long as they need it. Remove the entry
661 * from the booter memory map after this is done.
662 */
663 booterData = OSData::withBytesNoCopy(booterDataPtr,
664 deviceTreeBuffer->length);
665 if (!booterData) {
666 OSKextLog(/* kext */ NULL,
667 kOSKextLogErrorLevel |
668 kOSKextLogGeneralFlag,
669 "Error - Can't allocate OSData wrapper for device tree entry %s.",
670 devTreeNameCString);
671 goto finish;
672 }
673 booterData->setDeallocFunction(osdata_phys_free);
674
675 /* Create the kext for the entry, then release it, because the
676 * kext system keeps them around until explicitly removed.
677 * Any creation/registration failures are already logged for us.
678 */
679 OSKext * newKext = OSKext::withBooterData(deviceTreeName, booterData);
680 OSSafeReleaseNULL(newKext);
681
682 booterMemoryMap->removeProperty(deviceTreeName);
683
684 } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */
685
686finish:
687
688 OSSafeReleaseNULL(booterMemoryMap);
689 OSSafeReleaseNULL(propertyDict);
690 OSSafeReleaseNULL(keyIterator);
691 OSSafeReleaseNULL(booterData);
692 OSSafeReleaseNULL(aKext);
693 return;
694}
695
696/*********************************************************************
697*********************************************************************/
698#define COM_APPLE "com.apple."
699
700void
701KLDBootstrap::loadSecurityExtensions(void)
702{
703 OSDictionary * extensionsDict = NULL; // must release
704 OSCollectionIterator * keyIterator = NULL; // must release
705 OSString * bundleID = NULL; // don't release
706 OSKext * theKext = NULL; // don't release
707 OSBoolean * isSecurityKext = NULL; // don't release
708
709 OSKextLog(/* kext */ NULL,
710 kOSKextLogStepLevel |
711 kOSKextLogLoadFlag,
712 "Loading security extensions.");
713
714 extensionsDict = OSKext::copyKexts();
715 if (!extensionsDict) {
716 return;
717 }
718
719 keyIterator = OSCollectionIterator::withCollection(extensionsDict);
720 if (!keyIterator) {
721 OSKextLog(/* kext */ NULL,
722 kOSKextLogErrorLevel |
723 kOSKextLogGeneralFlag,
724 "Failed to allocate iterator for security extensions.");
725 goto finish;
726 }
727
728 while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
729
730 const char * bundle_id = bundleID->getCStringNoCopy();
731
732 /* Skip extensions whose bundle IDs don't start with "com.apple.".
733 */
734 if (!bundle_id ||
735 (strncmp(bundle_id, COM_APPLE, CONST_STRLEN(COM_APPLE)) != 0)) {
736
737 continue;
738 }
739
740 theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID));
741 if (!theKext) {
742 continue;
743 }
744
745 isSecurityKext = OSDynamicCast(OSBoolean,
746 theKext->getPropertyForHostArch(kAppleSecurityExtensionKey));
747 if (isSecurityKext && isSecurityKext->isTrue()) {
748 OSKextLog(/* kext */ NULL,
749 kOSKextLogStepLevel |
750 kOSKextLogLoadFlag,
751 "Loading security extension %s.", bundleID->getCStringNoCopy());
752 OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(),
753 /* allowDefer */ false);
754 }
755 }
756
757finish:
758 OSSafeReleaseNULL(keyIterator);
759 OSSafeReleaseNULL(extensionsDict);
760
761 return;
762}
763
764/*********************************************************************
765* We used to require that all listed kernel components load, but
766* nowadays we can get them from userland so we only try to load the
767* ones we have. If an error occurs later, such is life.
768*
769* Note that we look the kexts up first, so we can avoid spurious
770* (in this context, anyhow) log messages about kexts not being found.
771*
772* xxx - do we even need to do this any more? Check if the kernel
773* xxx - compoonents just load in the regular paths
774*********************************************************************/
775OSReturn
776KLDBootstrap::loadKernelComponentKexts(void)
777{
778 OSReturn result = kOSReturnSuccess; // optimistic
779 OSKext * theKext = NULL; // must release
780 const char ** kextIDPtr = NULL; // do not release
781
782 for (kextIDPtr = &sKernelComponentNames[0]; *kextIDPtr; kextIDPtr++) {
783
784 OSSafeReleaseNULL(theKext);
785 theKext = OSKext::lookupKextWithIdentifier(*kextIDPtr);
786
787 if (theKext) {
788 if (kOSReturnSuccess != OSKext::loadKextWithIdentifier(
789 *kextIDPtr, /* allowDefer */ false)) {
790
791 // xxx - check KextBookkeeping, might be redundant
792 OSKextLog(/* kext */ NULL,
793 kOSKextLogErrorLevel |
794 kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag,
795 "Failed to initialize kernel component %s.", *kextIDPtr);
796 result = kOSReturnError;
797 }
798 }
799 }
800
801 OSSafeReleaseNULL(theKext);
802 return result;
803}
804
805/*********************************************************************
806* Ensure that Kernel External Components are loaded early in boot,
807* before other kext personalities get sent to the IOCatalogue. These
808* kexts are treated specially because they may provide the implementation
809* for kernel-vended KPI, so they must register themselves before
810* general purpose IOKit probing begins.
811*********************************************************************/
812
813#define COM_APPLE_KEC "com.apple.kec."
814
815void
816KLDBootstrap::loadKernelExternalComponents(void)
817{
818 OSDictionary * extensionsDict = NULL; // must release
819 OSCollectionIterator * keyIterator = NULL; // must release
820 OSString * bundleID = NULL; // don't release
821 OSKext * theKext = NULL; // don't release
822 OSBoolean * isKernelExternalComponent = NULL; // don't release
823
824 OSKextLog(/* kext */ NULL,
825 kOSKextLogStepLevel |
826 kOSKextLogLoadFlag,
827 "Loading Kernel External Components.");
828
829 extensionsDict = OSKext::copyKexts();
830 if (!extensionsDict) {
831 return;
832 }
833
834 keyIterator = OSCollectionIterator::withCollection(extensionsDict);
835 if (!keyIterator) {
836 OSKextLog(/* kext */ NULL,
837 kOSKextLogErrorLevel |
838 kOSKextLogGeneralFlag,
839 "Failed to allocate iterator for Kernel External Components.");
840 goto finish;
841 }
842
843 while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
844
845 const char * bundle_id = bundleID->getCStringNoCopy();
846
847 /* Skip extensions whose bundle IDs don't start with "com.apple.kec.".
848 */
849 if (!bundle_id ||
850 (strncmp(bundle_id, COM_APPLE_KEC, CONST_STRLEN(COM_APPLE_KEC)) != 0)) {
851
852 continue;
853 }
854
855 theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID));
856 if (!theKext) {
857 continue;
858 }
859
860 isKernelExternalComponent = OSDynamicCast(OSBoolean,
861 theKext->getPropertyForHostArch(kAppleKernelExternalComponentKey));
862 if (isKernelExternalComponent && isKernelExternalComponent->isTrue()) {
863 OSKextLog(/* kext */ NULL,
864 kOSKextLogStepLevel |
865 kOSKextLogLoadFlag,
866 "Loading kernel external component %s.", bundleID->getCStringNoCopy());
867 OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(),
868 /* allowDefer */ false);
869 }
870 }
871
872finish:
873 OSSafeReleaseNULL(keyIterator);
874 OSSafeReleaseNULL(extensionsDict);
875
876 return;
877}
878
879/*********************************************************************
880 *********************************************************************/
881void
882KLDBootstrap::readBuiltinPersonalities(void)
883{
884 OSObject * parsedXML = NULL; // must release
885 OSArray * builtinExtensions = NULL; // do not release
886 OSArray * allPersonalities = NULL; // must release
887 OSString * errorString = NULL; // must release
888 kernel_section_t * infosect = NULL; // do not free
889 OSCollectionIterator * personalitiesIterator = NULL; // must release
890 unsigned int count, i;
891
892 OSKextLog(/* kext */ NULL,
893 kOSKextLogStepLevel |
894 kOSKextLogLoadFlag,
895 "Reading built-in kernel personalities for I/O Kit drivers.");
896
897 /* Look in the __BUILTIN __info segment for an array of Info.plist
898 * entries. For each one, extract the personalities dictionary, add
899 * it to our array, then push them all (without matching) to
900 * the IOCatalogue. This can be used to augment the personalities
901 * in gIOKernelConfigTables, especially when linking entire kexts into
902 * the mach_kernel image.
903 */
904 infosect = getsectbyname("__BUILTIN", "__info");
905 if (!infosect) {
906 // this isn't fatal
907 goto finish;
908 }
909
910 parsedXML = OSUnserializeXML((const char *) (uintptr_t)infosect->addr,
911 &errorString);
912 if (parsedXML) {
913 builtinExtensions = OSDynamicCast(OSArray, parsedXML);
914 }
915 if (!builtinExtensions) {
916 const char * errorCString = "(unknown error)";
917
918 if (errorString && errorString->getCStringNoCopy()) {
919 errorCString = errorString->getCStringNoCopy();
920 } else if (parsedXML) {
921 errorCString = "not an array";
922 }
923 OSKextLog(/* kext */ NULL,
924 kOSKextLogErrorLevel |
925 kOSKextLogLoadFlag,
926 "Error unserializing built-in personalities: %s.", errorCString);
927 goto finish;
928 }
929
930 // estimate 3 personalities per Info.plist/kext
931 count = builtinExtensions->getCount();
932 allPersonalities = OSArray::withCapacity(count * 3);
933
934 for (i = 0; i < count; i++) {
935 OSDictionary * infoDict = NULL; // do not release
936 OSString * moduleName = NULL; // do not release
937 OSDictionary * personalities; // do not release
938 OSString * personalityName; // do not release
939
940 OSSafeReleaseNULL(personalitiesIterator);
941
942 infoDict = OSDynamicCast(OSDictionary,
943 builtinExtensions->getObject(i));
944 if (!infoDict) {
945 continue;
946 }
947
948 moduleName = OSDynamicCast(OSString,
949 infoDict->getObject(kCFBundleIdentifierKey));
950 if (!moduleName) {
951 continue;
952 }
953
954 OSKextLog(/* kext */ NULL,
955 kOSKextLogStepLevel |
956 kOSKextLogLoadFlag,
957 "Adding personalities for built-in driver %s:",
958 moduleName->getCStringNoCopy());
959
960 personalities = OSDynamicCast(OSDictionary,
961 infoDict->getObject("IOKitPersonalities"));
962 if (!personalities) {
963 continue;
964 }
965
966 personalitiesIterator = OSCollectionIterator::withCollection(personalities);
967 if (!personalitiesIterator) {
968 continue; // xxx - well really, what can we do? should we panic?
969 }
970
971 while ((personalityName = OSDynamicCast(OSString,
972 personalitiesIterator->getNextObject()))) {
973
974 OSDictionary * personality = OSDynamicCast(OSDictionary,
975 personalities->getObject(personalityName));
976
977 OSKextLog(/* kext */ NULL,
978 kOSKextLogDetailLevel |
979 kOSKextLogLoadFlag,
980 "Adding built-in driver personality %s.",
981 personalityName->getCStringNoCopy());
982
983 if (personality && !personality->getObject(kCFBundleIdentifierKey)) {
984 personality->setObject(kCFBundleIdentifierKey, moduleName);
985 }
986 allPersonalities->setObject(personality);
987 }
988 }
989
990 gIOCatalogue->addDrivers(allPersonalities, false);
991
992finish:
993 OSSafeReleaseNULL(parsedXML);
994 OSSafeReleaseNULL(allPersonalities);
995 OSSafeReleaseNULL(errorString);
996 OSSafeReleaseNULL(personalitiesIterator);
997 return;
998}
999
1000#if PRAGMA_MARK
1001#pragma mark Bootstrap Functions
1002#endif
1003/*********************************************************************
1004* Bootstrap Functions
1005*********************************************************************/
1006static void bootstrapRecordStartupExtensions(void)
1007{
1008 sBootstrapObject.readStartupExtensions();
1009 return;
1010}
1011
1012static void bootstrapLoadSecurityExtensions(void)
1013{
1014 sBootstrapObject.loadSecurityExtensions();
1015 return;
1016}
1017