diff options
Diffstat (limited to 'stand/i386/loader')
-rw-r--r-- | stand/i386/loader/Makefile | 89 | ||||
-rw-r--r-- | stand/i386/loader/Makefile.depend | 21 | ||||
-rw-r--r-- | stand/i386/loader/chain.c | 134 | ||||
-rw-r--r-- | stand/i386/loader/conf.c | 159 | ||||
-rw-r--r-- | stand/i386/loader/help.i386 | 54 | ||||
-rw-r--r-- | stand/i386/loader/loader.rc | 18 | ||||
-rw-r--r-- | stand/i386/loader/main.c | 477 | ||||
-rw-r--r-- | stand/i386/loader/version | 14 |
8 files changed, 966 insertions, 0 deletions
diff --git a/stand/i386/loader/Makefile b/stand/i386/loader/Makefile new file mode 100644 index 0000000..40ac46c --- /dev/null +++ b/stand/i386/loader/Makefile @@ -0,0 +1,89 @@ +# $FreeBSD$ + +HAVE_GELI= yes + +LOADER_NET_SUPPORT?= yes +LOADER_NFS_SUPPORT?= yes +LOADER_TFTP_SUPPORT?= yes +LOADER_CD9660_SUPPORT?= no +LOADER_EXT2FS_SUPPORT?= no +LOADER_MSDOS_SUPPORT?= no +LOADER_UFS_SUPPORT?= yes +LOADER_GZIP_SUPPORT?= yes +LOADER_BZIP2_SUPPORT?= yes + +.include <bsd.init.mk> + +MK_SSP= no + +LOADER?= loader +PROG= ${LOADER}.sym +MAN= +INTERNALPROG= +NEWVERSWHAT?= "bootstrap loader" x86 +VERSION_FILE= ${.CURDIR}/../loader/version + +.PATH: ${BOOTSRC}/i386/loader + +# architecture-specific loader code +SRCS= main.c conf.c vers.c chain.c + +# Include bcache code. +HAVE_BCACHE= yes + +# Enable PnP and ISA-PnP code. +HAVE_PNP= yes +HAVE_ISABUS= yes + +.if ${MK_LOADER_FIREWIRE} == "yes" +CFLAGS+= -DLOADER_FIREWIRE_SUPPORT +LIBFIREWIRE= ${BOOTOBJ}/i386/libfirewire/libfirewire.a +.endif + +.if exists(${.CURDIR}/help.i386) +HELP_FILES+= help.i386 +.else +HELP_FILES= +.endif + +# Always add MI sources +.include "${BOOTSRC}/loader.mk" + +CLEANFILES+= ${LOADER} ${LOADER}.bin + +CFLAGS+= -Wall +LDFLAGS+= -static -Ttext 0x0 + +# i386 standalone support library +LIBI386= ${BOOTOBJ}/i386/libi386/libi386.a +CFLAGS+= -I${BOOTSRC}/i386 + +# BTX components +CFLAGS+= -I${BTXLIB} + +# Debug me! +#CFLAGS+= -g +#LDFLAGS+= -g + +${LOADER}: ${LOADER}.bin ${BTXLDR} ${BTXKERN} + btxld -v -f aout -e ${LOADER_ADDRESS} -o ${.TARGET} -l ${BTXLDR} \ + -b ${BTXKERN} ${LOADER}.bin + +${LOADER}.bin: ${LOADER}.sym + strip -R .comment -R .note -o ${.TARGET} ${.ALLSRC} + +FILES+= ${LOADER} +# XXX INSTALLFLAGS_loader= -b +FILESMODE_${LOADER}= ${BINMODE} -b + +# XXX crt0.o needs to be first for pxeboot(8) to work +OBJS= ${BTXCRT} + +DPADD= ${LIBFICL32} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBGELIBOOT} ${LIBSA32} +LDADD= ${LIBFICL32} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBGELIBOOT} ${LIBSA32} + +.if ${MACHINE_CPUARCH} == "amd64" +CFLAGS+= -DLOADER_PREFER_AMD64 +.endif + +.include <bsd.prog.mk> diff --git a/stand/i386/loader/Makefile.depend b/stand/i386/loader/Makefile.depend new file mode 100644 index 0000000..89d5422 --- /dev/null +++ b/stand/i386/loader/Makefile.depend @@ -0,0 +1,21 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + include \ + include/xlocale \ + lib/libstand \ + sys/boot/ficl32 \ + sys/boot/geli \ + sys/boot/i386/btx/btx \ + sys/boot/i386/btx/btxldr \ + sys/boot/i386/btx/lib \ + sys/boot/i386/libi386 \ + sys/boot/libstand32 \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/stand/i386/loader/chain.c b/stand/i386/loader/chain.c new file mode 100644 index 0000000..d6810ef --- /dev/null +++ b/stand/i386/loader/chain.c @@ -0,0 +1,134 @@ +/*- + * Copyright 2015 Toomas Soome <tsoome@me.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Chain loader to load BIOS boot block either from MBR or PBR. + * + * Note the boot block location 0000:7c000 conflicts with loader, so we need to + * read in to temporary space and relocate on exec, when btx is stopped. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stand.h> +#include <sys/param.h> +#include <sys/linker.h> +#include <sys/diskmbr.h> + +#include "bootstrap.h" +#include "libi386/libi386.h" +#include "btxv86.h" + +/* + * The MBR/VBR is located in first sector of disk/partition. + * Read 512B to temporary location and set up relocation. Then + * exec relocator. + */ +#define SECTOR_SIZE (512) + +COMMAND_SET(chain, "chain", "chain load boot block from device", command_chain); + +static int +command_chain(int argc, char *argv[]) +{ + int fd, len, size = SECTOR_SIZE; + struct stat st; + vm_offset_t mem = 0x100000; + struct i386_devdesc *rootdev; + + if (argc == 1) { + command_errmsg = "no device or file name specified"; + return (CMD_ERROR); + } + if (argc != 2) { + command_errmsg = "invalid trailing arguments"; + return (CMD_ERROR); + } + + fd = open(argv[1], O_RDONLY); + if (fd == -1) { + command_errmsg = "open failed"; + return (CMD_ERROR); + } + + len = strlen(argv[1]); + if (argv[1][len-1] != ':') { + if (fstat(fd, &st) == -1) { + command_errmsg = "stat failed"; + close(fd); + return (CMD_ERROR); + } + size = st.st_size; + } else if (strncmp(argv[1], "disk", 4) != 0) { + command_errmsg = "can only use disk device"; + close(fd); + return (CMD_ERROR); + } + + i386_getdev((void **)(&rootdev), argv[1], NULL); + if (rootdev == NULL) { + command_errmsg = "can't determine root device"; + return (CMD_ERROR); + } + + if (archsw.arch_readin(fd, mem, SECTOR_SIZE) != SECTOR_SIZE) { + command_errmsg = "failed to read disk"; + close(fd); + return (CMD_ERROR); + } + close(fd); + + if (*((uint16_t *)PTOV(mem + DOSMAGICOFFSET)) != DOSMAGIC) { + command_errmsg = "wrong magic"; + return (CMD_ERROR); + } + + relocater_data[0].src = mem; + relocater_data[0].dest = 0x7C00; + relocater_data[0].size = SECTOR_SIZE; + + relocator_edx = bd_unit2bios(rootdev->d_unit); + relocator_esi = relocater_size; + relocator_ds = 0; + relocator_es = 0; + relocator_fs = 0; + relocator_gs = 0; + relocator_ss = 0; + relocator_cs = 0; + relocator_sp = 0x7C00; + relocator_ip = 0x7C00; + relocator_a20_enabled = 0; + + i386_copyin(relocater, 0x600, relocater_size); + + dev_cleanup(); + + __exec((void *)0x600); + + panic("exec returned"); + return (CMD_ERROR); /* not reached */ +} diff --git a/stand/i386/loader/conf.c b/stand/i386/loader/conf.c new file mode 100644 index 0000000..29ce1e3 --- /dev/null +++ b/stand/i386/loader/conf.c @@ -0,0 +1,159 @@ +/*- + * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stand.h> +#include <bootstrap.h> +#include "libi386/libi386.h" +#if defined(LOADER_ZFS_SUPPORT) +#include "../zfs/libzfs.h" +#endif + +/* + * We could use linker sets for some or all of these, but + * then we would have to control what ended up linked into + * the bootstrap. So it's easier to conditionalise things + * here. + * + * XXX rename these arrays to be consistent and less namespace-hostile + * + * XXX as libi386 and biosboot merge, some of these can become linker sets. + */ + +#if defined(LOADER_FIREWIRE_SUPPORT) +extern struct devsw fwohci; +#endif + +/* Exported for libstand */ +struct devsw *devsw[] = { + &bioscd, + &biosdisk, +#if defined(LOADER_NFS_SUPPORT) || defined(LOADER_TFTP_SUPPORT) + &pxedisk, +#endif +#if defined(LOADER_FIREWIRE_SUPPORT) + &fwohci, +#endif +#if defined(LOADER_ZFS_SUPPORT) + &zfs_dev, +#endif + NULL +}; + +struct fs_ops *file_system[] = { +#if defined(LOADER_ZFS_SUPPORT) + &zfs_fsops, +#endif + &ufs_fsops, + &ext2fs_fsops, + &dosfs_fsops, + &cd9660_fsops, +#if defined(LOADER_NANDFS_SUPPORT) + &nandfs_fsops, +#endif +#ifdef LOADER_NFS_SUPPORT + &nfs_fsops, +#endif +#ifdef LOADER_TFTP_SUPPORT + &tftp_fsops, +#endif +#ifdef LOADER_GZIP_SUPPORT + &gzipfs_fsops, +#endif +#ifdef LOADER_BZIP2_SUPPORT + &bzipfs_fsops, +#endif +#ifdef LOADER_SPLIT_SUPPORT + &splitfs_fsops, +#endif + NULL +}; + +/* Exported for i386 only */ +/* + * Sort formats so that those that can detect based on arguments + * rather than reading the file go first. + */ +extern struct file_format i386_elf; +extern struct file_format i386_elf_obj; +extern struct file_format amd64_elf; +extern struct file_format amd64_elf_obj; +extern struct file_format multiboot; +extern struct file_format multiboot_obj; + +struct file_format *file_formats[] = { + &multiboot, + &multiboot_obj, +#ifdef LOADER_PREFER_AMD64 + &amd64_elf, + &amd64_elf_obj, +#endif + &i386_elf, + &i386_elf_obj, +#ifndef LOADER_PREFER_AMD64 + &amd64_elf, + &amd64_elf_obj, +#endif + NULL +}; + +/* + * Consoles + * + * We don't prototype these in libi386.h because they require + * data structures from bootstrap.h as well. + */ +extern struct console vidconsole; +extern struct console comconsole; +#if defined(LOADER_FIREWIRE_SUPPORT) +extern struct console dconsole; +#endif +extern struct console nullconsole; +extern struct console spinconsole; + +struct console *consoles[] = { + &vidconsole, + &comconsole, +#if defined(LOADER_FIREWIRE_SUPPORT) + &dconsole, +#endif + &nullconsole, + &spinconsole, + NULL +}; + +extern struct pnphandler isapnphandler; +extern struct pnphandler biospnphandler; +extern struct pnphandler biospcihandler; + +struct pnphandler *pnphandlers[] = { + &biospnphandler, /* should go first, as it may set isapnp_readport */ + &isapnphandler, + &biospcihandler, + NULL +}; diff --git a/stand/i386/loader/help.i386 b/stand/i386/loader/help.i386 new file mode 100644 index 0000000..0ff6286 --- /dev/null +++ b/stand/i386/loader/help.i386 @@ -0,0 +1,54 @@ +################################################################################ +# Treboot DReboot the system + + reboot + + Causes the system to immediately reboot. + +################################################################################ +# Theap DDisplay memory management statistics + + heap + + Requests debugging output from the heap manager. For debugging use + only. + +################################################################################ +# Tset Snum_ide_disks DSet the number of IDE disks + + NOTE: this variable is deprecated, use root_disk_unit instead. + + set num_ide_disks=<value> + + When booting from a SCSI disk on a system with one or more IDE disks, + and where the IDE disks are the default boot device, it is necessary + to tell the kernel how many IDE disks there are in order to have it + correctly locate the SCSI disk you are booting from. + +################################################################################ +# Tset Sroot_disk_unit DForce the root disk unit number. + + set root_disk_unit=<value> + + If the code which detects the disk unit number for the root disk is + confused, eg. by a mix of SCSI and IDE disks, or IDE disks with + gaps in the sequence (eg. no primary slave), the unit number can be + forced by setting this variable. + +################################################################################ +# Tsmap DDisplay BIOS SMAP table + + smap + + Displays the BIOS SMAP (system memory map) table. + +################################################################################ +# Tchain DChain load disk block + + chain disk: + + chain will read stage1 (MBR or VBR) boot block from specified device + to address 0000:7C00 and attempts to run it. Use lsdev to get available + device names. Disk name must end with colon. + +################################################################################ diff --git a/stand/i386/loader/loader.rc b/stand/i386/loader/loader.rc new file mode 100644 index 0000000..287c05e --- /dev/null +++ b/stand/i386/loader/loader.rc @@ -0,0 +1,18 @@ +\ Loader.rc +\ $FreeBSD$ +\ +\ Includes additional commands +include /boot/loader.4th +try-include /boot/loader.rc.local + +\ Reads and processes loader.conf variables +initialize + +\ Tests for password -- executes autoboot first if a password was defined +check-password + +\ Load in the boot menu +include /boot/beastie.4th + +\ Start the boot menu +beastie-start diff --git a/stand/i386/loader/main.c b/stand/i386/loader/main.c new file mode 100644 index 0000000..81bc2ff --- /dev/null +++ b/stand/i386/loader/main.c @@ -0,0 +1,477 @@ +/*- + * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * MD bootstrap main() and assorted miscellaneous + * commands. + */ + +#include <stand.h> +#include <stddef.h> +#include <string.h> +#include <machine/bootinfo.h> +#include <machine/cpufunc.h> +#include <machine/psl.h> +#include <sys/disk.h> +#include <sys/reboot.h> +#include <common/drv.h> + +#include "bootstrap.h" +#include "common/bootargs.h" +#include "libi386/libi386.h" +#include "libi386/smbios.h" +#include "btxv86.h" + +#ifdef LOADER_ZFS_SUPPORT +#include "../zfs/libzfs.h" +#endif + +CTASSERT(sizeof(struct bootargs) == BOOTARGS_SIZE); +CTASSERT(offsetof(struct bootargs, bootinfo) == BA_BOOTINFO); +CTASSERT(offsetof(struct bootargs, bootflags) == BA_BOOTFLAGS); +CTASSERT(offsetof(struct bootinfo, bi_size) == BI_SIZE); + +/* Arguments passed in from the boot1/boot2 loader */ +static struct bootargs *kargs; + +static u_int32_t initial_howto; +static u_int32_t initial_bootdev; +static struct bootinfo *initial_bootinfo; + +struct arch_switch archsw; /* MI/MD interface boundary */ + +static void extract_currdev(void); +static int isa_inb(int port); +static void isa_outb(int port, int value); +void exit(int code); +#ifdef LOADER_GELI_SUPPORT +#include "geliboot.h" +struct geli_boot_args *gargs; +#endif +#ifdef LOADER_ZFS_SUPPORT +struct zfs_boot_args *zargs; +static void i386_zfs_probe(void); +#endif + +/* from vers.c */ +extern char bootprog_info[]; + +/* XXX debugging */ +extern char end[]; + +static void *heap_top; +static void *heap_bottom; + +int +main(void) +{ + int i; + + /* Pick up arguments */ + kargs = (void *)__args; + initial_howto = kargs->howto; + initial_bootdev = kargs->bootdev; + initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL; + + /* Initialize the v86 register set to a known-good state. */ + bzero(&v86, sizeof(v86)); + v86.efl = PSL_RESERVED_DEFAULT | PSL_I; + + /* + * Initialise the heap as early as possible. Once this is done, malloc() is usable. + */ + bios_getmem(); + +#if defined(LOADER_BZIP2_SUPPORT) || defined(LOADER_FIREWIRE_SUPPORT) || \ + defined(LOADER_GPT_SUPPORT) || defined(LOADER_ZFS_SUPPORT) + if (high_heap_size > 0) { + heap_top = PTOV(high_heap_base + high_heap_size); + heap_bottom = PTOV(high_heap_base); + if (high_heap_base < memtop_copyin) + memtop_copyin = high_heap_base; + } else +#endif + { + heap_top = (void *)PTOV(bios_basemem); + heap_bottom = (void *)end; + } + setheap(heap_bottom, heap_top); + + /* + * XXX Chicken-and-egg problem; we want to have console output early, but some + * console attributes may depend on reading from eg. the boot device, which we + * can't do yet. + * + * We can use printf() etc. once this is done. + * If the previous boot stage has requested a serial console, prefer that. + */ + bi_setboothowto(initial_howto); + if (initial_howto & RB_MULTIPLE) { + if (initial_howto & RB_SERIAL) + setenv("console", "comconsole vidconsole", 1); + else + setenv("console", "vidconsole comconsole", 1); + } else if (initial_howto & RB_SERIAL) + setenv("console", "comconsole", 1); + else if (initial_howto & RB_MUTE) + setenv("console", "nullconsole", 1); + cons_probe(); + + /* + * Initialise the block cache. Set the upper limit. + */ + bcache_init(32768, 512); + + /* + * Special handling for PXE and CD booting. + */ + if (kargs->bootinfo == 0) { + /* + * We only want the PXE disk to try to init itself in the below + * walk through devsw if we actually booted off of PXE. + */ + if (kargs->bootflags & KARGS_FLAGS_PXE) + pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL); + else if (kargs->bootflags & KARGS_FLAGS_CD) + bc_add(initial_bootdev); + } + + archsw.arch_autoload = i386_autoload; + archsw.arch_getdev = i386_getdev; + archsw.arch_copyin = i386_copyin; + archsw.arch_copyout = i386_copyout; + archsw.arch_readin = i386_readin; + archsw.arch_isainb = isa_inb; + archsw.arch_isaoutb = isa_outb; +#ifdef LOADER_ZFS_SUPPORT + archsw.arch_zfs_probe = i386_zfs_probe; + +#ifdef LOADER_GELI_SUPPORT + if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) { + zargs = (struct zfs_boot_args *)(kargs + 1); + if (zargs != NULL && zargs->size >= offsetof(struct zfs_boot_args, gelipw)) { + if (zargs->size >= offsetof(struct zfs_boot_args, keybuf_sentinel) && + zargs->keybuf_sentinel == KEYBUF_SENTINEL) { + geli_save_keybuf(zargs->keybuf); + } + if (zargs->gelipw[0] != '\0') { + setenv("kern.geom.eli.passphrase", zargs->gelipw, 1); + explicit_bzero(zargs->gelipw, sizeof(zargs->gelipw)); + } + } + } +#endif /* LOADER_GELI_SUPPORT */ +#else /* !LOADER_ZFS_SUPPORT */ +#ifdef LOADER_GELI_SUPPORT + if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) { + gargs = (struct geli_boot_args *)(kargs + 1); + if (gargs != NULL && gargs->size >= offsetof(struct geli_boot_args, gelipw)) { + if (gargs->keybuf_sentinel == KEYBUF_SENTINEL) { + geli_save_keybuf(gargs->keybuf); + } + if (gargs->gelipw[0] != '\0') { + setenv("kern.geom.eli.passphrase", gargs->gelipw, 1); + explicit_bzero(gargs->gelipw, sizeof(gargs->gelipw)); + } + } + } +#endif /* LOADER_GELI_SUPPORT */ +#endif /* LOADER_ZFS_SUPPORT */ + + /* + * March through the device switch probing for things. + */ + for (i = 0; devsw[i] != NULL; i++) + if (devsw[i]->dv_init != NULL) + (devsw[i]->dv_init)(); + printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024); + if (initial_bootinfo != NULL) { + initial_bootinfo->bi_basemem = bios_basemem / 1024; + initial_bootinfo->bi_extmem = bios_extmem / 1024; + } + + /* detect ACPI for future reference */ + biosacpi_detect(); + + /* detect SMBIOS for future reference */ + smbios_detect(NULL); + + /* detect PCI BIOS for future reference */ + biospci_detect(); + + printf("\n%s", bootprog_info); + + extract_currdev(); /* set $currdev and $loaddev */ + setenv("LINES", "24", 1); /* optional */ + + bios_getsmap(); + + interact(NULL); + + /* if we ever get here, it is an error */ + return (1); +} + +/* + * Set the 'current device' by (if possible) recovering the boot device as + * supplied by the initial bootstrap. + * + * XXX should be extended for netbooting. + */ +static void +extract_currdev(void) +{ + struct i386_devdesc new_currdev; +#ifdef LOADER_ZFS_SUPPORT + char buf[20]; +#endif + int biosdev = -1; + + /* Assume we are booting from a BIOS disk by default */ + new_currdev.d_dev = &biosdisk; + + /* new-style boot loaders such as pxeldr and cdldr */ + if (kargs->bootinfo == 0) { + if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) { + /* we are booting from a CD with cdboot */ + new_currdev.d_dev = &bioscd; + new_currdev.d_unit = bc_bios2unit(initial_bootdev); + } else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) { + /* we are booting from pxeldr */ + new_currdev.d_dev = &pxedisk; + new_currdev.d_unit = 0; + } else { + /* we don't know what our boot device is */ + new_currdev.d_kind.biosdisk.slice = -1; + new_currdev.d_kind.biosdisk.partition = 0; + biosdev = -1; + } +#ifdef LOADER_ZFS_SUPPORT + } else if ((kargs->bootflags & KARGS_FLAGS_ZFS) != 0) { + zargs = NULL; + /* check for new style extended argument */ + if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) + zargs = (struct zfs_boot_args *)(kargs + 1); + + if (zargs != NULL && + zargs->size >= offsetof(struct zfs_boot_args, primary_pool)) { + /* sufficient data is provided */ + new_currdev.d_kind.zfs.pool_guid = zargs->pool; + new_currdev.d_kind.zfs.root_guid = zargs->root; + if (zargs->size >= sizeof(*zargs) && zargs->primary_vdev != 0) { + sprintf(buf, "%llu", zargs->primary_pool); + setenv("vfs.zfs.boot.primary_pool", buf, 1); + sprintf(buf, "%llu", zargs->primary_vdev); + setenv("vfs.zfs.boot.primary_vdev", buf, 1); + } + } else { + /* old style zfsboot block */ + new_currdev.d_kind.zfs.pool_guid = kargs->zfspool; + new_currdev.d_kind.zfs.root_guid = 0; + } + new_currdev.d_dev = &zfs_dev; +#endif + } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) { + /* The passed-in boot device is bad */ + new_currdev.d_kind.biosdisk.slice = -1; + new_currdev.d_kind.biosdisk.partition = 0; + biosdev = -1; + } else { + new_currdev.d_kind.biosdisk.slice = B_SLICE(initial_bootdev) - 1; + new_currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev); + biosdev = initial_bootinfo->bi_bios_dev; + + /* + * If we are booted by an old bootstrap, we have to guess at the BIOS + * unit number. We will lose if there is more than one disk type + * and we are not booting from the lowest-numbered disk type + * (ie. SCSI when IDE also exists). + */ + if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) /* biosdev doesn't match major */ + biosdev = 0x80 + B_UNIT(initial_bootdev); /* assume harddisk */ + } + new_currdev.d_type = new_currdev.d_dev->dv_type; + + /* + * If we are booting off of a BIOS disk and we didn't succeed in determining + * which one we booted off of, just use disk0: as a reasonable default. + */ + if ((new_currdev.d_type == biosdisk.dv_type) && + ((new_currdev.d_unit = bd_bios2unit(biosdev)) == -1)) { + printf("Can't work out which disk we are booting from.\n" + "Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev); + new_currdev.d_unit = 0; + } + +#ifdef LOADER_ZFS_SUPPORT + if (new_currdev.d_type == DEVT_ZFS) + init_zfs_bootenv(zfs_fmtdev(&new_currdev)); +#endif + + env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev), + i386_setcurrdev, env_nounset); + env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset, + env_nounset); +} + +COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); + +static int +command_reboot(int argc, char *argv[]) +{ + int i; + + for (i = 0; devsw[i] != NULL; ++i) + if (devsw[i]->dv_cleanup != NULL) + (devsw[i]->dv_cleanup)(); + + printf("Rebooting...\n"); + delay(1000000); + __exit(0); +} + +/* provide this for panic, as it's not in the startup code */ +void +exit(int code) +{ + __exit(code); +} + +COMMAND_SET(heap, "heap", "show heap usage", command_heap); + +static int +command_heap(int argc, char *argv[]) +{ + mallocstats(); + printf("heap base at %p, top at %p, upper limit at %p\n", heap_bottom, + sbrk(0), heap_top); + return(CMD_OK); +} + +#ifdef LOADER_ZFS_SUPPORT +COMMAND_SET(lszfs, "lszfs", "list child datasets of a zfs dataset", + command_lszfs); + +static int +command_lszfs(int argc, char *argv[]) +{ + int err; + + if (argc != 2) { + command_errmsg = "wrong number of arguments"; + return (CMD_ERROR); + } + + err = zfs_list(argv[1]); + if (err != 0) { + command_errmsg = strerror(err); + return (CMD_ERROR); + } + + return (CMD_OK); +} + +COMMAND_SET(reloadbe, "reloadbe", "refresh the list of ZFS Boot Environments", + command_reloadbe); + +static int +command_reloadbe(int argc, char *argv[]) +{ + int err; + char *root; + + if (argc > 2) { + command_errmsg = "wrong number of arguments"; + return (CMD_ERROR); + } + + if (argc == 2) { + err = zfs_bootenv(argv[1]); + } else { + root = getenv("zfs_be_root"); + if (root == NULL) { + /* There does not appear to be a ZFS pool here, exit without error */ + return (CMD_OK); + } + err = zfs_bootenv(root); + } + + if (err != 0) { + command_errmsg = strerror(err); + return (CMD_ERROR); + } + + return (CMD_OK); +} +#endif + +/* ISA bus access functions for PnP. */ +static int +isa_inb(int port) +{ + + return (inb(port)); +} + +static void +isa_outb(int port, int value) +{ + + outb(port, value); +} + +#ifdef LOADER_ZFS_SUPPORT +static void +i386_zfs_probe(void) +{ + char devname[32]; + int unit; + + /* + * Open all the disks we can find and see if we can reconstruct + * ZFS pools from them. + */ + for (unit = 0; unit < MAXBDDEV; unit++) { + if (bd_unit2bios(unit) == -1) + break; + sprintf(devname, "disk%d:", unit); + zfs_probe_dev(devname, NULL); + } +} + +uint64_t +ldi_get_size(void *priv) +{ + int fd = (uintptr_t) priv; + uint64_t size; + + ioctl(fd, DIOCGMEDIASIZE, &size); + return (size); +} +#endif diff --git a/stand/i386/loader/version b/stand/i386/loader/version new file mode 100644 index 0000000..7a2acaf --- /dev/null +++ b/stand/i386/loader/version @@ -0,0 +1,14 @@ +$FreeBSD$ + +NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this +file is important. Make sure the current version number is on line 6. + +1.1: New calling conventions for fopen. +1.0: New semantics for finding the kernel, new boot. +0.8: Set/getenv & cia, copyin/out. +0.7: Supports large KVM +0.6: Increased dictionary size -- supports loader.4th +0.5: First release version +0.2: Initial integration with BTX +0.1: Initial i386 version, inspiration and some structure from the + NetBSD version. |