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/kext.cpp

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * The contents of this file constitute Original Code as defined in and
    7  * are subject to the Apple Public Source License Version 1.1 (the
    8  * "License").  You may not use this file except in compliance with the
    9  * License.  Please obtain a copy of the License at
   10  * http://www.apple.com/publicsource and read it before using this file.
   11  * 
   12  * This Original Code and all software distributed under the License are
   13  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   14  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   15  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   16  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
   17  * License for the specific language governing rights and limitations
   18  * under the License.
   19  * 
   20  * @APPLE_LICENSE_HEADER_END@
   21  */
   22 #include <libkern/c++/OSContainers.h>
   23 #include <IOKit/IOCatalogue.h>
   24 #include <IOKit/IOLib.h>
   25 #include <libsa/kext.h>
   26 #include <libsa/catalogue.h>
   27 
   28 extern "C" {
   29 #include <mach-o/kld.h>
   30 #include <libsa/vers_rsrc.h>
   31 #include <libsa/stdlib.h>
   32 #include <mach/kmod.h>
   33 #include <vm/vm_kern.h>
   34 #include <mach/kern_return.h>
   35 #include <mach-o/fat.h>
   36 #include <mach_loader.h>
   37 
   38 #include "kld_patch.h"
   39 #include "dgraph.h"
   40 #include "load.h"
   41 };
   42 
   43 
   44 extern "C" {
   45 extern kern_return_t
   46 kmod_create_internal(
   47             kmod_info_t *info,
   48             kmod_t *id);
   49 
   50 extern kern_return_t
   51 kmod_destroy_internal(kmod_t id);
   52 
   53 extern kern_return_t
   54 kmod_start_or_stop(
   55     kmod_t id,
   56     int start,
   57     kmod_args_t *data,
   58     mach_msg_type_number_t *dataCount);
   59 
   60 extern kern_return_t kmod_retain(kmod_t id);
   61 extern kern_return_t kmod_release(kmod_t id);
   62 
   63 extern void flush_dcache(vm_offset_t addr, unsigned cnt, int phys);
   64 extern void invalidate_icache(vm_offset_t addr, unsigned cnt, int phys);
   65 };
   66 
   67 #define DEBUG
   68 #ifdef DEBUG
   69 #define LOG_DELAY(x)    IODelay((x) * 1000000)
   70 #define VTYELLOW  "\033[33m"
   71 #define VTRESET   "\033[0m"
   72 #else
   73 #define LOG_DELAY(x)
   74 #define VTYELLOW
   75 #define VTRESET
   76 #endif /* DEBUG */
   77 
   78 /*********************************************************************
   79 *
   80 *********************************************************************/
   81 static
   82 bool getKext(
   83     const char * bundleid,
   84     OSDictionary ** plist,
   85     unsigned char ** code,
   86     unsigned long * code_size,
   87     bool * caller_owns_code)
   88 {
   89     bool result = true;
   90     OSDictionary * extensionsDict;   // don't release
   91     OSDictionary * extDict;          // don't release
   92     OSDictionary * extPlist;         // don't release
   93     unsigned long code_size_local;
   94 
   95    /* Get the dictionary of startup extensions.
   96     * This is keyed by module name.
   97     */
   98     extensionsDict = getStartupExtensions();
   99     if (!extensionsDict) {
  100         IOLog("startup extensions dictionary is missing\n");
  101         result = false;
  102         goto finish;
  103     }
  104 
  105    /* Get the requested extension's dictionary entry and its property
  106     * list, containing module dependencies.
  107     */
  108     extDict = OSDynamicCast(OSDictionary,
  109         extensionsDict->getObject(bundleid));
  110 
  111     if (!extDict) {
  112         IOLog("extension \"%s\" cannot be found\n",
  113            bundleid);
  114         result = false;
  115         goto finish;
  116     }
  117 
  118     if (plist) {
  119         extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
  120         if (!extPlist) {
  121             IOLog("extension \"%s\" has no info dictionary\n",
  122                 bundleid);
  123             result = false;
  124             goto finish;
  125         }
  126         *plist = extPlist;
  127     }
  128 
  129     if (code) {
  130 
  131        /* If asking for code, the caller must provide a return buffer
  132         * for ownership!
  133         */
  134         if (!caller_owns_code) {
  135             IOLog("getKext(): invalid usage (caller_owns_code not provided)\n");
  136             result = false;
  137             goto finish;
  138         }
  139     
  140         *code = 0;
  141         if (code_size) {
  142             *code_size = 0;
  143         }
  144         *caller_owns_code = false;
  145     
  146         *code = (unsigned char *)kld_file_getaddr(bundleid,
  147             (long *)&code_size_local);
  148         if (*code) {
  149             if (code_size) {
  150                 *code_size = code_size_local;
  151             }
  152         } else {
  153             OSData * driverCode = 0; // release only if uncompressing!
  154     
  155             driverCode = OSDynamicCast(OSData, extDict->getObject("code"));
  156             if (driverCode) {
  157                 *code = (unsigned char *)driverCode->getBytesNoCopy();
  158                 if (code_size) {
  159                     *code_size = driverCode->getLength();
  160                 }
  161             } else { // Look for compressed code and uncompress it
  162                 OSData * compressedCode = 0;
  163                 compressedCode = OSDynamicCast(OSData,
  164                     extDict->getObject("compressedCode"));
  165                 if (compressedCode) {
  166                     if (!uncompressModule(compressedCode, &driverCode)) {
  167                         IOLog("extension \"%s\": couldn't uncompress code\n",
  168                             bundleid);
  169                         LOG_DELAY(1);
  170                         result = false;
  171                         goto finish;
  172                     }
  173                     *caller_owns_code = true;
  174                     *code = (unsigned char *)driverCode->getBytesNoCopy();
  175                     if (code_size) {
  176                         *code_size = driverCode->getLength();
  177                     }
  178                     driverCode->release();
  179                 }
  180             }
  181         }
  182     }
  183 
  184 finish:
  185 
  186     return result;
  187 }
  188 
  189 
  190 /*********************************************************************
  191 *
  192 *********************************************************************/
  193 static
  194 bool verifyCompatibility(OSString * extName, OSString * requiredVersion)
  195 {
  196     OSDictionary * extPlist;         // don't release
  197     OSString     * extVersion;       // don't release
  198     OSString     * extCompatVersion; // don't release
  199     VERS_version ext_version;
  200     VERS_version ext_compat_version;
  201     VERS_version required_version;
  202 
  203     if (!getKext(extName->getCStringNoCopy(), &extPlist, NULL, NULL, NULL)) {
  204         return false;
  205     }
  206 
  207     extVersion = OSDynamicCast(OSString,
  208         extPlist->getObject("CFBundleVersion"));
  209     if (!extVersion) {
  210         IOLog("verifyCompatibility(): "
  211             "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
  212             extName->getCStringNoCopy());
  213         return false;
  214     }
  215 
  216     extCompatVersion = OSDynamicCast(OSString,
  217         extPlist->getObject("OSBundleCompatibleVersion"));
  218     if (!extCompatVersion) {
  219         IOLog("verifyCompatibility(): "
  220             "Extension \"%s\" has no \"OSBundleCompatibleVersion\" property.\n",
  221             extName->getCStringNoCopy());
  222         return false;
  223     }
  224 
  225     required_version = VERS_parse_string(requiredVersion->getCStringNoCopy());
  226     if (required_version < 0) {
  227         IOLog("verifyCompatibility(): "
  228             "Can't parse required version \"%s\" of dependency %s.\n",
  229             requiredVersion->getCStringNoCopy(),
  230             extName->getCStringNoCopy());
  231         return false;
  232     }
  233     ext_version = VERS_parse_string(extVersion->getCStringNoCopy());
  234     if (ext_version < 0) {
  235         IOLog("verifyCompatibility(): "
  236             "Can't parse version \"%s\" of dependency %s.\n",
  237             extVersion->getCStringNoCopy(),
  238             extName->getCStringNoCopy());
  239         return false;
  240     }
  241     ext_compat_version = VERS_parse_string(extCompatVersion->getCStringNoCopy());
  242     if (ext_compat_version < 0) {
  243         IOLog("verifyCompatibility(): "
  244             "Can't parse compatible version \"%s\" of dependency %s.\n",
  245             extCompatVersion->getCStringNoCopy(),
  246             extName->getCStringNoCopy());
  247         return false;
  248     }
  249 
  250     if (required_version > ext_version || required_version < ext_compat_version) {
  251         return false;
  252     }
  253 
  254     return true;
  255 }
  256 
  257 /*********************************************************************
  258 *********************************************************************/
  259 static
  260 bool kextIsDependency(const char * kext_name, char * is_kernel) {
  261     bool result = true;
  262     OSDictionary * extensionsDict = 0;    // don't release
  263     OSDictionary * extDict = 0;           // don't release
  264     OSDictionary * extPlist = 0;          // don't release
  265     OSBoolean * isKernelResourceObj = 0;  // don't release
  266     OSData * driverCode = 0;              // don't release
  267     OSData * compressedCode = 0;          // don't release
  268 
  269     if (is_kernel) {
  270         *is_kernel = false;
  271     }
  272 
  273    /* Get the dictionary of startup extensions.
  274     * This is keyed by module name.
  275     */
  276     extensionsDict = getStartupExtensions();
  277     if (!extensionsDict) {
  278         IOLog("startup extensions dictionary is missing\n");
  279         result = false;
  280         goto finish;
  281     }
  282 
  283    /* Get the requested extension's dictionary entry and its property
  284     * list, containing module dependencies.
  285     */
  286     extDict = OSDynamicCast(OSDictionary,
  287         extensionsDict->getObject(kext_name));
  288 
  289     if (!extDict) {
  290         IOLog("extension \"%s\" cannot be found\n",
  291            kext_name);
  292         result = false;
  293         goto finish;
  294     }
  295 
  296     extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist"));
  297     if (!extPlist) {
  298         IOLog("extension \"%s\" has no info dictionary\n",
  299             kext_name);
  300         result = false;
  301         goto finish;
  302     }
  303 
  304    /* A kext that is a kernel component is still a dependency, as there
  305     * are fake kmod entries for them.
  306     */
  307     isKernelResourceObj = OSDynamicCast(OSBoolean,
  308         extPlist->getObject("OSKernelResource"));
  309     if (isKernelResourceObj && isKernelResourceObj->isTrue()) {
  310         if (is_kernel) {
  311             *is_kernel = true;
  312         }
  313     }
  314 
  315     driverCode = OSDynamicCast(OSData, extDict->getObject("code"));
  316     compressedCode = OSDynamicCast(OSData,
  317         extDict->getObject("compressedCode"));
  318 
  319     if ((driverCode || compressedCode) && is_kernel && *is_kernel) {
  320         *is_kernel = 2;
  321     }
  322 
  323     if (!driverCode && !compressedCode && !isKernelResourceObj) {
  324         result = false;
  325         goto finish;
  326     }
  327 
  328 finish:
  329 
  330     return result;
  331 }
  332 
  333 /*********************************************************************
  334 *********************************************************************/
  335 static bool
  336 figureDependenciesForKext(OSDictionary * kextPlist,
  337     OSDictionary * dependencies,
  338     OSString * trueParent,
  339     Boolean    skipKernelDependencies)
  340 {
  341     bool result = true;
  342     bool hasDirectKernelDependency = false;
  343     OSString * kextName = 0;  // don't release
  344     OSDictionary * libraries = 0;  // don't release
  345     OSCollectionIterator * keyIterator = 0; // must release
  346     OSString * libraryName = 0; // don't release
  347 
  348     kextName = OSDynamicCast(OSString,
  349         kextPlist->getObject("CFBundleIdentifier"));
  350     if (!kextName) {
  351         // XXX: Add log message
  352         result = false;
  353         goto finish;
  354     }
  355 
  356     libraries = OSDynamicCast(OSDictionary,
  357         kextPlist->getObject("OSBundleLibraries"));
  358     if (!libraries) {
  359         result = true;
  360         goto finish;
  361     }
  362 
  363     keyIterator = OSCollectionIterator::withCollection(libraries);
  364     if (!keyIterator) {
  365         // XXX: Add log message
  366         result = false;
  367         goto finish;
  368     }
  369 
  370     while ( (libraryName = OSDynamicCast(OSString,
  371         keyIterator->getNextObject())) ) {
  372 
  373         OSString * libraryVersion = OSDynamicCast(OSString,
  374             libraries->getObject(libraryName));
  375         if (!libraryVersion) {
  376             // XXX: Add log message
  377             result = false;
  378             goto finish;
  379         }
  380         if (!verifyCompatibility(libraryName, libraryVersion)) {
  381             result = false;
  382             goto finish;
  383         } else {
  384             char is_kernel_component;
  385 
  386             if (!kextIsDependency(libraryName->getCStringNoCopy(), &is_kernel_component))
  387                 is_kernel_component = false;
  388 
  389             if (!skipKernelDependencies || !is_kernel_component) {
  390                 dependencies->setObject(libraryName,
  391                     trueParent ? trueParent : kextName);
  392             }
  393             if (!hasDirectKernelDependency && is_kernel_component) {
  394                 hasDirectKernelDependency = true;
  395             }
  396         }
  397     }
  398     if (!hasDirectKernelDependency) {
  399         /* a kext without any kernel dependency is assumed dependent on 6.0 */
  400         dependencies->setObject("com.apple.kernel.libkern",
  401                 trueParent ? trueParent : kextName);
  402         IOLog("Extension \"%s\" has no kernel dependency.\n",
  403                 kextName->getCStringNoCopy());
  404     }
  405 
  406 finish:
  407     if (keyIterator) keyIterator->release();
  408     return result;
  409 }
  410 
  411 /*********************************************************************
  412 *********************************************************************/
  413 static
  414 bool getVersionForKext(OSDictionary * kextPlist, char ** version)
  415 {
  416     OSString * kextName = 0;  // don't release
  417     OSString * kextVersion;       // don't release
  418 
  419     kextName = OSDynamicCast(OSString,
  420         kextPlist->getObject("CFBundleIdentifier"));
  421     if (!kextName) {
  422         // XXX: Add log message
  423         return false;
  424     }
  425 
  426     kextVersion = OSDynamicCast(OSString,
  427         kextPlist->getObject("CFBundleVersion"));
  428     if (!kextVersion) {
  429         IOLog("getVersionForKext(): "
  430             "Extension \"%s\" has no \"CFBundleVersion\" property.\n",
  431             kextName->getCStringNoCopy());
  432         return false;
  433     }
  434 
  435     if (version) {
  436         *version = (char *)kextVersion->getCStringNoCopy();
  437     }
  438 
  439     return true;
  440 }
  441 
  442 /*********************************************************************
  443 *********************************************************************/
  444 static
  445 bool add_dependencies_for_kmod(const char * kmod_name, dgraph_t * dgraph)
  446 {
  447     bool result = true;
  448     OSDictionary * kextPlist = 0; // don't release
  449     OSDictionary * workingDependencies = 0; // must release
  450     OSDictionary * pendingDependencies = 0; // must release
  451     OSDictionary * swapDict = 0; // don't release
  452     OSString * dependentName = 0; // don't release
  453     const char * dependent_name = 0;  // don't free
  454     OSString * libraryName = 0; // don't release
  455     const char * library_name = 0;  // don't free
  456     OSCollectionIterator * dependencyIterator = 0; // must release
  457     unsigned char * code = 0;
  458     unsigned long code_length = 0;
  459     bool code_is_kmem = false;
  460     char * kmod_vers = 0; // from plist, don't free
  461     char is_kernel_component = false;
  462     dgraph_entry_t * dgraph_entry = 0; // don't free
  463     dgraph_entry_t * dgraph_dependency = 0; // don't free
  464     unsigned int graph_depth = 0;
  465     bool kext_is_dependency = true;
  466 
  467     if (!getKext(kmod_name, &kextPlist, &code, &code_length,
  468         &code_is_kmem)) {
  469         IOLog("can't find extension %s\n", kmod_name);
  470         result = false;
  471         goto finish;
  472     }
  473 
  474     if (!kextIsDependency(kmod_name, &is_kernel_component)) {
  475         IOLog("extension %s is not loadable\n", kmod_name);
  476         result = false;
  477         goto finish;
  478     }
  479 
  480     if (!getVersionForKext(kextPlist, &kmod_vers)) {
  481         IOLog("can't get version for extension %s\n", kmod_name);
  482         result = false;
  483         goto finish;
  484     }
  485 
  486     dgraph_entry = dgraph_add_dependent(dgraph, kmod_name,
  487         code, code_length, code_is_kmem,
  488         kmod_name, kmod_vers,
  489         0 /* load_address not yet known */, is_kernel_component);
  490     if (!dgraph_entry) {
  491         IOLog("can't record %s in dependency graph\n", kmod_name);
  492         result = false;
  493         // kmem_alloc()ed code is freed in finish: block.
  494         goto finish;
  495     }
  496 
  497     // pass ownership of code to kld patcher
  498     if (code)
  499     {
  500         if (kload_map_entry(dgraph_entry) != kload_error_none) {
  501             IOLog("can't map %s in preparation for loading\n", kmod_name);
  502             result = false;
  503             // kmem_alloc()ed code is freed in finish: block.
  504            goto finish;
  505         }
  506     }
  507     // clear local record of code
  508     code = 0;
  509     code_length = 0;
  510     code_is_kmem = false;
  511 
  512     workingDependencies = OSDictionary::withCapacity(5);
  513     if (!workingDependencies) {
  514         IOLog("memory allocation failure\n");
  515         result = false;
  516         goto finish;
  517     }
  518 
  519     pendingDependencies = OSDictionary::withCapacity(5);
  520     if (!pendingDependencies) {
  521         IOLog("memory allocation failure\n");
  522         result = false;
  523         goto finish;
  524     }
  525 
  526     if (!figureDependenciesForKext(kextPlist, workingDependencies, NULL, false)) {
  527         IOLog("can't determine immediate dependencies for extension %s\n",
  528             kmod_name);
  529         result = false;
  530         goto finish;
  531     }
  532 
  533     graph_depth = 0;
  534     while (workingDependencies->getCount()) {
  535         if (graph_depth > 255) {
  536             IOLog("extension dependency graph ridiculously long, indicating a loop\n");
  537             result = false;
  538             goto finish;
  539         }
  540 
  541         if (dependencyIterator) {
  542             dependencyIterator->release();
  543             dependencyIterator = 0;
  544         }
  545 
  546         dependencyIterator = OSCollectionIterator::withCollection(
  547             workingDependencies);
  548         if (!dependencyIterator) {
  549             IOLog("memory allocation failure\n");
  550             result = false;
  551             goto finish;
  552         }
  553 
  554         while ( (libraryName =
  555                  OSDynamicCast(OSString, dependencyIterator->getNextObject())) ) {
  556 
  557             library_name = libraryName->getCStringNoCopy();
  558 
  559             dependentName = OSDynamicCast(OSString,
  560                 workingDependencies->getObject(libraryName));
  561 
  562             dependent_name = dependentName->getCStringNoCopy();
  563 
  564             if (!getKext(library_name, &kextPlist, NULL, NULL, NULL)) {
  565                 IOLog("can't find extension %s\n", library_name);
  566                 result = false;
  567                 goto finish;
  568             }
  569 
  570             OSString * string;
  571             if ((string = OSDynamicCast(OSString,
  572                             kextPlist->getObject("OSBundleSharedExecutableIdentifier"))))
  573             {
  574                 library_name = string->getCStringNoCopy();
  575                 if (!getKext(library_name, &kextPlist, NULL, NULL, NULL)) {
  576                     IOLog("can't find extension %s\n", library_name);
  577                     result = false;
  578                     goto finish;
  579                 }
  580             }
  581 
  582             kext_is_dependency = kextIsDependency(library_name,
  583                 &is_kernel_component);
  584 
  585             if (!kext_is_dependency) {
  586 
  587                /* For binaryless kexts, add a new pending dependency from the
  588                 * original dependent onto the dependencies of the current,
  589                 * binaryless, dependency.
  590                 */
  591                 if (!figureDependenciesForKext(kextPlist, pendingDependencies,
  592                     dependentName, true)) {
  593 
  594                     IOLog("can't determine immediate dependencies for extension %s\n",
  595                         library_name);
  596                     result = false;
  597                     goto finish;
  598                 }
  599                 continue;
  600             } else {
  601                 dgraph_entry = dgraph_find_dependent(dgraph, dependent_name);
  602                 if (!dgraph_entry) {
  603                     IOLog("internal error with dependency graph\n");
  604                     LOG_DELAY(1);
  605                     result = false;
  606                     goto finish;
  607                 }
  608 
  609                 if (!getVersionForKext(kextPlist, &kmod_vers)) {
  610                     IOLog("can't get version for extension %s\n", library_name);
  611                     result = false;
  612                     goto finish;
  613                 }
  614 
  615                /* It's okay for code to be zero, as for a pseudokext
  616                 * representing a kernel component.
  617                 */
  618                 if (!getKext(library_name, NULL /* already got it */,
  619                     &code, &code_length, &code_is_kmem)) {
  620                     IOLog("can't find extension %s\n", library_name);
  621                     result = false;
  622                     goto finish;
  623                 }
  624 
  625                 dgraph_dependency = dgraph_add_dependency(dgraph, dgraph_entry,
  626                     library_name, code, code_length, code_is_kmem,
  627                     library_name, kmod_vers,
  628                     0 /* load_address not yet known */, is_kernel_component);
  629 
  630                 if (!dgraph_dependency) {
  631                     IOLog("can't record dependency %s -> %s\n", dependent_name,
  632                         library_name);
  633                     result = false;
  634                     // kmem_alloc()ed code is freed in finish: block.
  635                     goto finish;
  636                 }
  637 
  638                 // pass ownership of code to kld patcher
  639                 if (code) {
  640                     if (kload_map_entry(dgraph_dependency) != kload_error_none) {
  641                         IOLog("can't map %s in preparation for loading\n", library_name);
  642                         result = false;
  643                         // kmem_alloc()ed code is freed in finish: block.
  644                         goto finish;
  645                     }
  646                 }
  647                 // clear local record of code
  648                 code = 0;
  649                 code_length = 0;
  650                 code_is_kmem = false;
  651             }
  652 
  653            /* Now put the library's dependencies onto the pending set.
  654             */
  655             if (!figureDependenciesForKext(kextPlist, pendingDependencies,
  656                 NULL, false)) {
  657 
  658                 IOLog("can't determine immediate dependencies for extension %s\n",
  659                     library_name);
  660                 result = false;
  661                 goto finish;
  662             }
  663         }
  664 
  665         dependencyIterator->release();
  666         dependencyIterator = 0;
  667 
  668         workingDependencies->flushCollection();
  669         swapDict = workingDependencies;
  670         workingDependencies = pendingDependencies;
  671         pendingDependencies = swapDict;
  672         graph_depth++;
  673     }
  674 
  675 finish:
  676     if (code && code_is_kmem) {
  677         kmem_free(kernel_map, (unsigned int)code, code_length);
  678     }
  679     if (workingDependencies)  workingDependencies->release();
  680     if (pendingDependencies)  pendingDependencies->release();
  681     if (dependencyIterator)   dependencyIterator->release();
  682     return result;
  683 }
  684 
  685 /*********************************************************************
  686 * This is the function that IOCatalogue calls in order to load a kmod.
  687 * It first checks whether the kmod is already loaded. If the kmod
  688 * isn't loaded, this function builds a dependency list and calls
  689 * load_kmod() repeatedly to guarantee that each dependency is in fact
  690 * loaded.
  691 *********************************************************************/
  692 __private_extern__
  693 kern_return_t load_kernel_extension(char * kmod_name)
  694 {
  695     kern_return_t result = KERN_SUCCESS;
  696     kload_error load_result = kload_error_none;
  697     dgraph_t dgraph;
  698     bool free_dgraph = false;
  699     kmod_info_t * kmod_info;
  700 
  701 // Put this in for lots of messages about kext loading.
  702 #if 0
  703     kload_set_log_level(kload_log_level_load_details);
  704 #endif
  705 
  706    /* See if the kmod is already loaded.
  707     */
  708     if ((kmod_info = kmod_lookupbyname_locked(kmod_name))) {
  709         kfree((vm_offset_t) kmod_info, sizeof(kmod_info_t));
  710         return KERN_SUCCESS;
  711     }
  712 
  713     if (dgraph_init(&dgraph) != dgraph_valid) {
  714         IOLog("Can't initialize dependency graph to load %s.\n",
  715             kmod_name);
  716         result = KERN_FAILURE;
  717         goto finish;
  718     }
  719 
  720     free_dgraph = true;
  721     if (!add_dependencies_for_kmod(kmod_name, &dgraph)) {
  722         IOLog("Can't determine dependencies for %s.\n",
  723             kmod_name);
  724         result = KERN_FAILURE;
  725         goto finish;
  726     }
  727 
  728     dgraph.root = dgraph_find_root(&dgraph);
  729 
  730     if (!dgraph.root) {
  731         IOLog("Dependency graph to load %s has no root.\n",
  732             kmod_name);
  733         result = KERN_FAILURE;
  734         goto finish;
  735     }
  736 
  737    /* A kernel component is built in and need not be loaded.
  738     */
  739     if (dgraph.root->is_kernel_component) {
  740         result = KERN_SUCCESS;
  741         goto finish;
  742     }
  743 
  744     dgraph_establish_load_order(&dgraph);
  745 
  746     load_result = kload_load_dgraph(&dgraph);
  747     if (load_result != kload_error_none &&
  748         load_result != kload_error_already_loaded) {
  749 
  750         IOLog(VTYELLOW "Failed to load extension %s.\n" VTRESET, kmod_name);
  751 
  752         result = KERN_FAILURE;
  753         goto finish;
  754     }
  755 
  756 finish:
  757 
  758     if (free_dgraph) {
  759         dgraph_free(&dgraph, 0 /* don't free dgraph itself */);
  760     }
  761     return result;
  762 }

Cache object: f4e6185dbad5e6101d330c3f8e439fb6


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