>>>>> "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