On Fri, Feb 11, 2011 at 09:47:02AM +0200, ucs...@gmail.com wrote: > 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). >
Can you provide some pointers to where you are deriving this information and what testing you have done and what setups now work that did not before? You hint in your description, but this is an area that has been argued over many times with each fix breaking some systems while fixing others. The last test rig I set up had eight extended partitions and seemed to work, but that was a while ago and my memory is vague on the testing done. Having working extended partitions would be nice, but finally finding definitive docs that clearly and correctly describe what is supposed to happen would be even better. .... Ken > 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