The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/libsa/bootstrap.cpp

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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/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 *********************************************************************/
   65 extern "C" {
   66     extern void (*record_startup_extensions_function)(void);
   67     extern void (*load_security_extensions_function)(void);
   68 };
   69 
   70 static void bootstrapRecordStartupExtensions(void);
   71 static 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 *********************************************************************/
   93 static 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 *********************************************************************/
  120 class KLDBootstrap {
  121     friend void bootstrapRecordStartupExtensions(void);
  122     friend void bootstrapLoadSecurityExtensions(void);
  123 
  124 private:
  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     
  140 public:
  141     KLDBootstrap(void);
  142     ~KLDBootstrap(void);
  143 };
  144 
  145 static KLDBootstrap sBootstrapObject;
  146 
  147 /*********************************************************************
  148 * Set the function pointers for the entry points into the bootstrap
  149 * segment upon C++ static constructor invocation.
  150 *********************************************************************/
  151 KLDBootstrap::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 *********************************************************************/
  164 KLDBootstrap::~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 *********************************************************************/
  177 void
  178 KLDBootstrap::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 *********************************************************************/
  210 void
  211 KLDBootstrap::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 
  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(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 
  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 * 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 
  821 void
  822 KLDBootstrap::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 
  878 finish:
  879     OSSafeRelease(keyIterator);
  880     OSSafeRelease(extensionsDict);
  881 
  882     return;
  883 }
  884 
  885 /*********************************************************************
  886  *********************************************************************/
  887 void
  888 KLDBootstrap::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 
  998 finish:
  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 *********************************************************************/
 1012 static void bootstrapRecordStartupExtensions(void)
 1013 {
 1014     sBootstrapObject.readStartupExtensions();
 1015     return;
 1016 }
 1017 
 1018 static void bootstrapLoadSecurityExtensions(void)
 1019 {
 1020     sBootstrapObject.loadSecurityExtensions();
 1021     return;
 1022 }
 1023 

Cache object: 9a22387d0cce6acb7c0b15541b5093d7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.