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(); }
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); }
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()"); } }
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; }
/* * 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; }
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); }
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]); }