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>
19 #include <sys/param.h>
20 #include <sys/errno.h>
21 #include <sys/diskmbr.h>
24 #include <sys/reboot.h>
25 #include <sys/queue.h>
26 #include <sys/multiboot.h>
28 #include <machine/bootinfo.h>
29 #include <machine/elf.h>
30 #include <machine/pc/bios.h>
36 #include "bootstrap.h"
54 #define BIOS_NUMDRIVES 0x475
60 #define TYPE_MAXHARD TYPE_DA
66 * Fake multiboot header to provide versioning and to pass
67 * partition start LBA. Partition is either GPT partition or
70 extern const struct multiboot_header mb_header
;
71 extern uint64_t start_sector
;
73 static const char optstr
[NOPT
] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */
74 static const unsigned char flags
[NOPT
] = {
92 static const unsigned char dev_maj
[NDEV
] = {30, 4, 2};
94 static struct i386_devdesc
*bdev
;
96 static char cmddup
[512];
97 static char kname
[1024];
98 static int comspeed
= SIOSPD
;
99 static struct bootinfo bootinfo
;
100 static uint32_t bootdev
;
101 static struct zfs_boot_args zfsargs
;
103 extern vm_offset_t high_heap_base
;
104 extern uint32_t bios_basemem
, bios_extmem
, high_heap_size
;
106 static char *heap_top
;
107 static char *heap_bottom
;
109 static void i386_zfs_probe(void);
111 static void load(void);
112 static int parse_cmd(void);
114 struct arch_switch archsw
; /* MI/MD interface boundary */
115 static char boot_devname
[2 * ZFS_MAXNAMELEN
+ 8]; /* disk or pool:dataset */
117 struct devsw
*devsw
[] = {
123 struct fs_ops
*file_system
[] = {
133 int auto_boot
, i
, fd
;
134 struct disk_devdesc devdesc
;
138 if (high_heap_size
> 0) {
139 heap_top
= PTOV(high_heap_base
+ high_heap_size
);
140 heap_bottom
= PTOV(high_heap_base
);
142 heap_bottom
= (char *)
143 (roundup2(__base
+ (int32_t)&_end
, 0x10000) - __base
);
144 heap_top
= (char *) PTOV(bios_basemem
);
146 setheap(heap_bottom
, heap_top
);
149 * Initialise the block cache. Set the upper limit.
151 bcache_init(32768, 512);
153 archsw
.arch_autoload
= NULL
;
154 archsw
.arch_getdev
= i386_getdev
;
155 archsw
.arch_copyin
= NULL
;
156 archsw
.arch_copyout
= NULL
;
157 archsw
.arch_readin
= NULL
;
158 archsw
.arch_isainb
= NULL
;
159 archsw
.arch_isaoutb
= NULL
;
160 archsw
.arch_zfs_probe
= i386_zfs_probe
;
162 bootinfo
.bi_version
= BOOTINFO_VERSION
;
163 bootinfo
.bi_size
= sizeof(bootinfo
);
164 bootinfo
.bi_basemem
= bios_basemem
/ 1024;
165 bootinfo
.bi_extmem
= bios_extmem
/ 1024;
166 bootinfo
.bi_memsizes_valid
++;
167 bootinfo
.bi_bios_dev
= *(uint8_t *)PTOV(ARGS
);
169 /* Set up fall back device name. */
170 snprintf(boot_devname
, sizeof (boot_devname
), "disk%d:",
171 bd_bios2unit(bootinfo
.bi_bios_dev
));
173 for (i
= 0; devsw
[i
] != NULL
; i
++)
174 if (devsw
[i
]->dv_init
!= NULL
)
175 (devsw
[i
]->dv_init
)();
177 disk_parsedev(&devdesc
, boot_devname
+4, NULL
);
179 bootdev
= MAKEBOOTDEV(dev_maj
[DEVT_DISK
], devdesc
.d_slice
+ 1,
180 devdesc
.dd
.d_unit
, devdesc
.d_partition
>= 0? devdesc
.d_partition
:0xff);
183 * zfs_fmtdev() can be called only after dv_init
185 if (bdev
!= NULL
&& bdev
->dd
.d_dev
->dv_type
== DEVT_ZFS
) {
186 /* set up proper device name string for ZFS */
187 strncpy(boot_devname
, zfs_fmtdev(bdev
), sizeof (boot_devname
));
190 /* now make sure we have bdev on all cases */
193 i386_getdev((void **)&bdev
, boot_devname
, NULL
);
195 env_setenv("currdev", EV_VOLATILE
, boot_devname
, i386_setcurrdev
,
198 /* Process configuration file */
199 setenv("LINES", "24", 1);
202 fd
= open(PATH_CONFIG
, O_RDONLY
);
204 fd
= open(PATH_DOTCONFIG
, O_RDONLY
);
207 read(fd
, cmd
, sizeof(cmd
));
213 * Note that parse_cmd() is destructive to cmd[] and we also want
214 * to honor RBX_QUIET option that could be present in cmd[].
216 memcpy(cmddup
, cmd
, sizeof(cmd
));
219 if (!OPT_CHECK(RBX_QUIET
))
220 printf("%s: %s\n", PATH_CONFIG
, cmddup
);
221 /* Do not process this command twice */
226 * Try to exec stage 3 boot loader. If interrupted by a keypress,
227 * or in case of failure, switch off auto boot.
230 if (auto_boot
&& !*kname
) {
231 memcpy(kname
, PATH_LOADER
, sizeof(PATH_LOADER
));
236 * Try to fall back to /boot/zfsloader.
237 * This fallback should be eventually removed.
238 * Created: 08/03/2018
240 #define PATH_ZFSLOADER "/boot/zfsloader"
241 memcpy(kname
, PATH_ZFSLOADER
, sizeof(PATH_ZFSLOADER
));
244 * Still there? restore default loader name for prompt.
246 memcpy(kname
, PATH_LOADER
, sizeof(PATH_LOADER
));
250 /* Present the user with the boot2 prompt. */
253 if (!auto_boot
|| !OPT_CHECK(RBX_QUIET
)) {
254 printf("\nillumos/x86 boot\n");
255 printf("Default: %s%s\nboot: ", boot_devname
, kname
);
257 if (ioctrl
& IO_SERIAL
)
259 if (!auto_boot
|| keyhit(5))
260 getstr(cmd
, sizeof(cmd
));
261 else if (!auto_boot
|| !OPT_CHECK(RBX_QUIET
))
271 /* XXX - Needed for btxld to link the boot2 binary; do not remove. */
284 static Elf32_Phdr ep
[2];
285 static Elf32_Shdr es
[2];
290 if ((fd
= open(kname
, O_RDONLY
)) == -1) {
291 printf("\nCan't find %s\n", kname
);
294 if (read(fd
, &hdr
, sizeof(hdr
)) != sizeof(hdr
)) {
298 if (N_GETMAGIC(hdr
.ex
) == ZMAGIC
)
300 else if (IS_ELF(hdr
.eh
))
303 printf("Invalid %s\n", "format");
308 addr
= hdr
.ex
.a_entry
& 0xffffff;
310 lseek(fd
, PAGE_SIZE
, SEEK_SET
);
311 if (read(fd
, p
, hdr
.ex
.a_text
) != hdr
.ex
.a_text
) {
315 p
+= roundup2(hdr
.ex
.a_text
, PAGE_SIZE
);
316 if (read(fd
, p
, hdr
.ex
.a_data
) != hdr
.ex
.a_data
) {
320 p
+= hdr
.ex
.a_data
+ roundup2(hdr
.ex
.a_bss
, PAGE_SIZE
);
321 bootinfo
.bi_symtab
= VTOP(p
);
322 memcpy(p
, &hdr
.ex
.a_syms
, sizeof(hdr
.ex
.a_syms
));
323 p
+= sizeof(hdr
.ex
.a_syms
);
325 if (read(fd
, p
, hdr
.ex
.a_syms
) != hdr
.ex
.a_syms
) {
330 if (read(fd
, p
, sizeof(int)) != sizeof(int)) {
337 if (read(fd
, p
, x
) != x
) {
344 lseek(fd
, hdr
.eh
.e_phoff
, SEEK_SET
);
345 for (j
= i
= 0; i
< hdr
.eh
.e_phnum
&& j
< 2; i
++) {
346 if (read(fd
, ep
+ j
, sizeof(ep
[0])) != sizeof(ep
[0])) {
350 if (ep
[j
].p_type
== PT_LOAD
)
353 for (i
= 0; i
< 2; i
++) {
354 p
= PTOV(ep
[i
].p_paddr
& 0xffffff);
355 lseek(fd
, ep
[i
].p_offset
, SEEK_SET
);
356 if (read(fd
, p
, ep
[i
].p_filesz
) != ep
[i
].p_filesz
) {
361 p
+= roundup2(ep
[1].p_memsz
, PAGE_SIZE
);
362 bootinfo
.bi_symtab
= VTOP(p
);
363 if (hdr
.eh
.e_shnum
== hdr
.eh
.e_shstrndx
+ 3) {
364 lseek(fd
, hdr
.eh
.e_shoff
+ sizeof(es
[0]) * (hdr
.eh
.e_shstrndx
+ 1),
366 if (read(fd
, &es
, sizeof(es
)) != sizeof(es
)) {
370 for (i
= 0; i
< 2; i
++) {
371 memcpy(p
, &es
[i
].sh_size
, sizeof(es
[i
].sh_size
));
372 p
+= sizeof(es
[i
].sh_size
);
373 lseek(fd
, es
[i
].sh_offset
, SEEK_SET
);
374 if (read(fd
, p
, es
[i
].sh_size
) != es
[i
].sh_size
) {
381 addr
= hdr
.eh
.e_entry
& 0xffffff;
385 bootinfo
.bi_esymtab
= VTOP(p
);
386 bootinfo
.bi_kernelname
= VTOP(kname
);
388 if (bdev
->dd
.d_dev
->dv_type
== DEVT_ZFS
) {
389 zfsargs
.size
= sizeof(zfsargs
);
390 zfsargs
.pool
= bdev
->d_kind
.zfs
.pool_guid
;
391 zfsargs
.root
= bdev
->d_kind
.zfs
.root_guid
;
392 __exec((caddr_t
)addr
, RB_BOOTINFO
| (opts
& RBX_MASK
),
394 KARGS_FLAGS_ZFS
| KARGS_FLAGS_EXTARG
,
395 (uint32_t) bdev
->d_kind
.zfs
.pool_guid
,
396 (uint32_t) (bdev
->d_kind
.zfs
.pool_guid
>> 32),
400 __exec((caddr_t
)addr
, RB_BOOTINFO
| (opts
& RBX_MASK
),
401 bootdev
, 0, 0, 0, VTOP(&bootinfo
));
405 mount_root(char *arg
)
408 struct i386_devdesc
*ddesc
;
411 root
= malloc(strlen(arg
) + 2);
414 sprintf(root
, "%s:", arg
);
415 if (i386_getdev((void **)&ddesc
, root
, NULL
)) {
420 /* we should have new device descriptor, free old and replace it. */
424 if (bdev
->dd
.d_dev
->dv_type
== DEVT_DISK
) {
425 if (bdev
->d_kind
.biosdisk
.partition
== -1)
428 part
= bdev
->d_kind
.biosdisk
.partition
;
429 bootdev
= MAKEBOOTDEV(dev_maj
[bdev
->dd
.d_dev
->dv_type
],
430 bdev
->d_kind
.biosdisk
.slice
+ 1,
431 bdev
->dd
.d_unit
, part
);
432 bootinfo
.bi_bios_dev
= bd_unit2bios(bdev
->dd
.d_unit
);
434 setenv("currdev", root
, 1);
446 fd
= open(arg
, O_RDONLY
);
450 while ((d
= readdirfd(fd
)) != NULL
) {
451 sprintf(line
, "%s\n", d
->d_name
);
452 if (pager_output(line
))
468 while ((c
= *arg
++)) {
469 if (c
== ' ' || c
== '\t' || c
== '\n')
471 for (p
= arg
; *p
&& *p
!= '\n' && *p
!= ' ' && *p
!= '\t'; p
++);
476 while ((c
= *arg
++)) {
478 if (*(uint8_t *)PTOV(0x496) & 0x10) {
481 opts
|= OPT_SET(RBX_DUAL
) | OPT_SET(RBX_SERIAL
);
484 printf("Keyboard: %s\n", cp
);
486 } else if (c
== 'S') {
488 while ((unsigned int)(i
= *arg
++ - '0') <= 9)
490 if (j
> 0 && i
== -'0') {
494 /* Fall through to error below ('S' not in optstr[]). */
496 for (i
= 0; c
!= optstr
[i
]; i
++)
499 opts
^= OPT_SET(flags
[i
]);
501 ioctrl
= OPT_CHECK(RBX_DUAL
) ? (IO_SERIAL
|IO_KEYBOARD
) :
502 OPT_CHECK(RBX_SERIAL
) ? IO_SERIAL
: IO_KEYBOARD
;
503 if (ioctrl
& IO_SERIAL
) {
504 if (sio_init(115200 / comspeed
) != 0)
505 ioctrl
&= ~IO_SERIAL
;
516 * Report pool status if the comment is 'status'. Lets
517 * hope no-one wants to load /status as a kernel.
519 if (!strcmp(arg
, "status")) {
521 for (i
= 0; devsw
[i
] != NULL
; i
++) {
522 if (devsw
[i
]->dv_print
!= NULL
) {
523 if (devsw
[i
]->dv_print(1))
526 sprintf(line
, "%s: (unknown)\n", devsw
[i
]->dv_name
);
527 if (pager_output(line
))
536 * If there is a colon, switch pools.
538 if (strncmp(arg
, "zfs:", 4) == 0)
539 q
= strchr(arg
+ 4, ':');
541 q
= strchr(arg
, ':');
544 if (mount_root(arg
) != 0)
548 if ((i
= ep
- arg
)) {
549 if ((size_t)i
>= sizeof(kname
))
551 memcpy(kname
, arg
, i
+ 1);
560 * probe arguments for partition iterator (see below)
570 * simple wrapper around read() to avoid using device specific
571 * strategy() directly.
574 parttblread(void *arg
, void *buf
, size_t blocks
, uint64_t offset
)
576 struct probe_args
*ppa
= arg
;
577 size_t size
= ppa
->secsz
* blocks
;
579 lseek(ppa
->fd
, offset
* ppa
->secsz
, SEEK_SET
);
580 if (read(ppa
->fd
, buf
, size
) == size
)
586 * scan partition entries to find boot partition starting at start_sector.
587 * in case of MBR partition type PART_SOLARIS2, read VTOC and recurse.
590 probe_partition(void *arg
, const char *partname
,
591 const struct ptable_entry
*part
)
593 struct probe_args pa
, *ppa
= arg
;
594 struct ptable
*table
;
595 uint64_t *pool_guid_ptr
= NULL
;
596 uint64_t pool_guid
= 0;
600 len
= strlen(ppa
->devname
);
601 if (len
> sizeof (devname
))
602 len
= sizeof (devname
);
604 strncpy(devname
, ppa
->devname
, len
- 1);
605 devname
[len
- 1] = '\0';
606 snprintf(devname
, sizeof (devname
), "%s%s:", devname
, partname
);
608 /* filter out partitions *not* used by zfs */
609 switch (part
->type
) {
610 case PART_RESERVED
: /* efi reserverd */
611 case PART_VTOC_BOOT
: /* vtoc boot area */
618 if (part
->type
== PART_SOLARIS2
) {
619 pa
.offset
= part
->start
;
620 pa
.fd
= open(devname
, O_RDONLY
);
623 pa
.devname
= devname
;
624 pa
.secsz
= ppa
->secsz
;
625 table
= ptable_open(&pa
, part
->end
- part
->start
+ 1,
626 ppa
->secsz
, parttblread
);
628 enum ptable_type pt
= ptable_gettype(table
);
630 if (pt
== PTABLE_VTOC8
|| pt
== PTABLE_VTOC
) {
631 ret
= ptable_iterate(table
, &pa
,
642 if (ppa
->offset
+ part
->start
== start_sector
) {
643 /* Ask zfs_probe_dev to provide guid. */
644 pool_guid_ptr
= &pool_guid
;
645 /* Set up boot device name for non-zfs case. */
646 strncpy(boot_devname
, devname
, sizeof (boot_devname
));
649 ret
= zfs_probe_dev(devname
, pool_guid_ptr
);
650 if (pool_guid
!= 0 && bdev
== NULL
) {
651 bdev
= malloc(sizeof (struct i386_devdesc
));
652 bzero(bdev
, sizeof (struct i386_devdesc
));
653 bdev
->dd
.d_dev
= &zfs_dev
;
654 bdev
->d_kind
.zfs
.pool_guid
= pool_guid
;
657 * We can not set up zfs boot device name yet, as the
658 * zfs dv_init() is not completed. We will set boot_devname
659 * in main, after devsw setup.
667 * open partition table on disk and scan partition entries to find
668 * boot partition starting at start_sector (recorded by installboot).
671 probe_disk(char *devname
)
673 struct ptable
*table
;
674 struct probe_args pa
;
679 pa
.devname
= devname
;
680 pa
.fd
= open(devname
, O_RDONLY
);
685 ret
= ioctl(pa
.fd
, DIOCGMEDIASIZE
, &mediasz
);
687 ret
= ioctl(pa
.fd
, DIOCGSECTORSIZE
, &pa
.secsz
);
689 table
= ptable_open(&pa
, mediasz
/ pa
.secsz
, pa
.secsz
,
692 ret
= ptable_iterate(table
, &pa
, probe_partition
);
701 * Probe all disks to discover ZFS pools. The idea is to walk all possible
702 * disk devices, however, we also need to identify possible boot pool.
703 * For boot pool detection we have boot disk passed us from BIOS, recorded
704 * in bootinfo.bi_bios_dev, and start_sector LBA recorded by installboot.
706 * To detect boot pool, we can not use generic zfs_probe_dev() on boot disk,
707 * but we need to walk partitions, as we have no way to pass start_sector
708 * to zfs_probe_dev(). Note we do need to detect the partition correcponding
709 * to non-zfs case, so here we can set boot_devname for both cases.
717 /* Translate bios dev to our unit number. */
718 boot_unit
= bd_bios2unit(bootinfo
.bi_bios_dev
);
721 * Open all the disks we can find and see if we can reconstruct
722 * ZFS pools from them.
724 for (unit
= 0; unit
< MAXBDDEV
; unit
++) {
725 if (bd_unit2bios(unit
) == -1)
727 if (bd_unit2bios(unit
) < 0x80)
730 sprintf(devname
, "disk%d:", unit
);
731 /* If this is not boot disk, use generic probe. */
732 if (unit
!= boot_unit
)
733 zfs_probe_dev(devname
, NULL
);
740 ldi_get_size(void *priv
)
742 int fd
= (uintptr_t) priv
;
745 ioctl(fd
, DIOCGMEDIASIZE
, &size
);