fygue: rework flash initialization + fix mount fail behaviour

This commit is contained in:
Yann MAGNIN 2025-04-07 13:29:02 +02:00
parent a56d57ad61
commit fc358c2fb1
No known key found for this signature in database
GPG key ID: D82629D933EADC59
10 changed files with 217 additions and 99 deletions

View file

@ -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)

View file

@ -2,6 +2,7 @@
** fygue/fat/initialize - FAT initialization
*/
#include <string.h>
#include <errno.h>
#include <gint/defs/attributes.h>
@ -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*)&sector,
0
);
if (rc != 0)
if (fygue_fat_sector_get_addr(fat, (void*)&sector, 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;
}

View file

@ -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,

View file

@ -13,11 +13,7 @@ int fygue_fat_sector_get_addr(
uintptr_t *addr,
int sector
) {
if (fat == NULL)
if (fat != NULL)
return fygue_flash_sector_get_addr(&(fat->_flash), addr, sector);
return -1;
return fygue_flash_cmap_lsector_get_addr(
&fat->_flash.cmap,
addr,
sector
);
}

View file

@ -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++)
{
meta = (void*)(bfile_meta | 0xa0000000);
if (
meta[i]->signature[0] != 0x5a ||
meta[i]->signature[1] != 0x5a ||
meta[i]->signature[2] != 0x5a
meta->signature[0] != 0x5a ||
meta->signature[1] != 0x5a ||
meta->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;
}
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;

View file

@ -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 (

View file

@ -0,0 +1,63 @@
#include <string.h>
#include <errno.h>
#include <gint/hardware.h>
#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;
}

View file

@ -4,18 +4,6 @@
#include <gint/defs/types.h>
#include <gint/config.h>
/* __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
);

View file

@ -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
);
}

View file

@ -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) {