2 * Copyright (c) 1998 Robert Nordier
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
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
16 #include <sys/cdefs.h>
17 __FBSDID("$FreeBSD$");
21 #include <sys/param.h>
22 #include <sys/errno.h>
23 #include <sys/diskmbr.h>
27 #include <sys/reboot.h>
28 #include <sys/queue.h>
29 #include <sys/zfs_bootenv.h>
31 #include <machine/bootinfo.h>
32 #include <machine/elf.h>
33 #include <machine/pc/bios.h>
39 #include "bootstrap.h"
57 #define BIOS_NUMDRIVES 0x475
63 #define TYPE_MAXHARD TYPE_DA
68 static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */
69 static const unsigned char flags[NOPT] = {
88 * Paths to try loading before falling back to the boot2 prompt.
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.
94 * If no loader is found, try to load a kernel directly instead.
96 static const struct string {
100 { PATH_LOADER_ZFS, sizeof(PATH_LOADER_ZFS) },
101 { PATH_LOADER, sizeof(PATH_LOADER) },
102 { PATH_KERNEL, sizeof(PATH_KERNEL) },
105 static const unsigned char dev_maj[NDEV] = {30, 4, 2};
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;
119 extern vm_offset_t high_heap_base;
120 extern uint32_t bios_basemem, bios_extmem, high_heap_size;
122 static char *heap_top;
123 static char *heap_bottom;
126 static void i386_zfs_probe(void);
127 static void load(void);
128 static int parse_cmd(void);
130 #ifdef LOADER_GELI_SUPPORT
131 #include "geliboot.h"
132 static char gelipw[GELI_PW_MAXLEN];
135 struct arch_switch archsw; /* MI/MD interface boundary */
136 static char boot_devname[2 * ZFS_MAXNAMELEN + 8]; /* disk or pool:dataset */
138 struct devsw *devsw[] = {
140 #if defined(LOADER_ZFS_SUPPORT)
146 struct fs_ops *file_system[] = {
147 #if defined(LOADER_ZFS_SUPPORT)
150 #if defined(LOADER_UFS_SUPPORT)
166 int auto_boot, fd, nextboot = 0;
167 struct disk_devdesc devdesc;
171 if (high_heap_size > 0) {
172 heap_top = PTOV(high_heap_base + high_heap_size);
173 heap_bottom = PTOV(high_heap_base);
175 heap_bottom = (char *)
176 (roundup2(__base + (int32_t)&_end, 0x10000) - __base);
177 heap_top = (char *)PTOV(bios_basemem);
179 setheap(heap_bottom, heap_top);
182 * Initialise the block cache. Set the upper limit.
184 bcache_init(32768, 512);
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;
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);
202 /* Set up fall back device name. */
203 snprintf(boot_devname, sizeof (boot_devname), "disk%d:",
204 bd_bios2unit(bootinfo.bi_bios_dev));
206 for (i = 0; devsw[i] != NULL; i++)
207 if (devsw[i]->dv_init != NULL)
208 (devsw[i]->dv_init)();
210 disk_parsedev(&devdesc, boot_devname + 4, NULL);
212 bootdev = MAKEBOOTDEV(dev_maj[DEVT_DISK], devdesc.d_slice + 1,
214 devdesc.d_partition >= 0 ? devdesc.d_partition : 0xff);
217 * zfs_fmtdev() can be called only after dv_init
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,
227 memcpy(cmddup, cmd, sizeof(cmd));
229 if (!OPT_CHECK(RBX_QUIET))
230 printf("failed to parse bootonce "
234 if (!OPT_CHECK(RBX_QUIET))
235 printf("zfs bootonce: %s\n", cmddup);
237 if (zfs_get_bootenv(bdev, &benv) == 0) {
238 nvlist_add_string(benv, OS_BOOTONCE_USED,
240 zfs_set_bootenv(bdev, benv);
242 /* Do not process this command twice */
247 /* now make sure we have bdev on all cases */
249 i386_getdev((void **)&bdev, boot_devname, NULL);
251 env_setenv("currdev", EV_VOLATILE, boot_devname, i386_setcurrdev,
254 /* Process configuration file */
257 fd = open(PATH_CONFIG, O_RDONLY);
259 fd = open(PATH_DOTCONFIG, O_RDONLY);
264 if ((cmdlen = read(fd, cmd, sizeof(cmd))) > 0)
273 * Note that parse_cmd() is destructive to cmd[] and we also
274 * want to honor RBX_QUIET option that could be present in
277 memcpy(cmddup, cmd, sizeof(cmd));
280 if (!OPT_CHECK(RBX_QUIET))
281 printf("%s: %s\n", PATH_CONFIG, cmddup);
282 /* Do not process this command twice */
286 /* Do not risk waiting at the prompt forever. */
287 if (nextboot && !auto_boot)
290 if (auto_boot && !*kname) {
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.
296 for (i = 0; i < nitems(loadpath); i++) {
297 memcpy(kname, loadpath[i].p, loadpath[i].len);
304 /* Present the user with the boot2 prompt. */
307 if (!auto_boot || !OPT_CHECK(RBX_QUIET)) {
308 printf("\nFreeBSD/x86 boot\n");
309 printf("Default: %s%s\nboot: ", boot_devname, kname);
311 if (ioctrl & IO_SERIAL)
313 if (!auto_boot || keyhit(5))
314 getstr(cmd, sizeof(cmd));
315 else if (!auto_boot || !OPT_CHECK(RBX_QUIET))
325 /* XXX - Needed for btxld to link the boot2 binary; do not remove. */
339 static Elf32_Phdr ep[2];
340 static Elf32_Shdr es[2];
346 if ((fd = open(kname, O_RDONLY)) == -1) {
347 printf("\nCan't find %s\n", kname);
352 if (read(fd, &hdr, sizeof (hdr)) != size) {
356 if (N_GETMAGIC(hdr.ex) == ZMAGIC) {
358 } else if (IS_ELF(hdr.eh)) {
361 printf("Invalid %s\n", "format");
366 addr = hdr.ex.a_entry & 0xffffff;
368 lseek(fd, PAGE_SIZE, SEEK_SET);
369 size = hdr.ex.a_text;
370 if (read(fd, p, hdr.ex.a_text) != size) {
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) {
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);
385 size = hdr.ex.a_syms;
386 if (read(fd, p, hdr.ex.a_syms) != size) {
392 if (read(fd, p, sizeof (int)) != size) {
400 if (read(fd, p, x) != size) {
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) {
414 if (ep[j].p_type == PT_LOAD)
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) {
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),
433 if (read(fd, &es, sizeof (es)) != size) {
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) {
450 addr = hdr.eh.e_entry & 0xffffff;
454 bootinfo.bi_esymtab = VTOP(p);
455 bootinfo.bi_kernelname = VTOP(kname);
456 #ifdef LOADER_GELI_SUPPORT
457 explicit_bzero(gelipw, sizeof(gelipw));
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);
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.
473 __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
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),
481 #ifdef LOADER_GELI_SUPPORT
482 geliargs.size = sizeof(geliargs);
483 export_geli_boot_data(&geliargs.gelidata);
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.
492 __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
494 #ifdef LOADER_GELI_SUPPORT
495 KARGS_FLAGS_GELI | KARGS_FLAGS_EXTARG, 0, 0,
496 VTOP(&bootinfo), geliargs
498 0, 0, 0, VTOP(&bootinfo)
505 mount_root(char *arg)
508 struct i386_devdesc *ddesc;
511 if (asprintf(&root, "%s:", arg) < 0)
514 if (i386_getdev((void **)&ddesc, root, NULL)) {
519 /* we should have new device descriptor, free old and replace it. */
522 if (bdev->dd.d_dev->dv_type == DEVT_DISK) {
523 if (bdev->d_kind.biosdisk.partition == -1)
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);
532 strncpy(boot_devname, root, sizeof (boot_devname));
533 setenv("currdev", root, 1);
545 fd = open(arg, O_RDONLY);
549 while ((d = readdirfd(fd)) != NULL) {
550 sprintf(line, "%s\n", d->d_name);
551 if (pager_output(line))
567 while ((c = *arg++)) {
568 if (c == ' ' || c == '\t' || c == '\n')
570 for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++)
576 while ((c = *arg++)) {
578 if (*(uint8_t *)PTOV(0x496) & 0x10) {
581 opts |= OPT_SET(RBX_DUAL);
582 opts |= OPT_SET(RBX_SERIAL);
585 printf("Keyboard: %s\n", cp);
587 } else if (c == 'S') {
589 while ((unsigned int)
590 (i = *arg++ - '0') <= 9)
592 if (j > 0 && i == -'0') {
597 * Fall through to error below
598 * ('S' not in optstr[]).
601 for (i = 0; c != optstr[i]; i++)
604 opts ^= OPT_SET(flags[i]);
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;
625 * Report pool status if the comment is 'status'. Lets
626 * hope no-one wants to load /status as a kernel.
628 if (strcmp(arg, "status") == 0) {
630 for (i = 0; devsw[i] != NULL; i++) {
631 if (devsw[i]->dv_print != NULL) {
632 if (devsw[i]->dv_print(1))
635 snprintf(line, sizeof(line),
638 if (pager_output(line))
647 * If there is "zfs:" prefix simply ignore it.
650 if (strncmp(ptr, "zfs:", 4) == 0)
654 * If there is a colon, switch pools.
656 q = strchr(ptr, ':');
659 if (mount_root(arg) != 0) {
664 if ((i = ep - arg)) {
665 if ((size_t)i >= sizeof(kname))
667 memcpy(kname, arg, i + 1);
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.
686 struct i386_devdesc dev;
687 uint64_t pool_guid = 0;
689 dev.dd.d_dev = &bioshd;
690 /* Translate bios dev to our unit number. */
691 boot_unit = bd_bios2unit(bootinfo.bi_bios_dev);
694 * Open all the disks we can find and see if we can reconstruct
695 * ZFS pools from them.
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,
700 /* If this is not boot disk, use generic probe. */
701 if (dev.dd.d_unit != boot_unit)
702 zfs_probe_dev(devname, NULL);
704 zfs_probe_dev(devname, &pool_guid);
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;