svn commit: r188893 - head/sys/geom/part

Marcel Moolenaar marcel at FreeBSD.org
Fri Feb 20 23:01:23 PST 2009


Author: marcel
Date: Sat Feb 21 07:01:21 2009
New Revision: 188893
URL: http://svn.freebsd.org/changeset/base/188893

Log:
  Add bootcode handling.

Modified:
  head/sys/geom/part/g_part_bsd.c

Modified: head/sys/geom/part/g_part_bsd.c
==============================================================================
--- head/sys/geom/part/g_part_bsd.c	Sat Feb 21 05:54:06 2009	(r188892)
+++ head/sys/geom/part/g_part_bsd.c	Sat Feb 21 07:01:21 2009	(r188893)
@@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$");
 
 struct g_part_bsd_table {
 	struct g_part_table	base;
-	u_char			*label;
+	u_char			*bbarea;
 	uint32_t		offset;
 };
 
@@ -58,6 +58,7 @@ struct g_part_bsd_entry {
 
 static int g_part_bsd_add(struct g_part_table *, struct g_part_entry *,
     struct g_part_parms *);
+static int g_part_bsd_bootcode(struct g_part_table *, struct g_part_parms *);
 static int g_part_bsd_create(struct g_part_table *, struct g_part_parms *);
 static int g_part_bsd_destroy(struct g_part_table *, struct g_part_parms *);
 static void g_part_bsd_dumpconf(struct g_part_table *, struct g_part_entry *,
@@ -75,6 +76,7 @@ static int g_part_bsd_write(struct g_par
 
 static kobj_method_t g_part_bsd_methods[] = {
 	KOBJMETHOD(g_part_add,		g_part_bsd_add),
+	KOBJMETHOD(g_part_bootcode,	g_part_bsd_bootcode),
 	KOBJMETHOD(g_part_create,	g_part_bsd_create),
 	KOBJMETHOD(g_part_destroy,	g_part_bsd_destroy),
 	KOBJMETHOD(g_part_dumpconf,	g_part_bsd_dumpconf),
@@ -95,6 +97,7 @@ static struct g_part_scheme g_part_bsd_s
 	.gps_entrysz = sizeof(struct g_part_bsd_entry),
 	.gps_minent = 8,
 	.gps_maxent = 20,
+	.gps_bootcodesz = BBSIZE,
 };
 G_PART_SCHEME_DECLARE(g_part_bsd);
 
@@ -157,6 +160,30 @@ g_part_bsd_add(struct g_part_table *base
 }
 
 static int
+g_part_bsd_bootcode(struct g_part_table *basetable, struct g_part_parms *gpp)
+{
+	struct g_part_bsd_table *table;
+	const u_char *codeptr;
+	size_t hdsz, tlsz;
+	size_t codesz, tlofs;
+
+	hdsz = 512;
+	tlofs = hdsz + 148 + basetable->gpt_entries * 16;
+	tlsz = BBSIZE - tlofs;
+	table = (struct g_part_bsd_table *)basetable;
+	bzero(table->bbarea, hdsz);
+	bzero(table->bbarea + tlofs, tlsz);
+	codeptr = gpp->gpp_codeptr;
+	codesz = MIN(hdsz, gpp->gpp_codesize);
+	if (codesz > 0)
+		bcopy(codeptr, table->bbarea, codesz);
+	codesz = MIN(tlsz, gpp->gpp_codesize - tlofs);
+	if (codesz > 0)
+		bcopy(codeptr + tlofs, table->bbarea + tlofs, codesz);
+	return (0);
+}
+
+static int
 g_part_bsd_create(struct g_part_table *basetable, struct g_part_parms *gpp)
 {
 	struct g_consumer *cp;
@@ -173,13 +200,16 @@ g_part_bsd_create(struct g_part_table *b
 
 	if (pp->sectorsize < sizeof(struct disklabel))
 		return (ENOSPC);
+	if (BBSIZE % pp->sectorsize)
+		return (ENOTBLK);
 
 	msize = pp->mediasize / pp->sectorsize;
 	secpercyl = basetable->gpt_sectors * basetable->gpt_heads;
 	ncyls = msize / secpercyl;
 
 	table = (struct g_part_bsd_table *)basetable;
-	ptr = table->label = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO);
+	table->bbarea = g_malloc(BBSIZE, M_WAITOK | M_ZERO);
+	ptr = table->bbarea + pp->sectorsize;
 
 	le32enc(ptr + 0, DISKMAGIC);			/* d_magic */
 	le32enc(ptr + 40, pp->sectorsize);		/* d_secsize */
@@ -284,6 +314,8 @@ g_part_bsd_probe(struct g_part_table *ta
 	if (pp->sectorsize < sizeof(struct disklabel) ||
 	    pp->mediasize < BBSIZE)
 		return (ENOSPC);
+	if (BBSIZE % pp->sectorsize)
+		return (ENOTBLK);
 
 	/* Check that there's a disklabel. */
 	buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error);
@@ -313,11 +345,11 @@ g_part_bsd_read(struct g_part_table *bas
 	table = (struct g_part_bsd_table *)basetable;
 	msize = pp->mediasize / pp->sectorsize;
 
-	buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error);
-	if (buf == NULL)
+	table->bbarea = g_read_data(cp, 0, BBSIZE, &error);
+	if (table->bbarea == NULL)
 		return (error);
 
-	table->label = buf;
+	buf = table->bbarea + pp->sectorsize;
 
 	if (le32dec(buf + 40) != pp->sectorsize)
 		goto invalid_label;
@@ -388,7 +420,7 @@ g_part_bsd_read(struct g_part_table *bas
 
  invalid_label:
 	printf("GEOM: %s: invalid disklabel.\n", pp->name);
-	g_free(table->label);
+	g_free(table->bbarea);
 	return (EINVAL);
 }
 
@@ -421,14 +453,15 @@ g_part_bsd_write(struct g_part_table *ba
 	struct g_part_bsd_entry *entry;
 	struct g_part_bsd_table *table;
 	uint16_t sum;
-	u_char *p, *pe;
+	u_char *label, *p, *pe;
 	int error, index;
 
 	pp = cp->provider;
 	table = (struct g_part_bsd_table *)basetable;
 	baseentry = LIST_FIRST(&basetable->gpt_entry);
+	label = table->bbarea + pp->sectorsize;
 	for (index = 1; index <= basetable->gpt_entries; index++) {
-		p = table->label + 148 + (index - 1) * 16;
+		p = label + 148 + (index - 1) * 16;
 		entry = (baseentry != NULL && index == baseentry->gpe_index)
 		    ? (struct g_part_bsd_entry *)baseentry : NULL;
 		if (entry != NULL && !baseentry->gpe_deleted) {
@@ -446,13 +479,13 @@ g_part_bsd_write(struct g_part_table *ba
 	}
 
 	/* Calculate checksum. */
-	le16enc(table->label + 136, 0);
-	pe = table->label + 148 + basetable->gpt_entries * 16;
+	le16enc(label + 136, 0);
+	pe = label + 148 + basetable->gpt_entries * 16;
 	sum = 0;
-	for (p = table->label; p < pe; p += 2)
+	for (p = label; p < pe; p += 2)
 		sum ^= le16dec(p);
-	le16enc(table->label + 136, sum);
+	le16enc(label + 136, sum);
 
-	error = g_write_data(cp, pp->sectorsize, table->label, pp->sectorsize);
+	error = g_write_data(cp, 0, table->bbarea, BBSIZE);
 	return (error);
 }


More information about the svn-src-head mailing list