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

Cache object: 339a54e6811798b676f96da577169fd3


[ 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.