Bring back disklabel -B for now, since hp300 installboot isn't ready

for prime time yet.
This commit is contained in:
fvdl 2003-11-10 09:22:09 +00:00
parent 8452757ae8
commit fe6b4c315f
3 changed files with 502 additions and 28 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.48 2003/11/08 09:25:01 dsl Exp $
# $NetBSD: Makefile,v 1.49 2003/11/10 09:22:09 fvdl Exp $
# @(#)Makefile 8.2 (Berkeley) 3/17/94
PROG= disklabel
@ -7,6 +7,18 @@ MAN= disklabel.5 disklabel.8
LDADD+= -lutil
DPADD+= ${LIBUTIL}
.if (${MACHINE} == "i386" || ${MACHINE} == "amd64")
# recognize old partition ID for a while
CPPFLAGS+= -DCOMPAT_386BSD_MBRPART
# use MBR partition info
CPPFLAGS+= -DUSE_MBR
.endif
.if (${MACHINE} == "hp300") || (${MACHINE} == "vax") \
|| (${MACHINE} == "arm32")
CPPFLAGS+= -DNUMBOOT=1
.endif
# these have additional requirements on the alignment of a partition
.if (${MACHINE} == "sparc") || (${MACHINE} == "sparc64") \
|| (${MACHINE} == "sun3")
@ -25,7 +37,6 @@ CPPFLAGS+= -DSAVEBOOTAREA
|| (${MACHINE} == "evbarm") || (${MACHINE} == "hpcarm") \
|| (${MACHINE} == "netwinder") || (${MACHINE} == "acorn32") \
|| (${MACHINE} == "cats") || (${MACHINE} == "shark") \
|| (${MACHINE} == "i386") || (${MACHINE} == "amd64") \
|| (${MACHINE} == "playstation2")
# recognize old partition ID for a while
CPPFLAGS+= -DCOMPAT_386BSD_MBRPART

View File

@ -1,4 +1,4 @@
.\" $NetBSD: disklabel.8,v 1.48 2003/11/08 09:25:01 dsl Exp $
.\" $NetBSD: disklabel.8,v 1.49 2003/11/10 09:22:09 fvdl Exp $
.\"
.\" Copyright (c) 1987, 1988, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -32,7 +32,7 @@
.\"
.\" @(#)disklabel.8 8.2 (Berkeley) 4/19/94
.\"
.Dd November 8, 2003
.Dd July 13, 2003
.Dt DISKLABEL 8
.Os
.Sh NAME
@ -67,6 +67,36 @@
.Nm
.Op Fl NW
.Ar disk
.sp
.Nm
.Fl B
.Op Fl f Ar disktab
.Oo
.Fl b Ar boot1
.Op Fl s Ar boot2
.Oc
.Ar disk
.Oo Ar disktype Oc
.Nm
.Fl w
.Fl B
.Op Fl f Ar disktab
.Oo
.Fl b Ar boot1
.Op Fl s Ar boot2
.Oc
.Ar disk Ar disktype
.Oo Ar packid Oc
.Nm
.Fl R
.Fl B
.Op Fl f Ar disktab
.Oo
.Fl b Ar boot1
.Op Fl s Ar boot2
.Oc
.Ar disk Ar protofile
.Oo Ar disktype Oc
.Sh DESCRIPTION
.Nm
can be used to install, examine or modify the label on a disk drive or pack.
@ -74,6 +104,9 @@ When writing the label, it can be used
to change the drive identification,
the disk partitions on the drive,
or to replace a damaged label.
On some systems,
.Nm
can be used to install bootstrap code as well.
.Pp
There are several forms of the command that read (display), install or edit
the label on a disk.
@ -95,6 +128,15 @@ option is similar to the
option but provides defaults instead of failing with
an error, if there is no existing disklabel on the disk.
.Pp
The read and install forms also support the
.Fl B
option to install bootstrap code on some platforms,
e.g., hp300, vax, and arm32.
The
.Fl B
option is not supported on all platforms.
These variants are described later.
.Pp
The first form of the command (read) is used to examine the label on the named
disk drive (e.g., sd0 or /dev/rsd0c).
It will display all of the parameters associated with the drive
@ -191,9 +233,74 @@ flags for
.Nm
explicitly disallow and
allow, respectively, writing of the pack label area on the selected disk.
.Pp
The final three forms of
.Nm
are used to install bootstrap code on machines where the bootstrap is part
of the label.
The bootstrap code is composed of one or two boot programs depending on
the machine.
The
.Fl B
option is used (on some platforms only, see above) to denote that
bootstrap code is to be installed.
The
.Fl r
flag is implied by
.Fl B
and never needs to be specified.
The name of the boot program(s) to be installed can be selected in a
variety of ways.
First, the names can be specified explicitly via the
.Fl b
and
.Fl s
flags.
On machines with only a single level of boot program,
.Fl b
is the name of that program.
For machines with a two-level bootstrap,
.Fl b
indicates the primary boot program and
.Fl s
the secondary boot program.
If the names are not explicitly given, standard boot programs will be used.
The boot programs are located in
.Pa /usr/mdec .
The names of the programs are taken from the
.Dq b0
and
.Dq b1
parameters of the
.Xr disktab 5
entry for the disk if
.Ar disktype
was given and its disktab entry exists and includes those parameters.
Otherwise, boot program names are derived from the name of the disk.
These names are of the form
.Pa basename Ns boot
for the primary (or only) bootstrap, and
.Pf boot Pa basename
for the secondary bootstrap;
for example,
.Pa /usr/mdec/sdboot
and
.Pa /usr/mdec/bootsd
if the disk device is
.Em sd0 .
.Pp
The first of the three boot-installation forms is used to install
bootstrap code without changing the existing label.
It is essentially a read command with respect to the disk label
itself and all options are related to the specification of the boot
program as described previously.
The final two forms are analogous to the basic write and restore versions
except that they will install bootstrap code in addition to a new label.
.Sh FILES
.Bl -tag -width /etc/disktab -compact
.Bl -tag -width /usr/mdec/xxboot -compact
.It Pa /etc/disktab
.It Pa /usr/mdec/ Ns Em xx Ns boot
.It Pa /usr/mdec/boot Ns Em xx
.El
.Sh EXAMPLES
.Dl disklabel sd0
@ -210,6 +317,7 @@ found in
using
.Pa foo
as the disk pack label.
Any existing bootstrap code will be clobbered.
If you do not have an entry for your disk in
.Pa /etc/disktab ,
you can use this style to put
@ -242,9 +350,32 @@ Restore the on-disk and in-core label for sd0 from information in
.Pa mylabel .
Existing bootstrap code is unaffected.
.Pp
.Dl disklabel -B sd0
.Pp
Install a new bootstrap on sd0 (only for platforms which support the
.Fl B
option, see above).
The boot code comes from
.Pa /usr/mdec/sdboot
and possibly
.Pa /usr/mdec/bootsd .
On-disk and in-core labels are unchanged.
.Pp
.Dl disklabel -w -B /dev/rsd0c -b newboot sd2212
.Pp
Install a new label and bootstrap (on platforms which support the
.Fl B
option, see above).
The label is derived from disktab information for
.Dq sd2212
and installed both in-core and on-disk.
The bootstrap code comes from the file
.Pa /usr/mdec/newboot .
.Pp
.Dl disklabel -R -r sd0 \*[Lt]protofile\*[Gt]
.Pp
Install a new label on a disk, from a prototype label file.
Install a new label and bootstrap on a disk, from a prototype label
file.
This is a good way to install a label on a previously unlabeled
disk for which no entry appears in
.Pa /etc/disktab ,
@ -265,6 +396,23 @@ while shrinking the
.Dq a
partition.
.Pp
On some machines the bootstrap code may not fit entirely in the area
allocated for it by some filesystems.
As a result, it may not be possible to have filesystems on some partitions
of a
.Dq bootable
disk.
When installing bootstrap code,
.Nm
checks for these cases.
If the installed boot code would overlap a partition of type FS_UNUSED
it is marked as type FS_BOOT.
The
.Xr newfs 8
utility will disallow creation of filesystems on FS_BOOT partitions.
Conversely, if a partition has a type other than FS_UNUSED or FS_BOOT,
.Nm
will not install bootstrap code that overlaps it.
.Sh SEE ALSO
.Xr disklabel 5 ,
.Xr disktab 5 ,

View File

@ -1,4 +1,4 @@
/* $NetBSD: disklabel.c,v 1.120 2003/11/08 09:25:01 dsl Exp $ */
/* $NetBSD: disklabel.c,v 1.121 2003/11/10 09:22:09 fvdl Exp $ */
/*
* Copyright (c) 1987, 1993
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1987, 1993\n\
static char sccsid[] = "@(#)disklabel.c 8.4 (Berkeley) 5/4/95";
/* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */
#else
__RCSID("$NetBSD: disklabel.c,v 1.120 2003/11/08 09:25:01 dsl Exp $");
__RCSID("$NetBSD: disklabel.c,v 1.121 2003/11/10 09:22:09 fvdl Exp $");
#endif
#endif /* not lint */
@ -90,6 +90,10 @@ __RCSID("$NetBSD: disklabel.c,v 1.120 2003/11/08 09:25:01 dsl Exp $");
#define BBSIZE 8192 /* size of boot area, with label */
#endif
#ifndef NUMBOOT
#define NUMBOOT 0
#endif
#define DEFEDITOR _PATH_VI
static char *dkname;
@ -102,8 +106,20 @@ char bootarea[BBSIZE];
char *specname;
static enum op {
UNSPEC, EDIT, READ, RESTORE, SETWRITABLE, WRITE, INTERACT
#if NUMBOOT > 0
static int installboot; /* non-zero if we should install a boot program */
static char *bootbuf; /* pointer to buffer with remainder of boot prog */
static int bootsize; /* size of remaining boot program */
static char *xxboot; /* primary boot */
static char *bootxx; /* secondary boot */
static char boot0[MAXPATHLEN];
#if NUMBOOT > 1
static char boot1[MAXPATHLEN];
#endif /* NUMBOOT > 1 */
#endif /* NUMBOOT > 0 */
static enum {
UNSPEC, EDIT, READ, RESTORE, SETWRITABLE, WRITE, WRITEBOOT, INTERACT
} op = UNSPEC;
static int rflag;
@ -150,6 +166,9 @@ static int editit(void);
static char *skip(char *);
static char *word(char *);
static int getasciilabel(FILE *, struct disklabel *);
#if NUMBOOT > 0
static void setbootflag(struct disklabel *);
#endif
static void usage(void);
int
@ -158,14 +177,23 @@ main(int argc, char *argv[])
struct disklabel *lp;
FILE *t;
int ch, f, writable, error;
enum op nop;
error = 0;
while ((ch = getopt(argc, argv, OPTIONS)) != -1) {
nop = UNSPEC;
while ((ch = getopt(argc, argv, OPTIONS)) != -1)
switch (ch) {
#if NUMBOOT > 0
case 'B':
errx(1,"use installboot to install bootstrap code");
++installboot;
break;
case 'b':
xxboot = optarg;
break;
#if NUMBOOT > 1
case 's':
bootxx = optarg;
break;
#endif /* NUMBOOT > 1 */
#endif /* NUMBOOT > 0 */
case 'C':
++Cflag;
break;
@ -173,25 +201,35 @@ main(int argc, char *argv[])
++Iflag;
break;
case 'N':
if (op != UNSPEC)
usage();
writable = 0;
nop = SETWRITABLE;
op = SETWRITABLE;
break;
case 'R':
nop = RESTORE;
if (op != UNSPEC)
usage();
op = RESTORE;
break;
case 'W':
if (op != UNSPEC)
usage();
writable = 1;
nop = SETWRITABLE;
op = SETWRITABLE;
break;
case 'e':
nop = EDIT;
if (op != UNSPEC)
usage();
op = EDIT;
break;
case 'f':
if (setdisktab(optarg) == -1)
usage();
break;
case 'i':
nop = INTERACT;
if (op != UNSPEC)
usage();
op = INTERACT;
break;
case 't':
++tflag;
@ -200,7 +238,9 @@ main(int argc, char *argv[])
++rflag;
break;
case 'w':
nop = WRITE;
if (op != UNSPEC)
usage();
op = WRITE;
break;
#ifdef DEBUG
case 'd':
@ -210,18 +250,23 @@ main(int argc, char *argv[])
case '?':
default:
usage();
}
if (nop != UNSPEC) {
if (op != UNSPEC)
usage();
op = nop;
}
}
argc -= optind;
argv += optind;
#if NUMBOOT > 0
if (installboot) {
rflag++;
if (op == UNSPEC)
op = WRITEBOOT;
} else {
if (op == UNSPEC)
op = READ;
}
#else /* NUMBOOT <= 0 */
if (op == UNSPEC)
op = READ;
#endif /* NUMBOOT <= 0 */
if (argc < 1)
usage();
@ -296,6 +341,10 @@ main(int argc, char *argv[])
case RESTORE:
if (argc < 2 || argc > 3)
usage();
#if NUMBOOT > 0
if (installboot && argc == 3)
makelabel(argv[2], (char *)0, &lab);
#endif
lp = makebootarea(bootarea, &lab, f);
if (!(t = fopen(argv[1], "r")))
err(4, "%s", argv[1]);
@ -320,6 +369,25 @@ main(int argc, char *argv[])
error = 1;
break;
case WRITEBOOT:
#if NUMBOOT > 0
{
struct disklabel tlab;
lp = readlabel(f);
tlab = *lp;
if (argc == 2)
makelabel(argv[1], (char *)0, &lab);
lp = makebootarea(bootarea, &lab, f);
*lp = tlab;
if (checklabel(lp) == 0)
error = writelabel(f, bootarea, lp);
else
error = 1;
break;
}
#endif /* NUMBOOT > 0 */
case UNSPEC:
usage();
@ -342,6 +410,35 @@ makelabel(const char *type, const char *name, struct disklabel *lp)
errx(1, "unknown disk type: %s", type);
*lp = *dp;
#if NUMBOOT > 0
/*
* Set bootstrap name(s).
* 1. If set from command line, use those,
* 2. otherwise, check if disktab specifies them (b0 or b1),
* 3. otherwise, makebootarea() will choose ones based on the name
* of the disk special file. E.g. /dev/ra0 -> raboot, bootra
*/
if (!xxboot && lp->d_boot0) {
if (*lp->d_boot0 != '/')
(void)snprintf(boot0, sizeof(boot0), "%s/%s",
_PATH_BOOTDIR, lp->d_boot0);
else
(void)strlcpy(boot0, lp->d_boot0, sizeof(boot0));
xxboot = boot0;
}
#if NUMBOOT > 1
if (!bootxx && lp->d_boot1) {
if (*lp->d_boot1 != '/')
(void)snprintf(boot1, sizeof(boot1), "%s/%s",
_PATH_BOOTDIR, lp->d_boot1);
else
(void)strlcpy(boot1, lp->d_boot1, sizeof(boot1));
bootxx = boot1;
}
#endif /* NUMBOOT > 1 */
#endif /* NUMBOOT > 0 */
/* d_packname is union d_boot[01], so zero */
(void) memset(lp->d_packname, 0, sizeof(lp->d_packname));
if (name)
@ -371,6 +468,9 @@ writelabel(int f, char *boot, struct disklabel *lp)
off_t sectoffset;
sectoffset = 0;
#if NUMBOOT > 0
setbootflag(lp);
#endif
lp->d_magic = DISKMAGIC;
lp->d_magic2 = DISKMAGIC;
lp->d_checksum = 0;
@ -456,6 +556,16 @@ writelabel(int f, char *boot, struct disklabel *lp)
return (1);
}
#if NUMBOOT > 0
/*
* Output the remainder of the disklabel
*/
if (bootbuf && write(f, bootbuf, bootsize) != bootsize) {
perror("write");
return (1);
}
#endif /* NUMBOOT > 0 */
writable = 0;
if (ioctl(f, DIOCWLABEL, &writable) < 0)
perror("ioctl DIOCWLABEL");
@ -830,8 +940,16 @@ static struct disklabel *
makebootarea(char *boot, struct disklabel *dp, int f)
{
struct disklabel *lp;
char *p;
daddr_t lsec;
off_t loff;
#if NUMBOOT > 0
int b;
char *dkbasename;
# if NUMBOOT <= 1
struct stat sb;
# endif
#endif /* NUMBOOT > 0 */
if ((lsec = getlabelsector()) < 0)
err(4, "getlabelsector()");
@ -844,6 +962,7 @@ makebootarea(char *boot, struct disklabel *dp, int f)
dp->d_bbsize = BBSIZE;
}
lp = (struct disklabel *) (boot + (lsec * dp->d_secsize) + loff);
(void) memset(lp, 0, sizeof(*lp));
#ifdef SAVEBOOTAREA
/*
@ -851,12 +970,139 @@ makebootarea(char *boot, struct disklabel *dp, int f)
* existing boot block, if any.
*/
if (rflag || Iflag) {
if (pread(f, boot, BBSIZE, 0) != BBSIZE)
off_t sectoffset;
sectoffset = 0;
if (lseek(f, sectoffset, SEEK_SET) < 0 ||
read(f, boot, BBSIZE) != BBSIZE)
err(4, "%s", specname);
(void) memset(lp, 0, sizeof(*lp));
}
#endif /* SAVEBOOTAREA */
(void) memset(lp, 0, sizeof(*lp));
#if NUMBOOT > 0
/*
* If we are not installing a boot program but we are installing a
* label on disk then we must read the current bootarea so we don't
* clobber the existing boot.
*/
if (!installboot) {
if (rflag || Iflag) {
off_t sectoffset;
sectoffset = 0;
#ifdef USE_MBR
if (dosdp)
sectoffset = (off_t)dosdp->mbrp_start * DEV_BSIZE;
#endif /* USE_MBR */
#ifdef USE_ACORN
/* XXX */
sectoffset = (off_t)filecore_partition_offset
* DEV_BSIZE;
#endif /* USE_ACORN */
if (lseek(f, sectoffset, SEEK_SET) < 0 ||
read(f, boot, BBSIZE) != BBSIZE)
err(4, "%s", specname);
(void) memset(lp, 0, sizeof(*lp));
}
return (lp);
}
/*
* We are installing a boot program. Determine the name(s) and
* read them into the appropriate places in the boot area.
*/
if (!xxboot || !bootxx) {
dkbasename = np;
if ((p = strrchr(dkname, '/')) == NULL)
p = dkname;
else
p++;
while (*p && !isdigit(*p))
*np++ = *p++;
*np++ = '\0';
if (!xxboot) {
(void)sprintf(np, "%s/%sboot",
_PATH_BOOTDIR, dkbasename);
if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
dkbasename++;
xxboot = np;
(void)sprintf(xxboot, "%s/%sboot",
_PATH_BOOTDIR, dkbasename);
np += strlen(xxboot) + 1;
}
#if NUMBOOT > 1
if (!bootxx) {
(void)sprintf(np, "%s/boot%s",
_PATH_BOOTDIR, dkbasename);
if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
dkbasename++;
bootxx = np;
(void)sprintf(bootxx, "%s/boot%s",
_PATH_BOOTDIR, dkbasename);
np += strlen(bootxx) + 1;
}
#endif /* NUMBOOT > 1 */
}
#ifdef DEBUG
if (debug)
warnx("bootstraps: xxboot = %s, bootxx = %s", xxboot,
bootxx ? bootxx : "NONE");
#endif
/*
* Strange rules:
* 1. One-piece bootstrap (hp300/hp800)
* up to d_bbsize bytes of ``xxboot'' go in bootarea, the rest
* is remembered and written later following the bootarea.
* 2. Two-piece bootstraps (vax/i386?/mips?)
* up to d_secsize bytes of ``xxboot'' go in first d_secsize
* bytes of bootarea, remaining d_bbsize-d_secsize filled
* from ``bootxx''.
*/
b = open(xxboot, O_RDONLY);
if (b < 0)
err(4, "%s", xxboot);
#if NUMBOOT > 1
if (read(b, boot, (int)dp->d_secsize) < 0)
err(4, "%s", xxboot);
(void)close(b);
b = open(bootxx, O_RDONLY);
if (b < 0)
err(4, "%s", bootxx);
if (read(b, &boot[dp->d_secsize],
(int)(dp->d_bbsize-dp->d_secsize)) < 0)
err(4, "%s", bootxx);
#else /* NUMBOOT <= 1 */
if (read(b, boot, (int)dp->d_bbsize) < 0)
err(4, "%s", xxboot);
(void)fstat(b, &sb);
bootsize = (int)sb.st_size - dp->d_bbsize;
if (bootsize > 0) {
/* XXX assume d_secsize is a power of two */
bootsize = (bootsize + dp->d_secsize-1) & ~(dp->d_secsize-1);
bootbuf = (char *)malloc((size_t)bootsize);
if (bootbuf == 0)
err(4, "%s", xxboot);
if (read(b, bootbuf, bootsize) < 0) {
free(bootbuf);
err(4, "%s", xxboot);
}
}
#endif /* NUMBOOT <= 1 */
(void)close(b);
#endif /* NUMBOOT > 0 */
/*
* Make sure no part of the bootstrap is written in the area
* reserved for the label.
*/
for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
if (*p)
errx(2, "Bootstrap doesn't leave room for disk label");
return (lp);
}
@ -1533,6 +1779,50 @@ checklabel(struct disklabel *lp)
return (errors);
}
#if NUMBOOT > 0
/*
* If we are installing a boot program that doesn't fit in d_bbsize
* we need to mark those partitions that the boot overflows into.
* This allows newfs to prevent creation of a filesystem where it might
* clobber bootstrap code.
*/
static void
setbootflag(struct disklabel *lp)
{
struct partition *pp;
int i, errors;
char part;
u_long boffset;
errors = 0;
if (bootbuf == 0)
return;
boffset = bootsize / lp->d_secsize;
for (i = 0; i < lp->d_npartitions; i++) {
part = 'a' + i;
pp = &lp->d_partitions[i];
if (pp->p_size == 0)
continue;
if (boffset <= pp->p_offset) {
if (pp->p_fstype == FS_BOOT)
pp->p_fstype = FS_UNUSED;
} else if (pp->p_fstype != FS_BOOT) {
if (pp->p_fstype != FS_UNUSED) {
warnx("boot overlaps used partition %c",
part);
errors++;
} else {
pp->p_fstype = FS_BOOT;
warnx("warning, boot overlaps partition %c, %s",
part, "marked as FS_BOOT");
}
}
}
if (errors)
errx(4, "cannot install boot program");
}
#endif /* NUMBOOT > 0 */
static void
usage(void)
{
@ -1543,15 +1833,40 @@ usage(void)
{ "[-rt] [-C] disk",
"(to read label)" },
{ "-w [-r] [-f disktab] disk type [ packid ]",
#if NUMBOOT > 0
"(to write label with existing boot program)"
#else
"(to write label)"
#endif
},
{ "-e [-r] [-I] [-C] disk",
"(to edit label)" },
{ "-i [-I] [-r] disk",
"(to create a label interactively)" },
{ "-R [-r] disk protofile",
#if NUMBOOT > 0
"(to restore label with existing boot program)"
#else
"(to restore label)"
#endif
},
#if NUMBOOT > 0
# if NUMBOOT > 1
{ "-B [-f disktab] [ -b xxboot [ -s bootxx ] ] disk [ type ]",
"(to install boot program with existing label)" },
{ "-w -B [-f disktab] [ -b xxboot [ -s bootxx ] ] disk type [ packid ]",
"(to write label and boot program)" },
{ "-R -B [-f disktab] [ -b xxboot [ -s bootxx ] ] disk protofile [ type ]",
"(to restore label and boot program)" },
# else
{ "-B [-f disktab] [ -b bootprog ] disk [ type ]",
"(to install boot program with existing on-disk label)" },
{ "-w -B [-f disktab] [ -b bootprog ] disk type [ packid ]",
"(to write label and install boot program)" },
{ "-R -B [-f disktab] [ -b bootprog ] disk protofile [ type ]",
"(to restore label and install boot program)" },
# endif
#endif
{ "[-NW] disk",
"(to write disable/enable label)" },
{ NULL,