diff --git a/CMakeLists.txt b/CMakeLists.txt index a80f886..5ae6bcf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -273,7 +273,7 @@ set(SOURCES src/fs/fygue/fygue_file_close.c src/fs/fygue/fygue_file_read.c src/fs/fygue/fat/cluster.c - src/fs/fygue/fat/initialize.c + src/fs/fygue/fat/fat.c src/fs/fygue/fat/fat_dir_read.c src/fs/fygue/fat/fat_dir_close.c src/fs/fygue/fat/fat_dir_stat.c @@ -285,6 +285,8 @@ set(SOURCES src/fs/fygue/fat/sector.c src/fs/fygue/flash/cluster.c src/fs/fygue/flash/cmap.c + src/fs/fygue/flash/flash.c + src/fs/fygue/flash/sector.c ) set(ASSETS_FX src/font5x7.png src/gdb/icons-i1msb.png) diff --git a/src/fs/fygue/fat/initialize.c b/src/fs/fygue/fat/fat.c similarity index 93% rename from src/fs/fygue/fat/initialize.c rename to src/fs/fygue/fat/fat.c index 1450594..d790337 100644 --- a/src/fs/fygue/fat/initialize.c +++ b/src/fs/fygue/fat/fat.c @@ -2,6 +2,7 @@ ** fygue/fat/initialize - FAT initialization */ #include +#include #include @@ -61,12 +62,7 @@ static int _fygue_fat_sector0(struct fygue_fat *fat) uint8_t *sector; int rc; - rc = fygue_flash_cmap_lsector_get_addr( - &fat->_flash.cmap, - (void*)§or, - 0 - ); - if (rc != 0) + if (fygue_fat_sector_get_addr(fat, (void*)§or, 0) != 0) return -1; fat->SectorHiddenCount = ( (sector[0x1c9] << 24) | @@ -80,8 +76,8 @@ static int _fygue_fat_sector0(struct fygue_fat *fat) (sector[0x1cb] << 8) | (sector[0x1ca] << 0) ); - rc = fygue_flash_cmap_lsector_get_addr( - &fat->_flash.cmap, + rc = fygue_fat_sector_get_addr( + fat, &fat->BPB, fat->SectorHiddenCount ); @@ -149,8 +145,8 @@ static int _fygue_fat_configure(struct fygue_fat *fat) /* _fygue_fat_prepare() - prepare logic information */ static int _fygue_fat_prepare(struct fygue_fat *fat) { - int rc = fygue_flash_cmap_lsector_get_addr( - &fat->_flash.cmap, + int rc = fygue_fat_sector_get_addr( + fat, &fat->RootAddr, fat->RootSectorID ); @@ -169,7 +165,7 @@ int fygue_fat_init_cold(struct fygue_fat *fat) if (fat == NULL) return -1; memset(fat, 0x00, sizeof(struct fygue_fat)); - if (fygue_flash_cmap_init(&fat->_flash.cmap) != 0) + if (fygue_flash_initialize(&(fat->_flash)) != 0) return -2; if ( _fygue_fat_sector0(fat) != 0 || @@ -186,5 +182,6 @@ int fygue_fat_init_hot(struct fygue_fat *fat) { //FIXME: implement (void)fat; + errno = ENOTSUP; return -3; } diff --git a/src/fs/fygue/fat/fat.h b/src/fs/fygue/fat/fat.h index 129ef1b..b33dd11 100644 --- a/src/fs/fygue/fat/fat.h +++ b/src/fs/fygue/fat/fat.h @@ -27,6 +27,7 @@ #define FYGUE_FAT_ATTR_ARCHIVE 0x20 /* fygue_fat - fat information */ +// TODO: rename fields struct fygue_fat { enum { @@ -46,9 +47,7 @@ struct fygue_fat int DataSectorID; uintptr_t RootAddr; uintptr_t BPB; - struct { - struct fygue_flash_cmap cmap; - } _flash; + struct fygue_flash _flash; }; /* fygue_fat_dirent - FAT dirent information */ @@ -176,7 +175,7 @@ extern int fygue_fat_file_close( ); //--- -// Cluster interface +// (internal) Cluster interface //--- /* fygue_fat_cluster_get_next() - find the next cluster ID of a file */ @@ -199,6 +198,10 @@ extern int fygue_fat_cluster_get_addr( int cluster_id ); +//--- +// (internal) Sector interface +//--- + /* fygue_fat_get_sector_addr() - get logical sector addr */ extern int fygue_fat_sector_get_addr( struct fygue_fat *fat, diff --git a/src/fs/fygue/fat/sector.c b/src/fs/fygue/fat/sector.c index cf7ea42..283dd90 100644 --- a/src/fs/fygue/fat/sector.c +++ b/src/fs/fygue/fat/sector.c @@ -13,11 +13,7 @@ int fygue_fat_sector_get_addr( uintptr_t *addr, int sector ) { - if (fat == NULL) - return -1; - return fygue_flash_cmap_lsector_get_addr( - &fat->_flash.cmap, - addr, - sector - ); + if (fat != NULL) + return fygue_flash_sector_get_addr(&(fat->_flash), addr, sector); + return -1; } diff --git a/src/fs/fygue/flash/cluster.c b/src/fs/fygue/flash/cluster.c index 866e72c..d6a5c05 100644 --- a/src/fs/fygue/flash/cluster.c +++ b/src/fs/fygue/flash/cluster.c @@ -42,6 +42,7 @@ struct _bfile_cluster_metadata * -1 if the bfile metadata cannot be validated * 0 otherwise */ static int _fygue_flash_cluster_convert( + struct fygue_flash *flash, struct fygue_flash_cluster *fcluster, uintptr_t bfile_meta ) { @@ -61,53 +62,44 @@ static int _fygue_flash_cluster_convert( 0xbb, 0xbb, 0xdd, 0xdd, 0xdd, 0xee, 0xee, 0xee, }; - struct _bfile_cluster_metadata *meta[2] = { - (void*)(bfile_meta | 0xa0000000), - (void*)(bfile_meta | 0x80000000), - }; + struct _bfile_cluster_metadata *meta; + if (fcluster == NULL) return -1; - for (int i = 0 ; i < 2 ; i++) - { - if ( - meta[i]->signature[0] != 0x5a || - meta[i]->signature[1] != 0x5a || - meta[i]->signature[2] != 0x5a - ) { - continue; - } - if ( - meta[i]->bitmask[0] != 0x88 && - meta[i]->bitmask[0] != 0x22 && - meta[i]->bitmask[0] != 0x11 - ) { - continue; - } - if (meta[i]->bitmask[1] != 0x0f) - continue; - if (meta[i]->bitmask[0] != 0x11 && meta[i]->lcluster_id != 0xffff) - continue; -#if GINT_HW_CP - // on the fxcp400, only some flash sector have the constants used - // in other device. Casio check an CRC that is performed on the - // whole cluster - // TODO: CRC check - (void)_constant1; - (void)_constant2; -#else - if ( - memcmp(&(meta[i]->constant), _constant1, 0x18) != 0 && - memcmp(&(meta[i]->constant), _constant2, 0x18) != 0 - ) { - continue; - } -#endif - fcluster->lcluster_id = meta[i]->lcluster_id; - fcluster->kind = meta[i]->bitmask[0]; - fcluster->version = meta[i]->fcluster_version; - return 0; + meta = (void*)(bfile_meta | 0xa0000000); + if ( + meta->signature[0] != 0x5a || + meta->signature[1] != 0x5a || + meta->signature[2] != 0x5a + ) { + return -2; } - return -2; + if ( + meta->bitmask[0] != 0x88 && + meta->bitmask[0] != 0x22 && + meta->bitmask[0] != 0x11 + ) { + return -3; + } + if (meta->bitmask[1] != 0x0f) + return -4; + if (meta->bitmask[0] != 0x11 && meta->lcluster_id != 0xffff) + return -5; + // on the fxcp400, have only some flash sector with the constants used + // in other device. Internally, on the fxcp400, Casio only perform + // a check an CRC that is performed on the whole cluster + // TODO: CRC check + if ( + flash->integrity == FYGUE_FLASH_INTEGRITY_FULL && + memcmp(&(meta->constant), _constant1, 0x18) != 0 && + memcmp(&(meta->constant), _constant2, 0x18) != 0 + ) { + return -6; + } + fcluster->lcluster_id = meta->lcluster_id; + fcluster->kind = meta->bitmask[0]; + fcluster->version = meta->fcluster_version; + return 0; } //--- @@ -125,14 +117,15 @@ static int _fygue_flash_cluster_convert( * -1 if the provided address is not valid * 0 success */ int fygue_flash_cluster_geometry( + struct fygue_flash *flash, uintptr_t addr, uint16_t *fcluster_id, uint16_t *fsector_id, uint16_t *fcluster_off ) { - if ((addr & 0x0fffffff) < __FYGUE_FSECTOR_START_ADDR) + if ((addr & 0x0fffffff) < flash->geometry.phy_start) return -1; - addr = (addr & 0x0fffffff) - __FYGUE_FSECTOR_START_ADDR; + addr = (addr & 0x0fffffff) - flash->geometry.phy_start; if (fcluster_id != NULL) { *fcluster_id = ((addr & 0xfffe0000) >> 17) * 32; *fcluster_id += ((addr & 0x0001ffff) >> 12); @@ -151,6 +144,7 @@ int fygue_flash_cluster_geometry( * -2 if the provided `fline` have invalid Bfile metadata * 0 if the meta information has been generated */ int fygue_flash_cluster_get( + struct fygue_flash *flash, uint16_t fcluster_id, struct fygue_flash_cluster *fcluster ) { @@ -159,9 +153,9 @@ int fygue_flash_cluster_get( int fsector_id; int fcluster_off; - if (fcluster == NULL) + if (flash == NULL || fcluster == NULL) return -1; - if (fcluster_id >= __FYGUE_FCLUSTER_COUNT) + if (fcluster_id >= flash->geometry.fcluster_count) return -1; fsector_id = fcluster_id / 32; fcluster_off = fcluster_id % 32; @@ -171,13 +165,13 @@ int fygue_flash_cluster_get( fcluster->lcluster_id = 0xffff; fcluster->version = 0xffffffff; } else { - bfile_meta = __FYGUE_FSECTOR_START_ADDR; + bfile_meta = flash->geometry.phy_start; bfile_meta += (fsector_id * 0x20000) + 0x1f000; bfile_meta += (fcluster_off * 0x40); - if (_fygue_flash_cluster_convert(fcluster, bfile_meta) != 0) + if (_fygue_flash_cluster_convert(flash, fcluster, bfile_meta) != 0) return -2; } - bfile_data = __FYGUE_FSECTOR_START_ADDR; + bfile_data = flash->geometry.phy_start; bfile_data += (fsector_id * 0x20000); bfile_data += (fcluster_off * 0x1000); fcluster->data_p1 = bfile_data | 0xa0000000; diff --git a/src/fs/fygue/flash/cmap.c b/src/fs/fygue/flash/cmap.c index 96923a2..ccdfa58 100644 --- a/src/fs/fygue/flash/cmap.c +++ b/src/fs/fygue/flash/cmap.c @@ -97,22 +97,33 @@ static int fygue_flash_cmap_update( * returns: * -1 if the sector 0 is not found * 0 success */ -int fygue_flash_cmap_init(struct fygue_flash_cmap *cmap) -{ +int fygue_flash_cmap_init( + struct fygue_flash *flash, + struct fygue_flash_cmap *cmap +) { struct fygue_flash_cluster fcluster; + int fsector; int rc; - if (cmap == NULL) + if (flash == NULL || cmap == NULL) return -1; - for (int fsector = 0 ; fsector < __FYGUE_FSECTOR_COUNT ; fsector++) - { - if (fygue_flash_cluster_get(fsector * 32, &fcluster) != 0) + memset(cmap, 0x00, sizeof(struct fygue_flash_cmap)); + for ( + fsector = 0 ; + fsector < flash->geometry.fsector_count ; + fsector++ + ) { + if (fygue_flash_cluster_get(flash, fsector * 32, &fcluster) != 0) continue; if (fcluster.kind != 0x22) continue; for (int j = 0 ; j < 31 ; j++) { - rc = fygue_flash_cluster_get((fsector * 32) + j, &fcluster); + rc = fygue_flash_cluster_get( + flash, + (fsector * 32) + j, + &fcluster + ); if (rc != 0) continue; if (fcluster.kind != 0x11) @@ -129,6 +140,7 @@ int fygue_flash_cmap_init(struct fygue_flash_cmap *cmap) /* fygue_flash_cmap_lsector_get_addr() - get logical sector address */ int fygue_flash_cmap_lsector_get_addr( + struct fygue_flash *flash, struct fygue_flash_cmap *cmap, uintptr_t *sector, uint16_t lsector_id @@ -136,7 +148,9 @@ int fygue_flash_cmap_lsector_get_addr( uintptr_t fsector_addr; uint16_t lcluster_id; - if (sector == NULL || cmap == NULL || cmap->lcluster == NULL) + if (flash == NULL || sector == NULL || cmap == NULL) + return -1; + if (cmap->lcluster == NULL) return -1; lcluster_id = lsector_id / 8; if ( diff --git a/src/fs/fygue/flash/flash.c b/src/fs/fygue/flash/flash.c new file mode 100644 index 0000000..63988f2 --- /dev/null +++ b/src/fs/fygue/flash/flash.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include "flash.h" + +//--- +// Internals +//--- + +/* _fygue_flash_hw_detect(): detect flash hardware information + * + * notes + * we cannot easily detect the exact geometry of the flash for the Fugue + * FS. For now, simply pseudo-detect hardware information and setup + * hardcoded information */ +// TODO: support CRC check and try each flash sector until one work ? +// TODO: cluster integrity check seems change between device (?) +static int _fygue_flash_hw_detect(struct fygue_flash *flash) +{ + switch (gint[HWCALC]) + { + case HWCALC_FXCP400: + flash->geometry.phy_start = 0x01a20000; + flash->geometry.fsector_count = 0xf2; + flash->integrity = FYGUE_FLASH_INTEGRITY_PARTIAL; + break; + case HWCALC_G35PE2: + flash->geometry.phy_start = 0x003f0000; + flash->geometry.fsector_count = 0x00; + flash->integrity = FYGUE_FLASH_INTEGRITY_FULL; + break; + case HWCALC_FXCG50: + flash->geometry.phy_start = 0x00c80000; + flash->geometry.fsector_count = 0x9c; + flash->integrity = FYGUE_FLASH_INTEGRITY_FULL; + break; + default: + errno = ENOTSUP; + return -1; + } + flash->geometry.fcluster_count = flash->geometry.fsector_count * 32; + flash->geometry.size = flash->geometry.fsector_count * 0x20000; + flash->geometry.phy_end = flash->geometry.phy_start; + flash->geometry.phy_end += flash->geometry.size; + return 0; +} + +//--- +// Public +//--- + +/* fygue_flash_initialize(): init flash abstraction */ +int fygue_flash_initialize(struct fygue_flash *flash) +{ + if (flash == NULL) + return -1; + memset(flash, 0x00, sizeof(struct fygue_flash)); + if (_fygue_flash_hw_detect(flash) != 0) + return -2; + if (fygue_flash_cmap_init(flash, &(flash->cmap)) != 0) + return -3; + return 0; +} diff --git a/src/fs/fygue/flash/flash.h b/src/fs/fygue/flash/flash.h index 89545d5..0742146 100644 --- a/src/fs/fygue/flash/flash.h +++ b/src/fs/fygue/flash/flash.h @@ -4,18 +4,6 @@ #include #include -/* __FYGUE_* - hardcoded fygue information */ -//FIXME: change between OS version ? -#if GINT_HW_CP -# define __FYGUE_FSECTOR_START_ADDR (0x01a20000) -# define __FYGUE_FSECTOR_COUNT (0xf2) -# define __FYGUE_FCLUSTER_COUNT (__FYGUE_FSECTOR_COUNT * 32) -#else -# define __FYGUE_FSECTOR_START_ADDR (0x00c80000) -# define __FYGUE_FSECTOR_COUNT (0x9c) -# define __FYGUE_FCLUSTER_COUNT (__FYGUE_FSECTOR_COUNT * 32) -#endif - /* fygue_fcluster - generic flash cluster information */ struct fygue_flash_cluster { @@ -45,22 +33,61 @@ struct fygue_flash_cmap int lcluster_id_max; }; -// cluster map interface +struct fygue_flash +{ + struct { + uintptr_t phy_start; + uintptr_t phy_end; + size_t size; + int fsector_count; + int fcluster_count; + } geometry; + enum { + FYGUE_FLASH_INTEGRITY_FULL, + FYGUE_FLASH_INTEGRITY_PARTIAL, + } integrity; + struct fygue_flash_cmap cmap; +}; + +//--- +// (public) Flash interface +//--- + +/* fygue_flash_initialize(): init flash abstraction */ +extern int fygue_flash_initialize(struct fygue_flash *flash); + +/* fygue_flash_sector_get_addr(): return the logical sector address */ +extern int fygue_flash_sector_get_addr( + struct fygue_flash *flash, + uintptr_t *sector_addr, + uint16_t sector_id +); + +//--- +// (internal) cluster map interface +//--- /* fygue_flash_cmap_init() - initialize the fcluster redirection map */ -extern int fygue_flash_cmap_init(struct fygue_flash_cmap *cmap); +extern int fygue_flash_cmap_init( + struct fygue_flash *flash, + struct fygue_flash_cmap *cmap +); /* fygue_flash_cmap_lsector_get_addr() - get logical sector address */ extern int fygue_flash_cmap_lsector_get_addr( + struct fygue_flash *flash, struct fygue_flash_cmap *cmap, uintptr_t *sector, uint16_t lsector_id ); -// cluster interface +//--- +// (internal) cluster interface +//--- /* fygue_flash_cluster_geometry() - get geometry information */ extern int fygue_flash_cluster_geometry( + struct fygue_flash *flash, uintptr_t addr, uint16_t *fcluster_id, uint16_t *fsector_id, @@ -69,6 +96,7 @@ extern int fygue_flash_cluster_geometry( /* fygue_flash_cluster_get() - get cluster information */ extern int fygue_flash_cluster_get( + struct fygue_flash *flash, uint16_t fcluster_id, struct fygue_flash_cluster *fcluster ); diff --git a/src/fs/fygue/flash/sector.c b/src/fs/fygue/flash/sector.c new file mode 100644 index 0000000..1549d8b --- /dev/null +++ b/src/fs/fygue/flash/sector.c @@ -0,0 +1,17 @@ +#include "flash.h" + +/* fygue_flash_sector_get_addr(): return the logical sector address */ +int fygue_flash_sector_get_addr( + struct fygue_flash *flash, + uintptr_t *sector_addr, + uint16_t sector_id +) { + if (flash == NULL || sector_addr == NULL) + return -1; + return fygue_flash_cmap_lsector_get_addr( + flash, + &(flash->cmap), + sector_addr, + sector_id + ); +} diff --git a/src/fs/fygue/fygue.c b/src/fs/fygue/fygue.c index 7932e04..607adb7 100644 --- a/src/fs/fygue/fygue.c +++ b/src/fs/fygue/fygue.c @@ -13,6 +13,7 @@ static struct fygue_fsinfo *__fygue_fsinfo = NULL; // Primitives //--- + /* fygue_mount() - mount (if needed) and return the filesystem information * * notes @@ -21,14 +22,17 @@ int fygue_mount(struct fygue_fsinfo **fsinfo, bool refresh) { if (fsinfo == NULL) return -1; + *fsinfo = NULL; if (__fygue_fsinfo == NULL) { - *fsinfo = NULL; __fygue_fsinfo = calloc(1, sizeof(struct fygue_fsinfo)); if (__fygue_fsinfo == NULL) return -2; - if (fygue_fat_init_cold(&(__fygue_fsinfo->fat)) != 0) + if (fygue_fat_init_cold(&(__fygue_fsinfo->fat)) != 0) { + free(__fygue_fsinfo); + __fygue_fsinfo = NULL; return -3; + } __fygue_fsinfo->dirty = false; } if (refresh && __fygue_fsinfo->dirty) {