svn commit: r189935 - in stable/7/sys: . contrib/pf dev/ata dev/ath/ath_hal dev/cxgb geom geom/part modules/geom/geom_part modules/geom/geom_part/geom_part_ebr sys

Marcel Moolenaar marcel at FreeBSD.org
Tue Mar 17 12:38:44 PDT 2009


Author: marcel
Date: Tue Mar 17 19:38:40 2009
New Revision: 189935
URL: http://svn.freebsd.org/changeset/base/189935

Log:
  Sync gpart with the trunk. This includes:
  o  APM scheme supports Tivo Series 1 partitions  (read only).
  o  Bootcode support added to BSD scheme.
  o  New EBR scheme to support Extended Boot Records (logical partitions).
  o  PC98 scheme fixes (credits to nyan@)
  o  VTOC8 scheme fixes (credits to marius@)

Added:
  stable/7/sys/geom/part/g_part_ebr.c
     - copied, changed from r188354, head/sys/geom/part/g_part_ebr.c
  stable/7/sys/modules/geom/geom_part/geom_part_ebr/
     - copied from r188354, head/sys/modules/geom/geom_part/geom_part_ebr/
Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ata/atapi-cd.c
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/geom/geom.h
  stable/7/sys/geom/geom_dev.c
  stable/7/sys/geom/geom_subr.c
  stable/7/sys/geom/part/g_part.c
  stable/7/sys/geom/part/g_part.h
  stable/7/sys/geom/part/g_part_apm.c
  stable/7/sys/geom/part/g_part_bsd.c
  stable/7/sys/geom/part/g_part_gpt.c
  stable/7/sys/geom/part/g_part_if.m
  stable/7/sys/geom/part/g_part_mbr.c
  stable/7/sys/geom/part/g_part_pc98.c
  stable/7/sys/geom/part/g_part_vtoc8.c
  stable/7/sys/modules/geom/geom_part/Makefile
  stable/7/sys/sys/disk.h
  stable/7/sys/sys/diskpc98.h

Modified: stable/7/sys/dev/ata/atapi-cd.c
==============================================================================
--- stable/7/sys/dev/ata/atapi-cd.c	Tue Mar 17 19:37:47 2009	(r189934)
+++ stable/7/sys/dev/ata/atapi-cd.c	Tue Mar 17 19:38:40 2009	(r189935)
@@ -218,7 +218,10 @@ acd_geom_ioctl(struct g_provider *pp, u_
 	case CDIOCRESET:
 	    acd_test_ready(dev);
 	    break;
-	   
+
+	case DIOCGPROVIDERALIAS:
+	    break;
+
 	default:
 	    acd_read_toc(dev);
 	    acd_prevent_allow(dev, 1);

Modified: stable/7/sys/geom/geom.h
==============================================================================
--- stable/7/sys/geom/geom.h	Tue Mar 17 19:37:47 2009	(r189934)
+++ stable/7/sys/geom/geom.h	Tue Mar 17 19:38:40 2009	(r189935)
@@ -227,10 +227,11 @@ void g_error_provider(struct g_provider 
 struct g_provider *g_provider_by_name(char const *arg);
 int g_getattr__(const char *attr, struct g_consumer *cp, void *var, int len);
 #define g_getattr(a, c, v) g_getattr__((a), (c), (v), sizeof *(v))
-int g_handleattr(struct bio *bp, const char *attribute, void *val, int len);
+int g_handleattr(struct bio *bp, const char *attribute, const void *val,
+    int len);
 int g_handleattr_int(struct bio *bp, const char *attribute, int val);
 int g_handleattr_off_t(struct bio *bp, const char *attribute, off_t val);
-int g_handleattr_str(struct bio *bp, const char *attribute, char *str);
+int g_handleattr_str(struct bio *bp, const char *attribute, const char *str);
 struct g_consumer * g_new_consumer(struct g_geom *gp);
 struct g_geom * g_new_geomf(struct g_class *mp, const char *fmt, ...);
 struct g_provider * g_new_providerf(struct g_geom *gp, const char *fmt, ...);

Modified: stable/7/sys/geom/geom_dev.c
==============================================================================
--- stable/7/sys/geom/geom_dev.c	Tue Mar 17 19:37:47 2009	(r189934)
+++ stable/7/sys/geom/geom_dev.c	Tue Mar 17 19:38:40 2009	(r189935)
@@ -124,6 +124,7 @@ g_dev_taste(struct g_class *mp, struct g
 {
 	struct g_geom *gp;
 	struct g_consumer *cp;
+	char *alias;
 	int error;
 	struct cdev *dev;
 	u_int unit;
@@ -147,6 +148,17 @@ g_dev_taste(struct g_class *mp, struct g
 	gp->softc = dev;
 	dev->si_drv1 = gp;
 	dev->si_drv2 = cp;
+
+	g_topology_unlock();
+
+	alias = g_malloc(MAXPATHLEN, M_WAITOK | M_ZERO);
+	error = (pp->geom->ioctl == NULL) ? ENODEV :
+	    pp->geom->ioctl(pp, DIOCGPROVIDERALIAS, alias, 0, curthread);
+	if (!error && alias[0] != '\0')
+		make_dev_alias(dev, "%s", alias);
+	g_free(alias);
+
+	g_topology_lock();
 	return (gp);
 }
 

Modified: stable/7/sys/geom/geom_subr.c
==============================================================================
--- stable/7/sys/geom/geom_subr.c	Tue Mar 17 19:37:47 2009	(r189934)
+++ stable/7/sys/geom/geom_subr.c	Tue Mar 17 19:38:40 2009	(r189935)
@@ -856,14 +856,14 @@ g_handleattr_off_t(struct bio *bp, const
 }
 
 int
-g_handleattr_str(struct bio *bp, const char *attribute, char *str)
+g_handleattr_str(struct bio *bp, const char *attribute, const char *str)
 {
 
 	return (g_handleattr(bp, attribute, str, 0));
 }
 
 int
-g_handleattr(struct bio *bp, const char *attribute, void *val, int len)
+g_handleattr(struct bio *bp, const char *attribute, const void *val, int len)
 {
 	int error = 0;
 
@@ -880,12 +880,13 @@ g_handleattr(struct bio *bp, const char 
 		}
 	} else if (bp->bio_length == len) {
 		bcopy(val, bp->bio_data, len);
-		bp->bio_completed = len;
 	} else {
 		printf("%s: %s bio_length %jd len %d -> EFAULT\n", __func__,
 		    bp->bio_to->name, (intmax_t)bp->bio_length, len);
 		error = EFAULT;
 	}
+	if (error == 0)
+		bp->bio_completed = bp->bio_length;
 	g_io_deliver(bp, error);
 	return (1);
 }

Modified: stable/7/sys/geom/part/g_part.c
==============================================================================
--- stable/7/sys/geom/part/g_part.c	Tue Mar 17 19:37:47 2009	(r189934)
+++ stable/7/sys/geom/part/g_part.c	Tue Mar 17 19:38:40 2009	(r189935)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2002, 2005-2008 Marcel Moolenaar
+ * Copyright (c) 2002, 2005-2009 Marcel Moolenaar
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/bio.h>
+#include <sys/disk.h>
 #include <sys/diskmbr.h>
 #include <sys/endian.h>
 #include <sys/kernel.h>
@@ -86,6 +87,7 @@ static g_taste_t g_part_taste;
 
 static g_access_t g_part_access;
 static g_dumpconf_t g_part_dumpconf;
+static g_ioctl_t g_part_ioctl;
 static g_orphan_t g_part_orphan;
 static g_spoiled_t g_part_spoiled;
 static g_start_t g_part_start;
@@ -102,6 +104,7 @@ static struct g_class g_part_class = {
 	/* Geom methods. */
 	.access = g_part_access,
 	.dumpconf = g_part_dumpconf,
+	.ioctl = g_part_ioctl,
 	.orphan = g_part_orphan,
 	.spoiled = g_part_spoiled,
 	.start = g_part_start,
@@ -109,23 +112,6 @@ static struct g_class g_part_class = {
 
 DECLARE_GEOM_CLASS(g_part_class, g_part);
 
-enum g_part_ctl {
-	G_PART_CTL_NONE,
-	G_PART_CTL_ADD,
-	G_PART_CTL_BOOTCODE,
-	G_PART_CTL_COMMIT,
-	G_PART_CTL_CREATE,
-	G_PART_CTL_DELETE,
-	G_PART_CTL_DESTROY,
-	G_PART_CTL_MODIFY,
-	G_PART_CTL_MOVE,
-	G_PART_CTL_RECOVER,
-	G_PART_CTL_RESIZE,
-	G_PART_CTL_SET,
-	G_PART_CTL_UNDO,
-	G_PART_CTL_UNSET
-};
-
 /*
  * Support functions.
  */
@@ -181,10 +167,8 @@ g_part_geometry(struct g_part_table *tab
 	u_int heads, sectors;
 	int idx;
 
-	if (g_getattr("GEOM::fwsectors", cp, &sectors) != 0 ||
-	    sectors < 1 || sectors > 63 ||
-	    g_getattr("GEOM::fwheads", cp, &heads) != 0 ||
-	    heads < 1 || heads > 255) {
+	if (g_getattr("GEOM::fwsectors", cp, &sectors) != 0 || sectors == 0 ||
+	    g_getattr("GEOM::fwheads", cp, &heads) != 0 || heads == 0) {
 		table->gpt_fixgeom = 0;
 		table->gpt_heads = 0;
 		table->gpt_sectors = 0;
@@ -245,7 +229,8 @@ g_part_new_entry(struct g_part_table *ta
 			LIST_INSERT_HEAD(&table->gpt_entry, entry, gpe_entry);
 		else
 			LIST_INSERT_AFTER(last, entry, gpe_entry);
-	}
+	} else
+		entry->gpe_offset = 0;
 	entry->gpe_start = start;
 	entry->gpe_end = end;
 	return (entry);
@@ -258,11 +243,14 @@ g_part_new_provider(struct g_geom *gp, s
 	char buf[32];
 	struct g_consumer *cp;
 	struct g_provider *pp;
+	off_t offset;
 
 	cp = LIST_FIRST(&gp->consumer);
 	pp = cp->provider;
 
-	entry->gpe_offset = entry->gpe_start * pp->sectorsize;
+	offset = entry->gpe_start * pp->sectorsize;
+	if (entry->gpe_offset < offset)
+		entry->gpe_offset = offset;
 
 	if (entry->gpe_pp == NULL) {
 		entry->gpe_pp = g_new_providerf(gp, "%s%s", gp->name,
@@ -272,6 +260,7 @@ g_part_new_provider(struct g_geom *gp, s
 	entry->gpe_pp->index = entry->gpe_index - 1;	/* index is 1-based. */
 	entry->gpe_pp->mediasize = (entry->gpe_end - entry->gpe_start + 1) *
 	    pp->sectorsize;
+	entry->gpe_pp->mediasize -= entry->gpe_offset - offset;
 	entry->gpe_pp->sectorsize = pp->sectorsize;
 	entry->gpe_pp->flags = pp->flags & G_PF_CANDELETE;
 	if (pp->stripesize > 0) {
@@ -534,8 +523,8 @@ g_part_ctl_bootcode(struct gctl_req *req
 		error = ENODEV;
 		goto fail;
 	}
-	if (gpp->gpp_codesize != sz) {
-		error = EINVAL;
+	if (gpp->gpp_codesize > sz) {
+		error = EFBIG;
 		goto fail;
 	}
 
@@ -579,6 +568,8 @@ g_part_ctl_commit(struct gctl_req *req, 
 		return (EPERM);
 	}
 
+	g_topology_unlock();
+
 	cp = LIST_FIRST(&gp->consumer);
 	if ((table->gpt_smhead | table->gpt_smtail) != 0) {
 		pp = cp->provider;
@@ -607,6 +598,7 @@ g_part_ctl_commit(struct gctl_req *req, 
 	}
 
 	if (table->gpt_scheme == &g_part_null_scheme) {
+		g_topology_lock();
 		g_access(cp, -1, -1, -1);
 		g_part_wither(gp, ENXIO);
 		return (0);
@@ -627,10 +619,13 @@ g_part_ctl_commit(struct gctl_req *req, 
 	}
 	table->gpt_created = 0;
 	table->gpt_opened = 0;
+
+	g_topology_lock();
 	g_access(cp, -1, -1, -1);
 	return (0);
 
 fail:
+	g_topology_lock();
 	gctl_error(req, "%d", error);
 	return (error);
 }
@@ -714,14 +709,6 @@ g_part_ctl_create(struct gctl_req *req, 
 	error = g_getattr("PART::depth", cp, &attr);
 	table->gpt_depth = (!error) ? attr + 1 : 0;
 
-	/* If we're nested, get the absolute sector offset on disk. */
-	if (table->gpt_depth) {
-		error = g_getattr("PART::offset", cp, &attr);
-		if (error)
-			goto fail;
-		table->gpt_offset = attr;
-	}
-
 	/*
 	 * Synthesize a disk geometry. Some partitioning schemes
 	 * depend on it and since some file systems need it even
@@ -1345,7 +1332,7 @@ g_part_ctlreq(struct gctl_req *req, stru
 
 	/* Obtain permissions if possible/necessary. */
 	close_on_error = 0;
-	table = NULL;	/* Suppress uninit. warning. */
+	table = NULL;
 	if (modifies && (gpp.gpp_parms & G_PART_PARM_GEOM)) {
 		table = gpp.gpp_geom->softc;
 		if (table != NULL && !table->gpt_opened) {
@@ -1361,7 +1348,16 @@ g_part_ctlreq(struct gctl_req *req, stru
 		}
 	}
 
-	error = EDOOFUS;	/* Prevent bogus  uninit. warning. */
+	/* Allow the scheme to check or modify the parameters. */
+	if (table != NULL) {
+		error = G_PART_PRECHECK(table, ctlreq, &gpp);
+		if (error) {
+			gctl_error(req, "%d pre-check failed", error);
+			goto out;
+		}
+	} else
+		error = EDOOFUS;	/* Prevent bogus uninit. warning. */
+
 	switch (ctlreq) {
 	case G_PART_CTL_NONE:
 		panic("%s", __func__);
@@ -1417,6 +1413,7 @@ g_part_ctlreq(struct gctl_req *req, stru
 		}
 	}
 
+ out:
 	if (error && close_on_error) {
 		g_access(LIST_FIRST(&gpp.gpp_geom->consumer), -1, -1, -1);
 		table->gpt_opened = 0;
@@ -1442,6 +1439,7 @@ g_part_taste(struct g_class *mp, struct 
 	struct g_geom *gp;
 	struct g_part_entry *entry;
 	struct g_part_table *table;
+	struct root_hold_token *rht;
 	int attr, depth;
 	int error;
 
@@ -1463,6 +1461,7 @@ g_part_taste(struct g_class *mp, struct 
 		return (NULL);
 	}
 
+	rht = root_mount_hold(mp->name);
 	g_topology_unlock();
 
 	/*
@@ -1489,14 +1488,6 @@ g_part_taste(struct g_class *mp, struct 
 
 	table = gp->softc;
 
-	/* If we're nested, get the absolute sector offset on disk. */
-	if (table->gpt_depth) {
-		error = g_getattr("PART::offset", cp, &attr);
-		if (error)
-			goto fail;
-		table->gpt_offset = attr;
-	}
-
 	/*
 	 * Synthesize a disk geometry. Some partitioning schemes
 	 * depend on it and since some file systems need it even
@@ -1515,11 +1506,13 @@ g_part_taste(struct g_class *mp, struct 
 			g_part_new_provider(gp, table, entry);
 	}
 
+	root_mount_rel(rht);
 	g_access(cp, -1, 0, 0);
 	return (gp);
 
  fail:
 	g_topology_lock();
+	root_mount_rel(rht);
 	g_access(cp, -1, 0, 0);
 	g_part_wither(gp, error);
 	return (NULL);
@@ -1576,6 +1569,10 @@ g_part_dumpconf(struct sbuf *sb, const c
 		entry = pp->private;
 		if (entry == NULL)
 			return;
+		sbuf_printf(sb, "%s<start>%ju</start>\n", indent,
+		    (uintmax_t)entry->gpe_start);
+		sbuf_printf(sb, "%s<end>%ju</end>\n", indent,
+		    (uintmax_t)entry->gpe_end);
 		sbuf_printf(sb, "%s<index>%u</index>\n", indent,
 		    entry->gpe_index);
 		sbuf_printf(sb, "%s<type>%s</type>\n", indent,
@@ -1602,6 +1599,31 @@ g_part_dumpconf(struct sbuf *sb, const c
 	}
 }
 
+static int
+g_part_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag,
+    struct thread *td)
+{
+	struct g_geom *gp;
+	struct g_part_table *table;
+	struct g_part_entry *entry;
+	int error;
+
+	gp = pp->geom;
+	table = gp->softc;
+	entry = pp->private;
+
+	switch (cmd) {
+	case DIOCGPROVIDERALIAS:
+		error = G_PART_DEVALIAS(table, entry, data, MAXPATHLEN);
+		break;
+	default:
+		error = ENOTTY;
+		break;
+	}
+
+	return (error);
+}
+
 static void
 g_part_orphan(struct g_consumer *cp)
 {
@@ -1681,8 +1703,8 @@ g_part_start(struct bio *bp)
 			return;
 		if (g_handleattr_int(bp, "PART::depth", table->gpt_depth))
 			return;
-		if (g_handleattr_int(bp, "PART::offset",
-		    table->gpt_offset + entry->gpe_start))
+		if (g_handleattr_str(bp, "PART::scheme",
+		    table->gpt_scheme->name))
 			return;
 		if (!strcmp("GEOM::kerneldump", bp->bio_attribute)) {
 			/*
@@ -1722,7 +1744,7 @@ static void
 g_part_init(struct g_class *mp)
 {
 
-	TAILQ_INSERT_TAIL(&g_part_schemes, &g_part_null_scheme, scheme_list);
+	TAILQ_INSERT_HEAD(&g_part_schemes, &g_part_null_scheme, scheme_list);
 }
 
 static void

Modified: stable/7/sys/geom/part/g_part.h
==============================================================================
--- stable/7/sys/geom/part/g_part.h	Tue Mar 17 19:37:47 2009	(r189934)
+++ stable/7/sys/geom/part/g_part.h	Tue Mar 17 19:38:40 2009	(r189935)
@@ -103,13 +103,6 @@ struct g_part_table {
 	 */
 	uint32_t	gpt_sectors;
 	uint32_t	gpt_heads;
-	/*
-	 * gpt_offset holds the absolute block address of the scheme
-	 * on disk. Some partitioning schemes (historically) use
-	 * absolute addressing. Relative addresses are obtained by
-	 * subtracting gpt_offset from the absolute addresses.
-	 */
-	uint64_t	gpt_offset;
 
 	int		gpt_depth;	/* Sub-partitioning level. */
 	int		gpt_isleaf:1;	/* Cannot be sub-partitioned. */
@@ -122,6 +115,23 @@ struct g_part_table {
 struct g_part_entry *g_part_new_entry(struct g_part_table *, int, quad_t,
     quad_t);
 
+enum g_part_ctl {
+	G_PART_CTL_NONE,
+	G_PART_CTL_ADD,
+	G_PART_CTL_BOOTCODE,
+	G_PART_CTL_COMMIT,
+	G_PART_CTL_CREATE,
+	G_PART_CTL_DELETE,
+	G_PART_CTL_DESTROY,
+	G_PART_CTL_MODIFY,
+	G_PART_CTL_MOVE,
+	G_PART_CTL_RECOVER,
+	G_PART_CTL_RESIZE,
+	G_PART_CTL_SET,
+	G_PART_CTL_UNDO,
+	G_PART_CTL_UNSET
+};
+
 /* G_PART ctlreq parameters. */
 #define	G_PART_PARM_ENTRIES	0x0001
 #define	G_PART_PARM_FLAGS	0x0002

Modified: stable/7/sys/geom/part/g_part_apm.c
==============================================================================
--- stable/7/sys/geom/part/g_part_apm.c	Tue Mar 17 19:37:47 2009	(r189934)
+++ stable/7/sys/geom/part/g_part_apm.c	Tue Mar 17 19:38:40 2009	(r189935)
@@ -50,6 +50,7 @@ struct g_part_apm_table {
 	struct g_part_table	base;
 	struct apm_ddr		ddr;
 	struct apm_ent		self;
+	int			tivo_series1;
 };
 
 struct g_part_apm_entry {
@@ -61,12 +62,12 @@ static int g_part_apm_add(struct g_part_
     struct g_part_parms *);
 static int g_part_apm_create(struct g_part_table *, struct g_part_parms *);
 static int g_part_apm_destroy(struct g_part_table *, struct g_part_parms *);
-static int g_part_apm_dumpconf(struct g_part_table *, struct g_part_entry *,
+static void g_part_apm_dumpconf(struct g_part_table *, struct g_part_entry *,
     struct sbuf *, const char *);
 static int g_part_apm_dumpto(struct g_part_table *, struct g_part_entry *);
 static int g_part_apm_modify(struct g_part_table *, struct g_part_entry *,
     struct g_part_parms *);
-static char *g_part_apm_name(struct g_part_table *, struct g_part_entry *,
+static const char *g_part_apm_name(struct g_part_table *, struct g_part_entry *,
     char *, size_t);
 static int g_part_apm_probe(struct g_part_table *, struct g_consumer *);
 static int g_part_apm_read(struct g_part_table *, struct g_consumer *);
@@ -99,6 +100,19 @@ static struct g_part_scheme g_part_apm_s
 };
 G_PART_SCHEME_DECLARE(g_part_apm);
 
+static void
+swab(char *buf, size_t bufsz)
+{
+	int i;
+	char ch;
+
+	for (i = 0; i < bufsz; i += 2) {
+		ch = buf[i];
+		buf[i] = buf[i + 1];
+		buf[i + 1] = ch;
+	}
+}
+
 static int
 apm_parse_type(const char *type, char *buf, size_t bufsz)
 {
@@ -143,7 +157,8 @@ apm_parse_type(const char *type, char *b
 }
 
 static int
-apm_read_ent(struct g_consumer *cp, uint32_t blk, struct apm_ent *ent)
+apm_read_ent(struct g_consumer *cp, uint32_t blk, struct apm_ent *ent,
+    int tivo_series1)
 {
 	struct g_provider *pp;
 	char *buf;
@@ -153,6 +168,8 @@ apm_read_ent(struct g_consumer *cp, uint
 	buf = g_read_data(cp, pp->sectorsize * blk, pp->sectorsize, &error);
 	if (buf == NULL)
 		return (error);
+	if (tivo_series1)
+		swab(buf, pp->sectorsize);
 	ent->ent_sig = be16dec(buf);
 	ent->ent_pmblkcnt = be32dec(buf + 4);
 	ent->ent_start = be32dec(buf + 8);
@@ -231,7 +248,7 @@ g_part_apm_destroy(struct g_part_table *
 	return (0);
 }
 
-static int
+static void
 g_part_apm_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry,
     struct sbuf *sb, const char *indent)
 {
@@ -256,7 +273,6 @@ g_part_apm_dumpconf(struct g_part_table 
 	} else {
 		/* confxml: scheme information */
 	}
-	return (0);
 }
 
 static int
@@ -294,7 +310,7 @@ g_part_apm_modify(struct g_part_table *b
 	return (0);
 }
 
-static char *
+static const char *
 g_part_apm_name(struct g_part_table *table, struct g_part_entry *baseentry,
     char *buf, size_t bufsz)
 {
@@ -316,6 +332,7 @@ g_part_apm_probe(struct g_part_table *ba
 		return (ENXIO);
 
 	table = (struct g_part_apm_table *)basetable;
+	table->tivo_series1 = 0;
 	pp = cp->provider;
 
 	/* Sanity-check the provider. */
@@ -326,17 +343,35 @@ g_part_apm_probe(struct g_part_table *ba
 	buf = g_read_data(cp, 0L, pp->sectorsize, &error);
 	if (buf == NULL)
 		return (error);
-	table->ddr.ddr_sig = be16dec(buf);
-	table->ddr.ddr_blksize = be16dec(buf + 2);
-	table->ddr.ddr_blkcount = be32dec(buf + 4);
-	g_free(buf);
-	if (table->ddr.ddr_sig != APM_DDR_SIG)
-		return (ENXIO);
-	if (table->ddr.ddr_blksize != pp->sectorsize)
-		return (ENXIO);
+	if (be16dec(buf) == be16toh(APM_DDR_SIG)) {
+		/* Normal Apple DDR */
+		table->ddr.ddr_sig = be16dec(buf);
+		table->ddr.ddr_blksize = be16dec(buf + 2);
+		table->ddr.ddr_blkcount = be32dec(buf + 4);
+		g_free(buf);
+		if (table->ddr.ddr_blksize != pp->sectorsize)
+			return (ENXIO);
+	} else {
+		/*
+		 * Check for Tivo drives, which have no DDR and a different
+		 * signature.  Those whose first two bytes are 14 92 are
+		 * Series 2 drives, and aren't supported.  Those that start
+		 * with 92 14 are series 1 drives and are supported.
+		 */
+		if (be16dec(buf) != 0x9214) {
+			/* If this is 0x1492 it could be a series 2 drive */
+			g_free(buf);
+			return (ENXIO);
+		}
+		table->ddr.ddr_sig = APM_DDR_SIG;		/* XXX */
+		table->ddr.ddr_blksize = pp->sectorsize;	/* XXX */
+		table->ddr.ddr_blkcount = pp->mediasize / pp->sectorsize;/* XXX */
+		table->tivo_series1 = 1;
+		g_free(buf);
+	}
 
 	/* Check that there's a Partition Map. */
-	error = apm_read_ent(cp, 1, &table->self);
+	error = apm_read_ent(cp, 1, &table->self, table->tivo_series1);
 	if (error)
 		return (error);
 	if (table->self.ent_sig != APM_ENT_SIG)
@@ -363,7 +398,7 @@ g_part_apm_read(struct g_part_table *bas
 	basetable->gpt_entries = table->self.ent_pmblkcnt - 1;
 
 	for (index = table->self.ent_pmblkcnt - 1; index > 0; index--) {
-		error = apm_read_ent(cp, index + 1, &ent);
+		error = apm_read_ent(cp, index + 1, &ent, table->tivo_series1);
 		if (error)
 			continue;
 		if (!strcmp(ent.ent_type, APM_ENT_TYPE_UNUSED))
@@ -413,6 +448,11 @@ g_part_apm_write(struct g_part_table *ba
 	int error, index;
 
 	table = (struct g_part_apm_table *)basetable;
+	/*
+	 * Tivo Series 1 disk partitions are currently read-only.
+	 */
+	if (table->tivo_series1)
+		return (EOPNOTSUPP);
 	bzero(buf, sizeof(buf));
 
 	/* Write the DDR and 'self' entry only when we're newly created. */

Modified: stable/7/sys/geom/part/g_part_bsd.c
==============================================================================
--- stable/7/sys/geom/part/g_part_bsd.c	Tue Mar 17 19:37:47 2009	(r189934)
+++ stable/7/sys/geom/part/g_part_bsd.c	Tue Mar 17 19:38:40 2009	(r189935)
@@ -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,14 +58,15 @@ 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 int g_part_bsd_dumpconf(struct g_part_table *, struct g_part_entry *,
+static void g_part_bsd_dumpconf(struct g_part_table *, struct g_part_entry *,
     struct sbuf *, const char *);
 static int g_part_bsd_dumpto(struct g_part_table *, struct g_part_entry *);
 static int g_part_bsd_modify(struct g_part_table *, struct g_part_entry *,  
     struct g_part_parms *);
-static char *g_part_bsd_name(struct g_part_table *, struct g_part_entry *,
+static const char *g_part_bsd_name(struct g_part_table *, struct g_part_entry *,
     char *, size_t);
 static int g_part_bsd_probe(struct g_part_table *, struct g_consumer *);
 static int g_part_bsd_read(struct g_part_table *, struct g_consumer *);
@@ -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 */
@@ -216,7 +246,7 @@ g_part_bsd_destroy(struct g_part_table *
 	return (0);
 }
 
-static int
+static void
 g_part_bsd_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry, 
     struct sbuf *sb, const char *indent)
 {
@@ -233,7 +263,6 @@ g_part_bsd_dumpconf(struct g_part_table 
 	} else {
 		/* confxml: scheme information */
 	}
-	return (0);
 }
 
 static int
@@ -241,9 +270,10 @@ g_part_bsd_dumpto(struct g_part_table *t
 {
 	struct g_part_bsd_entry *entry;
 
-	/* Allow dumping to a swap partition only. */
+	/* Allow dumping to a swap partition or an unused partition. */
 	entry = (struct g_part_bsd_entry *)baseentry;
-	return ((entry->part.p_fstype == FS_SWAP) ? 1 : 0);
+	return ((entry->part.p_fstype == FS_UNUSED ||
+	    entry->part.p_fstype == FS_SWAP) ? 1 : 0);
 }
 
 static int
@@ -261,7 +291,7 @@ g_part_bsd_modify(struct g_part_table *b
 	return (0);
 }
 
-static char *
+static const char *
 g_part_bsd_name(struct g_part_table *table, struct g_part_entry *baseentry,
     char *buf, size_t bufsz)
 {
@@ -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,16 +345,16 @@ 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;
 	sectors = le32dec(buf + 44);
-	if (sectors < 1 || sectors > 63)
+	if (sectors < 1 || sectors > 255)
 		goto invalid_label;
 	if (sectors != basetable->gpt_sectors && !basetable->gpt_fixgeom) {
 		g_part_geometry_heads(msize, sectors, &chs, &heads);
@@ -341,8 +373,13 @@ g_part_bsd_read(struct g_part_table *bas
 		printf("GEOM: %s: geometry does not match label.\n", pp->name);
 
 	chs = le32dec(buf + 60);
-	if (chs < 1 || chs > msize)
+	if (chs < 1)
 		goto invalid_label;
+	/* Fix-up a sysinstall bug. */
+	if (chs > msize) {
+		chs = msize;
+		le32enc(buf + 60, msize);
+	}
 	if (chs != msize)
 		printf("GEOM: %s: media size does not match label.\n",
 		    pp->name);
@@ -367,8 +404,6 @@ g_part_bsd_read(struct g_part_table *bas
 		part.p_cpg = le16dec(p + 14);
 		if (part.p_size == 0)
 			continue;
-		if (part.p_fstype == FS_UNUSED && index != RAW_PART)
-			continue;
 		if (part.p_offset < table->offset)
 			continue;
 		baseentry = g_part_new_entry(basetable, index + 1,
@@ -376,7 +411,7 @@ g_part_bsd_read(struct g_part_table *bas
 		    part.p_offset - table->offset + part.p_size - 1);
 		entry = (struct g_part_bsd_entry *)baseentry;
 		entry->part = part;
-		if (part.p_fstype == FS_UNUSED)
+		if (index == RAW_PART)
 			baseentry->gpe_internal = 1;
 	}
 
@@ -384,7 +419,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);
 }
 
@@ -417,14 +452,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) {
@@ -442,13 +478,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);
 }

Copied and modified: stable/7/sys/geom/part/g_part_ebr.c (from r188354, head/sys/geom/part/g_part_ebr.c)
==============================================================================
--- head/sys/geom/part/g_part_ebr.c	Sun Feb  8 23:51:44 2009	(r188354, copy source)
+++ stable/7/sys/geom/part/g_part_ebr.c	Tue Mar 17 19:38:40 2009	(r189935)
@@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/mutex.h>
 #include <sys/queue.h>
 #include <sys/sbuf.h>
-#include <sys/syscallsubr.h>
 #include <sys/systm.h>
 #include <geom/geom.h>
 #include <geom/part/g_part.h>
@@ -55,12 +54,15 @@ struct g_part_ebr_table {
 struct g_part_ebr_entry {
 	struct g_part_entry	base;
 	struct dos_partition	ent;
+	int	alias;
 };
 
 static int g_part_ebr_add(struct g_part_table *, struct g_part_entry *,
     struct g_part_parms *);
 static int g_part_ebr_create(struct g_part_table *, struct g_part_parms *);
 static int g_part_ebr_destroy(struct g_part_table *, struct g_part_parms *);
+static int g_part_ebr_devalias(struct g_part_table *, struct g_part_entry *,
+    char *, size_t);
 static void g_part_ebr_dumpconf(struct g_part_table *, struct g_part_entry *,
     struct sbuf *, const char *);
 static int g_part_ebr_dumpto(struct g_part_table *, struct g_part_entry *);
@@ -68,6 +70,8 @@ static int g_part_ebr_modify(struct g_pa
     struct g_part_parms *);
 static const char *g_part_ebr_name(struct g_part_table *, struct g_part_entry *,
     char *, size_t);
+static int g_part_ebr_precheck(struct g_part_table *, enum g_part_ctl,
+    struct g_part_parms *);
 static int g_part_ebr_probe(struct g_part_table *, struct g_consumer *);
 static int g_part_ebr_read(struct g_part_table *, struct g_consumer *);
 static int g_part_ebr_setunset(struct g_part_table *, struct g_part_entry *,
@@ -80,10 +84,12 @@ static kobj_method_t g_part_ebr_methods[
 	KOBJMETHOD(g_part_add,		g_part_ebr_add),
 	KOBJMETHOD(g_part_create,	g_part_ebr_create),
 	KOBJMETHOD(g_part_destroy,	g_part_ebr_destroy),
+	KOBJMETHOD(g_part_devalias,	g_part_ebr_devalias),
 	KOBJMETHOD(g_part_dumpconf,	g_part_ebr_dumpconf),
 	KOBJMETHOD(g_part_dumpto,	g_part_ebr_dumpto),
 	KOBJMETHOD(g_part_modify,	g_part_ebr_modify),
 	KOBJMETHOD(g_part_name,		g_part_ebr_name),
+	KOBJMETHOD(g_part_precheck,	g_part_ebr_precheck),
 	KOBJMETHOD(g_part_probe,	g_part_ebr_probe),
 	KOBJMETHOD(g_part_read,		g_part_ebr_read),
 	KOBJMETHOD(g_part_setunset,	g_part_ebr_setunset),
@@ -102,6 +108,9 @@ static struct g_part_scheme g_part_ebr_s
 };
 G_PART_SCHEME_DECLARE(g_part_ebr);
 
+static void ebr_set_chs(struct g_part_table *, uint32_t, u_char *, u_char *,
+    u_char *);
+
 static void
 ebr_entry_decode(const char *p, struct dos_partition *ent)
 {
@@ -117,19 +126,142 @@ ebr_entry_decode(const char *p, struct d
 	ent->dp_size = le32dec(p + 12);
 }
 
+static void
+ebr_entry_link(struct g_part_table *table, uint32_t start, uint32_t end,
+   u_char *buf)
+{
+
+	buf[0] = 0 /* dp_flag */;
+	ebr_set_chs(table, start, &buf[3] /* dp_scyl */, &buf[1] /* dp_shd */,
+	    &buf[2] /* dp_ssect */);
+	buf[4] = 5 /* dp_typ */;
+	ebr_set_chs(table, end, &buf[7] /* dp_ecyl */, &buf[5] /* dp_ehd */,
+	    &buf[6] /* dp_esect */);
+	le32enc(buf + 8, start);
+	le32enc(buf + 12, end - start + 1);
+}
+
+static int
+ebr_parse_type(const char *type, u_char *dp_typ)
+{
+	const char *alias;
+	char *endp;
+	long lt;
+
+	if (type[0] == '!') {
+		lt = strtol(type + 1, &endp, 0);
+		if (type[1] == '\0' || *endp != '\0' || lt <= 0 || lt >= 256)
+			return (EINVAL);
+		*dp_typ = (u_char)lt;
+		return (0);
+	}
+	alias = g_part_alias_name(G_PART_ALIAS_FREEBSD);
+	if (!strcasecmp(type, alias)) {
+		*dp_typ = DOSPTYP_386BSD;
+		return (0);
+	}
+	return (EINVAL);
+}
+
+static void
+ebr_set_chs(struct g_part_table *table, uint32_t lba, u_char *cylp, u_char *hdp,
+    u_char *secp)
+{
+	uint32_t cyl, hd, sec;
+
+	sec = lba % table->gpt_sectors + 1;
+	lba /= table->gpt_sectors;
+	hd = lba % table->gpt_heads;
+	lba /= table->gpt_heads;
+	cyl = lba;
+	if (cyl > 1023)
+		sec = hd = cyl = ~0;
+
+	*cylp = cyl & 0xff;
+	*hdp = hd & 0xff;
+	*secp = (sec & 0x3f) | ((cyl >> 2) & 0xc0);
+}
+
 static int
 g_part_ebr_add(struct g_part_table *basetable, struct g_part_entry *baseentry,
     struct g_part_parms *gpp)
 {
+	struct g_geom *gp;
+	struct g_provider *pp;
+	struct g_part_ebr_entry *entry;
+	uint32_t start, size, sectors;
 
-	return (ENOSYS);
+	if (gpp->gpp_parms & G_PART_PARM_LABEL)
+		return (EINVAL);
+
+	gp = basetable->gpt_gp;
+	pp = LIST_FIRST(&gp->consumer)->provider;
+	sectors = basetable->gpt_sectors;
+
+	entry = (struct g_part_ebr_entry *)baseentry;
+
+	start = gpp->gpp_start;
+	size = gpp->gpp_size;
+	if (size < 2 * sectors)
+		return (EINVAL);
+	if (start % sectors) {
+		size = size - sectors + (start % sectors);
+		start = start - (start % sectors) + sectors;
+	}
+	if (size % sectors)
+		size = size - (size % sectors);
+	if (size < 2 * sectors)
+		return (EINVAL);
+
+	if (baseentry->gpe_deleted)
+		bzero(&entry->ent, sizeof(entry->ent));
+
+	KASSERT(baseentry->gpe_start <= start, (__func__));
+	KASSERT(baseentry->gpe_end >= start + size - 1, (__func__));
+	baseentry->gpe_index = (start / sectors) + 1;
+	baseentry->gpe_offset = (off_t)(start + sectors) * pp->sectorsize;
+	baseentry->gpe_start = start;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list