]> git.saurik.com Git - apple/xnu.git/blame - libsa/bootstrap.cpp
xnu-4570.41.2.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
5ba3f43e
A
33#if CONFIG_EMBEDDED
34extern uuid_t kernelcache_uuid;
35#endif
b0d623f7
A
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>
6d2010ae 43#include <IOKit/IOService.h>
b0d623f7
A
44#include <IOKit/IODeviceTreeSupport.h>
45#include <IOKit/IOCatalogue.h>
46
316670eb
A
47#if __x86_64__
48#define KASLR_KEXT_DEBUG 0
49#endif
50
b0d623f7
A
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*********************************************************************/
69extern "C" {
70 extern void (*record_startup_extensions_function)(void);
71 extern void (*load_security_extensions_function)(void);
72};
1c79356b 73
b0d623f7
A
74static void bootstrapRecordStartupExtensions(void);
75static void bootstrapLoadSecurityExtensions(void);
76
6d2010ae 77
39236c6e
A
78#if NO_KEXTD
79extern "C" bool IORamDiskBSDRoot(void);
80#endif
81
b0d623f7
A
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*********************************************************************/
101static 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",
b0d623f7
A
115 NULL
116};
1c79356b 117
39037602
A
118static int __whereIsAddr(vm_offset_t theAddr, unsigned long * segSizes, vm_offset_t *segAddrs, int segCount );
119
813fb2f6 120#define PLK_SEGMENTS 12
39037602
A
121
122static 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",
813fb2f6 132 "__PLK_LLVM_COV",
39037602
A
133 "__PLK_LINKEDIT",
134 "__PRELINK_INFO",
135 NULL
136};
137
b0d623f7
A
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*********************************************************************/
1c79356b 148class KLDBootstrap {
b0d623f7
A
149 friend void bootstrapRecordStartupExtensions(void);
150 friend void bootstrapLoadSecurityExtensions(void);
151
152private:
153 void readStartupExtensions(void);
154
155 void readPrelinkedExtensions(
156 kernel_section_t * prelinkInfoSect);
157 void readBooterExtensions(void);
b0d623f7
A
158
159 OSReturn loadKernelComponentKexts(void);
316670eb 160 void loadKernelExternalComponents(void);
b0d623f7
A
161 void readBuiltinPersonalities(void);
162
163 void loadSecurityExtensions(void);
164
1c79356b 165public:
b0d623f7
A
166 KLDBootstrap(void);
167 ~KLDBootstrap(void);
1c79356b
A
168};
169
b0d623f7 170static KLDBootstrap sBootstrapObject;
1c79356b 171
b0d623f7
A
172/*********************************************************************
173* Set the function pointers for the entry points into the bootstrap
174* segment upon C++ static constructor invocation.
175*********************************************************************/
176KLDBootstrap::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;
b0d623f7
A
183}
184
185/*********************************************************************
186* Clear the function pointers for the entry points into the bootstrap
187* segment upon C++ static destructor invocation.
188*********************************************************************/
189KLDBootstrap::~KLDBootstrap(void)
190{
191 if (this != &sBootstrapObject) {
192 panic("Attempt to access bootstrap segment.");
193 }
6d2010ae
A
194
195
b0d623f7
A
196 record_startup_extensions_function = 0;
197 load_security_extensions_function = 0;
198}
1c79356b 199
b0d623f7
A
200/*********************************************************************
201*********************************************************************/
202void
203KLDBootstrap::readStartupExtensions(void)
204{
205 kernel_section_t * prelinkInfoSect = NULL; // do not free
1c79356b 206
b0d623f7
A
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();
316670eb 226 loadKernelExternalComponents();
b0d623f7
A
227 readBuiltinPersonalities();
228 OSKext::sendAllKextPersonalitiesToCatalog();
229
230 return;
231}
232
39037602
A
233typedef struct kaslrPackedOffsets {
234 uint32_t count; /* number of offsets */
235 uint32_t offsetsArray[]; /* offsets to slide */
236} kaslrPackedOffsets;
237
b0d623f7
A
238/*********************************************************************
239*********************************************************************/
240void
241KLDBootstrap::readPrelinkedExtensions(
242 kernel_section_t * prelinkInfoSect)
243{
244 OSArray * infoDictArray = NULL; // do not release
b0d623f7
A
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
5ba3f43e
A
249#if CONFIG_EMBEDDED
250 OSData * kernelcacheUUID = NULL; // do not release
251#endif
b0d623f7 252
b0d623f7
A
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
b0d623f7 260 vm_size_t prelinkLength = 0;
6d2010ae 261
b0d623f7
A
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;
316670eb 269#if NO_KEXTD
39236c6e 270 bool ramDiskBoot;
316670eb 271 bool developerDevice;
39236c6e 272 bool dontLoad;
316670eb 273#endif
39037602
A
274 OSData * kaslrOffsets = NULL;
275 unsigned long plk_segSizes[PLK_SEGMENTS];
276 vm_offset_t plk_segAddrs[PLK_SEGMENTS];
b0d623f7
A
277
278 OSKextLog(/* kext */ NULL,
279 kOSKextLogProgressLevel |
280 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
281 "Starting from prelinked kernel.");
282
b0d623f7
A
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 }
fe8ab488 291
316670eb
A
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
b0d623f7
A
334
335 prelinkData = (void *) prelinkTextSegment->vmaddr;
336 prelinkLength = prelinkTextSegment->vmsize;
337
39037602
A
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
b0d623f7
A
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
316670eb 367#if NO_KEXTD
39236c6e 368 /* Check if we should keep developer kexts around.
316670eb
A
369 * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201>
370 */
316670eb 371 developerDevice = true;
316670eb 372 PE_parse_boot_argn("developer", &developerDevice, sizeof(developerDevice));
39236c6e
A
373
374 ramDiskBoot = IORamDiskBSDRoot();
316670eb
A
375#endif /* NO_KEXTD */
376
5ba3f43e
A
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, (void *)kernelcacheUUID->getBytesNoCopy(), kernelcacheUUID->getLength());
388 }
389#endif /* CONFIG_EMBEDDED */
39037602 390
b0d623f7
A
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 }
39236c6e 398
39037602
A
399 /* kaslrOffsets are available use them to slide local relocations */
400 kaslrOffsets = OSDynamicCast(OSData,
401 prelinkInfoDict->getObject(kPrelinkLinkKASLROffsetsKey));
402
39236c6e
A
403 /* Create dictionary of excluded kexts
404 */
5ba3f43e 405#ifndef CONFIG_EMBEDDED
39236c6e 406 OSKext::createExcludeListFromPrelinkInfo(infoDictArray);
5ba3f43e 407#endif
39236c6e
A
408 /* Create OSKext objects for each info dictionary.
409 */
b0d623f7
A
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
316670eb 420#if NO_KEXTD
39236c6e
A
421 dontLoad = false;
422
316670eb
A
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) {
39236c6e
A
429 dontLoad = true;
430 }
431 }
316670eb 432
39236c6e
A
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 }
39037602 441 }
39236c6e
A
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) {
5ba3f43e
A
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
39236c6e 461#error Pick the right way to free prelinked data on this arch
5ba3f43e 462#endif
316670eb 463 }
39236c6e
A
464
465 infoDictArray->removeObject(i--);
466 continue;
316670eb
A
467 }
468#endif /* NO_KEXTD */
469
b0d623f7
A
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 */
39037602 474 OSKext * newKext = OSKext::withPrelinkedInfoDict(infoDict, (kaslrOffsets ? TRUE : FALSE));
b0d623f7
A
475 OSSafeReleaseNULL(newKext);
476 }
39037602
A
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 kaslrPackedOffsets * myOffsets = NULL;
485 myOffsets = (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
b0d623f7
A
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 }
39037602 528
b0d623f7
A
529 OSKextLog(/* kext */ NULL,
530 kOSKextLogProgressLevel |
531 kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
532 kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
6d2010ae
A
533 "%u prelinked kexts",
534 infoDictArray->getCount());
b0d623f7 535
316670eb
A
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.
b0d623f7
A
540 */
541 ml_static_mfree((vm_offset_t) prelinkData, prelinkLength);
316670eb 542#endif /* __x86_64__ */
b0d623f7 543
b0d623f7
A
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
552finish:
39037602
A
553 OSSafeReleaseNULL(errorString);
554 OSSafeReleaseNULL(parsedXML);
555 OSSafeReleaseNULL(theKernel);
556 OSSafeReleaseNULL(prelinkCountObj);
b0d623f7 557 return;
1c79356b
A
558}
559
39037602
A
560static 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
b0d623f7
A
577/*********************************************************************
578*********************************************************************/
579#define BOOTER_KEXT_PREFIX "Driver-"
b0d623f7
A
580
581typedef struct _DeviceTreeBuffer {
582 uint32_t paddr;
583 uint32_t length;
584} _DeviceTreeBuffer;
585
586void
587KLDBootstrap::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,
fe8ab488 603 "Reading startup extensions from booter memory.");
b0d623f7
A
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
39236c6e
A
633 /* Create dictionary of excluded kexts
634 */
5ba3f43e 635#ifndef CONFIG_EMBEDDED
39236c6e 636 OSKext::createExcludeListFromBooterData(propertyDict, keyIterator);
5ba3f43e 637#endif
39236c6e
A
638 keyIterator->reset();
639
b0d623f7
A
640 while ( ( deviceTreeName =
641 OSDynamicCast(OSString, keyIterator->getNextObject() ))) {
642
b0d623f7
A
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
fe8ab488
A
656 /* Make sure it is a kext */
657 if (strncmp(devTreeNameCString,
658 BOOTER_KEXT_PREFIX,
659 CONST_STRLEN(BOOTER_KEXT_PREFIX))) {
b0d623f7
A
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,
fe8ab488 682 "Can't get virtual address for device tree entry %s.",
b0d623f7
A
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
fe8ab488
A
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);
39037602 709 OSSafeReleaseNULL(newKext);
b0d623f7
A
710
711 booterMemoryMap->removeProperty(deviceTreeName);
712
713 } /* while ( (deviceTreeName = OSDynamicCast(OSString, ...) ) ) */
714
715finish:
716
39037602
A
717 OSSafeReleaseNULL(booterMemoryMap);
718 OSSafeReleaseNULL(propertyDict);
719 OSSafeReleaseNULL(keyIterator);
720 OSSafeReleaseNULL(booterData);
721 OSSafeReleaseNULL(aKext);
b0d623f7
A
722 return;
723}
724
725/*********************************************************************
726*********************************************************************/
b0d623f7
A
727#define COM_APPLE "com.apple."
728
729void
730KLDBootstrap::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,
316670eb 775 theKext->getPropertyForHostArch(kAppleSecurityExtensionKey));
b0d623f7
A
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
786finish:
39037602
A
787 OSSafeReleaseNULL(keyIterator);
788 OSSafeReleaseNULL(extensionsDict);
b0d623f7
A
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*********************************************************************/
804OSReturn
805KLDBootstrap::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
39037602 830 OSSafeReleaseNULL(theKext);
b0d623f7
A
831 return result;
832}
833
316670eb
A
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
844void
845KLDBootstrap::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
901finish:
39037602
A
902 OSSafeReleaseNULL(keyIterator);
903 OSSafeReleaseNULL(extensionsDict);
316670eb
A
904
905 return;
906}
907
b0d623f7
A
908/*********************************************************************
909 *********************************************************************/
910void
911KLDBootstrap::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.");
1c79356b 925
b0d623f7
A
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.
0b4e3aa0 932 */
b0d623f7
A
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
1021finish:
39037602
A
1022 OSSafeReleaseNULL(parsedXML);
1023 OSSafeReleaseNULL(allPersonalities);
1024 OSSafeReleaseNULL(errorString);
1025 OSSafeReleaseNULL(personalitiesIterator);
b0d623f7
A
1026 return;
1027}
1028
1029#if PRAGMA_MARK
1030#pragma mark Bootstrap Functions
1031#endif
1032/*********************************************************************
1033* Bootstrap Functions
1034*********************************************************************/
1035static void bootstrapRecordStartupExtensions(void)
1036{
1037 sBootstrapObject.readStartupExtensions();
1038 return;
1039}
1040
1041static void bootstrapLoadSecurityExtensions(void)
1042{
1043 sBootstrapObject.loadSecurityExtensions();
1044 return;
1c79356b 1045}
6d2010ae 1046