diff options
Diffstat (limited to 'sys/arch/amd64/stand/installboot/installboot.c')
-rw-r--r-- | sys/arch/amd64/stand/installboot/installboot.c | 83 |
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. */ |