PR kern/51208
Add DISKLABEL_EI (``Endian-Independent'' disklabel) kernel option to machines that support Master Boot Record (MBR)
This commit is contained in:
parent
15b3afa8c3
commit
ede747a0c4
@ -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 @@ This enables for example sshfs:
|
||||
.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
|
||||
|
@ -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 validate_label(mbr_args_t *, uint);
|
||||
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 @@ look_netbsd_part(mbr_args_t *a, mbr_partition_t *dp, int slot, uint ext_base)
|
||||
}
|
||||
|
||||
|
||||
#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 @@ validate_label(mbr_args_t *a, uint label_sector)
|
||||
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 @@ validate_label(mbr_args_t *a, uint label_sector)
|
||||
|
||||
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 @@ validate_label(mbr_args_t *a, uint label_sector)
|
||||
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 @@ setdisklabel(struct disklabel *olp, struct disklabel *nlp, u_long openmask,
|
||||
}
|
||||
|
||||
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 @@ write_netbsd_label(mbr_args_t *a, mbr_partition_t *dp, int slot, uint ext_base)
|
||||
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user