]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - stand/i386/zfsboot/zfsboot.c
Add 'contrib/unifdef/' from commit '0da44885831dc0a43c4ca6ff04a2430993cc0a80'
[FreeBSD/FreeBSD.git] / stand / i386 / zfsboot / zfsboot.c
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 #include <stand.h>
18
19 #include <sys/param.h>
20 #include <sys/errno.h>
21 #include <sys/diskmbr.h>
22 #ifdef GPT
23 #include <sys/gpt.h>
24 #endif
25 #include <sys/reboot.h>
26 #include <sys/queue.h>
27 #ifdef LOADER_ZFS_SUPPORT
28 #include <sys/zfs_bootenv.h>
29 #endif
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 main(void);
163
164 int
165 main(void)
166 {
167         unsigned i;
168         int auto_boot, fd, nextboot = 0;
169         struct disk_devdesc *devdesc;
170
171         bios_getmem();
172
173         if (high_heap_size > 0) {
174                 heap_top = PTOV(high_heap_base + high_heap_size);
175                 heap_bottom = PTOV(high_heap_base);
176         } else {
177                 heap_bottom = (char *)
178                     (roundup2(__base + (int32_t)&_end, 0x10000) - __base);
179                 heap_top = (char *)PTOV(bios_basemem);
180         }
181         setheap(heap_bottom, heap_top);
182
183         /*
184          * Initialise the block cache. Set the upper limit.
185          */
186         bcache_init(32768, 512);
187
188         archsw.arch_autoload = NULL;
189         archsw.arch_getdev = i386_getdev;
190         archsw.arch_copyin = NULL;
191         archsw.arch_copyout = NULL;
192         archsw.arch_readin = NULL;
193         archsw.arch_isainb = NULL;
194         archsw.arch_isaoutb = NULL;
195         archsw.arch_zfs_probe = i386_zfs_probe;
196
197         bootinfo.bi_version = BOOTINFO_VERSION;
198         bootinfo.bi_size = sizeof(bootinfo);
199         bootinfo.bi_basemem = bios_basemem / 1024;
200         bootinfo.bi_extmem = bios_extmem / 1024;
201         bootinfo.bi_memsizes_valid++;
202         bootinfo.bi_bios_dev = *(uint8_t *)PTOV(ARGS);
203
204         /* Set up fall back device name. */
205         snprintf(boot_devname, sizeof (boot_devname), "disk%d:",
206             bd_bios2unit(bootinfo.bi_bios_dev));
207
208         /* Set up currdev variable to have hooks in place. */
209         env_setenv("currdev", EV_VOLATILE, "", gen_setcurrdev,
210             env_nounset);
211
212         devinit();
213
214         /* XXX assumes this will be a disk, but it looks likely give above */
215         disk_parsedev((struct devdesc **)&devdesc, boot_devname, NULL);
216
217         bootdev = MAKEBOOTDEV(dev_maj[DEVT_DISK], devdesc->d_slice + 1,
218             devdesc->dd.d_unit,
219             devdesc->d_partition >= 0 ? devdesc->d_partition : 0xff);
220         free(devdesc);
221
222         /*
223          * devformat() can be called only after dv_init
224          */
225         if (bdev != NULL && bdev->dd.d_dev->dv_type == DEVT_ZFS) {
226                 /* set up proper device name string for ZFS */
227                 strncpy(boot_devname, devformat(&bdev->dd), sizeof (boot_devname));
228                 if (zfs_get_bootonce(bdev, OS_BOOTONCE, cmd,
229                     sizeof(cmd)) == 0) {
230                         nvlist_t *benv;
231
232                         nextboot = 1;
233                         memcpy(cmddup, cmd, sizeof(cmd));
234                         if (parse_cmd()) {
235                                 if (!OPT_CHECK(RBX_QUIET))
236                                         printf("failed to parse bootonce "
237                                             "command\n");
238                                 exit(0);
239                         }
240                         if (!OPT_CHECK(RBX_QUIET))
241                                 printf("zfs bootonce: %s\n", cmddup);
242
243                         if (zfs_get_bootenv(bdev, &benv) == 0) {
244                                 nvlist_add_string(benv, OS_BOOTONCE_USED,
245                                     cmddup);
246                                 zfs_set_bootenv(bdev, benv);
247                         }
248                         /* Do not process this command twice */
249                         *cmd = 0;
250                 }
251         }
252
253         /* now make sure we have bdev on all cases */
254         free(bdev);
255         i386_getdev((void **)&bdev, boot_devname, NULL);
256
257         env_setenv("currdev", EV_VOLATILE, boot_devname, gen_setcurrdev,
258             env_nounset);
259
260         /* Process configuration file */
261         auto_boot = 1;
262
263         fd = open(PATH_CONFIG, O_RDONLY);
264         if (fd == -1)
265                 fd = open(PATH_DOTCONFIG, O_RDONLY);
266
267         if (fd != -1) {
268                 ssize_t cmdlen;
269
270                 if ((cmdlen = read(fd, cmd, sizeof(cmd))) > 0)
271                         cmd[cmdlen] = '\0';
272                 else
273                         *cmd = '\0';
274                 close(fd);
275         }
276
277         if (*cmd) {
278                 /*
279                  * Note that parse_cmd() is destructive to cmd[] and we also
280                  * want to honor RBX_QUIET option that could be present in
281                  * cmd[].
282                  */
283                 memcpy(cmddup, cmd, sizeof(cmd));
284                 if (parse_cmd())
285                         auto_boot = 0;
286                 if (!OPT_CHECK(RBX_QUIET))
287                         printf("%s: %s\n", PATH_CONFIG, cmddup);
288                 /* Do not process this command twice */
289                 *cmd = 0;
290         }
291
292         /* Do not risk waiting at the prompt forever. */
293         if (nextboot && !auto_boot)
294                 exit(0);
295
296         if (auto_boot && !*kname) {
297                 /*
298                  * Iterate through the list of loader and kernel paths,
299                  * trying to load. If interrupted by a keypress, or in case of
300                  * failure, drop the user to the boot2 prompt.
301                  */
302                 for (i = 0; i < nitems(loadpath); i++) {
303                         memcpy(kname, loadpath[i].p, loadpath[i].len);
304                         if (keyhit(3))
305                                 break;
306                         load();
307                 }
308         }
309
310         /* Present the user with the boot2 prompt. */
311
312         for (;;) {
313                 if (!auto_boot || !OPT_CHECK(RBX_QUIET)) {
314                         printf("\nFreeBSD/x86 boot\n");
315                         printf("Default: %s%s\nboot: ", boot_devname, kname);
316                 }
317                 if (ioctrl & IO_SERIAL)
318                         sio_flush();
319                 if (!auto_boot || keyhit(5))
320                         getstr(cmd, sizeof(cmd));
321                 else if (!auto_boot || !OPT_CHECK(RBX_QUIET))
322                         putchar('\n');
323                 auto_boot = 0;
324                 if (parse_cmd())
325                         putchar('\a');
326                 else
327                         load();
328         }
329 }
330
331 /* XXX - Needed for btxld to link the boot2 binary; do not remove. */
332 void
333 exit(int x)
334 {
335         __exit(x);
336 }
337
338 static void
339 load(void)
340 {
341         union {
342                 struct exec ex;
343                 Elf32_Ehdr eh;
344         } hdr;
345         static Elf32_Phdr ep[2];
346         static Elf32_Shdr es[2];
347         caddr_t p;
348         uint32_t addr, x;
349         int fd, fmt, i, j;
350         ssize_t size;
351
352         if ((fd = open(kname, O_RDONLY)) == -1) {
353                 printf("\nCan't find %s\n", kname);
354                 return;
355         }
356
357         size = sizeof(hdr);
358         if (read(fd, &hdr, sizeof (hdr)) != size) {
359                 close(fd);
360                 return;
361         }
362         if (N_GETMAGIC(hdr.ex) == ZMAGIC) {
363                 fmt = 0;
364         } else if (IS_ELF(hdr.eh)) {
365                 fmt = 1;
366         } else {
367                 printf("Invalid %s\n", "format");
368                 close(fd);
369                 return;
370         }
371         if (fmt == 0) {
372                 addr = hdr.ex.a_entry & 0xffffff;
373                 p = PTOV(addr);
374                 lseek(fd, PAGE_SIZE, SEEK_SET);
375                 size = hdr.ex.a_text;
376                 if (read(fd, p, hdr.ex.a_text) != size) {
377                         close(fd);
378                         return;
379                 }
380                 p += roundup2(hdr.ex.a_text, PAGE_SIZE);
381                 size = hdr.ex.a_data;
382                 if (read(fd, p, hdr.ex.a_data) != size) {
383                         close(fd);
384                         return;
385                 }
386                 p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE);
387                 bootinfo.bi_symtab = VTOP(p);
388                 memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms));
389                 p += sizeof(hdr.ex.a_syms);
390                 if (hdr.ex.a_syms) {
391                         size = hdr.ex.a_syms;
392                         if (read(fd, p, hdr.ex.a_syms) != size) {
393                                 close(fd);
394                                 return;
395                         }
396                         p += hdr.ex.a_syms;
397                         size = sizeof (int);
398                         if (read(fd, p, sizeof (int)) != size) {
399                                 close(fd);
400                                 return;
401                         }
402                         x = *(uint32_t *)p;
403                         p += sizeof(int);
404                         x -= sizeof(int);
405                         size = x;
406                         if (read(fd, p, x) != size) {
407                                 close(fd);
408                                 return;
409                         }
410                         p += x;
411                 }
412         } else {
413                 lseek(fd, hdr.eh.e_phoff, SEEK_SET);
414                 for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) {
415                         size = sizeof (ep[0]);
416                         if (read(fd, ep + j, sizeof (ep[0])) != size) {
417                                 close(fd);
418                                 return;
419                         }
420                         if (ep[j].p_type == PT_LOAD)
421                                 j++;
422                 }
423                 for (i = 0; i < 2; i++) {
424                         p = PTOV(ep[i].p_paddr & 0xffffff);
425                         lseek(fd, ep[i].p_offset, SEEK_SET);
426                         size = ep[i].p_filesz;
427                         if (read(fd, p, ep[i].p_filesz) != size) {
428                                 close(fd);
429                                 return;
430                         }
431                 }
432                 p += roundup2(ep[1].p_memsz, PAGE_SIZE);
433                 bootinfo.bi_symtab = VTOP(p);
434                 if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) {
435                         lseek(fd, hdr.eh.e_shoff +
436                             sizeof (es[0]) * (hdr.eh.e_shstrndx + 1),
437                             SEEK_SET);
438                         size = sizeof(es);
439                         if (read(fd, &es, sizeof (es)) != size) {
440                                 close(fd);
441                                 return;
442                         }
443                         for (i = 0; i < 2; i++) {
444                                 memcpy(p, &es[i].sh_size,
445                                     sizeof(es[i].sh_size));
446                                 p += sizeof(es[i].sh_size);
447                                 lseek(fd, es[i].sh_offset, SEEK_SET);
448                                 size = es[i].sh_size;
449                                 if (read(fd, p, es[i].sh_size) != size) {
450                                         close(fd);
451                                         return;
452                                 }
453                                 p += es[i].sh_size;
454                         }
455                 }
456                 addr = hdr.eh.e_entry & 0xffffff;
457         }
458         close(fd);
459
460         bootinfo.bi_esymtab = VTOP(p);
461         bootinfo.bi_kernelname = VTOP(kname);
462 #ifdef LOADER_GELI_SUPPORT
463         explicit_bzero(gelipw, sizeof(gelipw));
464 #endif
465
466         if (bdev->dd.d_dev->dv_type == DEVT_ZFS) {
467                 zfsargs.size = sizeof(zfsargs);
468                 zfsargs.pool = bdev->zfs.pool_guid;
469                 zfsargs.root = bdev->zfs.root_guid;
470 #ifdef LOADER_GELI_SUPPORT
471                 export_geli_boot_data(&zfsargs.gelidata);
472 #endif
473                 /*
474                  * Note that the zfsargs struct is passed by value, not by
475                  * pointer. Code in btxldr.S copies the values from the entry
476                  * stack to a fixed location within loader(8) at startup due
477                  * to the presence of KARGS_FLAGS_EXTARG.
478                  */
479                 __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
480                     bootdev,
481                     KARGS_FLAGS_ZFS | KARGS_FLAGS_EXTARG,
482                     (uint32_t)bdev->zfs.pool_guid,
483                     (uint32_t)(bdev->zfs.pool_guid >> 32),
484                     VTOP(&bootinfo),
485                     zfsargs);
486         } else {
487 #ifdef LOADER_GELI_SUPPORT
488                 geliargs.size = sizeof(geliargs);
489                 export_geli_boot_data(&geliargs.gelidata);
490 #endif
491
492                 /*
493                  * Note that the geliargs struct is passed by value, not by
494                  * pointer. Code in btxldr.S copies the values from the entry
495                  * stack to a fixed location within loader(8) at startup due
496                  * to the presence of the KARGS_FLAGS_EXTARG flag.
497                  */
498                 __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
499                     bootdev,
500 #ifdef LOADER_GELI_SUPPORT
501                     KARGS_FLAGS_GELI | KARGS_FLAGS_EXTARG, 0, 0,
502                     VTOP(&bootinfo), geliargs
503 #else
504                     0, 0, 0, VTOP(&bootinfo)
505 #endif
506                     );
507         }
508 }
509
510 static int
511 mount_root(char *arg)
512 {
513         char *root;
514         struct i386_devdesc *ddesc;
515         uint8_t part;
516
517         if (asprintf(&root, "%s:", arg) < 0)
518                 return (1);
519
520         if (i386_getdev((void **)&ddesc, root, NULL)) {
521                 free(root);
522                 return (1);
523         }
524
525         /* we should have new device descriptor, free old and replace it. */
526         free(bdev);
527         bdev = ddesc;
528         if (bdev->dd.d_dev->dv_type == DEVT_DISK) {
529                 if (bdev->disk.d_partition == -1)
530                         part = 0xff;
531                 else
532                         part = bdev->disk.d_partition;
533                 bootdev = MAKEBOOTDEV(dev_maj[bdev->dd.d_dev->dv_type],
534                     bdev->disk.d_slice + 1, bdev->dd.d_unit, part);
535                 bootinfo.bi_bios_dev = bd_unit2bios(bdev);
536         }
537         strncpy(boot_devname, root, sizeof (boot_devname));
538         setenv("currdev", root, 1);
539         free(root);
540         return (0);
541 }
542
543 static void
544 fs_list(char *arg)
545 {
546         int fd;
547         struct dirent *d;
548         char line[80];
549
550         fd = open(arg, O_RDONLY);
551         if (fd < 0)
552                 return;
553         pager_open();
554         while ((d = readdirfd(fd)) != NULL) {
555                 sprintf(line, "%s\n", d->d_name);
556                 if (pager_output(line))
557                         break;
558         }
559         pager_close();
560         close(fd);
561 }
562
563 static int
564 parse_cmd(void)
565 {
566         char *arg = cmd;
567         char *ep, *p, *q;
568         const char *cp;
569         char line[80];
570         int c, i, j;
571
572         while ((c = *arg++)) {
573                 if (c == ' ' || c == '\t' || c == '\n')
574                         continue;
575                 for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++)
576                         ;
577                 ep = p;
578                 if (*p)
579                         *p++ = 0;
580                 if (c == '-') {
581                         while ((c = *arg++)) {
582                                 if (c == 'P') {
583                                         if (*(uint8_t *)PTOV(0x496) & 0x10) {
584                                                 cp = "yes";
585                                         } else {
586                                                 opts |= OPT_SET(RBX_DUAL);
587                                                 opts |= OPT_SET(RBX_SERIAL);
588                                                 cp = "no";
589                                         }
590                                         printf("Keyboard: %s\n", cp);
591                                         continue;
592                                 } else if (c == 'S') {
593                                         j = 0;
594                                         while ((unsigned int)
595                                             (i = *arg++ - '0') <= 9)
596                                                 j = j * 10 + i;
597                                         if (j > 0 && i == -'0') {
598                                                 comspeed = j;
599                                                 break;
600                                         }
601                                         /*
602                                          * Fall through to error below
603                                          * ('S' not in optstr[]).
604                                          */
605                                 }
606                                 for (i = 0; c != optstr[i]; i++)
607                                         if (i == NOPT - 1)
608                                                 return (-1);
609                                 opts ^= OPT_SET(flags[i]);
610                         }
611                         ioctrl = OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) :
612                             OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD;
613                         if (ioctrl & IO_SERIAL) {
614                                 if (sio_init(115200 / comspeed) != 0)
615                                         ioctrl &= ~IO_SERIAL;
616                         }
617                 } if (c == '?') {
618                         printf("\n");
619                         if (*arg == '\0')
620                                 arg = (char *)"/";
621                         fs_list(arg);
622                         zfs_list(arg);
623                         return (-1);
624                 } else {
625                         char *ptr;
626                         printf("\n");
627                         arg--;
628
629                         /*
630                          * Report pool status if the comment is 'status'. Lets
631                          * hope no-one wants to load /status as a kernel.
632                          */
633                         if (strcmp(arg, "status") == 0) {
634                                 pager_open();
635                                 for (i = 0; devsw[i] != NULL; i++) {
636                                         if (devsw[i]->dv_print != NULL) {
637                                                 if (devsw[i]->dv_print(1))
638                                                         break;
639                                         } else {
640                                                 snprintf(line, sizeof(line),
641                                                     "%s: (unknown)\n",
642                                                     devsw[i]->dv_name);
643                                                 if (pager_output(line))
644                                                         break;
645                                         }
646                                 }
647                                 pager_close();
648                                 return (-1);
649                         }
650
651                         /*
652                          * If there is "zfs:" prefix simply ignore it.
653                          */
654                         ptr = arg;
655                         if (strncmp(ptr, "zfs:", 4) == 0)
656                                 ptr += 4;
657
658                         /*
659                          * If there is a colon, switch pools.
660                          */
661                         q = strchr(ptr, ':');
662                         if (q) {
663                                 *q++ = '\0';
664                                 if (mount_root(arg) != 0) {
665                                         return (-1);
666                                 }
667                                 arg = q;
668                         }
669                         if ((i = ep - arg)) {
670                                 if ((size_t)i >= sizeof(kname))
671                                         return (-1);
672                                 memcpy(kname, arg, i + 1);
673                         }
674                 }
675                 arg = p;
676         }
677         return (0);
678 }
679
680 /*
681  * Probe all disks to discover ZFS pools. The idea is to walk all possible
682  * disk devices, however, we also need to identify possible boot pool.
683  * For boot pool detection we have boot disk passed us from BIOS, recorded
684  * in bootinfo.bi_bios_dev.
685  */
686 static void
687 i386_zfs_probe(void)
688 {
689         char devname[32];
690         int boot_unit;
691         struct i386_devdesc dev;
692         uint64_t pool_guid = 0;
693
694         dev.dd.d_dev = &bioshd;
695         /* Translate bios dev to our unit number. */
696         boot_unit = bd_bios2unit(bootinfo.bi_bios_dev);
697
698         /*
699          * Open all the disks we can find and see if we can reconstruct
700          * ZFS pools from them.
701          */
702         for (dev.dd.d_unit = 0; bd_unit2bios(&dev) >= 0; dev.dd.d_unit++) {
703                 snprintf(devname, sizeof (devname), "%s%d:", bioshd.dv_name,
704                     dev.dd.d_unit);
705                 /* If this is not boot disk, use generic probe. */
706                 if (dev.dd.d_unit != boot_unit)
707                         zfs_probe_dev(devname, NULL, true);
708                 else
709                         zfs_probe_dev(devname, &pool_guid, true);
710
711                 if (pool_guid != 0 && bdev == NULL) {
712                         bdev = malloc(sizeof (struct i386_devdesc));
713                         bzero(bdev, sizeof (struct i386_devdesc));
714                         bdev->zfs.dd.d_dev = &zfs_dev;
715                         bdev->zfs.pool_guid = pool_guid;
716                 }
717         }
718 }