Ejemplo n.º 1
0
/*
 * Find a valid disklabel.
 */
static char *
search_label(struct of_dev *devp, u_long off, char *buf, struct disklabel *lp,
    u_long off0)
{
	size_t read;
	struct mbr_partition *p;
	int i;
	u_long poff;

	struct disklabel *dlp;
	struct sun_disklabel *slp;
	int error;
	
	/* minimal requirements for archetypal disk label */
	if (DL_GETDSIZE(lp) == 0)
		DL_SETDSIZE(lp, 0x1fffffff);
	lp->d_npartitions = MAXPARTITIONS;
	if (DL_GETPSIZE(&lp->d_partitions[0]) == 0)
		DL_SETPSIZE(&lp->d_partitions[0], 0x1fffffff);
	DL_SETPOFFSET(&lp->d_partitions[0], 0);

	if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read)
	    || read != DEV_BSIZE)
		return ("Cannot read label");

	/* Check for a disk label. */
	dlp = (struct disklabel *) (buf + LABELOFFSET);
	if (dlp->d_magic == DISKMAGIC) {
		if (dkcksum(dlp))
			return ("corrupt disk label");
		*lp = *dlp;
		DNPRINTF(BOOT_D_OFDEV, "search_label: found disk label\n");
		return (NULL);
	}

	/* Check for a Sun disk label (for PROM compatibility). */
	slp = (struct sun_disklabel *)buf;
	if (slp->sl_magic == SUN_DKMAGIC) {
		if (disklabel_sun_to_bsd(slp, lp) != 0)
			return ("corrupt disk label");
		DNPRINTF(BOOT_D_OFDEV, "search_label: found disk label\n");
		return (NULL);
	}

	return ("no disk label");
}
Ejemplo n.º 2
0
/*
 * Read an ascii label in from FILE f,
 * in the same format as that put out by display(),
 * and fill in lp.
 */
int
getasciilabel(FILE *f, struct disklabel *lp)
{
	char **cpp, *cp;
	const char *errstr;
	struct partition *pp;
	char *tp, *s, line[BUFSIZ];
	int lineno = 0, errors = 0;
	u_int32_t v, fsize;
	u_int64_t lv;

	lp->d_version = 1;
	lp->d_bbsize = BBSIZE;				/* XXX */
	lp->d_sbsize = SBSIZE;				/* XXX */
	while (fgets(line, sizeof(line), f)) {
		lineno++;
		if ((cp = strpbrk(line, "#\r\n")))
			*cp = '\0';
		cp = skip(line);
		if (cp == NULL)
			continue;
		tp = strchr(cp, ':');
		if (tp == NULL) {
			warnx("line %d: syntax error", lineno);
			errors++;
			continue;
		}
		*tp++ = '\0', tp = skip(tp);
		if (!strcmp(cp, "type")) {
			if (tp == NULL)
				tp = "unknown";
			else if (strcasecmp(tp, "IDE") == 0)
				tp = "ESDI";
			cpp = dktypenames;
			for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
				if ((s = *cpp) && !strcasecmp(s, tp)) {
					lp->d_type = cpp - dktypenames;
					goto next;
				}
			v = GETNUM(lp->d_type, tp, 0, &errstr);
			if (errstr || v >= DKMAXTYPES)
				warnx("line %d: warning, unknown disk type: %s",
				    lineno, tp);
			lp->d_type = v;
			continue;
		}
		if (!strcmp(cp, "flags")) {
			for (v = 0; (cp = tp) && *cp != '\0';) {
				tp = word(cp);
				if (!strcmp(cp, "badsect"))
					v |= D_BADSECT;
				else if (!strcmp(cp, "vendor"))
					v |= D_VENDOR;
				else {
					warnx("line %d: bad flag: %s",
					    lineno, cp);
					errors++;
				}
			}
			lp->d_flags = v;
			continue;
		}
		if (!strcmp(cp, "drivedata")) {
			int i;

			for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
				v = GETNUM(lp->d_drivedata[i], cp, 0, &errstr);
				if (errstr)
					warnx("line %d: bad drivedata %s",
					   lineno, cp);
				lp->d_drivedata[i++] = v;
				tp = word(cp);
			}
			continue;
		}
		if (sscanf(cp, "%d partitions", &v) == 1) {
			if (v == 0 || v > MAXPARTITIONS) {
				warnx("line %d: bad # of partitions", lineno);
				lp->d_npartitions = MAXPARTITIONS;
				errors++;
			} else
				lp->d_npartitions = v;
			continue;
		}
		if (tp == NULL)
			tp = "";
		if (!strcmp(cp, "disk")) {
			strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
			continue;
		}
		if (!strcmp(cp, "label")) {
			strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
			continue;
		}
		if (!strcmp(cp, "duid")) {
			if (duid_parse(lp, tp) != 0) {
				warnx("line %d: bad %s: %s", lineno, cp, tp);
				errors++;
			}
			continue;
		}
		if (!strcmp(cp, "bytes/sector")) {
			v = GETNUM(lp->d_secsize, tp, 1, &errstr);
			if (errstr || (v % 512) != 0) {
				warnx("line %d: bad %s: %s", lineno, cp, tp);
				errors++;
			} else
				lp->d_secsize = v;
			continue;
		}
		if (!strcmp(cp, "sectors/track")) {
			v = GETNUM(lp->d_nsectors, tp, 1, &errstr);
			if (errstr) {
				warnx("line %d: bad %s: %s", lineno, cp, tp);
				errors++;
			} else
				lp->d_nsectors = v;
			continue;
		}
		if (!strcmp(cp, "sectors/cylinder")) {
			v = GETNUM(lp->d_secpercyl, tp, 1, &errstr);
			if (errstr) {
				warnx("line %d: bad %s: %s", lineno, cp, tp);
				errors++;
			} else
				lp->d_secpercyl = v;
			continue;
		}
		if (!strcmp(cp, "tracks/cylinder")) {
			v = GETNUM(lp->d_ntracks, tp, 1, &errstr);
			if (errstr) {
				warnx("line %d: bad %s: %s", lineno, cp, tp);
				errors++;
			} else
				lp->d_ntracks = v;
			continue;
		}
		if (!strcmp(cp, "cylinders")) {
			v = GETNUM(lp->d_ncylinders, tp, 1, &errstr);
			if (errstr) {
				warnx("line %d: bad %s: %s", lineno, cp, tp);
				errors++;
			} else
				lp->d_ncylinders = v;
			continue;
		}
		if (!strcmp(cp, "total sectors")) {
			lv = GETNUM(lv, tp, 1, &errstr);
			if (errstr) {
				warnx("line %d: bad %s: %s", lineno, cp, tp);
				errors++;
			} else {
				DL_SETDSIZE(lp, lv);
			}
			continue;
		}

		/* Ignore fields that are no longer in the disklabel. */
		if (!strcmp(cp, "rpm") ||
		    !strcmp(cp, "interleave") ||
		    !strcmp(cp, "trackskew") ||
		    !strcmp(cp, "cylinderskew") ||
		    !strcmp(cp, "headswitch") ||
		    !strcmp(cp, "track-to-track seek"))
			continue;

		/* Ignore fields that are forcibly set when label is read. */
		if (!strcmp(cp, "total sectors") ||
		    !strcmp(cp, "boundstart") ||
		    !strcmp(cp, "boundend"))
			continue;

		if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
			unsigned int part = *cp - 'a';

			if (part >= lp->d_npartitions) {
				if (part >= MAXPARTITIONS) {
					warnx("line %d: bad partition name: %s",
					    lineno, cp);
					errors++;
					continue;
				} else {
					lp->d_npartitions = part + 1;
				}
			}
			pp = &lp->d_partitions[part];
#define NXTNUM(n, field, errstr) { \
	if (tp == NULL) {					\
		warnx("line %d: too few fields", lineno);	\
		errors++;					\
		break;						\
	} else							\
		cp = tp, tp = word(cp), (n) = GETNUM(field, cp, 0, errstr); \
}
			NXTNUM(lv, lv, &errstr);
			if (errstr) {
				warnx("line %d: bad partition size: %s",
				    lineno, cp);
				errors++;
			} else {
				DL_SETPSIZE(pp, lv);
			}
			NXTNUM(lv, lv, &errstr);
			if (errstr) {
				warnx("line %d: bad partition offset: %s",
				    lineno, cp);
				errors++;
			} else {
				DL_SETPOFFSET(pp, lv);
			}
			if (tp == NULL) {
				pp->p_fstype = FS_UNUSED;
				goto gottype;
			}
			cp = tp, tp = word(cp);
			cpp = fstypenames;
			for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
				if ((s = *cpp) && !strcasecmp(s, cp)) {
					pp->p_fstype = cpp - fstypenames;
					goto gottype;
				}
			if (isdigit((unsigned char)*cp))
				v = GETNUM(pp->p_fstype, cp, 0, &errstr);
			else
				v = FSMAXTYPES;
			if (errstr || v >= FSMAXTYPES) {
				warnx("line %d: warning, unknown filesystem type: %s",
				    lineno, cp);
				v = FS_UNUSED;
			}
			pp->p_fstype = v;
	gottype:
			switch (pp->p_fstype) {

			case FS_UNUSED:				/* XXX */
				if (tp == NULL)	/* ok to skip fsize/bsize */
					break;
				NXTNUM(fsize, fsize, &errstr);
				if (fsize == 0)
					break;
				NXTNUM(v, v, &errstr);
				pp->p_fragblock =
				    DISKLABELV1_FFS_FRAGBLOCK(fsize, v / fsize);
				break;

			case FS_BSDFFS:
				NXTNUM(fsize, fsize, &errstr);
				if (fsize == 0)
					break;
				NXTNUM(v, v, &errstr);
				pp->p_fragblock =
				    DISKLABELV1_FFS_FRAGBLOCK(fsize, v / fsize);
				NXTNUM(pp->p_cpg, pp->p_cpg, &errstr);
				break;

			default:
				break;
			}
			continue;
		}
		warnx("line %d: unknown field: %s", lineno, cp);
		errors++;
	next:
		;
	}
	errors += checklabel(lp);
	return (errors > 0);
}
Ejemplo n.º 3
0
int
readdpmelabel(struct buf *bp, void (*strat)(struct buf *),
    struct disklabel *lp, daddr_t *partoffp, int spoofonly)
{
	int i, part_cnt, n, hfspartoff = -1;
	long long hfspartend = DL_GETDSIZE(lp);
	struct part_map_entry *part;

	/* First check for a DPME (HFS) disklabel */
	bp->b_blkno = LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if (biowait(bp))
		return (bp->b_error);

	/* if successful, wander through DPME partition table */
	part = (struct part_map_entry *)bp->b_data;
	/* if first partition is not valid, assume not HFS/DPME partitioned */
	if (part->pmSig != PART_ENTRY_MAGIC)
		return (EINVAL);	/* not a DPME partition */
	part_cnt = part->pmMapBlkCnt;
	n = 8;
	for (i = 0; i < part_cnt; i++) {
		struct partition *pp;
		char *s;

		bp->b_blkno = LABELSECTOR + i;
		bp->b_bcount = lp->d_secsize;
		CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
		SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
		(*strat)(bp);
		if (biowait(bp))
			return (bp->b_error);

		part = (struct part_map_entry *)bp->b_data;
		/* toupper the string, in case caps are different... */
		for (s = part->pmPartType; *s; s++)
			if ((*s >= 'a') && (*s <= 'z'))
				*s = (*s - 'a' + 'A');

		if (strcmp(part->pmPartType, PART_TYPE_OPENBSD) == 0) {
			hfspartoff = part->pmPyPartStart;
			hfspartend = hfspartoff + part->pmPartBlkCnt;
			if (partoffp) {
				*partoffp = hfspartoff;
				return (0);
			} else {
				DL_SETBSTART(lp, hfspartoff);
				DL_SETBEND(lp,
				    hfspartend < DL_GETDSIZE(lp) ? hfspartend :
				    DL_GETDSIZE(lp));
			}
			continue;
		}

		if (n >= MAXPARTITIONS || partoffp)
			continue;

		/* Currently we spoof HFS partitions only. */
		if (strcmp(part->pmPartType, PART_TYPE_MAC) == 0) {
			pp = &lp->d_partitions[n];
			DL_SETPOFFSET(pp, part->pmPyPartStart);
			DL_SETPSIZE(pp, part->pmPartBlkCnt);
			pp->p_fstype = FS_HFS;
			n++;
		}

	}

	if (hfspartoff == -1)
		return (EINVAL);	/* no OpenBSD partition inside DPME label */

	if (spoofonly)
		return (0);

	/* next, dig out disk label */
	bp->b_blkno = hfspartoff;
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if (biowait(bp))
		return(bp->b_error);

	/*
	 * Do OpenBSD disklabel validation/adjustment.
	 *
	 * N.B: No matter what the bits are on the disk, we now have the
	 * disklabel for this dpme disk. DO NOT proceed to readdoslabel(),
	 * iso_spooflabel(), * etc.
	 */
	checkdisklabel(bp->b_data + LABELOFFSET, lp, hfspartoff, hfspartend);
	return (0);
}
Ejemplo n.º 4
0
/*
 * Do a lazy probe on the underlying media to check if it's a UDF volume, in
 * which case we fake a disk label for it.
 */
int
udf_disklabelspoof(dev_t dev, void (*strat)(struct buf *),
    struct disklabel *lp)
{
	char vid[32];
	int i, bsize = 2048, error = EINVAL;
	uint32_t sector = 256, mvds_start, mvds_end;
	struct buf *bp;
	struct anchor_vdp avdp;
	struct pri_vol_desc *pvd;

	/*
	 * Get a buffer to work with.
	 */
	bp = geteblk(bsize);
	bp->b_dev = dev;

	/*
	 * Look for an Anchor Volume Descriptor at sector 256.
	 */
	bp->b_blkno = sector * btodb(bsize);
	bp->b_bcount = bsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	bp->b_resid = bp->b_blkno / lp->d_secpercyl;

	(*strat)(bp);
	if (biowait(bp))
		goto out;

	if (udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR))
		goto out;

	bcopy(bp->b_data, &avdp, sizeof(avdp));
	mvds_start = letoh32(avdp.main_vds_ex.loc);
	mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize;

	/*
	 * Then try to find a reference to a Primary Volume Descriptor.
	 */
	for (sector = mvds_start; sector < mvds_end; sector++) {
		bp->b_blkno = sector * btodb(bsize);
		bp->b_bcount = bsize;
		CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
		SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
		bp->b_resid = bp->b_blkno / lp->d_secpercyl;

		(*strat)(bp);
		if (biowait(bp))
			goto out;

		pvd = (struct pri_vol_desc *)bp->b_data;
		if (!udf_checktag(&pvd->tag, TAGID_PRI_VOL))
			break;
	}

	/*
	 * If we couldn't find a reference, bail out.
	 */
	if (sector == mvds_end)
		goto out;

	/*
	 * Okay, it's a UDF volume. Spoof a disk label for it.
	 */
	if (udf_transname(pvd->vol_id, vid, sizeof(pvd->vol_id) - 1, NULL))
		strlcpy(lp->d_typename, vid, sizeof(lp->d_typename));

	for (i = 0; i < MAXPARTITIONS; i++) {
		DL_SETPSIZE(&lp->d_partitions[i], 0);
		DL_SETPOFFSET(&lp->d_partitions[i], 0);
	}

	/*
	 * Fake two partitions, 'a' and 'c'.
	 */
	DL_SETPSIZE(&lp->d_partitions[0], DL_GETDSIZE(lp));
	lp->d_partitions[0].p_fstype = FS_UDF;
	DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
	lp->d_partitions[RAW_PART].p_fstype = FS_UDF;
	lp->d_npartitions = MAXPARTITIONS;
	lp->d_version = 1;

	lp->d_bbsize = 8192;	/* Fake. */
	lp->d_sbsize = 64*1024;	/* Fake. */
	lp->d_magic = DISKMAGIC;
	lp->d_magic2 = DISKMAGIC;
	lp->d_checksum = dkcksum(lp);

	error = 0;
out:
	bp->b_flags |= B_INVAL;
	brelse(bp);

	return (error);
}
Ejemplo n.º 5
0
/*
 * Given a SunOS disk label, set lp to a BSD disk label.
 * The BSD label is cleared out before this is called.
 */
static int
disklabel_sun_to_bsd(struct sun_disklabel *sl, struct disklabel *lp)
{
	struct sun_preamble *preamble = (struct sun_preamble *)sl;
	struct sun_partinfo *ppp;
	struct sun_dkpart *spp;
	struct partition *npp;
	u_short cksum = 0, *sp1, *sp2;
	int i, secpercyl;

	/* Verify the XOR check. */
	sp1 = (u_short *)sl;
	sp2 = (u_short *)(sl + 1);
	while (sp1 < sp2)
		cksum ^= *sp1++;
	if (cksum != 0)
		return (EINVAL);	/* SunOS disk label, bad checksum */

	/* Format conversion. */
	lp->d_magic = DISKMAGIC;
	lp->d_magic2 = DISKMAGIC;
	lp->d_flags = D_VENDOR;
	memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname));

	lp->d_secsize = DEV_BSIZE;
	lp->d_nsectors = sl->sl_nsectors;
	lp->d_ntracks = sl->sl_ntracks;
	lp->d_ncylinders = sl->sl_ncylinders;

	secpercyl = sl->sl_nsectors * sl->sl_ntracks;
	lp->d_secpercyl = secpercyl;
	/* If unset or initialized as full disk, permit refinement */
	if (DL_GETDSIZE(lp) == 0 || DL_GETDSIZE(lp) == MAXDISKSIZE)
		DL_SETDSIZE(lp, (u_int64_t)secpercyl * sl->sl_ncylinders);
	lp->d_version = 1;

	memcpy(&lp->d_uid, &sl->sl_uid, sizeof(lp->d_uid));

	lp->d_acylinders = sl->sl_acylinders;

	lp->d_npartitions = MAXPARTITIONS;
	/* These are as defined in <ufs/ffs/fs.h> */
	lp->d_bbsize = 8192;	/* XXX */
	lp->d_sbsize = 8192;	/* XXX */

	for (i = 0; i < 8; i++) {
		spp = &sl->sl_part[i];
		npp = &lp->d_partitions[i];
		DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl);
		DL_SETPSIZE(npp, spp->sdkp_nsectors);
		if (DL_GETPSIZE(npp) == 0) {
			npp->p_fstype = FS_UNUSED;
		} else {
			npp->p_fstype = sun_fstypes[i];
			if (npp->p_fstype == FS_BSDFFS) {
				/*
				 * The sun label does not store the FFS fields,
				 * so just set them with default values here.
				 */
				npp->p_fragblock =
				    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
				npp->p_cpg = 16;
			}
		}
	}

	/* Clear "extended" partition info, tentatively */
	for (i = 0; i < SUNXPART; i++) {
		npp = &lp->d_partitions[i+8];
		DL_SETPOFFSET(npp, 0);
		DL_SETPSIZE(npp, 0);
		npp->p_fstype = FS_UNUSED;
	}

	/* Check to see if there's an "extended" partition table
	 * SL_XPMAG partitions had checksums up to just before the
	 * (new) sl_types variable, while SL_XPMAGTYP partitions have
	 * checksums up to the just before the (new) sl_xxx1 variable.
	 * Also, disklabels created prior to the addition of sl_uid will
	 * have a checksum to just before the sl_uid variable.
	 */
	if ((sl->sl_xpmag == SL_XPMAG &&
	    sun_extended_sum(sl, &sl->sl_types) == sl->sl_xpsum) ||
	    (sl->sl_xpmag == SL_XPMAGTYP &&
	    sun_extended_sum(sl, &sl->sl_uid) == sl->sl_xpsum) ||
	    (sl->sl_xpmag == SL_XPMAGTYP &&
	    sun_extended_sum(sl, &sl->sl_xxx1) == sl->sl_xpsum)) {
		/*
		 * There is.  Copy over the "extended" partitions.
		 * This code parallels the loop for partitions a-h.
		 */
		for (i = 0; i < SUNXPART; i++) {
			spp = &sl->sl_xpart[i];
			npp = &lp->d_partitions[i+8];
			DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl);
			DL_SETPSIZE(npp, spp->sdkp_nsectors);
			if (DL_GETPSIZE(npp) == 0) {
				npp->p_fstype = FS_UNUSED;
				continue;
			}
			npp->p_fstype = sun_fstypes[i+8];
			if (npp->p_fstype == FS_BSDFFS) {
				npp->p_fragblock =
				    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
				npp->p_cpg = 16;
			}
		}
		if (sl->sl_xpmag == SL_XPMAGTYP) {
			for (i = 0; i < MAXPARTITIONS; i++) {
				npp = &lp->d_partitions[i];
				npp->p_fstype = sl->sl_types[i];
				npp->p_fragblock = sl->sl_fragblock[i];
				npp->p_cpg = sl->sl_cpg[i];
			}
		}
	} else if (preamble->sl_nparts <= 8) {
		/*
		 * A more traditional Sun label.  Recognise certain filesystem
		 * types from it, if they are available.
		 */
		i = preamble->sl_nparts;
		if (i == 0)
			i = 8;

		npp = &lp->d_partitions[i-1];
		ppp = &preamble->sl_part[i-1];
		for (; i > 0; i--, npp--, ppp--) {
			if (npp->p_size == 0)
				continue;
			if ((ppp->spi_tag == 0) && (ppp->spi_flag == 0))
				continue;

			switch (ppp->spi_tag) {
			case SPTAG_SUNOS_ROOT:
			case SPTAG_SUNOS_USR:
			case SPTAG_SUNOS_VAR:
			case SPTAG_SUNOS_HOME:
				npp->p_fstype = FS_BSDFFS;
				npp->p_fragblock =
				    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
				npp->p_cpg = 16;
				break;
			case SPTAG_LINUX_EXT2:
				npp->p_fstype = FS_EXT2FS;
				break;
			default:
				/* FS_SWAP for _SUNOS_SWAP and _LINUX_SWAP? */
				npp->p_fstype = FS_UNUSED;
				break;
			}
		}
	}

	lp->d_checksum = 0;
	lp->d_checksum = dkcksum(lp);
	return (checkdisklabel(lp, lp, 0, DL_GETDSIZE(lp)));
}
Ejemplo n.º 6
0
int
readliflabel(struct buf *bp, void (*strat)(struct buf *),
    struct disklabel *lp, int *partoffp, int spoofonly)
{
	struct buf *dbp = NULL;
	struct lifdir *p;
	struct lifvol *lvp;
	int error = 0;
	int fsoff = 0, openbsdstart = MAXLIFSPACE, i;

	/* read LIF volume header */
	bp->b_blkno = btodb(LIF_VOLSTART);
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if (biowait(bp))
		return (bp->b_error);

	lvp = (struct lifvol *)bp->b_data;
	if (lvp->vol_id != LIF_VOL_ID) {
		error = EINVAL;		/* no LIF volume header */
		goto done;
	}

	dbp = geteblk(LIF_DIRSIZE);
	dbp->b_dev = bp->b_dev;

	/* read LIF directory */
	dbp->b_blkno = lifstodb(lvp->vol_addr);
	dbp->b_bcount = lp->d_secsize;
	CLR(dbp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(dbp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(dbp);
	if (biowait(dbp)) {
		error = dbp->b_error;
		goto done;
	}

	/* scan for LIF_DIR_FS dir entry */
	for (i=0, p=(struct lifdir *)dbp->b_data; i < LIF_NUMDIR; p++, i++) {
		if (p->dir_type == LIF_DIR_FS || p->dir_type == LIF_DIR_HPLBL)
			break;
	}

	if (p->dir_type == LIF_DIR_FS) {
		fsoff = lifstodb(p->dir_addr);
		openbsdstart = 0;
		goto finished;
	}

	/* Only came here to find the offset... */
	if (partoffp)
		goto finished;

	if (p->dir_type == LIF_DIR_HPLBL) {
		struct hpux_label *hl;
		struct partition *pp;
		u_int8_t fstype;
		int i;

		/* read LIF directory */
		dbp->b_blkno = lifstodb(p->dir_addr);
		dbp->b_bcount = lp->d_secsize;
		CLR(dbp->b_flags, B_READ | B_WRITE | B_DONE);
		SET(dbp->b_flags, B_BUSY | B_READ | B_RAW);
		(*strat)(dbp);

		if (biowait(dbp)) {
			error = dbp->b_error;
			goto done;
		}

		hl = (struct hpux_label *)dbp->b_data;
		if (hl->hl_magic1 != hl->hl_magic2 ||
		    hl->hl_magic != HPUX_MAGIC || hl->hl_version != 1) {
			error = EINVAL;	 /* HPUX label magic mismatch */
			goto done;
		}

		lp->d_bbsize = 8192;
		lp->d_sbsize = 8192;
		for (i = 0; i < MAXPARTITIONS; i++) {
			DL_SETPSIZE(&lp->d_partitions[i], 0);
			DL_SETPOFFSET(&lp->d_partitions[i], 0);
			lp->d_partitions[i].p_fstype = 0;
		}

		for (i = 0; i < HPUX_MAXPART; i++) {
			if (!hl->hl_flags[i])
				continue;
			if (hl->hl_flags[i] == HPUX_PART_ROOT) {
				pp = &lp->d_partitions[0];
				fstype = FS_BSDFFS;
			} else if (hl->hl_flags[i] == HPUX_PART_SWAP) {
				pp = &lp->d_partitions[1];
				fstype = FS_SWAP;
			} else if (hl->hl_flags[i] == HPUX_PART_BOOT) {
				pp = &lp->d_partitions[RAW_PART + 1];
				fstype = FS_BSDFFS;
			} else
				continue;

			DL_SETPSIZE(pp, hl->hl_parts[i].hlp_length * 2);
			DL_SETPOFFSET(pp, hl->hl_parts[i].hlp_start * 2);
			pp->p_fstype = fstype;
		}

		DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
		DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
		lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
		lp->d_npartitions = MAXPARTITIONS;
		lp->d_magic = DISKMAGIC;
		lp->d_magic2 = DISKMAGIC;
		lp->d_version = 1;
		lp->d_checksum = 0;
		lp->d_checksum = dkcksum(lp);
		/* drop through */
	}

finished:
	/* record the OpenBSD partition's placement for the caller */
	if (partoffp)
		*partoffp = fsoff;
	else {
		DL_SETBSTART(lp, openbsdstart);
		DL_SETBEND(lp, DL_GETDSIZE(lp));	/* XXX */
	}

	/* don't read the on-disk label if we are in spoofed-only mode */
	if (spoofonly)
		goto done;

	bp->b_blkno = fsoff + LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if (biowait(bp)) {
		error = bp->b_error;
		goto done;
	}

	/*
	 * Do OpenBSD disklabel validation/adjustment.
	 *
	 * N.B: No matter what the bits are on the disk, we now have the
	 * OpenBSD disklabel for this lif disk. DO NOT proceed to
	 * readdoslabel(), iso_spooflabel(), etc.
	 */
	checkdisklabel(bp->b_data, lp, openbsdstart, DL_GETDSIZE(lp));
	error = 0;

done:
	if (dbp) {
		dbp->b_flags |= B_INVAL;
		brelse(dbp);
	}
	return (error);
}
Ejemplo n.º 7
0
/*
 * Given a UniOS/ISI disk label, set lp to a BSD disk label.
 *
 * The BSD label is cleared out before this is called.
 */
int
disklabel_om_to_bsd(struct sun_disklabel *sl, struct disklabel *lp)
{
	struct partition *npp;
	struct sun_dkpart *spp;
	int i, secpercyl;
	u_short cksum = 0, *sp1, *sp2;

	/* Verify the XOR check. */
	sp1 = (u_short *)sl;
	sp2 = (u_short *)(sl + 1);
	while (sp1 < sp2)
		cksum ^= *sp1++;
	if (cksum != 0)
		return (EINVAL);	/* UniOS disk label, bad checksum */

	/* Format conversion. */
	lp->d_magic = DISKMAGIC;
	lp->d_magic2 = DISKMAGIC;
	lp->d_flags = D_VENDOR;
	memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname));

	lp->d_secsize = DEV_BSIZE;
	lp->d_nsectors = sl->sl_nsectors;
	lp->d_ntracks = sl->sl_ntracks;
	lp->d_ncylinders = sl->sl_ncylinders;

	secpercyl = sl->sl_nsectors * sl->sl_ntracks;
	lp->d_secpercyl = secpercyl;
	/* If unset or initialized as full disk, permit refinement */
	if (DL_GETDSIZE(lp) == 0 || DL_GETDSIZE(lp) == MAXDISKSIZE)
		DL_SETDSIZE(lp, (u_int64_t)secpercyl * sl->sl_ncylinders);
	lp->d_version = 1;

	memcpy(&lp->d_uid, &sl->sl_uid, sizeof(sl->sl_uid));

	lp->d_acylinders = sl->sl_acylinders;

	lp->d_npartitions = MAXPARTITIONS;
	/* These are as defined in <ufs/ffs/fs.h> */
	lp->d_bbsize = 8192;	/* XXX */
	lp->d_sbsize = 8192;	/* XXX */

	for (i = 0; i < 8; i++) {
		spp = &sl->sl_part[i];
		npp = &lp->d_partitions[i];
		/* UniOS label uses blkoffset, not cyloffset */
		DL_SETPOFFSET(npp, spp->sdkp_cyloffset);
		DL_SETPSIZE(npp, spp->sdkp_nsectors);
		if (DL_GETPSIZE(npp) == 0) {
			npp->p_fstype = FS_UNUSED;
		} else {
			npp->p_fstype = sun_fstypes[i];
			if (npp->p_fstype == FS_BSDFFS) {
				/*
				 * The sun label does not store the FFS fields,
				 * so just set them with default values here.
				 */
				npp->p_fragblock =
				    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
				npp->p_cpg = 16;
			}
		}
	}

	/*
	 * XXX BandAid XXX
	 * UniOS rootfs sits on part c which don't begin at sect 0,
	 * and impossible to mount.  Thus, make it usable as part b.
	 * XXX how to setup a swap partition on disks shared with UniOS???
	 */
	if (sl->sl_rpm == 0 && DL_GETPOFFSET(&lp->d_partitions[2]) != 0) {
		lp->d_partitions[1] = lp->d_partitions[2];
		lp->d_partitions[1].p_fstype = FS_BSDFFS;
	}

	/* Clear "extended" partition info, tentatively */
	for (i = 0; i < SUNXPART; i++) {
		npp = &lp->d_partitions[i+8];
		DL_SETPOFFSET(npp, 0);
		DL_SETPSIZE(npp, 0);
		npp->p_fstype = FS_UNUSED;
	}

	/* Check to see if there's an "extended" partition table
	 * SL_XPMAG partitions had checksums up to just before the
	 * (new) sl_types variable, while SL_XPMAGTYP partitions have
	 * checksums up to the just before the (new) sl_xxx1 variable.
	 */
	if ((sl->sl_xpmag == SL_XPMAG &&
	    sun_extended_sum(sl, &sl->sl_types) == sl->sl_xpsum) ||
	    (sl->sl_xpmag == SL_XPMAGTYP &&
	    sun_extended_sum(sl, &sl->sl_xxx1) == sl->sl_xpsum)) {
		/*
		 * There is.  Copy over the "extended" partitions.
		 * This code parallels the loop for partitions a-h.
		 */
		for (i = 0; i < SUNXPART; i++) {
			spp = &sl->sl_xpart[i];
			npp = &lp->d_partitions[i+8];
			DL_SETPOFFSET(npp, spp->sdkp_cyloffset);
			DL_SETPSIZE(npp, spp->sdkp_nsectors);
			if (DL_GETPSIZE(npp) == 0) {
				npp->p_fstype = FS_UNUSED;
				continue;
			}
			npp->p_fstype = sun_fstypes[i+8];
			if (npp->p_fstype == FS_BSDFFS) {
				npp->p_fragblock =
				    DISKLABELV1_FFS_FRAGBLOCK(2048, 8);
				npp->p_cpg = 16;
			}
		}
		if (sl->sl_xpmag == SL_XPMAGTYP) {
			for (i = 0; i < MAXPARTITIONS; i++) {
				npp = &lp->d_partitions[i];
				npp->p_fstype = sl->sl_types[i];
				npp->p_fragblock = sl->sl_fragblock[i];
				npp->p_cpg = sl->sl_cpg[i];
			}
		}
	}

	lp->d_checksum = 0;
	lp->d_checksum = dkcksum(lp);
	return (checkdisklabel(lp, lp, 0, DL_GETDSIZE(lp)));
}
Ejemplo n.º 8
0
void
cdprobe(void)
{
	struct diskinfo *dip;
	int cddev = bios_cddev & 0xff;

	/* Another BIOS boot device... */

	if (bios_cddev == -1)			/* Not been set, so don't use */
		return;

	dip = alloc(sizeof(struct diskinfo));
	bzero(dip, sizeof(*dip));

#if 0
	if (bios_getdiskinfo(cddev, &dip->bios_info)) {
		printf(" <!cd0>");	/* XXX */
		free(dip, 0);
		return;
	}
#endif

	printf(" cd0");

	dip->bios_info.bios_number = cddev;
	dip->bios_info.bios_edd = 1;		/* Use the LBA calls */
	dip->bios_info.flags |= BDI_GOODLABEL | BDI_EL_TORITO;
	dip->bios_info.checksum = 0;		 /* just in case */
	dip->bios_info.bsd_dev =
	    MAKEBOOTDEV(6, 0, 0, 0, RAW_PART);

	/* Create an imaginary disk label */
	dip->disklabel.d_secsize = 2048;
	dip->disklabel.d_ntracks = 1;
	dip->disklabel.d_nsectors = 100;
	dip->disklabel.d_ncylinders = 1;
	dip->disklabel.d_secpercyl = dip->disklabel.d_ntracks *
	    dip->disklabel.d_nsectors;
	if (dip->disklabel.d_secpercyl == 0) {
		dip->disklabel.d_secpercyl = 100;
		/* as long as it's not 0, since readdisklabel divides by it */
	}

	strncpy(dip->disklabel.d_typename, "ATAPI CD-ROM",
	    sizeof(dip->disklabel.d_typename));
	dip->disklabel.d_type = DTYPE_ATAPI;

	strncpy(dip->disklabel.d_packname, "fictitious",
	    sizeof(dip->disklabel.d_packname));
	DL_SETDSIZE(&dip->disklabel, 100);

	dip->disklabel.d_bbsize = 2048;
	dip->disklabel.d_sbsize = 2048;

	/* 'a' partition covering the "whole" disk */
	DL_SETPOFFSET(&dip->disklabel.d_partitions[0], 0);
	DL_SETPSIZE(&dip->disklabel.d_partitions[0], 100);
	dip->disklabel.d_partitions[0].p_fstype = FS_UNUSED;

	/* The raw partition is special */
	DL_SETPOFFSET(&dip->disklabel.d_partitions[RAW_PART], 0);
	DL_SETPSIZE(&dip->disklabel.d_partitions[RAW_PART], 100);
	dip->disklabel.d_partitions[RAW_PART].p_fstype = FS_UNUSED;

	dip->disklabel.d_npartitions = MAXPARTITIONS;

	dip->disklabel.d_magic = DISKMAGIC;
	dip->disklabel.d_magic2 = DISKMAGIC;
	dip->disklabel.d_checksum = dkcksum(&dip->disklabel);

	/* Add to queue of disks */
	TAILQ_INSERT_TAIL(&disklist, dip, list);
}
Ejemplo n.º 9
0
int
readsgilabel(struct buf *bp, void (*strat)(struct buf *),
             struct disklabel *lp, daddr_t *partoffp, int spoofonly)
{
    struct sgilabel *dlp;
    int i, *p, cs = 0;
    daddr_t fsoffs, fsend;
    int error, offset;

    /* if successful, locate disk label within block and validate */
    error = readdisksector(bp, strat, lp, 0);
    if (error)
        return (error);

    fsoffs = DL_SECTOBLK(lp, DL_GETBSTART(lp));
    fsend = DL_SECTOBLK(lp, DL_GETBEND(lp));

    dlp = (struct sgilabel *)(bp->b_data + LABELOFFSET);
    if (dlp->magic != htobe32(SGILABEL_MAGIC))
        goto finished;

    if (dlp->partitions[0].blocks == 0)
        return (EINVAL);
    fsoffs = (long long)dlp->partitions[0].first;
    fsend = fsoffs + dlp->partitions[0].blocks;

    /* Only came here to find the offset... */
    if (partoffp) {
        *partoffp = fsoffs;
        goto finished;
    }

    p = (int *)dlp;
    i = sizeof(struct sgilabel) / sizeof(int);
    while (i--)
        cs += *p++;
    if (cs != 0)
        return (EINVAL);	/* sgilabel checksum error */

    /* Spoof info from sgi label, in case there is no OpenBSD label. */
    lp->d_npartitions = MAXPARTITIONS;

    for (i = 0; i < 16; i++) {
        int bsd = maptab[i].m;
        int type = maptab[i].b;

        if (spoofonly && type != FS_UNUSED && type != FS_OTHER)
            continue;

        DL_SETPOFFSET(&lp->d_partitions[bsd],
                      dlp->partitions[i].first);
        DL_SETPSIZE(&lp->d_partitions[bsd],
                    dlp->partitions[i].blocks);
        lp->d_partitions[bsd].p_fstype = type;
        if (type == FS_BSDFFS) {
            lp->d_partitions[bsd].p_fragblock =
                DISKLABELV1_FFS_FRAGBLOCK(1024, 8);
            lp->d_partitions[bsd].p_cpg = 16;
        }
    }

    DL_SETBSTART(lp, DL_BLKTOSEC(lp, fsoffs));
    DL_SETBEND(lp, DL_BLKTOSEC(lp, fsend));
    lp->d_version = 1;
    lp->d_flags = D_VENDOR;
    lp->d_checksum = 0;
    lp->d_checksum = dkcksum(lp);

finished:
    /* record the OpenBSD partition's placement for the caller */
    if (partoffp)
        *partoffp = fsoffs;
    else {
        DL_SETBSTART(lp, DL_BLKTOSEC(lp, fsoffs));
        DL_SETBEND(lp, DL_BLKTOSEC(lp, fsend));
    }

    /* don't read the on-disk label if we are in spoofed-only mode */
    if (spoofonly)
        return (0);

    error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, fsoffs +
                           LABELSECTOR));
    if (error)
        return (error);
    offset = DL_BLKOFFSET(lp, fsoffs + LABELSECTOR) + LABELOFFSET;

    /*
     * Do OpenBSD disklabel validation/adjustment.
     *
     * N.B: No matter what the bits are on the disk, we now have the
     * OpenBSD disklabel for this sgi disk. DO NOT proceed to
     * readdoslabel(), iso_spooflabel(), etc.
     */
    checkdisklabel(bp->b_data + offset, lp, fsoffs, fsend);
    return (0);
}