summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2013-09-29 16:32:26 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2013-09-29 16:32:26 +0000
commitda42e31395d08a08b30f86a4da2a810107c5ab24 (patch)
treea55204ad4cfd5a394d88d4491c8be0840e7c4e8c /sys/arch
parent6e414d665b5c32229646dc9c1955727f7f0c9988 (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.c87
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;
}