- Check if a disk has wedges, and use the wedge device corresponding to the

root partition, instead of punting. This makes booting work
  with traditional disklabel disks and wedge autoconfiguration.
- factor out disk opening code.
This commit is contained in:
christos 2006-08-12 21:45:22 +00:00
parent adddcaa6ee
commit cf1ddb6596

View File

@ -1,4 +1,4 @@
/* $NetBSD: x86_autoconf.c,v 1.17 2006/08/12 19:55:42 christos Exp $ */
/* $NetBSD: x86_autoconf.c,v 1.18 2006/08/12 21:45:22 christos Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -65,6 +65,109 @@ __KERNEL_RCSID(0, "$NetBSD");
struct disklist *x86_alldisks;
int x86_ndisks;
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:
booted_device = dv;
booted_partition = par;
}
static int
is_valid_disk(struct device *dv)
{
@ -93,7 +196,7 @@ matchbiosdisks(void)
struct vnode *tv;
char mbr[DEV_BSIZE];
int dklist_size;
int bmajor, numbig;
int numbig;
big = lookup_bootinfo(BTINFO_BIOSGEOM);
@ -149,19 +252,9 @@ matchbiosdisks(void)
sizeof(x86_alldisks->dl_nativedisks[n].ni_devname),
"%s", dv->dv_xname);
bmajor = devsw_name2blk(dv->dv_xname, NULL, 0);
if (bmajor == -1)
return;
if (bdevvp(MAKEDISKDEV(bmajor, device_unit(dv),
RAW_PART), &tv))
panic("matchbiosdisks: can't alloc vnode");
error = VOP_OPEN(tv, FREAD, NOCRED, 0);
if (error) {
vput(tv);
if ((tv = opendisk(dv)) == NULL)
continue;
}
error = vn_rdwr(UIO_READ, tv, mbr, DEV_BSIZE, 0,
UIO_SYSSPACE, 0, NOCRED, NULL, NULL);
VOP_CLOSE(tv, FREAD, NOCRED, 0);
@ -215,7 +308,6 @@ match_bootwedge(struct device *dv, struct btinfo_bootwedge *biw)
uint8_t bf[DEV_BSIZE];
uint8_t hash[16];
int found = 0;
int bmajor;
daddr_t blk;
uint64_t nblks;
@ -224,34 +316,6 @@ match_bootwedge(struct device *dv, struct btinfo_bootwedge *biw)
*/
if (biw->matchblk == -1)
return (0);
/*
* Lookup major number for disk block device.
*/
bmajor = devsw_name2blk(dv->dv_xname, NULL, 0);
if (bmajor == -1)
return (0); /* XXX panic ??? */
/*
* 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("findroot: can't alloc vnode");
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("findroot: can't open dev %s (%d)\n",
dv->dv_xname, error);
vput(tmpvn);
return (0);
}
MD5Init(&ctx);
for (blk = biw->matchblk, nblks = biw->matchnblks;
@ -288,7 +352,9 @@ match_bootdisk(struct device *dv, struct btinfo_bootdisk *bid)
int error;
struct disklabel label;
int found = 0;
int bmajor;
if (device_is_a(dv, "dk"))
return 0;
/*
* A disklabel is required here. The boot loader doesn't refuse
@ -298,33 +364,9 @@ match_bootdisk(struct device *dv, struct btinfo_bootdisk *bid)
if (bid->labelsector == -1)
return (0);
/*
* Lookup major number for disk block device.
*/
bmajor = devsw_name2blk(dv->dv_xname, NULL, 0);
if (bmajor == -1)
return (0); /* XXX panic ??? */
if ((tmpvn = opendisk(dv)) == NULL)
return 0;
/*
* Fake a temporary vnode for the disk, open it, and read
* the disklabel for comparison.
*/
if (bdevvp(MAKEDISKDEV(bmajor, device_unit(dv), RAW_PART), &tmpvn))
panic("findroot: can't alloc vnode");
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("findroot: can't open dev %s (%d)\n",
dv->dv_xname, error);
vput(tmpvn);
return (0);
}
error = VOP_IOCTL(tmpvn, DIOCGDINFO, &label, FREAD, NOCRED, 0);
if (error) {
/*
@ -340,7 +382,7 @@ match_bootdisk(struct device *dv, struct btinfo_bootdisk *bid)
if (label.d_type == bid->label.type &&
label.d_checksum == bid->label.checksum &&
strncmp(label.d_packname, bid->label.packname, 16) == 0)
found = 1;
found = 1;
closeout:
VOP_CLOSE(tmpvn, FREAD, NOCRED, 0);
@ -403,8 +445,7 @@ findroot(void)
if (strncmp(cd->cf_name, biv->devname, len) == 0 &&
biv->devname[len] - '0' == cd->cf_unit) {
booted_device = dv;
booted_partition = biv->devname[len + 1] - 'a';
handle_wedges(dv, biv->devname[len + 1] - 'a');
return;
}
}
@ -497,8 +538,7 @@ findroot(void)
booted_device->dv_xname, dv->dv_xname);
continue;
}
booted_device = dv;
booted_partition = bid->partition;
handle_wedges(dv, bid->partition);
}
if (booted_device)