int fatfs_fat_add_cluster_to_chain(struct fatfs *fs, UINT32 start_cluster, UINT32 newEntry) { UINT32 last_cluster = FAT32_LAST_CLUSTER; UINT32 next_cluster = start_cluster; if (start_cluster == FAT32_LAST_CLUSTER) return 0; // Loop until end of chain while ( next_cluster != FAT32_LAST_CLUSTER ) { last_cluster = next_cluster; // Find next link next_cluster = fatfs_find_next_cluster(fs, next_cluster); if (!next_cluster) return 0; } // Add link in for new cluster fatfs_fat_set_cluster(fs, last_cluster, newEntry); // Mark new cluster as end of chain fatfs_fat_set_cluster(fs, newEntry, FAT32_LAST_CLUSTER); return 1; }
//----------------------------------------------------------------------------- // fatfs_sector_reader: From the provided startcluster and sector offset // Returns True if success, returns False if not (including if read out of range) //----------------------------------------------------------------------------- int fatfs_sector_reader(struct fatfs *fs, uint32 start_cluster, uint32 offset, uint8 *target) { uint32 sector_to_read = 0; uint32 cluster_to_read = 0; uint32 cluster_chain = 0; uint32 i; uint32 lba; // FAT16 Root directory if (fs->fat_type == FAT_TYPE_16 && start_cluster == 0) { if (offset < fs->rootdir_sectors) lba = fs->lba_begin + fs->rootdir_first_sector + offset; else return 0; } // FAT16/32 Other else { // Set start of cluster chain to initial value cluster_chain = start_cluster; // Find parameters cluster_to_read = offset / fs->sectors_per_cluster; sector_to_read = offset - (cluster_to_read*fs->sectors_per_cluster); // Follow chain to find cluster to read for (i=0; i<cluster_to_read; i++) cluster_chain = fatfs_find_next_cluster(fs, cluster_chain); // If end of cluster chain then return false if (cluster_chain == FAT32_LAST_CLUSTER) return 0; // Calculate sector address lba = fatfs_lba_of_cluster(fs, cluster_chain)+sector_to_read; } // User provided target array if (target) return fs->disk_io.read_media(lba, target, 1); // Else read sector if not already loaded else if (lba != fs->currentsector.address) { fs->currentsector.address = lba; return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1); } else return 1; }
int fatfs_free_cluster_chain(struct fatfs *fs, UINT32 start_cluster) { UINT32 last_cluster; UINT32 next_cluster = start_cluster; // Loop until end of chain while ( (next_cluster != FAT32_LAST_CLUSTER) && (next_cluster != 0x00000000) ) { last_cluster = next_cluster; // Find next link next_cluster = fatfs_find_next_cluster(fs, next_cluster); // Clear last link fatfs_fat_set_cluster(fs, last_cluster, 0x00000000); } return 1; }
int fatfs_sector_reader(struct fatfs *fs, uint32 start_cluster, uint32 offset, uint8 *target) { uint32 sector_to_read = 0; uint32 cluster_to_read = 0; uint32 cluster_chain = 0; uint32 i; uint32 lba; // Set start of cluster chain to initial value cluster_chain = start_cluster; // Find parameters cluster_to_read = offset / fs->sectors_per_cluster; sector_to_read = offset - (cluster_to_read*fs->sectors_per_cluster); // Follow chain to find cluster to read for (i=0; i<cluster_to_read; i++) cluster_chain = fatfs_find_next_cluster(fs, cluster_chain); // If end of cluster chain then return false if (cluster_chain == FAT32_LAST_CLUSTER) return 0; // Calculate sector address lba = fatfs_lba_of_cluster(fs, cluster_chain)+sector_to_read; // User provided target array if (target) return media_read_ak(lba, target, 512); // Else read sector if not already loaded else if (lba != fs->currentsector.address) { fs->currentsector.address = lba; return media_read_ak(fs->currentsector.address, fs->currentsector.sector, 512); } else return 1; }
static int _write_sector(FL_FILE* file, UINT32 offset, unsigned char *buf) { UINT32 SectorNumber = 0; UINT32 ClusterIdx = 0; UINT32 Cluster = 0; UINT32 LastCluster = FAT32_LAST_CLUSTER; UINT32 i; // Find values for Cluster index & sector within cluster ClusterIdx = offset / _fs.sectors_per_cluster; SectorNumber = offset - (ClusterIdx * _fs.sectors_per_cluster); // Quick lookup for next link in the chain if (ClusterIdx == file->last_fat_lookup.ClusterIdx) Cluster = file->last_fat_lookup.CurrentCluster; // Else walk the chain else { // Starting from last recorded cluster? if (ClusterIdx && ClusterIdx == file->last_fat_lookup.ClusterIdx + 1) { i = file->last_fat_lookup.ClusterIdx; Cluster = file->last_fat_lookup.CurrentCluster; } // Start searching from the beginning.. else { // Set start of cluster chain to initial value i = 0; Cluster = file->startcluster; } // Follow chain to find cluster to read for ( ;i<ClusterIdx; i++) { UINT32 nextCluster; // Does the entry exist in the cache? if (!fatfs_cache_get_next_cluster(&_fs, file, i, &nextCluster)) { // Scan file linked list to find next entry nextCluster = fatfs_find_next_cluster(&_fs, Cluster); // Push entry into cache fatfs_cache_set_next_cluster(&_fs, file, i, nextCluster); } LastCluster = Cluster; Cluster = nextCluster; // Dont keep following a dead end if (Cluster == FAT32_LAST_CLUSTER) break; } // If we have reached the end of the chain, allocate more! if (Cluster == FAT32_LAST_CLUSTER) { // Add another cluster to the last good cluster chain if (!fatfs_add_free_space(&_fs, &LastCluster)) return 0; Cluster = LastCluster; } // Record current cluster lookup details file->last_fat_lookup.CurrentCluster = Cluster; file->last_fat_lookup.ClusterIdx = ClusterIdx; } return fatfs_write_sector(&_fs, Cluster, SectorNumber, buf); }
//----------------------------------------------------------------------------- // _read_sector: Read a sector from disk to file //----------------------------------------------------------------------------- static int _read_sector(FL_FILE* file, UINT32 offset) { UINT32 Sector = 0; UINT32 ClusterIdx = 0; UINT32 Cluster = 0; UINT32 i; UINT32 lba; // Find cluster index within file & sector with cluster ClusterIdx = offset / _fs.sectors_per_cluster; Sector = offset - (ClusterIdx * _fs.sectors_per_cluster); // Quick lookup for next link in the chain if (ClusterIdx == file->last_fat_lookup.ClusterIdx) Cluster = file->last_fat_lookup.CurrentCluster; // Else walk the chain else { // Starting from last recorded cluster? if (ClusterIdx && ClusterIdx == file->last_fat_lookup.ClusterIdx + 1) { i = file->last_fat_lookup.ClusterIdx; Cluster = file->last_fat_lookup.CurrentCluster; } // Start searching from the beginning.. else { // Set start of cluster chain to initial value i = 0; Cluster = file->startcluster; } // Follow chain to find cluster to read for ( ;i<ClusterIdx; i++) { UINT32 nextCluster; // Does the entry exist in the cache? if (!fatfs_cache_get_next_cluster(&_fs, file, i, &nextCluster)) { // Scan file linked list to find next entry nextCluster = fatfs_find_next_cluster(&_fs, Cluster); // Push entry into cache fatfs_cache_set_next_cluster(&_fs, file, i, nextCluster); } Cluster = nextCluster; } // Record current cluster lookup details (if valid) if (Cluster != FAT32_LAST_CLUSTER) { file->last_fat_lookup.CurrentCluster = Cluster; file->last_fat_lookup.ClusterIdx = ClusterIdx; } } // If end of cluster chain then return false if (Cluster == FAT32_LAST_CLUSTER) return 0; // Calculate sector address lba = fatfs_lba_of_cluster(&_fs, Cluster) + Sector; // Read sector of file return fatfs_sector_read(&_fs, lba, file->file_data.sector); }