mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-17 10:26:15 +00:00
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@
This commit is contained in:
parent
205e85c3e2
commit
0952268ecd
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=184552
@ -50,6 +50,7 @@ struct g_part_apm_table {
|
|||||||
struct g_part_table base;
|
struct g_part_table base;
|
||||||
struct apm_ddr ddr;
|
struct apm_ddr ddr;
|
||||||
struct apm_ent self;
|
struct apm_ent self;
|
||||||
|
int tivo_series1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct g_part_apm_entry {
|
struct g_part_apm_entry {
|
||||||
@ -99,6 +100,19 @@ static struct g_part_scheme g_part_apm_scheme = {
|
|||||||
};
|
};
|
||||||
G_PART_SCHEME_DECLARE(g_part_apm);
|
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
|
static int
|
||||||
apm_parse_type(const char *type, char *buf, size_t bufsz)
|
apm_parse_type(const char *type, char *buf, size_t bufsz)
|
||||||
{
|
{
|
||||||
@ -143,7 +157,8 @@ apm_parse_type(const char *type, char *buf, size_t bufsz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
struct g_provider *pp;
|
||||||
char *buf;
|
char *buf;
|
||||||
@ -153,6 +168,8 @@ apm_read_ent(struct g_consumer *cp, uint32_t blk, struct apm_ent *ent)
|
|||||||
buf = g_read_data(cp, pp->sectorsize * blk, pp->sectorsize, &error);
|
buf = g_read_data(cp, pp->sectorsize * blk, pp->sectorsize, &error);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return (error);
|
return (error);
|
||||||
|
if (tivo_series1)
|
||||||
|
swab(buf, pp->sectorsize);
|
||||||
ent->ent_sig = be16dec(buf);
|
ent->ent_sig = be16dec(buf);
|
||||||
ent->ent_pmblkcnt = be32dec(buf + 4);
|
ent->ent_pmblkcnt = be32dec(buf + 4);
|
||||||
ent->ent_start = be32dec(buf + 8);
|
ent->ent_start = be32dec(buf + 8);
|
||||||
@ -316,6 +333,7 @@ g_part_apm_probe(struct g_part_table *basetable, struct g_consumer *cp)
|
|||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
|
||||||
table = (struct g_part_apm_table *)basetable;
|
table = (struct g_part_apm_table *)basetable;
|
||||||
|
table->tivo_series1 = 0;
|
||||||
pp = cp->provider;
|
pp = cp->provider;
|
||||||
|
|
||||||
/* Sanity-check the provider. */
|
/* Sanity-check the provider. */
|
||||||
@ -323,21 +341,38 @@ g_part_apm_probe(struct g_part_table *basetable, struct g_consumer *cp)
|
|||||||
return (ENOSPC);
|
return (ENOSPC);
|
||||||
|
|
||||||
/* Check that there's a Driver Descriptor Record (DDR). */
|
/* 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);
|
buf = g_read_data(cp, 0L, pp->sectorsize, &error);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return (error);
|
return (error);
|
||||||
table->ddr.ddr_sig = be16dec(buf);
|
if (be16dec(buf) == be16toh(APM_DDR_SIG)) {
|
||||||
table->ddr.ddr_blksize = be16dec(buf + 2);
|
/* Normal Apple DDR */
|
||||||
table->ddr.ddr_blkcount = be32dec(buf + 4);
|
table->ddr.ddr_sig = be16dec(buf);
|
||||||
g_free(buf);
|
table->ddr.ddr_blksize = be16dec(buf + 2);
|
||||||
if (table->ddr.ddr_sig != APM_DDR_SIG)
|
table->ddr.ddr_blkcount = be32dec(buf + 4);
|
||||||
return (ENXIO);
|
g_free(buf);
|
||||||
if (table->ddr.ddr_blksize != pp->sectorsize)
|
if (table->ddr.ddr_blksize != pp->sectorsize)
|
||||||
return (ENXIO);
|
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. */
|
/* 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)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
if (table->self.ent_sig != APM_ENT_SIG)
|
if (table->self.ent_sig != APM_ENT_SIG)
|
||||||
@ -364,7 +399,7 @@ g_part_apm_read(struct g_part_table *basetable, struct g_consumer *cp)
|
|||||||
basetable->gpt_entries = table->self.ent_pmblkcnt - 1;
|
basetable->gpt_entries = table->self.ent_pmblkcnt - 1;
|
||||||
|
|
||||||
for (index = table->self.ent_pmblkcnt - 1; index > 0; index--) {
|
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)
|
if (error)
|
||||||
continue;
|
continue;
|
||||||
if (!strcmp(ent.ent_type, APM_ENT_TYPE_UNUSED))
|
if (!strcmp(ent.ent_type, APM_ENT_TYPE_UNUSED))
|
||||||
@ -414,6 +449,11 @@ g_part_apm_write(struct g_part_table *basetable, struct g_consumer *cp)
|
|||||||
int error, index;
|
int error, index;
|
||||||
|
|
||||||
table = (struct g_part_apm_table *)basetable;
|
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));
|
bzero(buf, sizeof(buf));
|
||||||
|
|
||||||
/* Write the DDR and 'self' entry only when we're newly created. */
|
/* Write the DDR and 'self' entry only when we're newly created. */
|
||||||
|
Loading…
Reference in New Issue
Block a user