summaryrefslogtreecommitdiffstats
path: root/stand/i386/loader
diff options
context:
space:
mode:
Diffstat (limited to 'stand/i386/loader')
-rw-r--r--stand/i386/loader/Makefile89
-rw-r--r--stand/i386/loader/Makefile.depend21
-rw-r--r--stand/i386/loader/chain.c134
-rw-r--r--stand/i386/loader/conf.c159
-rw-r--r--stand/i386/loader/help.i38654
-rw-r--r--stand/i386/loader/loader.rc18
-rw-r--r--stand/i386/loader/main.c477
-rw-r--r--stand/i386/loader/version14
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.
OpenPOWER on IntegriCloud