]> git.saurik.com Git - apple/xnu.git/blame - libsa/bootstrap.cpp
xnu-6153.141.1.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
cb323159 167LIBKERN_ALWAYS_DESTROY static 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
cb323159
A
193 record_startup_extensions_function = NULL;
194 load_security_extensions_function = NULL;
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
0a7de745
A
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
cb323159 763 if (kOSBooleanTrue == theKext->getPropertyForHostArch(kAppleSecurityExtensionKey)) {
0a7de745
A
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 }
b0d623f7
A
772
773finish:
0a7de745
A
774 OSSafeReleaseNULL(keyIterator);
775 OSSafeReleaseNULL(extensionsDict);
b0d623f7 776
0a7de745 777 return;
b0d623f7
A
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*********************************************************************/
791OSReturn
792KLDBootstrap::loadKernelComponentKexts(void)
793{
0a7de745
A
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;
b0d623f7
A
817}
818
316670eb
A
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
829void
830KLDBootstrap::loadKernelExternalComponents(void)
831{
0a7de745
A
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 }
316670eb
A
883
884finish:
0a7de745
A
885 OSSafeReleaseNULL(keyIterator);
886 OSSafeReleaseNULL(extensionsDict);
316670eb 887
0a7de745 888 return;
316670eb
A
889}
890
b0d623f7 891/*********************************************************************
0a7de745 892*********************************************************************/
b0d623f7
A
893void
894KLDBootstrap::readBuiltinPersonalities(void)
895{
0a7de745
A
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
b0d623f7
A
994 if (personality && !personality->getObject(kCFBundleIdentifierKey)) {
995 personality->setObject(kCFBundleIdentifierKey, moduleName);
996 }
0a7de745
A
997 allPersonalities->setObject(personality);
998 }
999 }
1000
1001 gIOCatalogue->addDrivers(allPersonalities, false);
b0d623f7
A
1002
1003finish:
0a7de745
A
1004 OSSafeReleaseNULL(parsedXML);
1005 OSSafeReleaseNULL(allPersonalities);
1006 OSSafeReleaseNULL(errorString);
1007 OSSafeReleaseNULL(personalitiesIterator);
1008 return;
b0d623f7
A
1009}
1010
1011#if PRAGMA_MARK
1012#pragma mark Bootstrap Functions
1013#endif
1014/*********************************************************************
1015* Bootstrap Functions
1016*********************************************************************/
0a7de745
A
1017static void
1018bootstrapRecordStartupExtensions(void)
b0d623f7 1019{
0a7de745
A
1020 sBootstrapObject.readStartupExtensions();
1021 return;
b0d623f7
A
1022}
1023
0a7de745
A
1024static void
1025bootstrapLoadSecurityExtensions(void)
b0d623f7 1026{
0a7de745
A
1027 sBootstrapObject.loadSecurityExtensions();
1028 return;
1c79356b 1029}
6d2010ae 1030