示例#1
0
void
init_volhdr(void)
{
    memset(volhdr, 0, sizeof(struct sgilabel));
    volhdr->magic = htobe32(SGILABEL_MAGIC);
    volhdr->root = htobe16(0);
    volhdr->swap = htobe16(1);
    strlcpy(volhdr->bootfile, "/bsd", sizeof(volhdr->bootfile));
    volhdr->dp.dp_skew = 1; /* XXX */
    volhdr->dp.dp_gap1 = 1; /* XXX */
    volhdr->dp.dp_gap2 = 1; /* XXX */
    volhdr->dp.dp_cyls = htobe16(lbl.d_ncylinders);
    volhdr->dp.dp_shd0 = 0;
    volhdr->dp.dp_trks0 = htobe16(lbl.d_ntracks);
    volhdr->dp.dp_secs = htobe16(lbl.d_nsectors);
    volhdr->dp.dp_secbytes = htobe16(lbl.d_secsize);
    volhdr->dp.dp_interleave = 1;
    volhdr->dp.dp_nretries = htobe32(22);
    volhdr->partitions[10].blocks =
        htobe32(DL_SECTOBLK(&lbl, DL_GETDSIZE(&lbl)));
    volhdr->partitions[10].first = 0;
    volhdr->partitions[10].type = htobe32(SGI_PTYPE_VOLUME);
    volhdr->partitions[8].blocks = htobe32(DL_SECTOBLK(&lbl, volhdr_size));
    volhdr->partitions[8].first = 0;
    volhdr->partitions[8].type = htobe32(SGI_PTYPE_VOLHDR);
    volhdr->partitions[0].blocks =
        htobe32(DL_SECTOBLK(&lbl, DL_GETDSIZE(&lbl) - volhdr_size));
    volhdr->partitions[0].first = htobe32(DL_SECTOBLK(&lbl, volhdr_size));
    volhdr->partitions[0].type = htobe32(SGI_PTYPE_BSD);
    write_volhdr();
}
示例#2
0
daddr_t
wdsize(dev_t dev)
{
	struct wd_softc *wd;
	struct disklabel *lp;
	int part, omask;
	daddr_t size;

	WDCDEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS);

	wd = wdlookup(DISKUNIT(dev));
	if (wd == NULL)
		return (-1);

	part = DISKPART(dev);
	omask = wd->sc_dk.dk_openmask & (1 << part);

	if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0) {
		size = -1;
		goto exit;
	}

	lp = wd->sc_dk.dk_label;
	size = DL_SECTOBLK(lp, DL_GETPSIZE(&lp->d_partitions[part]));
	if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0)
		size = -1;

 exit:
	device_unref(&wd->sc_dev);
	return (size);
}
示例#3
0
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()");
	}
}
示例#4
0
daddr_t
sdsize(dev_t dev)
{
	struct disklabel *lp;
	struct sd_softc *sc;
	int part, omask;
	daddr_t size;

	sc = sdlookup(DISKUNIT(dev));
	if (sc == NULL)
		return -1;
	if (sc->flags & SDF_DYING) {
		size = -1;
		goto exit;
	}

	part = DISKPART(dev);
	omask = sc->sc_dk.dk_openmask & (1 << part);

	if (omask == 0 && sdopen(dev, 0, S_IFBLK, NULL) != 0) {
		size = -1;
		goto exit;
	}

	lp = sc->sc_dk.dk_label;
	if ((sc->sc_link->flags & SDEV_MEDIA_LOADED) == 0)
		size = -1;
	else if (lp->d_partitions[part].p_fstype != FS_SWAP)
		size = -1;
	else
		size = DL_SECTOBLK(lp, DL_GETPSIZE(&lp->d_partitions[part]));
	if (omask == 0 && sdclose(dev, 0, S_IFBLK, NULL) != 0)
		size = -1;

 exit:
	device_unref(&sc->sc_dev);
	return size;
}
示例#5
0
/*
 * 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;
}
示例#6
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);
}
示例#7
0
void
MBR_init(struct disk *disk, struct mbr *mbr)
{
	daddr_t i;
	u_int64_t adj;

	/* Fix up given mbr for this disk */
	mbr->part[0].flag = 0;
	mbr->part[1].flag = 0;
	mbr->part[2].flag = 0;

	mbr->part[3].flag = DOSACTIVE;
	mbr->signature = DOSMBR_SIGNATURE;

	/* Use whole disk. Reserve first track, or first cyl, if possible. */
	mbr->part[3].id = DOSPTYP_OPENBSD;
	if (disk->real->heads > 1)
		mbr->part[3].shead = 1;
	else
		mbr->part[3].shead = 0;
	if (disk->real->heads < 2 && disk->real->cylinders > 1)
		mbr->part[3].scyl = 1;
	else
		mbr->part[3].scyl = 0;
	mbr->part[3].ssect = 1;

	/* Go right to the end */
	mbr->part[3].ecyl = disk->real->cylinders - 1;
	mbr->part[3].ehead = disk->real->heads - 1;
	mbr->part[3].esect = disk->real->sectors;

	/* Fix up start/length fields */
	PRT_fix_BN(disk, &mbr->part[3], 3);

#if defined(__powerpc__) || defined(__mips__)
	/* Now fix up for the MS-DOS boot partition on PowerPC. */
	mbr->part[0].flag = DOSACTIVE;	/* Boot from dos part */
	mbr->part[3].flag = 0;
	mbr->part[3].ns += mbr->part[3].bs;
	mbr->part[3].bs = mbr->part[0].bs + mbr->part[0].ns;
	mbr->part[3].ns -= mbr->part[3].bs;
	PRT_fix_CHS(disk, &mbr->part[3]);
	if ((mbr->part[3].shead != 1) || (mbr->part[3].ssect != 1)) {
		/* align the partition on a cylinder boundary */
		mbr->part[3].shead = 0;
		mbr->part[3].ssect = 1;
		mbr->part[3].scyl += 1;
	}
	/* Fix up start/length fields */
	PRT_fix_BN(disk, &mbr->part[3], 3);
#endif

	/* Start OpenBSD MBR partition on a power of 2 block number. */
	i = 1;
	while (i < DL_SECTOBLK(&dl, mbr->part[3].bs))
		i *= 2;
	adj = DL_BLKTOSEC(&dl, i) - mbr->part[3].bs;
	mbr->part[3].bs += adj;
	mbr->part[3].ns -= adj; 
	PRT_fix_CHS(disk, &mbr->part[3]);
}