diff options
Diffstat (limited to 'sys/arch/amd64/stand/libsa/biosdev.c')
-rw-r--r-- | sys/arch/amd64/stand/libsa/biosdev.c | 99 |
1 files changed, 78 insertions, 21 deletions
diff --git a/sys/arch/amd64/stand/libsa/biosdev.c b/sys/arch/amd64/stand/libsa/biosdev.c index 696acf81d24..0e4439c8296 100644 --- a/sys/arch/amd64/stand/libsa/biosdev.c +++ b/sys/arch/amd64/stand/libsa/biosdev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: biosdev.c,v 1.4 2007/04/04 14:36:05 jmc Exp $ */ +/* $OpenBSD: biosdev.c,v 1.5 2008/06/25 15:26:44 reyk Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff @@ -45,6 +45,9 @@ static int biosdisk_errno(u_int); static int CHS_rw (int, int, int, int, int, int, void *); static int EDD_rw (int, int, u_int64_t, u_int32_t, void *); +static daddr_t findopenbsd(bios_diskinfo_t *, daddr_t, daddr_t *, + const char **, int *); + extern int debug; int bios_bootdev; int bios_cddev = -1; /* Set by srt0 if coming from CD */ @@ -335,13 +338,76 @@ biosd_io(int rw, bios_diskinfo_t *bd, daddr_t off, int nsect, void *buf) /* * Try to read the bsd label on the given BIOS device */ +static daddr_t +findopenbsd(bios_diskinfo_t *bd, daddr_t off, daddr_t *roff, const char **err, + int *n) +{ + int error, i; + struct dos_mbr mbr; + struct dos_partition *dp; + + /* Limit the number of recursions */ + if (!(*n)--) { + *err = "too many extended partitions"; + return (0); + } + + /* Read MBR */ + error = biosd_io(F_READ, bd, off, 1, &mbr); + if (error) { + *err = biosdisk_err(error); + return (0); + } + + /* check mbr signature */ + if (mbr.dmbr_sign != DOSMBR_SIGNATURE) { + *err = "bad MBR signature\n"; + return (0); + } + + /* Search for OpenBSD partition */ + for (off = 0, i = 0; off == 0 && i < NDOSPART; i++) { + dp = &mbr.dmbr_parts[i]; +#ifdef BIOS_DEBUG + if (debug) + printf("found partition %u: " + "type %u (0x%x) offset %u (0x%x)\n", + (int)(dp - mbr.dmbr_parts), + dp->dp_typ, dp->dp_typ, + dp->dp_start, dp->dp_start); +#endif + if (dp->dp_typ == DOSPTYP_OPENBSD) + off = dp->dp_start; + else if (dp->dp_typ == DOSPTYP_EXTEND || + dp->dp_typ == DOSPTYP_EXTENDL) { + off = findopenbsd(bd, dp->dp_start, roff, err, n); + if (off != 0) + *roff = dp->dp_start; + } + } + +#ifdef BIOS_DEBUG + if (debug) + printf("using offset %u\n", off); +#endif + + if (off == 0) { + if (*err == NULL) + *err = "no OpenBSD partition\n"; + return (0); + } + + return (off); +} + const char * bios_getdisklabel(bios_diskinfo_t *bd, struct disklabel *label) { - daddr_t off = LABELSECTOR; + daddr_t off = 0, roff = 0; char *buf; - struct dos_mbr mbr; - int error, i; + const char *err = NULL; + int error; + int n = 8; /* Sanity check */ if(bd->bios_heads == 0 || bd->bios_sectors == 0) @@ -349,23 +415,14 @@ bios_getdisklabel(bios_diskinfo_t *bd, struct disklabel *label) /* MBR is a harddisk thing */ if (bd->bios_number & 0x80) { - /* Read MBR */ - error = biosd_io(F_READ, bd, DOSBBSECTOR, 1, &mbr); - if (error) - return(biosdisk_err(error)); - - /* check mbr signature */ - if (mbr.dmbr_sign != DOSMBR_SIGNATURE) - return("bad MBR signature\n"); - - /* Search for OpenBSD partition */ - for (off = 0, i = 0; off == 0 && i < NDOSPART; i++) - if (mbr.dmbr_parts[i].dp_typ == DOSPTYP_OPENBSD) - off = mbr.dmbr_parts[i].dp_start + LABELSECTOR; - if (off == 0) - return("no OpenBSD partition\n"); - } else - off = LABELSECTOR; + off = findopenbsd(bd, DOSBBSECTOR, &roff, &err, &n); + if (off == 0) { + if (err != NULL) + return (err); + return "no OpenBSD partition\n"; + } + } + off = LABELSECTOR + off + roff; /* Load BSD disklabel */ buf = alloca(DEV_BSIZE); |