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