From bc33ea1acc76c96c94f8a9a97cd48c8d34a8e020 Mon Sep 17 00:00:00 2001 From: Ruslan Ermilov Date: Sun, 16 Mar 2003 00:11:49 +0000 Subject: [PATCH] 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 --- sbin/bsdlabel/bsdlabel.8 | 69 +++++++++- sbin/bsdlabel/bsdlabel.c | 263 +++++++++++++++++++++++-------------- sbin/disklabel/disklabel.8 | 69 +++++++++- sbin/disklabel/disklabel.c | 263 +++++++++++++++++++++++-------------- 4 files changed, 452 insertions(+), 212 deletions(-) diff --git a/sbin/bsdlabel/bsdlabel.8 b/sbin/bsdlabel/bsdlabel.8 index 6a57d4035ade..3ca49ff90bdf 100644 --- a/sbin/bsdlabel/bsdlabel.8 +++ b/sbin/bsdlabel/bsdlabel.8 @@ -48,31 +48,37 @@ .Nm .Fl w .Op Fl nr -.Ar disk disktype Ns | Ns Cm auto +.Op Fl m Ar machine +.Ar disk type .Op Ar packid .Nm .Fl e .Op Fl nr +.Op Fl m Ar machine .Ar disk .Nm .Fl R .Op Fl nr +.Op Fl m Ar machine .Ar disk protofile .Pp .Nm .Fl B .Op Fl b Ar boot +.Op Fl m Ar machine .Ar disk .Nm .Fl w B .Op Fl n .Op Fl b Ar boot -.Ar disk disktype Ns | Ns Cm auto +.Op Fl m Ar machine +.Ar disk type .Op Ar packid .Nm .Fl R B .Op Fl n .Op Fl b Ar boot +.Op Fl m Ar machine .Ar disk protofile .Sh DESCRIPTION The @@ -167,7 +173,8 @@ To write a standard label, use the form .Nm .Fl w .Op Fl nr -.Ar disk disktype Ns | Ns Cm auto +.Op Fl m Ar machine +.Ar disk type .Op Ar packid .Pp The required arguments to @@ -187,6 +194,13 @@ The .Ar packid must be quoted if it contains blanks. .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 .Fl n 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 and the disk rendered unbootable. 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 .Fl r is not specified, @@ -212,7 +226,7 @@ In either case, the kernel's in-core label is replaced. .Pp For a virgin disk that is not known to .Xr disktab 5 , -.Ar disktype +.Ar type can be specified as .Cm auto . 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 .Fl e .Op Fl nr +.Op Fl m Ar machine .Ar disk .Pp 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 .Fl r 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 .Fl n 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 .Fl R .Op Fl nr +.Op Fl m Ar machine .Ar disk protofile .Pp .Nm @@ -317,6 +341,14 @@ clobbered if is specified, and will be unaffected otherwise. See the boot options below for a 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 .Fl n 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 .Fl B .Op Fl b Ar boot +.Op Fl m Ar machine .Ar disk .Pp This form installs the bootstrap only. @@ -357,11 +390,18 @@ disk. This command is typically run on a slice such as .Pa da0s1 . .Pp +The +.Fl m +option should be specified if the label was +created for a different hardware architecture, +.Ar machine . +.Pp .Nm .Fl w B .Op Fl n .Op Fl b Ar boot -.Ar disk disktype Ns | Ns Cm auto +.Op Fl m Ar machine +.Ar disk type .Op Ar packid .Pp This form corresponds to the @@ -372,6 +412,14 @@ If run on a base disk, this command will create a .Dq dangerously-dedicated label. 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 .Fl n 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 .Op Fl n .Op Fl b Ar boot +.Op Fl m Ar machine .Ar disk protofile .Pp 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 .Fl r 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 .Fl n is used, no data will be written to the device, and instead the diff --git a/sbin/bsdlabel/bsdlabel.c b/sbin/bsdlabel/bsdlabel.c index 88604d3c91e2..49ada3cab60f 100644 --- a/sbin/bsdlabel/bsdlabel.c +++ b/sbin/bsdlabel/bsdlabel.c @@ -64,11 +64,35 @@ __FBSDID("$FreeBSD$"); #define DKTYPENAMES #define FSTYPENAMES #include -#ifdef PC98 -#include -#else + #include +#if (DOSPARTOFF != 446 || NDOSPART != 4 || DOSPTYP_386BSD != 0xa5) +#error has changed +#else +#define I386_DOSPARTOFF 446 +#define I386_NDOSPART 4 +#define I386_DOSPTYP_386BSD 0xa5 #endif +#undef DOSPARTOFF +#undef NDOSPART +#undef DOSPTYP_386BSD + +#include +#if (DOSPARTOFF != 0 || NDOSPART != 16 || DOSPTYP_386BSD != 0x94) +#error 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 #include @@ -104,18 +128,11 @@ __FBSDID("$FreeBSD$"); #define BIG_NEWFS_FRAG 2048U #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 *); -int writelabel(int, const char *, struct disklabel *); +int writelabel(int, void *, struct disklabel *); void l_perror(const char *); struct disklabel *readlabel(int); -struct disklabel *makebootarea(char *, struct disklabel *, int); +struct disklabel *makebootarea(void *, struct disklabel *, int); void display(FILE *, const struct disklabel *); int edit(struct disklabel *, int); int editit(void); @@ -137,7 +154,7 @@ char tmpfil[] = PATH_TMPFILE; char namebuf[BBSIZE], *np = namebuf; struct disklabel lab; -char bootarea[BBSIZE]; +int64_t bootarea[BBSIZE / 8]; char blank[] = ""; char unknown[] = "unknown"; @@ -155,20 +172,36 @@ enum { UNSPEC, EDIT, READ, RESTORE, WRITE, WRITEBOOT } 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 disable_write; /* set to disable writing to disk label */ -#define OPTIONS "BRb:enrs:w" - int main(int argc, char *argv[]) { struct disklabel *lp; FILE *t; - int ch, f = 0, error = 0; + int ch, f = 0, error = 0, i; char *name = 0; - while ((ch = getopt(argc, argv, OPTIONS)) != -1) + while ((ch = getopt(argc, argv, "Bb:em:nRrs:w")) != -1) switch (ch) { case 'B': ++installboot; @@ -176,6 +209,15 @@ main(int argc, char *argv[]) case 'b': xxboot = optarg; 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': disable_write = 1; break; @@ -215,6 +257,30 @@ main(int argc, char *argv[]) if (argc < 1) 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]; if (dkname[0] != '/') { (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 -writelabel(int f, const char *boot, struct disklabel *lp) +writelabel(int f, void *boot, struct disklabel *lp) { -#ifdef __alpha__ - u_long *p, sum; + uint64_t *p, sum; int i; -#endif if (disable_write) { 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); -#ifdef __alpha__ - /* - * Generate the bootblock checksum for the SRM console. - */ - for (p = (u_long *)boot, i = 0, sum = 0; i < 63; i++) - sum += p[i]; - p[63] = sum; -#endif + if (arch->arch == ARCH_ALPHA) { + /* + * Generate the bootblock checksum for the SRM console. + */ + for (p = (uint64_t *)boot, i = 0, sum = 0; i < 63; i++) + sum += p[i]; + p[63] = sum; + } if (ioctl(f, DIOCBSDBB, &boot) == 0) return (0); if (write(f, boot, lp->d_bbsize) != (int)lp->d_bbsize) { @@ -420,12 +484,14 @@ readlabel(int f) if (read(f, bootarea, BBSIZE) < BBSIZE) err(4, "%s", specname); 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)) if (lp->d_magic == DISKMAGIC && lp->d_magic2 == DISKMAGIC) 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 || dkcksum(lp) != 0) errx(1, @@ -443,21 +509,17 @@ readlabel(int f) * Returns a pointer to the disklabel portion of the bootarea. */ struct disklabel * -makebootarea(char *boot, struct disklabel *dp, int f) +makebootarea(void *boot, struct disklabel *dp, int f) { struct disklabel *lp; char *p; int b; char *dkbasename; struct stat sb; -#ifdef __alpha__ - u_long *bootinfo; + uint64_t *bootinfo; int n; -#endif -#ifdef __i386__ char *tmpbuf; int i, found, dps; -#endif /* XXX */ if (dp->d_secsize == 0) { @@ -465,7 +527,8 @@ makebootarea(char *boot, struct disklabel *dp, int f) dp->d_bbsize = BBSIZE; } 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); /* * 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); if (fstat(b, &sb) != 0) err(4, "%s", xxboot); -#ifdef __i386__ - if (sb.st_size > BBSIZE) - errx(4, "%s too large", xxboot); - /* - * XXX Botch alert. - * The i386/PC98 has the so-called fdisk table embedded into the - * primary bootstrap. We take care to not clobber it, but - * only if it does already contain some data. (Otherwise, - * the xxboot provides a template.) - */ - if ((tmpbuf = (char *)malloc((int)dp->d_secsize)) == 0) - err(4, "%s", xxboot); - memcpy((void *)tmpbuf, (void *)boot, (int)dp->d_secsize); + if (arch->arch == ARCH_I386) { + if (sb.st_size > BBSIZE) + errx(4, "%s too large", xxboot); + /* + * XXX Botch alert. + * The i386/PC98 has the so-called fdisk table embedded into the + * primary bootstrap. We take care to not clobber it, but + * only if it does already contain some data. (Otherwise, + * the xxboot provides a template.) + */ + if ((tmpbuf = (char *)malloc((int)dp->d_secsize)) == 0) + err(4, "%s", xxboot); + memcpy((void *)tmpbuf, (void *)boot, (int)dp->d_secsize); - if (read(b, boot, BBSIZE) < 0) - err(4, "%s", xxboot); + if (read(b, boot, BBSIZE) < 0) + err(4, "%s", xxboot); - /* XXX: rely on some very precise overlaps in definitions */ -#ifdef PC98 - dps = sizeof(struct pc98_partition); -#else - dps = sizeof(struct dos_partition); -#endif - for (i = DOSPARTOFF, found = 0; - !found && i < (int)(DOSPARTOFF + NDOSPART * dps); - i++) - found = tmpbuf[i] != 0; - if (found) - memcpy((void *)&boot[DOSPARTOFF], - (void *)&tmpbuf[DOSPARTOFF], - NDOSPART * dps); - free(tmpbuf); -#endif /* __i386__ */ + /* XXX: rely on some very precise overlaps in definitions */ + dps = IS_PC98 ? sizeof(struct pc98_partition) : + sizeof(struct dos_partition); + for (i = DOSPARTOFF, found = 0; + !found && i < (int)(DOSPARTOFF + NDOSPART * dps); + i++) + found = tmpbuf[i] != 0; + if (found) + memcpy((void *)&((char *)boot)[DOSPARTOFF], + (void *)&tmpbuf[DOSPARTOFF], + NDOSPART * dps); + free(tmpbuf); + } -#ifdef __alpha__ - if (sb.st_size > BBSIZE - dp->d_secsize) - errx(4, "%s too large", xxboot); - /* - * On the alpha, the primary bootstrap starts at the - * second sector of the boot area. The first sector - * contains the label and must be edited to contain the - * size and location of the primary bootstrap. - */ - n = read(b, boot + dp->d_secsize, BBSIZE - dp->d_secsize); - if (n < 0) - err(4, "%s", xxboot); - bootinfo = (u_long *)(boot + 480); - bootinfo[0] = (n + dp->d_secsize - 1) / dp->d_secsize; - bootinfo[1] = 1; /* start at sector 1 */ - bootinfo[2] = 0; /* flags (must be zero) */ -#endif /* __alpha__ */ + if (arch->arch == ARCH_ALPHA) { + if (sb.st_size > BBSIZE - dp->d_secsize) + errx(4, "%s too large", xxboot); + /* + * On the alpha, the primary bootstrap starts at the + * second sector of the boot area. The first sector + * contains the label and must be edited to contain the + * size and location of the primary bootstrap. + */ + n = read(b, (char *)boot + dp->d_secsize, + BBSIZE - dp->d_secsize); + if (n < 0) + err(4, "%s", xxboot); + bootinfo = (uint64_t *)((char *)boot + 480); + bootinfo[0] = (n + dp->d_secsize - 1) / dp->d_secsize; + bootinfo[1] = 1; /* start at sector 1 */ + bootinfo[2] = 0; /* flags (must be zero) */ + } (void)close(b); /* @@ -1495,20 +1556,22 @@ Warning(const char *fmt, ...) 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", - "\t\t(to read label)", - " disklabel -w [-r] [-n] disk type [ packid ]", - "\t\t(to write label with existing boot program)", - " disklabel -e [-r] [-n] disk", - "\t\t(to edit label)", - " disklabel -R [-r] [-n] disk protofile", - "\t\t(to restore label with existing boot program)", - " disklabel -B [-n] [ -b bootprog ] disk [ type ]", - "\t\t(to install boot program with existing on-disk label)", - " disklabel -w -B [-n] [ -b bootprog ] disk type [ packid ]", - "\t\t(to write label and install boot program)", - " disklabel -R -B [-n] [ -b bootprog ] disk protofile", + + 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", + "\t\t(to read label)", + " disklabel -w [-nr] [-m machine] disk type [packid]", + "\t\t(to write label with existing boot program)", + " disklabel -e [-nr] [-m machine] disk", + "\t\t(to edit label)", + " disklabel -R [-nr] [-m machine] disk protofile", + "\t\t(to restore label with existing boot program)", + " disklabel -B [-b boot] [-m machine] disk", + "\t\t(to install boot program with existing on-disk label)", + " 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)" ); exit(1); diff --git a/sbin/disklabel/disklabel.8 b/sbin/disklabel/disklabel.8 index 6a57d4035ade..3ca49ff90bdf 100644 --- a/sbin/disklabel/disklabel.8 +++ b/sbin/disklabel/disklabel.8 @@ -48,31 +48,37 @@ .Nm .Fl w .Op Fl nr -.Ar disk disktype Ns | Ns Cm auto +.Op Fl m Ar machine +.Ar disk type .Op Ar packid .Nm .Fl e .Op Fl nr +.Op Fl m Ar machine .Ar disk .Nm .Fl R .Op Fl nr +.Op Fl m Ar machine .Ar disk protofile .Pp .Nm .Fl B .Op Fl b Ar boot +.Op Fl m Ar machine .Ar disk .Nm .Fl w B .Op Fl n .Op Fl b Ar boot -.Ar disk disktype Ns | Ns Cm auto +.Op Fl m Ar machine +.Ar disk type .Op Ar packid .Nm .Fl R B .Op Fl n .Op Fl b Ar boot +.Op Fl m Ar machine .Ar disk protofile .Sh DESCRIPTION The @@ -167,7 +173,8 @@ To write a standard label, use the form .Nm .Fl w .Op Fl nr -.Ar disk disktype Ns | Ns Cm auto +.Op Fl m Ar machine +.Ar disk type .Op Ar packid .Pp The required arguments to @@ -187,6 +194,13 @@ The .Ar packid must be quoted if it contains blanks. .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 .Fl n 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 and the disk rendered unbootable. 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 .Fl r is not specified, @@ -212,7 +226,7 @@ In either case, the kernel's in-core label is replaced. .Pp For a virgin disk that is not known to .Xr disktab 5 , -.Ar disktype +.Ar type can be specified as .Cm auto . 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 .Fl e .Op Fl nr +.Op Fl m Ar machine .Ar disk .Pp 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 .Fl r 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 .Fl n 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 .Fl R .Op Fl nr +.Op Fl m Ar machine .Ar disk protofile .Pp .Nm @@ -317,6 +341,14 @@ clobbered if is specified, and will be unaffected otherwise. See the boot options below for a 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 .Fl n 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 .Fl B .Op Fl b Ar boot +.Op Fl m Ar machine .Ar disk .Pp This form installs the bootstrap only. @@ -357,11 +390,18 @@ disk. This command is typically run on a slice such as .Pa da0s1 . .Pp +The +.Fl m +option should be specified if the label was +created for a different hardware architecture, +.Ar machine . +.Pp .Nm .Fl w B .Op Fl n .Op Fl b Ar boot -.Ar disk disktype Ns | Ns Cm auto +.Op Fl m Ar machine +.Ar disk type .Op Ar packid .Pp This form corresponds to the @@ -372,6 +412,14 @@ If run on a base disk, this command will create a .Dq dangerously-dedicated label. 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 .Fl n 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 .Op Fl n .Op Fl b Ar boot +.Op Fl m Ar machine .Ar disk protofile .Pp 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 .Fl r 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 .Fl n is used, no data will be written to the device, and instead the diff --git a/sbin/disklabel/disklabel.c b/sbin/disklabel/disklabel.c index 88604d3c91e2..49ada3cab60f 100644 --- a/sbin/disklabel/disklabel.c +++ b/sbin/disklabel/disklabel.c @@ -64,11 +64,35 @@ __FBSDID("$FreeBSD$"); #define DKTYPENAMES #define FSTYPENAMES #include -#ifdef PC98 -#include -#else + #include +#if (DOSPARTOFF != 446 || NDOSPART != 4 || DOSPTYP_386BSD != 0xa5) +#error has changed +#else +#define I386_DOSPARTOFF 446 +#define I386_NDOSPART 4 +#define I386_DOSPTYP_386BSD 0xa5 #endif +#undef DOSPARTOFF +#undef NDOSPART +#undef DOSPTYP_386BSD + +#include +#if (DOSPARTOFF != 0 || NDOSPART != 16 || DOSPTYP_386BSD != 0x94) +#error 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 #include @@ -104,18 +128,11 @@ __FBSDID("$FreeBSD$"); #define BIG_NEWFS_FRAG 2048U #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 *); -int writelabel(int, const char *, struct disklabel *); +int writelabel(int, void *, struct disklabel *); void l_perror(const char *); struct disklabel *readlabel(int); -struct disklabel *makebootarea(char *, struct disklabel *, int); +struct disklabel *makebootarea(void *, struct disklabel *, int); void display(FILE *, const struct disklabel *); int edit(struct disklabel *, int); int editit(void); @@ -137,7 +154,7 @@ char tmpfil[] = PATH_TMPFILE; char namebuf[BBSIZE], *np = namebuf; struct disklabel lab; -char bootarea[BBSIZE]; +int64_t bootarea[BBSIZE / 8]; char blank[] = ""; char unknown[] = "unknown"; @@ -155,20 +172,36 @@ enum { UNSPEC, EDIT, READ, RESTORE, WRITE, WRITEBOOT } 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 disable_write; /* set to disable writing to disk label */ -#define OPTIONS "BRb:enrs:w" - int main(int argc, char *argv[]) { struct disklabel *lp; FILE *t; - int ch, f = 0, error = 0; + int ch, f = 0, error = 0, i; char *name = 0; - while ((ch = getopt(argc, argv, OPTIONS)) != -1) + while ((ch = getopt(argc, argv, "Bb:em:nRrs:w")) != -1) switch (ch) { case 'B': ++installboot; @@ -176,6 +209,15 @@ main(int argc, char *argv[]) case 'b': xxboot = optarg; 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': disable_write = 1; break; @@ -215,6 +257,30 @@ main(int argc, char *argv[]) if (argc < 1) 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]; if (dkname[0] != '/') { (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 -writelabel(int f, const char *boot, struct disklabel *lp) +writelabel(int f, void *boot, struct disklabel *lp) { -#ifdef __alpha__ - u_long *p, sum; + uint64_t *p, sum; int i; -#endif if (disable_write) { 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); -#ifdef __alpha__ - /* - * Generate the bootblock checksum for the SRM console. - */ - for (p = (u_long *)boot, i = 0, sum = 0; i < 63; i++) - sum += p[i]; - p[63] = sum; -#endif + if (arch->arch == ARCH_ALPHA) { + /* + * Generate the bootblock checksum for the SRM console. + */ + for (p = (uint64_t *)boot, i = 0, sum = 0; i < 63; i++) + sum += p[i]; + p[63] = sum; + } if (ioctl(f, DIOCBSDBB, &boot) == 0) return (0); if (write(f, boot, lp->d_bbsize) != (int)lp->d_bbsize) { @@ -420,12 +484,14 @@ readlabel(int f) if (read(f, bootarea, BBSIZE) < BBSIZE) err(4, "%s", specname); 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)) if (lp->d_magic == DISKMAGIC && lp->d_magic2 == DISKMAGIC) 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 || dkcksum(lp) != 0) errx(1, @@ -443,21 +509,17 @@ readlabel(int f) * Returns a pointer to the disklabel portion of the bootarea. */ struct disklabel * -makebootarea(char *boot, struct disklabel *dp, int f) +makebootarea(void *boot, struct disklabel *dp, int f) { struct disklabel *lp; char *p; int b; char *dkbasename; struct stat sb; -#ifdef __alpha__ - u_long *bootinfo; + uint64_t *bootinfo; int n; -#endif -#ifdef __i386__ char *tmpbuf; int i, found, dps; -#endif /* XXX */ if (dp->d_secsize == 0) { @@ -465,7 +527,8 @@ makebootarea(char *boot, struct disklabel *dp, int f) dp->d_bbsize = BBSIZE; } 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); /* * 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); if (fstat(b, &sb) != 0) err(4, "%s", xxboot); -#ifdef __i386__ - if (sb.st_size > BBSIZE) - errx(4, "%s too large", xxboot); - /* - * XXX Botch alert. - * The i386/PC98 has the so-called fdisk table embedded into the - * primary bootstrap. We take care to not clobber it, but - * only if it does already contain some data. (Otherwise, - * the xxboot provides a template.) - */ - if ((tmpbuf = (char *)malloc((int)dp->d_secsize)) == 0) - err(4, "%s", xxboot); - memcpy((void *)tmpbuf, (void *)boot, (int)dp->d_secsize); + if (arch->arch == ARCH_I386) { + if (sb.st_size > BBSIZE) + errx(4, "%s too large", xxboot); + /* + * XXX Botch alert. + * The i386/PC98 has the so-called fdisk table embedded into the + * primary bootstrap. We take care to not clobber it, but + * only if it does already contain some data. (Otherwise, + * the xxboot provides a template.) + */ + if ((tmpbuf = (char *)malloc((int)dp->d_secsize)) == 0) + err(4, "%s", xxboot); + memcpy((void *)tmpbuf, (void *)boot, (int)dp->d_secsize); - if (read(b, boot, BBSIZE) < 0) - err(4, "%s", xxboot); + if (read(b, boot, BBSIZE) < 0) + err(4, "%s", xxboot); - /* XXX: rely on some very precise overlaps in definitions */ -#ifdef PC98 - dps = sizeof(struct pc98_partition); -#else - dps = sizeof(struct dos_partition); -#endif - for (i = DOSPARTOFF, found = 0; - !found && i < (int)(DOSPARTOFF + NDOSPART * dps); - i++) - found = tmpbuf[i] != 0; - if (found) - memcpy((void *)&boot[DOSPARTOFF], - (void *)&tmpbuf[DOSPARTOFF], - NDOSPART * dps); - free(tmpbuf); -#endif /* __i386__ */ + /* XXX: rely on some very precise overlaps in definitions */ + dps = IS_PC98 ? sizeof(struct pc98_partition) : + sizeof(struct dos_partition); + for (i = DOSPARTOFF, found = 0; + !found && i < (int)(DOSPARTOFF + NDOSPART * dps); + i++) + found = tmpbuf[i] != 0; + if (found) + memcpy((void *)&((char *)boot)[DOSPARTOFF], + (void *)&tmpbuf[DOSPARTOFF], + NDOSPART * dps); + free(tmpbuf); + } -#ifdef __alpha__ - if (sb.st_size > BBSIZE - dp->d_secsize) - errx(4, "%s too large", xxboot); - /* - * On the alpha, the primary bootstrap starts at the - * second sector of the boot area. The first sector - * contains the label and must be edited to contain the - * size and location of the primary bootstrap. - */ - n = read(b, boot + dp->d_secsize, BBSIZE - dp->d_secsize); - if (n < 0) - err(4, "%s", xxboot); - bootinfo = (u_long *)(boot + 480); - bootinfo[0] = (n + dp->d_secsize - 1) / dp->d_secsize; - bootinfo[1] = 1; /* start at sector 1 */ - bootinfo[2] = 0; /* flags (must be zero) */ -#endif /* __alpha__ */ + if (arch->arch == ARCH_ALPHA) { + if (sb.st_size > BBSIZE - dp->d_secsize) + errx(4, "%s too large", xxboot); + /* + * On the alpha, the primary bootstrap starts at the + * second sector of the boot area. The first sector + * contains the label and must be edited to contain the + * size and location of the primary bootstrap. + */ + n = read(b, (char *)boot + dp->d_secsize, + BBSIZE - dp->d_secsize); + if (n < 0) + err(4, "%s", xxboot); + bootinfo = (uint64_t *)((char *)boot + 480); + bootinfo[0] = (n + dp->d_secsize - 1) / dp->d_secsize; + bootinfo[1] = 1; /* start at sector 1 */ + bootinfo[2] = 0; /* flags (must be zero) */ + } (void)close(b); /* @@ -1495,20 +1556,22 @@ Warning(const char *fmt, ...) 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", - "\t\t(to read label)", - " disklabel -w [-r] [-n] disk type [ packid ]", - "\t\t(to write label with existing boot program)", - " disklabel -e [-r] [-n] disk", - "\t\t(to edit label)", - " disklabel -R [-r] [-n] disk protofile", - "\t\t(to restore label with existing boot program)", - " disklabel -B [-n] [ -b bootprog ] disk [ type ]", - "\t\t(to install boot program with existing on-disk label)", - " disklabel -w -B [-n] [ -b bootprog ] disk type [ packid ]", - "\t\t(to write label and install boot program)", - " disklabel -R -B [-n] [ -b bootprog ] disk protofile", + + 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", + "\t\t(to read label)", + " disklabel -w [-nr] [-m machine] disk type [packid]", + "\t\t(to write label with existing boot program)", + " disklabel -e [-nr] [-m machine] disk", + "\t\t(to edit label)", + " disklabel -R [-nr] [-m machine] disk protofile", + "\t\t(to restore label with existing boot program)", + " disklabel -B [-b boot] [-m machine] disk", + "\t\t(to install boot program with existing on-disk label)", + " 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)" ); exit(1);