199767f8919635c4928607450d9e0abb932109ceToomas Soome/*-
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
199767f8919635c4928607450d9e0abb932109ceToomas Soome * All rights reserved.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Redistribution and use in source and binary forms, with or without
199767f8919635c4928607450d9e0abb932109ceToomas Soome * modification, are permitted provided that the following conditions
199767f8919635c4928607450d9e0abb932109ceToomas Soome * are met:
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 1. Redistributions of source code must retain the above copyright
199767f8919635c4928607450d9e0abb932109ceToomas Soome * notice, this list of conditions and the following disclaimer.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
199767f8919635c4928607450d9e0abb932109ceToomas Soome * notice, this list of conditions and the following disclaimer in the
199767f8919635c4928607450d9e0abb932109ceToomas Soome * documentation and/or other materials provided with the distribution.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
199767f8919635c4928607450d9e0abb932109ceToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
199767f8919635c4928607450d9e0abb932109ceToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
199767f8919635c4928607450d9e0abb932109ceToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
199767f8919635c4928607450d9e0abb932109ceToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
199767f8919635c4928607450d9e0abb932109ceToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
199767f8919635c4928607450d9e0abb932109ceToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
199767f8919635c4928607450d9e0abb932109ceToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
199767f8919635c4928607450d9e0abb932109ceToomas Soome * SUCH DAMAGE.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/cdefs.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome__FBSDID("$FreeBSD$");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Loading modules, booting the system
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <stand.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <string.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include "bootstrap.h"
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic char *getbootfile(int try);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int loadakernel(int try, int argc, char* argv[]);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* List of kernel names to try (may be overwritten by boot.config) XXX should move from here? */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic const char *default_bootfiles = "kernel";
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int autoboot_tried;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * The user wants us to boot.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas SoomeCOMMAND_SET(boot, "boot", "boot a file or loaded kernel", command_boot);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomecommand_boot(int argc, char *argv[])
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct preloaded_file *fp;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * See if the user has specified an explicit kernel to boot.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((argc > 1) && (argv[1][0] == '/')) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* XXX maybe we should discard everything and start again? */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (file_findfile(NULL, NULL) != NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome snprintf(command_errbuf, sizeof (command_errbuf),
199767f8919635c4928607450d9e0abb932109ceToomas Soome "can't boot '%s', kernel module already loaded", argv[1]);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(CMD_ERROR);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* find/load the kernel module */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (mod_loadkld(argv[1], argc - 2, argv + 2) != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(CMD_ERROR);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* we have consumed all arguments */
199767f8919635c4928607450d9e0abb932109ceToomas Soome argc = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * See if there is a kernel module already loaded
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (file_findfile(NULL, NULL) == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (loadakernel(0, argc - 1, argv + 1))
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* we have consumed all arguments */
199767f8919635c4928607450d9e0abb932109ceToomas Soome argc = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Loaded anything yet?
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((fp = file_findfile(NULL, NULL)) == NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome command_errmsg = "no bootable kernel";
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(CMD_ERROR);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * If we were given arguments, discard any previous.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * XXX should we merge arguments? Hard to DWIM.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (argc > 1) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fp->f_args != NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fp->f_args);
199767f8919635c4928607450d9e0abb932109ceToomas Soome fp->f_args = unargv(argc - 1, argv + 1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Hook for platform-specific autoloading of modules */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (archsw.arch_autoload() != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(CMD_ERROR);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Call the exec handler from the loader matching the kernel */
199767f8919635c4928607450d9e0abb932109ceToomas Soome file_formats[fp->f_loader]->l_exec(fp);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(CMD_ERROR);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Autoboot after a delay
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas SoomeCOMMAND_SET(autoboot, "autoboot", "boot automatically after a delay", command_autoboot);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomecommand_autoboot(int argc, char *argv[])
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome int howlong;
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *cp, *prompt;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome prompt = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome howlong = -1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome switch(argc) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome case 3:
199767f8919635c4928607450d9e0abb932109ceToomas Soome prompt = argv[2];
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* FALLTHROUGH */
199767f8919635c4928607450d9e0abb932109ceToomas Soome case 2:
199767f8919635c4928607450d9e0abb932109ceToomas Soome howlong = strtol(argv[1], &cp, 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*cp != 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome snprintf(command_errbuf, sizeof (command_errbuf),
199767f8919635c4928607450d9e0abb932109ceToomas Soome "bad delay '%s'", argv[1]);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(CMD_ERROR);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* FALLTHROUGH */
199767f8919635c4928607450d9e0abb932109ceToomas Soome case 1:
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(autoboot(howlong, prompt));
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome command_errmsg = "too many arguments";
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(CMD_ERROR);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Called before we go interactive. If we think we can autoboot, and
199767f8919635c4928607450d9e0abb932109ceToomas Soome * we haven't tried already, try now.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomevoid
199767f8919635c4928607450d9e0abb932109ceToomas Soomeautoboot_maybe(void)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *cp;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* compatibility with sparc prom, check for autoboot? */
199767f8919635c4928607450d9e0abb932109ceToomas Soome cp = getenv("autoboot?");
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (cp != NULL && strcasecmp(cp, "true") != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome cp = getenv("autoboot_delay");
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((autoboot_tried == 0) && ((cp == NULL) || strcasecmp(cp, "NO")))
199767f8919635c4928607450d9e0abb932109ceToomas Soome autoboot(-1, NULL); /* try to boot automatically */
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint
199767f8919635c4928607450d9e0abb932109ceToomas Soomeautoboot(int timeout, char *prompt)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome time_t when, otime, ntime;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int c, yes;
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *argv[2], *cp, *ep;
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *kernelname;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct preloaded_file *fp;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome autoboot_tried = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (timeout == -1) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome timeout = 10;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* try to get a delay from the environment */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((cp = getenv("autoboot_delay"))) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome timeout = strtol(cp, &ep, 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (cp == ep)
199767f8919635c4928607450d9e0abb932109ceToomas Soome timeout = 10; /* Unparseable? Set default! */
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome fp = file_findfile(NULL, NULL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fp == NULL) { /* no preloaded files, run command start to load all */
199767f8919635c4928607450d9e0abb932109ceToomas Soome bf_run("start");
199767f8919635c4928607450d9e0abb932109ceToomas Soome fp = file_findfile(NULL, NULL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fp == NULL) { /* still nothing? can't boot */
199767f8919635c4928607450d9e0abb932109ceToomas Soome command_errmsg = "no valid kernel found";
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(CMD_ERROR);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome kernelname = fp->f_name;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (timeout >= 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome otime = time(NULL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome when = otime + timeout; /* when to boot */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome yes = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("%s\n", (prompt == NULL) ? "Hit [Enter] to boot immediately, or any other key for command prompt." : prompt);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (;;) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ischar()) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome c = getchar();
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((c == '\r') || (c == '\n'))
199767f8919635c4928607450d9e0abb932109ceToomas Soome yes = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome ntime = time(NULL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ntime >= when) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome yes = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ntime != otime) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("\rBooting [%s] in %d second%s... ",
199767f8919635c4928607450d9e0abb932109ceToomas Soome kernelname, (int)(when - ntime),
199767f8919635c4928607450d9e0abb932109ceToomas Soome (when-ntime)==1?"":"s");
199767f8919635c4928607450d9e0abb932109ceToomas Soome otime = ntime;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome yes = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (yes)
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("\rBooting [%s]... ", kernelname);
199767f8919635c4928607450d9e0abb932109ceToomas Soome putchar('\n');
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (yes) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome argv[0] = "boot";
199767f8919635c4928607450d9e0abb932109ceToomas Soome argv[1] = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(command_boot(1, argv));
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(CMD_OK);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Scrounge for the name of the (try)'th file we will try to boot.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic char *
199767f8919635c4928607450d9e0abb932109ceToomas Soomegetbootfile(int try)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome static char *name = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome const char *spec, *ep;
199767f8919635c4928607450d9e0abb932109ceToomas Soome size_t len;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* we use dynamic storage */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (name != NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(name);
199767f8919635c4928607450d9e0abb932109ceToomas Soome name = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Try $bootfile, then try our builtin default
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((spec = getenv("bootfile")) == NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome spec = default_bootfiles;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while ((try > 0) && (spec != NULL)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome spec = strchr(spec, ';');
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (spec)
199767f8919635c4928607450d9e0abb932109ceToomas Soome spec++; /* skip over the leading ';' */
199767f8919635c4928607450d9e0abb932109ceToomas Soome try--;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (spec != NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((ep = strchr(spec, ';')) != NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome len = ep - spec;
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome len = strlen(spec);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome name = malloc(len + 1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome strncpy(name, spec, len);
199767f8919635c4928607450d9e0abb932109ceToomas Soome name[len] = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (name && name[0] == 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(name);
199767f8919635c4928607450d9e0abb932109ceToomas Soome name = NULL;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(name);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Try to find the /etc/fstab file on the filesystem (rootdev),
199767f8919635c4928607450d9e0abb932109ceToomas Soome * which should be be the root filesystem, and parse it to find
199767f8919635c4928607450d9e0abb932109ceToomas Soome * out what the kernel ought to think the root filesystem is.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * If we're successful, set vfs.root.mountfrom to <vfstype>:<path>
199767f8919635c4928607450d9e0abb932109ceToomas Soome * so that the kernel can tell both which VFS and which node to use
199767f8919635c4928607450d9e0abb932109ceToomas Soome * to mount the device. If this variable's already set, don't
199767f8919635c4928607450d9e0abb932109ceToomas Soome * overwrite it.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint
199767f8919635c4928607450d9e0abb932109ceToomas Soomegetrootmount(char *rootdev)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome char lbuf[128], *cp, *ep, *dev, *fstyp, *options;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int fd, error;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (getenv("vfs.root.mountfrom") != NULL)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome error = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome sprintf(lbuf, "%s/etc/fstab", rootdev);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((fd = open(lbuf, O_RDONLY)) < 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome goto notfound;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* loop reading lines from /etc/fstab What was that about sscanf again? */
199767f8919635c4928607450d9e0abb932109ceToomas Soome while (fgetstr(lbuf, sizeof(lbuf), fd) >= 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((lbuf[0] == 0) || (lbuf[0] == '#'))
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* skip device name */
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (cp = lbuf; (*cp != 0) && !isspace(*cp); cp++)
199767f8919635c4928607450d9e0abb932109ceToomas Soome ;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*cp == 0) /* misformatted */
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* delimit and save */
199767f8919635c4928607450d9e0abb932109ceToomas Soome *cp++ = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome dev = strdup(lbuf);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* skip whitespace up to mountpoint */
199767f8919635c4928607450d9e0abb932109ceToomas Soome while ((*cp != 0) && isspace(*cp))
199767f8919635c4928607450d9e0abb932109ceToomas Soome cp++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* must have /<space> to be root */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((*cp == 0) || (*cp != '/') || !isspace(*(cp + 1)))
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* skip whitespace up to fstype */
199767f8919635c4928607450d9e0abb932109ceToomas Soome cp += 2;
199767f8919635c4928607450d9e0abb932109ceToomas Soome while ((*cp != 0) && isspace(*cp))
199767f8919635c4928607450d9e0abb932109ceToomas Soome cp++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*cp == 0) /* misformatted */
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* skip text to end of fstype and delimit */
199767f8919635c4928607450d9e0abb932109ceToomas Soome ep = cp;
199767f8919635c4928607450d9e0abb932109ceToomas Soome while ((*cp != 0) && !isspace(*cp))
199767f8919635c4928607450d9e0abb932109ceToomas Soome cp++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome *cp = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome fstyp = strdup(ep);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* skip whitespace up to mount options */
199767f8919635c4928607450d9e0abb932109ceToomas Soome cp += 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome while ((*cp != 0) && isspace(*cp))
199767f8919635c4928607450d9e0abb932109ceToomas Soome cp++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*cp == 0) /* misformatted */
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* skip text to end of mount options and delimit */
199767f8919635c4928607450d9e0abb932109ceToomas Soome ep = cp;
199767f8919635c4928607450d9e0abb932109ceToomas Soome while ((*cp != 0) && !isspace(*cp))
199767f8919635c4928607450d9e0abb932109ceToomas Soome cp++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome *cp = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome options = strdup(ep);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Build the <fstype>:<device> and save it in vfs.root.mountfrom */
199767f8919635c4928607450d9e0abb932109ceToomas Soome sprintf(lbuf, "%s:%s", fstyp, dev);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(dev);
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(fstyp);
199767f8919635c4928607450d9e0abb932109ceToomas Soome setenv("vfs.root.mountfrom", lbuf, 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Don't override vfs.root.mountfrom.options if it is already set */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (getenv("vfs.root.mountfrom.options") == NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* save mount options */
199767f8919635c4928607450d9e0abb932109ceToomas Soome setenv("vfs.root.mountfrom.options", options, 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome free(options);
199767f8919635c4928607450d9e0abb932109ceToomas Soome error = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome close(fd);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomenotfound:
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (error) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome const char *currdev;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome currdev = getenv("currdev");
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (currdev != NULL && strncmp("zfs:", currdev, 4) == 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome cp = strdup(currdev);
199767f8919635c4928607450d9e0abb932109ceToomas Soome cp[strlen(cp) - 1] = '\0';
199767f8919635c4928607450d9e0abb932109ceToomas Soome setenv("vfs.root.mountfrom", cp, 0);
199767f8919635c4928607450d9e0abb932109ceToomas Soome error = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome return(error);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomeloadakernel(int try, int argc, char* argv[])
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *cp;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (try = 0; (cp = getbootfile(try)) != NULL; try++)
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (mod_loadkld(cp, argc - 1, argv + 1) != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("can't load '%s'\n", cp);
199767f8919635c4928607450d9e0abb932109ceToomas Soome else
199767f8919635c4928607450d9e0abb932109ceToomas Soome return 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome}