void display(FILE *f, struct disklabel *lp, char unit, int all) { int i, j; double d; unit = canonical_unit(lp, unit); fprintf(f, "# %s:\n", specname); if (lp->d_type < DKMAXTYPES) fprintf(f, "type: %s\n", dktypenames[lp->d_type]); else fprintf(f, "type: %d\n", lp->d_type); fprintf(f, "disk: %.*s\n", (int)sizeof(lp->d_typename), lp->d_typename); fprintf(f, "label: %.*s\n", (int)sizeof(lp->d_packname), lp->d_packname); fprintf(f, "duid: %02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\n", lp->d_uid[0], lp->d_uid[1], lp->d_uid[2], lp->d_uid[3], lp->d_uid[4], lp->d_uid[5], lp->d_uid[6], lp->d_uid[7]); fprintf(f, "flags:"); if (lp->d_flags & D_BADSECT) fprintf(f, " badsect"); if (lp->d_flags & D_VENDOR) fprintf(f, " vendor"); putc('\n', f); fprintf(f, "bytes/sector: %u\n", lp->d_secsize); fprintf(f, "sectors/track: %u\n", lp->d_nsectors); fprintf(f, "tracks/cylinder: %u\n", lp->d_ntracks); fprintf(f, "sectors/cylinder: %u\n", lp->d_secpercyl); fprintf(f, "cylinders: %u\n", lp->d_ncylinders); fprintf(f, "total sectors: %llu", DL_GETDSIZE(lp)); d = scale(DL_GETDSIZE(lp), unit, lp); if (d > 0) fprintf(f, " # total bytes: %.*f%c", unit == 'B' ? 0 : 1, d, unit); fprintf(f, "\n"); fprintf(f, "boundstart: %llu\n", DL_GETBSTART(lp)); fprintf(f, "boundend: %llu\n", DL_GETBEND(lp)); fprintf(f, "drivedata: "); for (i = NDDATA - 1; i >= 0; i--) if (lp->d_drivedata[i]) break; if (i < 0) i = 0; for (j = 0; j <= i; j++) fprintf(f, "%d ", lp->d_drivedata[j]); fprintf(f, "\n"); if (all) { fprintf(f, "\n%hu partitions:\n", lp->d_npartitions); fprintf(f, "# %16.16s %16.16s fstype [fsize bsize cpg]\n", "size", "offset"); for (i = 0; i < lp->d_npartitions; i++) display_partition(f, lp, i, unit); } fflush(f); }
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(); }
/* * Attempt to read a disk label from a device * using the indicated strategy routine. * The label must be partly set up before this: * secpercyl, secsize and anything required for a block i/o read * operation in the driver's strategy/start routines * must be filled in before calling us. * * If dos partition table requested, attempt to load it and * find disklabel inside a DOS partition. * * We would like to check if each MBR has a valid DOSMBR_SIGNATURE, but * we cannot because it doesn't always exist. So.. we assume the * MBR is valid. */ int readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, int spoofonly) { bios_diskinfo_t *pdi; struct buf *bp = NULL; dev_t devno; int error; if ((error = initdisklabel(lp))) goto done; /* Look for any BIOS geometry information we should honour. */ devno = chrtoblk(dev); if (devno == NODEV) devno = dev; pdi = bios_getdiskinfo(MAKEBOOTDEV(major(devno), 0, 0, DISKUNIT(devno), RAW_PART)); if (pdi != NULL && pdi->bios_heads > 0 && pdi->bios_sectors > 0) { #ifdef DEBUG printf("Disk GEOM %u/%u/%u -> BIOS GEOM %u/%u/%u\n", lp->d_ntracks, lp->d_nsectors, lp->d_ncylinders, pdi->bios_heads, pdi->bios_sectors, DL_GETDSIZE(lp) / (pdi->bios_heads * pdi->bios_sectors)); #endif lp->d_ntracks = pdi->bios_heads; lp->d_nsectors = pdi->bios_sectors; lp->d_secpercyl = pdi->bios_sectors * pdi->bios_heads; lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl; } /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; error = readdoslabel(bp, strat, lp, NULL, spoofonly); if (error == 0) goto done; #if defined(CD9660) error = iso_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif #if defined(UDF) error = udf_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } disk_change = 1; return (error); }
void wdgetdefaultlabel(struct wd_softc *wd, struct disklabel *lp) { WDCDEBUG_PRINT(("wdgetdefaultlabel\n"), DEBUG_FUNCS); bzero(lp, sizeof(struct disklabel)); lp->d_secsize = DEV_BSIZE; DL_SETDSIZE(lp, wd->sc_capacity); lp->d_ntracks = wd->sc_params.atap_heads; lp->d_nsectors = wd->sc_params.atap_sectors; lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl; if (wd->drvp->ata_vers == -1) { lp->d_type = DTYPE_ST506; strncpy(lp->d_typename, "ST506/MFM/RLL", sizeof lp->d_typename); } else { lp->d_type = DTYPE_ESDI; strncpy(lp->d_typename, "ESDI/IDE disk", sizeof lp->d_typename); } /* XXX - user viscopy() like sd.c */ strncpy(lp->d_packname, wd->sc_params.atap_model, sizeof lp->d_packname); lp->d_flags = 0; lp->d_version = 1; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = dkcksum(lp); }
char canonical_unit(struct disklabel *lp, char unit) { struct partition *pp; u_int64_t small; int i; if (unit == '*') { small = DL_GETDSIZE(lp); pp = &lp->d_partitions[0]; for (i = 0; i < lp->d_npartitions; i++, pp++) if (DL_GETPSIZE(pp) > 0 && DL_GETPSIZE(pp) < small) small = DL_GETPSIZE(pp); if (small < DL_BLKTOSEC(lp, MEG(1))) unit = 'K'; else if (small < DL_BLKTOSEC(lp, MEG(1024))) unit = 'M'; else if (small < DL_BLKTOSEC(lp, GIG(1024))) unit = 'G'; else unit = 'T'; } unit = toupper((unsigned char)unit); return (unit); }
/* * Attempt to read a disk label from a device * using the indicated strategy routine. * The label must be partly set up before this: * secpercyl, secsize and anything required for a block i/o read * operation in the driver's strategy/start routines * must be filled in before calling us. */ int readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, int spoofonly) { struct buf *bp = NULL; int error; if ((error = initdisklabel(lp))) goto done; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; if (spoofonly) goto doslabel; 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)) { error = bp->b_error; goto done; } error = checkdisklabel(bp->b_data + LABELOFFSET, lp, 0, DL_GETDSIZE(lp)); if (error == 0) goto done; doslabel: error = readdoslabel(bp, strat, lp, NULL, spoofonly); if (error == 0) goto done; #if defined(CD9660) error = iso_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif #if defined(UDF) error = udf_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } disk_change = 1; return (error); }
int cputobsdlabel(struct disklabel *lp, struct mvmedisklabel *clp) { int i; if (clp->magic1 != DISKMAGIC || clp->magic2 != DISKMAGIC) return (EINVAL); /* no disk label */ lp->d_magic = clp->magic1; lp->d_type = clp->type; lp->d_subtype = clp->subtype; strncpy(lp->d_typename, clp->vid_vd, sizeof lp->d_typename); strncpy(lp->d_packname, clp->packname, sizeof lp->d_packname); lp->d_secsize = clp->cfg_psm; lp->d_nsectors = clp->cfg_spt; lp->d_ncylinders = clp->cfg_trk; /* trk is really num of cyl! */ lp->d_ntracks = clp->cfg_hds; lp->d_secpercyl = clp->secpercyl; if (DL_GETDSIZE(lp) == 0) DL_SETDSIZE(lp, clp->secperunit); lp->d_acylinders = clp->acylinders; lp->d_flags = clp->flags; for (i = 0; i < NDDATA; i++) lp->d_drivedata[i] = clp->drivedata[i]; for (i = 0; i < NSPARE; i++) lp->d_spare[i] = clp->spare[i]; lp->d_magic2 = clp->magic2; lp->d_npartitions = clp->partitions; lp->d_bbsize = clp->bbsize; lp->d_sbsize = clp->sbsize; bcopy(clp->vid_4, &lp->d_partitions[0], sizeof(struct partition) * 4); bcopy(clp->cfg_4, &lp->d_partitions[4], sizeof(struct partition) * 12); if (clp->version < 2) { struct __partitionv0 *v0pp = (struct __partitionv0 *)lp->d_partitions; struct partition *pp = lp->d_partitions; for (i = 0; i < lp->d_npartitions; i++, pp++, v0pp++) { pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(v0pp-> p_fsize, v0pp->p_frag); pp->p_offseth = 0; pp->p_sizeh = 0; } } lp->d_version = 1; lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); return (0); }
/* * Attempt to read a disk label from a device * using the indicated strategy routine. * The label must be partly set up before this: * secpercyl, secsize and anything required for a block i/o read * operation in the driver's strategy/start routines * must be filled in before calling us. */ int readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, int spoofonly) { struct sun_disklabel *slp; struct buf *bp = NULL; int error; if ((error = initdisklabel(lp))) goto done; lp->d_flags |= D_VENDOR; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; if (spoofonly) goto done; error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, LABELSECTOR)); if (error) goto done; slp = (struct sun_disklabel *)bp->b_data; if (slp->sl_magic == SUN_DKMAGIC) { error = disklabel_om_to_bsd(slp, lp); goto done; } error = checkdisklabel(bp->b_data + LABELOFFSET, lp, 0, DL_GETDSIZE(lp)); if (error == 0) goto done; #if defined(CD9660) error = iso_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif #if defined(UDF) error = udf_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } disk_change = 1; return (error); }
int allocate_space(int size) { int n, blocks; int first; blocks = howmany(size, DEV_BSIZE); first = roundup(2 * DEV_BSIZE, volhdr->dp.dp_secbytes) / DEV_BSIZE; for (n = 0; n < SGI_SIZE_VOLDIR;) { if (volhdr->voldir[n].name[0]) { if (first < (betoh32(volhdr->voldir[n].block) + howmany(betoh32(volhdr->voldir[n].bytes), DEV_BSIZE)) && (first + blocks) > betoh32(volhdr->voldir[n].block)) { first = roundup( betoh32(volhdr->voldir[n].block) + howmany(betoh32(volhdr->voldir[n].bytes), DEV_BSIZE), volhdr->dp.dp_secbytes / DEV_BSIZE); #if DEBUG printf("allocate: " "n=%d first=%d blocks=%d size=%d\n", n, first, blocks, size); printf("%s %d %d\n", volhdr->voldir[n].name, volhdr->voldir[n].block, volhdr->voldir[n].bytes); printf("first=%d block=%d last=%d end=%d\n", first, volhdr->voldir[n].block, first + blocks - 1, volhdr->voldir[n].block + howmany(volhdr->voldir[n].bytes, DEV_BSIZE)); #endif n = 0; continue; } } ++n; } if (first + blocks > DL_GETDSIZE(&lbl)) first = -1; /* XXX assumes volume header is partition 8 */ /* XXX assumes volume header starts at 0? */ if (first + blocks >= betoh32(volhdr->partitions[8].blocks)) first = -1; return (first); }
/* * 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"); }
void display_vol(void) { int32_t *l; int i; l = (int32_t *)buf; checksum = 0; for (i = 0; i < sizeof(struct sgilabel) / sizeof(int32_t); ++i) checksum += betoh32(l[i]); printf("disklabel shows %llu sectors with %u bytes per sector\n", DL_GETDSIZE(&lbl), lbl.d_secsize); printf("checksum: %08x%s\n", checksum, checksum == 0 ? "" : " *ERROR*"); printf("root part: %d\n", betoh32(volhdr->root)); printf("swap part: %d\n", betoh32(volhdr->swap)); printf("bootfile: %s\n", volhdr->bootfile); /* volhdr->devparams[0..47] */ printf("\nVolume header files:\n"); for (i = 0; i < SGI_SIZE_VOLDIR; ++i) { if (volhdr->voldir[i].name[0] != '\0') { printf("%-8s offset %4d blocks, " "length %8d bytes (%d blocks)\n", volhdr->voldir[i].name, betoh32(volhdr->voldir[i].block), betoh32(volhdr->voldir[i].bytes), howmany(betoh32(volhdr->voldir[i].bytes), DEV_BSIZE)); } } printf("\nSGI partitions:\n"); for (i = 0; i < MAXPARTITIONS; ++i) { if (betoh32(volhdr->partitions[i].blocks) != 0) { printf("%2d:%c blocks %8d first %8d type %2d (%s)\n", i, i + 'a', betoh32(volhdr->partitions[i].blocks), betoh32(volhdr->partitions[i].first), betoh32(volhdr->partitions[i].type), betoh32(volhdr->partitions[i].type) > (sizeof(sgi_types) / sizeof(sgi_types[0])) ? "???" : sgi_types[betoh32(volhdr->partitions[i].type)]); } } }
/* Routine to go after the disklabel for geometry * information. This should work everywhere, but * in the land of PC, things are not always what * they seem. */ DISK_metrics * DISK_getlabelmetrics(char *name) { DISK_metrics *lm = NULL; u_int64_t sz, spc; int fd; /* Get label metrics */ if ((fd = DISK_open(name, O_RDONLY)) != -1) { lm = malloc(sizeof(DISK_metrics)); if (lm == NULL) err(1, NULL); if (ioctl(fd, DIOCGPDINFO, &dl) == -1) { warn("DIOCGPDINFO"); free(lm); lm = NULL; } else { lm->cylinders = dl.d_ncylinders; lm->heads = dl.d_ntracks; lm->sectors = dl.d_nsectors; /* MBR handles only first UINT32_MAX sectors. */ spc = (u_int64_t)lm->heads * lm->sectors; sz = DL_GETDSIZE(&dl); if (sz > UINT32_MAX) { lm->cylinders = UINT32_MAX / spc; lm->size = lm->cylinders * spc; warnx("disk too large (%llu sectors)." " size truncated.", sz); } else lm->size = sz; unit_types[SECTORS].conversion = dl.d_secsize; } close(fd); } return (lm); }
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); }
/* * 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); }
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); }
/* * 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); }
/* * Attempt to read a disk label from a device * using the indicated strategy routine. * The label must be partly set up before this: * secpercyl, secsize and anything required for a block i/o read * operation in the driver's strategy/start routines * must be filled in before calling us. */ int readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, int spoofonly) { struct sun_disklabel *slp; struct buf *bp = NULL; int error; if ((error = initdisklabel(lp))) goto done; lp->d_flags |= D_VENDOR; /* * On sparc64 we check for a CD label first, because our * CD install media contains both sparc & sparc64 labels. * We want the sparc64 machine to find the "CD label", not * the SunOS label, for loading its kernel. */ #if NCD > 0 if (strat == cdstrategy) { #if defined(CD9660) if (iso_disklabelspoof(dev, strat, lp) == 0) goto done; #endif #if defined(UDF) if (udf_disklabelspoof(dev, strat, lp) == 0) goto done; #endif } #endif /* NCD > 0 */ /* get buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; if (spoofonly) goto doslabel; error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, LABELSECTOR)); if (error) goto done; slp = (struct sun_disklabel *)bp->b_data; if (slp->sl_magic == SUN_DKMAGIC) { error = disklabel_sun_to_bsd(slp, lp); goto done; } error = checkdisklabel(bp->b_data + LABELOFFSET, lp, 0, DL_GETDSIZE(lp)); if (error == 0) goto done; doslabel: error = readdoslabel(bp, strat, lp, NULL, spoofonly); if (error == 0) goto done; /* A CD9660/UDF label may be on a non-CD drive, so recheck */ #if defined(CD9660) error = iso_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif #if defined(UDF) error = udf_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } disk_change = 1; return (error); }
/* * 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))); }
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); }
void bsdtocpulabel(struct disklabel *lp, struct mvmedisklabel *clp) { char *tmot = "MOTOROLA", *id = "M68K", *mot; int i; u_short osa_u, osa_l, osl; u_int oss; /* preserve existing VID boot code information */ osa_u = clp->vid_osa_u; osa_l = clp->vid_osa_l; osl = clp->vid_osl; oss = clp->vid_oss; bzero(clp, sizeof(*clp)); clp->vid_osa_u = osa_u; clp->vid_osa_l = osa_l; clp->vid_osl = osl; clp->vid_oss = oss; clp->vid_cas = clp->vid_cal = 1; clp->magic1 = lp->d_magic; clp->type = lp->d_type; clp->subtype = lp->d_subtype; strncpy(clp->vid_vd, lp->d_typename, 16); strncpy(clp->packname, lp->d_packname, 16); clp->cfg_psm = lp->d_secsize; clp->cfg_spt = lp->d_nsectors; clp->cfg_trk = lp->d_ncylinders; /* trk is really num of cyl! */ clp->cfg_hds = lp->d_ntracks; clp->secpercyl = lp->d_secpercyl; clp->secperunit = DL_GETDSIZE(lp); clp->acylinders = lp->d_acylinders; clp->cfg_ilv = 1; clp->cfg_sof = 1; clp->cylskew = 1; clp->headswitch = 0; clp->cfg_ssr = 0; clp->flags = lp->d_flags; for (i = 0; i < NDDATA; i++) clp->drivedata[i] = lp->d_drivedata[i]; for (i = 0; i < NSPARE; i++) clp->spare[i] = lp->d_spare[i]; clp->magic2 = lp->d_magic2; clp->checksum = lp->d_checksum; clp->partitions = lp->d_npartitions; clp->bbsize = lp->d_bbsize; clp->sbsize = lp->d_sbsize; clp->checksum = lp->d_checksum; bcopy(&lp->d_partitions[0], clp->vid_4, sizeof(struct partition) * 4); bcopy(&lp->d_partitions[4], clp->cfg_4, sizeof(struct partition) * 12); clp->version = 2; /* Put "MOTOROLA" in the VID. This makes it a valid boot disk. */ for (mot = clp->vid_mot, i = 0; i < 8; i++) *mot++ = *tmot++; /* put volume id in the VID */ for (mot = clp->vid_id, i = 0; i < 4; i++) *mot++ = *id++; }
/* * Search for a VDIT volume information. If one is found, search for a * vdmpart instance of name "OpenBSD". If one is found, set the disklabel * bounds to the area it spans, and attempt to read a native label within * it. */ int readvditlabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, daddr_t *partoffp, int spoofonly, struct vdm_boot_info *vbi) { struct buf *sbp = NULL; struct vdit_block_header *vbh; struct vdit_entry_header *veh; char *vdit_storage = NULL, *vdit_end; size_t vdit_size; unsigned int largest_chunk, vdit_blkno; int expected_kind; daddr_t blkno; int error = 0; vdit_id_t *vdmpart_id; struct vdit_vdmpart_instance *bsd_vdmpart; /* * Figure out the size of the first VDIT. */ vdit_size = largest_chunk = 0; expected_kind = VDIT_BLOCK_HEAD_BE; blkno = VDIT_SECTOR; for (;;) { error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, blkno)); if (error) return (error); vbh = (struct vdit_block_header *)bp->b_data; if (VDM_ID_KIND(&vbh->id) != expected_kind || VDM_ID_BLKNO(&vbh->id) != vdit_size || vbh->id.node_number != VDM_NO_NODE_NUMBER) return EINVAL; if (vbi != NULL) { if ((blkno >= vbi->boot_start && blkno < vbi->boot_start + vbi->boot_size) || (blkno + vbh->chunksz - 1 >= vbi->boot_start && blkno + vbh->chunksz - 1 < vbi->boot_start + vbi->boot_size)) return EINVAL; } if (vbh->chunksz > largest_chunk) largest_chunk = vbh->chunksz; vdit_size += vbh->chunksz; if (vbh->nextblk == VDM_NO_BLK_NUMBER) break; blkno = vbh->nextblk; if (blkno >= DL_GETDSIZE(lp)) return EINVAL; expected_kind = VDIT_PORTION_HEADER_BLOCK; } /* * Now read the first VDIT. */ vdit_size *= dbtob(1) - sizeof(struct vdit_block_header); vdit_storage = malloc(vdit_size, M_DEVBUF, M_WAITOK); largest_chunk = dbtob(largest_chunk); sbp = geteblk(largest_chunk); sbp->b_dev = bp->b_dev; vdit_end = vdit_storage; expected_kind = VDIT_BLOCK_HEAD_BE; blkno = VDIT_SECTOR; vdit_blkno = 0; for (;;) { sbp->b_blkno = blkno; sbp->b_bcount = largest_chunk; CLR(sbp->b_flags, B_READ | B_WRITE | B_DONE); SET(sbp->b_flags, B_BUSY | B_READ | B_RAW); (*strat)(sbp); if ((error = biowait(sbp)) != 0) goto done; vbh = (struct vdit_block_header *)sbp->b_data; if (VDM_ID_KIND(&vbh->id) != expected_kind) { error = EINVAL; goto done; } vdit_end = extract_vdit_portion(vdit_end, sbp->b_data, vbh->chunksz, vdit_blkno, expected_kind); if (vdit_end == NULL) { error = EINVAL; goto done; } if (vbh->nextblk == VDM_NO_BLK_NUMBER) break; vdit_blkno += vbh->chunksz; blkno = vbh->nextblk; expected_kind = VDIT_PORTION_HEADER_BLOCK; } /* * Walk the VDIT entries. * * If we find an OpenBSD vdmpart, we'll set our disk area bounds to * its area, and will read a label from there. */ vdmpart_id = NULL; bsd_vdmpart = NULL; veh = (struct vdit_entry_header *)vdit_storage; while ((caddr_t)veh < vdit_end) { switch (veh->type) { case VDIT_ENTRY_SUBDRIVER_INFO: { struct vdit_subdriver_entry *vse; vse = (struct vdit_subdriver_entry *)(veh + 1); if (strcmp(vse->name, VDM_SUBDRIVER_VDMPART) == 0) vdmpart_id = &vse->subdriver_id; } break; case VDIT_ENTRY_INSTANCE: { struct vdit_instance_entry *vie; vie = (struct vdit_instance_entry *)(veh + 1); if (strcmp(vie->name, VDM_INSTANCE_OPENBSD) == 0) { if (vdmpart_id != NULL && memcmp(vdmpart_id, &vie->subdriver_id, sizeof(vdit_id_t)) == 0) { /* found it! */ if (bsd_vdmpart != NULL) { bsd_vdmpart = NULL; veh->type = VDIT_ENTRY_SENTINEL; } else bsd_vdmpart = (struct vdit_vdmpart_instance *)vie; } } } break; } if (veh->type == VDIT_ENTRY_SENTINEL) break; veh = (struct vdit_entry_header *)((char *)veh + veh->size); } if (bsd_vdmpart != NULL) { uint32_t start, size; memcpy(&start, &bsd_vdmpart->start_blkno, sizeof(uint32_t)); memcpy(&size, &bsd_vdmpart->size, sizeof(uint32_t)); if (start >= DL_GETDSIZE(lp) || start + size > DL_GETDSIZE(lp)) { error = EINVAL; goto done; } if (partoffp != NULL) { *partoffp = start; goto done; } else { DL_SETBSTART(lp, start); DL_SETBEND(lp, start + size); } /* * Now read the native label. */ if (spoofonly == 0) { error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, start + LABELSECTOR)); if (error) goto done; error = checkdisklabel(bp->b_data + LABELOFFSET, lp, start, start + size); } } else { /* * VDM label, but no OpenBSD vdmpart partition found. * XXX is it worth registering the whole disk as a * XXX `don't touch' vendor partition in that case? */ error = ENOENT; goto done; } done: free(vdit_storage, M_DEVBUF, vdit_size); if (sbp != NULL) { sbp->b_flags |= B_INVAL; brelse(sbp); } return error; }
int edit(struct disklabel *lp, int f) { int first, ch, fd, error = 0; struct disklabel label; FILE *fp; u_int64_t total_sectors, starting_sector, ending_sector; if ((fd = mkstemp(tmpfil)) == -1 || (fp = fdopen(fd, "w")) == NULL) { if (fd != -1) close(fd); warn("%s", tmpfil); return (1); } display(fp, lp, 0, 1); fprintf(fp, "\n# Notes:\n"); fprintf(fp, "# Up to 16 partitions are valid, named from 'a' to 'p'. Partition 'a' is\n" "# your root filesystem, 'b' is your swap, and 'c' should cover your whole\n" "# disk. Any other partition is free for any use. 'size' and 'offset' are\n" "# in 512-byte blocks. fstype should be '4.2BSD', 'swap', or 'none' or some\n" "# other values. fsize/bsize/cpg should typically be '2048 16384 16' for a\n" "# 4.2BSD filesystem (or '512 4096 16' except on alpha, sun4, ...)\n"); fclose(fp); for (;;) { if (editit(tmpfil) == -1) break; fp = fopen(tmpfil, "r"); if (fp == NULL) { warn("%s", tmpfil); break; } /* Get values set by OS and not the label. */ if (ioctl(f, DIOCGPDINFO, &label) < 0) err(4, "ioctl DIOCGPDINFO"); ending_sector = DL_GETBEND(&label); starting_sector = DL_GETBSTART(&label); total_sectors = DL_GETDSIZE(&label); memset(&label, 0, sizeof(label)); error = getasciilabel(fp, &label); DL_SETBEND(&label, ending_sector); DL_SETBSTART(&label, starting_sector); DL_SETDSIZE(&label, total_sectors); if (error == 0) { if (cmplabel(lp, &label) == 0) { puts("No changes."); fclose(fp); (void) unlink(tmpfil); return (0); } *lp = label; if (writelabel(f, bootarea, lp) == 0) { fclose(fp); (void) unlink(tmpfil); return (0); } } fclose(fp); printf("re-edit the label? [y]: "); fflush(stdout); first = ch = getchar(); while (ch != '\n' && ch != EOF) ch = getchar(); if (first == 'n' || first == 'N') break; } (void)unlink(tmpfil); return (1); }
/* * 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))); }