Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src PR kern/51208
details: https://anonhg.NetBSD.org/src/rev/15a4974d2e19
branches: trunk
changeset: 821841:15a4974d2e19
user: rin <rin%NetBSD.org@localhost>
date: Sun Feb 19 07:43:42 2017 +0000
description:
PR kern/51208
Add DISKLABEL_EI (``Endian-Independent'' disklabel) kernel option to machines
that support Master Boot Record (MBR)
diffstat:
share/man/man4/options.4 | 31 +++++++++-
sys/kern/subr_disk_mbr.c | 141 +++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 166 insertions(+), 6 deletions(-)
diffs (262 lines):
diff -r 937e0325832a -r 15a4974d2e19 share/man/man4/options.4
--- a/share/man/man4/options.4 Sun Feb 19 02:11:19 2017 +0000
+++ b/share/man/man4/options.4 Sun Feb 19 07:43:42 2017 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: options.4,v 1.461 2017/02/13 09:46:29 skrll Exp $
+.\" $NetBSD: options.4,v 1.462 2017/02/19 07:43:42 rin Exp $
.\"
.\" Copyright (c) 1996
.\" Perry E. Metzger. All rights reserved.
@@ -30,7 +30,7 @@
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\"
-.Dd January 8, 2017
+.Dd February 19, 2017
.Dt OPTIONS 4
.Os
.Sh NAME
@@ -971,6 +971,33 @@
.El
.Ss File System Options
.Bl -ohang
+.It Cd options DISKLABEL_EI
+Enable
+.Dq Endian-Independent
+.Xr disklabel 5
+support.
+This allows a system to recognize a disklabel written in the other byte order.
+For writing, when a label already exists, its byte order is preserved.
+Otherwise, a new label is written in the native byte order.
+To specify the byte order explicitly,
+.Fl F
+option of
+.Xr disklabel 8
+should be used with
+.Fl B
+option in order to avoid using
+.Xr ioctl 2 ,
+which results in the default behavior explained above.
+At the moment this option is restricted to the following ports:
+amd64, bebox, emips, epoc32, evbarm, i386, ibmnws, landisk, mvmeppc, prep,
+.\" riscv,
+rs6000, sandpoint,
+.\" usermode,
+xen, and zaurus.
+And to machines of
+.\" evbarm64,
+evbmips and evbppc ports that support
+Master Boot Record (MBR).
.It Cd options MAGICLINKS
Enables the expansion of special strings
.Po
diff -r 937e0325832a -r 15a4974d2e19 sys/kern/subr_disk_mbr.c
--- a/sys/kern/subr_disk_mbr.c Sun Feb 19 02:11:19 2017 +0000
+++ b/sys/kern/subr_disk_mbr.c Sun Feb 19 07:43:42 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_disk_mbr.c,v 1.46 2013/06/26 18:47:26 matt Exp $ */
+/* $NetBSD: subr_disk_mbr.c,v 1.47 2017/02/19 07:43:42 rin Exp $ */
/*
* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
@@ -54,7 +54,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_disk_mbr.c,v 1.46 2013/06/26 18:47:26 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_disk_mbr.c,v 1.47 2017/02/19 07:43:42 rin Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -117,6 +117,10 @@
static int look_netbsd_part(mbr_args_t *, mbr_partition_t *, int, uint);
static int write_netbsd_label(mbr_args_t *, mbr_partition_t *, int, uint);
+#ifdef DISKLABEL_EI
+static void swap_disklabel(struct disklabel *, struct disklabel *);
+#endif
+
static int
read_sector(mbr_args_t *a, uint sector, int count)
{
@@ -565,12 +569,23 @@
}
+#ifdef DISKLABEL_EI
+/*
+ * - For read, convert a label to the native byte order.
+ * - For update or write, if a label already exists, keep its byte order.
+ * Otherwise, write a new label in the native byte order.
+ */
+#endif
static int
validate_label(mbr_args_t *a, uint label_sector)
{
struct disklabel *dlp;
char *dlp_lim, *dlp_byte;
int error;
+#ifdef DISKLABEL_EI
+ int swapped = 0;
+ uint16_t npartitions;
+#endif
/* Next, dig out disk label */
if (read_sector(a, label_sector, SCANBLOCKS)) {
@@ -603,8 +618,31 @@
break;
}
if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC)
+#ifdef DISKLABEL_EI
+ {
+ if (bswap32(dlp->d_magic) != DISKMAGIC ||
+ bswap32(dlp->d_magic2) != DISKMAGIC)
+ continue;
+
+ /*
+ * The label is in the other byte order. We need to
+ * checksum before swapping the byte order.
+ */
+ npartitions = bswap16(dlp->d_npartitions);
+ if (npartitions > MAXPARTITIONS ||
+ dkcksum_sized(dlp, npartitions) != 0)
+ goto corrupted;
+
+ swapped = 1;
+ }
+#else
continue;
- if (dlp->d_npartitions > MAXPARTITIONS || dkcksum(dlp) != 0) {
+#endif
+ else if (dlp->d_npartitions > MAXPARTITIONS ||
+ dkcksum(dlp) != 0) {
+#ifdef DISKLABEL_EI
+corrupted:
+#endif
a->msg = "disk label corrupted";
continue;
}
@@ -613,7 +651,14 @@
switch (a->action) {
case READ_LABEL:
+#ifdef DISKLABEL_EI
+ if (swapped)
+ swap_disklabel(a->lp, dlp);
+ else
+ *a->lp = *dlp;
+#else
*a->lp = *dlp;
+#endif
if ((a->msg = convertdisklabel(a->lp, a->strat, a->bp,
a->secperunit)) != NULL)
return SCAN_ERROR;
@@ -621,7 +666,15 @@
return SCAN_FOUND;
case UPDATE_LABEL:
case WRITE_LABEL:
+#ifdef DISKLABEL_EI
+ /* DO NOT swap a->lp itself for later references. */
+ if (swapped)
+ swap_disklabel(dlp, a->lp);
+ else
+ *dlp = *a->lp;
+#else
*dlp = *a->lp;
+#endif
a->bp->b_oflags &= ~BO_DONE;
a->bp->b_flags &= ~B_READ;
a->bp->b_flags |= B_WRITE;
@@ -663,7 +716,7 @@
}
if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
- dkcksum(nlp) != 0)
+ nlp->d_npartitions > MAXPARTITIONS || dkcksum(nlp) != 0)
return (EINVAL);
/* XXX missing check if other dos partitions will be overwritten */
@@ -738,3 +791,83 @@
return validate_label(a, ptn_base);
}
+
+#ifdef DISKLABEL_EI
+/*
+ * from sh3/disksubr.c with modifications:
+ * - update d_checksum properly
+ * - replace memcpy(9) by memmove(9) as a precaution
+ */
+static void
+swap_disklabel(struct disklabel *nlp, struct disklabel *olp)
+{
+ int i;
+ uint16_t npartitions;
+
+#define SWAP16(x) nlp->x = bswap16(olp->x)
+#define SWAP32(x) nlp->x = bswap32(olp->x)
+
+ SWAP32(d_magic);
+ SWAP16(d_type);
+ SWAP16(d_subtype);
+ /* Do not need to swap char strings. */
+ memmove(nlp->d_typename, olp->d_typename, sizeof(nlp->d_typename));
+
+ /* XXX What should we do for d_un (an union of char and pointers) ? */
+ memmove(nlp->d_packname, olp->d_packname, sizeof(nlp->d_packname));
+
+ SWAP32(d_secsize);
+ SWAP32(d_nsectors);
+ SWAP32(d_ntracks);
+ SWAP32(d_ncylinders);
+ SWAP32(d_secpercyl);
+ SWAP32(d_secperunit);
+
+ SWAP16(d_sparespertrack);
+ SWAP16(d_sparespercyl);
+
+ SWAP32(d_acylinders);
+
+ SWAP16(d_rpm);
+ SWAP16(d_interleave);
+ SWAP16(d_trackskew);
+ SWAP16(d_cylskew);
+ SWAP32(d_headswitch);
+ SWAP32(d_trkseek);
+ SWAP32(d_flags);
+ for (i = 0; i < NDDATA; i++)
+ SWAP32(d_drivedata[i]);
+ for (i = 0; i < NSPARE; i++)
+ SWAP32(d_spare[i]);
+ SWAP32(d_magic2);
+ /* d_checksum is updated later. */
+
+ SWAP16(d_npartitions);
+ SWAP32(d_bbsize);
+ SWAP32(d_sbsize);
+ for (i = 0; i < MAXPARTITIONS; i++) {
+ SWAP32(d_partitions[i].p_size);
+ SWAP32(d_partitions[i].p_offset);
+ SWAP32(d_partitions[i].p_fsize);
+ /* p_fstype and p_frag is uint8_t, so no need to swap. */
+ nlp->d_partitions[i].p_fstype = olp->d_partitions[i].p_fstype;
+ nlp->d_partitions[i].p_frag = olp->d_partitions[i].p_frag;
+ SWAP16(d_partitions[i].p_cpg);
+ }
+
+#undef SWAP16
+#undef SWAP32
+
+ /* Update checksum in the target endian. */
+ nlp->d_checksum = 0;
+ npartitions = nlp->d_magic == DISKMAGIC ?
+ nlp->d_npartitions : olp->d_npartitions;
+ /*
+ * npartitions can be larger than MAXPARTITIONS when the label was not
+ * validated by setdisklabel. If so, the label is intentionally(?)
+ * corrupted and checksum should be meaningless.
+ */
+ if (npartitions <= MAXPARTITIONS)
+ nlp->d_checksum = dkcksum_sized(nlp, npartitions);
+}
+#endif /* DISKLABEL_EI */
Home |
Main Index |
Thread Index |
Old Index