From 27ec9b9d1dabc862cc0432307340fa19205a9b86 Mon Sep 17 00:00:00 2001 From: pooka Date: Tue, 22 Feb 2011 15:42:15 +0000 Subject: [PATCH] Add support for a byteswapped disklabel so that I can mount NetBSD/sparc anita images on my i386. --- lib/libukfs/ukfs.c | 18 ++++++++++--- lib/libukfs/ukfs_disklabel.c | 46 +++++++++++++++++++++++++------- lib/libukfs/ukfs_int_disklabel.h | 7 ++--- 3 files changed, 54 insertions(+), 17 deletions(-) diff --git a/lib/libukfs/ukfs.c b/lib/libukfs/ukfs.c index e52ac82dde65..f8612b1af3d8 100644 --- a/lib/libukfs/ukfs.c +++ b/lib/libukfs/ukfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: ukfs.c,v 1.56 2011/01/02 13:01:45 pooka Exp $ */ +/* $NetBSD: ukfs.c,v 1.57 2011/02/22 15:42:15 pooka Exp $ */ /* * Copyright (c) 2007, 2008, 2009 Antti Kantee. All Rights Reserved. @@ -246,9 +246,11 @@ ukfs_part_probe(char *devpath, struct ukfs_part **partp) *(MAGICADJ_DISKLABEL(p,0)) < 'a' + UKFS_MAXPARTITIONS) { struct ukfs__disklabel dl; struct ukfs__partition *pp; + int imswapped; char buf[65536]; char labelchar = *(MAGICADJ_DISKLABEL(p,0)); int partition = labelchar - 'a'; + uint32_t poffset, psize; *p = '\0'; devfd = open(devpath, O_RDONLY); @@ -263,7 +265,8 @@ ukfs_part_probe(char *devpath, struct ukfs_part **partp) goto out; } - if (ukfs__disklabel_scan(&dl, buf, sizeof(buf)) != 0) { + if (ukfs__disklabel_scan(&dl, &imswapped, + buf, sizeof(buf)) != 0) { error = ENOENT; goto out; } @@ -276,8 +279,15 @@ ukfs_part_probe(char *devpath, struct ukfs_part **partp) pp = &dl.d_partitions[partition]; part->part_type = UKFS_PART_DISKLABEL; part->part_labelchar = labelchar; - part->part_devoff = pp->p_offset << DEV_BSHIFT; - part->part_devsize = pp->p_size << DEV_BSHIFT; + if (imswapped) { + poffset = bswap32(pp->p_offset); + psize = bswap32(pp->p_size); + } else { + poffset = pp->p_offset; + psize = pp->p_size; + } + part->part_devoff = poffset << DEV_BSHIFT; + part->part_devsize = psize << DEV_BSHIFT; } else { error = EINVAL; } diff --git a/lib/libukfs/ukfs_disklabel.c b/lib/libukfs/ukfs_disklabel.c index 73ac061663ec..ff7e0d7dd5ea 100644 --- a/lib/libukfs/ukfs_disklabel.c +++ b/lib/libukfs/ukfs_disklabel.c @@ -1,4 +1,4 @@ -/* $NetBSD: ukfs_disklabel.c,v 1.2 2009/12/03 14:23:49 pooka Exp $ */ +/* $NetBSD: ukfs_disklabel.c,v 1.3 2011/02/22 15:42:15 pooka Exp $ */ /* * Local copies of libutil disklabel routines. This uncouples libukfs @@ -50,27 +50,42 @@ #define SCAN_INCR 4 int -ukfs__disklabel_scan(struct ukfs__disklabel *lp, char *buf, size_t buflen) +ukfs__disklabel_scan(struct ukfs__disklabel *lp, int *isswapped, + char *buf, size_t buflen) { - size_t i; + size_t i; + int imswapped; + uint16_t npart; /* scan for the correct magic numbers. */ for (i=0; i <= buflen - sizeof(*lp); i += SCAN_INCR) { memcpy(lp, buf + i, sizeof(*lp)); if (lp->d_magic == UKFS_DISKMAGIC && - lp->d_magic2 == UKFS_DISKMAGIC) + lp->d_magic2 == UKFS_DISKMAGIC) { + imswapped = 0; goto sanity; + } + if (lp->d_magic == bswap32(UKFS_DISKMAGIC) && + lp->d_magic2 == bswap32(UKFS_DISKMAGIC)) { + imswapped = 1; + goto sanity; + } } return 1; sanity: + if (imswapped) + npart = bswap16(lp->d_npartitions); + else + npart = lp->d_npartitions; /* we've found something, let's sanity check it */ - if (lp->d_npartitions > UKFS_MAXPARTITIONS - || ukfs__disklabel_dkcksum(lp)) + if (npart > UKFS_MAXPARTITIONS + || ukfs__disklabel_dkcksum(lp, imswapped)) return 1; + *isswapped = imswapped; return 0; } @@ -110,15 +125,26 @@ sanity: */ uint16_t -ukfs__disklabel_dkcksum(struct ukfs__disklabel *lp) +ukfs__disklabel_dkcksum(struct ukfs__disklabel *lp, int imswapped) { uint16_t *start, *end; uint16_t sum; + uint16_t npart; + + if (imswapped) + npart = bswap16(lp->d_npartitions); + else + npart = lp->d_npartitions; sum = 0; start = (uint16_t *)(void *)lp; - end = (uint16_t *)(void *)&lp->d_partitions[lp->d_npartitions]; - while (start < end) - sum ^= *start++; + end = (uint16_t *)(void *)&lp->d_partitions[npart]; + while (start < end) { + if (imswapped) + sum ^= bswap16(*start); + else + sum ^= *start; + start++; + } return (sum); } diff --git a/lib/libukfs/ukfs_int_disklabel.h b/lib/libukfs/ukfs_int_disklabel.h index 80760fb9c0c9..304f220ea352 100644 --- a/lib/libukfs/ukfs_int_disklabel.h +++ b/lib/libukfs/ukfs_int_disklabel.h @@ -1,4 +1,4 @@ -/* $NetBSD: ukfs_int_disklabel.h,v 1.2 2009/12/03 14:23:49 pooka Exp $ */ +/* $NetBSD: ukfs_int_disklabel.h,v 1.3 2011/02/22 15:42:15 pooka Exp $ */ /* * Modified copy of disklabel.h so that ukfs doesn't have to depend @@ -151,7 +151,8 @@ struct ukfs__disklabel { } d_partitions[UKFS_MAXPARTITIONS]; /* actually may be more */ }; -uint16_t ukfs__disklabel_dkcksum(struct ukfs__disklabel *); -int ukfs__disklabel_scan(struct ukfs__disklabel *, char *, size_t); +uint16_t ukfs__disklabel_dkcksum(struct ukfs__disklabel *, int); +int ukfs__disklabel_scan(struct ukfs__disklabel *, int *, + char *, size_t); #endif /* !LIB_UKFS_DISKLABEL_H_ */