* provide a fake label in which m/n/o/p are MBR * partitions 0/1/2/3
* provide a fake label in i-p.
readdisklabel(dev, strat, lp, osdep)	dev_t dev;	void (*strat) __P((struct buf *));	register struct disklabel *lp;	struct cpu_disklabel *osdep;{	struct dos_partition *dp = osdep->dosparts, *dp2;	struct dkbad *bdp = &osdep->bad;	struct buf *bp;	struct disklabel *dlp;	char *msg = NULL, *cp;	int dospartoff, cyl, i, ourpart = -1;	/* minimal requirements for archtypal disk label */	if (lp->d_secsize == 0)		lp->d_secsize = DEV_BSIZE;	if (lp->d_secperunit == 0)		lp->d_secperunit = 0x1fffffff;	lp->d_npartitions = RAW_PART + 1;	for (i = 0; i < RAW_PART; i++) {		lp->d_partitions[i].p_size = 0;		lp->d_partitions[i].p_offset = 0;	}	if (lp->d_partitions[i].p_size == 0)		lp->d_partitions[i].p_size = 0x1fffffff;	lp->d_partitions[i].p_offset = 0;	/* get a buffer and initialize it */	bp = geteblk((int)lp->d_secsize);	bp->b_dev = dev;	/* do dos partitions in the process of getting disklabel? */	dospartoff = 0;	cyl = LABELSECTOR / lp->d_secpercyl;	if (dp) {	        daddr_t part_blkno = DOSBBSECTOR;		unsigned long extoff = 0;		int wander = 1, n = 0, loop = 0;		/*		 * Read dos partition table, follow extended partitions.		 * Map the partitions to disklabel entries i-p		 */		while (wander && n < 8 && loop < 8) {		        loop++;			wander = 0;			/* read boot record */			bp->b_blkno = part_blkno;			bp->b_bcount = lp->d_secsize;			bp->b_flags = B_BUSY | B_READ;			bp->b_cylin = part_blkno / lp->d_secpercyl;			(*strat)(bp);		     			/* if successful, wander through dos partition table */			if (biowait(bp)) {				msg = "dos partition I/O error";				goto done;			}			bcopy(bp->b_data + DOSPARTOFF, dp, NDOSPART * sizeof(*dp));			if (ourpart == -1) {				/* Search for our MBR partition */				for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;				    i++, dp2++)					if (dp2->dp_size &&					    dp2->dp_typ == DOSPTYP_OPENBSD)						ourpart = i;				for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;				    i++, dp2++)					if (dp2->dp_size &&					    dp2->dp_typ == DOSPTYP_386BSD)						ourpart = i;				if (ourpart == -1)					goto donot;				/*				 * This is our MBR partition. need sector address				 * for SCSI/IDE, cylinder for ESDI/ST506/RLL				 */				dp2 = &dp[ourpart];				dospartoff = dp2->dp_start + part_blkno;				cyl = DPCYL(dp2->dp_scyl, dp2->dp_ssect);				/* XXX build a temporary disklabel */				lp->d_partitions[0].p_size = dp2->dp_size;				lp->d_partitions[0].p_offset = dp2->dp_start +				    part_blkno;				if (lp->d_ntracks == 0)					lp->d_ntracks = dp2->dp_ehd + 1;				if (lp->d_nsectors == 0)					lp->d_nsectors = DPSECT(dp2->dp_esect);				if (lp->d_secpercyl == 0)					lp->d_secpercyl = lp->d_ntracks *					    lp->d_nsectors;			}donot:			/*			 * In case the disklabel read below fails, we want to			 * provide a fake label in which m/n/o/p are MBR 			 * partitions 0/1/2/3			 */			for (dp2=dp, i=0; i < NDOSPART && !wander && n < 8;			    i++, dp2++) {				struct partition *pp = &lp->d_partitions[8+n];				if (dp2->dp_size)					pp->p_size = dp2->dp_size;				if (dp2->dp_start)					pp->p_offset =					    dp2->dp_start + part_blkno;				switch (dp2->dp_typ) {				case DOSPTYP_UNUSED:					for (cp = (char *)dp2;					    cp < (char *)(dp2 + 1); cp++)						if (*cp)							break;					/*					 * Was it all zeroes?  If so, it is					 * an unused entry that we don't					 * want to show.					 */					if (cp == (char *)(dp2 + 1))					    continue;					lp->d_partitions[8 + n++].p_fstype =					    FS_UNUSED;					break;				case DOSPTYP_LINUX:					pp->p_fstype = FS_EXT2FS;					n++;					break;				case DOSPTYP_FAT12:				case DOSPTYP_FAT16S:				case DOSPTYP_FAT16B:				case DOSPTYP_FAT16C:					pp->p_fstype = FS_MSDOS;					n++;					break;				case DOSPTYP_EXTEND:					part_blkno = dp2->dp_start + extoff;					if (!extoff)						extoff = dp2->dp_start;					wander = 1;					break;				default:					pp->p_fstype = FS_OTHER;					n++;					break;				}			}		}		lp->d_bbsize = 8192;		lp->d_sbsize = 64*1024;		/* XXX ? */		lp->d_npartitions = MAXPARTITIONS;	}	/* next, dig out disk label */	bp->b_blkno = dospartoff + LABELSECTOR;	bp->b_cylin = cyl;	bp->b_bcount = lp->d_secsize;	bp->b_flags = B_BUSY | B_READ;	(*strat)(bp);	/* if successful, locate disk label within block and validate */	if (biowait(bp)) {		/* XXX we return the faked label built so far */		msg = "disk label I/O error";		goto done;	}	for (dlp = (struct disklabel *)bp->b_data;	    dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - 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) {#if defined(CD9660)		if (iso_disklabelspoof(dev, strat, lp) == 0)			msg = NULL;#endif		goto done;	}	/* obtain bad sector table if requested and present */	if (bdp && (lp->d_flags & D_BADSECT)) {		struct dkbad *db;		i = 0;		do {			/* read a bad sector table */			bp->b_flags = B_BUSY | B_READ;			bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i;			if (lp->d_secsize > DEV_BSIZE)				bp->b_blkno *= lp->d_secsize / DEV_BSIZE;			else				bp->b_blkno /= DEV_BSIZE / lp->d_secsize;			bp->b_bcount = lp->d_secsize;			bp->b_cylin = lp->d_ncylinders - 1;			(*strat)(bp);			/* if successful, validate, otherwise try another */			if (biowait(bp)) {				msg = "bad sector table I/O error";			} else {				db = (struct dkbad *)(bp->b_data);#define DKBAD_MAGIC 0x4321				if (db->bt_mbz == 0					&& db->bt_flag == DKBAD_MAGIC) {					msg = NULL;					*bdp = *db;					break;				} else					msg = "bad sector table corrupted";			}		} while ((bp->b_flags & B_ERROR) && (i += 2) < 10 &&			i < lp->d_nsectors);	}done:	bp->b_flags |= B_INVAL;	brelse(bp);	return (msg);}