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/subr_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 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1998 Michael Smith
    5  * All rights reserved.
    6  * Copyright (c) 2020 NetApp Inc.
    7  * Copyright (c) 2020 Klara Inc.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/linker.h>
   37 #include <sys/sbuf.h>
   38 #include <sys/sysctl.h>
   39 
   40 #include <machine/metadata.h>
   41 
   42 #include <vm/vm.h>
   43 #include <vm/vm_extern.h>
   44 
   45 /*
   46  * Preloaded module support
   47  */
   48 
   49 vm_offset_t preload_addr_relocate = 0;
   50 caddr_t preload_metadata;
   51 
   52 /*
   53  * Search for the preloaded module (name)
   54  */
   55 caddr_t
   56 preload_search_by_name(const char *name)
   57 {
   58     caddr_t     curp;
   59     uint32_t    *hdr;
   60     int         next;
   61     
   62     if (preload_metadata != NULL) {
   63         curp = preload_metadata;
   64         for (;;) {
   65             hdr = (uint32_t *)curp;
   66             if (hdr[0] == 0 && hdr[1] == 0)
   67                 break;
   68 
   69             /* Search for a MODINFO_NAME field */
   70             if ((hdr[0] == MODINFO_NAME) &&
   71                 !strcmp(name, curp + sizeof(uint32_t) * 2))
   72                 return(curp);
   73 
   74             /* skip to next field */
   75             next = sizeof(uint32_t) * 2 + hdr[1];
   76             next = roundup(next, sizeof(u_long));
   77             curp += next;
   78         }
   79     }
   80     return(NULL);
   81 }
   82 
   83 /*
   84  * Search for the first preloaded module of (type)
   85  */
   86 caddr_t
   87 preload_search_by_type(const char *type)
   88 {
   89     caddr_t     curp, lname;
   90     uint32_t    *hdr;
   91     int         next;
   92 
   93     if (preload_metadata != NULL) {
   94         curp = preload_metadata;
   95         lname = NULL;
   96         for (;;) {
   97             hdr = (uint32_t *)curp;
   98             if (hdr[0] == 0 && hdr[1] == 0)
   99                 break;
  100 
  101             /* remember the start of each record */
  102             if (hdr[0] == MODINFO_NAME)
  103                 lname = curp;
  104 
  105             /* Search for a MODINFO_TYPE field */
  106             if ((hdr[0] == MODINFO_TYPE) &&
  107                 !strcmp(type, curp + sizeof(uint32_t) * 2))
  108                 return(lname);
  109 
  110             /* skip to next field */
  111             next = sizeof(uint32_t) * 2 + hdr[1];
  112             next = roundup(next, sizeof(u_long));
  113             curp += next;
  114         }
  115     }
  116     return(NULL);
  117 }
  118 
  119 /*
  120  * Walk through the preloaded module list
  121  */
  122 caddr_t
  123 preload_search_next_name(caddr_t base)
  124 {
  125     caddr_t     curp;
  126     uint32_t    *hdr;
  127     int         next;
  128     
  129     if (preload_metadata != NULL) {
  130         /* Pick up where we left off last time */
  131         if (base) {
  132             /* skip to next field */
  133             curp = base;
  134             hdr = (uint32_t *)curp;
  135             next = sizeof(uint32_t) * 2 + hdr[1];
  136             next = roundup(next, sizeof(u_long));
  137             curp += next;
  138         } else
  139             curp = preload_metadata;
  140 
  141         for (;;) {
  142             hdr = (uint32_t *)curp;
  143             if (hdr[0] == 0 && hdr[1] == 0)
  144                 break;
  145 
  146             /* Found a new record? */
  147             if (hdr[0] == MODINFO_NAME)
  148                 return curp;
  149 
  150             /* skip to next field */
  151             next = sizeof(uint32_t) * 2 + hdr[1];
  152             next = roundup(next, sizeof(u_long));
  153             curp += next;
  154         }
  155     }
  156     return(NULL);
  157 }
  158 
  159 /*
  160  * Given a preloaded module handle (mod), return a pointer
  161  * to the data for the attribute (inf).
  162  */
  163 caddr_t
  164 preload_search_info(caddr_t mod, int inf)
  165 {
  166     caddr_t     curp;
  167     uint32_t    *hdr;
  168     uint32_t    type = 0;
  169     int         next;
  170 
  171     if (mod == NULL)
  172         return (NULL);
  173 
  174     curp = mod;
  175     for (;;) {
  176         hdr = (uint32_t *)curp;
  177         /* end of module data? */
  178         if (hdr[0] == 0 && hdr[1] == 0)
  179             break;
  180         /* 
  181          * We give up once we've looped back to what we were looking at 
  182          * first - this should normally be a MODINFO_NAME field.
  183          */
  184         if (type == 0) {
  185             type = hdr[0];
  186         } else {
  187             if (hdr[0] == type)
  188                 break;
  189         }
  190 
  191         /* 
  192          * Attribute match? Return pointer to data.
  193          * Consumer may safely assume that size value precedes  
  194          * data.
  195          */
  196         if (hdr[0] == inf)
  197             return(curp + (sizeof(uint32_t) * 2));
  198 
  199         /* skip to next field */
  200         next = sizeof(uint32_t) * 2 + hdr[1];
  201         next = roundup(next, sizeof(u_long));
  202         curp += next;
  203     }
  204     return(NULL);
  205 }
  206 
  207 /*
  208  * Delete a preload record by name.
  209  */
  210 void
  211 preload_delete_name(const char *name)
  212 {
  213     caddr_t     addr, curp;
  214     uint32_t    *hdr, sz;
  215     int         next;
  216     int         clearing;
  217 
  218     addr = 0;
  219     sz = 0;
  220     
  221     if (preload_metadata != NULL) {
  222         clearing = 0;
  223         curp = preload_metadata;
  224         for (;;) {
  225             hdr = (uint32_t *)curp;
  226             if (hdr[0] == MODINFO_NAME || (hdr[0] == 0 && hdr[1] == 0)) {
  227                 /* Free memory used to store the file. */
  228                 if (addr != 0 && sz != 0)
  229                     kmem_bootstrap_free((vm_offset_t)addr, sz);
  230                 addr = 0;
  231                 sz = 0;
  232 
  233                 if (hdr[0] == 0)
  234                     break;
  235                 if (!strcmp(name, curp + sizeof(uint32_t) * 2))
  236                     clearing = 1;       /* got it, start clearing */
  237                 else if (clearing) {
  238                     clearing = 0;       /* at next one now.. better stop */
  239                 }
  240             }
  241             if (clearing) {
  242                 if (hdr[0] == MODINFO_ADDR)
  243                     addr = *(caddr_t *)(curp + sizeof(uint32_t) * 2);
  244                 else if (hdr[0] == MODINFO_SIZE)
  245                     sz = *(uint32_t *)(curp + sizeof(uint32_t) * 2);
  246                 hdr[0] = MODINFO_EMPTY;
  247             }
  248 
  249             /* skip to next field */
  250             next = sizeof(uint32_t) * 2 + hdr[1];
  251             next = roundup(next, sizeof(u_long));
  252             curp += next;
  253         }
  254     }
  255 }
  256 
  257 void *
  258 preload_fetch_addr(caddr_t mod)
  259 {
  260         caddr_t *mdp;
  261 
  262         mdp = (caddr_t *)preload_search_info(mod, MODINFO_ADDR);
  263         if (mdp == NULL)
  264                 return (NULL);
  265         return (*mdp + preload_addr_relocate);
  266 }
  267 
  268 size_t
  269 preload_fetch_size(caddr_t mod)
  270 {
  271         size_t *mdp;
  272 
  273         mdp = (size_t *)preload_search_info(mod, MODINFO_SIZE);
  274         if (mdp == NULL)
  275                 return (0);
  276         return (*mdp);
  277 }
  278 
  279 /* Called from locore.  Convert physical pointers to kvm. Sigh. */
  280 void
  281 preload_bootstrap_relocate(vm_offset_t offset)
  282 {
  283     caddr_t     curp;
  284     uint32_t    *hdr;
  285     vm_offset_t *ptr;
  286     int         next;
  287     
  288     if (preload_metadata != NULL) {
  289         curp = preload_metadata;
  290         for (;;) {
  291             hdr = (uint32_t *)curp;
  292             if (hdr[0] == 0 && hdr[1] == 0)
  293                 break;
  294 
  295             /* Deal with the ones that we know we have to fix */
  296             switch (hdr[0]) {
  297             case MODINFO_ADDR:
  298             case MODINFO_METADATA|MODINFOMD_FONT:
  299             case MODINFO_METADATA|MODINFOMD_SSYM:
  300             case MODINFO_METADATA|MODINFOMD_ESYM:
  301                 ptr = (vm_offset_t *)(curp + (sizeof(uint32_t) * 2));
  302                 *ptr += offset;
  303                 break;
  304             }
  305             /* The rest is beyond us for now */
  306 
  307             /* skip to next field */
  308             next = sizeof(uint32_t) * 2 + hdr[1];
  309             next = roundup(next, sizeof(u_long));
  310             curp += next;
  311         }
  312     }
  313 }
  314 
  315 /*
  316  * Parse the modinfo type and append to the provided sbuf.
  317  */
  318 static void
  319 preload_modinfo_type(struct sbuf *sbp, int type)
  320 {
  321 
  322         if ((type & MODINFO_METADATA) == 0) {
  323                 switch (type) {
  324                 case MODINFO_END:
  325                         sbuf_cat(sbp, "MODINFO_END");
  326                         break;
  327                 case MODINFO_NAME:
  328                         sbuf_cat(sbp, "MODINFO_NAME");
  329                         break;
  330                 case MODINFO_TYPE:
  331                         sbuf_cat(sbp, "MODINFO_TYPE");
  332                         break;
  333                 case MODINFO_ADDR:
  334                         sbuf_cat(sbp, "MODINFO_ADDR");
  335                         break;
  336                 case MODINFO_SIZE:
  337                         sbuf_cat(sbp, "MODINFO_SIZE");
  338                         break;
  339                 case MODINFO_EMPTY:
  340                         sbuf_cat(sbp, "MODINFO_EMPTY");
  341                         break;
  342                 case MODINFO_ARGS:
  343                         sbuf_cat(sbp, "MODINFO_ARGS");
  344                         break;
  345                 default:
  346                         sbuf_cat(sbp, "unrecognized modinfo attribute");
  347                 }
  348 
  349                 return;
  350         }
  351 
  352         sbuf_cat(sbp, "MODINFO_METADATA | ");
  353         switch (type & ~MODINFO_METADATA) {
  354         case MODINFOMD_ELFHDR:
  355                 sbuf_cat(sbp, "MODINFOMD_ELFHDR");
  356                 break;
  357         case MODINFOMD_SSYM:
  358                 sbuf_cat(sbp, "MODINFOMD_SSYM");
  359                 break;
  360         case MODINFOMD_ESYM:
  361                 sbuf_cat(sbp, "MODINFOMD_ESYM");
  362                 break;
  363         case MODINFOMD_DYNAMIC:
  364                 sbuf_cat(sbp, "MODINFOMD_DYNAMIC");
  365                 break;
  366         case MODINFOMD_ENVP:
  367                 sbuf_cat(sbp, "MODINFOMD_ENVP");
  368                 break;
  369         case MODINFOMD_HOWTO:
  370                 sbuf_cat(sbp, "MODINFOMD_HOWTO");
  371                 break;
  372         case MODINFOMD_KERNEND:
  373                 sbuf_cat(sbp, "MODINFOMD_KERNEND");
  374                 break;
  375         case MODINFOMD_SHDR:
  376                 sbuf_cat(sbp, "MODINFOMD_SHDR");
  377                 break;
  378         case MODINFOMD_CTORS_ADDR:
  379                 sbuf_cat(sbp, "MODINFOMD_CTORS_ADDR");
  380                 break;
  381         case MODINFOMD_CTORS_SIZE:
  382                 sbuf_cat(sbp, "MODINFOMD_CTORS_SIZE");
  383                 break;
  384         case MODINFOMD_FW_HANDLE:
  385                 sbuf_cat(sbp, "MODINFOMD_FW_HANDLE");
  386                 break;
  387         case MODINFOMD_KEYBUF:
  388                 sbuf_cat(sbp, "MODINFOMD_KEYBUF");
  389                 break;
  390 #ifdef MODINFOMD_SMAP
  391         case MODINFOMD_SMAP:
  392                 sbuf_cat(sbp, "MODINFOMD_SMAP");
  393                 break;
  394 #endif
  395 #ifdef MODINFOMD_SMAP_XATTR
  396         case MODINFOMD_SMAP_XATTR:
  397                 sbuf_cat(sbp, "MODINFOMD_SMAP_XATTR");
  398                 break;
  399 #endif
  400 #ifdef MODINFOMD_DTBP
  401         case MODINFOMD_DTBP:
  402                 sbuf_cat(sbp, "MODINFOMD_DTBP");
  403                 break;
  404 #endif
  405 #ifdef MODINFOMD_EFI_MAP
  406         case MODINFOMD_EFI_MAP:
  407                 sbuf_cat(sbp, "MODINFOMD_EFI_MAP");
  408                 break;
  409 #endif
  410 #ifdef MODINFOMD_EFI_FB
  411         case MODINFOMD_EFI_FB:
  412                 sbuf_cat(sbp, "MODINFOMD_EFI_FB");
  413                 break;
  414 #endif
  415 #ifdef MODINFOMD_MODULEP
  416         case MODINFOMD_MODULEP:
  417                 sbuf_cat(sbp, "MODINFOMD_MODULEP");
  418                 break;
  419 #endif
  420 #ifdef MODINFOMD_VBE_FB
  421         case MODINFOMD_VBE_FB:
  422                 sbuf_cat(sbp, "MODINFOMD_VBE_FB");
  423                 break;
  424 #endif
  425 #ifdef MODINFOMD_FONT
  426         case MODINFOMD_FONT:
  427                 sbuf_cat(sbp, "MODINFOMD_FONT");
  428                 break;
  429 #endif
  430         default:
  431                 sbuf_cat(sbp, "unrecognized metadata type");
  432         }
  433 }
  434 
  435 /*
  436  * Print the modinfo value, depending on type.
  437  */
  438 static void
  439 preload_modinfo_value(struct sbuf *sbp, uint32_t *bptr, int type, int len)
  440 {
  441 #ifdef __LP64__
  442 #define sbuf_print_vmoffset(sb, o)      sbuf_printf(sb, "0x%016lx", o);
  443 #else
  444 #define sbuf_print_vmoffset(sb, o)      sbuf_printf(sb, "0x%08x", o);
  445 #endif
  446 
  447         switch (type) {
  448         case MODINFO_NAME:
  449         case MODINFO_TYPE:
  450         case MODINFO_ARGS:
  451                 sbuf_printf(sbp, "%s", (char *)bptr);
  452                 break;
  453         case MODINFO_SIZE:
  454         case MODINFO_METADATA | MODINFOMD_CTORS_SIZE:
  455                 sbuf_printf(sbp, "%lu", *(u_long *)bptr);
  456                 break;
  457         case MODINFO_ADDR:
  458         case MODINFO_METADATA | MODINFOMD_SSYM:
  459         case MODINFO_METADATA | MODINFOMD_ESYM:
  460         case MODINFO_METADATA | MODINFOMD_DYNAMIC:
  461         case MODINFO_METADATA | MODINFOMD_KERNEND:
  462         case MODINFO_METADATA | MODINFOMD_ENVP:
  463         case MODINFO_METADATA | MODINFOMD_CTORS_ADDR:
  464 #ifdef MODINFOMD_SMAP
  465         case MODINFO_METADATA | MODINFOMD_SMAP:
  466 #endif
  467 #ifdef MODINFOMD_SMAP_XATTR
  468         case MODINFO_METADATA | MODINFOMD_SMAP_XATTR:
  469 #endif
  470 #ifdef MODINFOMD_DTBP
  471         case MODINFO_METADATA | MODINFOMD_DTBP:
  472 #endif
  473 #ifdef MODINFOMD_EFI_FB
  474         case MODINFO_METADATA | MODINFOMD_EFI_FB:
  475 #endif
  476 #ifdef MODINFOMD_VBE_FB
  477         case MODINFO_METADATA | MODINFOMD_VBE_FB:
  478 #endif
  479 #ifdef MODINFOMD_FONT
  480         case MODINFO_METADATA | MODINFOMD_FONT:
  481 #endif
  482                 sbuf_print_vmoffset(sbp, *(vm_offset_t *)bptr);
  483                 break;
  484         case MODINFO_METADATA | MODINFOMD_HOWTO:
  485                 sbuf_printf(sbp, "0x%08x", *bptr);
  486                 break;
  487         case MODINFO_METADATA | MODINFOMD_SHDR:
  488         case MODINFO_METADATA | MODINFOMD_ELFHDR:
  489         case MODINFO_METADATA | MODINFOMD_FW_HANDLE:
  490         case MODINFO_METADATA | MODINFOMD_KEYBUF:
  491 #ifdef MODINFOMD_EFI_MAP
  492         case MODINFO_METADATA | MODINFOMD_EFI_MAP:
  493 #endif
  494                 /* Don't print data buffers. */
  495                 sbuf_cat(sbp, "buffer contents omitted");
  496                 break;
  497         default:
  498                 break;
  499         }
  500 #undef sbuf_print_vmoffset
  501 }
  502 
  503 static void
  504 preload_dump_internal(struct sbuf *sbp)
  505 {
  506         uint32_t *bptr, type, len;
  507 
  508         KASSERT(preload_metadata != NULL,
  509             ("%s called without setting up preload_metadata", __func__));
  510 
  511         /*
  512          * Iterate through the TLV-encoded sections.
  513          */
  514         bptr = (uint32_t *)preload_metadata;
  515         sbuf_putc(sbp, '\n');
  516         while (bptr[0] != MODINFO_END || bptr[1] != MODINFO_END) {
  517                 sbuf_printf(sbp, " %p:\n", bptr);
  518                 type = *bptr++;
  519                 len = *bptr++;
  520 
  521                 sbuf_printf(sbp, "\ttype:\t(%#04x) ", type);
  522                 preload_modinfo_type(sbp, type);
  523                 sbuf_putc(sbp, '\n');
  524                 sbuf_printf(sbp, "\tlen:\t%u\n", len);
  525                 sbuf_cat(sbp, "\tvalue:\t");
  526                 preload_modinfo_value(sbp, bptr, type, len);
  527                 sbuf_putc(sbp, '\n');
  528 
  529                 bptr += roundup(len, sizeof(u_long)) / sizeof(uint32_t);
  530         }
  531 }
  532 
  533 /*
  534  * Print the preloaded data to the console. Called from the machine-dependent
  535  * initialization routines, e.g. hammer_time().
  536  */
  537 void
  538 preload_dump(void)
  539 {
  540         char buf[512];
  541         struct sbuf sb;
  542 
  543         /*
  544          * This function is expected to be called before malloc is available,
  545          * so use a static buffer and struct sbuf.
  546          */
  547         sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
  548         sbuf_set_drain(&sb, sbuf_printf_drain, NULL);
  549         preload_dump_internal(&sb);
  550 
  551         sbuf_finish(&sb);
  552         sbuf_delete(&sb);
  553 }
  554 
  555 static int
  556 sysctl_preload_dump(SYSCTL_HANDLER_ARGS)
  557 {
  558         struct sbuf sb;
  559         int error;
  560 
  561         if (preload_metadata == NULL)
  562                 return (EINVAL);
  563 
  564         sbuf_new_for_sysctl(&sb, NULL, 512, req);
  565         preload_dump_internal(&sb);
  566 
  567         error = sbuf_finish(&sb);
  568         sbuf_delete(&sb);
  569 
  570         return (error);
  571 }
  572 SYSCTL_PROC(_debug, OID_AUTO, dump_modinfo,
  573     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
  574     NULL, 0, sysctl_preload_dump, "A",
  575     "pretty-print the bootloader metadata");

Cache object: e73b7393044955b91deccc298043b562


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