diff options
author | rnordier <rnordier@FreeBSD.org> | 1999-02-21 21:23:42 +0000 |
---|---|---|
committer | rnordier <rnordier@FreeBSD.org> | 1999-02-21 21:23:42 +0000 |
commit | 5028d48a50af15d2232b9a6c2e085834fdd6f3f9 (patch) | |
tree | d5d6ab97393e97feb7fa8ab3dd4fafa273ad461b | |
parent | c4aec13535e56f9b28426e8a4cc096dab9d9fd9e (diff) | |
download | FreeBSD-src-5028d48a50af15d2232b9a6c2e085834fdd6f3f9.zip FreeBSD-src-5028d48a50af15d2232b9a6c2e085834fdd6f3f9.tar.gz |
Add boot0cfg: this installs/configures the `boot0' boot manager. A
CLI utility to do this has been requested by a few people.
-rw-r--r-- | usr.sbin/boot0cfg/Makefile | 6 | ||||
-rw-r--r-- | usr.sbin/boot0cfg/boot0cfg.8 | 137 | ||||
-rw-r--r-- | usr.sbin/boot0cfg/boot0cfg.c | 267 |
3 files changed, 410 insertions, 0 deletions
diff --git a/usr.sbin/boot0cfg/Makefile b/usr.sbin/boot0cfg/Makefile new file mode 100644 index 0000000..6f965e3 --- /dev/null +++ b/usr.sbin/boot0cfg/Makefile @@ -0,0 +1,6 @@ +# $Id: $ + +PROG= boot0cfg +MAN8= boot0cfg.8 + +.include <bsd.prog.mk> diff --git a/usr.sbin/boot0cfg/boot0cfg.8 b/usr.sbin/boot0cfg/boot0cfg.8 new file mode 100644 index 0000000..28a5d9e --- /dev/null +++ b/usr.sbin/boot0cfg/boot0cfg.8 @@ -0,0 +1,137 @@ +.\" Copyright (c) 1999 Robert Nordier +.\" 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: $ +.\" +.Dd February 21, 1999 +.Dt BOOT0CFG 8 +.Os +.Sh NAME +.Nm boot0cfg +.Nd boot manager installation/configuration utility +.Sh SYNOPSIS +.Nm boot0cfg +.Op Fl Bv +.Op Fl b Ar boot0 +.Op Fl d Ar drive +.Op Fl f Ar file +.Op Fl o Ar options +.Op Fl t Ar ticks +.Ar disk +.Sh DESCRIPTION +The FreeBSD +.Sq boot0 +boot manager permits the operator to select from which disk and which +slice an i386 machine (PC) is booted. +.Pp +Note that what are referred to here as +.Dq slices +are typically called +.Dq partitions +in non-BSD documentation relating to the PC. Typically, only +non-removable disks are sliced. +.Pp +The +.Nm +utility optionally installs the +.Sq boot0 +boot manager on the specified +.Ar disk ; +and allows various operational parameters to be configured. +.Pp +On PCs, a boot manager typically occupies sector 0 of a disk, which is +known as the Master Boot Record (MBR). The MBR contains both code (to +which control is passed by the PC BIOS) and data (an embedded table of +defined slices). +.Pp +The options are: +.Bl -tag -width indent +.It Fl B +Install the +.Sq boot0 +boot manager. This option causes MBR code to be replaced, but without +affecting the embedded slice table. +.It Fl v +Verbose: display information about the slices defined, etc. +.It Fl b Ar boot0 +Specify which +.Sq boot0 +image to use. The default is /boot/boot0. +.It Fl d Ar drive +Specify the drive number used by the PC BIOS in referencing the drive +which contains the specified +.Ar disk . +Typically this will be 0x80 for the first hard drive, 0x81 for the +second hard drive, and so on; however any integer between 0 and 0xff +is acceptable here. +.It Fl f Ar file +Specify that a backup copy of the preexisting MBR should be written to +.Ar file . +This file is created if it does not exist, and truncated if it does. +.It Fl o Ar options +A comma-separated string of any of the following options may be +specified (with +.Dq no +prepended as necessary): +.Bl -tag -width indent +.It packet +Use the disk packet (BIOS Int 0x13 extensions) interface rather than +the conventional (CHS) interface, when accessing disk-related BIOS +services. The default is +.Sq nopacket . +.It setdrv +Causes the drive containing the disk to be referenced using drive +number definable by means of the -d option. The default is +.Sq nosetdrv . +.It update +Allow the MBR to be updated by the boot manager. (The MBR may be +updated to flag slices as +.Sq active , +and to save slice selection information.) This is the default; a +.Sq noupdate +option causes the MBR to be treated as read-only. +.El +.It Fl t Ar secs +Set the timeout value to +.Ar ticks . +(There are approximately 18.2 ticks per second.) +.El +.Sh SEE ALSO +.Xr boot 8 , +.Xr fdisk 8 . +.Sh DIAGNOSTICS +Exit status is 0 on success and >0 on error. +.Sh AUTHORS +.An Robert Nordier Aq rnordier@FreeBSD.org . +.Sh BUGS +Use of the +.Sq packet +option may cause +.Sq boot0 +to fail, depending on the nature of BIOS support. +.Pp +The +.Sq setdrv +option is presently implemented +.Dq syntactically but not semantically . diff --git a/usr.sbin/boot0cfg/boot0cfg.c b/usr.sbin/boot0cfg/boot0cfg.c new file mode 100644 index 0000000..4075023 --- /dev/null +++ b/usr.sbin/boot0cfg/boot0cfg.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 1999 Robert Nordier + * 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. + */ + +#ifndef lint +static const char rcsid[] = +"$Id: $"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/disklabel.h> +#include <sys/stat.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define MBRSIZE 512 /* master boot record size */ + +#define OFF_FLAGS 0x1bb /* offset: option flags */ +#define OFF_TICKS 0x1bc /* offset: clock ticks */ +#define OFF_PTBL 0x1be /* offset: partition table */ +#define OFF_MAGIC 0x1fe /* offset: magic number */ + +#define cv2(p) ((p)[0] | (p)[1] << 010) + +#define mk2(p, x) \ + (p)[0] = (u_int8_t)(x), \ + (p)[1] = (u_int8_t)((x) >> 010) + +static const struct { + const char *tok; + int def; +} opttbl[] = { + {"packet", 0}, + {"update", 1}, + {"setdrv", 0} +}; +static const int nopt = sizeof(opttbl) / sizeof(opttbl[0]); + +static const char fmt0[] = "# flag start chs type" + " end chs offset size\n"; + +static const char fmt1[] = "%d 0x%02x %4u:%3u:%2u 0x%02x" + " %4u:%3u:%2u %10u %10u\n"; + +static void stropt(const char *, int *, int *); +static char *mkrdev(const char *); +static int argtoi(const char *, int, int, int); +static void usage(void); + +int +main(int argc, char *argv[]) +{ + u_int8_t buf[MBRSIZE]; + struct dos_partition part[4]; + const char *bpath, *fpath, *disk; + ssize_t n; + int B_flag, v_flag, o_flag; + int d_arg, t_arg; + int o_and, o_or; + int fd, fd1, up, c, i; + + bpath = "/boot/boot0"; + fpath = NULL; + B_flag = v_flag = o_flag = 0; + d_arg = t_arg = -1; + o_and = 0xff; + o_or = 0; + while ((c = getopt(argc, argv, "Bvb:d:f:o:t:")) != -1) + switch (c) { + case 'B': + B_flag = 1; + break; + case 'v': + v_flag = 1; + break; + case 'b': + bpath = optarg; + break; + case 'd': + d_arg = argtoi(optarg, 0, 0xff, 'd'); + break; + case 'f': + fpath = optarg; + break; + case 'o': + stropt(optarg, &o_and, &o_or); + o_flag = 1; + break; + case 't': + t_arg = argtoi(optarg, 1, 0xffff, 't'); + break; + default: + usage(); + } + argc -= optind; + argv += optind; + if (argc != 1) + usage(); + disk = mkrdev(*argv); + up = B_flag || d_arg || o_flag || t_arg; + if ((fd = open(disk, up ? O_RDWR : O_RDONLY)) == -1) + err(1, "%s", disk); + if ((n = read(fd, buf, MBRSIZE)) == -1) + err(1, "%s", disk); + if (n != MBRSIZE) + errx(1, "%s: short read", disk); + if (cv2(buf + OFF_MAGIC) != 0xaa55) + errx(1, "%s: bad magic", disk); + if (fpath) { + if ((fd1 = open(fpath, O_WRONLY | O_CREAT | O_TRUNC, + 0666)) == -1 || + (n = write(fd1, buf, MBRSIZE)) == -1 || close(fd1)) + err(1, "%s", fpath); + if (n != MBRSIZE) + errx(1, "%s: short write", fpath); + } + memcpy(part, buf + OFF_PTBL, sizeof(part)); + if (B_flag) { + if ((fd1 = open(bpath, O_RDONLY)) == -1 || + (n = read(fd1, buf, MBRSIZE)) == -1 || close(fd1)) + err(1, "%s", bpath); + if (n != MBRSIZE) + errx(1, "%s: short read", bpath); + if (cv2(buf + OFF_MAGIC) != 0xaa55) + errx(1, "%s: bad magic", bpath); + memcpy(buf + OFF_PTBL, part, sizeof(part)); + } + if (o_flag) { + buf[OFF_FLAGS] &= o_and; + buf[OFF_FLAGS] |= o_or; + } + if (t_arg != -1) + mk2(buf + OFF_TICKS, t_arg); + if (up) { + if (lseek(fd, 0, SEEK_SET) == -1 || + (n = write(fd, buf, MBRSIZE)) == -1 || close(fd)) + err(1, "%s", disk); + if (n != MBRSIZE) + errx(1, "%s: short write", disk); + } + if (v_flag) { + printf(fmt0); + for (i = 0; i < 4; i++) + if (part[i].dp_typ) { + printf(fmt1, + 1 + i, + part[i].dp_flag, + part[i].dp_scyl + ((part[i].dp_ssect & 0xc0) << 2), + part[i].dp_shd, + part[i].dp_ssect & 0x3f, + part[i].dp_typ, + part[i].dp_ecyl + ((part[i].dp_esect & 0xc0) << 2), + part[i].dp_ehd, + part[i].dp_esect & 0x3f, + part[i].dp_start, + part[i].dp_size); + } + printf("\n"); + printf("drive=0x0 options="); + for (i = 0; i < nopt; i++) { + if (i) + printf(","); + if (!(buf[OFF_FLAGS] & 1 << (7 - i)) ^ opttbl[i].def) + printf("no"); + printf("%s", opttbl[i].tok); + } + printf(" ticks=%u\n", cv2(buf + OFF_TICKS)); + } + return 0; +} + +static void +stropt(const char *arg, int *xa, int *xo) +{ + const char *q; + char *s, *s1; + int inv, i, x; + + if (!(s = strdup(arg))) + err(1, NULL); + for (s1 = s; (q = strtok(s1, ",")); s1 = NULL) { + if ((inv = !strncmp(q, "no", 2))) + q += 2; + for (i = 0; i < nopt; i++) + if (!strcmp(q, opttbl[i].tok)) + break; + if (i == nopt) + errx(1, "%s: Unknown -o option", q); + if (opttbl[i].def) + inv ^= 1; + x = 1 << (7 - i); + if (inv) + *xa &= ~x; + else + *xo |= x; + } + free(s); +} + +static char * +mkrdev(const char *fname) +{ + char buf[MAXPATHLEN]; + struct stat sb; + char *s; + + s = (char *) fname; + if (!strchr(fname, '/')) { + snprintf(buf, sizeof(buf), "%sr%s", _PATH_DEV, fname); + if (stat(buf, &sb)) + snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname); + if (!(s = strdup(buf))) + err(1, NULL); + } + return s; +} + +static int +argtoi(const char *arg, int lo, int hi, int opt) +{ + char *s; + long x; + + errno = 0; + x = strtol(arg, &s, 0); + if (errno || !*arg || *s || x < lo || x > hi) + errx(1, "%s: Bad argument to -%c option", arg, opt); + return x; +} + +static void +usage(void) +{ + fprintf(stderr, "%s\n%s\n", + "usage: boot0cfg [-Bv] [-b boot0] [-d drive] [-f file] [-o options]", + " [-t ticks] disk"); + exit(1); +} |