From julian Wed Aug 24 18:45:31 1994 Return-Path: Received: by tfs.com (smail3.1.28.1) Message-Id: Date: Wed, 24 Aug 94 18:45 PDT From: julian (Julian Elischer) To: phk Subject: Patch to allow mounting of inlabled DOS Hard disks. Cc: julian Status: RO here is a patch that allows the mounting of the DOS partition of a "previously unseen by FreeBSD", hard disk. ===General notes to the Users===== Once a disk has a disklabel added to it this patch has no more effect, however the use of this patch means that one need never 'fiddle with' a hard disk that has a single DOS (or other similar) partition in order to mount it. Note standard DOS disks have 4 partitions, of which only the first is used, however each partiton may be set to cover a different part of the disk, and be assigned to a different O/S. If there is a FreeBSD partition, it is further divided up using a disklabel. The disklabel defines which sections of disk are assigned to which subdevices.. (e.g. sd0a or sd0b, or alternatively wd0b and wd0h) These subdivisions need not lie within the BSD partition. This patch synthesizes a ficticious disklabel that has the following partitions in it: a: If a BSD partition exists, this points to it: b: empty c: If a BSD partition exists, this points to it: d: The whole disk. e: the first BIOS partition (usually DOS) f: the second BIOS partition g: the third BIOS partition h: the fourth BIOS partition (where xBSD is put by default) note: for a xBSD partition to appear here, it must have been created using fdisk, but not yet have had a disklabel added to it.. If there WERE a disklabel, then this ficticious label would not be returned, but the real one would instead. Note it should be possible to actually put a filesystem on a raw 386BSD partition using this ficticious label. julian +----------------------------------+ ______ _ __ | __--_|\ Julian Elischer | \ U \/ / On assignment | / \ julian@tfs.com +------>x USA \ in a very strange | ( OZ ) 300 lakeside Dr. oakland CA. \___ ___ | country ! +- X_.---._/ USA+(510) 645-3137(wk) \_/ \\ v ------------------cut here---------------------- *** src/sys/ufs/ufs_disksubr.c.orig Mon Jun 6 18:21:39 1994 --- src/sys/ufs/ufs_disksubr.c Tue Aug 23 22:53:30 1994 *************** *** 177,190 **** struct disklabel *dlp; char *msg = NULL; int cyl, dospartoff, i; /* minimal requirements for archtypal disk label */ if (lp->d_secperunit == 0) lp->d_secperunit = 0x1fffffff; ! lp->d_npartitions = 1; ! if (lp->d_partitions[0].p_size == 0) ! lp->d_partitions[0].p_size = 0x1fffffff; lp->d_partitions[0].p_offset = 0; /* obtain buffer to probe drive with */ bp = geteblk((int)lp->d_secsize); --- 177,198 ---- struct disklabel *dlp; char *msg = NULL; int cyl, dospartoff, i; + int pseudopart = 4; /* we fill in pseudoparts from e through h*/ + int seenBSD = 0; /* minimal requirements for archtypal disk label */ if (lp->d_secperunit == 0) lp->d_secperunit = 0x1fffffff; ! lp->d_npartitions = 4; ! lp->d_partitions[0].p_size = 0; lp->d_partitions[0].p_offset = 0; + lp->d_partitions[1].p_size = 0; + lp->d_partitions[1].p_offset = 0; + lp->d_partitions[2].p_size = 0; + lp->d_partitions[2].p_offset = 0; + if(lp->d_partitions[3].p_size == 0) + lp->d_partitions[3].p_size = DOSBBSECTOR + 1; /* start low */ + lp->d_partitions[3].p_offset = 0; /* obtain buffer to probe drive with */ bp = geteblk((int)lp->d_secsize); *************** *** 205,246 **** bp->b_cylin = DOSBBSECTOR / lp->d_secpercyl; (*strat)(bp); ! /* if successful, wander through dos partition table */ if (biowait(bp)) { msg = "dos partition I/O error"; goto done; ! } else { ! /* XXX how do we check veracity/bounds of this? */ ! bcopy(bp->b_un.b_addr + DOSPARTOFF, dp, ! NDOSPART * sizeof(*dp)); ! for (i = 0; i < NDOSPART; i++, dp++) ! /* is this ours? */ ! if (dp->dp_size && ! dp->dp_typ == DOSPTYP_386BSD ! && dospartoff == 0) { ! ! /* need sector address for SCSI/IDE, ! cylinder for ESDI/ST506/RLL */ ! dospartoff = dp->dp_start; ! cyl = DPCYL(dp->dp_scyl, dp->dp_ssect); ! ! /* update disklabel with details */ ! lp->d_partitions[0].p_size = ! dp->dp_size; ! lp->d_partitions[0].p_offset = ! dp->dp_start; ! lp->d_ntracks = dp->dp_ehd + 1; ! lp->d_nsectors = DPSECT(dp->dp_esect); ! lp->d_subtype |= (lp->d_subtype & 3) ! + i | DSTYPE_INDOSPART; ! lp->d_secpercyl = lp->d_ntracks * ! lp->d_nsectors; ! } } } ! /* next, dig out disk label */ bp->b_blkno = dospartoff + LABELSECTOR; bp->b_cylin = cyl; bp->b_bcount = lp->d_secsize; --- 213,356 ---- bp->b_cylin = DOSBBSECTOR / lp->d_secpercyl; (*strat)(bp); ! /* ! * if we failed in the read, give up. ! */ if (biowait(bp)) { msg = "dos partition I/O error"; goto done; ! } ! /* ! * If there seems to be BIOS bootblock and partition table ! * in that block, then try interpret it, otherwise ! * give up and use whatever we have synthesised so far ! */ ! if ((*(bp->b_un.b_addr + 510) != (char) 0x55) ! ||(*(bp->b_un.b_addr + 511) != (char) 0xaa)) { ! msg = "Disk has no Fdisk partitions"; ! goto done; } + + /* XXX how do we check veracity/bounds of this? */ + bcopy(bp->b_un.b_addr + DOSPARTOFF, dp, + NDOSPART * sizeof(*dp)); + /* + * We set up the last 4 partitions in the + * disklabel to reflect the DOS partitions + * In case we never find a disklabel, in which + * case this information will be all we have + * but it might be all we need to access a DOS + * partition. + */ + for (i = 0; i < NDOSPART; i++, dp++,pseudopart++) { + + /* + * Set this DOS part into the disklabel + */ + lp->d_partitions[pseudopart].p_size = + dp->dp_size; + lp->d_partitions[pseudopart].p_offset = + dp->dp_start; + + /* + * make sure the D part can hold it all + */ + if((dp->dp_start + dp->dp_size) + > lp->d_partitions[3].p_size) { + lp->d_partitions[3].p_size + = (dp->dp_start + dp->dp_size); + } + /* + * If we haven't seen a *BSD partition then + * check if this is a valid part.. + * if it is it may be the best we are going to + * to see, so take note of it to deduce a + * geometry in case we never find a disklabel. + */ + if (dp->dp_size) { + switch(dp->dp_typ) { + case DOSPTYP_386BSD: + /* + * at a pinch we could throw + * a FFS on here + */ + lp->d_partitions[pseudopart].p_fstype + = FS_BSDFFS; + /* + * Only get a disklabel from the + * first one we see.. + */ + if (seenBSD == 0) { + /* + * If it IS our part, then we + * need sector address for + * SCSI/IDE, cylinder for + * ESDI/ST506/RLL + */ + dospartoff = dp->dp_start; + seenBSD = 1; + cyl = DPCYL(dp->dp_scyl, + dp->dp_ssect); + + /* + * update disklabel with + * details for reading the REAL + * disklabel it it exists + */ + lp->d_partitions[0].p_size = + dp->dp_size; + lp->d_partitions[0].p_offset = + dp->dp_start; + lp->d_partitions[2].p_size = + dp->dp_size; + lp->d_partitions[2].p_offset = + dp->dp_start; + } + break; + case 0xB7: /* BSDI (?)*//* doubtful */ + lp->d_partitions[pseudopart].p_fstype + = FS_BSDFFS; + break; + case 1: + case 4: + case 6: + case 0xF2: + lp->d_partitions[pseudopart].p_fstype + = FS_MSDOS; + break; + } + + /* + * Try deduce the geometry, working + * on the principle that this + * partition PROBABLY ends on a + * cylinder boundary. + * This is really a kludge, but we are + * forced into it by the PC's design. + * If we've seen a 386bsd part, + * believe it and check no further. + */ + if (seenBSD) continue; + lp->d_ntracks = dp->dp_ehd + 1; + lp->d_nsectors = DPSECT(dp->dp_esect); + lp->d_subtype |= (lp->d_subtype & 3) + + i | DSTYPE_INDOSPART; + lp->d_secpercyl = lp->d_ntracks * + lp->d_nsectors; + } + } + lp->d_npartitions = 8; } ! /* ! * If we haven't seen a BSD partition, give up, use the dos version ! */ ! if(!seenBSD) goto done; ! ! /* ! * next, dig out disk label ! */ bp->b_blkno = dospartoff + LABELSECTOR; bp->b_cylin = cyl; bp->b_bcount = lp->d_secsize; *************** *** 249,274 **** /* if successful, locate disk label within block and validate */ if (biowait(bp)) { ! msg = "disk label I/O error"; goto done; ! } else for (dlp = (struct disklabel *)bp->b_un.b_addr; dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp)); dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { ! if (msg == NULL) ! msg = "no disk label"; ! } else if (dlp->d_npartitions > MAXPARTITIONS || ! dkcksum(dlp) != 0) ! msg = "disk label corrupted"; ! else { ! *lp = *dlp; ! msg = NULL; ! break; } } ! ! if (msg) goto done; /* obtain bad sector table if requested and present */ if (bdp && (lp->d_flags & D_BADSECT)) { --- 359,388 ---- /* if successful, locate disk label within block and validate */ if (biowait(bp)) { ! printf("disk label I/O error\n"); goto done; ! /* leave us at least with the dos partitions */ ! } ! for (dlp = (struct disklabel *)bp->b_un.b_addr; dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp)); dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { ! continue; ! } ! if (dlp->d_npartitions > MAXPARTITIONS || ! dkcksum(dlp) != 0) { ! printf("disk label corrupted\n"); ! goto done; ! /* leave us at least with the dos partitions */ } + *lp = *dlp; + msg = NULL; + break; } ! if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { ! printf("No disklabel found\n"); goto done; + } /* obtain bad sector table if requested and present */ if (bdp && (lp->d_flags & D_BADSECT)) { ------------------end patch---------------------