Despite the touted support, OpenBSD wouldn't be able to boot off an extended partition, unless it's the very first or second one.
The kernel was fixed (after a fashion) some time ago, but boot(8) and installboot(8) still live under the mistaken idea that extended partitions are defined recursively, with each of them acting like a full MBR again and again, each with 4 smaller partitions inside it, and the offset of each subsequent extended partition should be calculated wrt. the offset of the bigger one containing it. That doesn't work that way and never worked that way: There is one big extended partition defined in the MBR, and then inside it there is a linked list of 'logical' partitions, each of them with a fake MBR defining a data sub-partition (whose offset is from the start of this logical partition), and possibly a link to the next logical partition (whose offset is from the start of the main extended partition). diff -rup osys/arch/i386/stand/installboot/installboot.c sys/arch/i386/stand/installboot/installboot.c --- osys/arch/i386/stand/installboot/installboot.c 2011-01-26 01:56:16.000000000 +0200 +++ sys/arch/i386/stand/installboot/installboot.c 2011-02-07 19:33:08.000000000 +0200 @@ -103,7 +103,7 @@ static void devread(int, void *, daddr_t 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 long findopenbsd(int, struct disklabel *, off_t, int *); +static long findopenbsd(int, struct disklabel *); static void write_bootblocks(int devfd, struct disklabel *); static int sr_volume(int, int *, int *); @@ -213,7 +213,6 @@ write_bootblocks(int devfd, struct diskl struct stat sb; off_t startoff = 0; long start = 0; - int n = 8; /* Write patched proto bootblock(s) into the superblock. */ if (fstat(devfd, &sb) < 0) @@ -233,7 +232,7 @@ write_bootblocks(int devfd, struct diskl if (dl->d_type != 0 && dl->d_type != DTYPE_FLOPPY && dl->d_type != DTYPE_VND) { /* Find OpenBSD partition. */ - start = findopenbsd(devfd, dl, (off_t)DOSBBSECTOR, &n); + start = findopenbsd(devfd, dl); if (start == -1) errx(1, "no OpenBSD partition"); startoff = (off_t)start * dl->d_secsize; @@ -247,35 +246,30 @@ write_bootblocks(int devfd, struct diskl } long -findopenbsd(int devfd, struct disklabel *dl, off_t mbroff, int *n) +findopenbsd(int devfd, struct disklabel *dl) { struct dos_mbr mbr; struct dos_partition *dp; - off_t startoff; - long start; + off_t off, eoff, noff; - /* Limit the number of recursions */ - if (!(*n)--) - return (-1); - - if (lseek(devfd, mbroff * dl->d_secsize, SEEK_SET) < 0 || + off = eoff = 0; +redo: + if (lseek(devfd, off * dl->d_secsize, SEEK_SET) < 0 || read(devfd, &mbr, sizeof(mbr)) != sizeof(mbr)) err(4, "can't read master boot record"); if (mbr.dmbr_sign != DOSMBR_SIGNATURE) errx(1, "broken MBR"); - for (dp = mbr.dmbr_parts; dp < &mbr.dmbr_parts[NDOSPART]; + for (noff = 0, dp = mbr.dmbr_parts; dp < &mbr.dmbr_parts[NDOSPART]; dp++) { - if (!dp->dp_size) - continue; if (dp->dp_typ == DOSPTYP_OPENBSD) { if (verbose) fprintf(stderr, "using MBR partition %ld: type 0x%02X offset %d\n", (long)(dp - mbr.dmbr_parts), dp->dp_typ, dp->dp_start); - return (dp->dp_start + mbroff); + return (dp->dp_start + off); } else if (dp->dp_typ == DOSPTYP_EXTEND || dp->dp_typ == DOSPTYP_EXTENDL) { if (verbose) @@ -283,12 +277,14 @@ findopenbsd(int devfd, struct disklabel "extended partition %ld: type 0x%02X offset %d\n", (long)(dp - mbr.dmbr_parts), dp->dp_typ, dp->dp_start); - startoff = (off_t)dp->dp_start + mbroff; - start = findopenbsd(devfd, dl, startoff, n); - if (start != -1) - return (start); + noff = dp->dp_start + eoff; } } + if(noff){ + if(!eoff) eoff = noff; + off = noff; + goto redo; + } return (-1); } diff -rup osys/arch/i386/stand/libsa/biosdev.c sys/arch/i386/stand/libsa/biosdev.c --- osys/arch/i386/stand/libsa/biosdev.c 2011-01-09 01:15:25.000000000 +0200 +++ sys/arch/i386/stand/libsa/biosdev.c 2011-02-07 19:18:04.000000000 +0200 @@ -46,7 +46,7 @@ static int biosdisk_errno(u_int); 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, const char **, int *); +static daddr_t findopenbsd(bios_diskinfo_t *, const char **); extern int debug; int bios_bootdev; @@ -345,21 +345,17 @@ biosd_io(int rw, bios_diskinfo_t *bd, da * Try to read the bsd label on the given BIOS device */ static daddr_t -findopenbsd(bios_diskinfo_t *bd, daddr_t mbroff, const char **err, int *n) +findopenbsd(bios_diskinfo_t *bd, const char **err) { int error, i; struct dos_mbr mbr; struct dos_partition *dp; - daddr_t off; - - /* Limit the number of recursions */ - if (!(*n)--) { - *err = "too many extended partitions"; - return (-1); - } + daddr_t off, eoff, noff; + off = eoff = 0; +redo: /* Read MBR */ - error = biosd_io(F_READ, bd, mbroff, 1, &mbr); + error = biosd_io(F_READ, bd, off, 1, &mbr); if (error) { *err = biosdisk_err(error); return (-1); @@ -372,10 +368,8 @@ findopenbsd(bios_diskinfo_t *bd, daddr_t } /* Search for OpenBSD partition */ - for (i = 0; i < NDOSPART; i++) { + for (i = 0, noff = 0; i < NDOSPART; i++) { dp = &mbr.dmbr_parts[i]; - if (!dp->dp_size) - continue; #ifdef BIOS_DEBUG if (debug) printf("found partition %u: " @@ -385,14 +379,17 @@ findopenbsd(bios_diskinfo_t *bd, daddr_t dp->dp_start, dp->dp_start); #endif if (dp->dp_typ == DOSPTYP_OPENBSD) { - return (dp->dp_start + mbroff); + return (dp->dp_start + off); } else if (dp->dp_typ == DOSPTYP_EXTEND || dp->dp_typ == DOSPTYP_EXTENDL) { - off = findopenbsd(bd, dp->dp_start + mbroff, err, n); - if (off != -1) - return (off); + noff = dp->dp_start + eoff; } } + if(noff){ + if(!eoff) eoff = noff; + off = noff; + goto redo; + } return (-1); } @@ -404,7 +401,6 @@ bios_getdisklabel(bios_diskinfo_t *bd, s char *buf; const char *err = NULL; int error; - int n = 8; /* Sanity check */ if (bd->bios_edd == -1 && @@ -413,7 +409,7 @@ bios_getdisklabel(bios_diskinfo_t *bd, s /* MBR is a harddisk thing */ if (bd->bios_number & 0x80) { - off = findopenbsd(bd, DOSBBSECTOR, &err, &n); + off = findopenbsd(bd, &err); if (off == -1) { if (err != NULL) return (err); 62ccd6efa3a20d4a2684fc7e41566b11de0dfe955e899ce6d1f984ba9f3d9bb1