>>>>> "lp" == Lloyd Parkes <lloyd%must-have-coffee.gen.nz@localhost> writes: lp> Is it my imagination, or is disklabel not endian aware? The attached half-decade-old patch might not help the kind of endian aware you want, but in general the way to use it is, # sleep 90 < /dev/rsd0c& # disklabel -l sd0 # mount /dev/sd0a /mnt it will load foreign labels into the kernel ephemerally, without rewriting the on-disk label in the form of the native architecture. I don't know if it has any use for writing labels, though.
Index: arch/mac68k/mac68k/disksubr.c =================================================================== RCS file: /scratch/cvsroot/netbsd/src/sys/arch/mac68k/mac68k/disksubr.c,v retrieving revision 1.1.1.6 retrieving revision 1.8 diff -u -r1.1.1.6 -r1.8 --- arch/mac68k/mac68k/disksubr.c 18 Jul 2005 14:03:52 -0000 1.1.1.6 +++ arch/mac68k/mac68k/disksubr.c 20 Jul 2005 22:50:58 -0000 1.8 @@ -311,6 +311,8 @@ } /* + * XXX !! -- why is this cruft here? w.t.f. is wrong with mbrlabel? + * * Scan the disk buffer for a DOS style master boot record. * Return if no match; otherwise, set up an in-core disklabel . * @@ -465,7 +467,6 @@ setdisklabel(struct disklabel *olp, struct disklabel *nlp, u_long openmask, struct cpu_disklabel *osdep) { -#if 0 int i; struct partition *opp, *npp; @@ -512,7 +513,6 @@ nlp->d_checksum = 0; nlp->d_checksum = dkcksum(nlp); *olp = *nlp; -#endif return (0); } Index: sbin/disklabel/disklabel.c =================================================================== RCS file: /scratch/cvsroot/netbsd/src/sbin/disklabel/disklabel.c,v retrieving revision 1.1.1.8 retrieving revision 1.11 diff -u -r1.1.1.8 -r1.11 --- sbin/disklabel/disklabel.c 18 Jul 2005 13:58:24 -0000 1.1.1.8 +++ sbin/disklabel/disklabel.c 21 Jul 2005 04:32:09 -0000 1.11 @@ -55,6 +55,8 @@ #define DKTYPENAMES #define FSTYPENAMES #include <sys/disklabel.h> +#include <sys/types.h> +#include <machine/bswap.h> #include <sys/bootblock.h> #include <ufs/ufs/dinode.h> @@ -70,6 +72,7 @@ #include <stdlib.h> #include <unistd.h> #include <util.h> +#include <strings.h> #include <disktab.h> @@ -119,16 +122,17 @@ #endif /* NUMBOOT > 0 */ static enum { - UNSPEC, EDIT, READ, RESTORE, SETWRITABLE, WRITE, WRITEBOOT, INTERACT + UNSPEC, EDIT, READ, LOAD, RESTORE, SETWRITABLE, WRITE, WRITEBOOT, INTERACT } op = UNSPEC; static int Fflag; static int rflag; static int tflag; int Cflag; +static int lflag; static int Iflag; -#define COMMON_OPTIONS "BCFINRWb:ef:irs:tw" +#define COMMON_OPTIONS "BCFINRWb:ef:ilrs:tw" #ifdef DEBUG static int debug; @@ -159,6 +163,7 @@ struct disklabel *); static void l_perror(const char *); static struct disklabel *readlabel(int); +static struct disklabel *bswapdisklabel __P((struct disklabel *)); static struct disklabel *makebootarea(char *, struct disklabel *, int); static int edit(struct disklabel *, int); static int editit(void); @@ -244,6 +249,9 @@ case 'r': ++rflag; break; + case 'l': + ++lflag; + break; case 'w': if (op != UNSPEC) usage(); @@ -267,13 +275,35 @@ if (op == UNSPEC) op = WRITEBOOT; } else { - if (op == UNSPEC) - op = READ; - } #else /* NUMBOOT <= 0 */ - if (op == UNSPEC) - op = READ; + if (1) { #endif /* NUMBOOT <= 0 */ + if (lflag) { + if (op == UNSPEC) { + op = LOAD; + ++rflag; + } else { + if (op != WRITE && op != EDIT && op != INTERACT && op != RESTORE) + usage(); + /* + * rflag and lflag will actually work fine + * together in EDIT mode--the label is read + * in raw mode, and then loaded into the + * kernel without writing it to disk. but + * 'disklabel -l; disklabel -el' is equivalent + * as long as no partitions are open, and + * treating -l and -r as mutually exclusive + * brings the user closer to an intuitive + * understanding of their meanings. + */ + if (rflag) + usage(); + } + } else { + if (op == UNSPEC) + op = READ; + } + } if (argc < 1) usage(); @@ -347,6 +377,18 @@ error += 100; break; + case LOAD: + if (argc != 1) + usage(); + lp = readlabel(f); + if (checklabel(lp) && ~DE_WARN) + error = writelabel(f, bootarea, lp); + else { + error = 1; + warnx("label not loaded."); + } + break; + case RESTORE: if (argc < 2 || argc > 3) usage(); @@ -376,8 +418,10 @@ *lp = lab; if (checklabel(lp) == 0) error = writelabel(f, bootarea, lp); - else + else { error = 1; + warnx("label not written."); + } break; case WRITEBOOT: @@ -393,8 +437,10 @@ *lp = tlab; if (checklabel(lp) == 0) error = writelabel(f, bootarea, lp); - else + else { error = 1; + warnx("label not written."); + } break; } #endif /* NUMBOOT > 0 */ @@ -485,7 +531,15 @@ lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = 0; - lp->d_checksum = dkcksum(lp); + lp->d_checksum = dkcksum(lp, lp->d_npartitions); + + if (lflag) { + if (ioctl(f, DIOCSDINFO, lp) < 0) { + perror("ioctl DIOCSDINFO"); + return (1); + } + return 0; + } if (Fflag || rflag || Iflag) { @@ -883,7 +937,7 @@ static struct disklabel * readlabel(int f) { - struct disklabel *lp; + struct disklabel *lp, *bslp; if (Fflag || rflag || Iflag) { const char *msg; @@ -913,10 +967,19 @@ if (lp->d_magic == DISKMAGIC && lp->d_magic2 == DISKMAGIC) { if (lp->d_npartitions <= MAXPARTITIONS && - dkcksum(lp) == 0) + dkcksum(lp, lp->d_npartitions) == 0) return (lp); msg = "disk label corrupted"; } + if (lp->d_magic == bswap32(DISKMAGIC) && + lp->d_magic2 == bswap32(DISKMAGIC)) { + if (bswap16(lp->d_npartitions) <= MAXPARTITIONS && + dkcksum(lp, bswap16(lp->d_npartitions)) == 0) { + bslp = bswapdisklabel(lp); + return (bslp); + } + msg = "disk label corrupted"; + } } if (msg != NULL && !Iflag) errx(1, "%s", msg); @@ -937,6 +1000,74 @@ } /* + * byte-swap all the individual fields inside a disklabel. + * returns a pointer to the freshly-malloc'd disklabel. + * call with lp->d_npartitions as a sane (foreign-endiness) number, because + * bswapdisklabel will allocate enough memory to hold more than MAXPARTITIONS + */ +static struct disklabel * +bswapdisklabel(lp) + struct disklabel *lp; +{ + struct disklabel *bslp; + int i; + struct partition *part, *bspart, *partend; + size_t sz; + + /* sys/disklabel.h: ``actually may be more'' */ + sz = sizeof(*lp) + sizeof(struct partition) * (bswap16(lp->d_npartitions) - MAXPARTITIONS); + bslp = (struct disklabel *)malloc(sz < sizeof(*lp) ? sizeof(*lp) : sz); + /* + * bcopy without swapping, so we don't have to bother with strings. + * the variable-lengthyness expressed in the ? construct above is bzero'ed in the partition loop. + */ + bcopy(lp, bslp, sz); + + bslp->d_magic = bswap32(lp->d_magic); + bslp->d_type = bswap16(lp->d_type); + bslp->d_subtype = bswap16(lp->d_subtype); + bslp->d_secsize = bswap32(lp->d_secsize); + bslp->d_nsectors = bswap32(lp->d_nsectors); + bslp->d_ntracks = bswap32(lp->d_ntracks); + bslp->d_ncylinders = bswap32(lp->d_ncylinders); + bslp->d_secpercyl = bswap32(lp->d_secpercyl); + bslp->d_secperunit = bswap32(lp->d_secperunit); + bslp->d_sparespertrack = bswap16(lp->d_sparespertrack); + bslp->d_sparespercyl = bswap16(lp->d_sparespercyl); + bslp->d_acylinders = bswap32(lp->d_acylinders); + bslp->d_rpm = bswap16(lp->d_rpm); + bslp->d_interleave = bswap16(lp->d_interleave); + bslp->d_trackskew = bswap16(lp->d_trackskew); + bslp->d_cylskew = bswap16(lp->d_cylskew); + bslp->d_headswitch = bswap32(lp->d_headswitch); + bslp->d_trkseek = bswap32(lp->d_trkseek); + bslp->d_flags = bswap32(lp->d_flags); + for (i = 0; i < NDDATA; i++) + bslp->d_drivedata[i] = bswap32(lp->d_drivedata[i]); + for (i = 0; i < NSPARE; i++) + bslp->d_spare[i] = bswap32(lp->d_spare[i]); + bslp->d_magic2 = bswap32(lp->d_magic2); + bslp->d_checksum = 0; /* hopeless. but, checksumming is endian-independent so endian-ignorant routines elsewhere can fill this in. */ + bslp->d_npartitions = bswap16(lp->d_npartitions); + bslp->d_bbsize = bswap32(lp->d_bbsize); + bslp->d_sbsize = bswap32(lp->d_sbsize); + + bzero(bslp->d_partitions, sizeof(struct partition) * MAXPARTITIONS); + for (part = lp->d_partitions, bspart = bslp->d_partitions, partend = bslp->d_partitions + sizeof(struct partition) * bslp->d_npartitions; bspart < partend; bspart++, part++) { + bspart->p_size = bswap32(part->p_size); + bspart->p_offset = bswap32(part->p_offset); + bspart->p_fsize = bswap32(part->p_fsize); + /* p_fstype and p_frag don't need bswap, but we bzero'ed 'em */ + bspart->p_fstype = part->p_fstype; + bspart->p_frag = part->p_frag; + bspart->p_cpg = bswap16(part->p_cpg); + } + + return(bslp); +} + + +/* * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot'' * Returns a pointer to the disklabel portion of the bootarea. */ @@ -1724,19 +1855,19 @@ errors = 0; if (lp->d_secsize == 0) { warnx("sector size %d", lp->d_secsize); - return (1); + return (DE_ERROR); } if (lp->d_nsectors == 0) { warnx("sectors/track %d", lp->d_nsectors); - return (1); + return (DE_ERROR); } if (lp->d_ntracks == 0) { warnx("tracks/cylinder %d", lp->d_ntracks); - return (1); + return (DE_ERROR); } if (lp->d_ncylinders == 0) { warnx("cylinders/unit %d", lp->d_ncylinders); - errors++; + return (DE_ERROR); } if (lp->d_rpm == 0) warnx("warning, revolutions/minute %d", lp->d_rpm); @@ -1747,7 +1878,7 @@ #ifdef __i386__notyet__ if (dosdp && lp->d_secperunit > dosdp->mbrp_start + dosdp->mbrp_size) { warnx("exceeds DOS partition size"); - errors++; + errors |= DE_WARN; lp->d_secperunit = dosdp->mbrp_start + dosdp->mbrp_size; } /* XXX should also check geometry against BIOS's idea */ @@ -1757,12 +1888,12 @@ #endif /* __arm32__notyet__ */ if (lp->d_bbsize == 0) { warnx("boot block size %d", lp->d_bbsize); - errors++; + errors |= DE_WARN; } else if (lp->d_bbsize % lp->d_secsize) warnx("warning, boot block size %% sector-size != 0"); if (lp->d_sbsize == 0) { warnx("super block size %d", lp->d_sbsize); - errors++; + errors |= DE_WARN; } else if (lp->d_sbsize % lp->d_secsize) warnx("warning, super block size %% sector-size != 0"); if (lp->d_npartitions > MAXPARTITIONS) @@ -1791,18 +1922,18 @@ warnx("warning, partition %c:" " not starting on cylinder boundary", part); - errors++; + errors |= DE_WARN; } #endif /* STRICT_CYLINDER_ALIGNMENT */ if (pp->p_offset > lp->d_secperunit) { warnx("partition %c: offset past end of unit", part); - errors++; + errors |= DE_ERROR; } if (pp->p_offset + pp->p_size > lp->d_secperunit) { warnx("partition %c: partition extends" " past end of unit", part); - errors++; + errors |= DE_ERROR; } if (pp->p_fstype != FS_UNUSED) for (j = i + 1; j < lp->d_npartitions; j++) { @@ -1871,18 +2002,20 @@ } usages[] = { { "[-rt] [-C] [-F] disk", "(to read label)" }, - { "-w [-r] [-F] [-f disktab] disk type [ packid ]", + { "-l disk", + "(to read label and load it into the kernel)" }, + { "-w [-r|-l] [-F] [-f disktab] disk type [ packid ]", #if NUMBOOT > 0 "(to write label with existing boot program)" #else "(to write label)" #endif }, - { "-e [-r] [-I] [-C] [-F] disk", + { "-e [-r|-l] [-I] [-C] [-F] disk", "(to edit label)" }, - { "-i [-I] [-r] [-F] disk", + { "-i [-I] [-r|-l] [-F] disk", "(to create a label interactively)" }, - { "-R [-r] [-F] disk protofile", + { "-R [-r|-l] [-F] disk protofile", #if NUMBOOT > 0 "(to restore label with existing boot program)" #else Index: sbin/disklabel/dkcksum.c =================================================================== RCS file: /scratch/cvsroot/netbsd/src/sbin/disklabel/dkcksum.c,v retrieving revision 1.1.1.2 retrieving revision 1.3 diff -u -r1.1.1.2 -r1.3 --- sbin/disklabel/dkcksum.c 12 Dec 2003 11:29:04 -0000 1.1.1.2 +++ sbin/disklabel/dkcksum.c 12 Dec 2003 20:30:02 -0000 1.3 @@ -43,14 +43,14 @@ #include "dkcksum.h" u_short -dkcksum(struct disklabel *lp) +dkcksum(struct disklabel *lp, u_int16_t npart) { u_short *start, *end; u_short sum; sum = 0; start = (u_short *)lp; - end = (u_short *)&lp->d_partitions[lp->d_npartitions]; + end = (u_short *)&lp->d_partitions[npart]; while (start < end) sum ^= *start++; return (sum); Index: sbin/disklabel/dkcksum.h =================================================================== RCS file: /scratch/cvsroot/netbsd/src/sbin/disklabel/dkcksum.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sbin/disklabel/dkcksum.h 4 Mar 2002 18:38:33 -0000 1.1.1.1 +++ sbin/disklabel/dkcksum.h 8 Mar 2002 23:58:21 -0000 1.2 @@ -1,3 +1,3 @@ /* $NetBSD: dkcksum.h,v 1.3 2000/12/24 05:59:11 lukem Exp $ */ -u_short dkcksum(struct disklabel *); +u_short dkcksum __P((struct disklabel *, u_int16_t)); Index: sbin/disklabel/extern.h =================================================================== RCS file: /scratch/cvsroot/netbsd/src/sbin/disklabel/extern.h,v retrieving revision 1.1.1.2 retrieving revision 1.3 diff -u -r1.1.1.2 -r1.3 --- sbin/disklabel/extern.h 19 Apr 2002 18:31:56 -0000 1.1.1.2 +++ sbin/disklabel/extern.h 24 Apr 2002 23:26:03 -0000 1.3 @@ -29,6 +29,10 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* error codes for checklabel */ +#define DE_WARN (1 << 0) +#define DE_ERROR (1 << 1) + int writelabel(int, char *, struct disklabel *); int checklabel(struct disklabel *); void showinfo(FILE *, struct disklabel *, const char *);
Attachment:
pgpwS5n_fWtSq.pgp
Description: PGP signature