Teach disklabel(8) about different hardware architectures.

This is aimed at creating floppies during cross-releases.
For different endianness machines, a tool like bswapfs(8)
is necessary to make the generated floppies readable on
the target machine.  While here, fixed unaligned access
on Alphas.

Tested on:	i386, alpha
This commit is contained in:
Ruslan Ermilov 2003-03-16 00:11:49 +00:00
parent d647b74e54
commit bc33ea1acc
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=112307
4 changed files with 452 additions and 212 deletions

View File

@ -48,31 +48,37 @@
.Nm .Nm
.Fl w .Fl w
.Op Fl nr .Op Fl nr
.Ar disk disktype Ns | Ns Cm auto .Op Fl m Ar machine
.Ar disk type
.Op Ar packid .Op Ar packid
.Nm .Nm
.Fl e .Fl e
.Op Fl nr .Op Fl nr
.Op Fl m Ar machine
.Ar disk .Ar disk
.Nm .Nm
.Fl R .Fl R
.Op Fl nr .Op Fl nr
.Op Fl m Ar machine
.Ar disk protofile .Ar disk protofile
.Pp .Pp
.Nm .Nm
.Fl B .Fl B
.Op Fl b Ar boot .Op Fl b Ar boot
.Op Fl m Ar machine
.Ar disk .Ar disk
.Nm .Nm
.Fl w B .Fl w B
.Op Fl n .Op Fl n
.Op Fl b Ar boot .Op Fl b Ar boot
.Ar disk disktype Ns | Ns Cm auto .Op Fl m Ar machine
.Ar disk type
.Op Ar packid .Op Ar packid
.Nm .Nm
.Fl R B .Fl R B
.Op Fl n .Op Fl n
.Op Fl b Ar boot .Op Fl b Ar boot
.Op Fl m Ar machine
.Ar disk protofile .Ar disk protofile
.Sh DESCRIPTION .Sh DESCRIPTION
The The
@ -167,7 +173,8 @@ To write a standard label, use the form
.Nm .Nm
.Fl w .Fl w
.Op Fl nr .Op Fl nr
.Ar disk disktype Ns | Ns Cm auto .Op Fl m Ar machine
.Ar disk type
.Op Ar packid .Op Ar packid
.Pp .Pp
The required arguments to The required arguments to
@ -187,6 +194,13 @@ The
.Ar packid .Ar packid
must be quoted if it contains blanks. must be quoted if it contains blanks.
.Pp .Pp
If the
.Fl m
option is given, then label will be written so that
it is understood by the target
.Ar machine ;
defaults to the current hardware architecture.
.Pp
If If
.Fl n .Fl n
is used, no data will be written to the device, and instead the is used, no data will be written to the device, and instead the
@ -199,7 +213,7 @@ will be written directly.
A side-effect of this is that any existing bootstrap code will be overwritten A side-effect of this is that any existing bootstrap code will be overwritten
and the disk rendered unbootable. and the disk rendered unbootable.
See the boot options below for a method of See the boot options below for a method of
writing the label and the bootstrap at the same time. writing the and the bootstrap at the same time.
If If
.Fl r .Fl r
is not specified, is not specified,
@ -212,7 +226,7 @@ In either case, the kernel's in-core label is replaced.
.Pp .Pp
For a virgin disk that is not known to For a virgin disk that is not known to
.Xr disktab 5 , .Xr disktab 5 ,
.Ar disktype .Ar type
can be specified as can be specified as
.Cm auto . .Cm auto .
In this case, the driver is requested to produce a virgin label for the In this case, the driver is requested to produce a virgin label for the
@ -270,6 +284,7 @@ To edit an existing disk label, use the form
.Nm .Nm
.Fl e .Fl e
.Op Fl nr .Op Fl nr
.Op Fl m Ar machine
.Ar disk .Ar disk
.Pp .Pp
This command reads the label from the in-core kernel copy, or directly from the This command reads the label from the in-core kernel copy, or directly from the
@ -288,6 +303,14 @@ When the editor terminates, the label file is used to rewrite the disk label.
Existing bootstrap code is unchanged regardless of whether Existing bootstrap code is unchanged regardless of whether
.Fl r .Fl r
was specified. was specified.
.Pp
If the
.Fl m
option is given, then the label will be written so that
it is understood by the target
.Ar machine ;
defaults to the current hardware architecture.
.Pp
If If
.Fl n .Fl n
is used, no data will be written to the device, and instead the is used, no data will be written to the device, and instead the
@ -300,6 +323,7 @@ To restore a disk label from a file, use the form
.Nm .Nm
.Fl R .Fl R
.Op Fl nr .Op Fl nr
.Op Fl m Ar machine
.Ar disk protofile .Ar disk protofile
.Pp .Pp
.Nm .Nm
@ -317,6 +341,14 @@ clobbered if
is specified, and will be unaffected otherwise. is specified, and will be unaffected otherwise.
See the boot options below for a See the boot options below for a
method of restoring the label and writing the bootstrap at the same time. method of restoring the label and writing the bootstrap at the same time.
.Pp
If the
.Fl m
option is given, then the label will be written so that
it is understood by the target
.Ar machine ;
defaults to the current hardware architecture.
.Pp
If If
.Fl n .Fl n
is used, no data will be written to the device, and instead the is used, no data will be written to the device, and instead the
@ -345,6 +377,7 @@ on the base disk should probably be updated; see
.Nm .Nm
.Fl B .Fl B
.Op Fl b Ar boot .Op Fl b Ar boot
.Op Fl m Ar machine
.Ar disk .Ar disk
.Pp .Pp
This form installs the bootstrap only. This form installs the bootstrap only.
@ -357,11 +390,18 @@ disk.
This command is typically run on a slice such as This command is typically run on a slice such as
.Pa da0s1 . .Pa da0s1 .
.Pp .Pp
The
.Fl m
option should be specified if the label was
created for a different hardware architecture,
.Ar machine .
.Pp
.Nm .Nm
.Fl w B .Fl w B
.Op Fl n .Op Fl n
.Op Fl b Ar boot .Op Fl b Ar boot
.Ar disk disktype Ns | Ns Cm auto .Op Fl m Ar machine
.Ar disk type
.Op Ar packid .Op Ar packid
.Pp .Pp
This form corresponds to the This form corresponds to the
@ -372,6 +412,14 @@ If run on a base disk, this command will create a
.Dq dangerously-dedicated .Dq dangerously-dedicated
label. label.
This command is normally run on a slice rather than a base disk. This command is normally run on a slice rather than a base disk.
.Pp
If the
.Fl m
option is given, then the label and bootstrap will be written so that
they are understood by the target
.Ar machine ;
defaults to the current hardware architecture.
.Pp
If If
.Fl n .Fl n
is used, no data will be written to the device, and instead the is used, no data will be written to the device, and instead the
@ -381,6 +429,7 @@ disk label that would have been written will be printed to standard output.
.Fl R B .Fl R B
.Op Fl n .Op Fl n
.Op Fl b Ar boot .Op Fl b Ar boot
.Op Fl m Ar machine
.Ar disk protofile .Ar disk protofile
.Pp .Pp
This form corresponds to the This form corresponds to the
@ -396,6 +445,14 @@ The bootstrap commands always access the disk directly, so it is not necessary
to specify the to specify the
.Fl r .Fl r
option. option.
.Pp
If the
.Fl m
option is given, then the label and bootstrap will be written so that
they are understood by the target
.Ar machine ;
defaults to the current hardware architecture.
.Pp
If If
.Fl n .Fl n
is used, no data will be written to the device, and instead the is used, no data will be written to the device, and instead the

View File

@ -64,11 +64,35 @@ __FBSDID("$FreeBSD$");
#define DKTYPENAMES #define DKTYPENAMES
#define FSTYPENAMES #define FSTYPENAMES
#include <sys/disklabel.h> #include <sys/disklabel.h>
#ifdef PC98
#include <sys/diskpc98.h>
#else
#include <sys/diskmbr.h> #include <sys/diskmbr.h>
#if (DOSPARTOFF != 446 || NDOSPART != 4 || DOSPTYP_386BSD != 0xa5)
#error <sys/diskmbr.h> has changed
#else
#define I386_DOSPARTOFF 446
#define I386_NDOSPART 4
#define I386_DOSPTYP_386BSD 0xa5
#endif #endif
#undef DOSPARTOFF
#undef NDOSPART
#undef DOSPTYP_386BSD
#include <sys/diskpc98.h>
#if (DOSPARTOFF != 0 || NDOSPART != 16 || DOSPTYP_386BSD != 0x94)
#error <sys/diskpc98.h> has changed
#else
#define PC98_DOSPARTOFF 0
#define PC98_NDOSPART 16
#define PC98_DOSPTYP_386BSD 0x94
#endif
#undef DOSPARTOFF
#undef NDOSPART
#undef DOSPTYP_386BSD
#define IS_PC98 (arch->mach == MACH_PC98)
#define DOSPARTOFF (IS_PC98 ? PC98_DOSPARTOFF : I386_DOSPARTOFF)
#define NDOSPART (IS_PC98 ? PC98_NDOSPART : I386_NDOSPART)
#define DOSPTYP_386BSD (IS_PC98 ? PC98_DOSPTYP_386BSD : I386_DOSPTYP_386BSD)
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
@ -104,18 +128,11 @@ __FBSDID("$FreeBSD$");
#define BIG_NEWFS_FRAG 2048U #define BIG_NEWFS_FRAG 2048U
#define BIG_NEWFS_CPG 64U #define BIG_NEWFS_CPG 64U
#if defined(__i386__)
#elif defined(__alpha__)
#elif defined(__ia64__)
#else
#error I do not know about this architecture, and shall probably not be compiled for it.
#endif
void makelabel(const char *, const char *, struct disklabel *); void makelabel(const char *, const char *, struct disklabel *);
int writelabel(int, const char *, struct disklabel *); int writelabel(int, void *, struct disklabel *);
void l_perror(const char *); void l_perror(const char *);
struct disklabel *readlabel(int); struct disklabel *readlabel(int);
struct disklabel *makebootarea(char *, struct disklabel *, int); struct disklabel *makebootarea(void *, struct disklabel *, int);
void display(FILE *, const struct disklabel *); void display(FILE *, const struct disklabel *);
int edit(struct disklabel *, int); int edit(struct disklabel *, int);
int editit(void); int editit(void);
@ -137,7 +154,7 @@ char tmpfil[] = PATH_TMPFILE;
char namebuf[BBSIZE], *np = namebuf; char namebuf[BBSIZE], *np = namebuf;
struct disklabel lab; struct disklabel lab;
char bootarea[BBSIZE]; int64_t bootarea[BBSIZE / 8];
char blank[] = ""; char blank[] = "";
char unknown[] = "unknown"; char unknown[] = "unknown";
@ -155,20 +172,36 @@ enum {
UNSPEC, EDIT, READ, RESTORE, WRITE, WRITEBOOT UNSPEC, EDIT, READ, RESTORE, WRITE, WRITEBOOT
} op = UNSPEC; } op = UNSPEC;
enum { ARCH_I386, ARCH_ALPHA, ARCH_IA64 };
enum { MACH_I386, MACH_PC98 };
struct {
const char *name;
int arch;
int mach;
off_t label_sector;
off_t label_offset;
} arches[] = {
{ "i386", ARCH_I386, MACH_I386, 1, 0 },
{ "pc98", ARCH_I386, MACH_PC98, 1, 0 },
{ "alpha", ARCH_ALPHA, ARCH_ALPHA, 0, 64 },
{ "ia64", ARCH_IA64, ARCH_IA64, 1, 0 },
}, *arch;
#define NARCHES (int)(sizeof(arches) / sizeof(*arches))
int rflag; int rflag;
int disable_write; /* set to disable writing to disk label */ int disable_write; /* set to disable writing to disk label */
#define OPTIONS "BRb:enrs:w"
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
struct disklabel *lp; struct disklabel *lp;
FILE *t; FILE *t;
int ch, f = 0, error = 0; int ch, f = 0, error = 0, i;
char *name = 0; char *name = 0;
while ((ch = getopt(argc, argv, OPTIONS)) != -1) while ((ch = getopt(argc, argv, "Bb:em:nRrs:w")) != -1)
switch (ch) { switch (ch) {
case 'B': case 'B':
++installboot; ++installboot;
@ -176,6 +209,15 @@ main(int argc, char *argv[])
case 'b': case 'b':
xxboot = optarg; xxboot = optarg;
break; break;
case 'm':
for (i = 0; i < NARCHES &&
strcmp(arches[i].name, optarg) != 0;
i++);
if (i == NARCHES)
errx(1, "%s: unknown architecture",
optarg);
arch = &arches[i];
break;
case 'n': case 'n':
disable_write = 1; disable_write = 1;
break; break;
@ -215,6 +257,30 @@ main(int argc, char *argv[])
if (argc < 1) if (argc < 1)
usage(); usage();
if (arch == NULL) {
for (i = 0; i < NARCHES; i++)
if (strcmp(arches[i].name,
#if defined(__i386__)
#ifdef PC98
"pc98"
#else
"i386"
#endif
#elif defined(__alpha__)
"alpha"
#elif defined(__ia64__)
"ia64"
#else
"unknown"
#endif
) == 0) {
arch = &arches[i];
break;
}
if (i == NARCHES)
errx(1, "unsupported architecture");
}
dkname = argv[0]; dkname = argv[0];
if (dkname[0] != '/') { if (dkname[0] != '/') {
(void)sprintf(np, "%s%s%c", _PATH_DEV, dkname, 'a' + RAW_PART); (void)sprintf(np, "%s%s%c", _PATH_DEV, dkname, 'a' + RAW_PART);
@ -320,12 +386,10 @@ makelabel(const char *type, const char *name, struct disklabel *lp)
} }
int int
writelabel(int f, const char *boot, struct disklabel *lp) writelabel(int f, void *boot, struct disklabel *lp)
{ {
#ifdef __alpha__ uint64_t *p, sum;
u_long *p, sum;
int i; int i;
#endif
if (disable_write) { if (disable_write) {
Warning("write to disk label supressed - label was as follows:"); Warning("write to disk label supressed - label was as follows:");
@ -360,14 +424,14 @@ writelabel(int f, const char *boot, struct disklabel *lp)
} }
(void)lseek(f, (off_t)0, SEEK_SET); (void)lseek(f, (off_t)0, SEEK_SET);
#ifdef __alpha__ if (arch->arch == ARCH_ALPHA) {
/* /*
* Generate the bootblock checksum for the SRM console. * Generate the bootblock checksum for the SRM console.
*/ */
for (p = (u_long *)boot, i = 0, sum = 0; i < 63; i++) for (p = (uint64_t *)boot, i = 0, sum = 0; i < 63; i++)
sum += p[i]; sum += p[i];
p[63] = sum; p[63] = sum;
#endif }
if (ioctl(f, DIOCBSDBB, &boot) == 0) if (ioctl(f, DIOCBSDBB, &boot) == 0)
return (0); return (0);
if (write(f, boot, lp->d_bbsize) != (int)lp->d_bbsize) { if (write(f, boot, lp->d_bbsize) != (int)lp->d_bbsize) {
@ -420,12 +484,14 @@ readlabel(int f)
if (read(f, bootarea, BBSIZE) < BBSIZE) if (read(f, bootarea, BBSIZE) < BBSIZE)
err(4, "%s", specname); err(4, "%s", specname);
for (lp = (struct disklabel *)bootarea; for (lp = (struct disklabel *)bootarea;
lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); lp <= (struct disklabel *)
((char *)bootarea + BBSIZE - sizeof(*lp));
lp = (struct disklabel *)((char *)lp + 16)) lp = (struct disklabel *)((char *)lp + 16))
if (lp->d_magic == DISKMAGIC && if (lp->d_magic == DISKMAGIC &&
lp->d_magic2 == DISKMAGIC) lp->d_magic2 == DISKMAGIC)
break; break;
if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || if (lp > (struct disklabel *)
((char *)bootarea + BBSIZE - sizeof(*lp)) ||
lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
dkcksum(lp) != 0) dkcksum(lp) != 0)
errx(1, errx(1,
@ -443,21 +509,17 @@ readlabel(int f)
* Returns a pointer to the disklabel portion of the bootarea. * Returns a pointer to the disklabel portion of the bootarea.
*/ */
struct disklabel * struct disklabel *
makebootarea(char *boot, struct disklabel *dp, int f) makebootarea(void *boot, struct disklabel *dp, int f)
{ {
struct disklabel *lp; struct disklabel *lp;
char *p; char *p;
int b; int b;
char *dkbasename; char *dkbasename;
struct stat sb; struct stat sb;
#ifdef __alpha__ uint64_t *bootinfo;
u_long *bootinfo;
int n; int n;
#endif
#ifdef __i386__
char *tmpbuf; char *tmpbuf;
int i, found, dps; int i, found, dps;
#endif
/* XXX */ /* XXX */
if (dp->d_secsize == 0) { if (dp->d_secsize == 0) {
@ -465,7 +527,8 @@ makebootarea(char *boot, struct disklabel *dp, int f)
dp->d_bbsize = BBSIZE; dp->d_bbsize = BBSIZE;
} }
lp = (struct disklabel *) lp = (struct disklabel *)
(boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET); ((char *)boot + (arch->label_sector * dp->d_secsize) +
arch->label_offset);
bzero((char *)lp, sizeof *lp); bzero((char *)lp, sizeof *lp);
/* /*
* If we are not installing a boot program but we are installing a * If we are not installing a boot program but we are installing a
@ -505,57 +568,55 @@ makebootarea(char *boot, struct disklabel *dp, int f)
err(4, "%s", xxboot); err(4, "%s", xxboot);
if (fstat(b, &sb) != 0) if (fstat(b, &sb) != 0)
err(4, "%s", xxboot); err(4, "%s", xxboot);
#ifdef __i386__ if (arch->arch == ARCH_I386) {
if (sb.st_size > BBSIZE) if (sb.st_size > BBSIZE)
errx(4, "%s too large", xxboot); errx(4, "%s too large", xxboot);
/* /*
* XXX Botch alert. * XXX Botch alert.
* The i386/PC98 has the so-called fdisk table embedded into the * The i386/PC98 has the so-called fdisk table embedded into the
* primary bootstrap. We take care to not clobber it, but * primary bootstrap. We take care to not clobber it, but
* only if it does already contain some data. (Otherwise, * only if it does already contain some data. (Otherwise,
* the xxboot provides a template.) * the xxboot provides a template.)
*/ */
if ((tmpbuf = (char *)malloc((int)dp->d_secsize)) == 0) if ((tmpbuf = (char *)malloc((int)dp->d_secsize)) == 0)
err(4, "%s", xxboot); err(4, "%s", xxboot);
memcpy((void *)tmpbuf, (void *)boot, (int)dp->d_secsize); memcpy((void *)tmpbuf, (void *)boot, (int)dp->d_secsize);
if (read(b, boot, BBSIZE) < 0) if (read(b, boot, BBSIZE) < 0)
err(4, "%s", xxboot); err(4, "%s", xxboot);
/* XXX: rely on some very precise overlaps in definitions */ /* XXX: rely on some very precise overlaps in definitions */
#ifdef PC98 dps = IS_PC98 ? sizeof(struct pc98_partition) :
dps = sizeof(struct pc98_partition); sizeof(struct dos_partition);
#else for (i = DOSPARTOFF, found = 0;
dps = sizeof(struct dos_partition); !found && i < (int)(DOSPARTOFF + NDOSPART * dps);
#endif i++)
for (i = DOSPARTOFF, found = 0; found = tmpbuf[i] != 0;
!found && i < (int)(DOSPARTOFF + NDOSPART * dps); if (found)
i++) memcpy((void *)&((char *)boot)[DOSPARTOFF],
found = tmpbuf[i] != 0; (void *)&tmpbuf[DOSPARTOFF],
if (found) NDOSPART * dps);
memcpy((void *)&boot[DOSPARTOFF], free(tmpbuf);
(void *)&tmpbuf[DOSPARTOFF], }
NDOSPART * dps);
free(tmpbuf);
#endif /* __i386__ */
#ifdef __alpha__ if (arch->arch == ARCH_ALPHA) {
if (sb.st_size > BBSIZE - dp->d_secsize) if (sb.st_size > BBSIZE - dp->d_secsize)
errx(4, "%s too large", xxboot); errx(4, "%s too large", xxboot);
/* /*
* On the alpha, the primary bootstrap starts at the * On the alpha, the primary bootstrap starts at the
* second sector of the boot area. The first sector * second sector of the boot area. The first sector
* contains the label and must be edited to contain the * contains the label and must be edited to contain the
* size and location of the primary bootstrap. * size and location of the primary bootstrap.
*/ */
n = read(b, boot + dp->d_secsize, BBSIZE - dp->d_secsize); n = read(b, (char *)boot + dp->d_secsize,
if (n < 0) BBSIZE - dp->d_secsize);
err(4, "%s", xxboot); if (n < 0)
bootinfo = (u_long *)(boot + 480); err(4, "%s", xxboot);
bootinfo[0] = (n + dp->d_secsize - 1) / dp->d_secsize; bootinfo = (uint64_t *)((char *)boot + 480);
bootinfo[1] = 1; /* start at sector 1 */ bootinfo[0] = (n + dp->d_secsize - 1) / dp->d_secsize;
bootinfo[2] = 0; /* flags (must be zero) */ bootinfo[1] = 1; /* start at sector 1 */
#endif /* __alpha__ */ bootinfo[2] = 0; /* flags (must be zero) */
}
(void)close(b); (void)close(b);
/* /*
@ -1495,20 +1556,22 @@ Warning(const char *fmt, ...)
void void
usage(void) usage(void)
{ {
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
"usage: disklabel [-r] disk", fprintf(stderr,
"\t\t(to read label)", "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
" disklabel -w [-r] [-n] disk type [ packid ]", "usage: disklabel [-r] disk",
"\t\t(to write label with existing boot program)", "\t\t(to read label)",
" disklabel -e [-r] [-n] disk", " disklabel -w [-nr] [-m machine] disk type [packid]",
"\t\t(to edit label)", "\t\t(to write label with existing boot program)",
" disklabel -R [-r] [-n] disk protofile", " disklabel -e [-nr] [-m machine] disk",
"\t\t(to restore label with existing boot program)", "\t\t(to edit label)",
" disklabel -B [-n] [ -b bootprog ] disk [ type ]", " disklabel -R [-nr] [-m machine] disk protofile",
"\t\t(to install boot program with existing on-disk label)", "\t\t(to restore label with existing boot program)",
" disklabel -w -B [-n] [ -b bootprog ] disk type [ packid ]", " disklabel -B [-b boot] [-m machine] disk",
"\t\t(to write label and install boot program)", "\t\t(to install boot program with existing on-disk label)",
" disklabel -R -B [-n] [ -b bootprog ] disk protofile", " disklabel -w -B [-n] [-b boot] [-m machine] disk type [packid]",
"\t\t(to write label and install boot program)",
" disklabel -R -B [-n] [-b boot] [-m machine] disk protofile",
"\t\t(to restore label and install boot program)" "\t\t(to restore label and install boot program)"
); );
exit(1); exit(1);

View File

@ -48,31 +48,37 @@
.Nm .Nm
.Fl w .Fl w
.Op Fl nr .Op Fl nr
.Ar disk disktype Ns | Ns Cm auto .Op Fl m Ar machine
.Ar disk type
.Op Ar packid .Op Ar packid
.Nm .Nm
.Fl e .Fl e
.Op Fl nr .Op Fl nr
.Op Fl m Ar machine
.Ar disk .Ar disk
.Nm .Nm
.Fl R .Fl R
.Op Fl nr .Op Fl nr
.Op Fl m Ar machine
.Ar disk protofile .Ar disk protofile
.Pp .Pp
.Nm .Nm
.Fl B .Fl B
.Op Fl b Ar boot .Op Fl b Ar boot
.Op Fl m Ar machine
.Ar disk .Ar disk
.Nm .Nm
.Fl w B .Fl w B
.Op Fl n .Op Fl n
.Op Fl b Ar boot .Op Fl b Ar boot
.Ar disk disktype Ns | Ns Cm auto .Op Fl m Ar machine
.Ar disk type
.Op Ar packid .Op Ar packid
.Nm .Nm
.Fl R B .Fl R B
.Op Fl n .Op Fl n
.Op Fl b Ar boot .Op Fl b Ar boot
.Op Fl m Ar machine
.Ar disk protofile .Ar disk protofile
.Sh DESCRIPTION .Sh DESCRIPTION
The The
@ -167,7 +173,8 @@ To write a standard label, use the form
.Nm .Nm
.Fl w .Fl w
.Op Fl nr .Op Fl nr
.Ar disk disktype Ns | Ns Cm auto .Op Fl m Ar machine
.Ar disk type
.Op Ar packid .Op Ar packid
.Pp .Pp
The required arguments to The required arguments to
@ -187,6 +194,13 @@ The
.Ar packid .Ar packid
must be quoted if it contains blanks. must be quoted if it contains blanks.
.Pp .Pp
If the
.Fl m
option is given, then label will be written so that
it is understood by the target
.Ar machine ;
defaults to the current hardware architecture.
.Pp
If If
.Fl n .Fl n
is used, no data will be written to the device, and instead the is used, no data will be written to the device, and instead the
@ -199,7 +213,7 @@ will be written directly.
A side-effect of this is that any existing bootstrap code will be overwritten A side-effect of this is that any existing bootstrap code will be overwritten
and the disk rendered unbootable. and the disk rendered unbootable.
See the boot options below for a method of See the boot options below for a method of
writing the label and the bootstrap at the same time. writing the and the bootstrap at the same time.
If If
.Fl r .Fl r
is not specified, is not specified,
@ -212,7 +226,7 @@ In either case, the kernel's in-core label is replaced.
.Pp .Pp
For a virgin disk that is not known to For a virgin disk that is not known to
.Xr disktab 5 , .Xr disktab 5 ,
.Ar disktype .Ar type
can be specified as can be specified as
.Cm auto . .Cm auto .
In this case, the driver is requested to produce a virgin label for the In this case, the driver is requested to produce a virgin label for the
@ -270,6 +284,7 @@ To edit an existing disk label, use the form
.Nm .Nm
.Fl e .Fl e
.Op Fl nr .Op Fl nr
.Op Fl m Ar machine
.Ar disk .Ar disk
.Pp .Pp
This command reads the label from the in-core kernel copy, or directly from the This command reads the label from the in-core kernel copy, or directly from the
@ -288,6 +303,14 @@ When the editor terminates, the label file is used to rewrite the disk label.
Existing bootstrap code is unchanged regardless of whether Existing bootstrap code is unchanged regardless of whether
.Fl r .Fl r
was specified. was specified.
.Pp
If the
.Fl m
option is given, then the label will be written so that
it is understood by the target
.Ar machine ;
defaults to the current hardware architecture.
.Pp
If If
.Fl n .Fl n
is used, no data will be written to the device, and instead the is used, no data will be written to the device, and instead the
@ -300,6 +323,7 @@ To restore a disk label from a file, use the form
.Nm .Nm
.Fl R .Fl R
.Op Fl nr .Op Fl nr
.Op Fl m Ar machine
.Ar disk protofile .Ar disk protofile
.Pp .Pp
.Nm .Nm
@ -317,6 +341,14 @@ clobbered if
is specified, and will be unaffected otherwise. is specified, and will be unaffected otherwise.
See the boot options below for a See the boot options below for a
method of restoring the label and writing the bootstrap at the same time. method of restoring the label and writing the bootstrap at the same time.
.Pp
If the
.Fl m
option is given, then the label will be written so that
it is understood by the target
.Ar machine ;
defaults to the current hardware architecture.
.Pp
If If
.Fl n .Fl n
is used, no data will be written to the device, and instead the is used, no data will be written to the device, and instead the
@ -345,6 +377,7 @@ on the base disk should probably be updated; see
.Nm .Nm
.Fl B .Fl B
.Op Fl b Ar boot .Op Fl b Ar boot
.Op Fl m Ar machine
.Ar disk .Ar disk
.Pp .Pp
This form installs the bootstrap only. This form installs the bootstrap only.
@ -357,11 +390,18 @@ disk.
This command is typically run on a slice such as This command is typically run on a slice such as
.Pa da0s1 . .Pa da0s1 .
.Pp .Pp
The
.Fl m
option should be specified if the label was
created for a different hardware architecture,
.Ar machine .
.Pp
.Nm .Nm
.Fl w B .Fl w B
.Op Fl n .Op Fl n
.Op Fl b Ar boot .Op Fl b Ar boot
.Ar disk disktype Ns | Ns Cm auto .Op Fl m Ar machine
.Ar disk type
.Op Ar packid .Op Ar packid
.Pp .Pp
This form corresponds to the This form corresponds to the
@ -372,6 +412,14 @@ If run on a base disk, this command will create a
.Dq dangerously-dedicated .Dq dangerously-dedicated
label. label.
This command is normally run on a slice rather than a base disk. This command is normally run on a slice rather than a base disk.
.Pp
If the
.Fl m
option is given, then the label and bootstrap will be written so that
they are understood by the target
.Ar machine ;
defaults to the current hardware architecture.
.Pp
If If
.Fl n .Fl n
is used, no data will be written to the device, and instead the is used, no data will be written to the device, and instead the
@ -381,6 +429,7 @@ disk label that would have been written will be printed to standard output.
.Fl R B .Fl R B
.Op Fl n .Op Fl n
.Op Fl b Ar boot .Op Fl b Ar boot
.Op Fl m Ar machine
.Ar disk protofile .Ar disk protofile
.Pp .Pp
This form corresponds to the This form corresponds to the
@ -396,6 +445,14 @@ The bootstrap commands always access the disk directly, so it is not necessary
to specify the to specify the
.Fl r .Fl r
option. option.
.Pp
If the
.Fl m
option is given, then the label and bootstrap will be written so that
they are understood by the target
.Ar machine ;
defaults to the current hardware architecture.
.Pp
If If
.Fl n .Fl n
is used, no data will be written to the device, and instead the is used, no data will be written to the device, and instead the

View File

@ -64,11 +64,35 @@ __FBSDID("$FreeBSD$");
#define DKTYPENAMES #define DKTYPENAMES
#define FSTYPENAMES #define FSTYPENAMES
#include <sys/disklabel.h> #include <sys/disklabel.h>
#ifdef PC98
#include <sys/diskpc98.h>
#else
#include <sys/diskmbr.h> #include <sys/diskmbr.h>
#if (DOSPARTOFF != 446 || NDOSPART != 4 || DOSPTYP_386BSD != 0xa5)
#error <sys/diskmbr.h> has changed
#else
#define I386_DOSPARTOFF 446
#define I386_NDOSPART 4
#define I386_DOSPTYP_386BSD 0xa5
#endif #endif
#undef DOSPARTOFF
#undef NDOSPART
#undef DOSPTYP_386BSD
#include <sys/diskpc98.h>
#if (DOSPARTOFF != 0 || NDOSPART != 16 || DOSPTYP_386BSD != 0x94)
#error <sys/diskpc98.h> has changed
#else
#define PC98_DOSPARTOFF 0
#define PC98_NDOSPART 16
#define PC98_DOSPTYP_386BSD 0x94
#endif
#undef DOSPARTOFF
#undef NDOSPART
#undef DOSPTYP_386BSD
#define IS_PC98 (arch->mach == MACH_PC98)
#define DOSPARTOFF (IS_PC98 ? PC98_DOSPARTOFF : I386_DOSPARTOFF)
#define NDOSPART (IS_PC98 ? PC98_NDOSPART : I386_NDOSPART)
#define DOSPTYP_386BSD (IS_PC98 ? PC98_DOSPTYP_386BSD : I386_DOSPTYP_386BSD)
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
@ -104,18 +128,11 @@ __FBSDID("$FreeBSD$");
#define BIG_NEWFS_FRAG 2048U #define BIG_NEWFS_FRAG 2048U
#define BIG_NEWFS_CPG 64U #define BIG_NEWFS_CPG 64U
#if defined(__i386__)
#elif defined(__alpha__)
#elif defined(__ia64__)
#else
#error I do not know about this architecture, and shall probably not be compiled for it.
#endif
void makelabel(const char *, const char *, struct disklabel *); void makelabel(const char *, const char *, struct disklabel *);
int writelabel(int, const char *, struct disklabel *); int writelabel(int, void *, struct disklabel *);
void l_perror(const char *); void l_perror(const char *);
struct disklabel *readlabel(int); struct disklabel *readlabel(int);
struct disklabel *makebootarea(char *, struct disklabel *, int); struct disklabel *makebootarea(void *, struct disklabel *, int);
void display(FILE *, const struct disklabel *); void display(FILE *, const struct disklabel *);
int edit(struct disklabel *, int); int edit(struct disklabel *, int);
int editit(void); int editit(void);
@ -137,7 +154,7 @@ char tmpfil[] = PATH_TMPFILE;
char namebuf[BBSIZE], *np = namebuf; char namebuf[BBSIZE], *np = namebuf;
struct disklabel lab; struct disklabel lab;
char bootarea[BBSIZE]; int64_t bootarea[BBSIZE / 8];
char blank[] = ""; char blank[] = "";
char unknown[] = "unknown"; char unknown[] = "unknown";
@ -155,20 +172,36 @@ enum {
UNSPEC, EDIT, READ, RESTORE, WRITE, WRITEBOOT UNSPEC, EDIT, READ, RESTORE, WRITE, WRITEBOOT
} op = UNSPEC; } op = UNSPEC;
enum { ARCH_I386, ARCH_ALPHA, ARCH_IA64 };
enum { MACH_I386, MACH_PC98 };
struct {
const char *name;
int arch;
int mach;
off_t label_sector;
off_t label_offset;
} arches[] = {
{ "i386", ARCH_I386, MACH_I386, 1, 0 },
{ "pc98", ARCH_I386, MACH_PC98, 1, 0 },
{ "alpha", ARCH_ALPHA, ARCH_ALPHA, 0, 64 },
{ "ia64", ARCH_IA64, ARCH_IA64, 1, 0 },
}, *arch;
#define NARCHES (int)(sizeof(arches) / sizeof(*arches))
int rflag; int rflag;
int disable_write; /* set to disable writing to disk label */ int disable_write; /* set to disable writing to disk label */
#define OPTIONS "BRb:enrs:w"
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
struct disklabel *lp; struct disklabel *lp;
FILE *t; FILE *t;
int ch, f = 0, error = 0; int ch, f = 0, error = 0, i;
char *name = 0; char *name = 0;
while ((ch = getopt(argc, argv, OPTIONS)) != -1) while ((ch = getopt(argc, argv, "Bb:em:nRrs:w")) != -1)
switch (ch) { switch (ch) {
case 'B': case 'B':
++installboot; ++installboot;
@ -176,6 +209,15 @@ main(int argc, char *argv[])
case 'b': case 'b':
xxboot = optarg; xxboot = optarg;
break; break;
case 'm':
for (i = 0; i < NARCHES &&
strcmp(arches[i].name, optarg) != 0;
i++);
if (i == NARCHES)
errx(1, "%s: unknown architecture",
optarg);
arch = &arches[i];
break;
case 'n': case 'n':
disable_write = 1; disable_write = 1;
break; break;
@ -215,6 +257,30 @@ main(int argc, char *argv[])
if (argc < 1) if (argc < 1)
usage(); usage();
if (arch == NULL) {
for (i = 0; i < NARCHES; i++)
if (strcmp(arches[i].name,
#if defined(__i386__)
#ifdef PC98
"pc98"
#else
"i386"
#endif
#elif defined(__alpha__)
"alpha"
#elif defined(__ia64__)
"ia64"
#else
"unknown"
#endif
) == 0) {
arch = &arches[i];
break;
}
if (i == NARCHES)
errx(1, "unsupported architecture");
}
dkname = argv[0]; dkname = argv[0];
if (dkname[0] != '/') { if (dkname[0] != '/') {
(void)sprintf(np, "%s%s%c", _PATH_DEV, dkname, 'a' + RAW_PART); (void)sprintf(np, "%s%s%c", _PATH_DEV, dkname, 'a' + RAW_PART);
@ -320,12 +386,10 @@ makelabel(const char *type, const char *name, struct disklabel *lp)
} }
int int
writelabel(int f, const char *boot, struct disklabel *lp) writelabel(int f, void *boot, struct disklabel *lp)
{ {
#ifdef __alpha__ uint64_t *p, sum;
u_long *p, sum;
int i; int i;
#endif
if (disable_write) { if (disable_write) {
Warning("write to disk label supressed - label was as follows:"); Warning("write to disk label supressed - label was as follows:");
@ -360,14 +424,14 @@ writelabel(int f, const char *boot, struct disklabel *lp)
} }
(void)lseek(f, (off_t)0, SEEK_SET); (void)lseek(f, (off_t)0, SEEK_SET);
#ifdef __alpha__ if (arch->arch == ARCH_ALPHA) {
/* /*
* Generate the bootblock checksum for the SRM console. * Generate the bootblock checksum for the SRM console.
*/ */
for (p = (u_long *)boot, i = 0, sum = 0; i < 63; i++) for (p = (uint64_t *)boot, i = 0, sum = 0; i < 63; i++)
sum += p[i]; sum += p[i];
p[63] = sum; p[63] = sum;
#endif }
if (ioctl(f, DIOCBSDBB, &boot) == 0) if (ioctl(f, DIOCBSDBB, &boot) == 0)
return (0); return (0);
if (write(f, boot, lp->d_bbsize) != (int)lp->d_bbsize) { if (write(f, boot, lp->d_bbsize) != (int)lp->d_bbsize) {
@ -420,12 +484,14 @@ readlabel(int f)
if (read(f, bootarea, BBSIZE) < BBSIZE) if (read(f, bootarea, BBSIZE) < BBSIZE)
err(4, "%s", specname); err(4, "%s", specname);
for (lp = (struct disklabel *)bootarea; for (lp = (struct disklabel *)bootarea;
lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); lp <= (struct disklabel *)
((char *)bootarea + BBSIZE - sizeof(*lp));
lp = (struct disklabel *)((char *)lp + 16)) lp = (struct disklabel *)((char *)lp + 16))
if (lp->d_magic == DISKMAGIC && if (lp->d_magic == DISKMAGIC &&
lp->d_magic2 == DISKMAGIC) lp->d_magic2 == DISKMAGIC)
break; break;
if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || if (lp > (struct disklabel *)
((char *)bootarea + BBSIZE - sizeof(*lp)) ||
lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
dkcksum(lp) != 0) dkcksum(lp) != 0)
errx(1, errx(1,
@ -443,21 +509,17 @@ readlabel(int f)
* Returns a pointer to the disklabel portion of the bootarea. * Returns a pointer to the disklabel portion of the bootarea.
*/ */
struct disklabel * struct disklabel *
makebootarea(char *boot, struct disklabel *dp, int f) makebootarea(void *boot, struct disklabel *dp, int f)
{ {
struct disklabel *lp; struct disklabel *lp;
char *p; char *p;
int b; int b;
char *dkbasename; char *dkbasename;
struct stat sb; struct stat sb;
#ifdef __alpha__ uint64_t *bootinfo;
u_long *bootinfo;
int n; int n;
#endif
#ifdef __i386__
char *tmpbuf; char *tmpbuf;
int i, found, dps; int i, found, dps;
#endif
/* XXX */ /* XXX */
if (dp->d_secsize == 0) { if (dp->d_secsize == 0) {
@ -465,7 +527,8 @@ makebootarea(char *boot, struct disklabel *dp, int f)
dp->d_bbsize = BBSIZE; dp->d_bbsize = BBSIZE;
} }
lp = (struct disklabel *) lp = (struct disklabel *)
(boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET); ((char *)boot + (arch->label_sector * dp->d_secsize) +
arch->label_offset);
bzero((char *)lp, sizeof *lp); bzero((char *)lp, sizeof *lp);
/* /*
* If we are not installing a boot program but we are installing a * If we are not installing a boot program but we are installing a
@ -505,57 +568,55 @@ makebootarea(char *boot, struct disklabel *dp, int f)
err(4, "%s", xxboot); err(4, "%s", xxboot);
if (fstat(b, &sb) != 0) if (fstat(b, &sb) != 0)
err(4, "%s", xxboot); err(4, "%s", xxboot);
#ifdef __i386__ if (arch->arch == ARCH_I386) {
if (sb.st_size > BBSIZE) if (sb.st_size > BBSIZE)
errx(4, "%s too large", xxboot); errx(4, "%s too large", xxboot);
/* /*
* XXX Botch alert. * XXX Botch alert.
* The i386/PC98 has the so-called fdisk table embedded into the * The i386/PC98 has the so-called fdisk table embedded into the
* primary bootstrap. We take care to not clobber it, but * primary bootstrap. We take care to not clobber it, but
* only if it does already contain some data. (Otherwise, * only if it does already contain some data. (Otherwise,
* the xxboot provides a template.) * the xxboot provides a template.)
*/ */
if ((tmpbuf = (char *)malloc((int)dp->d_secsize)) == 0) if ((tmpbuf = (char *)malloc((int)dp->d_secsize)) == 0)
err(4, "%s", xxboot); err(4, "%s", xxboot);
memcpy((void *)tmpbuf, (void *)boot, (int)dp->d_secsize); memcpy((void *)tmpbuf, (void *)boot, (int)dp->d_secsize);
if (read(b, boot, BBSIZE) < 0) if (read(b, boot, BBSIZE) < 0)
err(4, "%s", xxboot); err(4, "%s", xxboot);
/* XXX: rely on some very precise overlaps in definitions */ /* XXX: rely on some very precise overlaps in definitions */
#ifdef PC98 dps = IS_PC98 ? sizeof(struct pc98_partition) :
dps = sizeof(struct pc98_partition); sizeof(struct dos_partition);
#else for (i = DOSPARTOFF, found = 0;
dps = sizeof(struct dos_partition); !found && i < (int)(DOSPARTOFF + NDOSPART * dps);
#endif i++)
for (i = DOSPARTOFF, found = 0; found = tmpbuf[i] != 0;
!found && i < (int)(DOSPARTOFF + NDOSPART * dps); if (found)
i++) memcpy((void *)&((char *)boot)[DOSPARTOFF],
found = tmpbuf[i] != 0; (void *)&tmpbuf[DOSPARTOFF],
if (found) NDOSPART * dps);
memcpy((void *)&boot[DOSPARTOFF], free(tmpbuf);
(void *)&tmpbuf[DOSPARTOFF], }
NDOSPART * dps);
free(tmpbuf);
#endif /* __i386__ */
#ifdef __alpha__ if (arch->arch == ARCH_ALPHA) {
if (sb.st_size > BBSIZE - dp->d_secsize) if (sb.st_size > BBSIZE - dp->d_secsize)
errx(4, "%s too large", xxboot); errx(4, "%s too large", xxboot);
/* /*
* On the alpha, the primary bootstrap starts at the * On the alpha, the primary bootstrap starts at the
* second sector of the boot area. The first sector * second sector of the boot area. The first sector
* contains the label and must be edited to contain the * contains the label and must be edited to contain the
* size and location of the primary bootstrap. * size and location of the primary bootstrap.
*/ */
n = read(b, boot + dp->d_secsize, BBSIZE - dp->d_secsize); n = read(b, (char *)boot + dp->d_secsize,
if (n < 0) BBSIZE - dp->d_secsize);
err(4, "%s", xxboot); if (n < 0)
bootinfo = (u_long *)(boot + 480); err(4, "%s", xxboot);
bootinfo[0] = (n + dp->d_secsize - 1) / dp->d_secsize; bootinfo = (uint64_t *)((char *)boot + 480);
bootinfo[1] = 1; /* start at sector 1 */ bootinfo[0] = (n + dp->d_secsize - 1) / dp->d_secsize;
bootinfo[2] = 0; /* flags (must be zero) */ bootinfo[1] = 1; /* start at sector 1 */
#endif /* __alpha__ */ bootinfo[2] = 0; /* flags (must be zero) */
}
(void)close(b); (void)close(b);
/* /*
@ -1495,20 +1556,22 @@ Warning(const char *fmt, ...)
void void
usage(void) usage(void)
{ {
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
"usage: disklabel [-r] disk", fprintf(stderr,
"\t\t(to read label)", "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
" disklabel -w [-r] [-n] disk type [ packid ]", "usage: disklabel [-r] disk",
"\t\t(to write label with existing boot program)", "\t\t(to read label)",
" disklabel -e [-r] [-n] disk", " disklabel -w [-nr] [-m machine] disk type [packid]",
"\t\t(to edit label)", "\t\t(to write label with existing boot program)",
" disklabel -R [-r] [-n] disk protofile", " disklabel -e [-nr] [-m machine] disk",
"\t\t(to restore label with existing boot program)", "\t\t(to edit label)",
" disklabel -B [-n] [ -b bootprog ] disk [ type ]", " disklabel -R [-nr] [-m machine] disk protofile",
"\t\t(to install boot program with existing on-disk label)", "\t\t(to restore label with existing boot program)",
" disklabel -w -B [-n] [ -b bootprog ] disk type [ packid ]", " disklabel -B [-b boot] [-m machine] disk",
"\t\t(to write label and install boot program)", "\t\t(to install boot program with existing on-disk label)",
" disklabel -R -B [-n] [ -b bootprog ] disk protofile", " disklabel -w -B [-n] [-b boot] [-m machine] disk type [packid]",
"\t\t(to write label and install boot program)",
" disklabel -R -B [-n] [-b boot] [-m machine] disk protofile",
"\t\t(to restore label and install boot program)" "\t\t(to restore label and install boot program)"
); );
exit(1); exit(1);