diff options
author | msmith <msmith@FreeBSD.org> | 1998-08-21 03:17:42 +0000 |
---|---|---|
committer | msmith <msmith@FreeBSD.org> | 1998-08-21 03:17:42 +0000 |
commit | 8adeb775c43d4c2ae76cce40837a3953af6abc83 (patch) | |
tree | ec778e5f3903abe2dbb59959c0fd8398c99c145b /sys/boot/i386 | |
parent | 335c4be5b17816baac6b70d4d0b3132925de858d (diff) | |
download | FreeBSD-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')
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. |