summaryrefslogtreecommitdiff
path: root/sys/arch/amd64/stand/installboot/installboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/amd64/stand/installboot/installboot.c')
-rw-r--r--sys/arch/amd64/stand/installboot/installboot.c83
1 files changed, 58 insertions, 25 deletions
diff --git a/sys/arch/amd64/stand/installboot/installboot.c b/sys/arch/amd64/stand/installboot/installboot.c
index 85bc9bf0399..88f134a0094 100644
--- a/sys/arch/amd64/stand/installboot/installboot.c
+++ b/sys/arch/amd64/stand/installboot/installboot.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: installboot.c,v 1.8 2008/01/24 12:09:53 krw Exp $ */
+/* $OpenBSD: installboot.c,v 1.9 2008/06/25 15:26:44 reyk Exp $ */
/* $NetBSD: installboot.c,v 1.5 1995/11/17 23:23:50 gwr Exp $ */
/*
@@ -98,6 +98,7 @@ static void devread(int, void *, daddr_t, size_t, char *);
static void sym_set_value(struct sym_data *, char *, u_int32_t);
static void pbr_set_symbols(char *, char *, struct sym_data *);
static void usage(void);
+static long findopenbsd(int, struct disklabel *, off_t, int *);
static void
usage(void)
@@ -120,9 +121,9 @@ main(int argc, char *argv[])
long protosize;
struct stat sb;
struct disklabel dl;
- struct dos_mbr mbr;
- struct dos_partition *dp;
off_t startoff = 0;
+ long start = 0;
+ int n = 8;
while ((c = getopt(argc, argv, "vn")) != -1) {
switch (c) {
@@ -200,29 +201,11 @@ main(int argc, char *argv[])
if (dl.d_type != 0 && dl.d_type != DTYPE_FLOPPY &&
dl.d_type != DTYPE_VND) {
- if (lseek(devfd, (off_t)DOSBBSECTOR, SEEK_SET) < 0 ||
- read(devfd, &mbr, sizeof(mbr)) != sizeof(mbr))
- err(4, "can't read master boot record");
-
- if (mbr.dmbr_sign != DOSMBR_SIGNATURE)
- errx(1, "broken MBR");
-
/* Find OpenBSD partition. */
- for (dp = mbr.dmbr_parts; dp < &mbr.dmbr_parts[NDOSPART];
- dp++) {
- if (dp->dp_size && dp->dp_typ == DOSPTYP_OPENBSD) {
- startoff = (off_t)dp->dp_start * dl.d_secsize;
- fprintf(stderr, "using MBR partition %ld: "
- "type %d (0x%02x) offset %d (0x%x)\n",
- (long)(dp - mbr.dmbr_parts),
- dp->dp_typ, dp->dp_typ,
- dp->dp_start, dp->dp_start);
- break;
- }
- }
- /* Don't check for old part number, that is ;-p */
- if (dp >= &mbr.dmbr_parts[NDOSPART])
- errx(1, "no OpenBSD partition");
+ start = findopenbsd(devfd, &dl, (off_t)DOSBBSECTOR, &n);
+ if (start == -1)
+ errx(1, "no OpenBSD partition");
+ startoff = (off_t)start * dl.d_secsize;
}
if (!nowrite) {
@@ -236,6 +219,56 @@ main(int argc, char *argv[])
return 0;
}
+long
+findopenbsd(int devfd, struct disklabel *dl, off_t mbroff, int *n)
+{
+ struct dos_mbr mbr;
+ struct dos_partition *dp;
+ off_t startoff;
+ long start;
+
+ /* Limit the number of recursions */
+ if (!(*n)--)
+ return (-1);
+
+ if (lseek(devfd, mbroff, SEEK_SET) < 0 ||
+ read(devfd, &mbr, sizeof(mbr)) != sizeof(mbr))
+ err(4, "can't read master boot record");
+
+ if (mbr.dmbr_sign != DOSMBR_SIGNATURE)
+ errx(1, "broken MBR");
+
+ for (dp = mbr.dmbr_parts; dp < &mbr.dmbr_parts[NDOSPART];
+ dp++) {
+ if (!dp->dp_size)
+ continue;
+ startoff = (off_t)dp->dp_start * dl->d_secsize;
+ if (dp->dp_typ == DOSPTYP_OPENBSD) {
+ fprintf(stderr, "using MBR partition %ld: "
+ "type %d (0x%02x) offset %d (0x%x)\n",
+ (long)(dp - mbr.dmbr_parts),
+ dp->dp_typ, dp->dp_typ,
+ dp->dp_start, dp->dp_start);
+ break;
+ } else if (dp->dp_typ == DOSPTYP_EXTEND ||
+ dp->dp_typ == DOSPTYP_EXTENDL) {
+ fprintf(stderr, "extended partition %ld: "
+ "type %d (0x%02x) offset %d (0x%x)\n",
+ (long)(dp - mbr.dmbr_parts),
+ dp->dp_typ, dp->dp_typ,
+ dp->dp_start, dp->dp_start);
+ start = findopenbsd(devfd, dl, startoff, n);
+ if (start != -1)
+ return (dp->dp_start + start);
+ }
+ }
+ /* Don't check for old part number, that is ;-p */
+ if (dp >= &mbr.dmbr_parts[NDOSPART])
+ return (-1);
+
+ return (dp->dp_start);
+}
+
/*
* Load the prototype boot sector (biosboot) into memory.
*/