fix extended partition support by handling chained EBRs correctly
authorreyk <reyk@openbsd.org>
Mon, 4 Aug 2008 15:58:13 +0000 (15:58 +0000)
committerreyk <reyk@openbsd.org>
Mon, 4 Aug 2008 15:58:13 +0000 (15:58 +0000)
(using a recursion limit).  now OpenBSD can be installed in a
subsequent DOS/Linux-compatible extended partition.

ok krw@ deraadt@

sbin/disklabel/disklabel.c
sys/arch/amd64/stand/installboot/installboot.c
sys/arch/amd64/stand/libsa/biosdev.c
sys/arch/i386/stand/installboot/installboot.c
sys/arch/i386/stand/libsa/biosdev.c

index 7c287a3..abc88b9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: disklabel.c,v 1.133 2008/07/10 00:21:39 krw Exp $     */
+/*     $OpenBSD: disklabel.c,v 1.134 2008/08/04 15:58:13 reyk Exp $    */
 
 /*
  * Copyright (c) 1987, 1993
@@ -39,7 +39,7 @@ static const char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
-static const char rcsid[] = "$OpenBSD: disklabel.c,v 1.133 2008/07/10 00:21:39 krw Exp $";
+static const char rcsid[] = "$OpenBSD: disklabel.c,v 1.134 2008/08/04 15:58:13 reyk Exp $";
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -579,19 +579,19 @@ findopenbsd(int f, off_t mbroff, struct dos_partition **first, int *n)
                            "type %02X start %u size %u\n",
                            part, dp[part].dp_typ,
                            letoh32(dp[part].dp_start), letoh32(dp[part].dp_size));
+                       dp[part].dp_start =
+                           htole32((off_t)letoh32(dp[part].dp_start) + mbroff);
                        return (&dp[part]);
+               case DOSPTYP_EXTEND:
                case DOSPTYP_EXTENDL:
                        fprintf(stderr, "# Extended partition %d: "
                            "type %02X start %u size %u\n",
                            part, dp[part].dp_typ,
                            letoh32(dp[part].dp_start), letoh32(dp[part].dp_size));
-                       start = letoh32(dp[part].dp_start);
+                       start = letoh32(dp[part].dp_start) + mbroff;
                        p = findopenbsd(f, start, NULL, n);
-                       if (p != NULL) {
-                               p->dp_start =
-                                   htole32(letoh32(p->dp_start) + start);
+                       if (p != NULL)
                                return (p);
-                       }
                        break;
                }
        }
index 88f134a..fb0e95f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: installboot.c,v 1.9 2008/06/25 15:26:44 reyk Exp $    */
+/*     $OpenBSD: installboot.c,v 1.10 2008/08/04 15:58:13 reyk Exp $   */
 /*     $NetBSD: installboot.c,v 1.5 1995/11/17 23:23:50 gwr Exp $ */
 
 /*
@@ -231,7 +231,7 @@ findopenbsd(int devfd, struct disklabel *dl, off_t mbroff, int *n)
        if (!(*n)--)
                return (-1);
 
-       if (lseek(devfd, mbroff, SEEK_SET) < 0 ||
+       if (lseek(devfd, mbroff * dl->d_secsize, SEEK_SET) < 0 ||
            read(devfd, &mbr, sizeof(mbr)) != sizeof(mbr))
                err(4, "can't read master boot record");
 
@@ -242,14 +242,13 @@ findopenbsd(int devfd, struct disklabel *dl, off_t mbroff, int *n)
            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;
+                       return (dp->dp_start + mbroff);
                } else if (dp->dp_typ == DOSPTYP_EXTEND ||
                    dp->dp_typ == DOSPTYP_EXTENDL) {
                        fprintf(stderr, "extended partition %ld: "
@@ -257,16 +256,14 @@ findopenbsd(int devfd, struct disklabel *dl, off_t mbroff, int *n)
                            (long)(dp - mbr.dmbr_parts),
                            dp->dp_typ, dp->dp_typ,
                            dp->dp_start, dp->dp_start);
+                       startoff = (off_t)dp->dp_start + mbroff;
                        start = findopenbsd(devfd, dl, startoff, n);
                        if (start != -1)
-                               return (dp->dp_start + start);
+                               return (start);
                }
        }
-       /* Don't check for old part number, that is ;-p */
-       if (dp >= &mbr.dmbr_parts[NDOSPART])
-               return (-1);
 
-       return (dp->dp_start);
+       return (-1);
 }
 
 /*
index 7358eab..ad5075e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: biosdev.c,v 1.6 2008/06/25 15:32:18 reyk Exp $        */
+/*     $OpenBSD: biosdev.c,v 1.7 2008/08/04 15:58:13 reyk Exp $        */
 
 /*
  * Copyright (c) 1996 Michael Shalayeff
@@ -45,8 +45,7 @@ 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 *);
+static daddr_t findopenbsd(bios_diskinfo_t *, daddr_t, const char **, int *);
 
 extern int debug;
 int bios_bootdev;
@@ -343,8 +342,7 @@ 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)
+findopenbsd(bios_diskinfo_t *bd, daddr_t off, const char **err, int *n)
 {
        int error, i;
        struct dos_mbr mbr;
@@ -370,7 +368,7 @@ findopenbsd(bios_diskinfo_t *bd, daddr_t off, daddr_t *roff, const char **err,
        }
 
        /* Search for OpenBSD partition */
-       for (off = 0, i = 0; off == 0 && i < NDOSPART; i++) {
+       for (i = 0; i < NDOSPART; i++) {
                dp = &mbr.dmbr_parts[i];
 #ifdef BIOS_DEBUG
                if (debug)
@@ -380,13 +378,14 @@ findopenbsd(bios_diskinfo_t *bd, daddr_t off, daddr_t *roff, const char **err,
                            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 ||
+               if (dp->dp_typ == DOSPTYP_OPENBSD) {
+                       off = dp->dp_start + off;
+                       break;
+               } else if (dp->dp_typ == DOSPTYP_EXTEND ||
                    dp->dp_typ == DOSPTYP_EXTENDL) {
-                       off = findopenbsd(bd, dp->dp_start, roff, err, n);
+                       off = findopenbsd(bd, dp->dp_start + off, err, n);
                        if (off != 0)
-                               *roff = dp->dp_start;
+                               break;
                }
        }
 
@@ -407,7 +406,7 @@ findopenbsd(bios_diskinfo_t *bd, daddr_t off, daddr_t *roff, const char **err,
 const char *
 bios_getdisklabel(bios_diskinfo_t *bd, struct disklabel *label)
 {
-       daddr_t off = 0, roff = 0;
+       daddr_t off = 0;
        char *buf;
        const char *err = NULL;
        int error;
@@ -420,14 +419,14 @@ bios_getdisklabel(bios_diskinfo_t *bd, struct disklabel *label)
 
        /* MBR is a harddisk thing */
        if (bd->bios_number & 0x80) {
-               off = findopenbsd(bd, DOSBBSECTOR, &roff, &err, &n);
+               off = findopenbsd(bd, DOSBBSECTOR, &err, &n);
                if (off == 0) {
                        if (err != NULL)
                                return (err);
                        return "no OpenBSD partition\n";
                }
        }
-       off = LABELSECTOR + off + roff;
+       off = LABELSECTOR + off;
 
        /* Load BSD disklabel */
        buf = alloca(DEV_BSIZE);
index d0a4501..1658d05 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: installboot.c,v 1.52 2008/06/25 15:26:44 reyk Exp $   */
+/*     $OpenBSD: installboot.c,v 1.53 2008/08/04 15:58:13 reyk Exp $   */
 /*     $NetBSD: installboot.c,v 1.5 1995/11/17 23:23:50 gwr Exp $ */
 
 /*
@@ -227,7 +227,7 @@ findopenbsd(int devfd, struct disklabel *dl, off_t mbroff, int *n)
        if (!(*n)--)
                return (-1);
 
-       if (lseek(devfd, mbroff, SEEK_SET) < 0 ||
+       if (lseek(devfd, mbroff * dl->d_secsize, SEEK_SET) < 0 ||
            read(devfd, &mbr, sizeof(mbr)) != sizeof(mbr))
                err(4, "can't read master boot record");
 
@@ -238,14 +238,13 @@ findopenbsd(int devfd, struct disklabel *dl, off_t mbroff, int *n)
            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;
+                       return (dp->dp_start + mbroff);
                } else if (dp->dp_typ == DOSPTYP_EXTEND ||
                    dp->dp_typ == DOSPTYP_EXTENDL) {
                        fprintf(stderr, "extended partition %ld: "
@@ -253,16 +252,14 @@ findopenbsd(int devfd, struct disklabel *dl, off_t mbroff, int *n)
                            (long)(dp - mbr.dmbr_parts),
                            dp->dp_typ, dp->dp_typ,
                            dp->dp_start, dp->dp_start);
+                       startoff = (off_t)dp->dp_start + mbroff;
                        start = findopenbsd(devfd, dl, startoff, n);
                        if (start != -1)
-                               return (dp->dp_start + start);
+                               return (start);
                }
        }
-       /* Don't check for old part number, that is ;-p */
-       if (dp >= &mbr.dmbr_parts[NDOSPART])
-               return (-1);
 
-       return (dp->dp_start);
+       return (-1);
 }
 
 /*
index 2b82202..3ccc012 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: biosdev.c,v 1.74 2008/06/25 15:32:18 reyk Exp $       */
+/*     $OpenBSD: biosdev.c,v 1.75 2008/08/04 15:58:13 reyk Exp $       */
 
 /*
  * Copyright (c) 1996 Michael Shalayeff
@@ -46,8 +46,7 @@ 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 *);
+static daddr_t findopenbsd(bios_diskinfo_t *, daddr_t, const char **, int *);
 
 extern int debug;
 int bios_bootdev;
@@ -346,8 +345,7 @@ 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)
+findopenbsd(bios_diskinfo_t *bd, daddr_t off, const char **err, int *n)
 {
        int error, i;
        struct dos_mbr mbr;
@@ -373,7 +371,7 @@ findopenbsd(bios_diskinfo_t *bd, daddr_t off, daddr_t *roff, const char **err,
        }
 
        /* Search for OpenBSD partition */
-       for (off = 0, i = 0; off == 0 && i < NDOSPART; i++) {
+       for (i = 0; i < NDOSPART; i++) {
                dp = &mbr.dmbr_parts[i];
 #ifdef BIOS_DEBUG
                if (debug)
@@ -383,13 +381,14 @@ findopenbsd(bios_diskinfo_t *bd, daddr_t off, daddr_t *roff, const char **err,
                            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 ||
+               if (dp->dp_typ == DOSPTYP_OPENBSD) {
+                       off = dp->dp_start + off;
+                       break;
+               } else if (dp->dp_typ == DOSPTYP_EXTEND ||
                    dp->dp_typ == DOSPTYP_EXTENDL) {
-                       off = findopenbsd(bd, dp->dp_start, roff, err, n);
+                       off = findopenbsd(bd, dp->dp_start + off, err, n);
                        if (off != 0)
-                               *roff = dp->dp_start;
+                               break;
                }
        }
 
@@ -410,7 +409,7 @@ findopenbsd(bios_diskinfo_t *bd, daddr_t off, daddr_t *roff, const char **err,
 const char *
 bios_getdisklabel(bios_diskinfo_t *bd, struct disklabel *label)
 {
-       daddr_t off = 0, roff = 0;
+       daddr_t off = 0;
        char *buf;
        const char *err = NULL;
        int error;
@@ -423,14 +422,14 @@ bios_getdisklabel(bios_diskinfo_t *bd, struct disklabel *label)
 
        /* MBR is a harddisk thing */
        if (bd->bios_number & 0x80) {
-               off = findopenbsd(bd, DOSBBSECTOR, &roff, &err, &n);
+               off = findopenbsd(bd, DOSBBSECTOR, &err, &n);
                if (off == 0) {
                        if (err != NULL)
                                return (err);
                        return "no OpenBSD partition\n";
                }
        }
-       off = LABELSECTOR + off + roff;
+       off = LABELSECTOR + off;
 
        /* Load BSD disklabel */
        buf = alloca(DEV_BSIZE);