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