199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
199767f8919635c4928607450d9e0abb932109ceToomas Soome * All rights reserved.
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 * 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 * 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 * Loading modules, booting the system
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int loadakernel(int try, int argc, char* argv[]);
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 * The user wants us to boot.
199767f8919635c4928607450d9e0abb932109ceToomas SoomeCOMMAND_SET(boot, "boot", "boot a file or loaded kernel", command_boot);
199767f8919635c4928607450d9e0abb932109ceToomas Soome * See if the user has specified an explicit kernel to boot.
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* XXX maybe we should discard everything and start again? */
199767f8919635c4928607450d9e0abb932109ceToomas Soome snprintf(command_errbuf, sizeof (command_errbuf),
199767f8919635c4928607450d9e0abb932109ceToomas Soome "can't boot '%s', kernel module already loaded", argv[1]);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* find/load the kernel module */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (mod_loadkld(argv[1], argc - 2, argv + 2) != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* we have consumed all arguments */
199767f8919635c4928607450d9e0abb932109ceToomas Soome * See if there is a kernel module already loaded
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* we have consumed all arguments */
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Loaded anything yet?
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((fp = file_findfile(NULL, NULL)) == NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome * If we were given arguments, discard any previous.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * XXX should we merge arguments? Hard to DWIM.
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Hook for platform-specific autoloading of modules */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Call the exec handler from the loader matching the kernel */
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Autoboot after a delay
199767f8919635c4928607450d9e0abb932109ceToomas SoomeCOMMAND_SET(autoboot, "autoboot", "boot automatically after a delay", command_autoboot);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* FALLTHROUGH */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*cp != 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome snprintf(command_errbuf, sizeof (command_errbuf),
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* FALLTHROUGH */
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 /* compatibility with sparc prom, check for autoboot? */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((autoboot_tried == 0) && ((cp == NULL) || strcasecmp(cp, "NO")))
199767f8919635c4928607450d9e0abb932109ceToomas Soome autoboot(-1, NULL); /* try to boot automatically */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* try to get a delay from the environment */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fp == NULL) { /* no preloaded files, run command start to load all */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (fp == NULL) { /* still nothing? can't boot */
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("%s\n", (prompt == NULL) ? "Hit [Enter] to boot immediately, or any other key for command prompt." : prompt);
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Scrounge for the name of the (try)'th file we will try to boot.
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic char *
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* we use dynamic storage */
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Try $bootfile, then try our builtin default
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 * 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 char lbuf[128], *cp, *ep, *dev, *fstyp, *options;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* loop reading lines from /etc/fstab What was that about sscanf again? */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* skip device name */
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (cp = lbuf; (*cp != 0) && !isspace(*cp); cp++)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* delimit and save */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* skip whitespace up to mountpoint */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* must have /<space> to be root */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((*cp == 0) || (*cp != '/') || !isspace(*(cp + 1)))
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* skip whitespace up to fstype */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* skip text to end of fstype and delimit */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* skip whitespace up to mount options */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* skip text to end of mount options and delimit */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Build the <fstype>:<device> and save it in vfs.root.mountfrom */
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 if (currdev != NULL && strncmp("zfs:", currdev, 4) == 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (try = 0; (cp = getbootfile(try)) != NULL; try++)