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

Cache object: 54922495d8cc04e39e952e7716943767


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