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