Subject: Re: wedges dump autoconfiguration code
To: None <tech-kern@NetBSD.org>
From: David Young <dyoung@pobox.com>
List: tech-kern
Date: 06/20/2007 14:13:45
--9amGYk9869ThD9tj
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Wed, Jun 20, 2007 at 02:12:33PM -0500, David Young wrote:
> On Wed, Jun 20, 2007 at 01:46:25PM -0500, David Young wrote:
> > On Wed, Jun 20, 2007 at 01:56:06PM -0400, Christos Zoulas wrote:
> > > 
> > > And merging of the disklabel compat wedge code (we had 3 copies).
> > 
> > You can share handle_wedges with sparc64, too.  Let me send you my
> > patches.
> 
> These patches create config_handle_wedges() for both x86 and
> sparc64 to use.  On x86, handle_wedges() is a thin wrapper for
> config_handle_wedges().

Oops, here are the patches.

Dave

-- 
David Young             OJC Technologies
dyoung@ojctech.com      Urbana, IL * (217) 278-3933 ext 24

--9amGYk9869ThD9tj
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="dk.patches"

Index: arch/evbmips/evbmips/disksubr.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbmips/evbmips/disksubr.c,v
retrieving revision 1.12
diff -p -u -u -p -r1.12 disksubr.c
--- arch/evbmips/evbmips/disksubr.c	6 Mar 2007 00:48:08 -0000	1.12
+++ arch/evbmips/evbmips/disksubr.c	20 Jun 2007 18:40:09 -0000
@@ -54,6 +54,7 @@ readdisklabel(dev_t dev, void (*strat)(s
 	struct disklabel *dlp;
 	struct dkbad *bdp;
 	const char *msg = NULL;
+	uint32_t secperunit;
 	int i;
 
 	/* minimal requirements for archtypal disk label */
@@ -66,19 +67,16 @@ readdisklabel(dev_t dev, void (*strat)(s
 		lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
 	lp->d_partitions[RAW_PART].p_offset = 0;
 
+	secperunit = lp->d_secperunit;
+
 	/* obtain buffer to probe drive with */
 	bp = geteblk((int)lp->d_secsize);
-
-	/* next, dig out disk label */
 	bp->b_dev = dev;
-	bp->b_blkno = LABELSECTOR;
-	bp->b_cylinder = 0;
-	bp->b_bcount = lp->d_secsize;
-	bp->b_flags |= B_READ;
-	(*strat)(bp);
 
-	/* if successful, locate disk label within block and validate */
-	if (biowait(bp)) {
+	/* Next, dig out disk label.  If successful, locate disk
+	 * label within block and validate.
+	 */
+	if (disk_read_sectors(strat, lp, bp, LABELSECTOR, 1) != 0) {
 		msg = "disk label read error";
 		goto done;
 	}
@@ -103,6 +101,9 @@ readdisklabel(dev_t dev, void (*strat)(s
 	if (msg)
 		goto done;
 
+	if ((msg = convertdisklabel(lp, strat, bp, secperunit)) != NULL)
+		goto done;
+
 	/* obtain bad sector table if requested and present */
 	if (clp && (bdp = &clp->bad) != NULL && (lp->d_flags & D_BADSECT)) {
 		struct dkbad *db;
Index: arch/sparc64/sparc64/autoconf.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/autoconf.c,v
retrieving revision 1.137
diff -p -u -u -p -r1.137 autoconf.c
--- arch/sparc64/sparc64/autoconf.c	4 Mar 2007 06:00:50 -0000	1.137
+++ arch/sparc64/sparc64/autoconf.c	20 Jun 2007 18:40:15 -0000
@@ -430,58 +430,9 @@ cpu_configure(void)
 	(void)spl0();
 }
 
-static struct vnode *
-opendisk(struct device *dv)
-{
-	int bmajor, bminor;
-	struct vnode *tmpvn;
-	int error;
-	dev_t dev;
-	
-	/*
-	 * Lookup major number for disk block device.
-	 */
-	bmajor = devsw_name2blk(device_xname(dv), NULL, 0);
-	if (bmajor == -1)
-		return NULL;
-	
-	bminor = minor(device_unit(dv));
-	/*
-	 * Fake a temporary vnode for the disk, open it, and read
-	 * and hash the sectors.
-	 */
-	dev = device_is_a(dv, "dk") ? makedev(bmajor, bminor) :
-	    MAKEDISKDEV(bmajor, bminor, RAW_PART);
-	if (bdevvp(dev, &tmpvn))
-		panic("%s: can't alloc vnode for %s", __func__,
-		    device_xname(dv));
-	error = VOP_OPEN(tmpvn, FREAD, NOCRED, 0);
-	if (error) {
-#ifndef DEBUG
-		/*
-		 * Ignore errors caused by missing device, partition,
-		 * or medium.
-		 */
-		if (error != ENXIO && error != ENODEV)
-#endif
-			printf("%s: can't open dev %s (%d)\n",
-			    __func__, device_xname(dv), error);
-		vput(tmpvn);
-		return NULL;
-	}
-
-	return tmpvn;
-}
-
 void
 cpu_rootconf(void)
 {
-	struct dkwedge_list wl;
-	struct dkwedge_info *wi;
-	struct vnode *vn;
-	char diskname[16];
-	int i, error;
-
 	if (booted_device == NULL) {
 		printf("FATAL: boot device not found, check your firmware "
 		    "settings!\n");
@@ -489,37 +440,10 @@ cpu_rootconf(void)
 		return;
 	}
 
-	if ((vn = opendisk(booted_device)) == NULL)
-		goto nowedge;
-
-	wl.dkwl_bufsize = sizeof(*wi) * 16;
-	wl.dkwl_buf = wi = malloc(wl.dkwl_bufsize, M_TEMP, M_WAITOK);
-	error = VOP_IOCTL(vn, DIOCLWEDGES, &wl, FREAD, NOCRED, 0);
-	VOP_CLOSE(vn, FREAD, NOCRED, 0);
-	vput(vn);
-	if (error)
-		goto nowedge2;
-
-	snprintf(diskname, sizeof(diskname), "%s%c",
-	    device_xname(booted_device),
-	    booted_partition + 'a');
-
-	for (i = 0; i < wl.dkwl_ncopied; i++) {
-		if (strcmp(wi[i].dkw_wname, diskname) == 0)
-			break;
-	}
-	if (i == wl.dkwl_ncopied)
-		goto nowedge2;
-
-	dkwedge_set_bootwedge(booted_device, wi[i].dkw_offset, wi[i].dkw_size);
-	free(wi, M_TEMP);
-	setroot(booted_wedge, 0);
-	return;
-
-nowedge2:
-	free(wi, M_TEMP);
-nowedge:
-	setroot(booted_device, booted_partition);
+	if (config_handle_wedges(booted_device, booted_partition) == 0)
+		setroot(booted_wedge, 0);
+	else
+		setroot(booted_device, booted_partition);
 }
 
 char *
Index: arch/x86/x86/x86_autoconf.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/x86_autoconf.c,v
retrieving revision 1.25
diff -p -u -u -p -r1.25 x86_autoconf.c
--- arch/x86/x86/x86_autoconf.c	4 Mar 2007 06:01:09 -0000	1.25
+++ arch/x86/x86/x86_autoconf.c	20 Jun 2007 18:40:16 -0000
@@ -65,114 +65,15 @@ __KERNEL_RCSID(0, "$NetBSD");
 struct disklist *x86_alldisks;
 int x86_ndisks;
 
-static struct vnode *
-opendisk(struct device *dv)
-{
-	int bmajor, bminor;
-	struct vnode *tmpvn;
-	int error;
-	dev_t dev;
-	
-	/*
-	 * Lookup major number for disk block device.
-	 */
-	bmajor = devsw_name2blk(dv->dv_xname, NULL, 0);
-	if (bmajor == -1)
-		return NULL;
-	
-	bminor = minor(device_unit(dv));
-	/*
-	 * Fake a temporary vnode for the disk, open it, and read
-	 * and hash the sectors.
-	 */
-	dev = device_is_a(dv, "dk") ? makedev(bmajor, bminor) :
-	    MAKEDISKDEV(bmajor, bminor, RAW_PART);
-	if (bdevvp(dev, &tmpvn))
-		panic("%s: can't alloc vnode for %s", __func__, dv->dv_xname);
-	error = VOP_OPEN(tmpvn, FREAD, NOCRED, 0);
-	if (error) {
-#ifndef DEBUG
-		/*
-		 * Ignore errors caused by missing device, partition,
-		 * or medium.
-		 */
-		if (error != ENXIO && error != ENODEV)
-#endif
-			printf("%s: can't open dev %s (%d)\n",
-			    __func__, dv->dv_xname, error);
-		vput(tmpvn);
-		return NULL;
-	}
-
-	return tmpvn;
-}
-
 static void
 handle_wedges(struct device *dv, int par)
 {
-	struct dkwedge_list wl;
-	struct dkwedge_info *wi;
-	struct vnode *vn;
-	char diskname[16];
-	int i, error;
-
-	if ((vn = opendisk(dv)) == NULL)
-		goto out;
-
-	wl.dkwl_bufsize = sizeof(*wi) * 16;
-	wl.dkwl_buf = wi = malloc(wl.dkwl_bufsize, M_TEMP, M_WAITOK);
-
-	error = VOP_IOCTL(vn, DIOCLWEDGES, &wl, FREAD, NOCRED, 0);
-	VOP_CLOSE(vn, FREAD, NOCRED, 0);
-	vput(vn);
-	if (error) {
-#ifdef DEBUG_WEDGE
-		printf("%s: List wedges returned %d\n", dv->dv_xname, error);
-#endif
-		free(wi, M_TEMP);
-		goto out;
-	}
-
-#ifdef DEBUG_WEDGE
-	printf("%s: Returned %u(%u) wedges\n", dv->dv_xname,
-	    wl.dkwl_nwedges, wl.dkwl_ncopied);
-#endif
-	snprintf(diskname, sizeof(diskname), "%s%c", dv->dv_xname,
-	    par + 'a');
-
-	for (i = 0; i < wl.dkwl_ncopied; i++) {
-#ifdef DEBUG_WEDGE
-		printf("%s: Looking for %s in %s\n", 
-		    dv->dv_xname, diskname, wi[i].dkw_wname);
-#endif
-		if (strcmp(wi[i].dkw_wname, diskname) == 0)
-			break;
-	}
-
-	if (i == wl.dkwl_ncopied) {
-#ifdef DEBUG_WEDGE
-		printf("%s: Cannot find wedge with parent %s\n",
-		    dv->dv_xname, diskname);
-#endif
-		free(wi, M_TEMP);
-		goto out;
-	}
-
-#ifdef DEBUG_WEDGE
-	printf("%s: Setting boot wedge %s (%s) at %llu %llu\n", 
-		dv->dv_xname, wi[i].dkw_devname, wi[i].dkw_wname,
-		(unsigned long long)wi[i].dkw_offset,
-		(unsigned long long)wi[i].dkw_size);
-#endif
-	dkwedge_set_bootwedge(dv, wi[i].dkw_offset, wi[i].dkw_size);
-	free(wi, M_TEMP);
-	return;
-out:
+	if (config_handle_wedges(dv, par) == 0)
+		return;
 	booted_device = dv;
 	booted_partition = par;
 }
 
-
 static int
 is_valid_disk(struct device *dv)
 {
Index: arch/xen/i386/autoconf.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/i386/autoconf.c,v
retrieving revision 1.22
diff -p -u -u -p -r1.22 autoconf.c
--- arch/xen/i386/autoconf.c	29 Jan 2007 01:52:46 -0000	1.22
+++ arch/xen/i386/autoconf.c	20 Jun 2007 18:40:17 -0000
@@ -94,7 +94,6 @@ static int match_harddisk(struct device 
 static void matchbiosdisks(void);
 static void findroot(void);
 static int is_valid_disk(struct device *);
-static struct vnode *opendisk(struct device *);
 static void handle_wedges(struct device *, int);
 
 struct disklist *x86_alldisks;
@@ -570,104 +569,11 @@ found:
 	booted_device = dev;
 }
 
-static struct vnode *
-opendisk(struct device *dv)
-{
-	int bmajor;
-	struct vnode *tmpvn;
-	int error;
-	
-	/*
-	 * Lookup major number for disk block device.
-	 */
-	bmajor = devsw_name2blk(dv->dv_xname, NULL, 0);
-	if (bmajor == -1)
-		return NULL;
-	
-	/*
-	 * Fake a temporary vnode for the disk, open it, and read
-	 * and hash the sectors.
-	 */
-	if (bdevvp(MAKEDISKDEV(bmajor, device_unit(dv), RAW_PART), &tmpvn))
-		panic("%s: can't alloc vnode for %s", __func__, dv->dv_xname);
-	error = VOP_OPEN(tmpvn, FREAD, NOCRED, 0);
-	if (error) {
-#ifndef DEBUG
-		/*
-		 * Ignore errors caused by missing device, partition,
-		 * or medium.
-		 */
-		if (error != ENXIO && error != ENODEV)
-#endif
-			printf("%s: can't open dev %s (%d)\n",
-			    __func__, dv->dv_xname, error);
-		vput(tmpvn);
-		return NULL;
-	}
-
-	return tmpvn;
-}
-
 static void
 handle_wedges(struct device *dv, int par)
 {
-	struct dkwedge_list wl;
-	struct dkwedge_info *wi;
-	struct vnode *vn;
-	char diskname[16];
-	int i, error;
-
-	if ((vn = opendisk(dv)) == NULL)
-		goto out;
-
-	wl.dkwl_bufsize = sizeof(*wi) * 16;
-	wl.dkwl_buf = wi = malloc(wl.dkwl_bufsize, M_TEMP, M_WAITOK);
-
-	error = VOP_IOCTL(vn, DIOCLWEDGES, &wl, FREAD, NOCRED, 0);
-	vput(vn);
-	if (error) {
-#ifdef DEBUG_WEDGE
-		printf("%s: List wedges returned %d\n", dv->dv_xname, error);
-#endif
-		free(wi, M_TEMP);
-		goto out;
-	}
-
-#ifdef DEBUG_WEDGE
-	printf("%s: Returned %u(%u) wedges\n", dv->dv_xname,
-	    wl.dkwl_nwedges, wl.dkwl_ncopied);
-#endif
-	snprintf(diskname, sizeof(diskname), "%s%c", dv->dv_xname,
-	    par + 'a');
-
-	for (i = 0; i < wl.dkwl_ncopied; i++) {
-#ifdef DEBUG_WEDGE
-		printf("%s: Looking for %s in %s\n", 
-		    dv->dv_xname, diskname, wi[i].dkw_wname);
-#endif
-		if (strcmp(wi[i].dkw_wname, diskname) == 0)
-			break;
-	}
-
-	if (i == wl.dkwl_ncopied) {
-#ifdef DEBUG_WEDGE
-		printf("%s: Cannot find wedge with parent %s\n",
-		    dv->dv_xname, diskname);
-#endif
-		free(wi, M_TEMP);
-		goto out;
-	}
-
-#ifdef DEBUG_WEDGE
-	printf("%s: Setting boot wedge %s (%s) at %llu %llu\n", 
-		dv->dv_xname, wi[i].dkw_devname, wi[i].dkw_wname,
-		(unsigned long long)wi[i].dkw_offset,
-		(unsigned long long)wi[i].dkw_size);
-#endif
-	dkwedge_set_bootwedge(dv, wi[i].dkw_offset, wi[i].dkw_size);
-	free(wi, M_TEMP);
-	return;
-out:
+	if (config_handle_wedges(dv, par) == 0)
+		return;
 	booted_device = dv;
 	booted_partition = par;
 }
Index: dev/dkwedge/dk.c
===================================================================
RCS file: /cvsroot/src/sys/dev/dkwedge/dk.c,v
retrieving revision 1.24
diff -p -u -u -p -r1.24 dk.c
--- dev/dkwedge/dk.c	16 Jun 2007 18:11:33 -0000	1.24
+++ dev/dkwedge/dk.c	20 Jun 2007 18:40:20 -0000
@@ -642,6 +642,47 @@ dkwedge_list(struct disk *pdk, struct dk
 	return (error);
 }
 
+device_t
+dkwedge_find_by_wname(const char *wname)
+{
+	device_t dv = NULL;
+	struct dkwedge_softc *sc;
+	int i;
+
+	(void) lockmgr(&dkwedges_lock, LK_EXCLUSIVE, NULL);
+	for (i = 0; i < ndkwedges; i++) {
+		if ((sc = dkwedges[i]) == NULL)
+			continue;
+		if (strcmp(sc->sc_wname, wname) == 0) {
+			if (dv != NULL) {
+				printf(
+				    "WARNING: double match for wedge name %s "
+				    "(%s, %s)\n", wname, device_xname(dv),
+				    device_xname(sc->sc_dev));
+				continue;
+			}
+			dv = sc->sc_dev;
+		}
+	}
+	(void) lockmgr(&dkwedges_lock, LK_RELEASE, NULL);
+	return dv;
+}
+
+void
+dkwedge_print_wnames(void)
+{
+	struct dkwedge_softc *sc;
+	int i;
+
+	(void) lockmgr(&dkwedges_lock, LK_EXCLUSIVE, NULL);
+	for (i = 0; i < ndkwedges; i++) {
+		if ((sc = dkwedges[i]) == NULL)
+			continue;
+		printf(" wedge:%s", sc->sc_wname);
+	}
+	(void) lockmgr(&dkwedges_lock, LK_RELEASE, NULL);
+}
+
 /*
  * dkwedge_set_bootwedge
  *
Index: kern/kern_subr.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_subr.c,v
retrieving revision 1.156
diff -p -u -u -p -r1.156 kern_subr.c
--- kern/kern_subr.c	8 Mar 2007 21:25:27 -0000	1.156
+++ kern/kern_subr.c	20 Jun 2007 18:40:26 -0000
@@ -104,6 +104,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_subr.c,
 #include <sys/device.h>
 #include <sys/reboot.h>
 #include <sys/conf.h>
+#include <sys/disk.h>
 #include <sys/disklabel.h>
 #include <sys/queue.h>
 #include <sys/systrace.h>
@@ -121,6 +122,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_subr.c,
 static struct device *finddevice(const char *);
 static struct device *getdisk(char *, int, int, dev_t *, int);
 static struct device *parsedisk(char *, int, int, dev_t *);
+static const char *getwedgename(const char *, int);
 
 /*
  * A generic linear hook.
@@ -806,7 +808,7 @@ void
 setroot(struct device *bootdv, int bootpartition)
 {
 	struct device *dv;
-	int len;
+	int len, majdev;
 #ifdef MEMORY_DISK_HOOKS
 	int i;
 #endif
@@ -1001,8 +1003,6 @@ setroot(struct device *bootdv, int bootp
 		}
 
 	} else if (rootspec == NULL) {
-		int majdev;
-
 		/*
 		 * Wildcarded root; use the boot device.
 		 */
@@ -1037,6 +1037,11 @@ setroot(struct device *bootdv, int bootp
 			goto haveroot;
 		}
 
+		if (rootdev == NODEV &&
+		    device_class(dv) == DV_DISK && device_is_a(dv, "dk") &&
+		    (majdev = devsw_name2blk(dv->dv_xname, NULL, 0)) >= 0)
+			rootdev = makedev(majdev, device_unit(dv));
+
 		rootdevname = devsw_blk2name(major(rootdev));
 		if (rootdevname == NULL) {
 			printf("unknown device major 0x%x\n", rootdev);
@@ -1142,25 +1147,27 @@ setroot(struct device *bootdv, int bootp
 static struct device *
 finddevice(const char *name)
 {
+	const char *wname;
 	struct device *dv;
 #if defined(BOOT_FROM_MEMORY_HOOKS)
 	int j;
 #endif /* BOOT_FROM_MEMORY_HOOKS */
 
+	if ((wname = getwedgename(name, strlen(name))) != NULL)
+		return dkwedge_find_by_wname(wname);
+
 #ifdef BOOT_FROM_MEMORY_HOOKS
 	for (j = 0; j < NMD; j++) {
-		if (strcmp(name, fakemdrootdev[j].dv_xname) == 0) {
-			dv = &fakemdrootdev[j];
-			return (dv);
-		}
+		if (strcmp(name, fakemdrootdev[j].dv_xname) == 0)
+			return &fakemdrootdev[j];
 	}
 #endif /* BOOT_FROM_MEMORY_HOOKS */
 
-	for (dv = TAILQ_FIRST(&alldevs); dv != NULL;
-	    dv = TAILQ_NEXT(dv, dv_list))
+	TAILQ_FOREACH(dv, &alldevs, dv_list) {
 		if (strcmp(dv->dv_xname, name) == 0)
 			break;
-	return (dv);
+	}
+	return dv;
 }
 
 static struct device *
@@ -1188,6 +1195,7 @@ getdisk(char *str, int len, int defpart,
 			if (isdump == 0 && device_class(dv) == DV_IFNET)
 				printf(" %s", dv->dv_xname);
 		}
+		dkwedge_print_wnames();
 		if (isdump)
 			printf(" none");
 #if defined(DDB)
@@ -1195,13 +1203,26 @@ getdisk(char *str, int len, int defpart,
 #endif
 		printf(" halt reboot\n");
 	}
-	return (dv);
+	return dv;
+}
+
+static const char *
+getwedgename(const char *name, int namelen)
+{
+	const char *wpfx = "wedge:";
+	const int wpfxlen = strlen(wpfx);
+
+	if (namelen < wpfxlen || strncmp(name, wpfx, wpfxlen) != 0)
+		return NULL;
+
+	return name + wpfxlen;
 }
 
 static struct device *
 parsedisk(char *str, int len, int defpart, dev_t *devp)
 {
 	struct device *dv;
+	const char *wname;
 	char *cp, c;
 	int majdev, part;
 #ifdef MEMORY_DISK_HOOKS
@@ -1221,7 +1242,13 @@ parsedisk(char *str, int len, int defpar
 
 	cp = str + len - 1;
 	c = *cp;
-	if (c >= 'a' && c <= ('a' + MAXPARTITIONS - 1)) {
+
+	if ((wname = getwedgename(str, len)) != NULL) {
+		if ((dv = dkwedge_find_by_wname(wname)) == NULL)
+			return NULL;
+		part = defpart;
+		goto gotdisk;
+	} else if (c >= 'a' && c <= ('a' + MAXPARTITIONS - 1)) {
 		part = c - 'a';
 		*cp = '\0';
 	} else
@@ -1238,9 +1265,7 @@ parsedisk(char *str, int len, int defpar
 	dv = finddevice(str);
 	if (dv != NULL) {
 		if (device_class(dv) == DV_DISK) {
-#ifdef MEMORY_DISK_HOOKS
  gotdisk:
-#endif
 			majdev = devsw_name2blk(dv->dv_xname, NULL, 0);
 			if (majdev < 0)
 				panic("parsedisk");
Index: kern/subr_autoconf.c
===================================================================
RCS file: /cvsroot/src/sys/kern/subr_autoconf.c,v
retrieving revision 1.117
diff -p -u -u -p -r1.117 subr_autoconf.c
--- kern/subr_autoconf.c	5 Mar 2007 20:32:45 -0000	1.117
+++ kern/subr_autoconf.c	20 Jun 2007 18:40:28 -0000
@@ -83,12 +83,28 @@ __KERNEL_RCSID(0, "$NetBSD: subr_autocon
 
 #include <sys/param.h>
 #include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/conf.h>
+#include <sys/kauth.h>
 #include <sys/malloc.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/errno.h>
 #include <sys/proc.h>
 #include <sys/reboot.h>
+
+#include <sys/buf.h>
+#include <sys/dirent.h>
+#include <sys/lock.h>
+#include <sys/vnode.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/unistd.h>
+#include <sys/fcntl.h>
+#include <sys/lockf.h>
+
+#include <sys/disk.h>
+
 #include <machine/limits.h>
 
 #include "opt_userconf.h"
@@ -187,6 +203,112 @@ static int config_initialized;		/* confi
 
 static int config_do_twiddle;
 
+struct vnode *
+opendisk(struct device *dv)
+{
+	int bmajor, bminor;
+	struct vnode *tmpvn;
+	int error;
+	dev_t dev;
+	
+	/*
+	 * Lookup major number for disk block device.
+	 */
+	bmajor = devsw_name2blk(device_xname(dv), NULL, 0);
+	if (bmajor == -1)
+		return NULL;
+	
+	bminor = minor(device_unit(dv));
+	/*
+	 * Fake a temporary vnode for the disk, open it, and read
+	 * and hash the sectors.
+	 */
+	dev = device_is_a(dv, "dk") ? makedev(bmajor, bminor) :
+	    MAKEDISKDEV(bmajor, bminor, RAW_PART);
+	if (bdevvp(dev, &tmpvn))
+		panic("%s: can't alloc vnode for %s", __func__,
+		    device_xname(dv));
+	error = VOP_OPEN(tmpvn, FREAD, NOCRED, 0);
+	if (error) {
+#ifndef DEBUG
+		/*
+		 * Ignore errors caused by missing device, partition,
+		 * or medium.
+		 */
+		if (error != ENXIO && error != ENODEV)
+#endif
+			printf("%s: can't open dev %s (%d)\n",
+			    __func__, device_xname(dv), error);
+		vput(tmpvn);
+		return NULL;
+	}
+
+	return tmpvn;
+}
+
+int
+config_handle_wedges(struct device *dv, int par)
+{
+	struct dkwedge_list wl;
+	struct dkwedge_info *wi;
+	struct vnode *vn;
+	char diskname[16];
+	int i, error;
+
+	if ((vn = opendisk(dv)) == NULL)
+		return -1;
+
+	wl.dkwl_bufsize = sizeof(*wi) * 16;
+	wl.dkwl_buf = wi = malloc(wl.dkwl_bufsize, M_TEMP, M_WAITOK);
+
+	error = VOP_IOCTL(vn, DIOCLWEDGES, &wl, FREAD, NOCRED, 0);
+	VOP_CLOSE(vn, FREAD, NOCRED, 0);
+	vput(vn);
+	if (error) {
+#ifdef DEBUG_WEDGE
+		printf("%s: List wedges returned %d\n",
+		    device_xname(dv), error);
+#endif
+		free(wi, M_TEMP);
+		return -1;
+	}
+
+#ifdef DEBUG_WEDGE
+	printf("%s: Returned %u(%u) wedges\n", device_xname(dv),
+	    wl.dkwl_nwedges, wl.dkwl_ncopied);
+#endif
+	snprintf(diskname, sizeof(diskname), "%s%c", device_xname(dv),
+	    par + 'a');
+
+	for (i = 0; i < wl.dkwl_ncopied; i++) {
+#ifdef DEBUG_WEDGE
+		printf("%s: Looking for %s in %s\n", 
+		    device_xname(dv), diskname, wi[i].dkw_wname);
+#endif
+		if (strcmp(wi[i].dkw_wname, diskname) == 0)
+			break;
+	}
+
+	if (i == wl.dkwl_ncopied) {
+#ifdef DEBUG_WEDGE
+		printf("%s: Cannot find wedge with parent %s\n",
+		    device_xname(dv), diskname);
+#endif
+		free(wi, M_TEMP);
+		return -1;
+	}
+
+#ifdef DEBUG_WEDGE
+	printf("%s: Setting boot wedge %s (%s) at %llu %llu\n", 
+		device_xname(dv), wi[i].dkw_devname, wi[i].dkw_wname,
+		(unsigned long long)wi[i].dkw_offset,
+		(unsigned long long)wi[i].dkw_size);
+#endif
+	dkwedge_set_bootwedge(dv, wi[i].dkw_offset, wi[i].dkw_size);
+	free(wi, M_TEMP);
+	return 0;
+}
+
 /*
  * Initialize the autoconfiguration data structures.  Normally this
  * is done by configure(), but some platforms need to do this very
Index: kern/subr_disk.c
===================================================================
RCS file: /cvsroot/src/sys/kern/subr_disk.c,v
retrieving revision 1.85
diff -p -u -u -p -r1.85 subr_disk.c
--- kern/subr_disk.c	4 Mar 2007 06:03:07 -0000	1.85
+++ kern/subr_disk.c	20 Jun 2007 18:40:28 -0000
@@ -266,6 +266,7 @@ disk_detach(struct disk *diskp)
 {
 
 	(void) lockmgr(&diskp->dk_openlock, LK_DRAIN, NULL);
+	(void) lockmgr(&diskp->dk_rawlock, LK_DRAIN, NULL);
 	disk_detach0(diskp);
 }
 
@@ -430,6 +431,81 @@ bad:
 	return (-1);
 }
 
+int
+disk_read_sectors(void (*strat)(struct buf *), const struct disklabel *lp,
+    struct buf *bp, unsigned int sector, int count)
+{
+	bp->b_blkno = sector;
+	bp->b_bcount = count * lp->d_secsize;
+	bp->b_flags = (bp->b_flags & ~(B_WRITE | B_DONE)) | B_READ;
+	bp->b_cylinder = sector / lp->d_secpercyl;
+	(*strat)(bp);
+	return biowait(bp);
+}
+
+const char *
+convertdisklabel(struct disklabel *lp, void (*strat)(struct buf *),
+    struct buf *bp, uint32_t secperunit)
+{
+	struct partition rp, *altp, *p;
+	int geom_ok;
+
+	memset(&rp, 0, sizeof(rp));
+	rp.p_size = secperunit;
+	rp.p_fstype = FS_UNUSED;
+
+	/* If we can seek to d_secperunit - 1, believe the disk geometry. */
+	if (secperunit != 0 &&
+	    disk_read_sectors(strat, lp, bp, secperunit - 1, 1) == 0)
+		geom_ok = 1;
+	else
+		geom_ok = 0;
+
+#if 0
+	printf("%s: secperunit (%" PRIu32 ") %s\n", __func__,
+	    secperunit, geom_ok ? "ok" : "not ok");
+#endif
+
+	p = &lp->d_partitions[RAW_PART];
+	if (RAW_PART == 'c' - 'a')
+		altp = &lp->d_partitions['d' - 'a'];
+	else
+		altp = &lp->d_partitions['c' - 'a'];
+
+	if (lp->d_npartitions > RAW_PART && p->p_offset == 0 && p->p_size != 0)
+		;	/* already a raw partition */
+	else if (lp->d_npartitions > MAX('c', 'd') - 'a' &&
+		 altp->p_offset == 0 && altp->p_size != 0) {
+		/* alternate partition ('c' or 'd') is suitable for raw slot,
+		 * swap with 'd' or 'c'.
+		 */
+		rp = *p;
+		*p = *altp;
+		*altp = rp;
+	} else if (lp->d_npartitions <= RAW_PART &&
+	           lp->d_npartitions > 'c' - 'a') {
+		/* No raw partition is present, but the alternate is present.
+		 * Copy alternate to raw partition.
+		 */
+		lp->d_npartitions = RAW_PART + 1;
+		*p = *altp;
+	} else if (!geom_ok)
+		return "no raw partition and disk reports bad geometry";
+	else if (lp->d_npartitions <= RAW_PART) {
+		memset(&lp->d_partitions[lp->d_npartitions], 0,
+		    sizeof(struct partition) * (RAW_PART - lp->d_npartitions));
+		*p = rp;
+		lp->d_npartitions = RAW_PART + 1;
+	} else if (lp->d_npartitions < MAXPARTITIONS) {
+		memmove(p + 1, p,
+		    sizeof(struct partition) * (lp->d_npartitions - RAW_PART));
+		*p = rp;
+		lp->d_npartitions++;
+	} else
+		return "no raw partition and partition table is full";
+	return NULL;
+}
+
 /*
  * disk_ioctl --
  *	Generic disk ioctl handling.
Index: kern/subr_disk_mbr.c
===================================================================
RCS file: /cvsroot/src/sys/kern/subr_disk_mbr.c,v
retrieving revision 1.26
diff -p -u -u -p -r1.26 subr_disk_mbr.c
--- kern/subr_disk_mbr.c	4 Mar 2007 06:03:07 -0000	1.26
+++ kern/subr_disk_mbr.c	20 Jun 2007 18:40:28 -0000
@@ -59,6 +59,7 @@ __KERNEL_RCSID(0, "$NetBSD: subr_disk_mb
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/buf.h>
+#include <sys/bootblock.h>
 #include <sys/disklabel.h>
 #include <sys/disk.h>
 #include <sys/syslog.h>
@@ -92,6 +93,7 @@ typedef struct mbr_args {
 	int		found_mbr;	/* set if disk has a valid mbr */
 	uint		label_sector;	/* where we found the label */
 	int		action;
+	uint32_t	secperunit;
 #define READ_LABEL	1
 #define UPDATE_LABEL	2
 #define WRITE_LABEL	3
@@ -104,15 +106,9 @@ static int write_netbsd_label(mbr_args_t
 static int
 read_sector(mbr_args_t *a, uint sector, int count)
 {
-	struct buf *bp = a->bp;
 	int error;
 
-	bp->b_blkno = sector;
-	bp->b_bcount = count * a->lp->d_secsize;
-	bp->b_flags = (bp->b_flags & ~(B_WRITE | B_DONE)) | B_READ;
-	bp->b_cylinder = sector / a->lp->d_secpercyl;
-	(*a->strat)(bp);
-	error = biowait(bp);
+	error = disk_read_sectors(a->strat, a->lp, a->bp, sector, count);
 	if (error != 0)
 		a->error = error;
 	return error;
@@ -264,6 +260,7 @@ readdisklabel(dev_t dev, void (*strat)(s
 		lp->d_secsize = DEV_BSIZE;
 	if (lp->d_secperunit == 0)
 		lp->d_secperunit = 0x1fffffff;
+	a.secperunit = lp->d_secperunit;
 	lp->d_npartitions = RAW_PART + 1;
 	for (i = 0; i < RAW_PART; i++) {
 		lp->d_partitions[i].p_size = 0;
@@ -458,6 +455,9 @@ validate_label(mbr_args_t *a, uint label
 	switch (a->action) {
 	case READ_LABEL:
 		*a->lp = *dlp;
+		if ((a->msg = convertdisklabel(a->lp, a->strat, a->bp,
+		                              a->secperunit)) != NULL)
+			return SCAN_ERROR;
 		a->label_sector = label_sector;
 		return SCAN_FOUND;
 	case UPDATE_LABEL:
Index: sys/device.h
===================================================================
RCS file: /cvsroot/src/sys/sys/device.h,v
retrieving revision 1.94
diff -p -u -u -p -r1.94 device.h
--- sys/device.h	5 Mar 2007 20:32:43 -0000	1.94
+++ sys/device.h	20 Jun 2007 18:40:40 -0000
@@ -307,6 +307,9 @@ extern int booted_partition;		/* or the 
 
 extern volatile int config_pending; 	/* semaphore for mountroot */
 
+struct vnode *opendisk(struct device *);
+int config_handle_wedges(struct device *, int);
+
 void	config_init(void);
 void	configure(void);
 
Index: sys/disk.h
===================================================================
RCS file: /cvsroot/src/sys/sys/disk.h,v
retrieving revision 1.43
diff -p -u -u -p -r1.43 disk.h
--- sys/disk.h	4 Mar 2007 06:03:40 -0000	1.43
+++ sys/disk.h	20 Jun 2007 18:40:40 -0000
@@ -517,6 +517,8 @@ int	dkwedge_list(struct disk *, struct d
 void	dkwedge_discover(struct disk *);
 void	dkwedge_set_bootwedge(struct device *, daddr_t, uint64_t);
 int	dkwedge_read(struct disk *, struct vnode *, daddr_t, void *, size_t);
+device_t dkwedge_find_by_wname(const char *);
+void	dkwedge_print_wnames(void);
 #endif
 
 #endif /* _SYS_DISK_H_ */
Index: sys/disklabel.h
===================================================================
RCS file: /cvsroot/src/sys/sys/disklabel.h,v
retrieving revision 1.99
diff -p -u -u -p -r1.99 disklabel.h
--- sys/disklabel.h	10 Mar 2007 16:42:04 -0000	1.99
+++ sys/disklabel.h	20 Jun 2007 18:40:40 -0000
@@ -433,6 +433,8 @@ struct partinfo {
 
 struct disk;
 
+int disk_read_sectors(void (*)(struct buf *), const struct disklabel *,
+    struct buf *, unsigned int, int);
 void	 diskerr(const struct buf *, const char *, const char *, int,
 	    int, const struct disklabel *);
 u_int	 dkcksum(struct disklabel *);
@@ -443,6 +445,8 @@ const char *readdisklabel(dev_t, void (*
 	    struct disklabel *, struct cpu_disklabel *);
 int	 writedisklabel(dev_t, void (*)(struct buf *), struct disklabel *,
 	    struct cpu_disklabel *);
+const char *convertdisklabel(struct disklabel *, void (*)(struct buf *),
+    struct buf *, uint32_t);
 int	 bounds_check_with_label(struct disk *, struct buf *, int);
 int	 bounds_check_with_mediasize(struct buf *, int, uint64_t);
 #endif

--9amGYk9869ThD9tj--