diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2008-06-25 15:26:45 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2008-06-25 15:26:45 +0000 |
commit | e8081b48c75a0706b31e6d542ae4a6476fab5ce2 (patch) | |
tree | fa0c25e24ebdfb4956aba1541e71e1633f11290f /sbin/disklabel | |
parent | b5284be880007f164a2487415ab161a259150927 (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.c | 78 |
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); } |