Beispiel #1
0
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);
	}
Beispiel #2
0
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);
}
Beispiel #3
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);
}
Beispiel #4
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);
}
Beispiel #5
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);
}