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 */
28extern "C" {
29#include <mach/kmod.h>
30#include <libkern/kernel_mach_header.h>
31#include <libkern/prelink.h>
32}
33
34#include <libkern/version.h>
35#include <libkern/c++/OSContainers.h>
36#include <libkern/OSKextLibPrivate.h>
37#include <libkern/c++/OSKext.h>
38#include <IOKit/IOLib.h>
39#include <IOKit/IOService.h>
40#include <IOKit/IODeviceTreeSupport.h>
41#include <IOKit/IOCatalogue.h>
42
43#if __x86_64__
44#define KASLR_KEXT_DEBUG 0
45#endif
46
47#if PRAGMA_MARK
48#pragma mark Bootstrap Declarations
49#endif
50/*********************************************************************
51* Bootstrap Declarations
52*
53* The ENTIRE point of the libsa/KLD segment is to isolate bootstrap
54* code from other parts of the kernel, so function symbols are not
55* exported; rather pointers to those functions are exported.
56*
57* xxx - need to think about locking for handling the 'weak' refs.
58* xxx - do export a non-KLD function that says you've called a
59* xxx - bootstrap function that has been removed.
60*
61* ALL call-ins to this segment of the kernel must be done through
62* exported pointers. The symbols themselves are private and not to
63* be linked against.
64*********************************************************************/
65extern "C" {
66    extern void (*record_startup_extensions_function)(void);
67    extern void (*load_security_extensions_function)(void);
68};
69
70static void bootstrapRecordStartupExtensions(void);
71static void bootstrapLoadSecurityExtensions(void);
72
73
74#if PRAGMA_MARK
75#pragma mark Macros
76#endif
77/*********************************************************************
78* Macros
79*********************************************************************/
80#define CONST_STRLEN(str) (sizeof(str) - 1)
81
82#if PRAGMA_MARK
83#pragma mark Kernel Component Kext Identifiers
84#endif
85/*********************************************************************
86* Kernel Component Kext Identifiers
87*
88* We could have each kernel resource kext automatically "load" as
89* it's created, but it's nicer to have them listed in kextstat in
90* the order of this list. We'll walk through this after setting up
91* all the boot kexts and have them load up.
92*********************************************************************/
93static const char * sKernelComponentNames[] = {
94   // The kexts for these IDs must have a version matching 'osrelease'.
95   "com.apple.kernel",
96   "com.apple.kpi.bsd",
97   "com.apple.kpi.dsep",
98   "com.apple.kpi.iokit",
99   "com.apple.kpi.libkern",
100   "com.apple.kpi.mach",
101   "com.apple.kpi.private",
102   "com.apple.kpi.unsupported",
103   "com.apple.iokit.IONVRAMFamily",
104   "com.apple.driver.AppleNMI",
105   "com.apple.iokit.IOSystemManagementFamily",
106   "com.apple.iokit.ApplePlatformFamily",
107   NULL
108};
109
110#if PRAGMA_MARK
111#pragma mark KLDBootstrap Class
112#endif
113/*********************************************************************
114* KLDBootstrap Class
115*
116* We use a C++ class here so that it can be a friend of OSKext and
117* get at private stuff. We can't hide the class itself, but we can
118* hide the instance through which we invoke the functions.
119*********************************************************************/
120class KLDBootstrap {
121    friend void bootstrapRecordStartupExtensions(void);
122    friend void bootstrapLoadSecurityExtensions(void);
123
124private:
125    void readStartupExtensions(void);
126
127    void readPrelinkedExtensions(
128        kernel_section_t * prelinkInfoSect);
129    void readBooterExtensions(void);
130    OSReturn readMkextExtensions(
131        OSString * deviceTreeName,
132        OSData   * deviceTreeData);
133
134    OSReturn loadKernelComponentKexts(void);
135    void     loadKernelExternalComponents(void);
136    void     readBuiltinPersonalities(void);
137
138    void     loadSecurityExtensions(void);
139
140public:
141    KLDBootstrap(void);
142    ~KLDBootstrap(void);
143};
144
145static KLDBootstrap sBootstrapObject;
146
147/*********************************************************************
148* Set the function pointers for the entry points into the bootstrap
149* segment upon C++ static constructor invocation.
150*********************************************************************/
151KLDBootstrap::KLDBootstrap(void)
152{
153    if (this != &sBootstrapObject) {
154        panic("Attempt to access bootstrap segment.");
155    }
156    record_startup_extensions_function = &bootstrapRecordStartupExtensions;
157    load_security_extensions_function = &bootstrapLoadSecurityExtensions;
158}
159
160/*********************************************************************
161* Clear the function pointers for the entry points into the bootstrap
162* segment upon C++ static destructor invocation.
163*********************************************************************/
164KLDBootstrap::~KLDBootstrap(void)
165{
166    if (this != &sBootstrapObject) {
167        panic("Attempt to access bootstrap segment.");
168    }
169
170
171    record_startup_extensions_function = 0;
172    load_security_extensions_function = 0;
173}
174
175/*********************************************************************
176*********************************************************************/
177void
178KLDBootstrap::readStartupExtensions(void)
179{
180    kernel_section_t * prelinkInfoSect = NULL;  // do not free
181
182    OSKextLog(/* kext */ NULL,
183        kOSKextLogProgressLevel |
184        kOSKextLogGeneralFlag | kOSKextLogDirectoryScanFlag |
185        kOSKextLogKextBookkeepingFlag,
186        "Reading startup extensions.");
187
188   /* If the prelink info segment has a nonzero size, we are prelinked
189    * and won't have any individual kexts or mkexts to read.
190    * Otherwise, we need to read kexts or the mkext from what the booter
191    * has handed us.
192    */
193    prelinkInfoSect = getsectbyname(kPrelinkInfoSegment, kPrelinkInfoSection);
194    if (prelinkInfoSect->size) {
195        readPrelinkedExtensions(prelinkInfoSect);
196    } else {
197        readBooterExtensions();
198    }
199
200    loadKernelComponentKexts();
201    loadKernelExternalComponents();
202    readBuiltinPersonalities();
203    OSKext::sendAllKextPersonalitiesToCatalog();
204
205    return;
206}
207
208/*********************************************************************
209*********************************************************************/
210void
211KLDBootstrap::readPrelinkedExtensions(
212    kernel_section_t * prelinkInfoSect)
213{
214    OSArray                   * infoDictArray           = NULL;  // do not release
215    OSObject                  * parsedXML       = NULL;  // must release
216    OSDictionary              * prelinkInfoDict         = NULL;  // do not release
217    OSString                  * errorString             = NULL;  // must release
218    OSKext                    * theKernel               = NULL;  // must release
219
220    kernel_segment_command_t  * prelinkTextSegment      = NULL;  // see code
221    kernel_segment_command_t  * prelinkInfoSegment      = NULL;  // see code
222
223   /* We make some copies of data, but if anything fails we're basically
224    * going to fail the boot, so these won't be cleaned up on error.
225    */
226    void                      * prelinkData             = NULL;  // see code
227    vm_size_t                   prelinkLength           = 0;
228
229#if __i386__
230    vm_map_offset_t             prelinkDataMapOffset    = 0;
231    void                      * prelinkCopy             = NULL;  // see code
232    kern_return_t               mem_result              = KERN_SUCCESS;
233#endif
234
235    OSDictionary              * infoDict                = NULL;  // do not release
236
237    IORegistryEntry           * registryRoot            = NULL;  // do not release
238    OSNumber                  * prelinkCountObj         = NULL;  // must release
239
240    u_int                       i = 0;
241#if NO_KEXTD
242    bool                        developerDevice;
243#endif
244
245    OSKextLog(/* kext */ NULL,
246        kOSKextLogProgressLevel |
247        kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
248        "Starting from prelinked kernel.");
249
250    prelinkTextSegment = getsegbyname(kPrelinkTextSegment);
251    if (!prelinkTextSegment) {
252        OSKextLog(/* kext */ NULL,
253            kOSKextLogErrorLevel |
254            kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
255            "Can't find prelinked kexts' text segment.");
256        goto finish;
257    }
258
259#if KASLR_KEXT_DEBUG
260    unsigned long   scratchSize;
261    vm_offset_t     scratchAddr;
262
263    IOLog("kaslr: prelinked kernel address info: \n");
264
265    scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__TEXT", &scratchSize);
266    IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __TEXT \n",
267          (unsigned long)scratchAddr,
268          (unsigned long)(scratchAddr + scratchSize),
269          scratchSize);
270
271    scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__DATA", &scratchSize);
272    IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __DATA \n",
273          (unsigned long)scratchAddr,
274          (unsigned long)(scratchAddr + scratchSize),
275          scratchSize);
276
277    scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__LINKEDIT", &scratchSize);
278    IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __LINKEDIT \n",
279          (unsigned long)scratchAddr,
280          (unsigned long)(scratchAddr + scratchSize),
281          scratchSize);
282
283    scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__KLD", &scratchSize);
284    IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __KLD \n",
285          (unsigned long)scratchAddr,
286          (unsigned long)(scratchAddr + scratchSize),
287          scratchSize);
288
289    scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_TEXT", &scratchSize);
290    IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_TEXT \n",
291          (unsigned long)scratchAddr,
292          (unsigned long)(scratchAddr + scratchSize),
293          scratchSize);
294
295    scratchAddr = (vm_offset_t) getsegdatafromheader(&_mh_execute_header, "__PRELINK_INFO", &scratchSize);
296    IOLog("kaslr: start 0x%lx end 0x%lx length %lu for __PRELINK_INFO \n",
297          (unsigned long)scratchAddr,
298          (unsigned long)(scratchAddr + scratchSize),
299          scratchSize);
300#endif
301
302    prelinkData = (void *) prelinkTextSegment->vmaddr;
303    prelinkLength = prelinkTextSegment->vmsize;
304
305#if __i386__
306    /* To enable paging and write/execute protections on the kext
307     * executables, we need to copy them out of the booter-created
308     * memory, reallocate that space with VM, then prelinkCopy them back in.
309     *
310     * This isn't necessary on x86_64 because kexts have their own VM
311     * region for that architecture.
312     *
313     * XXX: arm's pmap implementation doesn't seem to let us do this.
314     */
315
316    mem_result = kmem_alloc(kernel_map, (vm_offset_t *)&prelinkCopy,
317        prelinkLength);
318    if (mem_result != KERN_SUCCESS) {
319        OSKextLog(/* kext */ NULL,
320            kOSKextLogErrorLevel |
321            kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
322            "Can't copy prelinked kexts' text for VM reassign.");
323        goto finish;
324    }
325
326   /* Copy it out.
327    */
328    memcpy(prelinkCopy, prelinkData, prelinkLength);
329
330   /* Dump the booter memory.
331    */
332    ml_static_mfree((vm_offset_t)prelinkData, prelinkLength);
333
334   /* Set up the VM region.
335    */
336    prelinkDataMapOffset = (vm_map_offset_t)(uintptr_t)prelinkData;
337    mem_result = vm_map_enter_mem_object(
338        kernel_map,
339        &prelinkDataMapOffset,
340        prelinkLength, /* mask */ 0,
341        VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
342        (ipc_port_t)NULL,
343        (vm_object_offset_t) 0,
344        /* copy */ FALSE,
345        /* cur_protection */ VM_PROT_ALL,
346        /* max_protection */ VM_PROT_ALL,
347        /* inheritance */ VM_INHERIT_DEFAULT);
348    if ((mem_result != KERN_SUCCESS) ||
349        (prelinkTextSegment->vmaddr != prelinkDataMapOffset))
350    {
351        OSKextLog(/* kext */ NULL,
352            kOSKextLogErrorLevel |
353            kOSKextLogGeneralFlag | kOSKextLogArchiveFlag,
354            "Can't create kexts' text VM entry at 0x%llx, length 0x%x (error 0x%x).",
355            (unsigned long long) prelinkDataMapOffset, prelinkLength, mem_result);
356        goto finish;
357    }
358    prelinkData = (void *)(uintptr_t)prelinkDataMapOffset;
359
360   /* And copy it back.
361    */
362    memcpy(prelinkData, prelinkCopy, prelinkLength);
363
364    kmem_free(kernel_map, (vm_offset_t)prelinkCopy, prelinkLength);
365#endif /* __i386__ */
366
367   /* Unserialize the info dictionary from the prelink info section.
368    */
369    parsedXML = OSUnserializeXML((const char *)prelinkInfoSect->addr,
370        &errorString);
371    if (parsedXML) {
372        prelinkInfoDict = OSDynamicCast(OSDictionary, parsedXML);
373    }
374    if (!prelinkInfoDict) {
375        const char * errorCString = "(unknown error)";
376
377        if (errorString && errorString->getCStringNoCopy()) {
378            errorCString = errorString->getCStringNoCopy();
379        } else if (parsedXML) {
380            errorCString = "not a dictionary";
381        }
382        OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
383            "Error unserializing prelink plist: %s.", errorCString);
384        goto finish;
385    }
386
387#if NO_KEXTD
388    /* Check if we should keep developer kexts around. Default:
389     *   Release: No
390     *   Development: Yes
391     *   Debug : Yes
392     * TODO: Check DeviceTree instead of a boot-arg <rdar://problem/10604201>
393     */
394#if DEVELOPMENT
395    developerDevice = true;
396#else
397    developerDevice = false;
398#endif
399
400    PE_parse_boot_argn("developer", &developerDevice, sizeof(developerDevice));
401#endif /* NO_KEXTD */
402
403    infoDictArray = OSDynamicCast(OSArray,
404        prelinkInfoDict->getObject(kPrelinkInfoDictionaryKey));
405    if (!infoDictArray) {
406        OSKextLog(/* kext */ NULL, kOSKextLogErrorLevel | kOSKextLogArchiveFlag,
407            "The prelinked kernel has no kext info dictionaries");
408        goto finish;
409    }
410
411   /* Create OSKext objects for each info dictionary.
412    */
413    for (i = 0; i < infoDictArray->getCount(); ++i) {
414        infoDict = OSDynamicCast(OSDictionary, infoDictArray->getObject(i));
415        if (!infoDict) {
416            OSKextLog(/* kext */ NULL,
417                kOSKextLogErrorLevel |
418                kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
419                "Can't find info dictionary for prelinked kext #%d.", i);
420            continue;
421        }
422
423#if NO_KEXTD
424        /* If we're not on a developer device, skip and free developer kexts.
425         */
426        if (developerDevice == false) {
427            OSBoolean *devOnlyBool = OSDynamicCast(OSBoolean,
428                infoDict->getObject(kOSBundleDeveloperOnlyKey));
429            if (devOnlyBool == kOSBooleanTrue) {
430                OSString *bundleID = OSDynamicCast(OSString,
431                    infoDict->getObject(kCFBundleIdentifierKey));
432                if (bundleID) {
433                    OSKextLog(NULL, kOSKextLogWarningLevel | kOSKextLogGeneralFlag,
434                        "Kext %s not loading on non-dev device.", bundleID->getCStringNoCopy());
435                }
436
437                OSNumber *addressNum = OSDynamicCast(OSNumber,
438                    infoDict->getObject(kPrelinkExecutableLoadKey));
439                OSNumber *lengthNum = OSDynamicCast(OSNumber,
440                    infoDict->getObject(kPrelinkExecutableSizeKey));
441                if (addressNum && lengthNum) {
442#error Pick the right way to free prelinked data on this arch
443                }
444
445                infoDictArray->removeObject(i--);
446                continue;
447            }
448        }
449#endif /* NO_KEXTD */
450
451       /* Create the kext for the entry, then release it, because the
452        * kext system keeps them around until explicitly removed.
453        * Any creation/registration failures are already logged for us.
454        */
455        OSKext * newKext = OSKext::withPrelinkedInfoDict(infoDict);
456        OSSafeReleaseNULL(newKext);
457    }
458
459   /* Store the number of prelinked kexts in the registry so we can tell
460    * when the system has been started from a prelinked kernel.
461    */
462    registryRoot = IORegistryEntry::getRegistryRoot();
463    assert(registryRoot);
464
465    prelinkCountObj = OSNumber::withNumber(
466        (unsigned long long)infoDictArray->getCount(),
467        8 * sizeof(uint32_t));
468    assert(prelinkCountObj);
469    if (prelinkCountObj) {
470        registryRoot->setProperty(kOSPrelinkKextCountKey, prelinkCountObj);
471    }
472
473    OSKextLog(/* kext */ NULL,
474        kOSKextLogProgressLevel |
475        kOSKextLogGeneralFlag | kOSKextLogKextBookkeepingFlag |
476        kOSKextLogDirectoryScanFlag | kOSKextLogArchiveFlag,
477        "%u prelinked kexts",
478        infoDictArray->getCount());
479
480#if CONFIG_KEXT_BASEMENT
481        /* On CONFIG_KEXT_BASEMENT systems, kexts are copied to their own
482         * special VM region during OSKext init time, so we can free the whole
483         * segment now.
484         */
485        ml_static_mfree((vm_offset_t) prelinkData, prelinkLength);
486#endif /* __x86_64__ */
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
496finish:
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
509typedef struct _DeviceTreeBuffer {
510    uint32_t paddr;
511    uint32_t length;
512} _DeviceTreeBuffer;
513
514void
515KLDBootstrap::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
649finish:
650
651    OSSafeRelease(booterMemoryMap);
652    OSSafeRelease(propertyDict);
653    OSSafeRelease(keyIterator);
654    OSSafeRelease(booterData);
655    OSSafeRelease(aKext);
656    return;
657}
658
659/*********************************************************************
660*********************************************************************/
661OSReturn
662KLDBootstrap::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
706void
707KLDBootstrap::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(kAppleSecurityExtensionKey));
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
763finish:
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*********************************************************************/
781OSReturn
782KLDBootstrap::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* Ensure that Kernel External Components are loaded early in boot,
813* before other kext personalities get sent to the IOCatalogue. These
814* kexts are treated specially because they may provide the implementation
815* for kernel-vended KPI, so they must register themselves before
816* general purpose IOKit probing begins.
817*********************************************************************/
818
819#define COM_APPLE_KEC  "com.apple.kec."
820
821void
822KLDBootstrap::loadKernelExternalComponents(void)
823{
824    OSDictionary         * extensionsDict = NULL;  // must release
825    OSCollectionIterator * keyIterator    = NULL;  // must release
826    OSString             * bundleID       = NULL;  // don't release
827    OSKext               * theKext        = NULL;  // don't release
828    OSBoolean            * isKernelExternalComponent = NULL;  // don't release
829
830    OSKextLog(/* kext */ NULL,
831        kOSKextLogStepLevel |
832        kOSKextLogLoadFlag,
833        "Loading Kernel External Components.");
834
835    extensionsDict = OSKext::copyKexts();
836    if (!extensionsDict) {
837        return;
838    }
839
840    keyIterator = OSCollectionIterator::withCollection(extensionsDict);
841    if (!keyIterator) {
842        OSKextLog(/* kext */ NULL,
843            kOSKextLogErrorLevel |
844            kOSKextLogGeneralFlag,
845            "Failed to allocate iterator for Kernel External Components.");
846        goto finish;
847    }
848
849    while ((bundleID = OSDynamicCast(OSString, keyIterator->getNextObject()))) {
850
851        const char * bundle_id = bundleID->getCStringNoCopy();
852
853       /* Skip extensions whose bundle IDs don't start with "com.apple.kec.".
854        */
855        if (!bundle_id ||
856            (strncmp(bundle_id, COM_APPLE_KEC, CONST_STRLEN(COM_APPLE_KEC)) != 0)) {
857
858            continue;
859        }
860
861        theKext = OSDynamicCast(OSKext, extensionsDict->getObject(bundleID));
862        if (!theKext) {
863            continue;
864        }
865
866        isKernelExternalComponent = OSDynamicCast(OSBoolean,
867            theKext->getPropertyForHostArch(kAppleKernelExternalComponentKey));
868        if (isKernelExternalComponent && isKernelExternalComponent->isTrue()) {
869            OSKextLog(/* kext */ NULL,
870                kOSKextLogStepLevel |
871                kOSKextLogLoadFlag,
872                "Loading kernel external component %s.", bundleID->getCStringNoCopy());
873            OSKext::loadKextWithIdentifier(bundleID->getCStringNoCopy(),
874                /* allowDefer */ false);
875        }
876    }
877
878finish:
879    OSSafeRelease(keyIterator);
880    OSSafeRelease(extensionsDict);
881
882    return;
883}
884
885/*********************************************************************
886 *********************************************************************/
887void
888KLDBootstrap::readBuiltinPersonalities(void)
889{
890    OSObject              * parsedXML             = NULL;  // must release
891    OSArray               * builtinExtensions     = NULL;  // do not release
892    OSArray               * allPersonalities      = NULL;  // must release
893    OSString              * errorString           = NULL;  // must release
894    kernel_section_t      * infosect              = NULL;  // do not free
895    OSCollectionIterator  * personalitiesIterator = NULL;  // must release
896    unsigned int            count, i;
897
898    OSKextLog(/* kext */ NULL,
899        kOSKextLogStepLevel |
900        kOSKextLogLoadFlag,
901        "Reading built-in kernel personalities for I/O Kit drivers.");
902
903   /* Look in the __BUILTIN __info segment for an array of Info.plist
904    * entries. For each one, extract the personalities dictionary, add
905    * it to our array, then push them all (without matching) to
906    * the IOCatalogue. This can be used to augment the personalities
907    * in gIOKernelConfigTables, especially when linking entire kexts into
908    * the mach_kernel image.
909    */
910    infosect   = getsectbyname("__BUILTIN", "__info");
911    if (!infosect) {
912        // this isn't fatal
913        goto finish;
914    }
915
916    parsedXML = OSUnserializeXML((const char *) (uintptr_t)infosect->addr,
917        &errorString);
918    if (parsedXML) {
919        builtinExtensions = OSDynamicCast(OSArray, parsedXML);
920    }
921    if (!builtinExtensions) {
922        const char * errorCString = "(unknown error)";
923
924        if (errorString && errorString->getCStringNoCopy()) {
925            errorCString = errorString->getCStringNoCopy();
926        } else if (parsedXML) {
927            errorCString = "not an array";
928        }
929        OSKextLog(/* kext */ NULL,
930            kOSKextLogErrorLevel |
931            kOSKextLogLoadFlag,
932            "Error unserializing built-in personalities: %s.", errorCString);
933        goto finish;
934    }
935
936    // estimate 3 personalities per Info.plist/kext
937    count = builtinExtensions->getCount();
938    allPersonalities = OSArray::withCapacity(count * 3);
939
940    for (i = 0; i < count; i++) {
941        OSDictionary            * infoDict = NULL;      // do not release
942        OSString                * moduleName = NULL;    // do not release
943        OSDictionary            * personalities;        // do not release
944        OSString                * personalityName;      // do not release
945
946        OSSafeReleaseNULL(personalitiesIterator);
947
948        infoDict = OSDynamicCast(OSDictionary,
949            builtinExtensions->getObject(i));
950        if (!infoDict) {
951            continue;
952        }
953
954        moduleName = OSDynamicCast(OSString,
955            infoDict->getObject(kCFBundleIdentifierKey));
956        if (!moduleName) {
957            continue;
958        }
959
960        OSKextLog(/* kext */ NULL,
961            kOSKextLogStepLevel |
962            kOSKextLogLoadFlag,
963            "Adding personalities for built-in driver %s:",
964            moduleName->getCStringNoCopy());
965
966        personalities = OSDynamicCast(OSDictionary,
967            infoDict->getObject("IOKitPersonalities"));
968        if (!personalities) {
969            continue;
970        }
971
972        personalitiesIterator = OSCollectionIterator::withCollection(personalities);
973        if (!personalitiesIterator) {
974            continue;  // xxx - well really, what can we do? should we panic?
975        }
976
977        while ((personalityName = OSDynamicCast(OSString,
978            personalitiesIterator->getNextObject()))) {
979
980            OSDictionary * personality = OSDynamicCast(OSDictionary,
981                personalities->getObject(personalityName));
982
983            OSKextLog(/* kext */ NULL,
984                kOSKextLogDetailLevel |
985                kOSKextLogLoadFlag,
986                "Adding built-in driver personality %s.",
987                personalityName->getCStringNoCopy());
988
989			if (personality && !personality->getObject(kCFBundleIdentifierKey)) {
990				personality->setObject(kCFBundleIdentifierKey, moduleName);
991			}
992            allPersonalities->setObject(personality);
993        }
994    }
995
996    gIOCatalogue->addDrivers(allPersonalities, false);
997
998finish:
999    OSSafeRelease(parsedXML);
1000    OSSafeRelease(allPersonalities);
1001    OSSafeRelease(errorString);
1002    OSSafeRelease(personalitiesIterator);
1003    return;
1004}
1005
1006#if PRAGMA_MARK
1007#pragma mark Bootstrap Functions
1008#endif
1009/*********************************************************************
1010* Bootstrap Functions
1011*********************************************************************/
1012static void bootstrapRecordStartupExtensions(void)
1013{
1014    sBootstrapObject.readStartupExtensions();
1015    return;
1016}
1017
1018static void bootstrapLoadSecurityExtensions(void)
1019{
1020    sBootstrapObject.loadSecurityExtensions();
1021    return;
1022}
1023
1024