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--