Add boot0cfg: this installs/configures the `boot0' boot manager. A

CLI utility to do this has been requested by a few people.
This commit is contained in:
rnordier 1999-02-21 21:23:42 +00:00
parent c4aec13535
commit 5028d48a50
3 changed files with 410 additions and 0 deletions

View File

@ -0,0 +1,6 @@
# $Id: $
PROG= boot0cfg
MAN8= boot0cfg.8
.include <bsd.prog.mk>

View File

@ -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 .

View File

@ -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);
}