Date: Tue, 17 Mar 2009 19:38:40 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org Subject: 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 Message-ID: <200903171938.n2HJceUA004503@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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, §ors) != 0 || - sectors < 1 || sectors > 63 || - g_getattr("GEOM::fwheads", cp, &heads) != 0 || - heads < 1 || heads > 255) { + if (g_getattr("GEOM::fwsectors", cp, §ors) != 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 ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903171938.n2HJceUA004503>