From b1b4e8a2872b9093ee70d61bf99bd83f1b3884eb Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Sat, 5 Apr 2025 15:22:09 +0200 Subject: [PATCH] fygue: support cluster chunk list generator for file (needed for the future read() primitive) --- src/fs/fygue/fat/cluster.c | 13 ++++++ src/fs/fygue/fat/fat.h | 13 ++++++ src/fs/fygue/fat/initialize.c | 20 +-------- src/fs/fygue/fat/resolve.c | 78 +++++++++++++++++++++++++++++++---- 4 files changed, 96 insertions(+), 28 deletions(-) diff --git a/src/fs/fygue/fat/cluster.c b/src/fs/fygue/fat/cluster.c index d6d0301..17e6ad7 100644 --- a/src/fs/fygue/fat/cluster.c +++ b/src/fs/fygue/fat/cluster.c @@ -79,3 +79,16 @@ int fygue_fat_cluster_get_sector( } return 0; } + +/* fygue_fat_get_cluster_addr() - get logical sector addr */ +int fygue_fat_cluster_get_addr( + struct fygue_fat *fat, + uintptr_t *addr, + int cluster_id +) { + int sector_id; + + if (fygue_fat_cluster_get_sector(fat, cluster_id, §or_id) != 0) + return -1; + return fygue_fat_sector_get_addr(fat, addr, sector_id); +} diff --git a/src/fs/fygue/fat/fat.h b/src/fs/fygue/fat/fat.h index c321a1b..681a0d1 100644 --- a/src/fs/fygue/fat/fat.h +++ b/src/fs/fygue/fat/fat.h @@ -83,6 +83,12 @@ struct fygue_fat_file int cluster_entry; int attribute; size_t size; + struct { + uintptr_t addr; + size_t size; + int cluster_count; + } *chunk; + int chunk_count; }; /* fygue_fat_resolve: internal resolve information */ @@ -163,6 +169,13 @@ extern int fygue_fat_cluster_get_sector( int *sector_id ); +/* fygue_fat_get_cluster_addr() - get logical sector addr */ +extern int fygue_fat_cluster_get_addr( + struct fygue_fat *fat, + uintptr_t *addr, + int cluster_id +); + /* 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/initialize.c b/src/fs/fygue/fat/initialize.c index e498707..1450594 100644 --- a/src/fs/fygue/fat/initialize.c +++ b/src/fs/fygue/fat/initialize.c @@ -149,25 +149,7 @@ 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; - -#if 0 - rc = fygue_fat_sector_get_addr( - fat, - &fat->FAT0Addr, - fat->FAT0SectorID - ); - if (rc != 0) - return -1; - rc = fygue_fat_sector_get_addr( - fat, - (void*)&fat->FAT1Addr, - fat->FAT1SectorID - ); - if (rc != 0) - return -1; -#endif - rc = fygue_flash_cmap_lsector_get_addr( + int rc = fygue_flash_cmap_lsector_get_addr( &fat->_flash.cmap, &fat->RootAddr, fat->RootSectorID diff --git a/src/fs/fygue/fat/resolve.c b/src/fs/fygue/fat/resolve.c index af458d1..6400c0c 100644 --- a/src/fs/fygue/fat/resolve.c +++ b/src/fs/fygue/fat/resolve.c @@ -1,4 +1,5 @@ #include +#include #include "fat.h" //--- @@ -30,8 +31,70 @@ static int _fygue_path_get_name( return 0; } -/* _fugue_dirent_resolve(): convert found dirent to dir */ -static int _fygue_dirent_resolve( +/* _fygue_dirent_resolve_file(): generate file information + * + * notes + * - assume FAT integrity */ +static int _fygue_dirent_resolve_file( + struct fygue_fat *fat, + struct fygue_fat_file *file, + struct fygue_fat_dirent *dirent +) { + uintptr_t cluster_addr_prev; + uintptr_t cluster_addr; + size_t cluster_size; + int cluster; + void *tmp; + + memset(file, 0x00, sizeof(struct fygue_fat_file)); + file->attribute = dirent->attribute; + file->cluster_entry = dirent->cluster_id; + file->size = dirent->size; + file->chunk = NULL; + file->chunk_count = 0; + + cluster = file->cluster_entry; + cluster_size = fat->SectorSize * fat->SectorPerClus; + while (true) + { + if (fygue_fat_cluster_get_addr(fat, &cluster_addr, cluster) != 0) + goto error; + if (file->chunk_count > 0) { + cluster_addr_prev = file->chunk[file->chunk_count - 1].addr; + cluster_addr_prev += file->chunk[file->chunk_count - 1].size; + if (cluster_addr == cluster_addr_prev) { + file->chunk[file->chunk_count - 1].size += cluster_size; + file->chunk[file->chunk_count - 1].cluster_count += 1; + if (fygue_fat_cluster_get_next(fat, &cluster) != 0) + break; + continue; + } + } + tmp = reallocarray( + file->chunk, + file->chunk_count + 1, + sizeof(*file->chunk) + ); + if (tmp == NULL) + goto error; + file->chunk = tmp; + file->chunk[file->chunk_count].size = cluster_size; + file->chunk[file->chunk_count].addr = cluster_addr; + file->chunk[file->chunk_count].cluster_count = 1; + file->chunk_count += 1; + if (fygue_fat_cluster_get_next(fat, &cluster) != 0) + break; + } + return 0; +error: + if (file->chunk == NULL) + free(file->chunk); + memset(file, 0x00, sizeof(struct fygue_fat_file)); + return -1; +} + +/* _fugue_dirent_resolve_dir(): convert found dirent to dir */ +static int _fygue_dirent_resolve_dir( struct fygue_fat *fat, struct fygue_fat_dir *dir, struct fygue_fat_dirent *dirent @@ -96,13 +159,10 @@ static int _fygue_resolve_set( ) { if (dirent == NULL || (dirent->attribute & FYGUE_FAT_ATTR_DIRECTORY)) { resolve->type = FYGUE_FAT_FILE_TYPE_DIR; - return _fygue_dirent_resolve(fat, &(resolve->dir), dirent); + return _fygue_dirent_resolve_dir(fat, &(resolve->dir), dirent); } resolve->type = FYGUE_FAT_FILE_TYPE_FILE; - resolve->file.attribute = dirent->attribute; - resolve->file.cluster_entry = dirent->cluster_id; - resolve->file.size = dirent->size; - return 0; + return _fygue_dirent_resolve_file(fat, &(resolve->file), dirent); } //--- @@ -134,7 +194,7 @@ int fygue_fat_resolve( while (true) { if (is_root) { - if (_fygue_dirent_resolve(fat, &dir, NULL) != 0) + if (_fygue_dirent_resolve_dir(fat, &dir, NULL) != 0) return -3; if (_fygue_path_get_name(&prefix, &start, &len) != 0) break; @@ -145,7 +205,7 @@ int fygue_fat_resolve( return -4; if (_fygue_path_get_name(&prefix, &start, &len) != 0) break; - if (_fygue_dirent_resolve(fat, &dir, &dirent) != 0) + if (_fygue_dirent_resolve_dir(fat, &dir, &dirent) != 0) return -5; } if (is_root)