summaryrefslogtreecommitdiff
path: root/sbin/disklabel
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2008-06-25 15:26:45 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2008-06-25 15:26:45 +0000
commite8081b48c75a0706b31e6d542ae4a6476fab5ce2 (patch)
treefa0c25e24ebdfb4956aba1541e71e1633f11290f /sbin/disklabel
parentb5284be880007f164a2487415ab161a259150927 (diff)
allow to install and boot the OpenBSD A6 partition and disklabel in an
extended DOS partition. the concept of extended partitions is very simple, it is just another mbr at the partition offset (well, the standard "EBR" is a linked list with a few limitations, but this diff works with both variants). this diff has been in the snapshots for a while. with input from weingart@ and krw@ ok deraadt@
Diffstat (limited to 'sbin/disklabel')
-rw-r--r--sbin/disklabel/disklabel.c78
1 files changed, 57 insertions, 21 deletions
diff --git a/sbin/disklabel/disklabel.c b/sbin/disklabel/disklabel.c
index 3352bff5c00..21782ce453d 100644
--- a/sbin/disklabel/disklabel.c
+++ b/sbin/disklabel/disklabel.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: disklabel.c,v 1.128 2008/06/04 01:27:54 deraadt Exp $ */
+/* $OpenBSD: disklabel.c,v 1.129 2008/06/25 15:26:43 reyk Exp $ */
/*
* Copyright (c) 1987, 1993
@@ -39,7 +39,7 @@ static const char copyright[] =
#endif /* not lint */
#ifndef lint
-static const char rcsid[] = "$OpenBSD: disklabel.c,v 1.128 2008/06/04 01:27:54 deraadt Exp $";
+static const char rcsid[] = "$OpenBSD: disklabel.c,v 1.129 2008/06/25 15:26:43 reyk Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -113,6 +113,7 @@ int donothing;
#ifdef DOSLABEL
struct dos_partition *dosdp; /* DOS partition, if found */
+struct dos_partition *findopenbsd(int, off_t, struct dos_partition **, int *);
struct dos_partition *readmbr(int);
#endif
@@ -525,23 +526,25 @@ l_perror(char *s)
}
#ifdef DOSLABEL
-/*
- * Fetch DOS partition table from disk.
- */
struct dos_partition *
-readmbr(int f)
+findopenbsd(int f, off_t mbroff, struct dos_partition **first, int *n)
{
static int mbr[DEV_BSIZE / sizeof(int)];
- struct dos_partition *dp;
+ struct dos_partition *dp, *p;
u_int16_t signature;
+ u_int32_t start = 0;
int part;
+ /* Limit the number of recursions */
+ if (!(*n)--)
+ return (NULL);
+
/*
* This must be done this way due to alignment restrictions
* in for example mips processors.
*/
dp = (struct dos_partition *)mbr;
- if (lseek(f, (off_t)DOSBBSECTOR * DEV_BSIZE, SEEK_SET) < 0 ||
+ if (lseek(f, (off_t)mbroff * DEV_BSIZE, SEEK_SET) < 0 ||
read(f, mbr, sizeof(mbr)) != sizeof(mbr))
return (NULL);
signature = *((u_char *)mbr + DOSMBR_SIGNATURE_OFF) |
@@ -549,39 +552,72 @@ readmbr(int f)
bcopy((char *)mbr+DOSPARTOFF, (char *)mbr, sizeof(*dp) * NDOSPART);
/*
+ * If there is no signature and no OpenBSD partition this is probably
+ * not an MBR.
+ */
+ if (signature != DOSMBR_SIGNATURE)
+ return (NULL);
+
+ /*
* Don't (yet) know disk geometry, use partition table to find OpenBSD
* partition, and obtain disklabel from there.
*/
/* Check if table is valid. */
for (part = 0; part < NDOSPART; part++) {
if ((dp[part].dp_flag & ~0x80) != 0)
- return (0);
+ return (NULL);
}
/* Find OpenBSD partition. */
for (part = 0; part < NDOSPART; part++) {
- if (letoh32(dp[part].dp_size) && dp[part].dp_typ == DOSPTYP_OPENBSD) {
+ if (!letoh32(dp[part].dp_size))
+ continue;
+ if (first && *first == NULL)
+ *first = &dp[part];
+ switch (dp[part].dp_typ) {
+ case DOSPTYP_OPENBSD:
fprintf(stderr, "# Inside MBR partition %d: "
"type %02X start %u size %u\n",
part, dp[part].dp_typ,
letoh32(dp[part].dp_start), letoh32(dp[part].dp_size));
return (&dp[part]);
+ case DOSPTYP_EXTENDL:
+ fprintf(stderr, "# Extended partition %d: "
+ "type %02X start %u size %u\n",
+ part, dp[part].dp_typ,
+ letoh32(dp[part].dp_start), letoh32(dp[part].dp_size));
+ start = letoh32(dp[part].dp_start);
+ p = findopenbsd(f, start, NULL, n);
+ if (p != NULL) {
+ p->dp_start =
+ htole32(letoh32(p->dp_start) + start);
+ return (p);
+ }
+ break;
}
}
- /*
- * If there is no signature and no OpenBSD partition this is probably
- * not an MBR.
- */
- if (signature != DOSMBR_SIGNATURE)
- return (NULL);
+ return (NULL);
+}
+
+/*
+ * Fetch DOS partition table from disk.
+ */
+struct dos_partition *
+readmbr(int f)
+{
+ struct dos_partition *dp, *first;
+ int part, n = 8;
+
+ dp = findopenbsd(f, DOSBBSECTOR, &first, &n);
+ if (dp != NULL)
+ return (dp);
/* If no OpenBSD partition, find first used partition. */
- for (part = 0; part < NDOSPART; part++) {
- if (letoh32(dp[part].dp_size)) {
- warnx("warning, DOS partition table with no valid OpenBSD partition");
- return (&dp[part]);
- }
+ if (first != NULL) {
+ warnx("warning, DOS partition table with no valid OpenBSD partition");
+ return (first);
}
+
/* Table appears to be empty. */
return (NULL);
}