fygue: rework flash abstraction to reduce device-specific cases and allow future optimization

This commit is contained in:
Yann MAGNIN 2025-04-08 19:03:47 +02:00
parent 8156c8437b
commit ba7d84dbb2
No known key found for this signature in database
GPG key ID: D82629D933EADC59
4 changed files with 106 additions and 90 deletions

View file

@ -48,8 +48,9 @@ uintptr_t debug_meta = 0;
static int _fygue_flash_cluster_convert( static int _fygue_flash_cluster_convert(
struct fygue_flash *flash, struct fygue_flash *flash,
struct fygue_flash_cluster *fcluster, struct fygue_flash_cluster *fcluster,
uintptr_t bfile_meta uintptr_t meta
) { ) {
#if 0
static const uint8_t _constant1[] = { static const uint8_t _constant1[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@ -66,44 +67,49 @@ static int _fygue_flash_cluster_convert(
0xbb, 0xbb, 0xdd, 0xdd, 0xbb, 0xbb, 0xdd, 0xdd,
0xdd, 0xee, 0xee, 0xee, 0xdd, 0xee, 0xee, 0xee,
}; };
struct _bfile_cluster_metadata *meta; #endif
struct _bfile_cluster_metadata *bfile_meta;
if (fcluster == NULL) if (flash == NULL || fcluster == NULL)
return -1; return -1;
debug_meta = bfile_meta; bfile_meta = (void*)(meta | 0xa0000000);
meta = (void*)(bfile_meta | 0xa0000000);
if ( if (
meta->signature[0] != 0x5a || bfile_meta->signature[0] != 0x5a ||
meta->signature[1] != 0x5a || bfile_meta->signature[1] != 0x5a ||
meta->signature[2] != 0x5a bfile_meta->signature[2] != 0x5a
) { ) {
return -2; return -2;
} }
if ( if (
meta->bitmask[0] != 0x88 && bfile_meta->bitmask[0] != 0x88 &&
meta->bitmask[0] != 0x22 && bfile_meta->bitmask[0] != 0x22 &&
meta->bitmask[0] != 0x11 bfile_meta->bitmask[0] != 0x11
) { ) {
return -3; return -3;
} }
if (meta->bitmask[1] != 0x0f) if (bfile_meta->bitmask[1] != 0x0f)
return -4; return -4;
if (meta->bitmask[0] != 0x11 && meta->lcluster_id != 0xffff) if (
bfile_meta->bitmask[0] != 0x11 &&
bfile_meta->lcluster_id != 0xffff
) {
return -5; return -5;
}
// on the fxcp400, have only some flash sector with the constants used // on the fxcp400, have only some flash sector with the constants used
// in other device. Internally, on the fxcp400, Casio only perform // in other device. Internally, on the fxcp400, Casio only perform
// a check an CRC that is performed on the whole cluster // a check an CRC that is performed on the whole cluster
// TODO: CRC check // TODO: CRC check
#if 0
if ( if (
flash->integrity == FYGUE_FLASH_INTEGRITY_FULL && memcmp(&(bfile_meta->constant), _constant1, 0x18) != 0 &&
memcmp(&(meta->constant), _constant1, 0x18) != 0 && memcmp(&(bfile_meta->constant), _constant2, 0x18) != 0
memcmp(&(meta->constant), _constant2, 0x18) != 0
) { ) {
return -6; return -6;
} }
fcluster->lcluster_id = meta->lcluster_id; #endif
fcluster->kind = meta->bitmask[0]; fcluster->lcluster_id = bfile_meta->lcluster_id;
fcluster->version = meta->fcluster_version; fcluster->kind = bfile_meta->bitmask[0];
fcluster->version = bfile_meta->fcluster_version;
return 0; return 0;
} }
@ -146,8 +152,11 @@ static int _fygue_flash_cluster_meta(
* sector of 64ko merge the details sector inside the metadata cluster to * sector of 64ko merge the details sector inside the metadata cluster to
* keep some space which is not the case with the FXCP400 or CG50 that * keep some space which is not the case with the FXCP400 or CG50 that
* use 128ko flash sector and which the first cluster should be a details * use 128ko flash sector and which the first cluster should be a details
* one type. */ * one type.
//TODO: remove device-specific code *
* for 64k cluster the 0xf3c0 offset can be calculated as:
* 0x10000 - (8*512) = 0xf000 | sector size minus cluster size
* 15 * 0x40 = 0x3c0 | skip all data cluster meta info */
static int _fygue_flash_cluster_details( static int _fygue_flash_cluster_details(
struct fygue_flash *flash, struct fygue_flash *flash,
struct fygue_flash_cluster *fcluster, struct fygue_flash_cluster *fcluster,
@ -159,21 +168,18 @@ static int _fygue_flash_cluster_details(
uintptr_t data; uintptr_t data;
memset(fcluster, 0x00, sizeof(struct fygue_flash_cluster)); memset(fcluster, 0x00, sizeof(struct fygue_flash_cluster));
if (gint[HWCALC] == HWCALC_G35PE2) { if (geometry->fsector_size == FYGUE_FSECTOR_SIZE_64K) {
data = ( data = (
(geometry->phy_start | 0xa0000000) + (geometry->phy_start | 0xa0000000) +
(fsector_id * geometry->fsector_size) + (fsector_id * 0x10000) +
(geometry->fsector_size - (8*512)) + (0xf3c0)
((geometry->fcluster_per_fsector - 1) * 0x40)
); );
meta = data + 512; meta = data + 512;
} else { } else {
data = ( data = (geometry->phy_start | 0xa0000000) + (fsector_id * 0x20000);
(geometry->phy_start | 0xa0000000) + meta = data + 0x1f000;
(fsector_id * geometry->fsector_size)
);
meta = data + (geometry->fsector_size) - (8*512);
} }
debug_meta = meta;
if (_fygue_flash_cluster_convert(flash, fcluster, meta) != 0) if (_fygue_flash_cluster_convert(flash, fcluster, meta) != 0)
return -1; return -1;
if (fcluster->version != 0xffffffff) if (fcluster->version != 0xffffffff)
@ -208,20 +214,33 @@ static int _fygue_flash_cluster_data(
uintptr_t meta; uintptr_t meta;
uintptr_t data; uintptr_t data;
if (geometry->fsector_size == FYGUE_FSECTOR_SIZE_64K) {
data = ( data = (
(geometry->phy_start | 0xa0000000) + (geometry->phy_start | 0xa0000000) +
(fsector_id * geometry->fsector_size) + (fsector_id * 0x10000) +
(fcluster_off * (8 * 512)) (fcluster_off * (8 * 512))
); );
meta = ( meta = (
(geometry->phy_start | 0xa0000000) + (geometry->phy_start | 0xa0000000) +
(fsector_id * geometry->fsector_size) + (fsector_id * 0x10000) +
(geometry->fsector_size - (8 * 512)) + (0xf000) +
(fcluster_off * 0x40) (fcluster_off * 0x40)
); );
int rc = _fygue_flash_cluster_convert(flash, fcluster, meta); } else {
if (rc != 0) data = (
return rc; (geometry->phy_start | 0xa0000000) +
(fsector_id * 0x20000) +
(fcluster_off * (8 * 512))
);
meta = (
(geometry->phy_start | 0xa0000000) +
(fsector_id * 0x20000) +
(0x1f000) +
(fcluster_off * 0x40)
);
}
if (_fygue_flash_cluster_convert(flash, fcluster, meta) != 0)
return -1;
fcluster->data_addr = data; fcluster->data_addr = data;
fcluster->meta_addr = meta; fcluster->meta_addr = meta;
fcluster->fcluster_id = fcluster_id; fcluster->fcluster_id = fcluster_id;
@ -247,6 +266,7 @@ int fygue_flash_cluster_get(
struct fygue_flash_cluster *fcluster, struct fygue_flash_cluster *fcluster,
int fcluster_id int fcluster_id
) { ) {
GAUTOTYPE geometry = &(flash->geometry);
int fsector_id; int fsector_id;
int fcluster_off; int fcluster_off;
int nb_entry; int nb_entry;
@ -256,14 +276,20 @@ int fygue_flash_cluster_get(
if (fcluster_id >= flash->geometry.fcluster_count) if (fcluster_id >= flash->geometry.fcluster_count)
return -1; return -1;
nb_entry = flash->geometry.fcluster_per_fsector; if (geometry->fsector_size == FYGUE_FSECTOR_SIZE_64K) {
fsector_id = fcluster_id / nb_entry; nb_entry = 16;
fcluster_off = fcluster_id % nb_entry; fsector_id = fcluster_id / 16;
fcluster_off = fcluster_id % 16;
} else {
nb_entry = 32;
fsector_id = fcluster_id / 32;
fcluster_off = fcluster_id % 32;
}
if (fcluster_off == (nb_entry - 1))
return _fygue_flash_cluster_meta(flash, fcluster, fsector_id);
if (fcluster_off == 0) if (fcluster_off == 0)
return _fygue_flash_cluster_details(flash, fcluster, fsector_id); return _fygue_flash_cluster_details(flash, fcluster, fsector_id);
if (fcluster_off == (nb_entry - 1))
return _fygue_flash_cluster_meta(flash, fcluster, fsector_id);
return _fygue_flash_cluster_data( return _fygue_flash_cluster_data(
flash, flash,
fcluster, fcluster,

View file

@ -78,8 +78,6 @@ static int fygue_flash_cmap_update(
// Public // Public
//--- //---
int debug_count = 0;
/* fygue_flash_cmap_init() - initialize fcluster translation /* fygue_flash_cmap_init() - initialize fcluster translation
* *
* notes: * notes:
@ -122,7 +120,6 @@ int fygue_flash_cmap_init(
continue; continue;
if (fcluster.kind != 0x22) if (fcluster.kind != 0x22)
continue; continue;
debug_count += 1;
for (j = 1 ; j < (flash->geometry.fcluster_per_fsector - 1) ; j++) for (j = 1 ; j < (flash->geometry.fcluster_per_fsector - 1) ; j++)
{ {
rc = fygue_flash_cluster_get(flash, &fcluster, fsector_id + j); rc = fygue_flash_cluster_get(flash, &fcluster, fsector_id + j);

View file

@ -1,6 +1,7 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <gint/hardware.h> #include <gint/hardware.h>
#include <gint/defs/util.h>
#include "flash.h" #include "flash.h"
//--- //---
@ -13,52 +14,46 @@
* we cannot easily detect the exact geometry of the flash for the Fugue * we cannot easily detect the exact geometry of the flash for the Fugue
* FS. For now, simply pseudo-detect hardware information and setup * FS. For now, simply pseudo-detect hardware information and setup
* hardcoded information */ * hardcoded information */
// TODO: support CRC check and try each flash sector until one work ?
// TODO: cluster integrity check seems change between device (?)
int _fygue_flash_hw_detect(struct fygue_flash *flash) int _fygue_flash_hw_detect(struct fygue_flash *flash)
{ {
GAUTOTYPE geometry = &(flash->geometry);
switch (gint[HWCALC]) switch (gint[HWCALC])
{ {
case HWCALC_FXCP400: case HWCALC_FXCP400:
flash->geometry.phy_start = 0x01a20000; geometry->phy_start = 0x01a20000;
flash->geometry.fsector_count = 0xf2; geometry->fsector_size = FYGUE_FSECTOR_SIZE_128K;
flash->geometry.fcluster_per_fsector = 32; geometry->fsector_count = 0xf2;
flash->integrity = FYGUE_FLASH_INTEGRITY_PARTIAL;
break; break;
case HWCALC_G35PE2: case HWCALC_G35PE2:
flash->geometry.phy_start = 0x003f0000; geometry->phy_start = 0x003f0000;
flash->geometry.fsector_count = 0x41; geometry->fsector_size = FYGUE_FSECTOR_SIZE_64K;
flash->geometry.fcluster_per_fsector = 16; geometry->fsector_count = 0x41;
flash->integrity = FYGUE_FLASH_INTEGRITY_PARTIAL;
break; break;
case HWCALC_FXCG50: case HWCALC_FXCG50:
flash->geometry.phy_start = 0x00c80000; geometry->phy_start = 0x00c80000;
flash->geometry.fsector_count = 0x9c; geometry->fsector_count = 0x9c;
flash->geometry.fcluster_per_fsector = 32; geometry->fsector_size = FYGUE_FSECTOR_SIZE_128K;
flash->integrity = FYGUE_FLASH_INTEGRITY_FULL;
break; break;
case HWCALC_FXCG100: case HWCALC_FXCG100:
flash->geometry.phy_start = 0x00bc0000; geometry->phy_start = 0x00bc0000;
flash->geometry.fsector_count = 0x26; geometry->fsector_size = FYGUE_FSECTOR_SIZE_128K;
flash->geometry.fcluster_per_fsector = 32; geometry->fsector_count = 0x26;
flash->integrity = FYGUE_FLASH_INTEGRITY_PARTIAL;
break; break;
default: default:
errno = ENOTSUP; errno = ENOTSUP;
return -1; return -1;
} }
flash->geometry.fcluster_count = ( if (geometry->fsector_size == FYGUE_FSECTOR_SIZE_128K) {
flash->geometry.fsector_count * flash->geometry.fcluster_per_fsector geometry->size = geometry->fsector_count * 0x20000;
); geometry->fcluster_count = geometry->fsector_count * 32;
flash->geometry.fsector_size = ( geometry->fcluster_per_fsector = 32;
flash->geometry.fcluster_per_fsector * (8 * 512) } else {
); geometry->size = geometry->fsector_count * 0x10000;
flash->geometry.size = ( geometry->fcluster_count = geometry->fsector_count * 16;
flash->geometry.fsector_count * flash->geometry.fsector_size geometry->fcluster_per_fsector = 16;
); }
flash->geometry.phy_end = ( geometry->phy_end = geometry->phy_start + geometry->size;
flash->geometry.phy_start + flash->geometry.size
);
return 0; return 0;
} }
@ -74,8 +69,7 @@ int fygue_flash_initialize(struct fygue_flash *flash)
memset(flash, 0x00, sizeof(struct fygue_flash)); memset(flash, 0x00, sizeof(struct fygue_flash));
if (_fygue_flash_hw_detect(flash) != 0) if (_fygue_flash_hw_detect(flash) != 0)
return -2; return -2;
int rc = fygue_flash_cmap_init(flash, &(flash->cmap)); if (fygue_flash_cmap_init(flash, &(flash->cmap)) != 0)
if (rc != 0) return -3;
return rc;
return 0; return 0;
} }

View file

@ -44,15 +44,14 @@ struct fygue_flash
uintptr_t phy_start; uintptr_t phy_start;
uintptr_t phy_end; uintptr_t phy_end;
size_t size; size_t size;
enum {
FYGUE_FSECTOR_SIZE_64K,
FYGUE_FSECTOR_SIZE_128K,
} fsector_size;
int fsector_count; int fsector_count;
size_t fsector_size;
int fcluster_per_fsector; int fcluster_per_fsector;
int fcluster_count; int fcluster_count;
} geometry; } geometry;
enum {
FYGUE_FLASH_INTEGRITY_FULL,
FYGUE_FLASH_INTEGRITY_PARTIAL,
} integrity;
struct fygue_flash_cmap cmap; struct fygue_flash_cmap cmap;
}; };