summaryrefslogtreecommitdiff
path: root/lib/libukfs
diff options
context:
space:
mode:
authorpooka <pooka@NetBSD.org>2011-02-22 15:42:15 +0000
committerpooka <pooka@NetBSD.org>2011-02-22 15:42:15 +0000
commit80daf6e115cb03f5a4cc8cc910e951b258a6aa0e (patch)
tree7e59f6799abd8de235724273598f0860b26b5dcf /lib/libukfs
parent2f96beb83f0593b78d3ea5d7a739a4b7354362ae (diff)
Add support for a byteswapped disklabel so that I can mount
NetBSD/sparc anita images on my i386.
Diffstat (limited to 'lib/libukfs')
-rw-r--r--lib/libukfs/ukfs.c18
-rw-r--r--lib/libukfs/ukfs_disklabel.c46
-rw-r--r--lib/libukfs/ukfs_int_disklabel.h7
3 files changed, 54 insertions, 17 deletions
diff --git a/lib/libukfs/ukfs.c b/lib/libukfs/ukfs.c
index e52ac82dde6..f8612b1af3d 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 73ac061663e..ff7e0d7dd5e 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 80760fb9c0c..304f220ea35 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_ */