xref: /illumos-gate/usr/src/boot/sys/boot/common/boot.c (revision d66a72cf)
1bc85f3b0SToomas Soome /*
2199767f8SToomas Soome  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3199767f8SToomas Soome  * All rights reserved.
4199767f8SToomas Soome  *
5199767f8SToomas Soome  * Redistribution and use in source and binary forms, with or without
6199767f8SToomas Soome  * modification, are permitted provided that the following conditions
7199767f8SToomas Soome  * are met:
8199767f8SToomas Soome  * 1. Redistributions of source code must retain the above copyright
9199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer.
10199767f8SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
11199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
12199767f8SToomas Soome  *    documentation and/or other materials provided with the distribution.
13199767f8SToomas Soome  *
14199767f8SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15199767f8SToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16199767f8SToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17199767f8SToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18199767f8SToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19199767f8SToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20199767f8SToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21199767f8SToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22199767f8SToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23199767f8SToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24199767f8SToomas Soome  * SUCH DAMAGE.
25199767f8SToomas Soome  */
26199767f8SToomas Soome 
27199767f8SToomas Soome #include <sys/cdefs.h>
28199767f8SToomas Soome 
29199767f8SToomas Soome /*
30199767f8SToomas Soome  * Loading modules, booting the system
31199767f8SToomas Soome  */
32199767f8SToomas Soome 
33199767f8SToomas Soome #include <stand.h>
34199767f8SToomas Soome #include <string.h>
35199767f8SToomas Soome 
36199767f8SToomas Soome #include "bootstrap.h"
37199767f8SToomas Soome 
38199767f8SToomas Soome static char	*getbootfile(int try);
39*d66a72cfSToomas Soome static int	loadakernel(int try, int argc, char *argv[]);
40199767f8SToomas Soome 
41*d66a72cfSToomas Soome /*
42*d66a72cfSToomas Soome  * List of kernel names to try (may be overwritten by boot.config)
43*d66a72cfSToomas Soome  * XXX should move from here?
44*d66a72cfSToomas Soome  */
45199767f8SToomas Soome static const char *default_bootfiles = "kernel";
46199767f8SToomas Soome 
47199767f8SToomas Soome static int autoboot_tried;
48199767f8SToomas Soome 
49199767f8SToomas Soome /*
50199767f8SToomas Soome  * The user wants us to boot.
51199767f8SToomas Soome  */
52199767f8SToomas Soome COMMAND_SET(boot, "boot", "boot a file or loaded kernel", command_boot);
53199767f8SToomas Soome 
54199767f8SToomas Soome static int
command_boot(int argc,char * argv[])55199767f8SToomas Soome command_boot(int argc, char *argv[])
56199767f8SToomas Soome {
57*d66a72cfSToomas Soome 	struct preloaded_file *fp;
58*d66a72cfSToomas Soome 
59*d66a72cfSToomas Soome 	/*
60*d66a72cfSToomas Soome 	 * See if the user has specified an explicit kernel to boot.
61*d66a72cfSToomas Soome 	 */
62*d66a72cfSToomas Soome 	if ((argc > 1) && (argv[1][0] == '/')) {
63*d66a72cfSToomas Soome 
64*d66a72cfSToomas Soome 		/* XXX maybe we should discard everything and start again? */
65*d66a72cfSToomas Soome 		if (file_findfile(NULL, NULL) != NULL) {
66*d66a72cfSToomas Soome 			snprintf(command_errbuf, sizeof (command_errbuf),
67*d66a72cfSToomas Soome 			    "can't boot '%s', kernel module already loaded",
68*d66a72cfSToomas Soome 			    argv[1]);
69*d66a72cfSToomas Soome 			return (CMD_ERROR);
70*d66a72cfSToomas Soome 		}
71*d66a72cfSToomas Soome 
72*d66a72cfSToomas Soome 		/* find/load the kernel module */
73*d66a72cfSToomas Soome 		if (mod_loadkld(argv[1], argc - 2, argv + 2) != 0)
74*d66a72cfSToomas Soome 			return (CMD_ERROR);
75*d66a72cfSToomas Soome 		/* we have consumed all arguments */
76*d66a72cfSToomas Soome 		argc = 1;
77*d66a72cfSToomas Soome 	}
78*d66a72cfSToomas Soome 
79*d66a72cfSToomas Soome 	/*
80*d66a72cfSToomas Soome 	 * See if there is a kernel module already loaded
81*d66a72cfSToomas Soome 	 */
82*d66a72cfSToomas Soome 	if (file_findfile(NULL, NULL) == NULL)
83*d66a72cfSToomas Soome 		if (loadakernel(0, argc - 1, argv + 1)) {
84*d66a72cfSToomas Soome 			/* we have consumed all arguments */
85*d66a72cfSToomas Soome 			argc = 1;
86*d66a72cfSToomas Soome 		}
87*d66a72cfSToomas Soome 
88*d66a72cfSToomas Soome 	/*
89*d66a72cfSToomas Soome 	 * Loaded anything yet?
90*d66a72cfSToomas Soome 	 */
91*d66a72cfSToomas Soome 	if ((fp = file_findfile(NULL, NULL)) == NULL) {
92*d66a72cfSToomas Soome 		command_errmsg = "no bootable kernel";
93*d66a72cfSToomas Soome 		return (CMD_ERROR);
94*d66a72cfSToomas Soome 	}
95*d66a72cfSToomas Soome 
96*d66a72cfSToomas Soome 	/*
97*d66a72cfSToomas Soome 	 * If we were given arguments, discard any previous.
98*d66a72cfSToomas Soome 	 * XXX should we merge arguments?  Hard to DWIM.
99*d66a72cfSToomas Soome 	 */
100*d66a72cfSToomas Soome 	if (argc > 1) {
101*d66a72cfSToomas Soome 		free(fp->f_args);
102*d66a72cfSToomas Soome 		fp->f_args = unargv(argc - 1, argv + 1);
103199767f8SToomas Soome 	}
104199767f8SToomas Soome 
105*d66a72cfSToomas Soome 	/* Hook for platform-specific autoloading of modules */
106*d66a72cfSToomas Soome 	if (archsw.arch_autoload() != 0)
107*d66a72cfSToomas Soome 		return (CMD_ERROR);
108*d66a72cfSToomas Soome 
109*d66a72cfSToomas Soome 	/* Call the exec handler from the loader matching the kernel */
110*d66a72cfSToomas Soome 	file_formats[fp->f_loader]->l_exec(fp);
111*d66a72cfSToomas Soome 	return (CMD_ERROR);
112199767f8SToomas Soome }
113199767f8SToomas Soome 
114199767f8SToomas Soome 
115199767f8SToomas Soome /*
116199767f8SToomas Soome  * Autoboot after a delay
117199767f8SToomas Soome  */
118199767f8SToomas Soome 
119*d66a72cfSToomas Soome COMMAND_SET(autoboot, "autoboot", "boot automatically after a delay",
120*d66a72cfSToomas Soome     command_autoboot);
121199767f8SToomas Soome 
122199767f8SToomas Soome static int
command_autoboot(int argc,char * argv[])123199767f8SToomas Soome command_autoboot(int argc, char *argv[])
124199767f8SToomas Soome {
125*d66a72cfSToomas Soome 	int howlong;
126*d66a72cfSToomas Soome 	char *cp, *prompt;
127*d66a72cfSToomas Soome 
128*d66a72cfSToomas Soome 	prompt = NULL;
129*d66a72cfSToomas Soome 	howlong = -1;
130*d66a72cfSToomas Soome 	switch (argc) {
131*d66a72cfSToomas Soome 	case 3:
132*d66a72cfSToomas Soome 		prompt = argv[2];
133*d66a72cfSToomas Soome 		/* FALLTHROUGH */
134*d66a72cfSToomas Soome 	case 2:
135*d66a72cfSToomas Soome 		howlong = strtol(argv[1], &cp, 0);
136*d66a72cfSToomas Soome 		if (*cp != 0) {
137*d66a72cfSToomas Soome 			snprintf(command_errbuf, sizeof (command_errbuf),
138*d66a72cfSToomas Soome 			    "bad delay '%s'", argv[1]);
139*d66a72cfSToomas Soome 			return (CMD_ERROR);
140*d66a72cfSToomas Soome 		}
141*d66a72cfSToomas Soome 		/* FALLTHROUGH */
142*d66a72cfSToomas Soome 	case 1:
143*d66a72cfSToomas Soome 		return (autoboot(howlong, prompt));
144199767f8SToomas Soome 	}
145199767f8SToomas Soome 
146*d66a72cfSToomas Soome 	command_errmsg = "too many arguments";
147*d66a72cfSToomas Soome 	return (CMD_ERROR);
148199767f8SToomas Soome }
149199767f8SToomas Soome 
150199767f8SToomas Soome /*
151199767f8SToomas Soome  * Called before we go interactive.  If we think we can autoboot, and
152199767f8SToomas Soome  * we haven't tried already, try now.
153199767f8SToomas Soome  */
154199767f8SToomas Soome void
autoboot_maybe(void)155199767f8SToomas Soome autoboot_maybe(void)
156199767f8SToomas Soome {
157*d66a72cfSToomas Soome 	char *cp;
158*d66a72cfSToomas Soome 
159*d66a72cfSToomas Soome 	/* compatibility with sparc prom, check for autoboot? */
160*d66a72cfSToomas Soome 	cp = getenv("autoboot?");
161*d66a72cfSToomas Soome 	if (cp != NULL && strcasecmp(cp, "true") != 0)
162*d66a72cfSToomas Soome 		return;
163*d66a72cfSToomas Soome 	cp = getenv("autoboot_delay");
164*d66a72cfSToomas Soome 	if ((autoboot_tried == 0) && ((cp == NULL) || strcasecmp(cp, "NO")))
165*d66a72cfSToomas Soome 		autoboot(-1, NULL);		/* try to boot automatically */
166199767f8SToomas Soome }
167199767f8SToomas Soome 
168199767f8SToomas Soome int
autoboot(int timeout,char * prompt)169199767f8SToomas Soome autoboot(int timeout, char *prompt)
170199767f8SToomas Soome {
171*d66a72cfSToomas Soome 	time_t when, otime, ntime;
172*d66a72cfSToomas Soome 	int c, yes;
173*d66a72cfSToomas Soome 	char *argv[2], *cp, *ep;
174*d66a72cfSToomas Soome 	char *kernelname;
175*d66a72cfSToomas Soome 	struct preloaded_file *fp;
176*d66a72cfSToomas Soome 
177*d66a72cfSToomas Soome 	autoboot_tried = 1;
178*d66a72cfSToomas Soome 
179*d66a72cfSToomas Soome 	if (timeout == -1) {
180*d66a72cfSToomas Soome 		timeout = 10;
181*d66a72cfSToomas Soome 		/* try to get a delay from the environment */
182*d66a72cfSToomas Soome 		if ((cp = getenv("autoboot_delay"))) {
183*d66a72cfSToomas Soome 			timeout = strtol(cp, &ep, 0);
184*d66a72cfSToomas Soome 			if (cp == ep)
185*d66a72cfSToomas Soome 				timeout = 10;	/* Unparseable? Set default! */
186*d66a72cfSToomas Soome 		}
187199767f8SToomas Soome 	}
188199767f8SToomas Soome 
189199767f8SToomas Soome 	fp = file_findfile(NULL, NULL);
190*d66a72cfSToomas Soome 	if (fp == NULL) {
191*d66a72cfSToomas Soome 		/* no preloaded files, run command start to load all */
192*d66a72cfSToomas Soome 		bf_run("start");
193*d66a72cfSToomas Soome 		fp = file_findfile(NULL, NULL);
194*d66a72cfSToomas Soome 		if (fp == NULL) { /* still nothing? can't boot */
195*d66a72cfSToomas Soome 			command_errmsg = "no valid kernel found";
196*d66a72cfSToomas Soome 			return (CMD_ERROR);
197*d66a72cfSToomas Soome 		}
198*d66a72cfSToomas Soome 	}
199*d66a72cfSToomas Soome 
200*d66a72cfSToomas Soome 	kernelname = fp->f_name;
201*d66a72cfSToomas Soome 
202*d66a72cfSToomas Soome 	if (timeout >= 0) {
203*d66a72cfSToomas Soome 		otime = time(NULL);
204*d66a72cfSToomas Soome 		when = otime + timeout;	/* when to boot */
205*d66a72cfSToomas Soome 
206*d66a72cfSToomas Soome 		yes = 0;
207*d66a72cfSToomas Soome 
208*d66a72cfSToomas Soome 		printf("%s\n", (prompt == NULL) ?
209*d66a72cfSToomas Soome 		    "Hit [Enter] to boot immediately, or any other key "
210*d66a72cfSToomas Soome 		    "for command prompt." : prompt);
211*d66a72cfSToomas Soome 
212*d66a72cfSToomas Soome 		for (;;) {
213*d66a72cfSToomas Soome 			if (ischar()) {
214*d66a72cfSToomas Soome 				c = getchar();
215*d66a72cfSToomas Soome 				if ((c == '\r') || (c == '\n'))
216*d66a72cfSToomas Soome 					yes = 1;
217*d66a72cfSToomas Soome 				break;
218*d66a72cfSToomas Soome 			}
219*d66a72cfSToomas Soome 			ntime = time(NULL);
220*d66a72cfSToomas Soome 			if (ntime >= when) {
221*d66a72cfSToomas Soome 				yes = 1;
222*d66a72cfSToomas Soome 				break;
223*d66a72cfSToomas Soome 			}
224*d66a72cfSToomas Soome 
225*d66a72cfSToomas Soome 			if (ntime != otime) {
226*d66a72cfSToomas Soome 				printf("\rBooting [%s] in %d second%s... ",
227*d66a72cfSToomas Soome 				    kernelname, (int)(when - ntime),
228*d66a72cfSToomas Soome 				    (when - ntime) == 1? "":"s");
229*d66a72cfSToomas Soome 				otime = ntime;
230*d66a72cfSToomas Soome 			}
231*d66a72cfSToomas Soome 		}
232*d66a72cfSToomas Soome 	} else {
233*d66a72cfSToomas Soome 		yes = 1;
234199767f8SToomas Soome 	}
235*d66a72cfSToomas Soome 
236*d66a72cfSToomas Soome 	if (yes)
237*d66a72cfSToomas Soome 		printf("\rBooting [%s]...               ", kernelname);
238*d66a72cfSToomas Soome 	putchar('\n');
239*d66a72cfSToomas Soome 	if (yes) {
240*d66a72cfSToomas Soome 		argv[0] = "boot";
241*d66a72cfSToomas Soome 		argv[1] = NULL;
242*d66a72cfSToomas Soome 		return (command_boot(1, argv));
243*d66a72cfSToomas Soome 	}
244*d66a72cfSToomas Soome 	return (CMD_OK);
245199767f8SToomas Soome }
246199767f8SToomas Soome 
247199767f8SToomas Soome /*
248199767f8SToomas Soome  * Scrounge for the name of the (try)'th file we will try to boot.
249199767f8SToomas Soome  */
250199767f8SToomas Soome static char *
getbootfile(int try)251199767f8SToomas Soome getbootfile(int try)
252199767f8SToomas Soome {
253*d66a72cfSToomas Soome 	static char *name = NULL;
254*d66a72cfSToomas Soome 	const char *spec, *ep;
255*d66a72cfSToomas Soome 	size_t len;
256199767f8SToomas Soome 
257*d66a72cfSToomas Soome 	/* we use dynamic storage */
258199767f8SToomas Soome 	free(name);
259199767f8SToomas Soome 	name = NULL;
260*d66a72cfSToomas Soome 
261*d66a72cfSToomas Soome 	/*
262*d66a72cfSToomas Soome 	 * Try $bootfile, then try our builtin default
263*d66a72cfSToomas Soome 	 */
264*d66a72cfSToomas Soome 	if ((spec = getenv("bootfile")) == NULL)
265*d66a72cfSToomas Soome 		spec = default_bootfiles;
266*d66a72cfSToomas Soome 
267*d66a72cfSToomas Soome 	while ((try > 0) && (spec != NULL)) {
268*d66a72cfSToomas Soome 		spec = strchr(spec, ';');
269*d66a72cfSToomas Soome 		if (spec)
270*d66a72cfSToomas Soome 			spec++;	/* skip over the leading ';' */
271*d66a72cfSToomas Soome 		try--;
272199767f8SToomas Soome 	}
273*d66a72cfSToomas Soome 	if (spec != NULL) {
274*d66a72cfSToomas Soome 		if ((ep = strchr(spec, ';')) != NULL) {
275*d66a72cfSToomas Soome 			len = ep - spec;
276*d66a72cfSToomas Soome 		} else {
277*d66a72cfSToomas Soome 			len = strlen(spec);
278*d66a72cfSToomas Soome 		}
279*d66a72cfSToomas Soome 		name = malloc(len + 1);
280*d66a72cfSToomas Soome 		strncpy(name, spec, len);
281*d66a72cfSToomas Soome 		name[len] = 0;
282*d66a72cfSToomas Soome 	}
283*d66a72cfSToomas Soome 	if (name && name[0] == 0) {
284*d66a72cfSToomas Soome 		free(name);
285*d66a72cfSToomas Soome 		name = NULL;
286*d66a72cfSToomas Soome 	}
287*d66a72cfSToomas Soome 	return (name);
288199767f8SToomas Soome }
289199767f8SToomas Soome 
290199767f8SToomas Soome /*
291199767f8SToomas Soome  * Try to find the /etc/fstab file on the filesystem (rootdev),
292199767f8SToomas Soome  * which should be be the root filesystem, and parse it to find
293199767f8SToomas Soome  * out what the kernel ought to think the root filesystem is.
294199767f8SToomas Soome  *
295199767f8SToomas Soome  * If we're successful, set vfs.root.mountfrom to <vfstype>:<path>
296199767f8SToomas Soome  * so that the kernel can tell both which VFS and which node to use
297199767f8SToomas Soome  * to mount the device.  If this variable's already set, don't
298199767f8SToomas Soome  * overwrite it.
299199767f8SToomas Soome  */
300199767f8SToomas Soome int
getrootmount(char * rootdev)301199767f8SToomas Soome getrootmount(char *rootdev)
302199767f8SToomas Soome {
303*d66a72cfSToomas Soome 	char lbuf[128], *cp, *ep, *dev, *fstyp, *options;
304*d66a72cfSToomas Soome 	int fd, error;
305*d66a72cfSToomas Soome 
306*d66a72cfSToomas Soome 	if (getenv("vfs.root.mountfrom") != NULL)
307*d66a72cfSToomas Soome 		return (0);
308*d66a72cfSToomas Soome 
309*d66a72cfSToomas Soome 	error = 1;
310*d66a72cfSToomas Soome 	sprintf(lbuf, "%s/etc/fstab", rootdev);
311*d66a72cfSToomas Soome 	if ((fd = open(lbuf, O_RDONLY)) < 0)
312*d66a72cfSToomas Soome 		goto notfound;
313*d66a72cfSToomas Soome 
314*d66a72cfSToomas Soome 	/*
315*d66a72cfSToomas Soome 	 * loop reading lines from /etc/fstab
316*d66a72cfSToomas Soome 	 * What was that about sscanf again?
317*d66a72cfSToomas Soome 	 */
318*d66a72cfSToomas Soome 	fstyp = NULL;
319*d66a72cfSToomas Soome 	dev = NULL;
320*d66a72cfSToomas Soome 	while (fgetstr(lbuf, sizeof (lbuf), fd) >= 0) {
321*d66a72cfSToomas Soome 		if ((lbuf[0] == 0) || (lbuf[0] == '#'))
322*d66a72cfSToomas Soome 			continue;
323*d66a72cfSToomas Soome 
324*d66a72cfSToomas Soome 		/* skip device name */
325*d66a72cfSToomas Soome 		for (cp = lbuf; (*cp != 0) && !isspace(*cp); cp++)
326*d66a72cfSToomas Soome 			;
327*d66a72cfSToomas Soome 		if (*cp == 0)		/* misformatted */
328*d66a72cfSToomas Soome 			continue;
329*d66a72cfSToomas Soome 		/* delimit and save */
330*d66a72cfSToomas Soome 		*cp++ = 0;
331*d66a72cfSToomas Soome 		free(dev);
332*d66a72cfSToomas Soome 		dev = strdup(lbuf);
333*d66a72cfSToomas Soome 
334*d66a72cfSToomas Soome 		/* skip whitespace up to mountpoint */
335*d66a72cfSToomas Soome 		while ((*cp != 0) && isspace(*cp))
336*d66a72cfSToomas Soome 			cp++;
337*d66a72cfSToomas Soome 		/* must have /<space> to be root */
338*d66a72cfSToomas Soome 		if ((*cp == 0) || (*cp != '/') || !isspace(*(cp + 1)))
339*d66a72cfSToomas Soome 			continue;
340*d66a72cfSToomas Soome 		/* skip whitespace up to fstype */
341*d66a72cfSToomas Soome 		cp += 2;
342*d66a72cfSToomas Soome 		while ((*cp != 0) && isspace(*cp))
343*d66a72cfSToomas Soome 			cp++;
344*d66a72cfSToomas Soome 		if (*cp == 0)		/* misformatted */
345*d66a72cfSToomas Soome 			continue;
346*d66a72cfSToomas Soome 		/* skip text to end of fstype and delimit */
347*d66a72cfSToomas Soome 		ep = cp;
348*d66a72cfSToomas Soome 		while ((*cp != 0) && !isspace(*cp))
349*d66a72cfSToomas Soome 			cp++;
350*d66a72cfSToomas Soome 		*cp = 0;
351*d66a72cfSToomas Soome 		free(fstyp);
352*d66a72cfSToomas Soome 		fstyp = strdup(ep);
353*d66a72cfSToomas Soome 
354*d66a72cfSToomas Soome 		/* skip whitespace up to mount options */
355*d66a72cfSToomas Soome 		cp += 1;
356*d66a72cfSToomas Soome 		while ((*cp != 0) && isspace(*cp))
357*d66a72cfSToomas Soome 			cp++;
358*d66a72cfSToomas Soome 		if (*cp == 0)		/* misformatted */
359*d66a72cfSToomas Soome 			continue;
360*d66a72cfSToomas Soome 		/* skip text to end of mount options and delimit */
361*d66a72cfSToomas Soome 		ep = cp;
362*d66a72cfSToomas Soome 		while ((*cp != 0) && !isspace(*cp))
363*d66a72cfSToomas Soome 			cp++;
364*d66a72cfSToomas Soome 		*cp = 0;
365*d66a72cfSToomas Soome 		options = strdup(ep);
366*d66a72cfSToomas Soome 		/*
367*d66a72cfSToomas Soome 		 * Build the <fstype>:<device> and save it in
368*d66a72cfSToomas Soome 		 * vfs.root.mountfrom
369*d66a72cfSToomas Soome 		 */
370*d66a72cfSToomas Soome 		sprintf(lbuf, "%s:%s", fstyp, dev);
371*d66a72cfSToomas Soome 		setenv("vfs.root.mountfrom", lbuf, 0);
372*d66a72cfSToomas Soome 
373*d66a72cfSToomas Soome 		/*
374*d66a72cfSToomas Soome 		 * Don't override vfs.root.mountfrom.options if it is
375*d66a72cfSToomas Soome 		 * already set
376*d66a72cfSToomas Soome 		 */
377*d66a72cfSToomas Soome 		if (getenv("vfs.root.mountfrom.options") == NULL) {
378*d66a72cfSToomas Soome 			/* save mount options */
379*d66a72cfSToomas Soome 			setenv("vfs.root.mountfrom.options", options, 0);
380*d66a72cfSToomas Soome 		}
381*d66a72cfSToomas Soome 		free(options);
382*d66a72cfSToomas Soome 		error = 0;
383*d66a72cfSToomas Soome 		break;
384*d66a72cfSToomas Soome 	}
385*d66a72cfSToomas Soome 	close(fd);
386bc85f3b0SToomas Soome 	free(dev);
387bc85f3b0SToomas Soome 	free(fstyp);
388199767f8SToomas Soome 
389199767f8SToomas Soome notfound:
390*d66a72cfSToomas Soome 	if (error) {
391*d66a72cfSToomas Soome 		const char *currdev;
392*d66a72cfSToomas Soome 
393*d66a72cfSToomas Soome 		currdev = getenv("currdev");
394*d66a72cfSToomas Soome 		if (currdev != NULL && strncmp("zfs:", currdev, 4) == 0) {
395*d66a72cfSToomas Soome 			cp = strdup(currdev);
396*d66a72cfSToomas Soome 			cp[strlen(cp) - 1] = '\0';
397*d66a72cfSToomas Soome 			setenv("vfs.root.mountfrom", cp, 0);
398*d66a72cfSToomas Soome 			error = 0;
399*d66a72cfSToomas Soome 			free(cp);
400*d66a72cfSToomas Soome 		}
401199767f8SToomas Soome 	}
402199767f8SToomas Soome 
403*d66a72cfSToomas Soome 	return (error);
404199767f8SToomas Soome }
405199767f8SToomas Soome 
406199767f8SToomas Soome static int
loadakernel(int try,int argc,char * argv[])407*d66a72cfSToomas Soome loadakernel(int try, int argc, char *argv[])
408199767f8SToomas Soome {
409*d66a72cfSToomas Soome 	char *cp;
410199767f8SToomas Soome 
411199767f8SToomas Soome 	for (try = 0; (cp = getbootfile(try)) != NULL; try++)
412*d66a72cfSToomas Soome 		if (mod_loadkld(cp, argc - 1, argv + 1) != 0)
413*d66a72cfSToomas Soome 			printf("can't load '%s'\n", cp);
414*d66a72cfSToomas Soome 		else
415*d66a72cfSToomas Soome 			return (1);
416*d66a72cfSToomas Soome 	return (0);
417199767f8SToomas Soome }
418