xref: /freebsd/stand/i386/zfsboot/zfsboot.c (revision a3d9bf49b57923118c339642594246ef73872ee8)
1 /*-
2  * Copyright (c) 1998 Robert Nordier
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are freely
6  * permitted provided that the above copyright notice and this
7  * paragraph and the following disclaimer are duplicated in all
8  * such forms.
9  *
10  * This software is provided "AS IS" and without any express or
11  * implied warranties, including, without limitation, the implied
12  * warranties of merchantability and fitness for a particular
13  * purpose.
14  */
15 
16 #include <sys/cdefs.h>
17 __FBSDID("$FreeBSD$");
18 
19 #include <stand.h>
20 
21 #include <sys/param.h>
22 #include <sys/errno.h>
23 #include <sys/diskmbr.h>
24 #ifdef GPT
25 #include <sys/gpt.h>
26 #endif
27 #include <sys/reboot.h>
28 #include <sys/queue.h>
29 #include <sys/zfs_bootenv.h>
30 
31 #include <machine/bootinfo.h>
32 #include <machine/elf.h>
33 #include <machine/pc/bios.h>
34 
35 #include <stdarg.h>
36 #include <stddef.h>
37 
38 #include <a.out.h>
39 #include "bootstrap.h"
40 #include "libi386.h"
41 #include <btxv86.h>
42 
43 #include "lib.h"
44 #include "rbx.h"
45 #include "cons.h"
46 #include "bootargs.h"
47 #include "disk.h"
48 #include "part.h"
49 #include "paths.h"
50 
51 #include "libzfs.h"
52 
53 #define	ARGS			0x900
54 #define	NOPT			14
55 #define	NDEV			3
56 
57 #define	BIOS_NUMDRIVES		0x475
58 #define	DRV_HARD		0x80
59 #define	DRV_MASK		0x7f
60 
61 #define	TYPE_AD			0
62 #define	TYPE_DA			1
63 #define	TYPE_MAXHARD		TYPE_DA
64 #define	TYPE_FD			2
65 
66 extern uint32_t _end;
67 
68 static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */
69 static const unsigned char flags[NOPT] = {
70     RBX_DUAL,
71     RBX_SERIAL,
72     RBX_ASKNAME,
73     RBX_CDROM,
74     RBX_CONFIG,
75     RBX_KDB,
76     RBX_GDB,
77     RBX_MUTE,
78     RBX_NOINTR,
79     RBX_PAUSE,
80     RBX_QUIET,
81     RBX_DFLTROOT,
82     RBX_SINGLE,
83     RBX_VERBOSE
84 };
85 uint32_t opts;
86 
87 /*
88  * Paths to try loading before falling back to the boot2 prompt.
89  *
90  * /boot/zfsloader must be tried before /boot/loader in order to remain
91  * backward compatible with ZFS boot environments where /boot/loader exists
92  * but does not have ZFS support, which was the case before FreeBSD 12.
93  *
94  * If no loader is found, try to load a kernel directly instead.
95  */
96 static const struct string {
97 	const char *p;
98 	size_t len;
99 } loadpath[] = {
100 	{ PATH_LOADER_ZFS, sizeof(PATH_LOADER_ZFS) },
101 	{ PATH_LOADER, sizeof(PATH_LOADER) },
102 	{ PATH_KERNEL, sizeof(PATH_KERNEL) },
103 };
104 
105 static const unsigned char dev_maj[NDEV] = {30, 4, 2};
106 
107 static struct i386_devdesc *bdev;
108 static char cmd[512];
109 static char cmddup[512];
110 static char kname[1024];
111 static int comspeed = SIOSPD;
112 static struct bootinfo bootinfo;
113 static uint32_t bootdev;
114 static struct zfs_boot_args zfsargs;
115 #ifdef LOADER_GELI_SUPPORT
116 static struct geli_boot_args geliargs;
117 #endif
118 
119 extern vm_offset_t high_heap_base;
120 extern uint32_t	bios_basemem, bios_extmem, high_heap_size;
121 
122 static char *heap_top;
123 static char *heap_bottom;
124 
125 void exit(int);
126 static void i386_zfs_probe(void);
127 static void load(void);
128 static int parse_cmd(void);
129 
130 #ifdef LOADER_GELI_SUPPORT
131 #include "geliboot.h"
132 static char gelipw[GELI_PW_MAXLEN];
133 #endif
134 
135 struct arch_switch archsw;	/* MI/MD interface boundary */
136 static char boot_devname[2 * ZFS_MAXNAMELEN + 8]; /* disk or pool:dataset */
137 
138 struct devsw *devsw[] = {
139 	&bioshd,
140 #if defined(LOADER_ZFS_SUPPORT)
141 	&zfs_dev,
142 #endif
143 	NULL
144 };
145 
146 struct fs_ops *file_system[] = {
147 #if defined(LOADER_ZFS_SUPPORT)
148 	&zfs_fsops,
149 #endif
150 #if defined(LOADER_UFS_SUPPORT)
151 	&ufs_fsops,
152 #endif
153 	NULL
154 };
155 
156 caddr_t
157 ptov(uintptr_t x)
158 {
159 	return (PTOV(x));
160 }
161 
162 int
163 main(void)
164 {
165 	unsigned i;
166 	int auto_boot, fd, nextboot = 0;
167 	struct disk_devdesc devdesc;
168 
169 	bios_getmem();
170 
171 	if (high_heap_size > 0) {
172 		heap_top = PTOV(high_heap_base + high_heap_size);
173 		heap_bottom = PTOV(high_heap_base);
174 	} else {
175 		heap_bottom = (char *)
176 		    (roundup2(__base + (int32_t)&_end, 0x10000) - __base);
177 		heap_top = (char *)PTOV(bios_basemem);
178 	}
179 	setheap(heap_bottom, heap_top);
180 
181 	/*
182 	 * Initialise the block cache. Set the upper limit.
183 	 */
184 	bcache_init(32768, 512);
185 
186 	archsw.arch_autoload = NULL;
187 	archsw.arch_getdev = i386_getdev;
188 	archsw.arch_copyin = NULL;
189 	archsw.arch_copyout = NULL;
190 	archsw.arch_readin = NULL;
191 	archsw.arch_isainb = NULL;
192 	archsw.arch_isaoutb = NULL;
193 	archsw.arch_zfs_probe = i386_zfs_probe;
194 
195 	bootinfo.bi_version = BOOTINFO_VERSION;
196 	bootinfo.bi_size = sizeof(bootinfo);
197 	bootinfo.bi_basemem = bios_basemem / 1024;
198 	bootinfo.bi_extmem = bios_extmem / 1024;
199 	bootinfo.bi_memsizes_valid++;
200 	bootinfo.bi_bios_dev = *(uint8_t *)PTOV(ARGS);
201 
202 	/* Set up fall back device name. */
203 	snprintf(boot_devname, sizeof (boot_devname), "disk%d:",
204 	    bd_bios2unit(bootinfo.bi_bios_dev));
205 
206 	for (i = 0; devsw[i] != NULL; i++)
207 		if (devsw[i]->dv_init != NULL)
208 			(devsw[i]->dv_init)();
209 
210 	disk_parsedev(&devdesc, boot_devname + 4, NULL);
211 
212 	bootdev = MAKEBOOTDEV(dev_maj[DEVT_DISK], devdesc.d_slice + 1,
213 	    devdesc.dd.d_unit,
214 	    devdesc.d_partition >= 0 ? devdesc.d_partition : 0xff);
215 
216 	/*
217 	 * zfs_fmtdev() can be called only after dv_init
218 	 */
219 	if (bdev != NULL && bdev->dd.d_dev->dv_type == DEVT_ZFS) {
220 		/* set up proper device name string for ZFS */
221 		strncpy(boot_devname, zfs_fmtdev(bdev), sizeof (boot_devname));
222 		if (zfs_get_bootonce(bdev, OS_BOOTONCE, cmd,
223 		    sizeof(cmd)) == 0) {
224 			nvlist_t *benv;
225 
226 			nextboot = 1;
227 			memcpy(cmddup, cmd, sizeof(cmd));
228 			if (parse_cmd()) {
229 				if (!OPT_CHECK(RBX_QUIET))
230 					printf("failed to parse bootonce "
231 					    "command\n");
232 				exit(0);
233 			}
234 			if (!OPT_CHECK(RBX_QUIET))
235 				printf("zfs bootonce: %s\n", cmddup);
236 
237 			if (zfs_get_bootenv(bdev, &benv) == 0) {
238 				nvlist_add_string(benv, OS_BOOTONCE_USED,
239 				    cmddup);
240 				zfs_set_bootenv(bdev, benv);
241 			}
242 			/* Do not process this command twice */
243 			*cmd = 0;
244 		}
245 	}
246 
247 	/* now make sure we have bdev on all cases */
248 	free(bdev);
249 	i386_getdev((void **)&bdev, boot_devname, NULL);
250 
251 	env_setenv("currdev", EV_VOLATILE, boot_devname, i386_setcurrdev,
252 	    env_nounset);
253 
254 	/* Process configuration file */
255 	auto_boot = 1;
256 
257 	fd = open(PATH_CONFIG, O_RDONLY);
258 	if (fd == -1)
259 		fd = open(PATH_DOTCONFIG, O_RDONLY);
260 
261 	if (fd != -1) {
262 		ssize_t cmdlen;
263 
264 		if ((cmdlen = read(fd, cmd, sizeof(cmd))) > 0)
265 			cmd[cmdlen] = '\0';
266 		else
267 			*cmd = '\0';
268 		close(fd);
269 	}
270 
271 	if (*cmd) {
272 		/*
273 		 * Note that parse_cmd() is destructive to cmd[] and we also
274 		 * want to honor RBX_QUIET option that could be present in
275 		 * cmd[].
276 		 */
277 		memcpy(cmddup, cmd, sizeof(cmd));
278 		if (parse_cmd())
279 			auto_boot = 0;
280 		if (!OPT_CHECK(RBX_QUIET))
281 			printf("%s: %s\n", PATH_CONFIG, cmddup);
282 		/* Do not process this command twice */
283 		*cmd = 0;
284 	}
285 
286 	/* Do not risk waiting at the prompt forever. */
287 	if (nextboot && !auto_boot)
288 		exit(0);
289 
290 	if (auto_boot && !*kname) {
291 		/*
292 		 * Iterate through the list of loader and kernel paths,
293 		 * trying to load. If interrupted by a keypress, or in case of
294 		 * failure, drop the user to the boot2 prompt.
295 		 */
296 		for (i = 0; i < nitems(loadpath); i++) {
297 			memcpy(kname, loadpath[i].p, loadpath[i].len);
298 			if (keyhit(3))
299 				break;
300 			load();
301 		}
302 	}
303 
304 	/* Present the user with the boot2 prompt. */
305 
306 	for (;;) {
307 		if (!auto_boot || !OPT_CHECK(RBX_QUIET)) {
308 			printf("\nFreeBSD/x86 boot\n");
309 			printf("Default: %s%s\nboot: ", boot_devname, kname);
310 		}
311 		if (ioctrl & IO_SERIAL)
312 			sio_flush();
313 		if (!auto_boot || keyhit(5))
314 			getstr(cmd, sizeof(cmd));
315 		else if (!auto_boot || !OPT_CHECK(RBX_QUIET))
316 			putchar('\n');
317 		auto_boot = 0;
318 		if (parse_cmd())
319 			putchar('\a');
320 		else
321 			load();
322 	}
323 }
324 
325 /* XXX - Needed for btxld to link the boot2 binary; do not remove. */
326 void
327 exit(int x)
328 {
329 	__exit(x);
330 }
331 
332 static void
333 load(void)
334 {
335 	union {
336 		struct exec ex;
337 		Elf32_Ehdr eh;
338 	} hdr;
339 	static Elf32_Phdr ep[2];
340 	static Elf32_Shdr es[2];
341 	caddr_t p;
342 	uint32_t addr, x;
343 	int fd, fmt, i, j;
344 	ssize_t size;
345 
346 	if ((fd = open(kname, O_RDONLY)) == -1) {
347 		printf("\nCan't find %s\n", kname);
348 		return;
349 	}
350 
351 	size = sizeof(hdr);
352 	if (read(fd, &hdr, sizeof (hdr)) != size) {
353 		close(fd);
354 		return;
355 	}
356 	if (N_GETMAGIC(hdr.ex) == ZMAGIC) {
357 		fmt = 0;
358 	} else if (IS_ELF(hdr.eh)) {
359 		fmt = 1;
360 	} else {
361 		printf("Invalid %s\n", "format");
362 		close(fd);
363 		return;
364 	}
365 	if (fmt == 0) {
366 		addr = hdr.ex.a_entry & 0xffffff;
367 		p = PTOV(addr);
368 		lseek(fd, PAGE_SIZE, SEEK_SET);
369 		size = hdr.ex.a_text;
370 		if (read(fd, p, hdr.ex.a_text) != size) {
371 			close(fd);
372 			return;
373 		}
374 		p += roundup2(hdr.ex.a_text, PAGE_SIZE);
375 		size = hdr.ex.a_data;
376 		if (read(fd, p, hdr.ex.a_data) != size) {
377 			close(fd);
378 			return;
379 		}
380 		p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE);
381 		bootinfo.bi_symtab = VTOP(p);
382 		memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
383 		p += sizeof(hdr.ex.a_syms);
384 		if (hdr.ex.a_syms) {
385 			size = hdr.ex.a_syms;
386 			if (read(fd, p, hdr.ex.a_syms) != size) {
387 				close(fd);
388 				return;
389 			}
390 			p += hdr.ex.a_syms;
391 			size = sizeof (int);
392 			if (read(fd, p, sizeof (int)) != size) {
393 				close(fd);
394 				return;
395 			}
396 			x = *(uint32_t *)p;
397 			p += sizeof(int);
398 			x -= sizeof(int);
399 			size = x;
400 			if (read(fd, p, x) != size) {
401 				close(fd);
402 				return;
403 			}
404 			p += x;
405 		}
406 	} else {
407 		lseek(fd, hdr.eh.e_phoff, SEEK_SET);
408 		for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) {
409 			size = sizeof (ep[0]);
410 			if (read(fd, ep + j, sizeof (ep[0])) != size) {
411 				close(fd);
412 				return;
413 			}
414 			if (ep[j].p_type == PT_LOAD)
415 				j++;
416 		}
417 		for (i = 0; i < 2; i++) {
418 			p = PTOV(ep[i].p_paddr & 0xffffff);
419 			lseek(fd, ep[i].p_offset, SEEK_SET);
420 			size = ep[i].p_filesz;
421 			if (read(fd, p, ep[i].p_filesz) != size) {
422 				close(fd);
423 				return;
424 			}
425 		}
426 		p += roundup2(ep[1].p_memsz, PAGE_SIZE);
427 		bootinfo.bi_symtab = VTOP(p);
428 		if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) {
429 			lseek(fd, hdr.eh.e_shoff +
430 			    sizeof (es[0]) * (hdr.eh.e_shstrndx + 1),
431 			    SEEK_SET);
432 			size = sizeof(es);
433 			if (read(fd, &es, sizeof (es)) != size) {
434 				close(fd);
435 				return;
436 			}
437 			for (i = 0; i < 2; i++) {
438 				memcpy(p, &es[i].sh_size,
439 				    sizeof(es[i].sh_size));
440 				p += sizeof(es[i].sh_size);
441 				lseek(fd, es[i].sh_offset, SEEK_SET);
442 				size = es[i].sh_size;
443 				if (read(fd, p, es[i].sh_size) != size) {
444 					close(fd);
445 					return;
446 				}
447 				p += es[i].sh_size;
448 			}
449 		}
450 		addr = hdr.eh.e_entry & 0xffffff;
451 	}
452 	close(fd);
453 
454 	bootinfo.bi_esymtab = VTOP(p);
455 	bootinfo.bi_kernelname = VTOP(kname);
456 #ifdef LOADER_GELI_SUPPORT
457 	explicit_bzero(gelipw, sizeof(gelipw));
458 #endif
459 
460 	if (bdev->dd.d_dev->dv_type == DEVT_ZFS) {
461 		zfsargs.size = sizeof(zfsargs);
462 		zfsargs.pool = bdev->d_kind.zfs.pool_guid;
463 		zfsargs.root = bdev->d_kind.zfs.root_guid;
464 #ifdef LOADER_GELI_SUPPORT
465 		export_geli_boot_data(&zfsargs.gelidata);
466 #endif
467 		/*
468 		 * Note that the zfsargs struct is passed by value, not by
469 		 * pointer. Code in btxldr.S copies the values from the entry
470 		 * stack to a fixed location within loader(8) at startup due
471 		 * to the presence of KARGS_FLAGS_EXTARG.
472 		 */
473 		__exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
474 		    bootdev,
475 		    KARGS_FLAGS_ZFS | KARGS_FLAGS_EXTARG,
476 		    (uint32_t)bdev->d_kind.zfs.pool_guid,
477 		    (uint32_t)(bdev->d_kind.zfs.pool_guid >> 32),
478 		    VTOP(&bootinfo),
479 		    zfsargs);
480 	} else {
481 #ifdef LOADER_GELI_SUPPORT
482 		geliargs.size = sizeof(geliargs);
483 		export_geli_boot_data(&geliargs.gelidata);
484 #endif
485 
486 		/*
487 		 * Note that the geliargs struct is passed by value, not by
488 		 * pointer. Code in btxldr.S copies the values from the entry
489 		 * stack to a fixed location within loader(8) at startup due
490 		 * to the presence of the KARGS_FLAGS_EXTARG flag.
491 		 */
492 		__exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
493 		    bootdev,
494 #ifdef LOADER_GELI_SUPPORT
495 		    KARGS_FLAGS_GELI | KARGS_FLAGS_EXTARG, 0, 0,
496 		    VTOP(&bootinfo), geliargs
497 #else
498 		    0, 0, 0, VTOP(&bootinfo)
499 #endif
500 		    );
501 	}
502 }
503 
504 static int
505 mount_root(char *arg)
506 {
507 	char *root;
508 	struct i386_devdesc *ddesc;
509 	uint8_t part;
510 
511 	if (asprintf(&root, "%s:", arg) < 0)
512 		return (1);
513 
514 	if (i386_getdev((void **)&ddesc, root, NULL)) {
515 		free(root);
516 		return (1);
517 	}
518 
519 	/* we should have new device descriptor, free old and replace it. */
520 	free(bdev);
521 	bdev = ddesc;
522 	if (bdev->dd.d_dev->dv_type == DEVT_DISK) {
523 		if (bdev->d_kind.biosdisk.partition == -1)
524 			part = 0xff;
525 		else
526 			part = bdev->d_kind.biosdisk.partition;
527 		bootdev = MAKEBOOTDEV(dev_maj[bdev->dd.d_dev->dv_type],
528 		    bdev->d_kind.biosdisk.slice + 1,
529 		    bdev->dd.d_unit, part);
530 		bootinfo.bi_bios_dev = bd_unit2bios(bdev);
531 	}
532 	strncpy(boot_devname, root, sizeof (boot_devname));
533 	setenv("currdev", root, 1);
534 	free(root);
535 	return (0);
536 }
537 
538 static void
539 fs_list(char *arg)
540 {
541 	int fd;
542 	struct dirent *d;
543 	char line[80];
544 
545 	fd = open(arg, O_RDONLY);
546 	if (fd < 0)
547 		return;
548 	pager_open();
549 	while ((d = readdirfd(fd)) != NULL) {
550 		sprintf(line, "%s\n", d->d_name);
551 		if (pager_output(line))
552 			break;
553 	}
554 	pager_close();
555 	close(fd);
556 }
557 
558 static int
559 parse_cmd(void)
560 {
561 	char *arg = cmd;
562 	char *ep, *p, *q;
563 	const char *cp;
564 	char line[80];
565 	int c, i, j;
566 
567 	while ((c = *arg++)) {
568 		if (c == ' ' || c == '\t' || c == '\n')
569 			continue;
570 		for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++)
571 			;
572 		ep = p;
573 		if (*p)
574 			*p++ = 0;
575 		if (c == '-') {
576 			while ((c = *arg++)) {
577 				if (c == 'P') {
578 					if (*(uint8_t *)PTOV(0x496) & 0x10) {
579 						cp = "yes";
580 					} else {
581 						opts |= OPT_SET(RBX_DUAL);
582 						opts |= OPT_SET(RBX_SERIAL);
583 						cp = "no";
584 					}
585 					printf("Keyboard: %s\n", cp);
586 					continue;
587 				} else if (c == 'S') {
588 					j = 0;
589 					while ((unsigned int)
590 					    (i = *arg++ - '0') <= 9)
591 						j = j * 10 + i;
592 					if (j > 0 && i == -'0') {
593 						comspeed = j;
594 						break;
595 					}
596 					/*
597 					 * Fall through to error below
598 					 * ('S' not in optstr[]).
599 					 */
600 				}
601 				for (i = 0; c != optstr[i]; i++)
602 					if (i == NOPT - 1)
603 						return (-1);
604 				opts ^= OPT_SET(flags[i]);
605 			}
606 			ioctrl = OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) :
607 			    OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD;
608 			if (ioctrl & IO_SERIAL) {
609 				if (sio_init(115200 / comspeed) != 0)
610 					ioctrl &= ~IO_SERIAL;
611 			}
612 		} if (c == '?') {
613 			printf("\n");
614 			if (*arg == '\0')
615 				arg = (char *)"/";
616 			fs_list(arg);
617 			zfs_list(arg);
618 			return (-1);
619 		} else {
620 			char *ptr;
621 			printf("\n");
622 			arg--;
623 
624 			/*
625 			 * Report pool status if the comment is 'status'. Lets
626 			 * hope no-one wants to load /status as a kernel.
627 			 */
628 			if (strcmp(arg, "status") == 0) {
629 				pager_open();
630 				for (i = 0; devsw[i] != NULL; i++) {
631 					if (devsw[i]->dv_print != NULL) {
632 						if (devsw[i]->dv_print(1))
633 							break;
634 					} else {
635 						snprintf(line, sizeof(line),
636 						    "%s: (unknown)\n",
637 						    devsw[i]->dv_name);
638 						if (pager_output(line))
639 							break;
640 					}
641 				}
642 				pager_close();
643 				return (-1);
644 			}
645 
646 			/*
647 			 * If there is "zfs:" prefix simply ignore it.
648 			 */
649 			ptr = arg;
650 			if (strncmp(ptr, "zfs:", 4) == 0)
651 				ptr += 4;
652 
653 			/*
654 			 * If there is a colon, switch pools.
655 			 */
656 			q = strchr(ptr, ':');
657 			if (q) {
658 				*q++ = '\0';
659 				if (mount_root(arg) != 0) {
660 					return (-1);
661 				}
662 				arg = q;
663 			}
664 			if ((i = ep - arg)) {
665 				if ((size_t)i >= sizeof(kname))
666 					return (-1);
667 				memcpy(kname, arg, i + 1);
668 			}
669 		}
670 		arg = p;
671 	}
672 	return (0);
673 }
674 
675 /*
676  * Probe all disks to discover ZFS pools. The idea is to walk all possible
677  * disk devices, however, we also need to identify possible boot pool.
678  * For boot pool detection we have boot disk passed us from BIOS, recorded
679  * in bootinfo.bi_bios_dev.
680  */
681 static void
682 i386_zfs_probe(void)
683 {
684 	char devname[32];
685 	int boot_unit;
686 	struct i386_devdesc dev;
687 	uint64_t pool_guid = 0;
688 
689 	dev.dd.d_dev = &bioshd;
690 	/* Translate bios dev to our unit number. */
691 	boot_unit = bd_bios2unit(bootinfo.bi_bios_dev);
692 
693 	/*
694 	 * Open all the disks we can find and see if we can reconstruct
695 	 * ZFS pools from them.
696 	 */
697 	for (dev.dd.d_unit = 0; bd_unit2bios(&dev) >= 0; dev.dd.d_unit++) {
698 		snprintf(devname, sizeof (devname), "%s%d:", bioshd.dv_name,
699 		    dev.dd.d_unit);
700 		/* If this is not boot disk, use generic probe. */
701 		if (dev.dd.d_unit != boot_unit)
702 			zfs_probe_dev(devname, NULL);
703 		else
704 			zfs_probe_dev(devname, &pool_guid);
705 
706 		if (pool_guid != 0 && bdev == NULL) {
707 			bdev = malloc(sizeof (struct i386_devdesc));
708 			bzero(bdev, sizeof (struct i386_devdesc));
709 			bdev->dd.d_dev = &zfs_dev;
710 			bdev->d_kind.zfs.pool_guid = pool_guid;
711 		}
712 	}
713 }
714