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/kern/kern_module.c

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 /*      $NetBSD: kern_module.c,v 1.24.4.1 2009/02/02 22:15:15 snj Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   26  * POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 /*
   30  * Kernel module support.
   31  */
   32 
   33 #include "opt_modular.h"
   34 
   35 #include <sys/cdefs.h>
   36 __KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.24.4.1 2009/02/02 22:15:15 snj Exp $");
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/fcntl.h>
   41 #include <sys/proc.h>
   42 #include <sys/kauth.h>
   43 #include <sys/kobj.h>
   44 #include <sys/kmem.h>
   45 #include <sys/module.h>
   46 #include <sys/kauth.h>
   47 
   48 #include <uvm/uvm_extern.h>
   49 
   50 #include <machine/stdarg.h>
   51 
   52 #ifndef LKM     /* XXX */
   53 struct vm_map *lkm_map;
   54 #endif
   55 
   56 struct modlist  module_list = TAILQ_HEAD_INITIALIZER(module_list);
   57 struct modlist  module_bootlist = TAILQ_HEAD_INITIALIZER(module_bootlist);
   58 static module_t *module_active;
   59 static char     module_base[64];
   60 u_int           module_count;
   61 kmutex_t        module_lock;
   62 
   63 /* Ensure that the kernel's link set isn't empty. */
   64 static modinfo_t module_dummy;
   65 __link_set_add_rodata(modules, module_dummy);
   66 
   67 static module_t *module_lookup(const char *);
   68 static int      module_do_load(const char *, bool, int, prop_dictionary_t,
   69                     module_t **, modclass_t class, bool);
   70 static int      module_do_unload(const char *);
   71 static void     module_error(const char *, ...);
   72 static int      module_do_builtin(const char *, module_t **);
   73 static int      module_fetch_info(module_t *);
   74 
   75 /*
   76  * module_error:
   77  *
   78  *      Utility function: log an error.
   79  */
   80 static void
   81 module_error(const char *fmt, ...)
   82 {
   83         va_list ap;
   84 
   85         va_start(ap, fmt);
   86         printf("WARNING: module error: ");
   87         vprintf(fmt, ap);
   88         printf("\n");
   89         va_end(ap);
   90 }
   91 
   92 /*
   93  * module_init:
   94  *
   95  *      Initialize the module subsystem.
   96  */
   97 void
   98 module_init(void)
   99 {
  100         extern struct vm_map *lkm_map;
  101 
  102         if (lkm_map == NULL)
  103                 lkm_map = kernel_map;
  104         mutex_init(&module_lock, MUTEX_DEFAULT, IPL_NONE);
  105 #ifdef MODULAR  /* XXX */
  106         module_init_md();
  107 #endif
  108 
  109 #if __NetBSD_Version__ / 1000000 % 100 == 99    /* -current */
  110         snprintf(module_base, sizeof(module_base), "/stand/%s/%s/modules",
  111             machine, osrelease);
  112 #else                                           /* release */
  113         snprintf(module_base, sizeof(module_base), "/stand/%s/%d.%d/modules",
  114             machine, __NetBSD_Version__ / 100000000,
  115             __NetBSD_Version__ / 1000000 % 100);
  116 #endif
  117 }
  118 
  119 /*
  120  * module_init_class:
  121  *
  122  *      Initialize all built-in and pre-loaded modules of the
  123  *      specified class.
  124  */
  125 void
  126 module_init_class(modclass_t class)
  127 {
  128         __link_set_decl(modules, modinfo_t);
  129         modinfo_t *const *mip, *mi;
  130         module_t *mod;
  131 
  132         mutex_enter(&module_lock);
  133         /*
  134          * Builtins first.  These can't depend on pre-loaded modules.
  135          */
  136         __link_set_foreach(mip, modules) {
  137                 mi = *mip;
  138                 if (mi == &module_dummy) {
  139                         continue;
  140                 }
  141                 if (class != MODULE_CLASS_ANY && class != mi->mi_class) {
  142                         continue;
  143                 }
  144                 (void)module_do_builtin(mi->mi_name, NULL);
  145         }
  146         /*
  147          * Now preloaded modules.  These will be pulled off the
  148          * list as we call module_do_load();
  149          */
  150         do {
  151                 TAILQ_FOREACH(mod, &module_bootlist, mod_chain) {
  152                         mi = mod->mod_info;
  153                         if (class != MODULE_CLASS_ANY &&
  154                             class != mi->mi_class)
  155                                 continue;
  156                         module_do_load(mi->mi_name, false, 0, NULL, NULL,
  157                             class, true);
  158                         break;
  159                 }
  160         } while (mod != NULL);
  161         mutex_exit(&module_lock);
  162 }
  163 
  164 /*
  165  * module_compatible:
  166  *
  167  *      Return true if the two supplied kernel versions are said to
  168  *      have the same binary interface for kernel code.  The entire
  169  *      version is signficant for the development tree (-current),
  170  *      major and minor versions are significant for official
  171  *      releases of the system.
  172  */
  173 bool
  174 module_compatible(int v1, int v2)
  175 {
  176 
  177 #if __NetBSD_Version__ / 1000000 % 100 == 99    /* -current */
  178         return v1 == v2;
  179 #else                                           /* release */
  180         return abs(v1 - v2) < 10000;
  181 #endif
  182 }
  183 
  184 /*
  185  * module_load:
  186  *
  187  *      Load a single module from the file system.
  188  */
  189 int
  190 module_load(const char *filename, int flags, prop_dictionary_t props,
  191             modclass_t class)
  192 {
  193         int error;
  194 
  195         /* Authorize. */
  196         error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
  197             0, (void *)(uintptr_t)MODCTL_LOAD, NULL, NULL);
  198         if (error != 0) {
  199                 return error;
  200         }
  201 
  202         mutex_enter(&module_lock);
  203         error = module_do_load(filename, false, flags, props, NULL, class,
  204             false);
  205         mutex_exit(&module_lock);
  206 
  207         return error;
  208 }
  209 
  210 /*
  211  * module_autoload:
  212  *
  213  *      Load a single module from the file system, system initiated.
  214  */
  215 int
  216 module_autoload(const char *filename, modclass_t class)
  217 {
  218         int error;
  219 
  220         KASSERT(mutex_owned(&module_lock));
  221 
  222         /* Not yet for 5.0. */
  223         return EPERM;
  224 
  225         /* Authorize. */
  226         error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
  227             0, (void *)(uintptr_t)MODCTL_LOAD, (void *)(uintptr_t)1, NULL);
  228         if (error != 0) {
  229                 return error;
  230         }
  231 
  232         return module_do_load(filename, false, 0, NULL, NULL, class, true);
  233 }
  234 
  235 /*
  236  * module_unload:
  237  *
  238  *      Find and unload a module by name.
  239  */
  240 int
  241 module_unload(const char *name)
  242 {
  243         int error;
  244 
  245         /* Authorize. */
  246         error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
  247             0, (void *)(uintptr_t)MODCTL_UNLOAD, NULL, NULL);
  248         if (error != 0) {
  249                 return error;
  250         }
  251 
  252         mutex_enter(&module_lock);
  253         error = module_do_unload(name);
  254         mutex_exit(&module_lock);
  255 
  256         return error;
  257 }
  258 
  259 /*
  260  * module_lookup:
  261  *
  262  *      Look up a module by name.
  263  */
  264 module_t *
  265 module_lookup(const char *name)
  266 {
  267         module_t *mod;
  268 
  269         KASSERT(mutex_owned(&module_lock));
  270 
  271         TAILQ_FOREACH(mod, &module_list, mod_chain) {
  272                 if (strcmp(mod->mod_info->mi_name, name) == 0) {
  273                         break;
  274                 }
  275         }
  276 
  277         return mod;
  278 }
  279 
  280 /*
  281  * module_hold:
  282  *
  283  *      Add a single reference to a module.  It's the caller's
  284  *      responsibility to ensure that the reference is dropped
  285  *      later.
  286  */
  287 int
  288 module_hold(const char *name)
  289 {
  290         module_t *mod;
  291 
  292         mutex_enter(&module_lock);
  293         mod = module_lookup(name);
  294         if (mod == NULL) {
  295                 mutex_exit(&module_lock);
  296                 return ENOENT;
  297         }
  298         mod->mod_refcnt++;
  299         mutex_exit(&module_lock);
  300 
  301         return 0;
  302 }
  303 
  304 /*
  305  * module_rele:
  306  *
  307  *      Release a reference acquired with module_hold().
  308  */
  309 void
  310 module_rele(const char *name)
  311 {
  312         module_t *mod;
  313 
  314         mutex_enter(&module_lock);
  315         mod = module_lookup(name);
  316         if (mod == NULL) {
  317                 mutex_exit(&module_lock);
  318                 panic("module_rele: gone");
  319         }
  320         mod->mod_refcnt--;
  321         mutex_exit(&module_lock);
  322 }
  323 
  324 /*
  325  * module_do_builtin:
  326  *
  327  *      Initialize a single module from the list of modules that are
  328  *      built into the kernel (linked into the kernel image).
  329  */
  330 static int
  331 module_do_builtin(const char *name, module_t **modp)
  332 {
  333         __link_set_decl(modules, modinfo_t);
  334         modinfo_t *const *mip;
  335         const char *p, *s;
  336         char buf[MAXMODNAME];
  337         modinfo_t *mi;
  338         module_t *mod, *mod2;
  339         size_t len;
  340         int error, i;
  341 
  342         KASSERT(mutex_owned(&module_lock));
  343 
  344         /*
  345          * Check to see if already loaded.
  346          */
  347         if ((mod = module_lookup(name)) != NULL) {
  348                 if (modp != NULL) {
  349                         *modp = mod;
  350                 }
  351                 return 0;
  352         }
  353 
  354         /*
  355          * Search the list to see if we have a module by this name.
  356          */
  357         error = ENOENT;
  358         __link_set_foreach(mip, modules) {
  359                 mi = *mip;
  360                 if (mi == &module_dummy) {
  361                         continue;
  362                 }
  363                 if (strcmp(mi->mi_name, name) == 0) {
  364                         error = 0;
  365                         break;
  366                 }
  367         }
  368         if (error != 0) {
  369                 return error;
  370         }
  371 
  372         /*
  373          * Initialize pre-requisites.
  374          */
  375         mod = kmem_zalloc(sizeof(*mod), KM_SLEEP);
  376         if (mod == NULL) {
  377                 return ENOMEM;
  378         }
  379         if (modp != NULL) {
  380                 *modp = mod;
  381         }
  382         if (mi->mi_required != NULL) {
  383                 for (s = mi->mi_required; *s != '\0'; s = p) {
  384                         if (*s == ',')
  385                                 s++;
  386                         p = s;
  387                         while (*p != '\0' && *p != ',')
  388                                 p++;
  389                         len = min(p - s + 1, sizeof(buf));
  390                         strlcpy(buf, s, len);
  391                         if (buf[0] == '\0')
  392                                 break;
  393                         if (mod->mod_nrequired == MAXMODDEPS - 1) {
  394                                 module_error("too many required modules");
  395                                 kmem_free(mod, sizeof(*mod));
  396                                 return EINVAL;
  397                         }
  398                         error = module_do_builtin(buf, &mod2);
  399                         if (error != 0) {
  400                                 kmem_free(mod, sizeof(*mod));
  401                                 return error;
  402                         }
  403                         mod->mod_required[mod->mod_nrequired++] = mod2;
  404                 }
  405         }
  406 
  407         /*
  408          * Try to initialize the module.
  409          */
  410         KASSERT(module_active == NULL);
  411         module_active = mod;
  412         error = (*mi->mi_modcmd)(MODULE_CMD_INIT, NULL);
  413         module_active = NULL;
  414         if (error != 0) {
  415                 module_error("builtin module `%s' "
  416                     "failed to init", mi->mi_name);
  417                 kmem_free(mod, sizeof(*mod));
  418                 return error;
  419         }
  420         mod->mod_info = mi;
  421         mod->mod_source = MODULE_SOURCE_KERNEL;
  422         module_count++;
  423         TAILQ_INSERT_TAIL(&module_list, mod, mod_chain);
  424 
  425         /*
  426          * If that worked, count dependencies.
  427          */
  428         for (i = 0; i < mod->mod_nrequired; i++) {
  429                 mod->mod_required[i]->mod_refcnt++;
  430         }
  431 
  432         return 0;
  433 }
  434 
  435 /*
  436  * module_do_load:
  437  *
  438  *      Helper routine: load a module from the file system, or one
  439  *      pushed by the boot loader.
  440  */
  441 static int
  442 module_do_load(const char *filename, bool isdep, int flags,
  443                prop_dictionary_t props, module_t **modp, modclass_t class,
  444                bool autoload)
  445 {
  446         static TAILQ_HEAD(,module) pending = TAILQ_HEAD_INITIALIZER(pending);
  447         static int depth;
  448         const int maxdepth = 6;
  449         modinfo_t *mi;
  450         module_t *mod, *mod2;
  451         char buf[MAXMODNAME];
  452         const char *s, *p;
  453         int error;
  454         size_t len;
  455         u_int i;
  456 
  457         KASSERT(mutex_owned(&module_lock));
  458 
  459         error = 0;
  460 
  461         /*
  462          * Avoid recursing too far.
  463          */
  464         if (++depth > maxdepth) {
  465                 module_error("too many required modules");
  466                 depth--;
  467                 return EMLINK;
  468         }
  469 
  470         /*
  471          * Load the module and link.  Before going to the file system,
  472          * scan the list of modules loaded by the boot loader.  Just
  473          * before init is started the list of modules loaded at boot
  474          * will be purged.  Before init is started we can assume that
  475          * `filename' is a module name and not a path name.
  476          */
  477         TAILQ_FOREACH(mod, &module_bootlist, mod_chain) {
  478                 if (strcmp(mod->mod_info->mi_name, filename) == 0) {
  479                         TAILQ_REMOVE(&module_bootlist, mod, mod_chain);
  480                         break;
  481                 }
  482         }
  483         if (mod != NULL) {
  484                 TAILQ_INSERT_TAIL(&pending, mod, mod_chain);
  485         } else {
  486                 mod = kmem_zalloc(sizeof(*mod), KM_SLEEP);
  487                 if (mod == NULL) {
  488                         depth--;
  489                         return ENOMEM;
  490                 }
  491                 error = kobj_load_file(&mod->mod_kobj, filename, module_base,
  492                     autoload);
  493                 if (error != 0) {
  494                         kmem_free(mod, sizeof(*mod));
  495                         depth--;
  496                         module_error("unable to load kernel object");
  497                         return error;
  498                 }
  499                 TAILQ_INSERT_TAIL(&pending, mod, mod_chain);
  500                 mod->mod_source = MODULE_SOURCE_FILESYS;
  501                 error = module_fetch_info(mod);
  502                 if (error != 0) {
  503                         goto fail;
  504                 }
  505         }
  506 
  507         /*
  508          * Check compatibility.
  509          */
  510         mi = mod->mod_info;
  511         if (strlen(mi->mi_name) >= MAXMODNAME) {
  512                 error = EINVAL;
  513                 module_error("module name too long");
  514                 goto fail;
  515         }
  516         if (!module_compatible(mi->mi_version, __NetBSD_Version__)) {
  517                 module_error("module built for different version of system");
  518                 if ((flags & MODCTL_LOAD_FORCE) != 0) {
  519                         module_error("forced load, system may be unstable");
  520                 } else {
  521                         error = EPROGMISMATCH;
  522                         goto fail;
  523                 }
  524         }
  525 
  526         /*
  527          * If a specific kind of module was requested, ensure that we have
  528          * a match.
  529          */
  530         if (class != MODULE_CLASS_ANY && class != mi->mi_class) {
  531                 error = ENOENT;
  532                 goto fail;
  533         }
  534 
  535         /*
  536          * If loading a dependency, `filename' is a plain module name.
  537          * The name must match.
  538          */
  539         if (isdep && strcmp(mi->mi_name, filename) != 0) {
  540                 error = ENOENT;
  541                 goto fail;
  542         }
  543 
  544         /*
  545          * Check to see if the module is already loaded.  If so, we may
  546          * have been recursively called to handle a dependency, so be sure
  547          * to set modp.
  548          */
  549         if ((mod2 = module_lookup(mi->mi_name)) != NULL) {
  550                 if (modp != NULL)
  551                         *modp = mod2;
  552                 error = EEXIST;
  553                 goto fail;
  554         }
  555 
  556         /*
  557          * Block circular dependencies.
  558          */
  559         TAILQ_FOREACH(mod2, &pending, mod_chain) {
  560                 if (mod == mod2) {
  561                         continue;
  562                 }
  563                 if (strcmp(mod2->mod_info->mi_name, mi->mi_name) == 0) {
  564                         error = EDEADLK;
  565                         module_error("circular dependency detected");
  566                         goto fail;
  567                 }
  568         }
  569 
  570         /*
  571          * Now try to load any requisite modules.
  572          */
  573         if (mi->mi_required != NULL) {
  574                 for (s = mi->mi_required; *s != '\0'; s = p) {
  575                         if (*s == ',')
  576                                 s++;
  577                         p = s;
  578                         while (*p != '\0' && *p != ',')
  579                                 p++;
  580                         len = p - s + 1;
  581                         if (len >= MAXMODNAME) {
  582                                 error = EINVAL;
  583                                 module_error("required module name too long");
  584                                 goto fail;
  585                         }
  586                         strlcpy(buf, s, len);
  587                         if (buf[0] == '\0')
  588                                 break;
  589                         if (mod->mod_nrequired == MAXMODDEPS - 1) {
  590                                 error = EINVAL;
  591                                 module_error("too many required modules");
  592                                 goto fail;
  593                         }
  594                         if (strcmp(buf, mi->mi_name) == 0) {
  595                                 error = EDEADLK;
  596                                 module_error("self-dependency detected");
  597                                 goto fail;
  598                         }
  599                         error = module_do_load(buf, true, flags, NULL,
  600                             &mod->mod_required[mod->mod_nrequired++],
  601                             MODULE_CLASS_ANY, true);
  602                         if (error != 0 && error != EEXIST)
  603                                 goto fail;
  604                 }
  605         }
  606 
  607         /*
  608          * We loaded all needed modules successfully: perform global
  609          * relocations and initialize.
  610          */
  611         error = kobj_affix(mod->mod_kobj, mi->mi_name);
  612         if (error != 0) {
  613                 module_error("unable to affix module");
  614                 goto fail2;
  615         }
  616 
  617         KASSERT(module_active == NULL);
  618         module_active = mod;
  619         error = (*mi->mi_modcmd)(MODULE_CMD_INIT, props);
  620         module_active = NULL;
  621         if (error != 0) {
  622                 module_error("modctl function returned error %d", error);
  623                 goto fail;
  624         }
  625 
  626         /*
  627          * Good, the module loaded successfully.  Put it onto the
  628          * list and add references to its requisite modules.
  629          */
  630         module_count++;
  631         TAILQ_REMOVE(&pending, mod, mod_chain);
  632         TAILQ_INSERT_TAIL(&module_list, mod, mod_chain);
  633         for (i = 0; i < mod->mod_nrequired; i++) {
  634                 KASSERT(mod->mod_required[i] != NULL);
  635                 mod->mod_required[i]->mod_refcnt++;
  636         }
  637         if (modp != NULL) {
  638                 *modp = mod;
  639         }
  640         depth--;
  641         return 0;
  642 
  643  fail:
  644         kobj_unload(mod->mod_kobj);
  645  fail2:
  646         TAILQ_REMOVE(&pending, mod, mod_chain);
  647         kmem_free(mod, sizeof(*mod));
  648         depth--;
  649         return error;
  650 }
  651 
  652 /*
  653  * module_do_unload:
  654  *
  655  *      Helper routine: do the dirty work of unloading a module.
  656  */
  657 static int
  658 module_do_unload(const char *name)
  659 {
  660         module_t *mod;
  661         int error;
  662         u_int i;
  663 
  664         KASSERT(mutex_owned(&module_lock));
  665 
  666         mod = module_lookup(name);
  667         if (mod == NULL) {
  668                 return ENOENT;
  669         }
  670         if (mod->mod_refcnt != 0 || mod->mod_source == MODULE_SOURCE_KERNEL) {
  671                 return EBUSY;
  672         }
  673         KASSERT(module_active == NULL);
  674         module_active = mod;
  675         error = (*mod->mod_info->mi_modcmd)(MODULE_CMD_FINI, NULL);
  676         module_active = NULL;
  677         if (error != 0) {
  678                 return error;
  679         }
  680         module_count--;
  681         TAILQ_REMOVE(&module_list, mod, mod_chain);
  682         for (i = 0; i < mod->mod_nrequired; i++) {
  683                 mod->mod_required[i]->mod_refcnt--;
  684         }
  685         if (mod->mod_kobj != NULL) {
  686                 kobj_unload(mod->mod_kobj);
  687         }
  688         kmem_free(mod, sizeof(*mod));
  689 
  690         return 0;
  691 }
  692 
  693 /*
  694  * module_prime:
  695  *
  696  *      Push a module loaded by the bootloader onto our internal
  697  *      list.
  698  */
  699 int
  700 module_prime(void *base, size_t size)
  701 {
  702         module_t *mod;
  703         int error;
  704 
  705         mod = kmem_zalloc(sizeof(*mod), KM_SLEEP);
  706         if (mod == NULL) {
  707                 return ENOMEM;
  708         }
  709         mod->mod_source = MODULE_SOURCE_BOOT;
  710 
  711         error = kobj_load_mem(&mod->mod_kobj, base, size);
  712         if (error != 0) {
  713                 kmem_free(mod, sizeof(*mod));
  714                 module_error("unable to load object pushed by boot loader");
  715                 return error;
  716         }
  717         error = module_fetch_info(mod);
  718         if (error != 0) {
  719                 kobj_unload(mod->mod_kobj);
  720                 kmem_free(mod, sizeof(*mod));
  721                 module_error("unable to load object pushed by boot loader");
  722                 return error;
  723         }
  724 
  725         TAILQ_INSERT_TAIL(&module_bootlist, mod, mod_chain);
  726 
  727         return 0;
  728 }
  729 
  730 /*
  731  * module_fetch_into:
  732  *
  733  *      Fetch modinfo record from a loaded module.
  734  */
  735 static int
  736 module_fetch_info(module_t *mod)
  737 {
  738         int error;
  739         void *addr;
  740         size_t size;
  741 
  742         /*
  743          * Find module info record and check compatibility.
  744          */
  745         error = kobj_find_section(mod->mod_kobj, "link_set_modules",
  746             &addr, &size);
  747         if (error != 0) {
  748                 module_error("`link_set_modules' section not present");
  749                 return error;
  750         }
  751         if (size != sizeof(modinfo_t **)) {
  752                 module_error("`link_set_modules' section wrong size");
  753                 return error;
  754         }
  755         mod->mod_info = *(modinfo_t **)addr;
  756 
  757         return 0;
  758 }
  759 
  760 /*
  761  * module_find_section:
  762  *
  763  *      Allows a module that is being initialized to look up a section
  764  *      within its ELF object.
  765  */
  766 int
  767 module_find_section(const char *name, void **addr, size_t *size)
  768 {
  769 
  770         KASSERT(mutex_owned(&module_lock));
  771         KASSERT(module_active != NULL);
  772 
  773         return kobj_find_section(module_active->mod_kobj, name, addr, size);
  774 }

Cache object: e1499018d1aa27b181f60036e6c7bc6d


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