]> git.saurik.com Git - apple/xnu.git/blame - libsa/bootstrap.cpp
xnu-4903.270.47.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@
0a7de745 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.
0a7de745 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.
0a7de745 17 *
2d21ac55
A
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.
0a7de745 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>
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>
6d2010ae 39#include <IOKit/IOService.h>
b0d623f7
A
40#include <IOKit/IODeviceTreeSupport.h>
41#include <IOKit/IOCatalogue.h>
42
316670eb
A
43#if __x86_64__
44#define KASLR_KEXT_DEBUG 0
45#endif
46
b0d623f7
A
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*********************************************************************/
65extern "C" {
0a7de745
A
66extern void (*record_startup_extensions_function)(void);
67extern void (*load_security_extensions_function)(void);
b0d623f7 68};
1c79356b 69
b0d623f7
A
70static void bootstrapRecordStartupExtensions(void);
71static void bootstrapLoadSecurityExtensions(void);
72
6d2010ae 73
39236c6e
A
74#if NO_KEXTD
75extern "C" bool IORamDiskBSDRoot(void);
76#endif
77
b0d623f7
A
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*********************************************************************/
97static const char * sKernelComponentNames[] = {
0a7de745
A
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
b0d623f7 113};
1c79356b 114
39037602
A
115static int __whereIsAddr(vm_offset_t theAddr, unsigned long * segSizes, vm_offset_t *segAddrs, int segCount );
116
813fb2f6 117#define PLK_SEGMENTS 12
39037602
A
118
119static const char * plk_segNames[] = {
0a7de745
A
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
39037602
A
133};
134
b0d623f7
A
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*********************************************************************/
1c79356b 145class KLDBootstrap {
0a7de745
A
146 friend void bootstrapRecordStartupExtensions(void);
147 friend void bootstrapLoadSecurityExtensions(void);
b0d623f7
A
148
149private:
0a7de745
A
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
1c79356b 162public:
0a7de745
A
163 KLDBootstrap(void);
164 ~KLDBootstrap(void);
1c79356b
A
165};
166
b0d623f7 167static KLDBootstrap sBootstrapObject;
1c79356b 168
b0d623f7
A
169/*********************************************************************
170* Set the function pointers for the entry points into the bootstrap
171* segment upon C++ static constructor invocation.
172*********************************************************************/
173KLDBootstrap::KLDBootstrap(void)
174{
0a7de745
A
175 if (this != &sBootstrapObject) {
176 panic("Attempt to access bootstrap segment.");
177 }
178 record_startup_extensions_function = &bootstrapRecordStartupExtensions;
179 load_security_extensions_function = &bootstrapLoadSecurityExtensions;
b0d623f7
A
180}
181
182/*********************************************************************
183* Clear the function pointers for the entry points into the bootstrap
184* segment upon C++ static destructor invocation.
185*********************************************************************/
186KLDBootstrap::~KLDBootstrap(void)
187{
0a7de745
A
188 if (this != &sBootstrapObject) {
189 panic("Attempt to access bootstrap segment.");
190 }
6d2010ae
A
191
192
0a7de745
A
193 record_startup_extensions_function = 0;
194 load_security_extensions_function = 0;
b0d623f7 195}
1c79356b 196
b0d623f7
A
197/*********************************************************************
198*********************************************************************/
199void
200KLDBootstrap::readStartupExtensions(void)
201{
0a7de745
A
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;
b0d623f7
A
228}
229
39037602 230typedef struct kaslrPackedOffsets {
0a7de745
A
231 uint32_t count; /* number of offsets */
232 uint32_t offsetsArray[]; /* offsets to slide */
39037602
A
233} kaslrPackedOffsets;
234
b0d623f7
A
235/*********************************************************************
236*********************************************************************/
237void
238KLDBootstrap::readPrelinkedExtensions(
0a7de745 239 kernel_section_t * prelinkInfoSect)
b0d623f7 240{
0a7de745
A
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
b0d623f7 247
0a7de745
A
248 kernel_segment_command_t * prelinkTextSegment = NULL;// see code
249 kernel_segment_command_t * prelinkInfoSegment = NULL;// see code
b0d623f7 250
0a7de745
A
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;
6d2010ae 256
b0d623f7 257
0a7de745 258 OSDictionary * infoDict = NULL;// do not release
b0d623f7 259
0a7de745
A
260 IORegistryEntry * registryRoot = NULL;// do not release
261 OSNumber * prelinkCountObj = NULL;// must release
b0d623f7 262
0a7de745 263 u_int i = 0;
316670eb 264#if NO_KEXTD
0a7de745
A
265 bool ramDiskBoot;
266 bool developerDevice;
267 bool dontLoad;
316670eb 268#endif
0a7de745
A
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 }
fe8ab488 286
316670eb 287#if KASLR_KEXT_DEBUG
0a7de745
A
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);
316670eb 328#endif
b0d623f7 329
0a7de745
A
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 }
b0d623f7 361
316670eb 362#if NO_KEXTD
0a7de745
A
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));
39236c6e 368
0a7de745 369 ramDiskBoot = IORamDiskBSDRoot();
316670eb
A
370#endif /* NO_KEXTD */
371
0a7de745
A
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 */
5ba3f43e 400#ifndef CONFIG_EMBEDDED
0a7de745 401 OSKext::createExcludeListFromPrelinkInfo(infoDictArray);
5ba3f43e 402#endif
0a7de745
A
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 }
b0d623f7 414
316670eb 415#if NO_KEXTD
0a7de745
A
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) {
5ba3f43e 451#if __arm__ || __arm64__
0a7de745
A
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);
5ba3f43e 455#else
39236c6e 456#error Pick the right way to free prelinked data on this arch
5ba3f43e 457#endif
0a7de745 458 }
39236c6e 459
0a7de745
A
460 infoDictArray->removeObject(i--);
461 continue;
462 }
316670eb
A
463#endif /* NO_KEXTD */
464
0a7de745
A
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());
b0d623f7 528
316670eb 529#if CONFIG_KEXT_BASEMENT
0a7de745
A
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);
316670eb 535#endif /* __x86_64__ */
b0d623f7 536
0a7de745
A
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 }
b0d623f7
A
544
545finish:
0a7de745
A
546 OSSafeReleaseNULL(errorString);
547 OSSafeReleaseNULL(parsedXML);
548 OSSafeReleaseNULL(theKernel);
549 OSSafeReleaseNULL(prelinkCountObj);
550 return;
1c79356b
A
551}
552
0a7de745
A
553static int
554__whereIsAddr(vm_offset_t theAddr, unsigned long * segSizes, vm_offset_t *segAddrs, int segCount)
39037602
A
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
b0d623f7
A
571/*********************************************************************
572*********************************************************************/
573#define BOOTER_KEXT_PREFIX "Driver-"
b0d623f7
A
574
575typedef struct _DeviceTreeBuffer {
0a7de745
A
576 uint32_t paddr;
577 uint32_t length;
b0d623f7
A
578} _DeviceTreeBuffer;
579
580void
581KLDBootstrap::readBooterExtensions(void)
582{
0a7de745
A
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 */
5ba3f43e 629#ifndef CONFIG_EMBEDDED
0a7de745 630 OSKext::createExcludeListFromBooterData(propertyDict, keyIterator);
5ba3f43e 631#endif
0a7de745
A
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, ...) ) ) */
b0d623f7
A
706
707finish:
708
0a7de745
A
709 OSSafeReleaseNULL(booterMemoryMap);
710 OSSafeReleaseNULL(propertyDict);
711 OSSafeReleaseNULL(keyIterator);
712 OSSafeReleaseNULL(booterData);
713 OSSafeReleaseNULL(aKext);
714 return;
b0d623f7
A
715}
716
717/*********************************************************************
718*********************************************************************/
b0d623f7
A
719#define COM_APPLE "com.apple."
720
721void
722KLDBootstrap::loadSecurityExtensions(void)
723{
0a7de745
A
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 OSBoolean * isSecurityKext = NULL;// don't release
729
730 OSKextLog(/* kext */ NULL,
731 kOSKextLogStepLevel |
732 kOSKextLogLoadFlag,
733 "Loading security extensions.");
734
735 extensionsDict = OSKext::copyKexts();
736 if (!extensionsDict) {
737 return;
738 }
739
740 keyIterator = OSCollectionIterator::withCollection(extensionsDict);
741 if (!keyIterator) {
742 OSKextLog(/* kext */ NULL,
743 kOSKextLogErrorLevel |
744 kOSKextLogGeneralFlag,
745 "Failed to allocate iterator for security extensions.");
746 goto finish;
747 }
748
749 while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
750 const char * bundle_id = bundleID->getCStringNoCopy();
751
752 /* Skip extensions whose bundle IDs don't start with "com.apple.".
753 */
754 if (!bundle_id ||
755 (strncmp(bundle_id, COM_APPLE, CONST_STRLEN(COM_APPLE)) != 0)) {
756 continue;
757 }
758
759 theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID));
760 if (!theKext) {
761 continue;
762 }
763
764 isSecurityKext = OSDynamicCast(OSBoolean,
765 theKext->getPropertyForHostArch(kAppleSecurityExtensionKey));
766 if (isSecurityKext && isSecurityKext->isTrue()) {
767 OSKextLog(/* kext */ NULL,
768 kOSKextLogStepLevel |
769 kOSKextLogLoadFlag,
770 "Loading security extension %s.", bundleID->getCStringNoCopy());
771 OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(),
772 /* allowDefer */ false);
773 }
774 }
b0d623f7
A
775
776finish:
0a7de745
A
777 OSSafeReleaseNULL(keyIterator);
778 OSSafeReleaseNULL(extensionsDict);
b0d623f7 779
0a7de745 780 return;
b0d623f7
A
781}
782
783/*********************************************************************
784* We used to require that all listed kernel components load, but
785* nowadays we can get them from userland so we only try to load the
786* ones we have. If an error occurs later, such is life.
787*
788* Note that we look the kexts up first, so we can avoid spurious
789* (in this context, anyhow) log messages about kexts not being found.
790*
791* xxx - do we even need to do this any more? Check if the kernel
792* xxx - compoonents just load in the regular paths
793*********************************************************************/
794OSReturn
795KLDBootstrap::loadKernelComponentKexts(void)
796{
0a7de745
A
797 OSReturn result = kOSReturnSuccess;// optimistic
798 OSKext * theKext = NULL; // must release
799 const char ** kextIDPtr = NULL; // do not release
800
801 for (kextIDPtr = &sKernelComponentNames[0]; *kextIDPtr; kextIDPtr++) {
802 OSSafeReleaseNULL(theKext);
803 theKext = OSKext::lookupKextWithIdentifier(*kextIDPtr);
804
805 if (theKext) {
806 if (kOSReturnSuccess != OSKext::loadKextWithIdentifier(
807 *kextIDPtr, /* allowDefer */ false)) {
808 // xxx - check KextBookkeeping, might be redundant
809 OSKextLog(/* kext */ NULL,
810 kOSKextLogErrorLevel |
811 kOSKextLogDirectoryScanFlag | kOSKextLogKextBookkeepingFlag,
812 "Failed to initialize kernel component %s.", *kextIDPtr);
813 result = kOSReturnError;
814 }
815 }
816 }
817
818 OSSafeReleaseNULL(theKext);
819 return result;
b0d623f7
A
820}
821
316670eb
A
822/*********************************************************************
823* Ensure that Kernel External Components are loaded early in boot,
824* before other kext personalities get sent to the IOCatalogue. These
825* kexts are treated specially because they may provide the implementation
826* for kernel-vended KPI, so they must register themselves before
827* general purpose IOKit probing begins.
828*********************************************************************/
829
830#define COM_APPLE_KEC "com.apple.kec."
831
832void
833KLDBootstrap::loadKernelExternalComponents(void)
834{
0a7de745
A
835 OSDictionary * extensionsDict = NULL;// must release
836 OSCollectionIterator * keyIterator = NULL;// must release
837 OSString * bundleID = NULL;// don't release
838 OSKext * theKext = NULL;// don't release
839 OSBoolean * isKernelExternalComponent = NULL;// don't release
840
841 OSKextLog(/* kext */ NULL,
842 kOSKextLogStepLevel |
843 kOSKextLogLoadFlag,
844 "Loading Kernel External Components.");
845
846 extensionsDict = OSKext::copyKexts();
847 if (!extensionsDict) {
848 return;
849 }
850
851 keyIterator = OSCollectionIterator::withCollection(extensionsDict);
852 if (!keyIterator) {
853 OSKextLog(/* kext */ NULL,
854 kOSKextLogErrorLevel |
855 kOSKextLogGeneralFlag,
856 "Failed to allocate iterator for Kernel External Components.");
857 goto finish;
858 }
859
860 while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
861 const char * bundle_id = bundleID->getCStringNoCopy();
862
863 /* Skip extensions whose bundle IDs don't start with "com.apple.kec.".
864 */
865 if (!bundle_id ||
866 (strncmp(bundle_id, COM_APPLE_KEC, CONST_STRLEN(COM_APPLE_KEC)) != 0)) {
867 continue;
868 }
869
870 theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID));
871 if (!theKext) {
872 continue;
873 }
874
875 isKernelExternalComponent = OSDynamicCast(OSBoolean,
876 theKext->getPropertyForHostArch(kAppleKernelExternalComponentKey));
877 if (isKernelExternalComponent && isKernelExternalComponent->isTrue()) {
878 OSKextLog(/* kext */ NULL,
879 kOSKextLogStepLevel |
880 kOSKextLogLoadFlag,
881 "Loading kernel external component %s.", bundleID->getCStringNoCopy());
882 OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(),
883 /* allowDefer */ false);
884 }
885 }
316670eb
A
886
887finish:
0a7de745
A
888 OSSafeReleaseNULL(keyIterator);
889 OSSafeReleaseNULL(extensionsDict);
316670eb 890
0a7de745 891 return;
316670eb
A
892}
893
b0d623f7 894/*********************************************************************
0a7de745 895*********************************************************************/
b0d623f7
A
896void
897KLDBootstrap::readBuiltinPersonalities(void)
898{
0a7de745
A
899 OSObject * parsedXML = NULL;// must release
900 OSArray * builtinExtensions = NULL;// do not release
901 OSArray * allPersonalities = NULL;// must release
902 OSString * errorString = NULL;// must release
903 kernel_section_t * infosect = NULL;// do not free
904 OSCollectionIterator * personalitiesIterator = NULL;// must release
905 unsigned int count, i;
906
907 OSKextLog(/* kext */ NULL,
908 kOSKextLogStepLevel |
909 kOSKextLogLoadFlag,
910 "Reading built-in kernel personalities for I/O Kit drivers.");
911
912 /* Look in the __BUILTIN __info segment for an array of Info.plist
913 * entries. For each one, extract the personalities dictionary, add
914 * it to our array, then push them all (without matching) to
915 * the IOCatalogue. This can be used to augment the personalities
916 * in gIOKernelConfigTables, especially when linking entire kexts into
917 * the mach_kernel image.
918 */
919 infosect = getsectbyname("__BUILTIN", "__info");
920 if (!infosect) {
921 // this isn't fatal
922 goto finish;
923 }
924
925 parsedXML = OSUnserializeXML((const char *) (uintptr_t)infosect->addr,
926 &errorString);
927 if (parsedXML) {
928 builtinExtensions = OSDynamicCast(OSArray, parsedXML);
929 }
930 if (!builtinExtensions) {
931 const char * errorCString = "(unknown error)";
932
933 if (errorString && errorString->getCStringNoCopy()) {
934 errorCString = errorString->getCStringNoCopy();
935 } else if (parsedXML) {
936 errorCString = "not an array";
937 }
938 OSKextLog(/* kext */ NULL,
939 kOSKextLogErrorLevel |
940 kOSKextLogLoadFlag,
941 "Error unserializing built-in personalities: %s.", errorCString);
942 goto finish;
943 }
944
945 // estimate 3 personalities per Info.plist/kext
946 count = builtinExtensions->getCount();
947 allPersonalities = OSArray::withCapacity(count * 3);
948
949 for (i = 0; i < count; i++) {
950 OSDictionary * infoDict = NULL;// do not release
951 OSString * moduleName = NULL;// do not release
952 OSDictionary * personalities;// do not release
953 OSString * personalityName;// do not release
954
955 OSSafeReleaseNULL(personalitiesIterator);
956
957 infoDict = OSDynamicCast(OSDictionary,
958 builtinExtensions->getObject(i));
959 if (!infoDict) {
960 continue;
961 }
962
963 moduleName = OSDynamicCast(OSString,
964 infoDict->getObject(kCFBundleIdentifierKey));
965 if (!moduleName) {
966 continue;
967 }
968
969 OSKextLog(/* kext */ NULL,
970 kOSKextLogStepLevel |
971 kOSKextLogLoadFlag,
972 "Adding personalities for built-in driver %s:",
973 moduleName->getCStringNoCopy());
974
975 personalities = OSDynamicCast(OSDictionary,
976 infoDict->getObject("IOKitPersonalities"));
977 if (!personalities) {
978 continue;
979 }
980
981 personalitiesIterator = OSCollectionIterator::withCollection(personalities);
982 if (!personalitiesIterator) {
983 continue; // xxx - well really, what can we do? should we panic?
984 }
985
986 while ((personalityName = OSDynamicCast(OSString,
987 personalitiesIterator->getNextObject()))) {
988 OSDictionary * personality = OSDynamicCast(OSDictionary,
989 personalities->getObject(personalityName));
990
991 OSKextLog(/* kext */ NULL,
992 kOSKextLogDetailLevel |
993 kOSKextLogLoadFlag,
994 "Adding built-in driver personality %s.",
995 personalityName->getCStringNoCopy());
996
b0d623f7
A
997 if (personality && !personality->getObject(kCFBundleIdentifierKey)) {
998 personality->setObject(kCFBundleIdentifierKey, moduleName);
999 }
0a7de745
A
1000 allPersonalities->setObject(personality);
1001 }
1002 }
1003
1004 gIOCatalogue->addDrivers(allPersonalities, false);
b0d623f7
A
1005
1006finish:
0a7de745
A
1007 OSSafeReleaseNULL(parsedXML);
1008 OSSafeReleaseNULL(allPersonalities);
1009 OSSafeReleaseNULL(errorString);
1010 OSSafeReleaseNULL(personalitiesIterator);
1011 return;
b0d623f7
A
1012}
1013
1014#if PRAGMA_MARK
1015#pragma mark Bootstrap Functions
1016#endif
1017/*********************************************************************
1018* Bootstrap Functions
1019*********************************************************************/
0a7de745
A
1020static void
1021bootstrapRecordStartupExtensions(void)
b0d623f7 1022{
0a7de745
A
1023 sBootstrapObject.readStartupExtensions();
1024 return;
b0d623f7
A
1025}
1026
0a7de745
A
1027static void
1028bootstrapLoadSecurityExtensions(void)
b0d623f7 1029{
0a7de745
A
1030 sBootstrapObject.loadSecurityExtensions();
1031 return;
1c79356b 1032}
6d2010ae 1033