summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2011-03-17 12:53:45 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2011-03-17 12:53:45 +0000
commit84121f4de9a9fa6fa2579b4e25cfb843b467f73c (patch)
tree45f2a34c2ad3082a9ab326a6f17f83f74f149585 /sys/arch/i386
parentb8687d4fd2f9b6a441b17a13ed402ac1adb107e1 (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.c56
-rw-r--r--sys/arch/i386/stand/libsa/biosdev.c48
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);