summaryrefslogtreecommitdiff
path: root/sys/arch/amd64/stand/libsa/biosdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/amd64/stand/libsa/biosdev.c')
-rw-r--r--sys/arch/amd64/stand/libsa/biosdev.c99
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);