コード例 #1
0
ファイル: wd.c プロジェクト: DavidAlphaFox/openbsd-kernel
void
__wdstart(struct wd_softc *wd, struct buf *bp)
{
	struct disklabel *lp;
	u_int64_t nsecs;

	lp = wd->sc_dk.dk_label;
	wd->sc_wdc_bio.blkno = DL_BLKTOSEC(lp, bp->b_blkno + DL_SECTOBLK(lp,
	    DL_GETPOFFSET(&lp->d_partitions[DISKPART(bp->b_dev)])));
	wd->sc_wdc_bio.blkdone =0;
	wd->sc_bp = bp;
	/*
	 * If we're retrying, retry in single-sector mode. This will give us
	 * the sector number of the problem, and will eventually allow the
	 * transfer to succeed.
	 */
	if (wd->retries >= WDIORETRIES_SINGLE)
		wd->sc_wdc_bio.flags = ATA_SINGLE;
	else
		wd->sc_wdc_bio.flags = 0;
	nsecs = howmany(bp->b_bcount, lp->d_secsize);
	if ((wd->sc_flags & WDF_LBA48) &&
	    /* use LBA48 only if really need */
	    ((wd->sc_wdc_bio.blkno + nsecs - 1 >= LBA48_THRESHOLD) ||
	     (nsecs > 0xff)))
		wd->sc_wdc_bio.flags |= ATA_LBA48;
	if (wd->sc_flags & WDF_LBA)
		wd->sc_wdc_bio.flags |= ATA_LBA;
	if (bp->b_flags & B_READ)
		wd->sc_wdc_bio.flags |= ATA_READ;
	wd->sc_wdc_bio.bcount = bp->b_bcount;
	wd->sc_wdc_bio.databuf = bp->b_data;
	wd->sc_wdc_bio.wd = wd;
	/* Instrumentation. */
	disk_busy(&wd->sc_dk);
	switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) {
	case WDC_TRY_AGAIN:
		timeout_add_sec(&wd->sc_restart_timeout, 1);
		break;
	case WDC_QUEUED:
		break;
	case WDC_COMPLETE:
		/*
		 * This code is never executed because we never set
		 * the ATA_POLL flag above
		 */
#if 0
		if (wd->sc_wdc_bio.flags & ATA_POLL)
			wddone(wd);
#endif
		break;
	default:
		panic("__wdstart: bad return code from wdc_ata_bio()");
	}
}
コード例 #2
0
/*
 * Display a particular partition.
 */
void
display_partition(FILE *f, struct disklabel *lp, int i, char unit)
{
	volatile struct partition *pp = &lp->d_partitions[i];
	double p_size;

	p_size = scale(DL_GETPSIZE(pp), unit, lp);
	if (DL_GETPSIZE(pp)) {
		u_int32_t frag = DISKLABELV1_FFS_FRAG(pp->p_fragblock);
		u_int32_t fsize = DISKLABELV1_FFS_FSIZE(pp->p_fragblock);

		if (p_size < 0)
			fprintf(f, "  %c: %16llu %16llu ", 'a' + i,
			    DL_GETPSIZE(pp), DL_GETPOFFSET(pp));
		else
			fprintf(f, "  %c: %15.*f%c %16llu ", 'a' + i,
			    unit == 'B' ? 0 : 1, p_size, unit,
			    DL_GETPOFFSET(pp));
		if (pp->p_fstype < FSMAXTYPES)
			fprintf(f, "%7.7s", fstypenames[pp->p_fstype]);
		else
			fprintf(f, "%7d", pp->p_fstype);

		switch (pp->p_fstype) {
		case FS_BSDFFS:
			fprintf(f, "  %5u %5u %4hu ",
			    fsize, fsize * frag,
			    pp->p_cpg);
			break;
		default:
			fprintf(f, "%19.19s", "");
			break;
		}

		if (mountpoints[i] != NULL)
			fprintf(f, "# %s", mountpoints[i]);
		putc('\n', f);
	}
}
コード例 #3
0
ファイル: rd.c プロジェクト: sofuture/bitrig
void
rdstrategy(struct buf *bp)
{
	struct rd_softc *sc;
	struct partition *p;
	size_t off, xfer;
	caddr_t addr;
	int s;

	sc = rdlookup(DISKUNIT(bp->b_dev));
	if (sc == NULL) {
		bp->b_error = ENXIO;
		goto bad;
	}

	/* Validate the request. */
	if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1)
		goto done;

	/* Do the transfer. */
	/* XXX: Worry about overflow when computing off? */

	p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
	off = DL_GETPOFFSET(p) * sc->sc_dk.dk_label->d_secsize +
	    (u_int64_t)bp->b_blkno * DEV_BSIZE;
	if (off > rd_root_size)
		off = rd_root_size;
	xfer = bp->b_bcount;
	if (xfer > rd_root_size - off)
		xfer = rd_root_size - off;
	addr = rd_root_image + off;
	if (bp->b_flags & B_READ)
		memcpy(bp->b_data, addr, xfer);
	else
		memcpy(addr, bp->b_data, xfer);
	bp->b_resid = bp->b_bcount - xfer;
	goto done;

 bad:
	bp->b_flags |= B_ERROR;
	bp->b_resid = bp->b_bcount;
 done:
	s = splbio();
	biodone(bp);
	splx(s);
	if (sc != NULL)
		device_unref(&sc->sc_dev);
}
コード例 #4
0
/*
 * If we are installing a boot program that doesn't fit in d_bbsize
 * we need to mark those partitions that the boot overflows into.
 * This allows newfs to prevent creation of a filesystem where it might
 * clobber bootstrap code.
 */
void
setbootflag(struct disklabel *lp)
{
	struct partition *pp;
	int i, errors = 0;
	u_int64_t bend;
	char part;

	if (bootbuf == NULL)
		return;

	bend = (u_int64_t)bootsize / lp->d_secsize;
	for (i = 0; i < lp->d_npartitions; i++) {
		if (i == RAW_PART)
			/* It will *ALWAYS* overlap 'c'. */
			continue;
		pp = &lp->d_partitions[i];
		if (DL_GETPSIZE(pp) == 0)
			/* Partition is unused. */
			continue;
		if (bend <= DL_GETPOFFSET(pp)) {
			/* Boot blocks end before this partition starts. */
			if (pp->p_fstype == FS_BOOT)
				pp->p_fstype = FS_UNUSED;
			continue;
		}

		part = 'a' + i;
		switch (pp->p_fstype) {
		case FS_BOOT:	/* Already marked. */
			break;
		case FS_UNUSED:	/* Mark. */
			pp->p_fstype = FS_BOOT;
			warnx("warning, boot overlaps partition %c, %s",
			    part, "marked as FS_BOOT");
			break;
		default:
			warnx("boot overlaps used partition %c", part);
			errors++;
			break;
		}
	}
	if (errors)
		errx(4, "cannot install boot program");
}
コード例 #5
0
/*
 * Check disklabel for errors and fill in
 * derived fields according to supplied values.
 */
int
checklabel(struct disklabel *lp)
{
	struct partition *pp;
	int i, errors = 0;
	char part;

	if (lp->d_secsize == 0) {
		warnx("sector size %d", lp->d_secsize);
		return (1);
	}
	if (lp->d_nsectors == 0) {
		warnx("sectors/track %d", lp->d_nsectors);
		return (1);
	}
	if (lp->d_ntracks == 0) {
		warnx("tracks/cylinder %d", lp->d_ntracks);
		return (1);
	}
	if  (lp->d_ncylinders == 0) {
		warnx("cylinders/unit %d", lp->d_ncylinders);
		errors++;
	}
	if (lp->d_secpercyl == 0)
		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
	if (DL_GETDSIZE(lp) == 0)
		DL_SETDSIZE(lp, (u_int64_t)lp->d_secpercyl * lp->d_ncylinders);
	if (lp->d_bbsize == 0) {
		warnx("boot block size %d", lp->d_bbsize);
		errors++;
	} else if (lp->d_bbsize % lp->d_secsize)
		warnx("warning, boot block size %% sector-size != 0");
	if (lp->d_sbsize == 0) {
		warnx("super block size %d", lp->d_sbsize);
		errors++;
	} else if (lp->d_sbsize % lp->d_secsize)
		warnx("warning, super block size %% sector-size != 0");
	if (lp->d_npartitions > MAXPARTITIONS)
		warnx("warning, number of partitions (%d) > MAXPARTITIONS (%d)",
		    lp->d_npartitions, MAXPARTITIONS);
	for (i = 0; i < lp->d_npartitions; i++) {
		part = 'a' + i;
		pp = &lp->d_partitions[i];
		if (DL_GETPSIZE(pp) == 0 && DL_GETPOFFSET(pp) != 0)
			warnx("warning, partition %c: size 0, but offset %llu",
			    part, DL_GETPOFFSET(pp));
#ifdef SUN_CYLCHECK
		if (lp->d_flags & D_VENDOR) {
			if (i != RAW_PART && DL_GETPSIZE(pp) % lp->d_secpercyl)
				warnx("warning, partition %c: size %% "
				    "cylinder-size != 0", part);
			if (i != RAW_PART && DL_GETPOFFSET(pp) % lp->d_secpercyl)
				warnx("warning, partition %c: offset %% "
				    "cylinder-size != 0", part);
		}
#endif
#ifdef SUN_AAT0
		if ((lp->d_flags & D_VENDOR) &&
		    i == 0 && DL_GETPSIZE(pp) != 0 && DL_GETPOFFSET(pp) != 0) {
			warnx("this architecture requires partition 'a' to "
			    "start at sector 0");
			errors++;
		}
#endif
		if (DL_GETPOFFSET(pp) > DL_GETDSIZE(lp)) {
			warnx("partition %c: offset past end of unit", part);
			errors++;
		}
		if (DL_GETPOFFSET(pp) + DL_GETPSIZE(pp) > DL_GETDSIZE(lp)) {
			warnx("partition %c: partition extends past end of unit",
			    part);
			errors++;
		}
#if 0
		if (pp->p_frag == 0 && pp->p_fsize != 0) {
			warnx("partition %c: block size < fragment size", part);
			errors++;
		}
#endif
	}
	for (; i < MAXPARTITIONS; i++) {
		part = 'a' + i;
		pp = &lp->d_partitions[i];
		if (DL_GETPSIZE(pp) || DL_GETPOFFSET(pp))
			warnx("warning, unused partition %c: size %llu "
			    "offset %llu", part, DL_GETPSIZE(pp),
			    DL_GETPOFFSET(pp));
	}
	return (errors > 0);
}
コード例 #6
0
ファイル: disksubr.c プロジェクト: ajinkya93/OpenBSD
/*
 * Given a BSD disk label, update the Sun disklabel
 * pointed to by cp with the new info.  Note that the
 * Sun disklabel may have other info we need to keep.
 */
static int
disklabel_bsd_to_sun(struct disklabel *lp, struct sun_disklabel *sl)
{
	struct partition *npp;
	struct sun_dkpart *spp;
	int i, secpercyl;
	u_short cksum, *sp1, *sp2;

	/* Enforce preconditions */
	if (lp->d_secsize != DEV_BSIZE || lp->d_nsectors == 0 ||
	    lp->d_ntracks == 0)
		return (EINVAL);

	/* Format conversion. */
	bzero(sl, sizeof(*sl));
	memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname));
	sl->sl_pcylinders = lp->d_ncylinders + lp->d_acylinders; /* XXX */
	sl->sl_ncylinders = lp->d_ncylinders;
	sl->sl_acylinders = lp->d_acylinders;
	sl->sl_ntracks = lp->d_ntracks;
	sl->sl_nsectors = lp->d_nsectors;

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

	secpercyl = sl->sl_nsectors * sl->sl_ntracks;
	for (i = 0; i < 8; i++) {
		spp = &sl->sl_part[i];
		npp = &lp->d_partitions[i];
		spp->sdkp_cyloffset = 0;
		spp->sdkp_nsectors = 0;
		if (DL_GETPSIZE(npp)) {
			if (DL_GETPOFFSET(npp) % secpercyl)
				return (EINVAL);
			spp->sdkp_cyloffset = DL_GETPOFFSET(npp) / secpercyl;
			spp->sdkp_nsectors = DL_GETPSIZE(npp);
		}
	}
	sl->sl_magic = SUN_DKMAGIC;

	for (i = 0; i < SUNXPART; i++) {
		spp = &sl->sl_xpart[i];
		npp = &lp->d_partitions[i+8];
		spp->sdkp_cyloffset = 0;
		spp->sdkp_nsectors = 0;
		if (DL_GETPSIZE(npp)) {
			if (DL_GETPOFFSET(npp) % secpercyl)
				return (EINVAL);
			spp->sdkp_cyloffset = DL_GETPOFFSET(npp) / secpercyl;
			spp->sdkp_nsectors = DL_GETPSIZE(npp);
		}
	}
	for (i = 0; i < MAXPARTITIONS; i++) {
		npp = &lp->d_partitions[i];
		sl->sl_types[i] = npp->p_fstype;
		sl->sl_fragblock[i] = npp->p_fragblock;
		sl->sl_cpg[i] = npp->p_cpg;
	}
	sl->sl_xpmag = SL_XPMAGTYP;
	sl->sl_xpsum = sun_extended_sum(sl, &sl->sl_xxx1);

	/* Correct the XOR check. */
	sp1 = (u_short *)sl;
	sp2 = (u_short *)(sl + 1);
	sl->sl_cksum = cksum = 0;
	while (sp1 < sp2)
		cksum ^= *sp1++;
	sl->sl_cksum = cksum;

	return (0);
}
コード例 #7
0
ファイル: cd.c プロジェクト: repos-holder/openbsd-patches
/*
 * cdstart looks to see if there is a buf waiting for the device
 * and that the device is not already busy. If both are true,
 * It deques the buf and creates a scsi command to perform the
 * transfer in the buf. The transfer request will call scsi_done
 * on completion, which will in turn call this routine again
 * so that the next queued transfer is performed.
 * The bufs are queued by the strategy routine (cdstrategy)
 *
 * This routine is also called after other non-queued requests
 * have been made of the scsi driver, to ensure that the queue
 * continues to be drained.
 *
 * must be called at the correct (highish) spl level
 * cdstart() is called at splbio from cdstrategy, cdrestart and scsi_done
 */
void
cdstart(void *v)
{
	struct cd_softc *cd = v;
	struct scsi_link *sc_link = cd->sc_link;
	struct buf *bp = 0;
	struct buf *dp;
	struct scsi_rw_big cmd_big;
	struct scsi_rw cmd_small;
	struct scsi_generic *cmdp;
	int blkno, nblks, cmdlen, error;
	struct partition *p;

	splassert(IPL_BIO);

	SC_DEBUG(sc_link, SDEV_DB2, ("cdstart\n"));
	/*
	 * Check if the device has room for another command
	 */
	while (sc_link->openings > 0) {
		/*
		 * there is excess capacity, but a special waits
		 * It'll need the adapter as soon as we clear out of the
		 * way and let it run (user level wait).
		 */
		if (sc_link->flags & SDEV_WAITING) {
			sc_link->flags &= ~SDEV_WAITING;
			wakeup((caddr_t)sc_link);
			return;
		}

		/*
		 * See if there is a buf with work for us to do..
		 */
		dp = &cd->buf_queue;
		if ((bp = dp->b_actf) == NULL)	/* yes, an assign */
			return;
		dp->b_actf = bp->b_actf;

		/*
		 * If the device has become invalid, abort all the
		 * reads and writes until all files have been closed and
		 * re-opened
		 */
		if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
			bp->b_error = EIO;
			bp->b_flags |= B_ERROR;
			bp->b_resid = bp->b_bcount;
			biodone(bp);
			continue;
		}

		/*
		 * We have a buf, now we should make a command
		 *
		 * First, translate the block to absolute and put it in terms
		 * of the logical blocksize of the device.
		 */
		blkno =
		    bp->b_blkno / (cd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
		p = &cd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
		blkno += DL_GETPOFFSET(p);
		nblks = howmany(bp->b_bcount, cd->sc_dk.dk_label->d_secsize);

		/*
		 *  Fill out the scsi command.  If the transfer will
		 *  fit in a "small" cdb, use it.
		 */
		if (!(sc_link->flags & SDEV_ATAPI) &&
		    !(sc_link->quirks & SDEV_ONLYBIG) && 
		    ((blkno & 0x1fffff) == blkno) &&
		    ((nblks & 0xff) == nblks)) {
			/*
			 * We can fit in a small cdb.
			 */
			bzero(&cmd_small, sizeof(cmd_small));
			cmd_small.opcode = (bp->b_flags & B_READ) ?
			    READ_COMMAND : WRITE_COMMAND;
			_lto3b(blkno, cmd_small.addr);
			cmd_small.length = nblks & 0xff;
			cmdlen = sizeof(cmd_small);
			cmdp = (struct scsi_generic *)&cmd_small;
		} else {
			/*
			 * Need a large cdb.
			 */
			bzero(&cmd_big, sizeof(cmd_big));
			cmd_big.opcode = (bp->b_flags & B_READ) ?
			    READ_BIG : WRITE_BIG;
			_lto4b(blkno, cmd_big.addr);
			_lto2b(nblks, cmd_big.length);
			cmdlen = sizeof(cmd_big);
			cmdp = (struct scsi_generic *)&cmd_big;
		}

		/* Instrumentation. */
		disk_busy(&cd->sc_dk);

		/*
		 * Call the routine that chats with the adapter.
		 * Note: we cannot sleep as we may be an interrupt
		 */
		error = scsi_scsi_cmd(sc_link, cmdp, cmdlen,
		    (u_char *) bp->b_data, bp->b_bcount, SCSI_RETRIES, 30000,
		    bp, SCSI_NOSLEEP | ((bp->b_flags & B_READ) ? SCSI_DATA_IN :
		    SCSI_DATA_OUT));
		switch (error) {
		case 0:
			timeout_del(&cd->sc_timeout);
			break;
		case EAGAIN:
			/*
			 * The device can't start another i/o. Try again later.
			 */
			dp->b_actf = bp;
			disk_unbusy(&cd->sc_dk, 0, 0);
			timeout_add(&cd->sc_timeout, 1);
			return;
		default:
			disk_unbusy(&cd->sc_dk, 0, 0);
			printf("%s: not queued, error %d\n",
			    cd->sc_dev.dv_xname, error);
			break;
		}
	}
}
コード例 #8
0
ファイル: disksubr.c プロジェクト: ajinkya93/OpenBSD
/*
 * 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)));
}
コード例 #9
0
/*
 * sdstart looks to see if there is a buf waiting for the device
 * and that the device is not already busy. If both are true,
 * It dequeues the buf and creates a scsi command to perform the
 * transfer in the buf. The transfer request will call scsi_done
 * on completion, which will in turn call this routine again
 * so that the next queued transfer is performed.
 * The bufs are queued by the strategy routine (sdstrategy)
 *
 * This routine is also called after other non-queued requests
 * have been made of the scsi driver, to ensure that the queue
 * continues to be drained.
 */
void
sdstart(struct scsi_xfer *xs)
{
	struct scsi_link *link = xs->sc_link;
	struct sd_softc *sc = link->device_softc;
	struct buf *bp;
	u_int64_t secno;
	int nsecs;
	int read;
	struct partition *p;

	if (sc->flags & SDF_DYING) {
		scsi_xs_put(xs);
		return;
	}
	if ((link->flags & SDEV_MEDIA_LOADED) == 0) {
		bufq_drain(&sc->sc_bufq);
		scsi_xs_put(xs);
		return;
	}

	bp = bufq_dequeue(&sc->sc_bufq);
	if (bp == NULL) {
		scsi_xs_put(xs);
		return;
	}

	secno = DL_BLKTOSEC(sc->sc_dk.dk_label, bp->b_blkno);

	p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
	secno += DL_GETPOFFSET(p);
	nsecs = howmany(bp->b_bcount, sc->sc_dk.dk_label->d_secsize);
	read = bp->b_flags & B_READ;

	/*
	 *  Fill out the scsi command.  If the transfer will
	 *  fit in a "small" cdb, use it.
	 */
	if (!(link->flags & SDEV_ATAPI) &&
	    !(link->quirks & SDEV_ONLYBIG) &&
	    ((secno & 0x1fffff) == secno) &&
	    ((nsecs & 0xff) == nsecs))
		sd_cmd_rw6(xs, read, secno, nsecs);
	else if (((secno & 0xffffffff) == secno) &&
	    ((nsecs & 0xffff) == nsecs))
		sd_cmd_rw10(xs, read, secno, nsecs);
	else if (((secno & 0xffffffff) == secno) &&
	    ((nsecs & 0xffffffff) == nsecs))
		sd_cmd_rw12(xs, read, secno, nsecs);
	else
		sd_cmd_rw16(xs, read, secno, nsecs);

	xs->flags |= (read ? SCSI_DATA_IN : SCSI_DATA_OUT);
	xs->timeout = 60000;
	xs->data = bp->b_data;
	xs->datalen = bp->b_bcount;

	xs->done = sd_buf_done;
	xs->cookie = bp;
	xs->bp = bp;

	/* Instrumentation. */
	disk_busy(&sc->sc_dk);

	/* Mark disk as dirty. */
	if (!read)
		sc->flags |= SDF_DIRTY;

	scsi_xs_exec(xs);

	/* move onto the next io */
	if (ISSET(sc->flags, SDF_WAITING))
		CLR(sc->flags, SDF_WAITING);
	else if (bufq_peek(&sc->sc_bufq))
		scsi_xsh_add(&sc->sc_xsh);
}
コード例 #10
0
void
bootstrap(int devfd, char *dev, char *bootfile)
{
	struct disklabel dl;
	struct disklabel *lp;
	struct partition *pp;
	char *boot, *p, part;
	size_t bootsize;
	size_t bootsec;
	struct stat sb;
	int fd, i;

	/*
	 * Install bootstrap code onto the given disk, preserving the
	 * existing disklabel.
	 */

	/* Read disklabel from disk. */
	if (ioctl(devfd, DIOCGDINFO, &dl) == -1)
		err(1, "disklabel");
	if (dl.d_secsize == 0) {
		warnx("disklabel has sector size of 0, assuming %d", DEV_BSIZE);
		dl.d_secsize = DEV_BSIZE;
	}

	/* Read bootstrap file. */
	if (verbose)
		fprintf(stderr, "reading bootstrap from %s\n", bootfile);
	fd = open(bootfile, O_RDONLY);
	if (fd < 0)
		err(1, "open %s", bootfile);
	if (fstat(fd, &sb) != 0)
		err(1, "fstat %s", bootfile);
	bootsec = howmany((ssize_t)sb.st_size, dl.d_secsize);
	bootsize = bootsec * dl.d_secsize;
	if (verbose)
		fprintf(stderr, "bootstrap is %zu bytes "
		    "(%zu sectors @ %u bytes = %zu bytes)\n",
		    (ssize_t)sb.st_size, bootsec, dl.d_secsize, bootsize);
	boot = calloc(1, bootsize);
	if (boot == NULL)
		err(1, "calloc");
	if (read(fd, boot, bootsize) != (ssize_t)sb.st_size)
		err(1, "read");
	close(fd);

	/*
	 * Check that the bootstrap will fit - partitions must not overlap,
	 * or if they do, the partition type must be either FS_BOOT or
	 * FS_UNUSED. The 'c' partition will always overlap and is ignored.
	 */
	if (verbose)
		fprintf(stderr, "ensuring used partitions do not overlap "
		    "with bootstrap sectors 0-%zu\n", bootsec);
	for (i = 0; i < dl.d_npartitions; i++) {
		part = 'a' + i;
		pp = &dl.d_partitions[i];
		if (i == RAW_PART)
			continue;
		if (DL_GETPSIZE(pp) == 0)
			continue;
		if ((u_int64_t)bootsec <= DL_GETPOFFSET(pp))
			continue;
		switch (pp->p_fstype) {
		case FS_BOOT:
			break;
		case FS_UNUSED:
			warnx("bootstrap overlaps with unused partition %c",
			    part);
			break;
		default:
			errx(1, "bootstrap overlaps with partition %c", part);
		}
	}

	/* Make sure the bootstrap has left space for the disklabel. */
        lp = (struct disklabel *)(boot + (LABELSECTOR * dl.d_secsize) +
	    LABELOFFSET);
	for (i = 0, p = (char *)lp; i < (int)sizeof(*lp); i++)
		if (p[i] != 0)
			errx(1, "bootstrap has data in disklabel area");

	/* Patch the disklabel into the bootstrap code. */
	memcpy(lp, &dl, sizeof(dl));

	/* Write the bootstrap out to the disk. */
	if (lseek(devfd, 0, SEEK_SET) != 0)
		err(1, "lseek");
	if (verbose)
		fprintf(stderr, "%s bootstrap to disk\n",
		    (nowrite ? "would write" : "writing"));
	if (nowrite)
		return;
	if (write(devfd, boot, bootsize) != (ssize_t)bootsize)
		err(1, "write");
}
コード例 #11
0
ファイル: wd.c プロジェクト: DavidAlphaFox/openbsd-kernel
/*
 * Dump core after a system crash.
 */
int
wddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
{
	struct wd_softc *wd;	/* disk unit to do the I/O */
	struct disklabel *lp;   /* disk's disklabel */
	int unit, part;
	int nblks;	/* total number of sectors left to write */
	int nwrt;	/* sectors to write with current i/o. */
	int err;
	char errbuf[256];

	/* Check if recursive dump; if so, punt. */
	if (wddoingadump)
		return EFAULT;
	wddoingadump = 1;

	unit = DISKUNIT(dev);
	wd = wdlookup(unit);
	if (wd == NULL)
		return ENXIO;

	part = DISKPART(dev);

	/* Make sure it was initialized. */
	if (wd->drvp->state < READY)
		return ENXIO;

	/* Convert to disk sectors.  Request must be a multiple of size. */
	lp = wd->sc_dk.dk_label;
	if ((size % lp->d_secsize) != 0)
		return EFAULT;
	nblks = size / lp->d_secsize;
	blkno = blkno / (lp->d_secsize / DEV_BSIZE);

	/* Check transfer bounds against partition size. */
	if ((blkno < 0) || ((blkno + nblks) > DL_GETPSIZE(&lp->d_partitions[part])))
		return EINVAL;

	/* Offset block number to start of partition. */
	blkno += DL_GETPOFFSET(&lp->d_partitions[part]);

	/* Recalibrate, if first dump transfer. */
	if (wddumprecalibrated == 0) {
		wddumpmulti = wd->sc_multi;
		wddumprecalibrated = 1;
		wd->drvp->state = RECAL;
	}

	while (nblks > 0) {
		nwrt = min(nblks, wddumpmulti);
		wd->sc_wdc_bio.blkno = blkno;
		wd->sc_wdc_bio.flags = ATA_POLL;
		if (wd->sc_flags & WDF_LBA48)
			wd->sc_wdc_bio.flags |= ATA_LBA48;
		if (wd->sc_flags & WDF_LBA)
			wd->sc_wdc_bio.flags |= ATA_LBA;
		wd->sc_wdc_bio.bcount = nwrt * lp->d_secsize;
		wd->sc_wdc_bio.databuf = va;
		wd->sc_wdc_bio.wd = wd;
#ifndef WD_DUMP_NOT_TRUSTED
		switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) {
		case WDC_TRY_AGAIN:
			panic("wddump: try again");
			break;
		case WDC_QUEUED:
			panic("wddump: polled command has been queued");
			break;
		case WDC_COMPLETE:
			break;
		}
		switch(wd->sc_wdc_bio.error) {
		case TIMEOUT:
			printf("wddump: device timed out");
			err = EIO;
			break;
		case ERR_DF:
			printf("wddump: drive fault");
			err = EIO;
			break;
		case ERR_DMA:
			printf("wddump: DMA error");
			err = EIO;
			break;
		case ERROR:
			errbuf[0] = '\0';
			ata_perror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf,
			    sizeof errbuf);
			printf("wddump: %s", errbuf);
			err = EIO;
			break;
		case NOERROR:
			err = 0;
			break;
		default:
			panic("wddump: unknown error type");
		}
		if (err != 0) {
			printf("\n");
			return err;
		}
#else	/* WD_DUMP_NOT_TRUSTED */
		/* Let's just talk about this first... */
		printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
		    unit, va, cylin, head, sector);
		delay(500 * 1000);	/* half a second */
#endif

		/* update block count */
		nblks -= nwrt;
		blkno += nwrt;
		va += nwrt * lp->d_secsize;
	}

	wddoingadump = 0;
	return 0;
}
コード例 #12
0
ファイル: installboot.c プロジェクト: appleorange1/bitrig
/*
 * Read information about /boot's inode, then put this and filesystem
 * parameters from the superblock into pbr_symbols.
 */
static int
getbootparams(char *boot, int devfd, struct disklabel *dl)
{
	int		fd;
	struct stat	statbuf, sb;
	struct statfs	statfsbuf;
	struct partition *pp;
	struct fs	*fs;
	char		*buf;
	u_int		blk, *ap;
	struct ufs1_dinode	*ip1;
	struct ufs2_dinode	*ip2;
	int		ndb;
	int		mib[3];
	size_t		size;
	dev_t		dev;
	int		skew;

	/*
	 * Open 2nd-level boot program and record enough details about
	 * where it is on the filesystem represented by `devfd'
	 * (inode block, offset within that block, and various filesystem
	 * parameters essentially taken from the superblock) for biosboot
	 * to be able to load it later.
	 */

	/* Make sure the (probably new) boot file is on disk. */
	sync(); sleep(1);

	if ((fd = open(boot, O_RDONLY)) < 0)
		err(1, "open: %s", boot);

	if (fstatfs(fd, &statfsbuf) != 0)
		err(1, "statfs: %s", boot);

	if (strncmp(statfsbuf.f_fstypename, "ffs", MFSNAMELEN) &&
	    strncmp(statfsbuf.f_fstypename, "ufs", MFSNAMELEN) )
		errx(1, "%s: not on an FFS filesystem", boot);

#if 0
	if (read(fd, &eh, sizeof(eh)) != sizeof(eh))
		errx(1, "read: %s", boot);

	if (!IS_ELF(eh)) {
		errx(1, "%s: bad magic: 0x%02x%02x%02x%02x",
		    boot,
		    eh.e_ident[EI_MAG0], eh.e_ident[EI_MAG1],
		    eh.e_ident[EI_MAG2], eh.e_ident[EI_MAG3]);
	}
#endif

	if (fsync(fd) != 0)
		err(1, "fsync: %s", boot);

	if (fstat(fd, &statbuf) != 0)
		err(1, "fstat: %s", boot);

	if (fstat(devfd, &sb) != 0)
		err(1, "fstat: %s", realdev);

	/* Check devices. */
	mib[0] = CTL_MACHDEP;
	mib[1] = CPU_CHR2BLK;
	mib[2] = sb.st_rdev;
	size = sizeof(dev);
	if (sysctl(mib, 3, &dev, &size, NULL, 0) >= 0) {
		if (statbuf.st_dev / MAXPARTITIONS != dev / MAXPARTITIONS)
			errx(1, "cross-device install");
	}

	pp = &dl->d_partitions[DISKPART(statbuf.st_dev)];
	close(fd);

	sbread(devfd, DL_SECTOBLK(dl, DL_GETPOFFSET(pp)), &fs);

	/* Read inode. */
	if ((buf = malloc(fs->fs_bsize)) == NULL)
		err(1, NULL);

	blk = fsbtodb(fs, ino_to_fsba(fs, statbuf.st_ino));

	/*
	 * Have the inode.  Figure out how many filesystem blocks (not disk
	 * sectors) there are for biosboot to load.
	 */
	devread(devfd, buf, DL_SECTOBLK(dl, pp->p_offset) + blk,
	    fs->fs_bsize, "inode");
	if (fs->fs_magic == FS_UFS2_MAGIC) {
		ip2 = (struct ufs2_dinode *)(buf) +
		    ino_to_fsbo(fs, statbuf.st_ino);
		ndb = howmany(ip2->di_size, fs->fs_bsize);
		ap = (u_int *)ip2->di_db;
		skew = sizeof(u_int32_t);
	} else {
		ip1 = (struct ufs1_dinode *)(buf) +
		    ino_to_fsbo(fs, statbuf.st_ino);
		ndb = howmany(ip1->di_size, fs->fs_bsize);
		ap = (u_int *)ip1->di_db;
		skew = 0;
	}
	if (ndb <= 0)
		errx(1, "No blocks to load");

	/*
	 * Now set the values that will need to go into biosboot
	 * (the partition boot record, a.k.a. the PBR).
	 */
	sym_set_value(pbr_symbols, "_fs_bsize_p", (fs->fs_bsize / 16));
	sym_set_value(pbr_symbols, "_fs_bsize_s", (fs->fs_bsize / 
	    dl->d_secsize));

	/*
	 * fs_fsbtodb is the shift to convert fs_fsize to DEV_BSIZE. The
	 * ino_to_fsba() return value is the number of fs_fsize units.
	 * Calculate the shift to convert fs_fsize into physical sectors,
	 * which are added to p_offset to get the sector address BIOS
	 * will use.
	 *
	 * N.B.: ASSUMES fs_fsize is a power of 2 of d_secsize.
	 */
	sym_set_value(pbr_symbols, "_fsbtodb",
	    ffs(fs->fs_fsize / dl->d_secsize) - 1);

	if (pp->p_offseth != 0)
		errx(1, "partition offset too high");
	sym_set_value(pbr_symbols, "_p_offset", pp->p_offset);
	sym_set_value(pbr_symbols, "_inodeblk",
	    ino_to_fsba(fs, statbuf.st_ino));
	sym_set_value(pbr_symbols, "_inodedbl",
	    ((((char *)ap) - buf) + INODEOFF));
	sym_set_value(pbr_symbols, "_nblocks", ndb);
	sym_set_value(pbr_symbols, "_blkskew", skew);

	if (verbose) {
		fprintf(stderr, "%s is %d blocks x %d bytes\n",
		    boot, ndb, fs->fs_bsize);
		fprintf(stderr, "fs block shift %u; part offset %llu; "
		    "inode block %lld, offset %u\n",
		    ffs(fs->fs_fsize / dl->d_secsize) - 1,
		    DL_GETPOFFSET(pp), ino_to_fsba(fs, statbuf.st_ino),
		    (unsigned int)((((char *)ap) - buf) + INODEOFF));
		fprintf(stderr, "expecting %d-bit fs blocks (skew %d)\n",
		    skew ? 64 : 32, skew);
	}

	return 0;
}
コード例 #13
0
ファイル: sd.c プロジェクト: 7shi/openbsd-loongson-vc
/*
 * sdstart looks to see if there is a buf waiting for the device
 * and that the device is not already busy. If both are true,
 * It dequeues the buf and creates a scsi command to perform the
 * transfer in the buf. The transfer request will call scsi_done
 * on completion, which will in turn call this routine again
 * so that the next queued transfer is performed.
 * The bufs are queued by the strategy routine (sdstrategy)
 *
 * This routine is also called after other non-queued requests
 * have been made of the scsi driver, to ensure that the queue
 * continues to be drained.
 */
void
sdstart(void *v)
{
    struct sd_softc *sc = (struct sd_softc *)v;
    struct scsi_link *link = sc->sc_link;
    struct scsi_xfer *xs;
    struct buf *bp;
    daddr64_t blkno;
    int nblks;
    int read;
    struct partition *p;
    int s;

    if (sc->flags & SDF_DYING)
        return;

    SC_DEBUG(link, SDEV_DB2, ("sdstart\n"));

    mtx_enter(&sc->sc_start_mtx);
    if (ISSET(sc->flags, SDF_STARTING)) {
        mtx_leave(&sc->sc_start_mtx);
        return;
    }

    SET(sc->flags, SDF_STARTING);
    mtx_leave(&sc->sc_start_mtx);

    CLR(sc->flags, SDF_WAITING);
    while (!ISSET(sc->flags, SDF_WAITING) &&
            (bp = sd_buf_dequeue(sc)) != NULL) {
        /*
         * If the device has become invalid, abort all the
         * reads and writes until all files have been closed and
         * re-opened
         */
        if ((link->flags & SDEV_MEDIA_LOADED) == 0) {
            bp->b_error = EIO;
            bp->b_flags |= B_ERROR;
            bp->b_resid = bp->b_bcount;
            s = splbio();
            biodone(bp);
            splx(s);
            continue;
        }

        xs = scsi_xs_get(link, SCSI_NOSLEEP);
        if (xs == NULL) {
            sd_buf_requeue(sc, bp);
            break;
        }

        blkno =
            bp->b_blkno / (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE);
        p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
        blkno += DL_GETPOFFSET(p);
        nblks = howmany(bp->b_bcount, sc->sc_dk.dk_label->d_secsize);
        read = bp->b_flags & B_READ;

        /*
         *  Fill out the scsi command.  If the transfer will
         *  fit in a "small" cdb, use it.
         */
        if (!(link->flags & SDEV_ATAPI) &&
                !(link->quirks & SDEV_ONLYBIG) &&
                ((blkno & 0x1fffff) == blkno) &&
                ((nblks & 0xff) == nblks))
            sd_cmd_rw6(xs, read, blkno, nblks);
        else if (((blkno & 0xffffffff) == blkno) &&
                 ((nblks & 0xffff) == nblks))
            sd_cmd_rw10(xs, read, blkno, nblks);
        else if (((blkno & 0xffffffff) == blkno) &&
                 ((nblks & 0xffffffff) == nblks))
            sd_cmd_rw12(xs, read, blkno, nblks);
        else
            sd_cmd_rw16(xs, read, blkno, nblks);

        xs->flags |= (read ? SCSI_DATA_IN : SCSI_DATA_OUT);
        xs->timeout = 60000;
        xs->data = bp->b_data;
        xs->datalen = bp->b_bcount;

        xs->done = sd_buf_done;
        xs->cookie = bp;

        /* Instrumentation. */
        disk_busy(&sc->sc_dk);

        /* Mark disk as dirty. */
        if ((bp->b_flags & B_READ) == 0)
            sc->flags |= SDF_DIRTY;

        scsi_xs_exec(xs);
    }

    mtx_enter(&sc->sc_start_mtx);
    CLR(sc->flags, SDF_STARTING);
    mtx_leave(&sc->sc_start_mtx);
}
コード例 #14
0
ファイル: vnd.c プロジェクト: orumin/openbsd-efivars
void
vndstrategy(struct buf *bp)
{
	int unit = DISKUNIT(bp->b_dev);
	struct vnd_softc *sc;
	struct partition *p;
	off_t off;
	long origbcount;
	int s;

	DNPRINTF(VDB_FOLLOW, "vndstrategy(%p): unit %d\n", bp, unit);

	if (unit >= numvnd) {
		bp->b_error = ENXIO;
		goto bad;
	}
	sc = &vnd_softc[unit];

	if ((sc->sc_flags & VNF_HAVELABEL) == 0) {
		bp->b_error = ENXIO;
		goto bad;
	}

	/*
	 * Many of the distrib scripts assume they can issue arbitrary
	 * sized requests to raw vnd devices irrespective of the
	 * emulated disk geometry.
	 *
	 * To continue supporting this, round the block count up to a
	 * multiple of d_secsize for bounds_check_with_label(), and
	 * then restore afterwards.
	 *
	 * We only do this for non-encrypted vnd, because encryption
	 * requires operating on blocks at a time.
	 */
	origbcount = bp->b_bcount;
	if (sc->sc_keyctx == NULL) {
		u_int32_t secsize = sc->sc_dk.dk_label->d_secsize;
		bp->b_bcount = ((origbcount + secsize - 1) & ~(secsize - 1));
#ifdef DIAGNOSTIC
		if (bp->b_bcount != origbcount) {
			struct proc *pr = curproc;
			printf("%s: sloppy %s from proc %d (%s): "
			    "blkno %lld bcount %ld\n", sc->sc_dev.dv_xname,
			    (bp->b_flags & B_READ) ? "read" : "write",
			    pr->p_pid, pr->p_comm, (long long)bp->b_blkno,
			    origbcount);
		}
#endif
	}

	if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1) {
		bp->b_resid = bp->b_bcount = origbcount;
		goto done;
	}

	if (origbcount < bp->b_bcount)
		bp->b_bcount = origbcount;

	p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
	off = DL_GETPOFFSET(p) * sc->sc_dk.dk_label->d_secsize +
	    (u_int64_t)bp->b_blkno * DEV_BSIZE;

	if (sc->sc_keyctx && !(bp->b_flags & B_READ))
		vndencryptbuf(sc, bp, 1);

	/*
	 * Use IO_NOLIMIT because upper layer has already checked I/O
	 * for limits, so there is no need to do it again.
	 */
	bp->b_error = vn_rdwr((bp->b_flags & B_READ) ? UIO_READ : UIO_WRITE,
	    sc->sc_vp, bp->b_data, bp->b_bcount, off, UIO_SYSSPACE, IO_NOLIMIT,
	    sc->sc_cred, &bp->b_resid, curproc);
	if (bp->b_error)
		bp->b_flags |= B_ERROR;

	/* Data in buffer cache needs to be in clear */
	if (sc->sc_keyctx)
		vndencryptbuf(sc, bp, 0);

	goto done;

 bad:
	bp->b_flags |= B_ERROR;
	bp->b_resid = bp->b_bcount;
 done:
	s = splbio();
	biodone(bp);
	splx(s);
}
コード例 #15
0
void
makedisktab(FILE *f, struct disklabel *lp)
{
	int i;
	struct partition *pp;

	if (lp->d_packname[0])
		(void)fprintf(f, "%.*s|", (int)sizeof(lp->d_packname),
		    lp->d_packname);
	if (lp->d_typename[0])
		(void)fprintf(f, "%.*s|", (int)sizeof(lp->d_typename),
		    lp->d_typename);
	(void)fputs("Automatically generated label:\\\n\t:dt=", f);
	if (lp->d_type < DKMAXTYPES)
		(void)fprintf(f, "%s:", dktypenames[lp->d_type]);
	else
		(void)fprintf(f, "unknown%d:", lp->d_type);

	(void)fprintf(f, "se#%u:", lp->d_secsize);
	(void)fprintf(f, "ns#%u:", lp->d_nsectors);
	(void)fprintf(f, "nt#%u:", lp->d_ntracks);
	(void)fprintf(f, "nc#%u:", lp->d_ncylinders);
	(void)fprintf(f, "sc#%u:", lp->d_secpercyl);
	(void)fprintf(f, "su#%llu:", DL_GETDSIZE(lp));

	/*
	 * XXX We do not print have disktab information yet for
	 * XXX DL_GETBSTART DL_GETBEND
	 */
	for (i = 0; i < NDDATA; i++)
		if (lp->d_drivedata[i])
			(void)fprintf(f, "d%d#%u", i, lp->d_drivedata[i]);
	pp = lp->d_partitions;
	for (i = 0; i < lp->d_npartitions; i++, pp++) {
		if (DL_GETPSIZE(pp)) {
			char c = 'a' + i;

			(void)fprintf(f, "\\\n\t:");
			(void)fprintf(f, "p%c#%llu:", c, DL_GETPSIZE(pp));
			(void)fprintf(f, "o%c#%llu:", c, DL_GETPOFFSET(pp));
			if (pp->p_fstype != FS_UNUSED) {
				if (pp->p_fstype < FSMAXTYPES)
					(void)fprintf(f, "t%c=%s:", c,
					    fstypenames[pp->p_fstype]);
				else
					(void)fprintf(f, "t%c=unknown%d:",
					    c, pp->p_fstype);
			}
			switch (pp->p_fstype) {

			case FS_UNUSED:
				break;

			case FS_BSDFFS:
				(void)fprintf(f, "b%c#%u:", c,
				    DISKLABELV1_FFS_BSIZE(pp->p_fragblock));
				(void)fprintf(f, "f%c#%u:", c,
				    DISKLABELV1_FFS_FSIZE(pp->p_fragblock));
				break;

			default:
				break;
			}
		}
	}
	(void)fputc('\n', f);
	(void)fflush(f);
}
コード例 #16
0
/*
 * dump all of physical memory into the partition specified, starting
 * at offset 'dumplo' into the partition.
 */
int
sddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
{
	struct sd_softc *sc;	/* disk unit to do the I/O */
	struct disklabel *lp;	/* disk's disklabel */
	int	unit, part;
	u_int32_t sectorsize;	/* size of a disk sector */
	u_int64_t nsects;	/* number of sectors in partition */
	u_int64_t sectoff;	/* sector offset of partition */
	u_int64_t totwrt;	/* total number of sectors left to write */
	u_int32_t nwrt;		/* current number of sectors to write */
	struct scsi_xfer *xs;	/* ... convenience */
	int rv;

	/* Check if recursive dump; if so, punt. */
	if (sddoingadump)
		return EFAULT;
	if (blkno < 0)
		return EINVAL;

	/* Mark as active early. */
	sddoingadump = 1;

	unit = DISKUNIT(dev);	/* Decompose unit & partition. */
	part = DISKPART(dev);

	/* Check for acceptable drive number. */
	if (unit >= sd_cd.cd_ndevs || (sc = sd_cd.cd_devs[unit]) == NULL)
		return ENXIO;

	/*
	 * XXX Can't do this check, since the media might have been
	 * XXX marked `invalid' by successful unmounting of all
	 * XXX filesystems.
	 */
#if 0
	/* Make sure it was initialized. */
	if ((sc->sc_link->flags & SDEV_MEDIA_LOADED) != SDEV_MEDIA_LOADED)
		return ENXIO;
#endif

	/* Convert to disk sectors.  Request must be a multiple of size. */
	lp = sc->sc_dk.dk_label;
	sectorsize = lp->d_secsize;
	if ((size % sectorsize) != 0)
		return EFAULT;
	if ((blkno % DL_BLKSPERSEC(lp)) != 0)
		return EFAULT;
	totwrt = size / sectorsize;
	blkno = DL_BLKTOSEC(lp, blkno);

	nsects = DL_GETPSIZE(&lp->d_partitions[part]);
	sectoff = DL_GETPOFFSET(&lp->d_partitions[part]);

	/* Check transfer bounds against partition size. */
	if ((blkno + totwrt) > nsects)
		return EINVAL;

	/* Offset block number to start of partition. */
	blkno += sectoff;

	while (totwrt > 0) {
		if (totwrt > UINT32_MAX)
			nwrt = UINT32_MAX;
		else
			nwrt = totwrt;

#ifndef	SD_DUMP_NOT_TRUSTED
		xs = scsi_xs_get(sc->sc_link, SCSI_NOSLEEP);
		if (xs == NULL)
			return (ENOMEM);

		xs->timeout = 10000;
		xs->flags |= SCSI_DATA_OUT;
		xs->data = va;
		xs->datalen = nwrt * sectorsize;

		sd_cmd_rw10(xs, 0, blkno, nwrt); /* XXX */

		rv = scsi_xs_sync(xs);
		scsi_xs_put(xs);
		if (rv != 0)
			return (ENXIO);
#else	/* SD_DUMP_NOT_TRUSTED */
		/* Let's just talk about this first... */
		printf("sd%d: dump addr 0x%x, blk %lld\n", unit, va,
		    (long long)blkno);
		delay(500 * 1000);	/* half a second */
#endif	/* SD_DUMP_NOT_TRUSTED */

		/* update block count */
		totwrt -= nwrt;
		blkno += nwrt;
		va += sectorsize * nwrt;
	}

	sddoingadump = 0;

	return (0);
}
コード例 #17
0
int
main(int argc, char *argv[])
{
	int	c, devfd;
	char	*protostore;
	long	protosize;
	struct stat disksb, bootsb;
	struct disklabel dl;
	daddr64_t partoffset;
#define BBPAD   0x1e0
	struct bb {
		char	bb_pad[BBPAD];	/* disklabel lives in here, actually */
		long	bb_secsize;	/* size of secondary boot block */
		long	bb_secstart;	/* start of secondary boot block */
		long	bb_flags;	/* unknown; always zero */
		long	bb_cksum;	/* checksum of the boot block, as longs. */
	} bb;
	long *lp, *ep;

	while ((c = getopt(argc, argv, "vns:e:")) != -1) {
		switch (c) {
		case 'n':
			/* Do not actually write the bootblock to disk */
			nowrite = 1;
			break;
		case 'v':
			/* Chat */
			verbose = 1;
			break;
		case 's':
			isofsblk = atoi(optarg);
			break;
		case 'e':
			isofseblk = atoi(optarg);
			break;
		default:
			usage();
		}
	}

	if (argc - optind < 3)
		usage();

	boot = argv[optind];
	proto = argv[optind + 1];
	dev = argv[optind + 2];

	if (verbose) {
		(void)printf("boot: %s\n", boot);
		(void)printf("proto: %s\n", proto);
		(void)printf("device: %s\n", dev);
	}

	/* Load proto blocks into core */
	if ((protostore = loadprotoblocks(proto, &protosize)) == NULL)
		exit(1);

	/* Open and check raw disk device */
	if ((devfd = opendev(dev, O_RDONLY, OPENDEV_PART, &dev)) < 0)
		err(1, "open: %s", dev);
	if (fstat(devfd, &disksb) == -1)
		err(1, "fstat: %s", dev);
	if (!S_ISCHR(disksb.st_mode))
		errx(1, "%s must be a character device node", dev);
	if ((minor(disksb.st_rdev) % getmaxpartitions()) != getrawpartition())
		errx(1, "%s must be the raw partition", dev);

	/* Extract and load block numbers */
	if (stat(boot, &bootsb) == -1)
		err(1, "stat: %s", boot);
	if (!S_ISREG(bootsb.st_mode))
		errx(1, "%s must be a regular file", boot);
	if ((minor(disksb.st_rdev) / getmaxpartitions()) !=
	    (minor(bootsb.st_dev) / getmaxpartitions()))
		errx(1, "%s must be somewhere on %s", boot, dev);

	/*
	 * Find the offset of the secondary boot block's partition
	 * into the disk.  If disklabels not supported, assume zero.
	 */
	if (ioctl(devfd, DIOCGDINFO, &dl) != -1) {
		partoffset = DL_GETPOFFSET(&dl.d_partitions[minor(bootsb.st_dev) %
		    getmaxpartitions()]);
	} else {
		if (errno != ENOTTY)
			err(1, "read disklabel: %s", dev);
		warnx("couldn't read label from %s, using part offset of 0",
		    dev);
		partoffset = 0;
	}
	if (verbose)
		(void)printf("%s partition offset = 0x%lx\n", boot, partoffset);

	/* Sync filesystems (make sure boot's block numbers are stable) */
	sync();
	sleep(2);
	sync();
	sleep(2);

	if (loadblocknums(boot, devfd, partoffset) != 0)
		exit(1);

	(void)close(devfd);

	if (nowrite)
		return 0;

#if 0
	/* Write patched proto bootblocks into the superblock */
	if (protosize > SBSIZE - DEV_BSIZE)
		errx(1, "proto bootblocks too big");
#endif

	if ((devfd = opendev(dev, O_RDWR, OPENDEV_PART, &dev)) < 0)
		err(1, "open: %s", dev);

	if (lseek(devfd, DEV_BSIZE, SEEK_SET) != DEV_BSIZE)
		err(1, "lseek bootstrap");

	if (write(devfd, protostore, protosize) != protosize)
		err(1, "write bootstrap");

	if (lseek(devfd, 0, SEEK_SET) != 0)
		err(1, "lseek label");

	if (read(devfd, &bb, sizeof (bb)) != sizeof (bb))
		err(1, "read label");

	bb.bb_secsize = 15;
	bb.bb_secstart = 1;
	bb.bb_flags = 0;
	bb.bb_cksum = 0;

	for (lp = (long *)&bb, ep = &bb.bb_cksum; lp < ep; lp++)
		bb.bb_cksum += *lp;

	if (lseek(devfd, 0, SEEK_SET) != 0)
		err(1, "lseek label 2");

	if (write(devfd, &bb, sizeof bb) != sizeof bb)
		err(1, "write label ");

	(void)close(devfd);
	return 0;
}