summaryrefslogtreecommitdiffstats
path: root/sys/boot/i386
diff options
context:
space:
mode:
authormsmith <msmith@FreeBSD.org>1998-08-21 03:17:42 +0000
committermsmith <msmith@FreeBSD.org>1998-08-21 03:17:42 +0000
commit8adeb775c43d4c2ae76cce40837a3953af6abc83 (patch)
treeec778e5f3903abe2dbb59959c0fd8398c99c145b /sys/boot/i386
parent335c4be5b17816baac6b70d4d0b3132925de858d (diff)
downloadFreeBSD-src-8adeb775c43d4c2ae76cce40837a3953af6abc83.zip
FreeBSD-src-8adeb775c43d4c2ae76cce40837a3953af6abc83.tar.gz
This is the new unified bootstrap, sometimes known previously as the
'three-stage' bootstrap. There are a number of caveats with the code in its current state: - The i386 bootstrap only supports booting from a floppy. - The kernel and kld do not yet know how to deal with the extended information and module summary passed in. - PnP-based autodetection and demand loading of modules is not implemented. - i386 ELF kernel loading is not ready yet. - The i386 bootstrap is loaded via an ugly blockmap. On the alpha, both net- and disk-booting (SRM console machines only) is supported. No blockmaps are used by this code. Obtained from: Parts from the NetBSD/i386 standalone bootstrap.
Diffstat (limited to 'sys/boot/i386')
-rw-r--r--sys/boot/i386/Makefile3
-rw-r--r--sys/boot/i386/installboot/Makefile16
-rw-r--r--sys/boot/i386/installboot/bootblks.c146
-rw-r--r--sys/boot/i386/installboot/getmount.c156
-rw-r--r--sys/boot/i386/installboot/installboot.8150
-rw-r--r--sys/boot/i386/installboot/installboot.c433
-rw-r--r--sys/boot/i386/installboot/installboot.h9
-rw-r--r--sys/boot/i386/libi386/Makefile21
-rw-r--r--sys/boot/i386/libi386/aout_freebsd.c274
-rw-r--r--sys/boot/i386/libi386/biosdelay.S79
-rw-r--r--sys/boot/i386/libi386/biosdisk.c408
-rw-r--r--sys/boot/i386/libi386/biosdisk_support.S114
-rw-r--r--sys/boot/i386/libi386/biosgetrtc.S77
-rw-r--r--sys/boot/i386/libi386/biosmem.S99
-rw-r--r--sys/boot/i386/libi386/biosreboot.S66
-rw-r--r--sys/boot/i386/libi386/bootinfo.c197
-rw-r--r--sys/boot/i386/libi386/comconsole.c78
-rw-r--r--sys/boot/i386/libi386/comconsole_support.S147
-rw-r--r--sys/boot/i386/libi386/crt/Makefile3
-rw-r--r--sys/boot/i386/libi386/crt/bios_disk.S176
-rw-r--r--sys/boot/i386/libi386/crt/biosdisk_ll.c148
-rw-r--r--sys/boot/i386/libi386/crt/biosdisk_ll.h54
-rw-r--r--sys/boot/i386/libi386/crt/bootsect/Makefile25
-rw-r--r--sys/boot/i386/libi386/crt/bootsect/bbinfo.h64
-rw-r--r--sys/boot/i386/libi386/crt/bootsect/bootsectmain.c88
-rw-r--r--sys/boot/i386/libi386/crt/bootsect/fraglist.S49
-rw-r--r--sys/boot/i386/libi386/crt/bootsect/start_bootsect.S540
-rw-r--r--sys/boot/i386/libi386/crt/buffers.S27
-rw-r--r--sys/boot/i386/libi386/crt/diskbuf.h42
-rw-r--r--sys/boot/i386/libi386/devicename.c234
-rw-r--r--sys/boot/i386/libi386/gatea20.c52
-rw-r--r--sys/boot/i386/libi386/getsecs.c40
-rw-r--r--sys/boot/i386/libi386/i386_module.c64
-rw-r--r--sys/boot/i386/libi386/libi386.h86
-rw-r--r--sys/boot/i386/libi386/pread.c79
-rw-r--r--sys/boot/i386/libi386/startprog.S120
-rw-r--r--sys/boot/i386/libi386/vidconsole.c199
-rw-r--r--sys/boot/i386/libi386/vidconsole_support.S103
-rw-r--r--sys/boot/i386/loader/Makefile36
-rw-r--r--sys/boot/i386/loader/conf.c85
-rw-r--r--sys/boot/i386/loader/main.c156
-rwxr-xr-xsys/boot/i386/loader/newvers.sh44
-rw-r--r--sys/boot/i386/loader/version7
43 files changed, 4994 insertions, 0 deletions
diff --git a/sys/boot/i386/Makefile b/sys/boot/i386/Makefile
new file mode 100644
index 0000000..72d5627
--- /dev/null
+++ b/sys/boot/i386/Makefile
@@ -0,0 +1,3 @@
+SUBDIR= installboot libi386 loader
+
+.include <bsd.subdir.mk>
diff --git a/sys/boot/i386/installboot/Makefile b/sys/boot/i386/installboot/Makefile
new file mode 100644
index 0000000..b989f07
--- /dev/null
+++ b/sys/boot/i386/installboot/Makefile
@@ -0,0 +1,16 @@
+# $NetBSD: Makefile,v 1.5 1998/03/02 19:57:01 cgd Exp $
+
+.include <bsd.own.mk>
+
+BINDIR= /usr/mdec
+PROG= installboot
+
+SRCS= installboot.c bootblks.c getmount.c
+
+NOMAN= yes
+
+CPPFLAGS= -I${.CURDIR}/../libi386/crt/bootsect
+CFLAGS+= -Wall ${CPPFLAGS}
+LDSTATIC?=-static
+
+.include <bsd.prog.mk>
diff --git a/sys/boot/i386/installboot/bootblks.c b/sys/boot/i386/installboot/bootblks.c
new file mode 100644
index 0000000..cb17b92
--- /dev/null
+++ b/sys/boot/i386/installboot/bootblks.c
@@ -0,0 +1,146 @@
+/* $NetBSD: bootblks.c,v 1.2 1997/07/21 18:04:35 drochner Exp $ */
+
+/*
+ * Copyright (c) 1996
+ * Matthias Drochner. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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/param.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <err.h>
+
+#include "installboot.h"
+
+static char bootblkpath[MAXPATHLEN];
+static char backuppath[MAXPATHLEN];
+static char backupext[] = ".bak";
+static int havebackup;
+
+ino_t
+createfileondev(diskdev, bootblkname, bp, size)
+ char *diskdev, *bootblkname;
+ char *bp;
+ int size;
+{
+ char *mntpoint;
+ int fd = -1;
+ struct stat statbuf;
+ int allok = 0;
+
+ if ((mntpoint = getmountpoint(diskdev)) == NULL)
+ return ((ino_t) - 1);
+
+ /*
+ * create file in fs root for bootloader data
+ * try to rename existing file before
+ */
+ havebackup = 0;
+ sprintf(bootblkpath, "%s/%s", mntpoint, bootblkname);
+ sprintf(backuppath, "%s%s", bootblkpath, backupext);
+ if(rename(bootblkpath, backuppath) == -1) {
+ if(errno != ENOENT) {
+ warn("rename old %s", bootblkpath);
+ goto out;
+ }
+ } else {
+ if(verbose)
+ fprintf(stderr, "renamed %s -> %s\n",
+ bootblkpath, backuppath);
+ havebackup = 1;
+ }
+ fd = open(bootblkpath, O_RDWR | O_CREAT | O_EXCL, 0444);
+ if (fd < 0) {
+ warn("open %s", bootblkpath);
+ goto out;
+ }
+ /*
+ * do the write, flush, get inode number
+ */
+ if (write(fd, bp, size) < 0) {
+ warn("write %s", bootblkpath);
+ goto out;
+ }
+ if (fsync(fd) != 0) {
+ warn("fsync: %s", bootblkpath);
+ goto out;
+ }
+ if (fstat(fd, &statbuf) != 0) {
+ warn("fstat: %s", bootblkpath);
+ goto out;
+ }
+ allok = 1;
+
+out:
+ if (fd != -1) {
+ close(fd);
+ if (!allok)
+ unlink(bootblkpath);
+ }
+ if(!allok && havebackup)
+ rename(backuppath, bootblkpath);
+ cleanupmount(mntpoint);
+ return (allok ? statbuf.st_ino : (ino_t) - 1);
+}
+
+void
+cleanupfileondev(diskdev, bootblkname, recover)
+ char *diskdev, *bootblkname;
+{
+ char *mntpoint;
+
+ /* save some work if nothing to do */
+ if(!(recover || havebackup))
+ return;
+
+ if ((mntpoint = getmountpoint(diskdev)) == NULL)
+ return;
+
+ sprintf(bootblkpath, "%s/%s", mntpoint, bootblkname);
+ sprintf(backuppath, "%s%s", bootblkpath, backupext);
+
+ if(recover) {
+ unlink(bootblkpath);
+ if(havebackup) {
+ fprintf(stderr, "renaming %s -> %s\n",
+ backuppath, bootblkpath);
+ rename(backuppath, bootblkpath);
+ }
+ } else if(havebackup) {
+ if(verbose)
+ fprintf(stderr, "deleting %s\n", backuppath);
+ unlink(backuppath);
+ }
+
+ cleanupmount(mntpoint);
+}
diff --git a/sys/boot/i386/installboot/getmount.c b/sys/boot/i386/installboot/getmount.c
new file mode 100644
index 0000000..6aa8427
--- /dev/null
+++ b/sys/boot/i386/installboot/getmount.c
@@ -0,0 +1,156 @@
+/* $NetBSD: getmount.c,v 1.3 1998/03/01 13:22:55 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1996
+ * Matthias Drochner. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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/param.h>
+#include <sys/mount.h>
+#include <ufs/ufs/ufsmount.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <err.h>
+
+#include "installboot.h"
+
+static int tempmounted = 0;
+
+/* make block device name from character device name */
+static char *
+getbdev(dev)
+ char *dev;
+{
+ static char bdiskdev[MAXPATHLEN];
+
+ if (strncmp(dev, "/dev/r", 6)) {
+ warnx("bad device name %s", dev);
+ return (0);
+ }
+ sprintf(bdiskdev, "/dev/%s", dev + 6);
+ return (bdiskdev);
+}
+
+/*
+ * create mountpoint and mount given block device there, return
+ * mountpoint
+ */
+static char *
+dotempmount(bdiskdev)
+ char *bdiskdev;
+{
+ static char dir[] = "/tmp/installbootXXXXXX";
+ struct ufs_args data;
+
+ if (mktemp(dir) == NULL) {
+ warnx("mktemp failed");
+ return (0);
+ }
+ if (mkdir(dir, 0700)) {
+ warn("could not create temporary dir %s", dir);
+ return (0);
+ }
+ bzero(&data, sizeof(data));
+ data.fspec = bdiskdev;
+
+ /* this code if FFS only */
+ if (mount("ufs", dir, 0, &data) == -1) {
+ warn("mount %s->%s failed", bdiskdev, dir);
+ rmdir(dir);
+ return (0);
+ }
+ if (verbose)
+ fprintf(stderr, "mounted %s at %s\n", bdiskdev, dir);
+ tempmounted = 1;
+ return (dir);
+}
+
+/*
+ * Find out if given character device is already mounted. If not, mount it
+ * temporarily.
+ */
+char *
+getmountpoint(diskdev)
+ char *diskdev;
+{
+ char *bdiskdev;
+ struct statfs *buf;
+ int num, i;
+
+ bdiskdev = getbdev(diskdev);
+ if (bdiskdev == NULL)
+ return (0);
+
+ num = getmntinfo(&buf, MNT_WAIT);
+ if (num == 0) {
+ warn("getmntinfo");
+ return (0);
+ }
+ for (i = 0; i < num; i++)
+ if (strncmp(bdiskdev, buf[i].f_mntfromname, MNAMELEN) == 0) {
+ int j;
+
+ /* Device is mounted. If there are more devices mounted
+ at the same point, the fs could be hidden. Don't think
+ too much about layering order - simply refuse. */
+ for (j = 0; j < num; j++)
+ if ((i != j) && (strncmp(buf[i].f_mntonname,
+ buf[j].f_mntonname,
+ MNAMELEN) == 0)) {
+ warnx("there is more than 1 mount at %s",
+ buf[i].f_mntonname);
+ return (0);
+ }
+ /* this code is FFS only */
+ if (strncmp(buf[i].f_fstypename, "ufs", MFSNAMELEN)) {
+ warnx("%s: must be a FFS filesystem", bdiskdev);
+ return (0);
+ }
+ return (buf[i].f_mntonname);
+ }
+ if (verbose)
+ fprintf(stderr, "%s is not mounted\n", bdiskdev);
+ return (dotempmount(bdiskdev));
+}
+
+void
+cleanupmount(dir)
+ char *dir;
+{
+ if (tempmounted) {
+ if (verbose)
+ fprintf(stderr, "unmounting\n");
+ unmount(dir, 0);
+ rmdir(dir);
+ tempmounted = 0;
+ }
+}
diff --git a/sys/boot/i386/installboot/installboot.8 b/sys/boot/i386/installboot/installboot.8
new file mode 100644
index 0000000..776f594
--- /dev/null
+++ b/sys/boot/i386/installboot/installboot.8
@@ -0,0 +1,150 @@
+.\" $NetBSD: installboot.8,v 1.1.1.1 1997/03/14 02:40:32 perry Exp $
+.\"
+.\" Copyright (c) 1997 Perry E. Metzger. All rights reserved.
+.\" Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
+.\" Copyright (c) 1995 Paul Kranenburg. 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.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Paul Kranenburg.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+.\"
+.Dd March 14, 1997
+.Dt INSTALLBOOT 8 i386
+.Os
+.Sh NAME
+.Nm installboot
+.Nd install disk bootstrap software
+.Sh SYNOPSIS
+.Nm installboot
+.Op Fl nvf
+.Ar bootfile
+.Ar rawdiskdevice
+.Sh DESCRIPTION
+The
+.Nm installboot
+utility prepares a disk for bootstrapping.
+.Pp
+The
+.Nx /i386
+disk bootstrap software is split into two parts:
+a small first-stage boot program that is written into the disklabel
+area of a disk and a second-stage boot program that resides in a FFS file
+system on the disk (named
+.Pa /boot ) .
+Both parts of the boot are derived from a single object file
+which is split by
+.Nm
+during the installation process.
+The first-stage boot program is loaded into memory by the BIOS.
+After receiving control of the system, it loads the
+second-stage boot program from a set of filesystem block numbers that
+have been hard-coded into it by
+.Nm
+during execution.
+The second-stage boot program then locates and loads the kernel.
+.Pp
+Note: so that the
+.Pa /boot
+file can be installed on the bootable partition, the partition must be
+mounted before
+.Nm
+is run.
+.Pp
+The options recognized by
+.Nm installboot
+are as follows:
+.Bl -tag -width flag
+.It Fl n
+Do not actually write anything on the disk.
+.It Fl v
+Verbose mode.
+.It Fl f
+Force a write of the boot blocks (with the first stage put at offset
+zero) even if no disk label is detected.
+This is useful if there is no disk label (as is often the case with
+floppy or vnode devices).
+.El
+.Pp
+The arguments are:
+.Bl -tag -width rawdiskdevice
+.It Ar bootfile
+The name of the special object file
+(typically
+.Pa /usr/mdec/biosboot.sym )
+where the first and second stage boot programs to be installed reside.
+.It Ar rawdiskdevice
+The name of the device corresponding to the raw whole-disk partition (the
+.Dq raw partition )
+of the disk on which the first-stage boot program is to be installed.
+.El
+.Sh EXAMPLES
+Assuming the file containing the boot program is in its typical place,
+and you wished to make
+.Pa /dev/fd0a
+bootable. One might first mount
+.Pa /dev/fd0a
+on
+.Pa /mnt ,
+and in the case that there is already a file named
+.Pa boot
+in that directory, remove it.
+To install the boot blocks, one then would issue the command:
+.Bd -literal -offset indent
+installboot -f /usr/mdec/biosboot.sym /dev/rfd0a
+.Ed
+Note that the -f option is needed if the floppy is unlabeled -- see
+.Xr disklabel 8 .
+.Sh BUGS
+The NetBSD/i386 boot blocks can only read from the first 1024
+cylinders of the disk because they use the BIOS to do their I/O. Thus,
+it is advisable that
+.Dq a
+partitions reside entirely within the first 1024 cylinders.
+.Pp
+.Nm
+requires simultaneous access to the mounted file system and
+the disks' raw partition.
+That is not allowed with the kernel
+.Dv securelevel
+variable
+.Po
+see
+.Xr sysctl 8
+.Pc
+set to a value greater than one, or with
+.Dv securelevel
+set to one if the
+.Dq boot
+program resides in a file system on the disk's raw partition.
+.Sh "SEE ALSO"
+.Xr boot 8 ,
+.Xr disklabel 8 ,
+.Xr init 8 ,
+.Xr sysctl 8 ,
+.Xr vnd 4
+.Sh HISTORY
+The NetBSD/i386
+.Nm
+command first appeared in
+.Nx 1.3 .
diff --git a/sys/boot/i386/installboot/installboot.c b/sys/boot/i386/installboot/installboot.c
new file mode 100644
index 0000000..a5bfd3b
--- /dev/null
+++ b/sys/boot/i386/installboot/installboot.c
@@ -0,0 +1,433 @@
+/* $NetBSD: installboot.c,v 1.5 1997/11/01 06:49:50 lukem Exp $ */
+
+/*
+ * Copyright (c) 1994 Paul Kranenburg
+ * All rights reserved.
+ * Copyright (c) 1996, 1997
+ * Matthias Drochner. All rights reserved.
+ * Copyright (c) 1996, 1997
+ * Perry E. Metzger. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Paul Kranenburg.
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * This product includes software developed for the NetBSD Project
+ * by Perry E. Metzger.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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/param.h>
+#include <sys/disklabel.h>
+/* #include <sys/dkio.h> */
+#include <ufs/ufs/dinode.h>
+#include <ufs/ufs/dir.h>
+#include <ufs/ffs/fs.h>
+#include <sys/errno.h>
+#include <err.h>
+#include <a.out.h>
+#include <fcntl.h>
+#include <nlist.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#include "installboot.h"
+
+#include "bbinfo.h"
+
+#define DEFBBLKNAME "boot"
+
+struct fraglist *fraglist;
+
+struct nlist nl[] = {
+#define X_fraglist 0
+ {{"_fraglist"}},
+ {{NULL}}
+};
+
+int verbose = 0;
+
+char *
+loadprotoblocks(fname, size)
+ char *fname;
+ long *size;
+{
+ int fd;
+ size_t tdsize; /* text+data size */
+ size_t bbsize; /* boot block size (block aligned) */
+ char *bp;
+ struct nlist *nlp;
+ struct exec eh;
+
+ fd = -1;
+ bp = NULL;
+
+ /* Locate block number array in proto file */
+ if (nlist(fname, nl) != 0) {
+ warnx("nlist: %s: symbols not found", fname);
+ return NULL;
+ }
+ /* Validate symbol types (global text!). */
+ for (nlp = nl; nlp->n_un.n_name; nlp++) {
+ if (nlp->n_type != (N_TEXT | N_EXT)) {
+ warnx("nlist: %s: wrong type", nlp->n_un.n_name);
+ return NULL;
+ }
+ }
+
+ if ((fd = open(fname, O_RDONLY)) < 0) {
+ warn("open: %s", fname);
+ return NULL;
+ }
+ if (read(fd, &eh, sizeof(eh)) != sizeof(eh)) {
+ warn("read: %s", fname);
+ goto bad;
+ }
+ if (N_GETMAGIC(eh) != OMAGIC) {
+ warn("bad magic: 0x%lx", eh.a_midmag);
+ goto bad;
+ }
+ /*
+ * We need only text and data.
+ */
+ tdsize = eh.a_text + eh.a_data;
+ bbsize = roundup(tdsize, DEV_BSIZE);
+
+ if ((bp = calloc(bbsize, 1)) == NULL) {
+ warnx("malloc: %s: no memory", fname);
+ goto bad;
+ }
+ /* read the rest of the file. */
+ if (read(fd, bp, tdsize) != tdsize) {
+ warn("read: %s", fname);
+ goto bad;
+ }
+ *size = bbsize; /* aligned to DEV_BSIZE */
+
+ fraglist = (struct fraglist *) (bp + nl[X_fraglist].n_value);
+
+ if (fraglist->magic != FRAGLISTMAGIC) {
+ warnx("invalid bootblock version");
+ goto bad;
+ }
+ if (verbose) {
+ fprintf(stderr, "%s: entry point %#lx\n", fname, eh.a_entry);
+ fprintf(stderr, "proto bootblock size %ld\n", *size);
+ fprintf(stderr, "room for %d filesystem blocks at %#lx\n",
+ fraglist->maxentries, nl[X_fraglist].n_value);
+ }
+ close(fd);
+ return bp;
+
+bad:
+ if (bp)
+ free(bp);
+ if (fd >= 0)
+ close(fd);
+ return NULL;
+}
+
+static int
+devread(fd, buf, blk, size, msg)
+ int fd;
+ void *buf;
+ daddr_t blk;
+ size_t size;
+ char *msg;
+{
+ if (lseek(fd, dbtob(blk), SEEK_SET) != dbtob(blk)) {
+ warn("%s: devread: lseek", msg);
+ return (1);
+ }
+ if (read(fd, buf, size) != size) {
+ warn("%s: devread: read", msg);
+ return (1);
+ }
+ return (0);
+}
+
+/* add file system blocks to fraglist */
+static int
+add_fsblk(fs, blk, blcnt)
+ struct fs *fs;
+ daddr_t blk;
+ int blcnt;
+{
+ int nblk;
+
+ /* convert to disk blocks */
+ blk = fsbtodb(fs, blk);
+ nblk = fs->fs_bsize / DEV_BSIZE;
+ if (nblk > blcnt)
+ nblk = blcnt;
+
+ if (verbose)
+ fprintf(stderr, "dblk: %d, num: %d\n", blk, nblk);
+
+ /* start new entry or append to previous? */
+ if (!fraglist->numentries ||
+ (fraglist->entries[fraglist->numentries - 1].offset
+ + fraglist->entries[fraglist->numentries - 1].num != blk)) {
+
+ /* need new entry */
+ if (fraglist->numentries > fraglist->maxentries - 1) {
+ errx(1, "not enough fragment space in bootcode\n");
+ return(-1);
+ }
+
+ fraglist->entries[fraglist->numentries].offset = blk;
+ fraglist->entries[fraglist->numentries++].num = 0;
+ }
+ fraglist->entries[fraglist->numentries - 1].num += nblk;
+
+ return (blcnt - nblk);
+}
+
+static char sblock[SBSIZE];
+
+int
+loadblocknums(diskdev, inode)
+ char *diskdev;
+ ino_t inode;
+{
+ int devfd = -1;
+ struct fs *fs;
+ char *buf = 0;
+ daddr_t blk, *ap;
+ struct dinode *ip;
+ int i, ndb;
+ int allok = 0;
+
+ devfd = open(diskdev, O_RDONLY, 0);
+ if (devfd < 0) {
+ warn("open raw partition");
+ return (1);
+ }
+ /* Read superblock */
+ if (devread(devfd, sblock, SBLOCK, SBSIZE, "superblock"))
+ goto out;
+ fs = (struct fs *) sblock;
+
+ if (fs->fs_magic != FS_MAGIC) {
+ warnx("invalid super block");
+ goto out;
+ }
+ /* Read inode */
+ if ((buf = malloc(fs->fs_bsize)) == NULL) {
+ warnx("No memory for filesystem block");
+ goto out;
+ }
+ blk = fsbtodb(fs, ino_to_fsba(fs, inode));
+ if (devread(devfd, buf, blk, fs->fs_bsize, "inode"))
+ goto out;
+ ip = (struct dinode *) (buf) + ino_to_fsbo(fs, inode);
+
+ /*
+ * Have the inode. Figure out how many blocks we need.
+ */
+ ndb = ip->di_size / DEV_BSIZE; /* size is rounded! */
+
+ if (verbose)
+ fprintf(stderr, "Will load %d blocks.\n", ndb);
+
+ /*
+ * Get the block numbers, first direct blocks
+ */
+ ap = ip->di_db;
+ for (i = 0; i < NDADDR && *ap && ndb > 0; i++, ap++)
+ ndb = add_fsblk(fs, *ap, ndb);
+
+ if (ndb > 0) {
+ /*
+ * Just one level of indirections; there isn't much room
+ * for more in the 1st-level bootblocks anyway.
+ */
+ blk = fsbtodb(fs, ip->di_ib[0]);
+ if (devread(devfd, buf, blk, fs->fs_bsize, "indirect block"))
+ goto out;
+ ap = (daddr_t *) buf;
+ for (; i < NINDIR(fs) && *ap && ndb > 0; i++, ap++) {
+ ndb = add_fsblk(fs, *ap, ndb);
+ }
+ }
+
+ if (!ndb)
+ allok = 1;
+ else {
+ if (ndb > 0)
+ warnx("too many fs blocks");
+ /* else, ie ndb < 0, add_fsblk returned error */
+ goto out;
+ }
+
+out:
+ if (buf)
+ free(buf);
+ if (devfd >= 0)
+ close(devfd);
+ return (!allok);
+}
+
+static void
+usage()
+{
+ fprintf(stderr,
+ "usage: installboot [-n] [-v] [-f] <boot> <device>\n");
+ exit(1);
+}
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char c, *bp = 0;
+ long size;
+ ino_t inode = (ino_t) -1;
+ int devfd = -1;
+ struct disklabel dl;
+ int bsdoffs;
+ int i, res;
+ int forceifnolabel = 0;
+ char *bootblkname = DEFBBLKNAME;
+ int nowrite = 0;
+ int allok = 0;
+
+ while ((c = getopt(argc, argv, "vnf")) != -1) {
+ switch (c) {
+ case 'n':
+ /* Do not actually write the bootblock to disk */
+ nowrite = 1;
+ break;
+ case 'v':
+ /* Chat */
+ verbose = 1;
+ break;
+ case 'f':
+ /* assume zero offset if no disklabel */
+ forceifnolabel = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (argc - optind != 2) {
+ usage();
+ }
+
+ bp = loadprotoblocks(argv[optind], &size);
+ if (!bp)
+ errx(1, "error reading bootblocks");
+
+ fraglist->numentries = 0;
+
+ /* do we need the fraglist? */
+ if (size > fraglist->loadsz * DEV_BSIZE) {
+
+ inode = createfileondev(argv[optind + 1], bootblkname,
+ bp + fraglist->loadsz * DEV_BSIZE,
+ size - fraglist->loadsz * DEV_BSIZE);
+ if (inode == (ino_t) - 1)
+ goto out;
+
+ /* paranoia */
+ sync();
+ sleep(3);
+
+ if (loadblocknums(argv[optind + 1], inode))
+ goto out;
+
+ size = fraglist->loadsz * DEV_BSIZE;
+ /* size to be written to bootsect */
+ }
+
+ devfd = open(argv[optind + 1], O_RDWR, 0);
+ if (devfd < 0) {
+ warn("open raw partition RW");
+ goto out;
+ }
+ if (ioctl(devfd, DIOCGDINFO, &dl) < 0) {
+ if ((errno == EINVAL) || (errno == ENOTTY)) {
+ if (forceifnolabel)
+ bsdoffs = 0;
+ else {
+ warnx("no disklabel, use -f to install anyway");
+ goto out;
+ }
+ } else {
+ warn("get disklabel");
+ goto out;
+ }
+ } else {
+ char c = argv[optind + 1][strlen(argv[optind + 1]) - 1];
+#define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
+ if(!isvalidpart(c) || (c - 'a') >= dl.d_npartitions) {
+ warnx("invalid partition");
+ goto out;
+ }
+ bsdoffs = dl.d_partitions[c - 'a'].p_offset;
+ }
+ if (verbose)
+ fprintf(stderr, "BSD partition starts at sector %d\n", bsdoffs);
+
+ /*
+ * add offset of BSD partition to fraglist entries
+ */
+ for (i = 0; i < fraglist->numentries; i++)
+ fraglist->entries[i].offset += bsdoffs;
+
+ if (!nowrite) {
+ /*
+ * write first blocks (max loadsz) to start of BSD partition,
+ * skip disklabel (in second disk block)
+ */
+ lseek(devfd, 0, SEEK_SET);
+ res = write(devfd, bp, DEV_BSIZE);
+ if (res < 0) {
+ warn("final write1");
+ goto out;
+ }
+ lseek(devfd, 2 * DEV_BSIZE, SEEK_SET);
+ res = write(devfd, bp + 2 * DEV_BSIZE, size - 2 * DEV_BSIZE);
+ if (res < 0) {
+ warn("final write2");
+ goto out;
+ }
+ }
+ allok = 1;
+
+out:
+ if (devfd >= 0)
+ close(devfd);
+ if (bp)
+ free(bp);
+ if (inode != (ino_t) - 1) {
+ cleanupfileondev(argv[optind + 1], bootblkname, !allok || nowrite);
+ }
+ return (!allok);
+}
diff --git a/sys/boot/i386/installboot/installboot.h b/sys/boot/i386/installboot/installboot.h
new file mode 100644
index 0000000..83d2275
--- /dev/null
+++ b/sys/boot/i386/installboot/installboot.h
@@ -0,0 +1,9 @@
+/* $NetBSD: installboot.h,v 1.3 1998/01/05 07:02:57 perry Exp $ */
+
+ino_t createfileondev __P((char *, char *, char *, int));
+void cleanupfileondev __P((char *, char *, int));
+
+char *getmountpoint __P((char *));
+void cleanupmount __P((char *));
+
+extern int verbose;
diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile
new file mode 100644
index 0000000..5a0f88f
--- /dev/null
+++ b/sys/boot/i386/libi386/Makefile
@@ -0,0 +1,21 @@
+# $Id$
+#
+SUBDIR= crt
+LIB= i386
+NOPIC=
+NOPROFILE=
+
+SRCS= aout_freebsd.c biosdelay.S biosdisk.c biosdisk_support.S biosgetrtc.S \
+ biosmem.S biosreboot.S bootinfo.c comconsole.c comconsole_support.S \
+ devicename.c gatea20.c getsecs.c i386_module.c pread.c startprog.S \
+ vidconsole.c vidconsole_support.S
+
+CFLAGS+= -I${.CURDIR}/../../common
+
+# Make the disk code more talkative
+#CFLAGS+= -DDISK_DEBUG
+
+# Minimise the pread() buffer at the price of slower loads
+#CPPFLAGS+= -DSAVE_MEMORY
+
+.include <bsd.lib.mk>
diff --git a/sys/boot/i386/libi386/aout_freebsd.c b/sys/boot/i386/libi386/aout_freebsd.c
new file mode 100644
index 0000000..847073a
--- /dev/null
+++ b/sys/boot/i386/libi386/aout_freebsd.c
@@ -0,0 +1,274 @@
+/*-
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <sys/imgact_aout.h>
+#include <sys/reboot.h>
+#include <string.h>
+#include <machine/bootinfo.h>
+#include <stand.h>
+
+#include "bootstrap.h"
+#include "libi386.h"
+
+struct aout_kernel_module
+{
+ struct loaded_module m;
+ vm_offset_t m_entry; /* module entrypoint */
+ struct bootinfo m_bi; /* legacy bootinfo */
+};
+
+static int aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result);
+static int aout_exec(struct loaded_module *amp);
+
+struct module_format i386_aout = { MF_AOUT, aout_loadmodule, aout_exec };
+
+static int aout_loadimage(int fd, vm_offset_t loadaddr, struct exec *ehdr);
+
+/*
+ * Attempt to load the file (file) as an a.out module. It will be stored at
+ * (dest), and a pointer to a module structure describing the loaded object
+ * will be saved in (result).
+ */
+static int
+aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
+{
+ struct aout_kernel_module *mp;
+ struct exec ehdr;
+ int fd;
+ vm_offset_t addr;
+ int err;
+ u_int pad;
+
+ /*
+ * Open the image, read and validate the a.out header
+ *
+ * XXX what do kld modules look like? We only handle kernels here.
+ */
+ if (filename == NULL) /* can't handle nameless */
+ return(EFTYPE);
+ if ((fd = open(filename, O_RDONLY)) == -1)
+ return(errno);
+ if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
+ return(EFTYPE); /* could be EIO, but may be small file */
+ if (N_BADMAG(ehdr))
+ return(EFTYPE);
+
+ /*
+ * Ok, we think this is for us.
+ */
+ mp = malloc(sizeof(struct aout_kernel_module));
+ mp->m.m_name = strdup(filename); /* XXX should we prune the name? */
+ mp->m.m_type = "a.out kernel"; /* XXX only if that's what we really are */
+ mp->m.m_args = NULL; /* XXX should we put the bootstrap args here and parse later? */
+ mp->m.m_flags = MF_AOUT; /* we're an a.out kernel */
+ mp->m_entry = (vm_offset_t)(ehdr.a_entry & 0xffffff);
+ if (dest == 0)
+ dest = (vm_offset_t)(ehdr.a_entry & 0x100000);
+ if (mod_findmodule(NULL, mp->m.m_type) != NULL) {
+ printf("aout_loadmodule: kernel already loaded\n");
+ err = EPERM;
+ goto out;
+ }
+ printf("%s at 0x%x\n", filename, dest);
+ mp->m.m_addr = addr = dest;
+
+ mp->m.m_size = aout_loadimage(fd, addr, &ehdr);
+ printf("\n");
+ if (mp->m.m_size == 0)
+ goto ioerr;
+
+ /* XXX and if these parts don't exist? */
+ mp->m_bi.bi_symtab = mp->m.m_addr + ehdr.a_text + ehdr.a_data + ehdr.a_bss;
+ mp->m_bi.bi_esymtab = mp->m_bi.bi_symtab + sizeof(ehdr.a_syms) + ehdr.a_syms;
+
+ /* Load OK, return module pointer */
+ *result = (struct loaded_module *)mp;
+ return(0);
+
+ ioerr:
+ err = EIO;
+ out:
+ close(fd);
+ free(mp);
+ return(err);
+}
+
+/*
+ * With the file (fd) open on the image, and (ehdr) containing
+ * the exec header, load the image at (addr)
+ *
+ * Fixup the a_bss field in (ehdr) to reflect the padding added to
+ * align the symbol table.
+ */
+static int
+aout_loadimage(int fd, vm_offset_t loadaddr, struct exec *ehdr)
+{
+ u_int pad;
+ vm_offset_t addr;
+ int ss;
+
+ addr = loadaddr;
+ lseek(fd, N_TXTOFF(*ehdr), SEEK_SET);
+
+ /* text segment */
+ printf("text=0x%x ", ehdr->a_text);
+ if (pread(fd, addr, ehdr->a_text) != ehdr->a_text)
+ return(0);
+ addr += ehdr->a_text;
+
+ /* data segment */
+ printf("data=0x%x ", ehdr->a_data);
+ if (pread(fd, addr, ehdr->a_data) != ehdr->a_data)
+ return(0);
+ addr += ehdr->a_data;
+
+ /* skip the BSS */
+ printf("bss=0x%x ", ehdr->a_bss);
+ addr += ehdr->a_bss;
+
+ /* pad to a page boundary */
+ pad = (u_int)addr & PAGE_MASK;
+ if (pad != 0) {
+ pad = PAGE_SIZE - pad;
+ addr += pad;
+ ehdr->a_bss += pad;
+ }
+ /* XXX bi_symtab = addr */
+
+ /* symbol table size */
+ vpbcopy(&ehdr->a_syms, addr, sizeof(ehdr->a_syms));
+ addr += sizeof(ehdr->a_syms);
+
+ /* symbol table */
+ printf("symbols=[0x%x+0x%x+0x%x", pad, sizeof(ehdr->a_syms), ehdr->a_syms);
+ if (pread(fd, addr, ehdr->a_syms) != ehdr->a_syms)
+ return(0);
+ addr += ehdr->a_syms;
+
+ /* string table */
+ read(fd, &ss, sizeof(ss));
+ vpbcopy(&ss, addr, sizeof(ss));
+ addr += sizeof(ss);
+ ss -= sizeof(ss);
+ printf("+0x%x+0x%x]", sizeof(ss), ss);
+ if (pread(fd, addr, ss) != ss)
+ return(0);
+ /* XXX bi_esymtab = addr */
+ addr += ss;
+ return(addr - loadaddr);
+}
+
+
+/*
+ * There is an a.out kernel and one or more a.out modules loaded.
+ * We wish to start executing the kernel image, so make such
+ * preparations as are required, and do so.
+ */
+static int
+aout_exec(struct loaded_module *amp)
+{
+ struct aout_kernel_module *mp = (struct aout_kernel_module *)amp;
+ struct loaded_module *xp;
+ struct i386_devdesc *currdev;
+ u_int32_t argv[6]; /* kernel arguments */
+ int major, bootdevnr;
+ vm_offset_t addr;
+ u_int pad;
+
+ if ((amp->m_flags & MF_FORMATMASK) != MF_AOUT)
+ return(EFTYPE);
+
+ /* Boot from whatever the current device is */
+ i386_getdev((void **)(&currdev), NULL, NULL);
+ switch(currdev->d_type) {
+ case DEVT_DISK:
+ major = 0; /* XXX in the short term, have to work out a major number here for old kernels */
+ bootdevnr = MAKEBOOTDEV(major,
+ currdev->d_kind.biosdisk.slice >> 4,
+ currdev->d_kind.biosdisk.slice & 0xf,
+ currdev->d_kind.biosdisk.unit,
+ currdev->d_kind.biosdisk.partition);
+ break;
+ default:
+ printf("aout_loadmodule: WARNING - don't know how to boot from device type %d\n", currdev->d_type);
+ }
+ free(currdev);
+
+ /* Device data is kept in the kernel argv array */
+ argv[1] = bootdevnr;
+
+ argv[0] = bi_getboothowto(amp->m_args);
+/* argv[2] = vtophys(bootinfo); /* old cyl offset (do we care about this?) */
+ argv[3] = 0;
+ argv[4] = 0;
+ argv[5] = (u_int32_t)vtophys(&(mp->m_bi));
+
+ /* legacy bootinfo structure */
+ mp->m_bi.bi_version = BOOTINFO_VERSION;
+ mp->m_bi.bi_memsizes_valid = 1;
+ /* XXX bi_vesa */
+ mp->m_bi.bi_basemem = getbasemem();
+ mp->m_bi.bi_extmem = getextmem();
+
+ /* find the last module in the chain */
+ for (xp = amp; xp->m_next != NULL; xp = xp->m_next)
+ ;
+ addr = xp->m_addr + xp->m_size;
+ /* pad to a page boundary */
+ pad = (u_int)addr & PAGE_MASK;
+ if (pad != 0) {
+ pad = PAGE_SIZE - pad;
+ addr += pad;
+ }
+ /* copy our environment XXX save addr here as env pointer */
+ addr = bi_copyenv(addr);
+
+ /* pad to a page boundary */
+ pad = (u_int)addr & PAGE_MASK;
+ if (pad != 0) {
+ pad = PAGE_SIZE - pad;
+ addr += pad;
+ }
+ /* copy module list and metadata */
+ bi_copymodules(addr);
+
+#ifdef DEBUG
+ {
+ int i;
+ for (i = 0; i < 6; i++)
+ printf("argv[%d]=%lx\n", i, argv[i]);
+ }
+
+ printf("Start @ 0x%lx ...\n", mp->m_entry);
+#endif
+
+ startprog(mp->m_entry, 6, argv, (vm_offset_t)0x90000);
+ panic("exec returned");
+}
diff --git a/sys/boot/i386/libi386/biosdelay.S b/sys/boot/i386/libi386/biosdelay.S
new file mode 100644
index 0000000..c04a57b
--- /dev/null
+++ b/sys/boot/i386/libi386/biosdelay.S
@@ -0,0 +1,79 @@
+/* $NetBSD: biosdelay.S,v 1.1.1.1 1997/03/14 02:40:32 perry Exp $ */
+
+/*
+ * Copyright (c) 1996, 1997
+ * Perry E. Metzger. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgements:
+ * This product includes software developed for the NetBSD Project
+ * by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 <machine/asm.h>
+
+#define data32 .byte 0x66
+
+ .text
+
+/*
+# BIOS call "INT 15H Function 86H" to sleep for a set number of microseconds
+# Call with %ah = 0x86
+# %cx = time interval (high)
+# %dx = time interval (low)
+# Return:
+# If error
+# CF = set
+# else
+# CF = clear
+*/
+ENTRY(delay)
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ movw 20(%esp), %dx
+ movw 22(%esp), %cx
+
+ call CNAME(prot_to_real)
+
+ movb $0x86, %ah
+ int $0x15
+ setnc %ah
+
+ movb %ah, %bl # real_to_prot uses %eax
+
+ data32
+ call CNAME(real_to_prot)
+
+ xorl %eax, %eax
+ movb %bl, %al
+
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
diff --git a/sys/boot/i386/libi386/biosdisk.c b/sys/boot/i386/libi386/biosdisk.c
new file mode 100644
index 0000000..a6bcbbe
--- /dev/null
+++ b/sys/boot/i386/libi386/biosdisk.c
@@ -0,0 +1,408 @@
+/*-
+ * 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.
+ *
+ * $Id$
+ */
+
+/*
+ * BIOS disk device handling.
+ *
+ * Ideas and algorithms from:
+ *
+ * - NetBSD libi386/biosdisk.c
+ * - FreeBSD biosboot/disk.c
+ *
+ * XXX Todo: add bad144 support.
+ */
+
+#include <stand.h>
+
+#include <sys/disklabel.h>
+#include <sys/diskslice.h>
+
+#include "bootstrap.h"
+#include "libi386.h"
+#include "crt/biosdisk_ll.h"
+
+#define BUFSIZE (1 * BIOSDISK_SECSIZE)
+#define MAXBDDEV MAXDEV
+
+#ifdef DISK_DEBUG
+# define D(x) x
+#else
+# define D(x)
+#endif
+
+/* biosdisk_support.S */
+extern u_long bd_int13fn8(int unit);
+
+static int bd_edd3probe(int unit);
+static int bd_edd1probe(int unit);
+static int bd_int13probe(int unit);
+
+static int bd_init(void);
+static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize);
+static int bd_open(struct open_file *f, void *vdev);
+static int bd_close(struct open_file *f);
+
+struct open_disk {
+ struct biosdisk_ll od_ll; /* contains bios unit, geometry (XXX absorb) */
+ int od_unit; /* our unit number */
+ int od_boff; /* block offset from beginning of BIOS disk */
+ int od_flags;
+#define BD_MODEMASK 0x3
+#define BD_MODEINT13 0x0
+#define BD_MODEEDD1 0x1
+#define BD_MODEEDD3 0x2
+#define BD_FLOPPY (1<<2)
+ u_char od_buf[BUFSIZE]; /* transfer buffer (do we want/need this?) */
+};
+
+struct devsw biosdisk = {
+ "disk",
+ DEVT_DISK,
+ bd_init,
+ bd_strategy,
+ bd_open,
+ bd_close,
+ noioctl
+};
+
+/*
+ * List of BIOS devices, translation from disk unit number to
+ * BIOS unit number.
+ */
+static struct
+{
+ int bd_unit; /* BIOS unit number */
+ int bd_flags;
+} bdinfo [MAXBDDEV];
+static int nbdinfo = 0;
+
+/*
+ * Quiz the BIOS for disk devices, save a little info about them.
+ *
+ * XXX should we be consulting the BIOS equipment list, specifically
+ * the value at 0x475?
+ */
+static int
+bd_init(void)
+{
+ int base, unit;
+
+ /* sequence 0, 0x80 */
+ for (base = 0; base <= 0x80; base += 0x80) {
+ for (unit = base; (nbdinfo < MAXBDDEV); unit++) {
+ bdinfo[nbdinfo].bd_unit = -1;
+ bdinfo[nbdinfo].bd_flags = (unit < 0x80) ? BD_FLOPPY : 0;
+
+ if (bd_edd3probe(unit)) {
+ bdinfo[nbdinfo].bd_flags |= BD_MODEEDD3;
+ } else if (bd_edd1probe(unit)) {
+ bdinfo[nbdinfo].bd_flags |= BD_MODEEDD1;
+ } else if (bd_int13probe(unit)) {
+ bdinfo[nbdinfo].bd_flags |= BD_MODEINT13;
+ } else {
+ break;
+ }
+ /* XXX we need "disk aliases" to make this simpler */
+ printf("BIOS drive %c: is disk%d\n",
+ (unit < 0x80) ? ('A' + unit) : ('C' + unit - 0x80), nbdinfo);
+ bdinfo[nbdinfo].bd_unit = unit;
+ nbdinfo++;
+ }
+ }
+ return(0);
+}
+
+/*
+ * Try to detect a device supported by an Enhanced Disk Drive 3.0-compliant BIOS
+ */
+static int
+bd_edd3probe(int unit)
+{
+ return(0); /* XXX not implemented yet */
+}
+
+/*
+ * Try to detect a device supported by an Enhanced Disk Drive 1.1-compliant BIOS
+ */
+static int
+bd_edd1probe(int unit)
+{
+ return(0); /* XXX not implemented yet */
+}
+
+/*
+ * Try to detect a device supported by the legacy int13 BIOS
+ */
+
+static int
+bd_int13probe(int unit)
+{
+ u_long geom;
+
+ /* try int 0x13, function 8 */
+ geom = bd_int13fn8(unit);
+
+ return(geom != 0);
+}
+
+/*
+ * Attempt to open the disk described by (dev) for use by (f).
+ *
+ * Note that the philosophy here is "give them exactly what
+ * they ask for". This is necessary because being too "smart"
+ * about what the user might want leads to complications.
+ * (eg. given no slice or partition value, with a disk that is
+ * sliced - are they after the first BSD slice, or the DOS
+ * slice before it?)
+ */
+static int
+bd_open(struct open_file *f, void *vdev)
+{
+ struct i386_devdesc *dev = (struct i386_devdesc *)vdev;
+ struct dos_partition *dptr;
+ struct open_disk *od;
+ struct disklabel *lp;
+ int sector, slice, i;
+ int error;
+
+ if (dev->d_kind.biosdisk.unit >= nbdinfo) {
+ D(printf("bd_open: attempt to open nonexistent disk\n"));
+ return(ENXIO);
+ }
+
+ od = (struct open_disk *)malloc(sizeof(struct open_disk));
+ if (!od) {
+ D(printf("bd_open: no memory\n"));
+ return (ENOMEM);
+ }
+
+ /* Look up BIOS unit number, intialise open_disk structure */
+ od->od_unit = dev->d_kind.biosdisk.unit;
+ od->od_ll.dev = bdinfo[od->od_unit].bd_unit;
+ od->od_flags = bdinfo[od->od_unit].bd_flags;
+ od->od_boff = 0;
+ error = 0;
+#if 0
+ D(printf("bd_open: open '%s' - unit 0x%x slice %d partition %c\n",
+ i386_fmtdev(dev), dev->d_kind.biosdisk.unit,
+ dev->d_kind.biosdisk.slice, dev->d_kind.biosdisk.partition + 'a'));
+#endif
+
+ /* Get geometry for this open (removable device may have changed) */
+ if (set_geometry(&od->od_ll)) {
+ D(printf("bd_open: can't get geometry\n"));
+ error = ENXIO;
+ goto out;
+ }
+
+ /*
+ * Following calculations attempt to determine the correct value
+ * for d->od_boff by looking for the slice and partition specified,
+ * or searching for reasonable defaults.
+ */
+
+ /*
+ * Find the slice in the DOS slice table.
+ */
+ if (readsects(&od->od_ll, 0, 1, od->od_buf, 0)) {
+ D(printf("bd_open: error reading MBR\n"));
+ error = EIO;
+ goto out;
+ }
+
+ /*
+ * Check the slice table magic.
+ */
+ if ((od->od_buf[0x1fe] != 0xff) || (od->od_buf[0x1ff] != 0xaa)) {
+ /* If a slice number was explicitly supplied, this is an error */
+ if (dev->d_kind.biosdisk.slice > 0) {
+ D(printf("bd_open: no slice table/MBR (no magic)\n"));
+ error = ENOENT;
+ goto out;
+ }
+ sector = 0;
+ goto unsliced; /* may be a floppy */
+ }
+ dptr = (struct dos_partition *) & od->od_buf[DOSPARTOFF];
+
+ /*
+ * XXX No support here for 'extended' slices
+ */
+ if (dev->d_kind.biosdisk.slice <= 0) {
+ /*
+ * Search for the first FreeBSD slice; this also works on "unsliced"
+ * disks, as they contain a "historically bogus" MBR.
+ */
+ for (i = 0; i < NDOSPART; i++, dptr++)
+ if (dptr->dp_typ == DOSPTYP_386BSD) {
+ sector = dptr->dp_start;
+ break;
+ }
+ /* Did we find something? */
+ if (sector == -1) {
+ error = ENOENT;
+ goto out;
+ }
+ } else {
+ /*
+ * Accept the supplied slice number unequivocally (we may be looking
+ * for a DOS partition) if we can handle it.
+ */
+ if ((dev->d_kind.biosdisk.slice > NDOSPART) || (dev->d_kind.biosdisk.slice < 1)) {
+ error = ENOENT;
+ goto out;
+ }
+ dptr += (dev->d_kind.biosdisk.slice - 1);
+ sector = dptr->dp_start;
+ }
+ unsliced:
+ /*
+ * Now we have the slice, look for the partition in the disklabel if we have
+ * a partition to start with.
+ *
+ * XXX we might want to check the label checksum.
+ */
+ if (dev->d_kind.biosdisk.partition < 0) {
+ od->od_boff = sector; /* no partition, must be after the slice */
+ D(printf("bd_open: opening raw slice\n"));
+ } else {
+
+ if (readsects(&od->od_ll, sector + LABELSECTOR, 1, od->od_buf, 0)) {
+ D(printf("bd_open: error reading disklabel\n"));
+ error = EIO;
+ goto out;
+ }
+ lp = (struct disklabel *) (od->od_buf + LABELOFFSET);
+ if (lp->d_magic != DISKMAGIC) {
+ D(printf("bd_open: no disklabel\n"));
+ error = ENOENT;
+ goto out;
+
+ } else if (dev->d_kind.biosdisk.partition >= lp->d_npartitions) {
+
+ /*
+ * The partition supplied is out of bounds; this is fatal.
+ */
+ D(printf("partition '%c' exceeds partitions in table (a-'%c')\n",
+ 'a' + dev->d_kind.biosdisk.partition, 'a' + lp->d_npartitions));
+ error = EPART;
+ goto out;
+
+ } else {
+
+ /*
+ * Complain if the partition type is wrong and it shouldn't be, but
+ * regardless accept this partition.
+ */
+ D(if ((lp->d_partitions[dev->d_kind.biosdisk.partition].p_fstype == FS_UNUSED) &&
+ !(od->od_flags & BD_FLOPPY)) /* Floppies often have bogus fstype */
+ printf("bd_open: warning, partition marked as unused\n"););
+
+ od->od_boff = lp->d_partitions[dev->d_kind.biosdisk.partition].p_offset;
+ }
+ }
+ /*
+ * Save our context
+ */
+ ((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data = od;
+#if 0
+ D(printf("bd_open: open_disk %p\n", od));
+#endif
+
+ out:
+ if (error)
+ free(od);
+ return(error);
+}
+
+static int
+bd_close(struct open_file *f)
+{
+ struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data);
+
+#if 0
+ D(printf("bd_close: open_disk %p\n", od));
+#endif
+
+ /* XXX is this required? (especially if disk already open...) */
+ if (od->od_flags & BD_FLOPPY)
+ delay(3000000);
+
+ free(od);
+ return(0);
+}
+
+static int
+bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize)
+{
+ struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data);
+ int blks;
+#ifdef BD_SUPPORT_FRAGS
+ char fragbuf[BIOSDISK_SECSIZE];
+ size_t fragsize;
+
+ fragsize = size % BIOSDISK_SECSIZE;
+#else
+ if (size % BIOSDISK_SECSIZE)
+ panic("bd_strategy: %d bytes I/O not multiple of block size", size);
+#endif
+
+#if 0
+ D(printf("bd_strategy: open_disk %p\n", od));
+#endif
+
+ if (rw != F_READ)
+ return(EROFS);
+
+
+ blks = size / BIOSDISK_SECSIZE;
+#if 0
+ D(printf("bd_strategy: read %d from %d+%d to %p\n", blks, od->od_boff, dblk, buf));
+#endif
+
+ if (rsize)
+ *rsize = 0;
+ if (blks && readsects(&od->od_ll, dblk + od->od_boff, blks, buf, 0)) {
+ D(printf("read error\n"));
+ return (EIO);
+ }
+#ifdef BD_SUPPORT_FRAGS
+#if 0
+ D(printf("bd_strategy: frag read %d from %d+%d+d to %p\n",
+#endif
+ fragsize, od->od_boff, dblk, blks, buf + (blks * BIOSDISK_SECSIZE)));
+ if (fragsize && readsects(&od->od_ll, dblk + od->od_boff + blks, 1, fragsize, 0)) {
+ D(printf("frag read error\n"));
+ return(EIO);
+ }
+ bcopy(fragbuf, buf + (blks * BIOSDISK_SECSIZE), fragsize);
+#endif
+ if (rsize)
+ *rsize = size;
+ return (0);
+}
diff --git a/sys/boot/i386/libi386/biosdisk_support.S b/sys/boot/i386/libi386/biosdisk_support.S
new file mode 100644
index 0000000..52e2e0f
--- /dev/null
+++ b/sys/boot/i386/libi386/biosdisk_support.S
@@ -0,0 +1,114 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ *
+ * from: Mach, Revision 2.2 92/04/04 11:34:26 rpd
+ * $Id: bios.S,v 1.12 1997/07/31 08:07:53 phk Exp $
+ */
+
+/*
+ Copyright 1988, 1989, 1990, 1991, 1992
+ by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include <machine/asm.h>
+
+#define addr32 .byte 0x67
+#define data32 .byte 0x66
+
+/*
+ *
+ * get_diskinfo(): return a word that represents the
+ * max number of sectors and heads and drives for this device
+ *
+ */
+
+ENTRY(bd_int13fn8)
+ push %ebp
+ mov %esp, %ebp
+ push %ebx
+ push %esi
+ push %edi
+
+ movb 0x8(%ebp), %dl /* diskinfo(drive #) */
+ call CNAME(prot_to_real) /* enter real mode */
+
+ movb $0x8, %ah /* ask for disk info */
+
+ sti
+ int $0x13
+ cli
+
+ jnc ok
+ /* call failed, return 0 */
+ subb %cl, %cl
+ subb %ch, %ch
+ subb %dl, %dl
+ subb %dh, %dh
+ok:
+
+ data32
+ call CNAME(real_to_prot) /* back to protected mode */
+
+ /*
+ * form a longword representing all this gunk:
+ * 6 bit zero
+ * 10 bit max cylinder (0 based)
+ * 8 bit max head (0 based)
+ * 2 bit zero
+ * 6 bit max sector (1 based) = # sectors
+ */
+ movb %cl, %al /* Upper two bits of cylinder count */
+ andl $0xc0,%eax
+ leal 0(,%eax,4),%eax /* << 2 */
+ movb %ch, %al /* Lower 8 bits */
+ sall $16,%eax /* << 16 */
+ movb %dh, %ah /* max head */
+ andb $0x3f, %cl /* mask of cylinder gunk */
+ movb %cl, %al /* max sector (and # sectors) */
+
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %ebp
+ ret
+
diff --git a/sys/boot/i386/libi386/biosgetrtc.S b/sys/boot/i386/libi386/biosgetrtc.S
new file mode 100644
index 0000000..5927a06
--- /dev/null
+++ b/sys/boot/i386/libi386/biosgetrtc.S
@@ -0,0 +1,77 @@
+/* $NetBSD: biosgetrtc.S,v 1.2 1997/06/13 13:42:27 drochner Exp $ */
+
+/*
+ * Copyright (c) 1996
+ * Matthias Drochner. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 <machine/asm.h>
+
+#define addr32 .byte 0x67
+#define data32 .byte 0x66
+
+ENTRY(biosgetrtc)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ push %esi
+ push %edi
+
+ xorl %ebx, %ebx
+
+ call CNAME(prot_to_real) # enter real mode
+
+ movb $2, %ah
+ int $0x1a
+ jnc ok
+ data32
+ movl $-1, %ebx
+
+ok:
+ data32
+ call CNAME(real_to_prot) # back to protected mode
+
+ movl 8(%ebp), %eax
+ movl $0, (%eax)
+ movb %ch, (%eax)
+ movb %cl, 1(%eax)
+ movb %dh, 2(%eax)
+
+ movl %ebx, %eax
+
+ pop %edi
+ pop %esi
+ popl %edx
+ popl %ecx
+ popl %ebx
+ popl %ebp
+ ret
diff --git a/sys/boot/i386/libi386/biosmem.S b/sys/boot/i386/libi386/biosmem.S
new file mode 100644
index 0000000..cb97672
--- /dev/null
+++ b/sys/boot/i386/libi386/biosmem.S
@@ -0,0 +1,99 @@
+/* $NetBSD: biosmem.S,v 1.5 1997/08/18 22:44:01 hannken Exp $ */
+
+/*
+ * Copyright (c) 1996
+ * Perry E. Metzger. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgements:
+ * This product includes software developed for the NetBSD Project
+ * by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 <machine/asm.h>
+
+#define data32 .byte 0x66
+
+ .text
+
+/* get mem below 1M, in kByte */
+
+ENTRY(getbasemem)
+ pushl %ebp
+ movl %esp,%ebp
+ pushl %ebx
+ push %esi
+ push %edi
+
+ call CNAME(prot_to_real)
+
+ int $0x12
+ # zero-extend 16-bit result to 32 bits.
+ data32
+ movl $0, %ebx
+ mov %eax,%ebx # !!! at run time, it is mov %ax,%bx
+
+ data32
+ call CNAME(real_to_prot)
+
+ movl %ebx, %eax
+
+ pop %edi
+ pop %esi
+ popl %ebx
+ popl %ebp
+ ret
+
+/* get mem above 1M, in kByte */
+
+ENTRY(getextmem)
+ pushl %ebp
+ movl %esp,%ebp
+ pushl %ebx
+ push %esi
+ push %edi
+
+ call CNAME(prot_to_real)
+
+ movb $0x88,%ah
+ int $0x15
+
+ # zero-extend 16-bit result to 32 bits.
+ data32
+ movl $0, %ebx
+ mov %eax,%ebx # !!! at run time, it is mov %ax,%bx
+
+ data32
+ call CNAME(real_to_prot)
+
+ movl %ebx, %eax
+
+ pop %edi
+ pop %esi
+ popl %ebx
+ popl %ebp
+ ret
+
diff --git a/sys/boot/i386/libi386/biosreboot.S b/sys/boot/i386/libi386/biosreboot.S
new file mode 100644
index 0000000..f2bfe65
--- /dev/null
+++ b/sys/boot/i386/libi386/biosreboot.S
@@ -0,0 +1,66 @@
+/* $NetBSD: biosreboot.S,v 1.1 1997/04/13 18:45:37 perry Exp $ */
+
+/*
+ * Copyright (c) 1997
+ * Perry E. Metzger. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgements:
+ * This product includes software developed for the NetBSD Project
+ * by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 <machine/asm.h>
+
+#define data32 .byte 0x66
+
+ .text
+
+/* Call INT 19 to do the equivalent of CTL-ALT-DEL */
+
+ENTRY(reboot)
+ pushl %ebp
+ movl %esp,%ebp
+ pushl %ebx
+ push %esi
+ push %edi
+
+ call CNAME(prot_to_real)
+
+ int $0x19
+
+ /* NOTE: We should never even get past this point. */
+
+ data32
+ call CNAME(real_to_prot)
+
+ movl %ebx, %eax
+
+ pop %edi
+ pop %esi
+ popl %ebx
+ popl %ebp
+ ret
diff --git a/sys/boot/i386/libi386/bootinfo.c b/sys/boot/i386/libi386/bootinfo.c
new file mode 100644
index 0000000..8554f2a
--- /dev/null
+++ b/sys/boot/i386/libi386/bootinfo.c
@@ -0,0 +1,197 @@
+/*-
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <sys/reboot.h>
+#include <stand.h>
+#include "bootstrap.h"
+
+
+/*
+ * Return a 'boothowto' value corresponding to the kernel arguments in
+ * (kargs) and any relevant environment variables.
+ */
+static struct
+{
+ char *ev;
+ int mask;
+} howto_names[] = {
+ {"boot_askname", RB_ASKNAME},
+ {"boot_userconfig", RB_CONFIG},
+ {"boot_ddb", RB_KDB},
+ {"boot_gdb", RB_GDB},
+ {"boot_single", RB_SINGLE},
+ {"boot_verbose", RB_VERBOSE},
+ {NULL, 0}
+};
+
+int
+bi_getboothowto(char *kargs)
+{
+ char *cp;
+ int howto;
+ int active;
+ int i;
+
+ howto = 0;
+ if (kargs != NULL) {
+ cp = kargs;
+ active = 0;
+ while (*cp != 0) {
+ if (!active && (*cp == '-')) {
+ active = 1;
+ } else if (active)
+ switch (*cp) {
+ case 'a':
+ howto |= RB_ASKNAME;
+ break;
+ case 'c':
+ howto |= RB_CONFIG;
+ break;
+ case 'd':
+ howto |= RB_KDB;
+ break;
+ case 'g':
+ howto |= RB_GDB;
+ break;
+ case 'h':
+ howto |= RB_SERIAL;
+ break;
+ case 'r':
+ howto |= RB_DFLTROOT;
+ break;
+ case 's':
+ howto |= RB_SINGLE;
+ break;
+ case 'v':
+ howto |= RB_VERBOSE;
+ break;
+ default:
+ active = 0;
+ break;
+ }
+ }
+ cp++;
+ }
+ for (i = 0; howto_names[i].ev != NULL; i++)
+ if (getenv(howto_names[i].ev) != NULL)
+ howto |= howto_names[i].mask;
+ if (!strcmp(getenv("console"), "comconsole"))
+ howto |= RB_SERIAL;
+ return(howto);
+}
+
+/*
+ * Copy the environment into the load area starting at (addr).
+ * Each variable is formatted as <name>=<value>, with a single nul
+ * separating each variable, and a double nul terminating the environment.
+ */
+vm_offset_t
+bi_copyenv(vm_offset_t addr)
+{
+ struct env_var *ep;
+
+ /* traverse the environment */
+ for (ep = environ; ep != NULL; ep = ep->ev_next) {
+ vpbcopy(ep->ev_name, addr, strlen(ep->ev_name));
+ addr += strlen(ep->ev_name);
+ vpbcopy("=", addr, 1);
+ addr++;
+ if (ep->ev_value != NULL) {
+ vpbcopy(ep->ev_value, addr, strlen(ep->ev_value));
+ addr += strlen(ep->ev_value);
+ }
+ vpbcopy("", addr, 1);
+ addr++;
+ }
+ vpbcopy("", addr, 1);
+ addr++;
+}
+
+/*
+ * Copy module-related data into the load area, where it can be
+ * used as a directory for loaded modules.
+ *
+ * Module data is presented in a self-describing format. Each datum
+ * is preceeded by a 16-bit identifier and a 16-bit size field.
+ *
+ * Currently, the following data are saved:
+ *
+ * MOD_NAME (variable) module name (string)
+ * MOD_TYPE (variable) module type (string)
+ * MOD_ADDR sizeof(vm_offset_t) module load address
+ * MOD_SIZE sizeof(size_t) module size
+ * MOD_METADATA (variable) type-specific metadata
+ */
+#define MOD_STR(t, a, s) { \
+ u_int32_t ident = (t << 16) + strlen(s) + 1; \
+ vpbcopy(&ident, a, sizeof(ident)); \
+ a += sizeof(ident); \
+ vpbcopy(s, a, strlen(s) + 1); \
+ a += strlen(s) + 1; \
+}
+
+#define MOD_NAME(a, s) MOD_STR(MODINFO_NAME, a, s)
+#define MOD_TYPE(a, s) MOD_STR(MODINFO_TYPE, a, s)
+
+#define MOD_VAR(t, a, s) { \
+ u_int32_t ident = (t << 16) + sizeof(s); \
+ vpbcopy(&ident, a, sizeof(ident)); \
+ a += sizeof(ident); \
+ vpbcopy(&s, a, sizeof(s)); \
+ a += sizeof(s); \
+}
+
+#define MOD_ADDR(a, s) MOD_VAR(MODINFO_ADDR, a, s)
+#define MOD_SIZE(a, s) MOD_VAR(MODINFO_SIZE, a, s)
+
+#define MOD_METADATA(a, mm) { \
+ u_int32_t ident = ((MODINFO_METADATA | mm->md_type) << 16) + mm->md_size; \
+ vpbcopy(&ident, a, sizeof(ident)); \
+ a += sizeof(ident); \
+ vpbcopy(mm->md_data, a, mm->md_size); \
+ a += mm->md_size; \
+}
+
+vm_offset_t
+bi_copymodules(vm_offset_t addr)
+{
+ struct loaded_module *mp;
+ struct module_metadata *md;
+
+ /* start with the first module on the list, should be the kernel */
+ for (mp = mod_findmodule(NULL, NULL); mp != NULL; mp = mp->m_next) {
+
+ MOD_NAME(addr, mp->m_name);
+ MOD_TYPE(addr, mp->m_type);
+ MOD_ADDR(addr, mp->m_addr);
+ MOD_SIZE(addr, mp->m_size);
+ for (md = mp->m_metadata; md != NULL; md = md->md_next)
+ MOD_METADATA(addr, md);
+ }
+ return(addr);
+}
diff --git a/sys/boot/i386/libi386/comconsole.c b/sys/boot/i386/libi386/comconsole.c
new file mode 100644
index 0000000..a75f92d
--- /dev/null
+++ b/sys/boot/i386/libi386/comconsole.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1998 Michael Smith (msmith@freebsd.org)
+ *
+ * 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.
+ *
+ * From Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp
+ *
+ * $Id$
+ */
+
+#include <stand.h>
+
+#include "bootstrap.h"
+
+/* in comconsole.S */
+extern void cominit(int s);
+extern void computc(int c);
+extern int comgetc(void);
+extern int comiskey(void);
+
+static void comc_probe(struct console *cp);
+static int comc_init(int arg);
+static int comc_in(void);
+
+struct console comconsole = {
+ "comconsole",
+ "BIOS serial port",
+ 0,
+ comc_probe,
+ comc_init,
+ computc,
+ comc_in,
+ comiskey
+};
+
+static void
+comc_probe(struct console *cp)
+{
+ /* XXX check the BIOS equipment list? */
+ cp->c_flags |= (C_PRESENTIN | C_PRESENTOUT);
+}
+
+static int
+comc_init(int arg)
+{
+ /* XXX arg is unit number, should we use variables instead? */
+ cominit(arg);
+ return(0);
+}
+
+static int
+comc_in(void)
+{
+ if (comiskey()) {
+ return(comgetc());
+ } else {
+ return(-1);
+ }
+}
diff --git a/sys/boot/i386/libi386/comconsole_support.S b/sys/boot/i386/libi386/comconsole_support.S
new file mode 100644
index 0000000..a6861dc
--- /dev/null
+++ b/sys/boot/i386/libi386/comconsole_support.S
@@ -0,0 +1,147 @@
+/* $NetBSD: comio.S,v 1.2 1997/10/27 19:51:18 drochner Exp $ */
+
+/* serial console handling
+ modelled after code in FreeBSD:sys/i386/boot/netboot/start2.S
+ */
+
+#include <machine/asm.h>
+
+#define addr32 .byte 0x67
+#define data32 .byte 0x66
+
+ .text
+
+/**************************************************************************
+INIT - Initialization (com number)
+**************************************************************************/
+ENTRY(cominit)
+ push %ebp
+ mov %esp,%ebp
+ push %ebx
+ push %edx
+ push %esi
+ push %edi
+
+ movl 8(%ebp), %edx
+
+ call CNAME(prot_to_real) # enter real mode
+
+ # Initialize the serial port (dl) to 9600 baud, 8N1.
+ movb $0xe3, %al
+ movb $0, %ah
+ int $0x14
+ mov %ax,%bx
+
+ data32
+ call CNAME(real_to_prot) # back to protected mode
+
+ xor %eax,%eax
+ mov %bx,%ax
+
+ pop %edi
+ pop %esi
+ pop %edx
+ pop %ebx
+ pop %ebp
+ ret
+
+/**************************************************************************
+PUTC - Print a character (char, com number)
+**************************************************************************/
+ENTRY(computc)
+ push %ebp
+ mov %esp,%ebp
+ push %ecx
+ push %ebx
+ push %edx
+ push %esi
+ push %edi
+
+ movb 8(%ebp),%cl
+ movl 12(%ebp),%edx
+
+ call CNAME(prot_to_real) # enter real mode
+
+ movb %cl,%al
+ movb $0x01, %ah
+ int $0x14
+
+ movb %ah,%bl
+
+ data32
+ call CNAME(real_to_prot) # back to protected mode
+
+ xor %eax,%eax
+ movb %bl,%al
+
+ pop %edi
+ pop %esi
+ pop %edx
+ pop %ebx
+ pop %ecx
+ pop %ebp
+ ret
+
+/**************************************************************************
+GETC - Get a character (com number)
+**************************************************************************/
+ENTRY(comgetc)
+ push %ebp
+ mov %esp,%ebp
+ push %ebx
+ push %edx
+ push %esi
+ push %edi
+
+ movl 8(%ebp),%edx
+
+ call CNAME(prot_to_real) # enter real mode
+
+ movb $0x02, %ah
+ int $0x14
+ movl %eax,%ebx # at run time, it is mov %ax,%bx
+
+ data32
+ call CNAME(real_to_prot) # back to protected mode
+
+ xor %eax,%eax
+ mov %bx,%ax
+
+ pop %edi
+ pop %esi
+ pop %edx
+ pop %ebx
+ pop %ebp
+ ret
+
+/**************************************************************************
+ISKEY - Check for keyboard interrupt (com number)
+**************************************************************************/
+ENTRY(comiskey)
+ push %ebp
+ mov %esp,%ebp
+ push %ebx
+ push %edx
+ push %esi
+ push %edi
+
+ movl 8(%ebp),%edx
+
+ call CNAME(prot_to_real) # enter real mode
+
+ movb $0x03, %ah
+ int $0x14
+ mov %ax,%bx
+
+ data32
+ call CNAME(real_to_prot) # back to protected mode
+
+ xor %eax,%eax
+ mov %bx,%ax
+
+ pop %edi
+ pop %esi
+ pop %edx
+ pop %ebx
+ pop %ebp
+ ret
diff --git a/sys/boot/i386/libi386/crt/Makefile b/sys/boot/i386/libi386/crt/Makefile
new file mode 100644
index 0000000..400cae8
--- /dev/null
+++ b/sys/boot/i386/libi386/crt/Makefile
@@ -0,0 +1,3 @@
+SUBDIR= bootsect
+
+.include <bsd.subdir.mk>
diff --git a/sys/boot/i386/libi386/crt/bios_disk.S b/sys/boot/i386/libi386/crt/bios_disk.S
new file mode 100644
index 0000000..3e383c5
--- /dev/null
+++ b/sys/boot/i386/libi386/crt/bios_disk.S
@@ -0,0 +1,176 @@
+/*
+ * $Id$
+ * From: $NetBSD: bios_disk.S,v 1.1.1.1 1997/03/14 02:40:32 perry Exp $
+ */
+
+/*
+ * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ *
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+ Copyright 1988, 1989, 1990, 1991, 1992
+ by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/* extracted from netbsd:sys/arch/i386/boot/bios.S */
+
+#include <machine/asm.h>
+
+#define addr32 .byte 0x67
+#define data32 .byte 0x66
+
+/*
+# BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
+# Call with %ah = 0x2
+# %al = number of sectors
+# %ch = cylinder
+# %cl = sector
+# %dh = head
+# %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
+# %es:%bx = segment:offset of buffer
+# Return:
+# %al = 0x0 on success; err code on failure
+*/
+ENTRY(biosread)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %ebx
+ push %ecx
+ push %edx
+ push %esi
+ push %edi
+
+ movb 16(%ebp), %dh
+ movw 12(%ebp), %cx
+ xchgb %ch, %cl # cylinder; the highest 2 bits of cyl is in %cl
+ rorb $2, %cl
+ movb 20(%ebp), %al
+ orb %al, %cl
+ incb %cl # sector; sec starts from 1, not 0
+ movb 8(%ebp), %dl # device
+ movl 28(%ebp), %ebx # offset
+ # prot_to_real will set %es to BOOTSEG
+
+ call CNAME(prot_to_real) # enter real mode
+
+ movb $0x2, %ah # subfunction
+ addr32
+ movb 24(%ebp), %al # number of sectors
+ int $0x13
+ setc %bl
+
+ data32
+ call CNAME(real_to_prot) # back to protected mode
+
+ xorl %eax, %eax
+ movb %bl, %al # return value in %ax
+
+ pop %edi
+ pop %esi
+ pop %edx
+ pop %ecx
+ popl %ebx
+ popl %ebp
+ ret
+
+/*
+#
+# get_diskinfo(): return a word that represents the
+# max number of sectors and heads and drives for this device
+#
+*/
+
+ENTRY(get_diskinfo)
+ pushl %ebp
+ movl %esp, %ebp
+ push %es
+ pushl %ebx
+ push %ecx
+ push %edx
+ push %esi
+ push %edi
+
+ movb 8(%ebp), %dl # diskinfo(drive #)
+
+ call CNAME(prot_to_real) # enter real mode
+
+ movb $0x08, %ah # ask for disk info
+ int $0x13
+ jnc ok
+
+ /*
+ * Urk. Call failed. It is not supported for floppies by old BIOS's.
+ * Guess it's a 15-sector floppy. Initialize all the registers for
+ * documentation, although we only need head and sector counts.
+ */
+# subb %ah, %ah # %ax = 0
+# movb %ah, %bh # %bh = 0
+# movb $2, %bl # %bl bits 0-3 = drive type, 2 = 1.2M
+# movb $79, %ch # max track
+ movb $15, %cl # max sector
+ movb $1, %dh # max head
+# movb $1, %dl # # floppy drives installed
+ # es:di = parameter table
+ # carry = 0
+
+ok:
+ data32
+ call CNAME(real_to_prot) # back to protected mode
+
+ xorl %eax, %eax
+
+ /*form a longword representing all this gunk*/
+ movb %dh, %ah # max head
+ andb $0x3f, %cl # mask of cylinder gunk
+ movb %cl, %al # max sector (and # sectors)
+
+ pop %edi
+ pop %esi
+ pop %edx
+ pop %ecx
+ popl %ebx
+ pop %es
+ popl %ebp
+ ret
diff --git a/sys/boot/i386/libi386/crt/biosdisk_ll.c b/sys/boot/i386/libi386/crt/biosdisk_ll.c
new file mode 100644
index 0000000..b7c77de
--- /dev/null
+++ b/sys/boot/i386/libi386/crt/biosdisk_ll.c
@@ -0,0 +1,148 @@
+/*
+ * $Id$
+ * From: $NetBSD: biosdisk_ll.c,v 1.3 1997/06/13 13:36:06 drochner Exp $
+ */
+
+/*
+ * Copyright (c) 1996
+ * Matthias Drochner. All rights reserved.
+ * Copyright (c) 1996
+ * Perry E. Metzger. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgements:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * This product includes software developed for the NetBSD Project
+ * by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ */
+
+/*
+ * shared by bootsector startup (bootsectmain) and biosdisk.c
+ * needs lowlevel parts from bios_disk.S
+ */
+
+#include <stand.h>
+
+#include "biosdisk_ll.h"
+#include "diskbuf.h"
+
+/* XXX prototypes from export header? */
+extern int get_diskinfo(int);
+extern int biosread(int, int, int, int, int, char *);
+
+#define SPT(di) ((di)&0xff)
+#define HEADS(di) ((((di)>>8)&0xff)+1)
+
+int
+set_geometry(d)
+ struct biosdisk_ll *d;
+{
+ int diskinfo;
+
+ diskinfo = get_diskinfo(d->dev);
+
+ d->spc = (d->spt = SPT(diskinfo)) * HEADS(diskinfo);
+
+ /*
+ * get_diskinfo assumes floppy if BIOS call fails. Check at least
+ * "valid" geometry.
+ */
+ return (!d->spc || !d->spt);
+}
+
+/*
+ * Global shared "diskbuf" is used as read ahead buffer. For reading from
+ * floppies, the bootstrap has to be loaded on a 64K boundary to ensure that
+ * this buffer doesn't cross a 64K DMA boundary.
+ */
+static int ra_dev;
+static int ra_end;
+static int ra_first;
+
+int
+readsects(d, dblk, num, buf, cold) /* reads ahead if (!cold) */
+ struct biosdisk_ll *d;
+ int dblk, num;
+ char *buf;
+ int cold; /* don't use data segment or bss, don't call
+ * library functions */
+{
+ while (num) {
+ int nsec;
+
+ /* check for usable data in read-ahead buffer */
+ if (cold || diskbuf_user != &ra_dev || d->dev != ra_dev
+ || dblk < ra_first || dblk >= ra_end) {
+
+ /* no, read from disk */
+ int cyl, head, sec;
+ char *trbuf;
+
+ cyl = dblk / d->spc;
+ head = (dblk % d->spc) / d->spt;
+ sec = dblk % d->spt;
+ nsec = d->spt - sec;
+
+ if (cold) {
+ /* transfer directly to buffer */
+ trbuf = buf;
+ if (nsec > num)
+ nsec = num;
+ } else {
+ /* fill read-ahead buffer */
+ trbuf = diskbuf;
+ if (nsec > diskbuf_size)
+ nsec = diskbuf_size;
+
+ ra_dev = d->dev;
+ ra_first = dblk;
+ ra_end = dblk + nsec;
+ diskbuf_user = &ra_dev;
+ }
+
+ if (biosread(d->dev, cyl, head, sec, nsec, trbuf)) {
+ if (!cold)
+ diskbuf_user = 0; /* mark invalid */
+ return (-1); /* XXX cannot output here if
+ * (cold) */
+ }
+ } else /* can take blocks from end of read-ahead
+ * buffer */
+ nsec = ra_end - dblk;
+
+ if (!cold) {
+ /* copy data from read-ahead to user buffer */
+ if (nsec > num)
+ nsec = num;
+ bcopy(diskbuf + (dblk - ra_first) * BIOSDISK_SECSIZE,
+ buf, nsec * BIOSDISK_SECSIZE);
+ }
+ buf += nsec * BIOSDISK_SECSIZE;
+ num -= nsec;
+ dblk += nsec;
+ }
+
+ return (0);
+}
diff --git a/sys/boot/i386/libi386/crt/biosdisk_ll.h b/sys/boot/i386/libi386/crt/biosdisk_ll.h
new file mode 100644
index 0000000..7e0782a
--- /dev/null
+++ b/sys/boot/i386/libi386/crt/biosdisk_ll.h
@@ -0,0 +1,54 @@
+/*
+ * $Id$
+ * From: $NetBSD: biosdisk_ll.h,v 1.2 1997/03/22 01:41:36 thorpej Exp $
+ */
+
+/*
+ * Copyright (c) 1996
+ * Matthias Drochner. All rights reserved.
+ * Copyright (c) 1996
+ * Perry E. Metzger. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgements:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * This product includes software developed for the NetBSD Project
+ * by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ */
+
+/*
+ * shared by bootsector startup (bootsectmain) and biosdisk.c needs lowlevel
+ * parts from bios_disk.S
+ */
+
+struct biosdisk_ll {
+ int dev; /* BIOS device number */
+ int spt, spc; /* geometry */
+};
+
+#define BIOSDISK_SECSIZE 512
+
+extern int set_geometry(struct biosdisk_ll *);
+extern int readsects(struct biosdisk_ll *, int, int, char *, int);
diff --git a/sys/boot/i386/libi386/crt/bootsect/Makefile b/sys/boot/i386/libi386/crt/bootsect/Makefile
new file mode 100644
index 0000000..1c04705
--- /dev/null
+++ b/sys/boot/i386/libi386/crt/bootsect/Makefile
@@ -0,0 +1,25 @@
+#
+# Build a startup module
+#
+
+# Disk buffer size in sectors
+CFLAGS+= -DDISKBUFSIZE=18
+# Stack size in bytes
+CFLAGS+= -DSTACKSIZE=0x1000
+
+PROG= bscrt.o
+LDFLAGS= -static -nostartfiles -nostdlib -Xlinker -r
+NOMAN= yes
+
+# Bootblock-specific sources
+SRCS= start_bootsect.S fraglist.S bootsectmain.c
+
+# Includes for libsa support routines XXX fix path!
+CFLAGS+= -I${.CURDIR}/../../../../../whole/lib/libstand
+
+# Common items across all startups
+.PATH: ${.CURDIR}/..
+CFLAGS+= -I${.CURDIR}/..
+SRCS+= biosdisk_ll.c bios_disk.S buffers.S
+
+.include <bsd.prog.mk>
diff --git a/sys/boot/i386/libi386/crt/bootsect/bbinfo.h b/sys/boot/i386/libi386/crt/bootsect/bbinfo.h
new file mode 100644
index 0000000..f777acf
--- /dev/null
+++ b/sys/boot/i386/libi386/crt/bootsect/bbinfo.h
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ * From: $NetBSD: bbinfo.h,v 1.3 1997/11/07 16:59:41 drochner Exp $
+ */
+
+/*
+ * Copyright (c) 1996
+ * Matthias Drochner. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ */
+
+/* data structure shared by bootsector
+ and installboot
+ */
+
+#ifndef __ASSEMBLER__
+
+struct fraglist {
+ int magic;
+ int loadsz; /* blocks loaded by primary boot */
+ int numentries, maxentries;
+ struct {
+ int offset, num;
+ } entries[1];
+};
+
+#endif
+
+#define FRAGLISTVERSION 0
+#define FRAGLISTMAGIC (0xb00deda5 + FRAGLISTVERSION)
+
+/* only used by bootsect code (not by installboot) */
+#ifndef MAXFLENTRIES
+#define MAXFLENTRIES 10
+#endif
+#ifndef PRIM_LOADSZ
+#define PRIM_LOADSZ 15
+#endif
diff --git a/sys/boot/i386/libi386/crt/bootsect/bootsectmain.c b/sys/boot/i386/libi386/crt/bootsect/bootsectmain.c
new file mode 100644
index 0000000..7c48506
--- /dev/null
+++ b/sys/boot/i386/libi386/crt/bootsect/bootsectmain.c
@@ -0,0 +1,88 @@
+/*
+ * $Id$
+ * From: $NetBSD: bootsectmain.c,v 1.1.1.1 1997/03/14 02:40:34 perry Exp $
+ */
+
+/*
+ * Copyright (c) 1996
+ * Matthias Drochner. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ */
+
+/* load remainder of boot program
+ (blocks from fraglist),
+ start main()
+ needs lowlevel parts from biosdisk_ll.c
+ */
+
+#include "biosdisk_ll.h"
+#include "bbinfo.h"
+
+int boot_biosdev; /* exported */
+
+extern struct fraglist fraglist;
+extern char edata[], end[];
+
+extern void main(void);
+
+void bootsectmain(biosdev)
+int biosdev;
+{
+ struct biosdisk_ll d;
+ int i;
+ char *buf;
+
+ /*
+ * load sectors from bootdev
+ */
+ d.dev = biosdev;
+ set_geometry(&d);
+
+ buf = (char*)(PRIM_LOADSZ * BIOSDISK_SECSIZE);
+
+ for(i = 0; i < fraglist.numentries; i++) {
+ int dblk, num;
+
+ dblk = fraglist.entries[i].offset;
+ num = fraglist.entries[i].num;
+
+ if(readsects(&d, dblk, num, buf, 1))
+ return; /* halts in start_bootsect.S */
+
+ buf += num * BIOSDISK_SECSIZE;
+ }
+
+ /* clear BSS */
+ buf = edata;
+ while(buf < end) *buf++ = 0;
+
+ /* call main() */
+ boot_biosdev = biosdev;
+/* main(); */
+}
diff --git a/sys/boot/i386/libi386/crt/bootsect/fraglist.S b/sys/boot/i386/libi386/crt/bootsect/fraglist.S
new file mode 100644
index 0000000..72ddad4
--- /dev/null
+++ b/sys/boot/i386/libi386/crt/bootsect/fraglist.S
@@ -0,0 +1,49 @@
+/* $NetBSD: fraglist.S,v 1.1.1.1 1997/03/14 02:40:34 perry Exp $ */
+
+/*
+ * Copyright (c) 1996
+ * Matthias Drochner. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ */
+
+/* space for fragment list
+ goes to text section - must be loaded by primary boot
+ */
+
+#include "bbinfo.h"
+
+ .text
+
+ .globl _fraglist
+_fraglist:
+ .long FRAGLISTMAGIC
+ .long PRIM_LOADSZ /* blocks already in memory */
+ .long 0
+ .long MAXFLENTRIES
+ . = . + 2 * MAXFLENTRIES * 4
diff --git a/sys/boot/i386/libi386/crt/bootsect/start_bootsect.S b/sys/boot/i386/libi386/crt/bootsect/start_bootsect.S
new file mode 100644
index 0000000..438ae69
--- /dev/null
+++ b/sys/boot/i386/libi386/crt/bootsect/start_bootsect.S
@@ -0,0 +1,540 @@
+/* $NetBSD: start_bootsect.S,v 1.3 1998/02/19 14:15:38 drochner Exp $ */
+
+/* BIOS bootsector startup
+ parts from netbsd:sys/arch/i386/boot/start.S
+ and freebsd:sys/i386/boot/biosboot/boot2.S
+ */
+
+/*
+ * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ *
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+ Copyright 1988, 1989, 1990, 1991, 1992
+ by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include <machine/asm.h>
+#define addr32 .byte 0x67
+#define data32 .byte 0x66
+/* #include <machine/disklabel.h> */
+
+#include "bbinfo.h"
+
+BOOTSEG = 0x0100 # boot will be loaded here (below 640K)
+BOOTSTACK = 0xfffc # boot stack
+LOADSZ = PRIM_LOADSZ # size of first loaded chunk
+
+SIGNATURE = 0xaa55
+PARTSTART = 0x1be # starting address of partition table
+NUMPART = 4 # number of partitions in partition table
+PARTSZ = 16 # sizeof(struct dos_partition)
+BSDPART = 0xA5
+BOOTABLE = 0x80 # value of dp_flag, means bootable partition
+
+ .text
+_boot1:
+ENTRY(start)
+ # start (aka boot1) is loaded at 0x0:0x7c00 but we want 0x7c0:0
+ # ljmp to the next instruction to adjust %cs
+ data32
+ ljmp $0x7c0, $start1
+
+start1:
+ # set up %ds
+ movl %cs, %ax
+ movl %ax, %ds
+
+ # temporary stack while we locate boot2
+ # set up %ss and %esp
+ data32
+ movl $BOOTSEG, %eax
+ movl %ax, %ss
+ data32
+ movl $BOOTSTACK, %esp
+
+ /*** set up %es, (where we will load boot2 to) ***/
+ movl %ax, %es
+
+ # bootstrap passes us drive number in %dl
+ cmpb $0x80, %dl
+ data32
+ jae hd
+
+fd:
+# reset the disk system
+ movb $0x00, %ah
+ int $0x13
+ data32
+ movl $0x0001, %ecx # cyl 0, sector 1
+ movb $0x00, %dh # head
+ # XXX Override the drive number.
+ movb $0x00, %dl
+ data32
+ jmp load
+
+hd: /**** load sector 0 (DOSBBSECTOR) into the BOOTSEG ****/
+ data32
+ movl $0x0201, %eax
+ xorl %ebx, %ebx # %bx = 0
+ data32
+ movl $0x0001, %ecx
+ data32
+ andl $0xff, %edx
+ /*mov $0x0080, %edx*/
+ int $0x13
+ data32
+ jb read_error
+
+ /***# find the first BSD partition *****/
+ data32
+ movl $PARTSTART, %ebx
+ data32
+ movl $NUMPART, %ecx
+again:
+ addr32
+ movb %es:4(%ebx), %al /* dp_typ */
+ cmpb $BSDPART, %al
+ data32
+ je found
+ data32
+ addl $PARTSZ, %ebx
+ data32
+ loop again
+
+ /* didn't find either NetBSD or 386BSD partitions */
+ data32
+ movl $enoboot, %esi
+ data32
+ jmp err_stop
+
+
+/*
+# BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
+# Call with %ah = 0x2
+# %al = number of sectors
+# %ch = cylinder
+# %cl = sector
+# %dh = head
+# %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
+# %es:%bx = segment:offset of buffer
+# Return:
+# %al = 0x0 on success; err code on failure
+*/
+
+found:
+ addr32
+ movb %es:1(%ebx), %dh /* head: dp_sdh */
+ addr32
+ movl %es:2(%ebx), %ecx /*sect, cyl: dp_ssect + (dp_scyl << 8)*/
+
+load:
+ movb $0x2, %ah /* function 2 */
+ movb $LOADSZ, %al /* number of blocks */
+ xorl %ebx, %ebx /* %bx = 0, put it at 0 in the BOOTSEG */
+ int $0x13
+ data32
+ jb read_error
+
+ # ljmp to the second stage boot loader (boot2).
+ # After ljmp, %cs is BOOTSEG and boot1 (512 bytes) will be used
+ # for stack space while we load boot3.
+
+ data32
+ ljmp $BOOTSEG, $CNAME(boot2)
+
+#
+# read_error
+#
+
+read_error:
+ data32
+ movl $eread, %esi
+err_stop:
+ data32
+ call message
+ data32
+ jmp stop
+
+#
+# message: write the error message in %ds:%esi to console
+#
+
+message:
+/*
+# BIOS call "INT 10H Function 0Eh" to write character to console
+# Call with %ah = 0x0e
+# %al = character
+# %bh = page
+# %bl = foreground color
+*/
+ data32
+ pushl %eax
+ data32
+ pushl %ebx
+ data32
+ pushl %edx
+
+nextb:
+ cld
+ lodsb # load a byte into %al
+ testb %al, %al
+ data32
+ jz done
+
+ movb $0x0e, %ah
+ data32
+ movl $0x0001, %ebx
+ int $0x10
+
+ data32
+ jmp nextb
+
+done:
+ data32
+ popl %edx
+ data32
+ popl %ebx
+ data32
+ popl %eax
+ data32
+ ret
+
+_ourseg:
+ .long 0
+
+/**************************************************************************
+GLOBAL DESCRIPTOR TABLE
+**************************************************************************/
+ .align 4
+gdt: /* 0x0 */
+ .word 0, 0
+ .byte 0, 0x00, 0x00, 0
+
+/* additional dummy for Linux support (?) */ /* 0x8 */
+ .word 0, 0
+ .byte 0, 0x00, 0x00, 0
+
+ /* kernel code segment */
+ .globl flatcodeseg
+flatcodeseg = . - gdt /* 0x10 */
+ .word 0xffff, 0
+ .byte 0, 0x9f, 0xcf, 0
+
+ /* kernel data segment */
+ .globl flatdataseg
+flatdataseg = . - gdt /* 0x18 */
+ .word 0xffff, 0
+ .byte 0, 0x93, 0xcf, 0
+
+ /* boot code segment, will be patched */
+bootcodeseg = . - gdt /* 0x20 */
+ .word 0xffff, 0
+ .byte 0, 0x9e, 0x40, 0
+
+ /* boot data segment, will be patched */
+bootdataseg = . - gdt /* 0x28 */
+ .word 0xffff, 0
+ .byte 0, 0x92, 0x0f, 0
+
+ /* 16 bit real mode, will be patched */
+bootrealseg = . - gdt /* 0x30 */
+ .word 0xffff, 0
+ .byte 0, 0x9e, 0x00, 0
+gdtlen = . - gdt
+
+ .align 4
+gdtarg:
+ .word gdtlen-1 /* limit */
+ .long 0 /* addr, will be inserted */
+
+_boot2:
+ data32
+ xorl %eax, %eax
+ movl %cs, %ax
+ movl %ax, %ds
+ movl %ax, %es
+ addr32
+ data32
+ movl %eax, CNAME(ourseg)
+ data32
+ shll $4, %eax
+
+ /* fix up GDT entries for bootstrap */
+#define FIXUP(gdt_index) \
+ addr32; \
+ movl %eax, gdt+gdt_index+2; /* actually movw %ax */ \
+ addr32; \
+ movb %bl, gdt+gdt_index+4
+
+ data32
+ shldl $16, %eax, %ebx
+
+ FIXUP(bootcodeseg)
+ FIXUP(bootrealseg)
+ FIXUP(bootdataseg)
+
+ /* fix up GDT pointer */
+ data32
+ addl $gdt, %eax
+ addr32
+ data32
+ movl %eax, gdtarg+2
+
+ /* change to protected mode */
+ data32
+ call CNAME(real_to_prot)
+
+ /* move the stack over the top of boot1 while we load */
+ movl $_ourseg - 4, %eax
+ movl %eax, %esp
+
+ movzbl %dl, %edx /* discard head (%dh) and random high bits */
+ pushl %edx
+ call CNAME(bootsectmain)
+
+ /* Go to internal stack */
+ movl $CNAME(stacktop), %eax
+ movl %eax, %esp
+ call CNAME(main)
+
+
+ENTRY(exit)
+stop:
+ cli
+ hlt
+
+eread: .asciz "Read error\r\n"
+enoboot: .asciz "No bootable partition\r\n"
+endofcode:
+/* throw in a partition in case we are block0 as well */
+/* flag, head, sec, cyl, typ, ehead, esect, ecyl, start, len */
+ . = CNAME(boot1) + PARTSTART
+ .byte 0x0,0,0,0,0,0,0,0
+ .long 0,0
+ .byte 0x0,0,0,0,0,0,0,0
+ .long 0,0
+ .byte 0x0,0,0,0,0,0,0,0
+ .long 0,0
+ .byte BOOTABLE,0,1,0,BSDPART,255,255,255
+ .long 0,50000
+/* the last 2 bytes in the sector 0 contain the signature */
+ . = CNAME(boot1) + 0x1fe
+ .short SIGNATURE
+ . = CNAME(boot1) + 0x200
+ .globl _disklabel
+_disklabel:
+ . = CNAME(boot1) + 0x400
+
+
+CR0_PE = 0x1
+/*
+ * real_to_prot()
+ * transfer from real mode to protected mode.
+ */
+ENTRY(real_to_prot)
+ # guarantee that interrupt is disabled when in prot mode
+ cli
+
+ # load the gdtr
+ addr32
+ data32
+ lgdt gdtarg
+
+ # set the PE bit of CR0
+ movl %cr0, %eax
+
+ data32
+ orl $CR0_PE, %eax
+ movl %eax, %cr0
+
+ # make intrasegment jump to flush the processor pipeline and
+ # reload CS register
+ data32
+ ljmp $bootcodeseg, $xprot
+
+xprot:
+ # we are in USE32 mode now
+ # set up the protected mode segment registers : DS, SS, ES
+ movl $bootdataseg, %eax
+ movl %ax, %ds
+ movl %ax, %ss
+ movl %ax, %es
+
+ ret
+
+/*
+ * prot_to_real()
+ * transfer from protected mode to real mode
+ */
+ENTRY(prot_to_real)
+ # set up a dummy stack frame for the second seg change.
+ # Adjust the intersegment jump instruction following
+ # the clearing of protected mode bit.
+ # This is self-modifying code, but we need a writable
+ # code segment, and an intersegment return does not give us that.
+
+ movl _ourseg, %eax
+ movw %ax, xreal-2
+
+ # Change to use16 mode.
+ ljmp $bootrealseg, $x16
+
+x16:
+ # clear the PE bit of CR0
+ movl %cr0, %eax
+ data32
+ andl $~CR0_PE, %eax
+ movl %eax, %cr0
+ # Here we have an 16 bits intersegment jump.
+ .byte 0xea
+ .word xreal
+ .word 0
+
+xreal:
+ # we are in real mode now
+ # set up the real mode segment registers : DS, SS, ES
+ movl %cs, %ax
+ movl %ax, %ds
+ movl %ax, %ss
+ movl %ax, %es
+
+ sti
+ data32
+ ret
+
+/*
+ * pbzero(dst, cnt)
+ * where dst is a physical address and cnt is the length
+ */
+ENTRY(pbzero)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %es
+ pushl %edi
+
+ cld
+
+ # set %es to point at the flat segment
+ movl $flatdataseg, %eax
+ movl %ax, %es
+
+ movl 8(%ebp), %edi # destination
+ movl 12(%ebp), %ecx # count
+ xorl %eax, %eax # value
+
+ rep
+ stosb
+
+ popl %edi
+ popl %es
+ popl %ebp
+ ret
+
+/*
+ * vpbcopy(src, dst, cnt)
+ * where src is a virtual address and dst is a physical address
+ */
+ENTRY(vpbcopy)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %es
+ pushl %esi
+ pushl %edi
+
+ cld
+
+ # set %es to point at the flat segment
+ movl $flatdataseg, %eax
+ movl %ax, %es
+
+ movl 8(%ebp), %esi # source
+ movl 12(%ebp), %edi # destination
+ movl 16(%ebp), %ecx # count
+
+ rep
+ movsb
+
+ popl %edi
+ popl %esi
+ popl %es
+ popl %ebp
+ ret
+
+/*
+ * pvbcopy(src, dst, cnt)
+ * where src is a physical address and dst is a virtual address
+ */
+ENTRY(pvbcopy)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %ds
+ pushl %esi
+ pushl %edi
+
+ cld
+
+ # set %ds to point at the flat segment
+ movl $flatdataseg, %eax
+ movl %ax, %ds
+
+ movl 8(%ebp), %esi # source
+ movl 12(%ebp), %edi # destination
+ movl 16(%ebp), %ecx # count
+
+ rep
+ movsb
+
+ popl %edi
+ popl %esi
+ popl %ds
+ popl %ebp
+ ret
+
+ENTRY(vtophys)
+ movl _ourseg, %eax
+ shll $4, %eax
+ addl 4(%esp), %eax
+ ret
diff --git a/sys/boot/i386/libi386/crt/buffers.S b/sys/boot/i386/libi386/crt/buffers.S
new file mode 100644
index 0000000..9ded63c
--- /dev/null
+++ b/sys/boot/i386/libi386/crt/buffers.S
@@ -0,0 +1,27 @@
+/*
+ * Provide buffer space for various items.
+ *
+ * We do this in the text segment so that we can control the location
+ * of the buffers at the link stage, and thus ensure that they are
+ * within reach of the real-mode support routines.
+ *
+ * It is especially important to have the stack down low so that
+ * it is reachable from both 32-bit and 16-bit code.
+ */
+
+#include <machine/asm.h>
+
+ .text
+ .align 4
+ENTRY(diskbuf)
+ . = CNAME(diskbuf) + (DISKBUFSIZE * 512)
+ENTRY(diskbuf_user)
+ .long 0
+ENTRY(diskbuf_size)
+ .long DISKBUFSIZE
+
+ .align 4
+ENTRY(stackbase)
+ . = CNAME(stackbase) + STACKSIZE
+ENTRY(stacktop)
+ .long 0
diff --git a/sys/boot/i386/libi386/crt/diskbuf.h b/sys/boot/i386/libi386/crt/diskbuf.h
new file mode 100644
index 0000000..ad4949c
--- /dev/null
+++ b/sys/boot/i386/libi386/crt/diskbuf.h
@@ -0,0 +1,42 @@
+/*
+ * $Id$
+ * From: $NetBSD: diskbuf.h,v 1.1.1.1 1997/03/14 02:40:32 perry Exp $
+ */
+
+/*
+ * Copyright (c) 1996
+ * Matthias Drochner. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ */
+
+/* data buffer for BIOS disk / DOS I/O */
+
+extern char diskbuf[]; /* client-supplied disk buffer */
+extern void *diskbuf_user; /* using function sets it to unique value to allow check if overwritten*/
+extern int diskbuf_size; /* size of client-supplied buffer in sectors */
diff --git a/sys/boot/i386/libi386/devicename.c b/sys/boot/i386/libi386/devicename.c
new file mode 100644
index 0000000..043589f
--- /dev/null
+++ b/sys/boot/i386/libi386/devicename.c
@@ -0,0 +1,234 @@
+/*-
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <stand.h>
+#include <string.h>
+#include <sys/disklabel.h>
+#include "bootstrap.h"
+#include "libi386.h"
+
+static int i386_parsedev(struct i386_devdesc **dev, char *devspec, char **path);
+
+/*
+ * Point (dev) at an allocated device specifier for the device matching the
+ * path in (devspec). If it contains an explicit device specification,
+ * use that. If not, use the default device.
+ */
+int
+i386_getdev(void **vdev, char *devspec, char **path)
+{
+ struct i386_devdesc **dev = (struct i386_devdesc **)vdev;
+ int rv;
+
+ /*
+ * If it looks like this is just a path and no
+ * device, go with the current device.
+ */
+ if ((devspec == NULL) ||
+ (devspec[0] == '/') ||
+ (strchr(devspec, ':') == NULL)) {
+
+ if (((rv = i386_parsedev(dev, getenv("currdev"), NULL)) == 0) &&
+ (path != NULL))
+ *path = devspec;
+ return(rv);
+ }
+
+ /*
+ * Try to parse the device name off the beginning of the devspec
+ */
+ return(i386_parsedev(dev, devspec, path));
+}
+
+/*
+ * Point (dev) at an allocated device specifier matching the string version
+ * at the beginning of (devspec). Return a pointer to the remaining
+ * text in (path).
+ *
+ * In all cases, the beginning of (devspec) is compared to the names
+ * of known devices in the device switch, and then any following text
+ * is parsed according to the rules applied to the device type.
+ *
+ * For disk-type devices, the syntax is:
+ *
+ * disk<unit>[s<slice>][<partition>]:
+ *
+ */
+static int
+i386_parsedev(struct i386_devdesc **dev, char *devspec, char **path)
+{
+ struct i386_devdesc *idev;
+ struct devsw *dv;
+ int i, unit, slice, partition, err;
+ char *cp, *np;
+
+ /* minimum length check */
+ if (strlen(devspec) < 2)
+ return(EINVAL);
+
+ /* look for a device that matches */
+ for (i = 0, dv = NULL; devsw[i] != NULL; i++) {
+ if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) {
+ dv = devsw[i];
+ break;
+ }
+ }
+ if (dv == NULL)
+ return(ENOENT);
+ idev = malloc(sizeof(struct i386_devdesc));
+ err = 0;
+ np = (devspec + strlen(dv->dv_name));
+
+ switch(dv->dv_type) {
+ case DEVT_NONE: /* XXX what to do here? Do we care? */
+ break;
+
+ case DEVT_DISK:
+ unit = -1;
+ slice = -1;
+ partition = -1;
+ if (*np && (*np != ':')) {
+ unit = strtol(np, &cp, 10); /* next comes the unit number */
+ if (cp == np) {
+ err = EUNIT;
+ goto fail;
+ }
+ if (*cp == 's') { /* got a slice number */
+ np = cp + 1;
+ slice = strtol(np, &cp, 10);
+ if (cp == np) {
+ err = ESLICE;
+ goto fail;
+ }
+ }
+ if (*cp && (*cp != ':')) {
+ partition = *cp - 'a'; /* get a partition number */
+ if ((partition < 0) || (partition >= MAXPARTITIONS)) {
+ err = EPART;
+ goto fail;
+ }
+ cp++;
+ }
+ }
+ if (*cp && (*cp != ':')) {
+ err = EINVAL;
+ goto fail;
+ }
+
+ idev->d_kind.biosdisk.unit = unit;
+ idev->d_kind.biosdisk.slice = slice;
+ idev->d_kind.biosdisk.partition = partition;
+ if (path != NULL)
+ *path = (*cp == 0) ? cp : cp + 1;
+ break;
+
+ case DEVT_NET:
+ unit = 0;
+
+ if (*np && (*np != ':')) {
+ unit = strtol(np, &cp, 0); /* get unit number if present */
+ if (cp == np) {
+ err = EUNIT;
+ goto fail;
+ }
+ }
+ if (*cp && (*cp != ':')) {
+ err = EINVAL;
+ goto fail;
+ }
+
+ idev->d_kind.netif.unit = unit;
+ if (path != NULL)
+ *path = (*cp == 0) ? cp : cp + 1;
+ break;
+
+ default:
+ err = EINVAL;
+ goto fail;
+ }
+ idev->d_dev = dv;
+ idev->d_type = dv->dv_type;
+ if (dev == NULL) {
+ free(idev);
+ } else {
+ *dev = idev;
+ }
+ return(0);
+
+ fail:
+ free(idev);
+ return(err);
+}
+
+
+char *
+i386_fmtdev(void *vdev)
+{
+ struct i386_devdesc *dev = (struct i386_devdesc *)vdev;
+ static char buf[128]; /* XXX device length constant? */
+ char *cp;
+
+ switch(dev->d_type) {
+ case DEVT_NONE:
+ strcpy(buf, "(no device)");
+ break;
+
+ case DEVT_DISK:
+ cp = buf;
+ cp += sprintf(cp, "%s%d", dev->d_dev->dv_name, dev->d_kind.biosdisk.unit);
+ if (dev->d_kind.biosdisk.slice > 0)
+ cp += sprintf(cp, "s%d", dev->d_kind.biosdisk.slice);
+ if (dev->d_kind.biosdisk.partition >= 0)
+ cp += sprintf(cp, "%c", dev->d_kind.biosdisk.partition + 'a');
+ strcat(cp, ":");
+ break;
+
+ case DEVT_NET:
+ sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_kind.netif.unit);
+ break;
+ }
+ return(buf);
+}
+
+
+/*
+ * Set currdev to suit the value being supplied in (value)
+ */
+int
+i386_setcurrdev(struct env_var *ev, int flags, void *value)
+{
+ struct i386_devdesc *ncurr;
+ int rv;
+
+ if ((rv = i386_parsedev(&ncurr, value, NULL)) != 0)
+ return(rv);
+ free(ncurr);
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+ return(0);
+}
+
diff --git a/sys/boot/i386/libi386/gatea20.c b/sys/boot/i386/libi386/gatea20.c
new file mode 100644
index 0000000..bb109db
--- /dev/null
+++ b/sys/boot/i386/libi386/gatea20.c
@@ -0,0 +1,52 @@
+/*
+ * $Id$
+ * From: $NetBSD: gatea20.c,v 1.2 1997/10/29 00:32:49 fvdl Exp $
+ */
+
+/* extracted from freebsd:sys/i386/boot/biosboot/io.c */
+
+#include <sys/types.h>
+#include <machine/cpufunc.h>
+
+#include <stand.h>
+
+#include "libi386.h"
+
+#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
+#define K_STATUS 0x64 /* keyboard status */
+#define K_CMD 0x64 /* keybd ctlr command (write-only) */
+
+#define K_OBUF_FUL 0x01 /* output buffer full */
+#define K_IBUF_FUL 0x02 /* input buffer full */
+
+#define KC_CMD_WIN 0xd0 /* read output port */
+#define KC_CMD_WOUT 0xd1 /* write output port */
+#define KB_A20 0x9f /* enable A20,
+ reset (!),
+ enable output buffer full interrupt
+ enable data line
+ disable clock line */
+
+/*
+ * Gate A20 for high memory
+ */
+static unsigned char x_20 = KB_A20;
+void gateA20()
+{
+ __asm("pushfl ; cli");
+#ifdef IBM_L40
+ outb(0x92, 0x2);
+#else IBM_L40
+ while (inb(K_STATUS) & K_IBUF_FUL);
+ while (inb(K_STATUS) & K_OBUF_FUL)
+ (void)inb(K_RDWR);
+
+ outb(K_CMD, KC_CMD_WOUT);
+ delay(100);
+ while (inb(K_STATUS) & K_IBUF_FUL);
+ outb(K_RDWR, x_20);
+ delay(100);
+ while (inb(K_STATUS) & K_IBUF_FUL);
+#endif IBM_L40
+ __asm("popfl");
+}
diff --git a/sys/boot/i386/libi386/getsecs.c b/sys/boot/i386/libi386/getsecs.c
new file mode 100644
index 0000000..3529c39
--- /dev/null
+++ b/sys/boot/i386/libi386/getsecs.c
@@ -0,0 +1,40 @@
+/*
+ * $Id$
+ * From: $NetBSD: getsecs.c,v 1.1.1.1 1997/03/14 02:40:32 perry Exp $
+ */
+
+/* extracted from netbsd:sys/arch/i386/netboot/misc.c */
+
+#include <sys/types.h>
+#include <stand.h>
+
+#include "libi386.h"
+
+extern int biosgetrtc __P((u_long*));
+
+time_t
+time(time_t *tloc) {
+ /*
+ * Return the current time (of day) in seconds.
+ * XXX should be extended to do it "more right" perhaps?
+ * XXX uses undocumented BCD support from libstand.
+ */
+
+ u_long t;
+ time_t sec;
+
+ if(biosgetrtc(&t))
+ panic("RTC invalid");
+
+ sec = bcd2bin(t & 0xff);
+ sec *= 60;
+ t >>= 8;
+ sec += bcd2bin(t & 0xff);
+ sec *= 60;
+ t >>= 8;
+ sec += bcd2bin(t & 0xff);
+
+ if (tloc != NULL)
+ *tloc = sec;
+ return(sec);
+}
diff --git a/sys/boot/i386/libi386/i386_module.c b/sys/boot/i386/libi386/i386_module.c
new file mode 100644
index 0000000..96eceb9
--- /dev/null
+++ b/sys/boot/i386/libi386/i386_module.c
@@ -0,0 +1,64 @@
+/*-
+ * 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.
+ *
+ * $Id$
+ */
+
+/*
+ * i386-specific module functionality.
+ *
+ */
+
+#include <stand.h>
+#include <string.h>
+
+#include "bootstrap.h"
+#include "libi386.h"
+
+/*
+ * Look for a method and having found it, boot the kernel module.
+ */
+int
+i386_boot(void)
+{
+ int i;
+
+ for (i = 0; module_formats[i] != NULL; i++) {
+ if (((loaded_modules->m_flags & MF_FORMATMASK) == module_formats[i]->l_format) &&
+ (module_formats[i]->l_exec != NULL)) {
+ return((module_formats[i]->l_exec)(loaded_modules));
+ }
+ }
+}
+
+/*
+ * Use voodoo to load modules required by current hardware.
+ */
+int
+i386_autoload(void)
+{
+ /* XXX use PnP to locate stuff here */
+ return(0);
+}
diff --git a/sys/boot/i386/libi386/libi386.h b/sys/boot/i386/libi386/libi386.h
new file mode 100644
index 0000000..300fb35
--- /dev/null
+++ b/sys/boot/i386/libi386/libi386.h
@@ -0,0 +1,86 @@
+/*-
+ * 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * i386 fully-qualified device descriptor.
+ * Note, this must match the 'struct devdesc' declaration
+ * in bootstrap.h.
+ */
+struct i386_devdesc
+{
+ struct devsw *d_dev;
+ int d_type;
+ union
+ {
+ struct
+ {
+ int unit;
+ int slice;
+ int partition;
+ void *data;
+ } biosdisk;
+ struct
+ {
+ int unit; /* XXX net layer lives over these? */
+ } netif;
+ } d_kind;
+};
+
+extern int i386_getdev(void **vdev, char *devspec, char **path);
+extern char *i386_fmtdev(void *vdev);
+extern int i386_setcurrdev(struct env_var *ev, int flags, void *value);
+
+extern struct devdesc currdev; /* our current device */
+
+#define MAXDEV 31 /* maximum number of distinct devices */
+
+/* exported devices XXX rename? */
+extern struct devsw biosdisk;
+
+/* from crt module */
+extern void vpbcopy(void*, vm_offset_t, int);
+extern void pvbcopy(vm_offset_t, void*, int);
+extern void pbzero(vm_offset_t, int);
+extern vm_offset_t vtophys(void*);
+
+extern int pread(int, vm_offset_t, int);
+extern void startprog(vm_offset_t, int, u_int32_t *, vm_offset_t);
+
+extern void delay(int);
+extern int getbasemem(void);
+extern int getextmem(void);
+
+extern void reboot(void);
+extern void gateA20(void);
+
+extern int i386_boot(void);
+extern int i386_autoload(void);
+
+extern int bi_getboothowto(char *kargs);
+extern vm_offset_t bi_copyenv(vm_offset_t addr);
diff --git a/sys/boot/i386/libi386/pread.c b/sys/boot/i386/libi386/pread.c
new file mode 100644
index 0000000..36ffb01
--- /dev/null
+++ b/sys/boot/i386/libi386/pread.c
@@ -0,0 +1,79 @@
+/*
+ * $Id$
+ * From: $NetBSD: pread.c,v 1.2 1997/03/22 01:48:38 thorpej Exp $
+ */
+
+/*
+ * Copyright (c) 1996
+ * Matthias Drochner. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ */
+
+/* read into destination in flat addr space */
+
+#include <stand.h>
+
+#include "libi386.h"
+
+#ifdef SAVE_MEMORY
+#define BUFSIZE (1*1024)
+#else
+#define BUFSIZE (4*1024)
+#endif
+
+static char buf[BUFSIZE];
+
+int
+pread(fd, dest, size)
+ int fd;
+ vm_offset_t dest;
+ int size;
+{
+ int rsize;
+
+ rsize = size;
+ while (rsize > 0) {
+ int count, got;
+
+ count = (rsize < BUFSIZE ? rsize : BUFSIZE);
+
+ got = read(fd, buf, count);
+ if (got < 0)
+ return (-1);
+
+ /* put to physical space */
+ vpbcopy(buf, dest, got);
+
+ dest += got;
+ rsize -= got;
+ if (got < count)
+ break; /* EOF */
+ }
+ return (size - rsize);
+}
diff --git a/sys/boot/i386/libi386/startprog.S b/sys/boot/i386/libi386/startprog.S
new file mode 100644
index 0000000..348341f
--- /dev/null
+++ b/sys/boot/i386/libi386/startprog.S
@@ -0,0 +1,120 @@
+/* $NetBSD: startprog.S,v 1.1.1.1 1997/03/14 02:40:33 perry Exp $ */
+
+/* starts program in protected mode / flat space
+ with given stackframe
+ needs global variables flatcodeseg and flatdataseg
+ (gdt offsets)
+ derivied from: NetBSD:sys/arch/i386/boot/asm.S
+ */
+
+/*
+ * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ *
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+ Copyright 1988, 1989, 1990, 1991, 1992
+ by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include <machine/asm.h>
+
+/*
+ * startprog(phyaddr,argc,argv,stack)
+ * start the program on protected mode where phyaddr is the entry point
+ */
+ENTRY(startprog)
+ pushl %ebp
+ movl %esp, %ebp
+
+ # prepare a new stack
+ movl $flatdataseg, %ebx
+ movw %bx, %es # for arg copy
+ movl 20(%ebp), %eax # stack
+ subl $4,%eax
+ movl %eax, %edi
+
+ # push some number of args onto the stack
+ movl 12(%ebp), %ecx # argc
+
+ movl %ecx, %eax
+ decl %eax
+ shl $2, %eax
+ addl 16(%ebp), %eax # ptr to last arg
+ movl %eax, %esi
+
+ std # backwards
+ rep
+ movsl
+
+ cld # LynxOS depends on it
+
+ movl 8(%ebp), %ecx # entry
+
+ # set new stackptr (movsl decd sp 1 more -> dummy return address)
+ movw %bx, %ss
+ movl %edi, %esp
+
+ # plug in a return address so that FreeBSD detects we are using
+ # bootinfo
+ movl $ourreturn, %eax
+ movl %eax, (%esp)
+
+ # push on our entry address
+ movl $flatcodeseg, %ebx # segment
+ pushl %ebx
+ pushl %ecx #entry
+
+ # convert over the other data segs
+ movl $flatdataseg, %ebx
+ movl %bx, %ds
+ movl %bx, %es
+
+ # convert the PC (and code seg)
+ lret
+
+ourreturn:
+ /* For now there is not much we can do, just lock in a loop */
+ jmp ourreturn
+
diff --git a/sys/boot/i386/libi386/vidconsole.c b/sys/boot/i386/libi386/vidconsole.c
new file mode 100644
index 0000000..f8903a4
--- /dev/null
+++ b/sys/boot/i386/libi386/vidconsole.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 1998 Michael Smith (msmith@freebsd.org)
+ * Copyright (c) 1997 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
+ * 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.
+ *
+ * From Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp
+ *
+ * $Id$
+ */
+
+#include <stand.h>
+
+#include <machine/cpufunc.h>
+
+#include "bootstrap.h"
+
+/* in vidconsole.S */
+extern void vidputc(int c);
+extern int kbdgetc(void);
+extern int kbdiskey(void);
+
+static int probe_keyboard(void);
+static void vidc_probe(struct console *cp);
+static int vidc_init(int arg);
+static int vidc_in(void);
+
+struct console vidconsole = {
+ "vidconsole",
+ "internal video/keyboard",
+ 0,
+ vidc_probe,
+ vidc_init,
+ vidputc,
+ vidc_in,
+ kbdiskey
+};
+
+static void
+vidc_probe(struct console *cp)
+{
+
+ /* look for a keyboard */
+#if 0
+ if (probe_keyboard()) {
+#else
+ if (1) {
+#endif
+ cp->c_flags |= C_PRESENTIN;
+ }
+
+ /* XXX for now, always assume we can do BIOS screen output */
+ cp->c_flags |= C_PRESENTOUT;
+}
+
+static int
+vidc_init(int arg)
+{
+ return(0); /* XXX reinit? */
+}
+
+static int
+vidc_in(void)
+{
+ if (kbdiskey()) {
+ return(kbdgetc());
+ } else {
+ return(-1);
+ }
+}
+
+#define PROBE_MAXRETRY 5
+#define PROBE_MAXWAIT 400
+#define IO_DUMMY 0x84
+#define IO_KBD 0x060 /* 8042 Keyboard */
+
+/* selected defines from kbdio.h */
+#define KBD_STATUS_PORT 4 /* status port, read */
+#define KBD_DATA_PORT 0 /* data port, read/write
+ * also used as keyboard command
+ * and mouse command port
+ */
+#define KBDC_ECHO 0x00ee
+#define KBDS_ANY_BUFFER_FULL 0x0001
+#define KBDS_INPUT_BUFFER_FULL 0x0002
+#define KBD_ECHO 0x00ee
+
+/* 7 microsec delay necessary for some keyboard controllers */
+static void
+delay7(void)
+{
+ /*
+ * I know this is broken, but no timer is avaiable yet at this stage...
+ * See also comments in `delay1ms()'.
+ */
+ inb(IO_DUMMY); inb(IO_DUMMY);
+ inb(IO_DUMMY); inb(IO_DUMMY);
+ inb(IO_DUMMY); inb(IO_DUMMY);
+}
+
+/*
+ * This routine uses an inb to an unused port, the time to execute that
+ * inb is approximately 1.25uS. This value is pretty constant across
+ * all CPU's and all buses, with the exception of some PCI implentations
+ * that do not forward this I/O adress to the ISA bus as they know it
+ * is not a valid ISA bus address, those machines execute this inb in
+ * 60 nS :-(.
+ *
+ */
+static void
+delay1ms(void)
+{
+ int i = 800;
+ while (--i >= 0)
+ (void)inb(0x84);
+}
+
+/*
+ * We use the presence/absence of a keyboard to determine whether the internal
+ * console can be used for input.
+ *
+ * Perform a simple test on the keyboard; issue the ECHO command and see
+ * if the right answer is returned. We don't do anything as drastic as
+ * full keyboard reset; it will be too troublesome and take too much time.
+ */
+static int
+probe_keyboard(void)
+{
+ int retry = PROBE_MAXRETRY;
+ int wait;
+ int i;
+
+ while (--retry >= 0) {
+ /* flush any noise */
+ while (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) {
+ delay7();
+ inb(IO_KBD + KBD_DATA_PORT);
+ delay1ms();
+ }
+
+ /* wait until the controller can accept a command */
+ for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
+ if (((i = inb(IO_KBD + KBD_STATUS_PORT))
+ & (KBDS_INPUT_BUFFER_FULL | KBDS_ANY_BUFFER_FULL)) == 0)
+ break;
+ if (i & KBDS_ANY_BUFFER_FULL) {
+ delay7();
+ inb(IO_KBD + KBD_DATA_PORT);
+ }
+ delay1ms();
+ }
+ if (wait <= 0)
+ continue;
+
+ /* send the ECHO command */
+ outb(IO_KBD + KBD_DATA_PORT, KBDC_ECHO);
+
+ /* wait for a response */
+ for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
+ if (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL)
+ break;
+ delay1ms();
+ }
+ if (wait <= 0)
+ continue;
+
+ delay7();
+ i = inb(IO_KBD + KBD_DATA_PORT);
+#ifdef PROBE_KBD_BEBUG
+ printf("probe_keyboard: got 0x%x.\n", i);
+#endif
+ if (i == KBD_ECHO) {
+ /* got the right answer */
+ return (0);
+ }
+ }
+
+ return (1);
+}
diff --git a/sys/boot/i386/libi386/vidconsole_support.S b/sys/boot/i386/libi386/vidconsole_support.S
new file mode 100644
index 0000000..2b11171
--- /dev/null
+++ b/sys/boot/i386/libi386/vidconsole_support.S
@@ -0,0 +1,103 @@
+/* $Id$ */
+
+/*
+ * PC console handling
+ * originally from: FreeBSD:sys/i386/boot/netboot/start2.S via NetBSD
+ */
+
+#include <machine/asm.h>
+
+#define data32 .byte 0x66
+
+ .text
+
+/**************************************************************************
+PUTC - Print a character
+**************************************************************************/
+ENTRY(vidputc)
+ push %ebp
+ mov %esp,%ebp
+ push %ecx
+ push %ebx
+ push %esi
+ push %edi
+
+ movb 8(%ebp),%cl
+
+ call CNAME(prot_to_real) # enter real mode
+
+ movb %cl,%al
+ data32
+ mov $1,%ebx
+ movb $0x0e,%ah
+ int $0x10
+
+ data32
+ call CNAME(real_to_prot) # back to protected mode
+
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %ecx
+ pop %ebp
+ ret
+
+/**************************************************************************
+GETC - Get a character
+**************************************************************************/
+ENTRY(kbdgetc)
+ push %ebp
+ mov %esp,%ebp
+ push %ebx
+ push %esi
+ push %edi
+
+ call CNAME(prot_to_real) # enter real mode
+
+ movb $0x0,%ah
+ int $0x16
+ movb %al,%bl
+
+ data32
+ call CNAME(real_to_prot) # back to protected mode
+
+ xor %eax,%eax
+ movb %bl,%al
+
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %ebp
+ ret
+
+/**************************************************************************
+ISKEY - Check for keyboard interrupt
+**************************************************************************/
+ENTRY(kbdiskey)
+ push %ebp
+ mov %esp,%ebp
+ push %ebx
+ push %esi
+ push %edi
+
+ call CNAME(prot_to_real) # enter real mode
+
+ xor %ebx,%ebx
+ movb $0x1,%ah
+ int $0x16
+ data32
+ jz 1f
+ movb %al,%bl
+1:
+
+ data32
+ call CNAME(real_to_prot) # back to protected mode
+
+ xor %eax,%eax
+ movb %bl,%al
+
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %ebp
+ ret
diff --git a/sys/boot/i386/loader/Makefile b/sys/boot/i386/loader/Makefile
new file mode 100644
index 0000000..614656e
--- /dev/null
+++ b/sys/boot/i386/loader/Makefile
@@ -0,0 +1,36 @@
+# $Id$
+# from $NetBSD: Makefile,v 1.12 1998/02/19 14:18:36 drochner Exp $
+
+BASE= loader
+PROG= ${BASE}.sym
+NOMAN=
+NEWVERSWHAT= "bootstrap loader"
+
+# architecture-specific loader code
+SRCS+= main.c conf.c
+
+# Always add MI sources
+.PATH: ${.CURDIR}/../../common
+.include <${.CURDIR}/../../common/Makefile.inc>
+CFLAGS+= -I${.CURDIR}/../../common
+# Verbose ls causes extra heap usage
+CFLAGS+= -DVERBOSE_LS
+
+CLEANFILES+= vers.c vers.o ${BASE}.list
+
+CFLAGS+= -Wall
+
+# i386 standalone support library
+LIBI386= ${.OBJDIR}/../libi386/libi386.a
+CFLAGS+= -I${.CURDIR}/..
+CRT= ${.OBJDIR}/../libi386/crt/bootsect/bscrt.o
+
+vers.o:
+ sh ${.CURDIR}/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
+ ${CC} -c vers.c
+
+${BASE}.sym: ${OBJS} ${LIBI386} ${CRT} vers.o
+ ${LD} -o ${BASE}.sym -M -e _start -N -Ttext 0 ${CRT} ${OBJS} \
+ vers.o -lstand ${LIBI386} -lstand >${.OBJDIR}/${BASE}.list
+
+.include <bsd.prog.mk>
diff --git a/sys/boot/i386/loader/conf.c b/sys/boot/i386/loader/conf.c
new file mode 100644
index 0000000..e172c7f
--- /dev/null
+++ b/sys/boot/i386/loader/conf.c
@@ -0,0 +1,85 @@
+/*-
+ * 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.
+ *
+ * $Id$
+ */
+
+#include <stand.h>
+#include <bootstrap.h>
+#include "libi386/libi386.h"
+
+/*
+ * 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.
+ */
+
+/* Exported for libstand */
+struct devsw *devsw[] = {
+ &biosdisk,
+ /* XXX network devices? */
+ NULL
+};
+
+struct fs_ops *file_system[] = {
+ &ufs_fsops,
+#if notyet
+ &dosfs_fsops,
+#endif
+ &zipfs_fsops,
+ 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 module_format i386_aout;
+
+struct module_format *module_formats[] = {
+ &i386_aout,
+ 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;
+
+struct console *consoles[] = {
+ &vidconsole,
+ &comconsole,
+ NULL
+};
diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c
new file mode 100644
index 0000000..ac8bf82
--- /dev/null
+++ b/sys/boot/i386/loader/main.c
@@ -0,0 +1,156 @@
+/*-
+ * 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.
+ *
+ * $Id$
+ */
+
+/*
+ * MD bootstrap main() and assorted miscellaneous
+ * commands.
+ */
+
+#include <stand.h>
+#include <string.h>
+
+#include "bootstrap.h"
+#include "libi386/libi386.h"
+
+extern int boot_biosdev; /* from runtime startup */
+
+struct arch_switch archsw; /* MI/MD interface boundary */
+
+/* from vers.c */
+extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
+
+/* XXX debugging */
+#include "libi386/crt/diskbuf.h"
+extern char stackbase, stacktop;
+extern char end[];
+
+void
+main(void)
+{
+ struct i386_devdesc currdev;
+ int i;
+
+ /*
+ * Initialise the heap as early as possible. Once this is done, alloc() is usable.
+ * The stack is buried inside us, so this is safe
+ */
+ setheap((void *)end, (void *)(end + 0x80000));
+
+ /*
+ * 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.
+ */
+ cons_probe();
+
+ /*
+ * 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("\n");
+ printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
+ printf("(%s, %s)\n", bootprog_maker, bootprog_date);
+ printf("memory: %d/%dkB\n", getbasemem(), getextmem());
+#if 0
+ printf("diskbuf at %p, %d sectors\n", &diskbuf, diskbuf_size);
+ printf("using %d bytes of stack at %p\n", (&stacktop - &stackbase), &stacktop);
+#endif
+
+ /* We're booting from a BIOS disk, try to spiff this */
+ currdev.d_dev = devsw[0]; /* XXX presumes that biosdisk is first in devsw */
+ currdev.d_type = currdev.d_dev->dv_type;
+ currdev.d_kind.biosdisk.unit = boot_biosdev;
+ currdev.d_kind.biosdisk.slice = -1; /* XXX should be able to detect this, default to autoprobe */
+ currdev.d_kind.biosdisk.partition = 0; /* default to 'a' */
+
+ /* Create i386-specific variables */
+
+ env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&currdev), i386_setcurrdev, env_nounset);
+ env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&currdev), env_noset, env_nounset);
+ setenv("LINES", "24", 1); /* optional */
+
+ archsw.arch_autoload = i386_autoload;
+ archsw.arch_boot = i386_boot;
+ archsw.arch_getdev = i386_getdev;
+ /*
+ * XXX should these be in the MI source?
+ */
+ source("/boot/boot.conf");
+#if 0
+ legacy_config(); /* read old /boot.config file */
+#endif
+ printf("\n");
+ autoboot(10, NULL); /* try to boot automatically */
+ printf("\nType '?' for a list of commands, 'help' for more detailed help.\n");
+ setenv("prompt", "$currdev>", 1);
+
+ interact(); /* doesn't return */
+}
+
+COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
+
+static int
+command_reboot(int argc, char *argv[])
+{
+
+ printf("Rebooting...\n");
+ delay(1000000);
+ reboot();
+ /* Note: we shouldn't get to this point! */
+ panic("Reboot failed!");
+ exit(0);
+}
+
+COMMAND_SET(stack, "stack", "show stack usage", command_stack);
+
+static int
+command_stack(int argc, char *argv[])
+{
+ char *cp;
+
+ for (cp = &stackbase; cp < &stacktop; cp++)
+ if (*cp != 0)
+ break;
+
+ printf("%d bytes of stack used\n", &stacktop - cp);
+ return(CMD_OK);
+}
+
+COMMAND_SET(heap, "heap", "show heap usage", command_heap);
+
+static int
+command_heap(int argc, char *argv[])
+{
+ printf("heap base at %p, top at %p, used %d\n", end, sbrk(0), sbrk(0) - end);
+ return(CMD_OK);
+}
diff --git a/sys/boot/i386/loader/newvers.sh b/sys/boot/i386/loader/newvers.sh
new file mode 100755
index 0000000..9330575
--- /dev/null
+++ b/sys/boot/i386/loader/newvers.sh
@@ -0,0 +1,44 @@
+#!/bin/sh -
+#
+# $NetBSD: newvers.sh,v 1.1 1997/07/26 01:50:38 thorpej Exp $
+#
+# Copyright (c) 1984, 1986, 1990, 1993
+# The Regents of the University of California. 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.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+#
+# @(#)newvers.sh 8.1 (Berkeley) 4/20/94
+
+u=${USER-root} h=`hostname` t=`date`
+r=`head -n 6 $1 | tail -n 1 | awk -F: ' { print $1 } '`
+
+echo "char bootprog_name[] = \"FreeBSD/i386 ${2}\";" > vers.c
+echo "char bootprog_rev[] = \"${r}\";" >> vers.c
+echo "char bootprog_date[] = \"${t}\";" >> vers.c
+echo "char bootprog_maker[] = \"${u}@${h}\";" >> vers.c
diff --git a/sys/boot/i386/loader/version b/sys/boot/i386/loader/version
new file mode 100644
index 0000000..df29e4e
--- /dev/null
+++ b/sys/boot/i386/loader/version
@@ -0,0 +1,7 @@
+$Id$
+
+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.
+
+0.1: Initial i386 version, inspiration and some structure from the
+ NetBSD version.
OpenPOWER on IntegriCloud