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