diff --git a/include/fat.h b/include/fat.h index 37211c7..81892a2 100644 --- a/include/fat.h +++ b/include/fat.h @@ -8,6 +8,7 @@ #include #include //#include +#include "../include/stdio.h" #include //------------------------------------------------------------------------------ @@ -74,7 +75,7 @@ typedef struct fat_t uint32_t sect_per_clust; uint32_t clust_cnt; uint32_t info_sect; - uint32_t fat_sect; + uint32_t fat_sect[2]; uint32_t data_sect; uint32_t root_sect; diff --git a/src/fat.c b/src/fat.c index 5930525..fde4613 100644 --- a/src/fat.c +++ b/src/fat.c @@ -2,11 +2,8 @@ // Copyright (c) 2025, Bjørn Brodtkorb. All rights reserved. //#include -#include "../include/fat.h" -#include "../include/stdio.h" #include "../include/string.h" - -#define NULL 0 +#include "../include/fat.h" //------------------------------------------------------------------------------ #define LIMIT(a, b) ((a) < (b) ? (a) : (b)) @@ -444,6 +441,7 @@ static fat_t* find_fat_volume(const char* path, int len) if (len == it->pathlen && 0 == memcmp(path, it->path, len)) return it; } + return NULL; } @@ -559,7 +557,8 @@ static uint32_t clust_to_sect(fat_t* fat, uint32_t clust) //------------------------------------------------------------------------------ static int get_fat(fat_t* fat, uint32_t clust, uint32_t* res) { - uint32_t sect = fat->fat_sect + clust / 128; + // Assume first FAT is correct + uint32_t sect = fat->fat_sect[0] + clust / 128; uint32_t off = (clust % 128) << 2; int err = move_win(fat, sect); @@ -573,9 +572,9 @@ static int get_fat(fat_t* fat, uint32_t clust, uint32_t* res) } //------------------------------------------------------------------------------ -static int put_fat(fat_t* fat, uint32_t clust, uint32_t val) +static int put_fat_in(fat_t* fat, int idx, uint32_t clust, uint32_t val) { - uint32_t sect = fat->fat_sect + clust / 128; + uint32_t sect = fat->fat_sect[idx] + clust / 128; uint32_t off = 4 * (clust % 128); int err = move_win(fat, sect); @@ -590,6 +589,16 @@ static int put_fat(fat_t* fat, uint32_t clust, uint32_t val) return FAT_ERR_NONE; } +//------------------------------------------------------------------------------ +static int put_fat(fat_t* fat, uint32_t clust, uint32_t val) +{ + int err = put_fat_in(fat, 0, clust, val); + if (err) + return err; + + return put_fat_in(fat, 1, clust, val); +} + //------------------------------------------------------------------------------ static int get_clust_status(fat_t* fat, uint32_t clust) { @@ -643,7 +652,7 @@ static int clust_chain_remove(fat_t* fat, uint32_t clust) if (err) return err; - fat->info_cnt--; + fat->info_cnt++; clust = next; if (status & CLUST_LAST) @@ -942,7 +951,7 @@ static int load_lfn_name(fat_t* fat, dir_t* dir) } //------------------------------------------------------------------------------ -static int dir_search(fat_t* fat, dir_t* dir, const char* name, int len) +static int dir_search(fat_t* fat, dir_t* dir, const char* name, int len, dir_t* start) { dir_rewind(fat, dir); @@ -959,8 +968,15 @@ static int dir_search(fat_t* fat, dir_t* dir, const char* name, int len) if (!dir_ent_is_free(ent)) { + if (start) + { + start->sect = dir->sect; + start->idx = dir->idx; + } + if (dir_ent_is_lfn(ent)) { + err = load_lfn_name(fat, dir); if (err) return err; @@ -1007,9 +1023,11 @@ static int follow_path(dir_t* dir, const char** path) len = subpath_len(str); if (len == 0) return FAT_ERR_PATH; + fat_t* fat = find_fat_volume(str, len); if (!fat) return FAT_ERR_PATH; + str += len; dir->fat = fat; @@ -1037,7 +1055,7 @@ static int follow_path(dir_t* dir, const char** path) if (len == 0) return FAT_ERR_NONE; - err = dir_search(fat, dir, str, len); + err = dir_search(fat, dir, str, len, NULL); if (err) return err; @@ -1184,8 +1202,10 @@ static int get_mbr_partition(fat_t* fat, mbr_part_t* part, int part_num) int err = move_win(fat, 0); if (err) return err; + if (fat->win[510] != 0x55 || fat->win[511] != 0xaa) return FAT_ERR_NOFAT; + *part = ((mbr_part_t*)(fat->win + 446))[part_num]; return FAT_ERR_NONE; } @@ -1238,8 +1258,9 @@ int fat_mount(disk_ops_t* ops, int part_num, fat_t* fat, const char* path) fat->sect_per_clust = bpb->sect_per_clust; fat->clust_cnt = bpb->sect_per_fat_32 * 128; fat->info_sect = part.lba + bpb->info_sect; - fat->fat_sect = part.lba + bpb->res_sect_cnt; - fat->data_sect = fat->fat_sect + bpb->fat_cnt * bpb->sect_per_fat_32; + fat->fat_sect[0] = part.lba + bpb->res_sect_cnt; + fat->fat_sect[1] = fat->fat_sect[0] + bpb->sect_per_fat_32; + fat->data_sect = fat->fat_sect[0] + bpb->fat_cnt * bpb->sect_per_fat_32; fat->root_sect = clust_to_sect(fat, bpb->root_cluster); err = move_win(fat, fat->info_sect); @@ -1258,7 +1279,7 @@ int fat_mount(disk_ops_t* ops, int part_num, fat_t* fat, const char* path) fat->info_last = info->next_free; fat->info_cnt = info->free_cnt; - + int path_len = strlen(path); if (sizeof(fat->path) < path_len) return FAT_ERR_PARAM; @@ -1345,13 +1366,13 @@ int fat_fopen(file_t* file, const char* path, const char* mode) if (len == 0 || path[len]) return FAT_ERR_PATH; - err = dir_search(fat, dir, path, len); + err = dir_search(fat, dir, path, len, NULL); if (err == FAT_ERR_EOF) { if (!create) return FAT_ERR_DENIED; - + // Create a new file uint32_t new; err = clust_chain_create(fat, &new); @@ -1640,8 +1661,9 @@ int fat_unlink(const char* path) return FAT_ERR_PATH; fat_t* fat = dir.fat; + dir_t sdir = dir; - err = dir_search(fat, &dir, path, len); + err = dir_search(fat, &dir, path, len, &sdir); if (err) return err; @@ -1651,8 +1673,23 @@ int fat_unlink(const char* path) if (err) return err; - ent->name[0] = SFN_FREE; - fat->win_dirty = true; + for (;;) + { + err = move_win(fat, sdir.sect); + if (err) + return err; + + dir_ent_t* ent = (dir_ent_t*)(fat->win + sdir.idx); + ent->name[0] = SFN_FREE; + fat->win_dirty = true; + + if (sdir.sect == dir.sect && sdir.idx == dir.idx) + break; + + err = dir_next(fat, &sdir); + if (err) + return err; + } return sync_fat(fat); } @@ -1666,11 +1703,15 @@ int fat_mkdir(const char* path) return err; fat_t* fat = dir.fat; - + int len = subpath_len(path); if (len == 0 || path[len]) return FAT_ERR_PATH; + uint32_t prev = dir.first_clust; + if (prev == 2) // Old cluster is the root directory + prev = 0; + // Create a new directory uint32_t new; err = clust_chain_create(fat, &new); @@ -1704,8 +1745,8 @@ int fat_mkdir(const char* path) memcpy(ent + 1, ent, sizeof(dir_ent_t)); ent[1].name[1] = '.'; - ent[1].clust_hi = dir.first_clust >> 16; - ent[1].clust_lo = dir.first_clust & 0xffff; + ent[1].clust_hi = prev >> 16; + ent[1].clust_lo = prev & 0xffff; err = dir_register(fat, &dir, path, len, FAT_ATTR_DIR, new); if (err)