Module Name:    src
Committed By:   hauke
Date:           Tue Jan 24 15:24:55 UTC 2012

Modified Files:
        src/sys/arch/macppc/macppc: disksubr.c

Log Message:
Add support for BSD disklabels, scanning the beginning of the disk
in four-byte strides, like disklabel(8) does it.

Since the netbsd-6 branch is around the corner, this is a
minimally-intrusive addition.

Note there is no write support, for good reasons.
Note also that disksubr.c is in dire need of re-structuring.


To generate a diff of this commit:
cvs rdiff -u -r1.47 -r1.48 src/sys/arch/macppc/macppc/disksubr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/macppc/macppc/disksubr.c
diff -u src/sys/arch/macppc/macppc/disksubr.c:1.47 src/sys/arch/macppc/macppc/disksubr.c:1.48
--- src/sys/arch/macppc/macppc/disksubr.c:1.47	Mon Mar 16 23:11:12 2009
+++ src/sys/arch/macppc/macppc/disksubr.c	Tue Jan 24 15:24:55 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: disksubr.c,v 1.47 2009/03/16 23:11:12 dsl Exp $	*/
+/*	$NetBSD: disksubr.c,v 1.48 2012/01/24 15:24:55 hauke Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
@@ -106,7 +106,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.47 2009/03/16 23:11:12 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.48 2012/01/24 15:24:55 hauke Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -137,6 +137,8 @@ static const char *read_mac_label(dev_t,
 		struct disklabel *, struct cpu_disklabel *);
 static const char *read_dos_label(dev_t, void (*)(struct buf *),
 		struct disklabel *, struct cpu_disklabel *);
+static const char *read_bsd_label(dev_t, void (*)(struct buf *),
+		struct disklabel *, struct cpu_disklabel *);
 static int get_netbsd_label(dev_t, void (*)(struct buf *),
 		struct disklabel *, struct cpu_disklabel *);
 
@@ -387,6 +389,78 @@ done:
 	return msg;
 }
 
+/*
+ * Scan the disk buffer in four byte strides for a native BSD
+ * disklabel (different ports have variably-sized bootcode before
+ * the label)
+ */
+static const char *
+read_bsd_label(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp,
+    struct cpu_disklabel *osdep)
+{
+	struct disklabel *dlp;
+	struct buf *bp;
+	const char *msg;
+	struct disklabel *blk_start, *blk_end;
+	int size, match;
+	
+	msg = NULL;
+
+	/* 
+	 * Read in the first #(NUM_PARTS + 1) blocks of the disk.
+	 * The native Macintosh partition table starts at 
+	 * sector #1, but we want #0 too for the BSD label.
+	 */
+	size = roundup((NUM_PARTS + 1) << DEV_BSHIFT, lp->d_secsize);
+	bp = geteblk(size);
+
+	bp->b_dev = dev;
+	bp->b_blkno = 0;
+	bp->b_resid = 0;
+	bp->b_bcount = size;
+	bp->b_flags |= B_READ;
+	bp->b_cylinder = 1 / lp->d_secpercyl;
+	(*strat)(bp);
+
+	match = 0;
+	
+	if (biowait(bp)) {
+		msg = "I/O error reading BSD disklabel";
+	} else {
+		/*
+		 * Hunt the label, starting at the beginning of the disk.
+		 * When we find an inconsistent label, report and continue.
+		 */
+		blk_start = (struct disklabel *)bp->b_data;
+		blk_end = (struct disklabel *)((char *)bp->b_data +
+		    (NUM_PARTS << DEV_BSHIFT) - sizeof(struct disklabel));
+
+		for (dlp = blk_start; dlp <= blk_end; 
+		     dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
+			if (dlp->d_magic == DISKMAGIC &&
+			    dlp->d_magic2 == DISKMAGIC) {
+				/* Sanity check */
+				if (dlp->d_npartitions <= MAXPARTITIONS && 
+				    dkcksum(dlp) == 0) {
+					*lp = *dlp;
+					match = -1;
+					break;
+#ifdef DIAGNOSTIC
+				} else {
+					printf("read_bsd_label() found "
+					    "damaged disklabel starting at "
+					    "0x0%p, ignore\n", dlp);
+#endif /* DIAGNOSTIC */
+				}
+			}
+		}
+		if (!match)
+			msg = "BSD disklabel not found";
+	}
+	brelse(bp, 0);
+	return msg;
+}
+
 /* Read MS-DOS partition table.
  *
  * XXX -
@@ -597,8 +671,9 @@ readdisklabel(dev_t dev, void (*strat)(s
 			if (!msg)
 				osdep->cd_start = 0;
 		} else {
-			msg = "no disk label -- NetBSD or Macintosh";
-			osdep->cd_start = 0;	/* XXX for now */
+			msg = read_bsd_label(dev, strat, lp, osdep);
+			if (!msg)
+				osdep->cd_start = 0;	/* XXX for now */
 		}
 	}
 

Reply via email to