diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2013-09-29 16:32:26 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2013-09-29 16:32:26 +0000 |
commit | da42e31395d08a08b30f86a4da2a810107c5ab24 (patch) | |
tree | a55204ad4cfd5a394d88d4491c8be0840e7c4e8c /sys/arch | |
parent | 6e414d665b5c32229646dc9c1955727f7f0c9988 (diff) |
Split the VDIT label code into VDM "label" (which only defines non-MBR
partitioning, and an optional boot area) and real VDIT.
If a VDM label is found, but no VDIT is found, search for a native label in
sector 1 (where VDIT would start).
In either case, make sure the OpenBSD area of the disk does not enclose the
boot area.
This allows PROM bootable disks, not shared with DG/UX, to be set up with
minimal hassle. To be done by the upcoming installboot(8) soon.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/aviion/aviion/disksubr.c | 87 |
1 files changed, 62 insertions, 25 deletions
diff --git a/sys/arch/aviion/aviion/disksubr.c b/sys/arch/aviion/aviion/disksubr.c index 84458d2a459..e365ac284f4 100644 --- a/sys/arch/aviion/aviion/disksubr.c +++ b/sys/arch/aviion/aviion/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.53 2013/09/29 12:17:59 miod Exp $ */ +/* $OpenBSD: disksubr.c,v 1.54 2013/09/29 16:32:25 miod Exp $ */ /* * Copyright (c) 2013 Miodrag Vallat. @@ -55,6 +55,8 @@ char *extract_vdit_portion(char *, const char *, unsigned int, unsigned int, int); int readvditlabel(struct buf *, void (*)(struct buf *), struct disklabel *, + int *, int, struct vdm_boot_info *); +int readvdmlabel(struct buf *, void (*)(struct buf *), struct disklabel *, int *, int); /* @@ -78,7 +80,7 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; - error = readvditlabel(bp, strat, lp, NULL, spoofonly); + error = readvdmlabel(bp, strat, lp, NULL, spoofonly); if (error == 0) goto done; @@ -121,7 +123,7 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp) bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; - if (readvditlabel(bp, strat, lp, &partoff, 1) == 0) { + if (readvdmlabel(bp, strat, lp, &partoff, 1) == 0) { bp->b_blkno = partoff + LABELSECTOR; offset = LABELOFFSET; } else if (readdoslabel(bp, strat, lp, &partoff, 1) == 0) { @@ -156,33 +158,22 @@ done: } /* - * Search for a VDIT volume information. If one is found, search for a - * vdmpart instance of name "OpenBSD". If one is found, set the disklabel - * bounds to the area it spans, and attempt to read a native label within - * it. + * Search for a VDM "label" (which does not describe any partition). + * If one is found, search for either a VDIT label, or a native OpenBSD + * label in the first sector. */ int -readvditlabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, +readvdmlabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, int *partoffp, int spoofonly) { - struct buf *sbp = NULL; struct vdm_label *vdl; struct vdm_boot_info *vbi; - struct vdit_block_header *vbh; - struct vdit_entry_header *veh; - char *vdit_storage = NULL, *vdit_end; - size_t vdit_size; - unsigned int largest_chunk, vdit_blkno; - int expected_kind; - daddr_t blkno; int error = 0; - vdit_id_t *vdmpart_id; - struct vdit_vdmpart_instance *bsd_vdmpart; /* * Read first sector and check for a VDM label. - * Note that a VDM label is theoretically only required for bootable - * disks; but do disks with a VDIT but no VDM label really exist? + * Note that a VDM label is only required for bootable disks, and + * may not be followed by a VDIT. */ bp->b_blkno = VDM_LABEL_SECTOR; @@ -211,9 +202,54 @@ readvditlabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, if (vbi != NULL && vbi->boot_start == VDIT_SECTOR) return EINVAL; - if (vbi != NULL && vbi->boot_start + vbi->boot_size < DL_GETBSTART(lp)) + if (vbi != NULL && vbi->boot_start + vbi->boot_size > DL_GETBSTART(lp)) DL_SETBSTART(lp, vbi->boot_start + vbi->boot_size); + error = readvditlabel(bp, strat, lp, partoffp, spoofonly, vbi); + if (error == 0) + return 0; + + /* + * Valid VDIT information, but no OpenBSD vdmpart found. + * Do not try to read a native label. + */ + if (error == ENOENT) + return EINVAL; + + bp->b_blkno = LABELSECTOR; + bp->b_bcount = lp->d_secsize; + CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); + SET(bp->b_flags, B_BUSY | B_READ | B_RAW); + (*strat)(bp); + if ((error = biowait(bp)) != 0) + return error; + + return checkdisklabel(bp->b_data + LABELOFFSET, lp, + DL_GETBSTART(lp), DL_GETBEND(lp)); +} + +/* + * Search for a VDIT volume information. If one is found, search for a + * vdmpart instance of name "OpenBSD". If one is found, set the disklabel + * bounds to the area it spans, and attempt to read a native label within + * it. + */ +int +readvditlabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, + int *partoffp, int spoofonly, struct vdm_boot_info *vbi) +{ + struct buf *sbp = NULL; + struct vdit_block_header *vbh; + struct vdit_entry_header *veh; + char *vdit_storage = NULL, *vdit_end; + size_t vdit_size; + unsigned int largest_chunk, vdit_blkno; + int expected_kind; + daddr_t blkno; + int error = 0; + vdit_id_t *vdmpart_id; + struct vdit_vdmpart_instance *bsd_vdmpart; + /* * Figure out the size of the first VDIT. */ @@ -299,7 +335,7 @@ readvditlabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, } /* - * Now walk the VDIT entries. + * Walk the VDIT entries. * * If we find an OpenBSD vdmpart, we'll set our disk area bounds to * its area, and will read a label from there. @@ -361,9 +397,10 @@ readvditlabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, if (partoffp != NULL) { *partoffp = start; goto done; + } else { + DL_SETBSTART(lp, start); + DL_SETBEND(lp, start + size); } - DL_SETBSTART(lp, start); - DL_SETBEND(lp, start + size); /* * Now read the native label. @@ -387,7 +424,7 @@ readvditlabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, * XXX is it worth registering the whole disk as a * XXX `don't touch' vendor partition in that case? */ - error = EINVAL; + error = ENOENT; goto done; } |