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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to