]> git.saurik.com Git - apple/xnu.git/blob - libsa/bootstrap.cpp
xnu-4570.61.1.tar.gz
[apple/xnu.git] / libsa / bootstrap.cpp
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 */
28 extern "C" {
29 #include <mach/kmod.h>
30 #include <libkern/kernel_mach_header.h>
31 #include <libkern/prelink.h>
32
33 #if CONFIG_EMBEDDED
34 extern uuid_t kernelcache_uuid;
35 #endif
36 }
37
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>
46
47 #if __x86_64__
48 #define KASLR_KEXT_DEBUG 0
49 #endif
50
51 #if PRAGMA_MARK
52 #pragma mark Bootstrap Declarations
53 #endif
54 /*********************************************************************
55 * Bootstrap Declarations
56 *
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.
60 *
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.
64 *
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
67 * be linked against.
68 *********************************************************************/
69 extern "C" {
70 extern void (*record_startup_extensions_function)(void);
71 extern void (*load_security_extensions_function)(void);
72 };
73
74 static void bootstrapRecordStartupExtensions(void);
75 static void bootstrapLoadSecurityExtensions(void);
76
77
78 #if NO_KEXTD
79 extern "C" bool IORamDiskBSDRoot(void);
80 #endif
81
82 #if PRAGMA_MARK
83 #pragma mark Macros
84 #endif
85 /*********************************************************************
86 * Macros
87 *********************************************************************/
88 #define CONST_STRLEN(str) (sizeof(str) - 1)
89
90 #if PRAGMA_MARK
91 #pragma mark Kernel Component Kext Identifiers
92 #endif
93 /*********************************************************************
94 * Kernel Component Kext Identifiers
95 *
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'.
103 "com.apple.kernel",
104 "com.apple.kpi.bsd",
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",
115 NULL
116 };
117
118 static int __whereIsAddr(vm_offset_t theAddr, unsigned long * segSizes, vm_offset_t *segAddrs, int segCount );
119
120 #define PLK_SEGMENTS 12
121
122 static const char * plk_segNames[] = {
123 "__TEXT",
124 "__TEXT_EXEC",
125 "__DATA",
126 "__DATA_CONST",
127 "__LINKEDIT",
128 "__PRELINK_TEXT",
129 "__PLK_TEXT_EXEC",
130 "__PRELINK_DATA",
131 "__PLK_DATA_CONST",
132 "__PLK_LLVM_COV",
133 "__PLK_LINKEDIT",
134 "__PRELINK_INFO",
135 NULL
136 };
137
138 #if PRAGMA_MARK
139 #pragma mark KLDBootstrap Class
140 #endif
141 /*********************************************************************
142 * KLDBootstrap Class
143 *
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 *********************************************************************/
148 class KLDBootstrap {
149 friend void bootstrapRecordStartupExtensions(void);
150 friend void bootstrapLoadSecurityExtensions(void);
151
152 private:
153 void readStartupExtensions(void);
154
155 void readPrelinkedExtensions(
156 kernel_section_t * prelinkInfoSect);
157 void readBooterExtensions(void);
158
159 OSReturn loadKernelComponentKexts(void);
160 void loadKernelExternalComponents(void);
161 void readBuiltinPersonalities(void);
162
163 void loadSecurityExtensions(void);
164
165 public:
166 KLDBootstrap(void);
167 ~KLDBootstrap(void);
168 };
169
170 static KLDBootstrap sBootstrapObject;
171
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)
177 {
178 if (this != &sBootstrapObject) {
179 panic("Attempt to access bootstrap segment.");
180 }
181 record_startup_extensions_function = &bootstrapRecordStartupExtensions;
182 load_security_extensions_function = &bootstrapLoadSecurityExtensions;
183 }
184
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)
190 {
191 if (this != &sBootstrapObject) {
192 panic("Attempt to access bootstrap segment.");
193 }
194
195
196 record_startup_extensions_function = 0;
197 load_security_extensions_function = 0;
198 }
199
200 /*********************************************************************
201 *********************************************************************/
202 void
203 KLDBootstrap::readStartupExtensions(void)
204 {
205 kernel_section_t * prelinkInfoSect = NULL; // do not free
206
207 OSKextLog(/* kext */ NULL,
208 kOSKextLogProgressLevel |
209 kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag |
210 kOSKextLogKextBookkeepingFlag,
211 "Reading startup extensions.");
212
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
216 * has handed us.
217 */
218 prelinkInfoSect = getsectbyname(kPrelinkInfoSegment, kPrelinkInfoSection);
219 if (prelinkInfoSect->size) {
220 readPrelinkedExtensions(prelinkInfoSect);
221 } else {
222 readBooterExtensions();
223 }
224
225 loadKernelComponentKexts();
226 loadKernelExternalComponents();
227 readBuiltinPersonalities();
228 OSKext::sendAllKextPersonalitiesToCatalog();
229
230 return;
231 }
232
233 typedef struct kaslrPackedOffsets {
234 uint32_t count; /* number of offsets */
235 uint32_t offsetsArray[]; /* offsets to slide */
236 } kaslrPackedOffsets;
237
238 /*********************************************************************
239 *********************************************************************/
240 void
241 KLDBootstrap::readPrelinkedExtensions(
242 kernel_section_t * prelinkInfoSect)
243 {
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
249 #if CONFIG_EMBEDDED
250 OSData * kernelcacheUUID = NULL; // do not release
251 #endif
252
253 kernel_segment_command_t * prelinkTextSegment = NULL; // see code
254 kernel_segment_command_t * prelinkInfoSegment = NULL; // see code
255
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.
258 */
259 void * prelinkData = NULL; // see code
260 vm_size_t prelinkLength = 0;
261
262
263 OSDictionary * infoDict = NULL; // do not release
264
265 IORegistryEntry * registryRoot = NULL; // do not release
266 OSNumber * prelinkCountObj = NULL; // must release
267
268 u_int i = 0;
269 #if NO_KEXTD
270 bool ramDiskBoot;
271 bool developerDevice;
272 bool dontLoad;
273 #endif
274 OSData * kaslrOffsets = NULL;
275 unsigned long plk_segSizes[PLK_SEGMENTS];
276 vm_offset_t plk_segAddrs[PLK_SEGMENTS];
277
278 OSKextLog(/* kext */ NULL,
279 kOSKextLogProgressLevel |
280 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
281 "Starting from prelinked kernel.");
282
283 prelinkTextSegment = getsegbyname(kPrelinkTextSegment);
284 if (!prelinkTextSegment) {
285 OSKextLog(/* kext */ NULL,
286 kOSKextLogErrorLevel |
287 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
288 "Can't find prelinked kexts' text segment.");
289 goto finish;
290 }
291
292 #if KASLR_KEXT_DEBUG
293 unsigned long scratchSize;
294 vm_offset_t scratchAddr;
295
296 IOLog("kaslr: prelinked kernel address info: \n");
297
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),
302 scratchSize);
303
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),
308 scratchSize);
309
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),
314 scratchSize);
315
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),
320 scratchSize);
321
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),
326 scratchSize);
327
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),
332 scratchSize);
333 #endif
334
335 prelinkData = (void *) prelinkTextSegment->vmaddr;
336 prelinkLength = prelinkTextSegment->vmsize;
337
338 /* build arrays of plk info for later use */
339 const char ** segNamePtr;
340
341 for (segNamePtr = &plk_segNames[0], i = 0; *segNamePtr && i < PLK_SEGMENTS; segNamePtr++, i++) {
342 plk_segSizes[i] = 0;
343 plk_segAddrs[i] = (vm_offset_t)getsegdatafromheader(&_mh_execute_header, *segNamePtr, &plk_segSizes[i]);
344 }
345
346
347 /* Unserialize the info dictionary from the prelink info section.
348 */
349 parsedXML = OSUnserializeXML((const char *)prelinkInfoSect->addr,
350 &errorString);
351 if (parsedXML) {
352 prelinkInfoDict = OSDynamicCast(OSDictionary, parsedXML);
353 }
354 if (!prelinkInfoDict) {
355 const char * errorCString = "(unknown error)";
356
357 if (errorString && errorString->getCStringNoCopy()) {
358 errorCString = errorString->getCStringNoCopy();
359 } else if (parsedXML) {
360 errorCString = "not a dictionary";
361 }
362 OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
363 "Error unserializing prelink plist: %s.", errorCString);
364 goto finish;
365 }
366
367 #if NO_KEXTD
368 /* Check if we should keep developer kexts around.
369 * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201>
370 */
371 developerDevice = true;
372 PE_parse_boot_argn("developer", &developerDevice, sizeof(developerDevice));
373
374 ramDiskBoot = IORamDiskBSDRoot();
375 #endif /* NO_KEXTD */
376
377 #if CONFIG_EMBEDDED
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));
386 } else {
387 memcpy((void *)&kernelcache_uuid, (const void *)kernelcacheUUID->getBytesNoCopy(), kernelcacheUUID->getLength());
388 }
389 #endif /* CONFIG_EMBEDDED */
390
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");
396 goto finish;
397 }
398
399 /* kaslrOffsets are available use them to slide local relocations */
400 kaslrOffsets = OSDynamicCast(OSData,
401 prelinkInfoDict->getObject(kPrelinkLinkKASLROffsetsKey));
402
403 /* Create dictionary of excluded kexts
404 */
405 #ifndef CONFIG_EMBEDDED
406 OSKext::createExcludeListFromPrelinkInfo(infoDictArray);
407 #endif
408 /* Create OSKext objects for each info dictionary.
409 */
410 for (i = 0; i < infoDictArray->getCount(); ++i) {
411 infoDict = OSDynamicCast(OSDictionary, infoDictArray->getObject(i));
412 if (!infoDict) {
413 OSKextLog(/* kext */ NULL,
414 kOSKextLogErrorLevel |
415 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
416 "Can't find info dictionary for prelinked kext #%d.", i);
417 continue;
418 }
419
420 #if NO_KEXTD
421 dontLoad = false;
422
423 /* If we're not on a developer device, skip and free developer kexts.
424 */
425 if (developerDevice == false) {
426 OSBoolean *devOnlyBool = OSDynamicCast(OSBoolean,
427 infoDict->getObject(kOSBundleDeveloperOnlyKey));
428 if (devOnlyBool == kOSBooleanTrue) {
429 dontLoad = true;
430 }
431 }
432
433 /* Skip and free kexts that are only needed when booted from a ram disk.
434 */
435 if (ramDiskBoot == false) {
436 OSBoolean *ramDiskOnlyBool = OSDynamicCast(OSBoolean,
437 infoDict->getObject(kOSBundleRamDiskOnlyKey));
438 if (ramDiskOnlyBool == kOSBooleanTrue) {
439 dontLoad = true;
440 }
441 }
442
443 if (dontLoad == true) {
444 OSString *bundleID = OSDynamicCast(OSString,
445 infoDict->getObject(kCFBundleIdentifierKey));
446 if (bundleID) {
447 OSKextLog(NULL, kOSKextLogWarningLevel | kOSKextLogGeneralFlag,
448 "Kext %s not loading.", bundleID->getCStringNoCopy());
449 }
450
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);
460 #else
461 #error Pick the right way to free prelinked data on this arch
462 #endif
463 }
464
465 infoDictArray->removeObject(i--);
466 continue;
467 }
468 #endif /* NO_KEXTD */
469
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.
473 */
474 OSKext * newKext = OSKext::withPrelinkedInfoDict(infoDict, (kaslrOffsets ? TRUE : FALSE));
475 OSSafeReleaseNULL(newKext);
476 }
477
478 /* slide kxld relocations */
479 if (kaslrOffsets && vm_kernel_slide > 0) {
480 int slidKextAddrCount = 0;
481 int badSlideAddr = 0;
482 int badSlideTarget = 0;
483
484 const kaslrPackedOffsets * myOffsets = NULL;
485 myOffsets = (const kaslrPackedOffsets *) kaslrOffsets->getBytesNoCopy();
486
487 for (uint32_t j = 0; j < myOffsets->count; j++) {
488
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;
493
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) {
498 badSlideTarget++;
499 continue;
500 }
501 }
502 else {
503 badSlideAddr++;
504 continue;
505 }
506
507 slidKextAddrCount++;
508 *(slideAddr) += vm_kernel_slide;
509 } // for ...
510
511 /* All kexts are now slid, set VM protections for them */
512 OSKext::setAllVMAttributes();
513 }
514
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.
517 */
518 registryRoot = IORegistryEntry::getRegistryRoot();
519 assert(registryRoot);
520
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);
527 }
528
529 OSKextLog(/* kext */ NULL,
530 kOSKextLogProgressLevel |
531 kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
532 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
533 "%u prelinked kexts",
534 infoDictArray->getCount());
535
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
539 * segment now.
540 */
541 ml_static_mfree((vm_offset_t) prelinkData, prelinkLength);
542 #endif /* __x86_64__ */
543
544 /* Free the prelink info segment, we're done with it.
545 */
546 prelinkInfoSegment = getsegbyname(kPrelinkInfoSegment);
547 if (prelinkInfoSegment) {
548 ml_static_mfree((vm_offset_t)prelinkInfoSegment->vmaddr,
549 (vm_size_t)prelinkInfoSegment->vmsize);
550 }
551
552 finish:
553 OSSafeReleaseNULL(errorString);
554 OSSafeReleaseNULL(parsedXML);
555 OSSafeReleaseNULL(theKernel);
556 OSSafeReleaseNULL(prelinkCountObj);
557 return;
558 }
559
560 static int __whereIsAddr(vm_offset_t theAddr, unsigned long * segSizes, vm_offset_t *segAddrs, int segCount)
561 {
562 int i;
563
564 for (i = 0; i < segCount; i++) {
565 vm_offset_t myAddr = *(segAddrs + i);
566 unsigned long mySize = *(segSizes + i);
567
568 if (theAddr >= myAddr && theAddr < (myAddr + mySize)) {
569 return i;
570 }
571 }
572
573 return -1;
574 }
575
576
577 /*********************************************************************
578 *********************************************************************/
579 #define BOOTER_KEXT_PREFIX "Driver-"
580
581 typedef struct _DeviceTreeBuffer {
582 uint32_t paddr;
583 uint32_t length;
584 } _DeviceTreeBuffer;
585
586 void
587 KLDBootstrap::readBooterExtensions(void)
588 {
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
593
594 const _DeviceTreeBuffer * deviceTreeBuffer = NULL; // do not free
595 char * booterDataPtr = NULL; // do not free
596 OSData * booterData = NULL; // must release
597
598 OSKext * aKext = NULL; // must release
599
600 OSKextLog(/* kext */ NULL,
601 kOSKextLogProgressLevel |
602 kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag,
603 "Reading startup extensions from booter memory.");
604
605 booterMemoryMap = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane);
606
607 if (!booterMemoryMap) {
608 OSKextLog(/* kext */ NULL,
609 kOSKextLogErrorLevel |
610 kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag,
611 "Can't read booter memory map.");
612 goto finish;
613 }
614
615 propertyDict = booterMemoryMap->dictionaryWithProperties();
616 if (!propertyDict) {
617 OSKextLog(/* kext */ NULL,
618 kOSKextLogErrorLevel |
619 kOSKextLogDirectoryScanFlag,
620 "Can't get property dictionary from memory map.");
621 goto finish;
622 }
623
624 keyIterator = OSCollectionIterator::withCollection(propertyDict);
625 if (!keyIterator) {
626 OSKextLog(/* kext */ NULL,
627 kOSKextLogErrorLevel |
628 kOSKextLogGeneralFlag,
629 "Can't allocate iterator for driver images.");
630 goto finish;
631 }
632
633 /* Create dictionary of excluded kexts
634 */
635 #ifndef CONFIG_EMBEDDED
636 OSKext::createExcludeListFromBooterData(propertyDict, keyIterator);
637 #endif
638 keyIterator->reset();
639
640 while ( ( deviceTreeName =
641 OSDynamicCast(OSString, keyIterator->getNextObject() ))) {
642
643 const char * devTreeNameCString = deviceTreeName->getCStringNoCopy();
644 OSData * deviceTreeEntry = OSDynamicCast(OSData,
645 propertyDict->getObject(deviceTreeName));
646
647 /* Clear out the booterData from the prior iteration.
648 */
649 OSSafeReleaseNULL(booterData);
650
651 /* If there is no entry for the name, we can't do much with it. */
652 if (!deviceTreeEntry) {
653 continue;
654 }
655
656 /* Make sure it is a kext */
657 if (strncmp(devTreeNameCString,
658 BOOTER_KEXT_PREFIX,
659 CONST_STRLEN(BOOTER_KEXT_PREFIX))) {
660 continue;
661 }
662
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).
668 */
669 OSKextLog(/* kext */ NULL,
670 kOSKextLogErrorLevel |
671 kOSKextLogDirectoryScanFlag,
672 "Device tree entry %s has NULL pointer.",
673 devTreeNameCString);
674 goto finish; // xxx - continue, panic?
675 }
676
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.",
683 devTreeNameCString);
684 goto finish;
685 }
686
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.
691 */
692 booterData = OSData::withBytesNoCopy(booterDataPtr,
693 deviceTreeBuffer->length);
694 if (!booterData) {
695 OSKextLog(/* kext */ NULL,
696 kOSKextLogErrorLevel |
697 kOSKextLogGeneralFlag,
698 "Error - Can't allocate OSData wrapper for device tree entry %s.",
699 devTreeNameCString);
700 goto finish;
701 }
702 booterData->setDeallocFunction(osdata_phys_free);
703
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.
707 */
708 OSKext * newKext = OSKext::withBooterData(deviceTreeName, booterData);
709 OSSafeReleaseNULL(newKext);
710
711 booterMemoryMap->removeProperty(deviceTreeName);
712
713 } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */
714
715 finish:
716
717 OSSafeReleaseNULL(booterMemoryMap);
718 OSSafeReleaseNULL(propertyDict);
719 OSSafeReleaseNULL(keyIterator);
720 OSSafeReleaseNULL(booterData);
721 OSSafeReleaseNULL(aKext);
722 return;
723 }
724
725 /*********************************************************************
726 *********************************************************************/
727 #define COM_APPLE "com.apple."
728
729 void
730 KLDBootstrap::loadSecurityExtensions(void)
731 {
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
737
738 OSKextLog(/* kext */ NULL,
739 kOSKextLogStepLevel |
740 kOSKextLogLoadFlag,
741 "Loading security extensions.");
742
743 extensionsDict = OSKext::copyKexts();
744 if (!extensionsDict) {
745 return;
746 }
747
748 keyIterator = OSCollectionIterator::withCollection(extensionsDict);
749 if (!keyIterator) {
750 OSKextLog(/* kext */ NULL,
751 kOSKextLogErrorLevel |
752 kOSKextLogGeneralFlag,
753 "Failed to allocate iterator for security extensions.");
754 goto finish;
755 }
756
757 while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
758
759 const char * bundle_id = bundleID->getCStringNoCopy();
760
761 /* Skip extensions whose bundle IDs don't start with "com.apple.".
762 */
763 if (!bundle_id ||
764 (strncmp(bundle_id, COM_APPLE, CONST_STRLEN(COM_APPLE)) != 0)) {
765
766 continue;
767 }
768
769 theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID));
770 if (!theKext) {
771 continue;
772 }
773
774 isSecurityKext = OSDynamicCast(OSBoolean,
775 theKext->getPropertyForHostArch(kAppleSecurityExtensionKey));
776 if (isSecurityKext && isSecurityKext->isTrue()) {
777 OSKextLog(/* kext */ NULL,
778 kOSKextLogStepLevel |
779 kOSKextLogLoadFlag,
780 "Loading security extension %s.", bundleID->getCStringNoCopy());
781 OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(),
782 /* allowDefer */ false);
783 }
784 }
785
786 finish:
787 OSSafeReleaseNULL(keyIterator);
788 OSSafeReleaseNULL(extensionsDict);
789
790 return;
791 }
792
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.
797 *
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.
800 *
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 *********************************************************************/
804 OSReturn
805 KLDBootstrap::loadKernelComponentKexts(void)
806 {
807 OSReturn result = kOSReturnSuccess; // optimistic
808 OSKext * theKext = NULL; // must release
809 const char ** kextIDPtr = NULL; // do not release
810
811 for (kextIDPtr = &sKernelComponentNames[0]; *kextIDPtr; kextIDPtr++) {
812
813 OSSafeReleaseNULL(theKext);
814 theKext = OSKext::lookupKextWithIdentifier(*kextIDPtr);
815
816 if (theKext) {
817 if (kOSReturnSuccess != OSKext::loadKextWithIdentifier(
818 *kextIDPtr, /* allowDefer */ false)) {
819
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;
826 }
827 }
828 }
829
830 OSSafeReleaseNULL(theKext);
831 return result;
832 }
833
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 *********************************************************************/
841
842 #define COM_APPLE_KEC "com.apple.kec."
843
844 void
845 KLDBootstrap::loadKernelExternalComponents(void)
846 {
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
852
853 OSKextLog(/* kext */ NULL,
854 kOSKextLogStepLevel |
855 kOSKextLogLoadFlag,
856 "Loading Kernel External Components.");
857
858 extensionsDict = OSKext::copyKexts();
859 if (!extensionsDict) {
860 return;
861 }
862
863 keyIterator = OSCollectionIterator::withCollection(extensionsDict);
864 if (!keyIterator) {
865 OSKextLog(/* kext */ NULL,
866 kOSKextLogErrorLevel |
867 kOSKextLogGeneralFlag,
868 "Failed to allocate iterator for Kernel External Components.");
869 goto finish;
870 }
871
872 while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
873
874 const char * bundle_id = bundleID->getCStringNoCopy();
875
876 /* Skip extensions whose bundle IDs don't start with "com.apple.kec.".
877 */
878 if (!bundle_id ||
879 (strncmp(bundle_id, COM_APPLE_KEC, CONST_STRLEN(COM_APPLE_KEC)) != 0)) {
880
881 continue;
882 }
883
884 theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID));
885 if (!theKext) {
886 continue;
887 }
888
889 isKernelExternalComponent = OSDynamicCast(OSBoolean,
890 theKext->getPropertyForHostArch(kAppleKernelExternalComponentKey));
891 if (isKernelExternalComponent && isKernelExternalComponent->isTrue()) {
892 OSKextLog(/* kext */ NULL,
893 kOSKextLogStepLevel |
894 kOSKextLogLoadFlag,
895 "Loading kernel external component %s.", bundleID->getCStringNoCopy());
896 OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(),
897 /* allowDefer */ false);
898 }
899 }
900
901 finish:
902 OSSafeReleaseNULL(keyIterator);
903 OSSafeReleaseNULL(extensionsDict);
904
905 return;
906 }
907
908 /*********************************************************************
909 *********************************************************************/
910 void
911 KLDBootstrap::readBuiltinPersonalities(void)
912 {
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;
920
921 OSKextLog(/* kext */ NULL,
922 kOSKextLogStepLevel |
923 kOSKextLogLoadFlag,
924 "Reading built-in kernel personalities for I/O Kit drivers.");
925
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.
932 */
933 infosect = getsectbyname("__BUILTIN", "__info");
934 if (!infosect) {
935 // this isn't fatal
936 goto finish;
937 }
938
939 parsedXML = OSUnserializeXML((const char *) (uintptr_t)infosect->addr,
940 &errorString);
941 if (parsedXML) {
942 builtinExtensions = OSDynamicCast(OSArray, parsedXML);
943 }
944 if (!builtinExtensions) {
945 const char * errorCString = "(unknown error)";
946
947 if (errorString && errorString->getCStringNoCopy()) {
948 errorCString = errorString->getCStringNoCopy();
949 } else if (parsedXML) {
950 errorCString = "not an array";
951 }
952 OSKextLog(/* kext */ NULL,
953 kOSKextLogErrorLevel |
954 kOSKextLogLoadFlag,
955 "Error unserializing built-in personalities: %s.", errorCString);
956 goto finish;
957 }
958
959 // estimate 3 personalities per Info.plist/kext
960 count = builtinExtensions->getCount();
961 allPersonalities = OSArray::withCapacity(count * 3);
962
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
968
969 OSSafeReleaseNULL(personalitiesIterator);
970
971 infoDict = OSDynamicCast(OSDictionary,
972 builtinExtensions->getObject(i));
973 if (!infoDict) {
974 continue;
975 }
976
977 moduleName = OSDynamicCast(OSString,
978 infoDict->getObject(kCFBundleIdentifierKey));
979 if (!moduleName) {
980 continue;
981 }
982
983 OSKextLog(/* kext */ NULL,
984 kOSKextLogStepLevel |
985 kOSKextLogLoadFlag,
986 "Adding personalities for built-in driver %s:",
987 moduleName->getCStringNoCopy());
988
989 personalities = OSDynamicCast(OSDictionary,
990 infoDict->getObject("IOKitPersonalities"));
991 if (!personalities) {
992 continue;
993 }
994
995 personalitiesIterator = OSCollectionIterator::withCollection(personalities);
996 if (!personalitiesIterator) {
997 continue; // xxx - well really, what can we do? should we panic?
998 }
999
1000 while ((personalityName = OSDynamicCast(OSString,
1001 personalitiesIterator->getNextObject()))) {
1002
1003 OSDictionary * personality = OSDynamicCast(OSDictionary,
1004 personalities->getObject(personalityName));
1005
1006 OSKextLog(/* kext */ NULL,
1007 kOSKextLogDetailLevel |
1008 kOSKextLogLoadFlag,
1009 "Adding built-in driver personality %s.",
1010 personalityName->getCStringNoCopy());
1011
1012 if (personality && !personality->getObject(kCFBundleIdentifierKey)) {
1013 personality->setObject(kCFBundleIdentifierKey, moduleName);
1014 }
1015 allPersonalities->setObject(personality);
1016 }
1017 }
1018
1019 gIOCatalogue->addDrivers(allPersonalities, false);
1020
1021 finish:
1022 OSSafeReleaseNULL(parsedXML);
1023 OSSafeReleaseNULL(allPersonalities);
1024 OSSafeReleaseNULL(errorString);
1025 OSSafeReleaseNULL(personalitiesIterator);
1026 return;
1027 }
1028
1029 #if PRAGMA_MARK
1030 #pragma mark Bootstrap Functions
1031 #endif
1032 /*********************************************************************
1033 * Bootstrap Functions
1034 *********************************************************************/
1035 static void bootstrapRecordStartupExtensions(void)
1036 {
1037 sBootstrapObject.readStartupExtensions();
1038 return;
1039 }
1040
1041 static void bootstrapLoadSecurityExtensions(void)
1042 {
1043 sBootstrapObject.loadSecurityExtensions();
1044 return;
1045 }
1046