static int g_flashmap_modify(struct g_geom *gp, const char *devname, int secsize, struct g_flashmap_head *slices) { struct g_flashmap_slice *slice; int i, error; g_topology_assert(); i = 0; STAILQ_FOREACH(slice, slices, sl_link) { if (bootverbose) { printf("%s: slice ", devname); g_flashmap_print(slice); } error = g_slice_config(gp, i++, G_SLICE_CONFIG_CHECK, slice->sl_start, slice->sl_end - slice->sl_start + 1, secsize, "%ss.%s", gp->name, slice->sl_name); if (error) return (error); } i = 0; STAILQ_FOREACH(slice, slices, sl_link) { error = g_slice_config(gp, i++, G_SLICE_CONFIG_SET, slice->sl_start, slice->sl_end - slice->sl_start + 1, secsize, "%ss.%s", gp->name, slice->sl_name); if (error) return (error); }
static int g_sunlabel_modify(struct g_geom *gp, struct g_sunlabel_softc *ms, u_char *sec0) { int i, error; u_int u, v, csize; struct sun_disklabel sl; MD5_CTX md5sum; error = sunlabel_dec(sec0, &sl); if (error) return (error); csize = sl.sl_ntracks * sl.sl_nsectors; for (i = 0; i < SUN_NPART; i++) { v = sl.sl_part[i].sdkp_cyloffset; u = sl.sl_part[i].sdkp_nsectors; error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK, ((off_t)v * csize) << 9ULL, ((off_t)u) << 9ULL, ms->sectorsize, "%s%c", gp->name, 'a' + i); if (error) return (error); } for (i = 0; i < SUN_NPART; i++) { v = sl.sl_part[i].sdkp_cyloffset; u = sl.sl_part[i].sdkp_nsectors; g_slice_config(gp, i, G_SLICE_CONFIG_SET, ((off_t)v * csize) << 9ULL, ((off_t)u) << 9ULL, ms->sectorsize, "%s%c", gp->name, 'a' + i); } ms->nalt = sl.sl_acylinders; ms->nheads = sl.sl_ntracks; ms->nsects = sl.sl_nsectors; /* * Calculate MD5 from the first sector and use it for avoiding * recursive labels creation. */ MD5Init(&md5sum); MD5Update(&md5sum, sec0, ms->sectorsize); MD5Final(ms->labelsum, &md5sum); return (0); }
/* * XXX: Add gctl_req arg and give good error msgs. * XXX: Check that length argument does not bring boot code inside any slice. */ static int g_mbr_modify(struct g_geom *gp, struct g_mbr_softc *ms, u_char *sec0, int len __unused) { int i, error; off_t l[NDOSPART]; struct dos_partition ndp[NDOSPART], *dp; MD5_CTX md5sum; g_topology_assert(); if (sec0[0x1fe] != 0x55 && sec0[0x1ff] != 0xaa) return (EBUSY); dp = ndp; for (i = 0; i < NDOSPART; i++) { dos_partition_dec( sec0 + DOSPARTOFF + i * sizeof(struct dos_partition), dp + i); } if ((!bcmp(dp, historical_bogus_partition_table, sizeof historical_bogus_partition_table)) || (!bcmp(dp, historical_bogus_partition_table_fixed, sizeof historical_bogus_partition_table_fixed))) { /* * We will not allow people to write these from "the inside", * Since properly selfdestructing takes too much code. If * people really want to do this, they cannot have any * providers of this geom open, and in that case they can just * as easily overwrite the MBR in the parent device. */ return(EBUSY); } for (i = 0; i < NDOSPART; i++) { /* * A Protective MBR (PMBR) has a single partition of * type 0xEE spanning the whole disk. Such a MBR * protects a GPT on the disk from MBR tools that * don't know anything about GPT. We're interpreting * it a bit more loosely: any partition of type 0xEE * is to be skipped as it doesn't contain any data * that we should care about. We still allow other * partitions to be present in the MBR. A PMBR will * be handled correctly anyway. */ if (dp[i].dp_typ == DOSPTYP_PMBR) l[i] = 0; else if (dp[i].dp_flag != 0 && dp[i].dp_flag != 0x80) l[i] = 0; else if (dp[i].dp_typ == 0) l[i] = 0; else l[i] = (off_t)dp[i].dp_size * ms->sectorsize; error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK, (off_t)dp[i].dp_start * ms->sectorsize, l[i], ms->sectorsize, "%ss%d", gp->name, 1 + i); if (error) return (error); } for (i = 0; i < NDOSPART; i++) { ms->type[i] = dp[i].dp_typ; g_slice_config(gp, i, G_SLICE_CONFIG_SET, (off_t)dp[i].dp_start * ms->sectorsize, l[i], ms->sectorsize, "%ss%d", gp->name, 1 + i); } bcopy(sec0, ms->sec0, 512); /* * Calculate MD5 from the first sector and use it for avoiding * recursive slices creation. */ MD5Init(&md5sum); MD5Update(&md5sum, ms->sec0, sizeof(ms->sec0)); MD5Final(ms->slicesum, &md5sum); return (0); }
/* * Modify our slicer to match proposed disklabel, if possible. * This is where we make sure we don't do something stupid. */ static int g_bsd_modify(struct g_geom *gp, u_char *label) { int i, error; struct partition *ppp; struct g_slicer *gsp; struct g_consumer *cp; struct g_bsd_softc *ms; u_int secsize, u; off_t rawoffset, o; struct disklabel dl; MD5_CTX md5sum; g_topology_assert(); gsp = gp->softc; ms = gsp->softc; error = bsd_disklabel_le_dec(label, &dl, MAXPARTITIONS); if (error) { return (error); } /* Get dimensions of our device. */ cp = LIST_FIRST(&gp->consumer); secsize = cp->provider->sectorsize; /* ... or a smaller sector size. */ if (dl.d_secsize < secsize) { return (EINVAL); } /* ... or a non-multiple sector size. */ if (dl.d_secsize % secsize != 0) { return (EINVAL); } /* Historical braindamage... */ rawoffset = (off_t)dl.d_partitions[RAW_PART].p_offset * dl.d_secsize; for (i = 0; i < dl.d_npartitions; i++) { ppp = &dl.d_partitions[i]; if (ppp->p_size == 0) continue; o = (off_t)ppp->p_offset * dl.d_secsize; if (o < rawoffset) rawoffset = 0; } if (rawoffset != 0 && (off_t)rawoffset != ms->mbroffset) printf("WARNING: %s expected rawoffset %jd, found %jd\n", gp->name, (intmax_t)ms->mbroffset/dl.d_secsize, (intmax_t)rawoffset/dl.d_secsize); /* Don't munge open partitions. */ for (i = 0; i < dl.d_npartitions; i++) { ppp = &dl.d_partitions[i]; o = (off_t)ppp->p_offset * dl.d_secsize; if (o == 0) o = rawoffset; error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK, o - rawoffset, (off_t)ppp->p_size * dl.d_secsize, dl.d_secsize, "%s%c", gp->name, 'a' + i); if (error) return (error); } /* Look good, go for it... */ for (u = 0; u < gsp->nslice; u++) { ppp = &dl.d_partitions[u]; o = (off_t)ppp->p_offset * dl.d_secsize; if (o == 0) o = rawoffset; g_slice_config(gp, u, G_SLICE_CONFIG_SET, o - rawoffset, (off_t)ppp->p_size * dl.d_secsize, dl.d_secsize, "%s%c", gp->name, 'a' + u); } /* Update our softc */ ms->ondisk = dl; if (label != ms->label) bcopy(label, ms->label, LABELSIZE); ms->rawoffset = rawoffset; /* * In order to avoid recursively attaching to the same * on-disk label (it's usually visible through the 'c' * partition) we calculate an MD5 and ask if other BSD's * below us love that label. If they do, we don't. */ MD5Init(&md5sum); MD5Update(&md5sum, ms->label, sizeof(ms->label)); MD5Final(ms->labelsum, &md5sum); return (0); }
/* * XXX: Add gctl_req arg and give good error msgs. * XXX: Check that length argument does not bring boot code inside any slice. */ static int g_pc98_modify(struct g_geom *gp, struct g_pc98_softc *ms, u_char *sec, int len __unused) { int i, error; off_t s[PC98_NPARTS], l[PC98_NPARTS]; struct pc98_partition dp[PC98_NPARTS]; g_topology_assert(); if (sec[0x1fe] != 0x55 || sec[0x1ff] != 0xaa) return (EBUSY); #if 0 /* * By convetion, it seems that the ipl program has a jump at location * 0 to the real start of the boot loader. By convetion, it appears * that after this jump, there's a string, terminated by at last one, * if not more, zeros, followed by the target of the jump. FreeBSD's * pc98 boot0 uses 'IPL1' followed by 3 zeros here, likely for * compatibility with some older boot loader. Linux98's boot loader * appears to use 'Linux 98' followed by only two. GRUB/98 appears to * use 'GRUB/98 ' followed by none. These last two appear to be * ported from the ia32 versions, but appear to show similar * convention. Grub/98 has an additional NOP after the jmp, which * isn't present in others. * * The following test was inspired by looking only at partitions * with FreeBSD's boot0 (or one that it is compatible with). As * such, if failed when other IPL programs were used. */ if (sec[4] != 'I' || sec[5] != 'P' || sec[6] != 'L' || sec[7] != '1') return (EBUSY); #endif for (i = 0; i < PC98_NPARTS; i++) pc98_partition_dec( sec + 512 + i * sizeof(struct pc98_partition), &dp[i]); for (i = 0; i < PC98_NPARTS; i++) { /* If start and end are identical it's bogus */ if (dp[i].dp_ssect == dp[i].dp_esect && dp[i].dp_shd == dp[i].dp_ehd && dp[i].dp_scyl == dp[i].dp_ecyl) s[i] = l[i] = 0; else if (dp[i].dp_ecyl == 0) s[i] = l[i] = 0; else { s[i] = (off_t)dp[i].dp_scyl * ms->fwsectors * ms->fwheads * ms->sectorsize; l[i] = (off_t)(dp[i].dp_ecyl - dp[i].dp_scyl + 1) * ms->fwsectors * ms->fwheads * ms->sectorsize; } if (bootverbose) { printf("PC98 Slice %d on %s:\n", i + 1, gp->name); g_pc98_print(i, dp + i); } if (s[i] < 0 || l[i] < 0) error = EBUSY; else error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK, s[i], l[i], ms->sectorsize, "%ss%d", gp->name, i + 1); if (error) return (error); } for (i = 0; i < PC98_NPARTS; i++) { ms->type[i] = (dp[i].dp_sid << 8) | dp[i].dp_mid; g_slice_config(gp, i, G_SLICE_CONFIG_SET, s[i], l[i], ms->sectorsize, "%ss%d", gp->name, i + 1); } bcopy(sec, ms->sec, sizeof (ms->sec)); return (0); }