diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2011-03-17 12:53:45 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2011-03-17 12:53:45 +0000 |
commit | 84121f4de9a9fa6fa2579b4e25cfb843b467f73c (patch) | |
tree | 45f2a34c2ad3082a9ab326a6f17f83f74f149585 /sys/arch/i386 | |
parent | b8687d4fd2f9b6a441b17a13ed402ac1adb107e1 (diff) |
Make the various findopenbsd() functions non-recursive, eliminating
a global, a couple of parameters, and opening up possibility of
traversing much longer EBR lists without blowing the stack.
Make seach algorithm the same as used in kern/subr_disk.c by checking
all primary partitions in the MBR/EBR before moving to next EBR. This
makes it more likely that everybody finds the same OpenBSD partition.
Largely from a diff posted to tech@ by ucsavl.
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/stand/installboot/installboot.c | 56 | ||||
-rw-r--r-- | sys/arch/i386/stand/libsa/biosdev.c | 48 |
2 files changed, 56 insertions, 48 deletions
diff --git a/sys/arch/i386/stand/installboot/installboot.c b/sys/arch/i386/stand/installboot/installboot.c index be384a635e8..edc4aa6626d 100644 --- a/sys/arch/i386/stand/installboot/installboot.c +++ b/sys/arch/i386/stand/installboot/installboot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: installboot.c,v 1.59 2011/03/14 22:14:40 krw Exp $ */ +/* $OpenBSD: installboot.c,v 1.60 2011/03/17 12:53:44 krw Exp $ */ /* $NetBSD: installboot.c,v 1.5 1995/11/17 23:23:50 gwr Exp $ */ /* @@ -103,15 +103,13 @@ static void devread(int, void *, daddr64_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 u_int findopenbsd(int, struct disklabel *, u_int, int *); +static u_int findopenbsd(int, struct disklabel *); static void write_bootblocks(int devfd, struct disklabel *); static int sr_volume(int, int *, int *); static void sr_installboot(int); static void sr_installpbr(int, int, int); -static u_int mbr_eoff; /* Offset of the MBR extended partition. */ - static void usage(void) { @@ -212,9 +210,8 @@ main(int argc, char *argv[]) void write_bootblocks(int devfd, struct disklabel *dl) { - struct stat sb; + struct stat sb; u_int start = 0; - int n = 8; /* Write patched proto bootblock(s) into the superblock. */ if (fstat(devfd, &sb) < 0) @@ -234,8 +231,7 @@ write_bootblocks(int devfd, struct disklabel *dl) if (dl->d_type != 0 && dl->d_type != DTYPE_FLOPPY && dl->d_type != DTYPE_VND) { /* Find OpenBSD partition. */ - mbr_eoff = DOSBBSECTOR; /* Offset of MBR extended partition. */ - start = findopenbsd(devfd, dl, DOSBBSECTOR, &n); + start = findopenbsd(devfd, dl); if (start == (u_int)-1) errx(1, "no OpenBSD partition"); } @@ -251,17 +247,23 @@ write_bootblocks(int devfd, struct disklabel *dl) } u_int -findopenbsd(int devfd, struct disklabel *dl, u_int mbroff, int *n) +findopenbsd(int devfd, struct disklabel *dl) { struct dos_mbr mbr; + u_int mbroff = DOSBBSECTOR; + u_int mbr_eoff = DOSBBSECTOR; /* Offset of extended part. */ struct dos_partition *dp; - u_int start = (u_int)-1; - int i; - - /* Limit the number of recursions */ - if (!(*n)--) - return (-1); + int i, maxebr = DOS_MAXEBR, nextebr; +again: + if (!maxebr--) { + if (verbose) + fprintf(stderr, "Traversed more than %d Extended Boot " + "Records (EBRs)\n", + DOS_MAXEBR); + return ((u_int)-1); + } + if (verbose) fprintf(stderr, "%s boot record (%cBR) at sector %u\n", (mbroff == DOSBBSECTOR) ? "master" : "extended", @@ -275,6 +277,7 @@ findopenbsd(int devfd, struct disklabel *dl, u_int mbroff, int *n) errx(1, "invalid boot record signature (0x%04X) @ sector %u", mbr.dmbr_sign, mbroff); + nextebr = 0; for (i = 0; i < NDOSPART; i++) { dp = &mbr.dmbr_parts[i]; if (!dp->dp_size) @@ -288,24 +291,25 @@ findopenbsd(int devfd, struct disklabel *dl, u_int mbroff, int *n) if (dp->dp_typ == DOSPTYP_OPENBSD) { if (dp->dp_start > (dp->dp_start + mbroff)) continue; - start = dp->dp_start + mbroff; - break; + return (dp->dp_start + mbroff); } - if (dp->dp_typ == DOSPTYP_EXTEND || - dp->dp_typ == DOSPTYP_EXTENDL) { - mbroff = dp->dp_start + mbr_eoff; + if (!nextebr && (dp->dp_typ == DOSPTYP_EXTEND || + dp->dp_typ == DOSPTYP_EXTENDL)) { + nextebr = dp->dp_start + mbr_eoff; + if (nextebr < dp->dp_start) + nextebr = (u_int)-1; if (mbr_eoff == DOSBBSECTOR) mbr_eoff = dp->dp_start; - if (mbroff < dp->dp_start) - continue; - start = findopenbsd(devfd, dl, mbroff, n); - if (start != (u_int)-1) - break; } } - return (start); + if (nextebr && nextebr != (u_int)-1) { + mbroff = nextebr; + goto again; + } + + return ((u_int)-1); } /* diff --git a/sys/arch/i386/stand/libsa/biosdev.c b/sys/arch/i386/stand/libsa/biosdev.c index 0b58f714581..de6efca14e5 100644 --- a/sys/arch/i386/stand/libsa/biosdev.c +++ b/sys/arch/i386/stand/libsa/biosdev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: biosdev.c,v 1.82 2011/03/15 14:00:26 krw Exp $ */ +/* $OpenBSD: biosdev.c,v 1.83 2011/03/17 12:53:44 krw Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff @@ -46,12 +46,11 @@ static int biosdisk_errno(u_int); int CHS_rw (int, int, int, int, int, int, void *); static int EDD_rw (int, int, u_int32_t, u_int32_t, void *); -static u_int findopenbsd(bios_diskinfo_t *, u_int, const char **, int *); +static u_int findopenbsd(bios_diskinfo_t *, const char **); extern int debug; int bios_bootdev; int bios_cddev = -1; /* Set by srt0 if coming from CD */ -u_int mbr_eoff; /* Offset of MBR extended partition. */ #if 0 struct biosdisk { @@ -350,15 +349,16 @@ biosd_io(int rw, bios_diskinfo_t *bd, u_int off, int nsect, void *buf) * Try to read the bsd label on the given BIOS device */ static u_int -findopenbsd(bios_diskinfo_t *bd, u_int mbroff, const char **err, int *n) +findopenbsd(bios_diskinfo_t *bd, const char **err) { struct dos_mbr mbr; struct dos_partition *dp; - u_int start = (u_int)-1; - int error, i; + u_int mbroff = DOSBBSECTOR; + u_int mbr_eoff = DOSBBSECTOR; /* Offset of MBR extended partition. */ + int error, i, maxebr = DOS_MAXEBR, nextebr; - /* Limit the number of recursions */ - if (!(*n)--) { +again: + if (!maxebr--) { *err = "too many extended partitions"; return (-1); } @@ -378,6 +378,7 @@ findopenbsd(bios_diskinfo_t *bd, u_int mbroff, const char **err, int *n) } /* Search for OpenBSD partition */ + nextebr = 0; for (i = 0; i < NDOSPART; i++) { dp = &mbr.dmbr_parts[i]; if (!dp->dp_size) @@ -393,24 +394,29 @@ findopenbsd(bios_diskinfo_t *bd, u_int mbroff, const char **err, int *n) if (dp->dp_typ == DOSPTYP_OPENBSD) { if (dp->dp_start > (dp->dp_start + mbroff)) continue; - start = dp->dp_start + mbroff; - break; + return (dp->dp_start + mbroff); } - if (dp->dp_typ == DOSPTYP_EXTEND || - dp->dp_typ == DOSPTYP_EXTENDL) { - mbroff = dp->dp_start + mbr_eoff; + /* + * Record location of next ebr if and only if this is the first + * extended partition in this boot record! + */ + if (!nextebr && (dp->dp_typ == DOSPTYP_EXTEND || + dp->dp_typ == DOSPTYP_EXTENDL)) { + nextebr = dp->dp_start + mbr_eoff; + if (nextebr < dp->dp_start) + nextebr = (u_int)-1; if (mbr_eoff == DOSBBSECTOR) mbr_eoff = dp->dp_start; - if (mbroff < dp->dp_start) - continue; - start = findopenbsd(bd, mbroff, err, n); - if (start != (u_int)-1) - break; } } - return (start); + if (nextebr && nextebr != (u_int)-1) { + mbroff = nextebr; + goto again; + } + + return (-1); } const char * @@ -420,7 +426,6 @@ bios_getdisklabel(bios_diskinfo_t *bd, struct disklabel *label) char *buf; const char *err = NULL; int error; - int n = 8; /* Sanity check */ if (bd->bios_edd == -1 && @@ -429,8 +434,7 @@ bios_getdisklabel(bios_diskinfo_t *bd, struct disklabel *label) /* MBR is a harddisk thing */ if (bd->bios_number & 0x80) { - mbr_eoff = DOSBBSECTOR; - start = findopenbsd(bd, DOSBBSECTOR, &err, &n); + start = findopenbsd(bd, &err); if (start == (u_int)-1) { if (err != NULL) return (err); |