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