Subject: Option to specify mbr sector in mbrlabel
To: None <tech-userlevel@netbsd.org>
From: Julio M. Merino Vidal <jmmv84@gmail.com>
List: tech-userlevel
Date: 12/25/2005 18:14:01
------=_Part_19019_24188799.1135530841919
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hi all,

a couple weeks ago I was lend an USB hard disk that came with
some of those drivers (OnTrack disk manager) that make old BIOS
recognize big drives.  That specific driver shifts the original MBR
to sector 63 and installs a fake one in sector 0.

I changed the mbrlabel(8) utility to use a different sector, which let
me add the required entries to the in-core disklabel.  After that, I
could access the real partitions just fine.

I cleaned up this patch by adding a new option to mbrlabel, -s,
which lets one specify the sector which is supposed to hold the
MBR.  It may be useful in situations like this.

Do you think this is an useful addition?  Patch attached.

Cheers,

PS: I also have a kernel patch to detect these drivers and use the
correct MBR by default, but I'll leave this change for another mail
as having this new option still seems good to me.

--
Julio M. Merino Vidal <jmmv84@gmail.com>
The Julipedia - http://julipedia.blogspot.com/
The NetBSD Project - http://www.NetBSD.org/

------=_Part_19019_24188799.1135530841919
Content-Type: text/x-patch; name=patch.diff; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="patch.diff"

Index: mbrlabel.8
===================================================================
RCS file: /cvsroot/src/sbin/mbrlabel/mbrlabel.8,v
retrieving revision 1.14
diff -u -r1.14 mbrlabel.8
--- mbrlabel.8	13 Jul 2003 09:56:09 -0000	1.14
+++ mbrlabel.8	25 Dec 2005 17:09:12 -0000
@@ -29,7 +29,7 @@
 .\"
 .\"	$NetBSD: mbrlabel.8,v 1.14 2003/07/13 09:56:09 lukem Exp $
 .\"
-.Dd July 13, 2003
+.Dd December 25, 2005
 .Dt MBRLABEL 8
 .Os
 .Sh NAME
@@ -38,6 +38,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl fqrw
+.Op Fl s Ar sector
 .Ar device
 .Sh DESCRIPTION
 .Nm
@@ -48,8 +49,10 @@
 other MBR using systems).
 .Pp
 .Nm
-scans the MBR contained in the very first block of the disk,
-then walks through every extended partition found and generating
+scans the MBR contained in the very first block of the disk (or the
+block specified through the
+.Fl s
+flag), then walks through every extended partition found and generating
 additional partition entries for the disk from the MBRs found in
 those extended partitions.
 .Pp
@@ -78,7 +81,7 @@
 .Pp
 Available options:
 .Pp
-.Bl -tag -width indent
+.Bl -tag -width sXsectorX
 .It Fl f
 Force an update, even if there has been no change.
 .It Fl q
@@ -89,6 +92,12 @@
 In conjunction with
 .Fl w ,
 also update the on-disk label.
+.It Fl s Ar sector
+Specifies the logical sector number that has to be read from the disk
+in order to find the MBR.
+Useful if the disk has remapping drivers on it and the MBR is located
+in a non-standard place.
+Defaults to 0.
 .El
 .Sh SEE ALSO
 .Xr disklabel 8 ,
Index: mbrlabel.c
===================================================================
RCS file: /cvsroot/src/sbin/mbrlabel/mbrlabel.c,v
retrieving revision 1.24
diff -u -r1.24 mbrlabel.c
--- mbrlabel.c	5 Jan 2004 23:23:33 -0000	1.24
+++ mbrlabel.c	25 Dec 2005 17:09:12 -0000
@@ -37,7 +37,10 @@
 #endif /* not lint */
 
 #include <stdio.h>
+#include <err.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -128,7 +131,11 @@
 		exit(1);
 	}
 	if (read(sd, buf, sizeof buf) != DEV_BSIZE) {
-		perror("read label");
+		if (off != MBR_BBSECTOR)
+			perror("read label (sector is possibly out of "
+			    "range)");
+		else
+			perror("read label");
 		exit(1);
 	}
 	if (getshort(buf + MBR_MAGIC_OFFSET) != MBR_MAGIC)
@@ -233,7 +240,8 @@
 void
 usage(void)
 {
-	fprintf(stderr, "usage: %s [-fqrw] rawdisk\n", getprogname());
+	fprintf(stderr, "usage: %s [-fqrw] [-s sector] rawdisk\n",
+	    getprogname());
 	exit(1);
 }
 
@@ -242,17 +250,19 @@
 main(int argc, char **argv)
 {
 	int	sd, ch, changed;
-	char	name[MAXPATHLEN];
+	char	*ep, name[MAXPATHLEN];
 	int	force;			/* force label update */
 	int	raw;			/* update on-disk label as well */
 	int	verbose;		/* verbose output */
 	int	write_it;		/* update in-core label if changed */
+	uint32_t sector;		/* sector that contains the MBR */
 
 	force = 0;
 	raw = 0;
 	verbose = 1;
 	write_it = 0;
-	while ((ch = getopt(argc, argv, "fqrw")) != -1) {
+	sector = MBR_BBSECTOR;
+	while ((ch = getopt(argc, argv, "fqrs:w")) != -1) {
 		switch (ch) {
 		case 'f':
 			force = 1;
@@ -263,6 +273,20 @@
 		case 'r':
 			raw = 1;
 			break;
+		case 's':
+			errno = 0;
+			sector = strtoul(optarg, &ep, 10);
+			if (optarg[0] == '\0' || *ep != '\0')
+				errx(EXIT_FAILURE,
+				    "sector number (%s) incorrectly specified",
+				    optarg);
+			if ((errno == ERANGE && sector == ULONG_MAX) ||
+			    sector > UINT32_MAX)
+			    	errx(EXIT_FAILURE,
+				    "sector number (%s) out of range",
+				    optarg);
+
+			break;
 		case 'w':
 			write_it = 1;
 			break;
@@ -281,7 +305,7 @@
 		exit(1);
 	}
 	getlabel(sd);
-	changed = getparts(sd, MBR_BBSECTOR, 0, verbose);
+	changed = getparts(sd, sector, 0, verbose);
 
 	if (verbose) {
 		putchar('\n');

------=_Part_19019_24188799.1135530841919--