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/boot/common/boot.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  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 /*
   31  * Loading modules, booting the system
   32  */
   33 
   34 #include <stand.h>
   35 #include <string.h>
   36 
   37 #include "bootstrap.h"
   38 
   39 static char     *getbootfile(int try);
   40 static int      loadakernel(int try, int argc, char* argv[]);
   41 
   42 /* List of kernel names to try (may be overwritten by boot.config) XXX should move from here? */
   43 static const char *default_bootfiles = "kernel";
   44 
   45 static int autoboot_tried;
   46 
   47 /*
   48  * The user wants us to boot.
   49  */
   50 COMMAND_SET(boot, "boot", "boot a file or loaded kernel", command_boot);
   51 
   52 static int
   53 command_boot(int argc, char *argv[])
   54 {
   55     struct preloaded_file       *fp;
   56 
   57     /*
   58      * See if the user has specified an explicit kernel to boot.
   59      */
   60     if ((argc > 1) && (argv[1][0] != '-')) {
   61 
   62         /* XXX maybe we should discard everything and start again? */
   63         if (file_findfile(NULL, NULL) != NULL) {
   64             sprintf(command_errbuf, "can't boot '%s', kernel module already loaded", argv[1]);
   65             return(CMD_ERROR);
   66         }
   67 
   68         /* find/load the kernel module */
   69         if (mod_loadkld(argv[1], argc - 2, argv + 2) != 0)
   70             return(CMD_ERROR);
   71         /* we have consumed all arguments */
   72         argc = 1;
   73     }
   74 
   75     /*
   76      * See if there is a kernel module already loaded
   77      */
   78     if (file_findfile(NULL, NULL) == NULL)
   79         if (loadakernel(0, argc - 1, argv + 1))
   80             /* we have consumed all arguments */
   81             argc = 1;
   82 
   83     /*
   84      * Loaded anything yet?
   85      */
   86     if ((fp = file_findfile(NULL, NULL)) == NULL) {
   87         command_errmsg = "no bootable kernel";
   88         return(CMD_ERROR);
   89     }
   90 
   91     /*
   92      * If we were given arguments, discard any previous.
   93      * XXX should we merge arguments?  Hard to DWIM.
   94      */
   95     if (argc > 1) {
   96         if (fp->f_args != NULL)
   97             free(fp->f_args);
   98         fp->f_args = unargv(argc - 1, argv + 1);
   99     }
  100 
  101     /* Hook for platform-specific autoloading of modules */
  102     if (archsw.arch_autoload() != 0)
  103         return(CMD_ERROR);
  104 
  105     /* Call the exec handler from the loader matching the kernel */
  106     file_formats[fp->f_loader]->l_exec(fp);
  107     return(CMD_ERROR);
  108 }
  109 
  110 
  111 /*
  112  * Autoboot after a delay
  113  */
  114 
  115 COMMAND_SET(autoboot, "autoboot", "boot automatically after a delay", command_autoboot);
  116 
  117 static int
  118 command_autoboot(int argc, char *argv[])
  119 {
  120     int         howlong;
  121     char        *cp, *prompt;
  122 
  123     prompt = NULL;
  124     howlong = -1;
  125     switch(argc) {
  126     case 3:
  127         prompt = argv[2];
  128         /* FALLTHROUGH */
  129     case 2:
  130         howlong = strtol(argv[1], &cp, 0);
  131         if (*cp != 0) {
  132             sprintf(command_errbuf, "bad delay '%s'", argv[1]);
  133             return(CMD_ERROR);
  134         }
  135         /* FALLTHROUGH */
  136     case 1:
  137         return(autoboot(howlong, prompt));
  138     }
  139 
  140     command_errmsg = "too many arguments";
  141     return(CMD_ERROR);
  142 }
  143 
  144 /*
  145  * Called before we go interactive.  If we think we can autoboot, and
  146  * we haven't tried already, try now.
  147  */
  148 void
  149 autoboot_maybe()
  150 {
  151     char        *cp;
  152 
  153     cp = getenv("autoboot_delay");
  154     if ((autoboot_tried == 0) && ((cp == NULL) || strcasecmp(cp, "NO")))
  155         autoboot(-1, NULL);             /* try to boot automatically */
  156 }
  157 
  158 int
  159 autoboot(int timeout, char *prompt)
  160 {
  161     time_t      when, otime, ntime;
  162     int         c, yes;
  163     char        *argv[2], *cp, *ep;
  164     char        *kernelname;
  165 
  166     autoboot_tried = 1;
  167 
  168     if (timeout == -1) {
  169         timeout = 10;
  170         /* try to get a delay from the environment */
  171         if ((cp = getenv("autoboot_delay"))) {
  172             timeout = strtol(cp, &ep, 0);
  173             if (cp == ep)
  174                 timeout = 10;           /* Unparseable? Set default! */
  175         }
  176     }
  177 
  178     kernelname = getenv("kernelname");
  179     if (kernelname == NULL) {
  180         argv[0] = NULL;
  181         loadakernel(0, 0, argv);
  182         kernelname = getenv("kernelname");
  183         if (kernelname == NULL) {
  184             command_errmsg = "no valid kernel found";
  185             return(CMD_ERROR);
  186         }
  187     }
  188 
  189     if (timeout >= 0) {
  190         otime = time(NULL);
  191         when = otime + timeout; /* when to boot */
  192 
  193         yes = 0;
  194 
  195         printf("%s\n", (prompt == NULL) ? "Hit [Enter] to boot immediately, or any other key for command prompt." : prompt);
  196 
  197         for (;;) {
  198             if (ischar()) {
  199                 c = getchar();
  200                 if ((c == '\r') || (c == '\n'))
  201                     yes = 1;
  202                 break;
  203             }
  204             ntime = time(NULL);
  205             if (ntime >= when) {
  206                 yes = 1;
  207                 break;
  208             }
  209 
  210             if (ntime != otime) {
  211                 printf("\rBooting [%s] in %d second%s... ",
  212                             kernelname, (int)(when - ntime),
  213                             (when-ntime)==1?"":"s");
  214                 otime = ntime;
  215             }
  216         }
  217     } else {
  218         yes = 1;
  219     }
  220 
  221     if (yes)
  222         printf("\rBooting [%s]...               ", kernelname);
  223     putchar('\n');
  224     if (yes) {
  225         argv[0] = "boot";
  226         argv[1] = NULL;
  227         return(command_boot(1, argv));
  228     }
  229     return(CMD_OK);
  230 }
  231 
  232 /*
  233  * Scrounge for the name of the (try)'th file we will try to boot.
  234  */
  235 static char *
  236 getbootfile(int try)
  237 {
  238     static char *name = NULL;
  239     const char  *spec, *ep;
  240     size_t      len;
  241 
  242     /* we use dynamic storage */
  243     if (name != NULL) {
  244         free(name);
  245         name = NULL;
  246     }
  247 
  248     /*
  249      * Try $bootfile, then try our builtin default
  250      */
  251     if ((spec = getenv("bootfile")) == NULL)
  252         spec = default_bootfiles;
  253 
  254     while ((try > 0) && (spec != NULL)) {
  255         spec = strchr(spec, ';');
  256         if (spec)
  257             spec++;     /* skip over the leading ';' */
  258         try--;
  259     }
  260     if (spec != NULL) {
  261         if ((ep = strchr(spec, ';')) != NULL) {
  262             len = ep - spec;
  263         } else {
  264             len = strlen(spec);
  265         }
  266         name = malloc(len + 1);
  267         strncpy(name, spec, len);
  268         name[len] = 0;
  269     }
  270     if (name && name[0] == 0) {
  271         free(name);
  272         name = NULL;
  273     }
  274     return(name);
  275 }
  276 
  277 /*
  278  * Try to find the /etc/fstab file on the filesystem (rootdev),
  279  * which should be be the root filesystem, and parse it to find
  280  * out what the kernel ought to think the root filesystem is.
  281  *
  282  * If we're successful, set vfs.root.mountfrom to <vfstype>:<path>
  283  * so that the kernel can tell both which VFS and which node to use
  284  * to mount the device.  If this variable's already set, don't
  285  * overwrite it.
  286  */
  287 int
  288 getrootmount(char *rootdev)
  289 {
  290     char        lbuf[128], *cp, *ep, *dev, *fstyp;
  291     int         fd, error;
  292 
  293     if (getenv("vfs.root.mountfrom") != NULL)
  294         return(0);
  295 
  296     sprintf(lbuf, "%s/etc/fstab", rootdev);
  297     if ((fd = open(lbuf, O_RDONLY)) < 0)
  298         return(1);
  299 
  300     /* loop reading lines from /etc/fstab    What was that about sscanf again? */
  301     error = 1;
  302     while (fgetstr(lbuf, sizeof(lbuf), fd) >= 0) {
  303         if ((lbuf[0] == 0) || (lbuf[0] == '#'))
  304             continue;
  305 
  306         /* skip device name */
  307         for (cp = lbuf; (*cp != 0) && !isspace(*cp); cp++)
  308             ;
  309         if (*cp == 0)           /* misformatted */
  310             continue;
  311         /* delimit and save */
  312         *cp++ = 0;
  313         dev = strdup(lbuf);
  314 
  315         /* skip whitespace up to mountpoint */
  316         while ((*cp != 0) && isspace(*cp))
  317             cp++;
  318         /* must have /<space> to be root */
  319         if ((*cp == 0) || (*cp != '/') || !isspace(*(cp + 1)))
  320             continue;
  321         /* skip whitespace up to fstype */
  322         cp += 2;
  323         while ((*cp != 0) && isspace(*cp))
  324             cp++;
  325         if (*cp == 0)           /* misformatted */
  326             continue;
  327         /* skip text to end of fstype and delimit */
  328         ep = cp;
  329         while ((*cp != 0) && !isspace(*cp))
  330             cp++;
  331         *cp = 0;
  332         fstyp = strdup(ep);
  333 
  334         /* build the final result and save it */
  335         sprintf(lbuf, "%s:%s", fstyp, dev);
  336         free(dev);
  337         free(fstyp);
  338         setenv("vfs.root.mountfrom", lbuf, 0);
  339         error = 0;
  340         break;
  341     }
  342     close(fd);
  343     return(error);
  344 }
  345 
  346 static int
  347 loadakernel(int try, int argc, char* argv[])
  348 {
  349     char *cp;
  350 
  351         for (try = 0; (cp = getbootfile(try)) != NULL; try++)
  352             if (mod_loadkld(cp, argc - 1, argv + 1) != 0)
  353                 printf("can't load '%s'\n", cp);
  354             else
  355                 return 1;
  356         return 0;
  357 }

Cache object: 3860bc5c3c070f141c5d21d35fe47de7


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