Date: Sun, 2 Nov 2008 03:02:56 +0000 (UTC) From: Warner Losh <imp@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r184552 - head/sys/geom/part Message-ID: <200811020302.mA232uDa027133@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: imp Date: Sun Nov 2 03:02:56 2008 New Revision: 184552 URL: http://svn.freebsd.org/changeset/base/184552 Log: Add support for reading Tivo Series 1 partitioning. This likely needs a little refinement, but is good enough to commit as is. # Should look to see if I should move swab(3) into the kernel or just # provide the unoptimized routine here. Reviewed by: marcel@ Modified: head/sys/geom/part/g_part_apm.c Modified: head/sys/geom/part/g_part_apm.c ============================================================================== --- head/sys/geom/part/g_part_apm.c Sun Nov 2 03:00:36 2008 (r184551) +++ head/sys/geom/part/g_part_apm.c Sun Nov 2 03:02:56 2008 (r184552) @@ -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 { @@ -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); @@ -316,6 +333,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. */ @@ -323,21 +341,38 @@ g_part_apm_probe(struct g_part_table *ba return (ENOSPC); /* Check that there's a Driver Descriptor Record (DDR). */ - /* XXX Tivo APM drives do not have a DDR */ 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) @@ -364,7 +399,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)) @@ -414,6 +449,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. */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811020302.mA232uDa027133>