www.pudn.com > UDiskFileSystem.rar > FAT.c
#include#include #include "fat.h" #include "fattime.h" #include "HAL.h" #include "global.h" #ifdef FOR_WIN #include "UFI_Layer.h" #else #include "2410lib.h" #define printf Uart_Printf #endif // globals variable // This buffer is used to put data read from NANDFlash u_8 SECTOR_BUFFER_ADDR[512]; // This buffer is used to put the fat data read from NANDFlash u_8 FAT_CACHE_ADDR[512]; u_8 *SectorBuffer = (u_8 *) SECTOR_BUFFER_ADDR; // Sector Buffer address u_8 *FatCache = (u_8 *) FAT_CACHE_ADDR; // Fat Buffer address char VolLabel[12] = {0}; // Volume Label u_8 DiskIndex; struct partrecord PartInfo; // Partition Information TFILE File; // File Information u_32 FSInfo; // File System Information u_8 Fat32Enabled; // Indicates if is FAT32 or FAT16 u_32 FirstDataSector; // First Data Sector Address , the first sector of cluster 2 . u_16 SectorsPerCluster; // Number of Sectors per Cluster u_32 FirstFATSector; // First FAT Sector Address u_32 FirstFAT2Sector; // First FAT2 Sector Address u_32 FirstDirCluster; // Root Directory Cluster Address u_32 RootDirSectors; // Justin add for The count of sectors occupied by the root directory for FAT16 u_32 FatInCache = 0xFFFFFFFF; // Address of the FAT Cluster in FatCache u_32 FatSectors; // Number of FAT Sectors u_32 currentDirCluster; // Actual Dir Cluster Number u_32 NumClusters; // NANDFlash Cluster Numbers u_32 SectorInCache = 0xFFFFFFFF; // Address of the Sector Cluster in SectorBuffer //Some compiler doesn't have this non-ansi C function , //It is for fatNormalize() use. char * MX_strupr (char *a) { char *ret = a; while (*ret != 0) { if ((0x61 <= *ret) && (*ret <= 0x7A)) { *ret = *ret - 0x20; } ret+=1; } return ret; } //***************************************************************************** // Function: fatClustToSect // Parameters: cluster // Returns: sector // // Description: Converts Sectors in Clusters //***************************************************************************** u_32 fatClustToSect(u_32 clust) { //if (clust == 0) // clust=2; //Justin modify for FAT16 if (Fat32Enabled) { if (clust == 0) clust=2; } else { if (clust == 0) return FirstDataSector - RootDirSectors; } return ((clust-2) * SectorsPerCluster) + FirstDataSector; } //***************************************************************************** // Function: fatInit // Parameters: none // Returns: 0 if a FAT drive was found, FALSE otherwise // // Description: Get FAT info from NANDFlash and initialize internal variables //***************************************************************************** u_8 fatInit(u_8 index) { struct bpb710 *bpb; u_32 TotalSectors; //Total sectors of this Volume u_8 i,j=0; DiskIndex = index; PartInfo.prStartLBA = 0;//Boot Sector Start LBA if(HAL_ReadSector( DiskIndex, PartInfo.prStartLBA, SectorBuffer, &SectorInCache )) return 1; for(i=0;i<512;i++) { if(i%16==0) { printf("\n"); j++; } if(j==7) break; printf("%2x ",SectorBuffer[i]); } bpb = (struct bpb710 *) ((struct bootsector710 *) SectorBuffer)->bsBPB; // setup global disk constants FirstDataSector = PartInfo.prStartLBA; if(bpb->bpbFATsecs) { FatSectors = bpb->bpbFATsecs; } else { FatSectors = bpb->bpbBigFATsecs; } RootDirSectors = ((bpb->bpbRootDirEnts * 32) + (bpb->bpbBytesPerSec -1))/bpb->bpbBytesPerSec; FirstDataSector += (bpb->bpbResSectors + bpb->bpbFATs * FatSectors) + RootDirSectors; //FirstDataSector += (bpb->bpbResSectors + bpb->bpbFATs * FatSectors) ; if(bpb->bpbSectors) { TotalSectors = bpb->bpbSectors; } else { TotalSectors = bpb->bpbHugeSectors; } // bpb->bpbSecPerClust=1; printf("bpb->bpbSecPerClust=%d\n\n",bpb->bpbSecPerClust); NumClusters = (TotalSectors - (bpb->bpbResSectors + (bpb->bpbFATs * FatSectors) + RootDirSectors))/ bpb->bpbSecPerClust; printf("aaaa\n\n"); //FAT Type Determination by count of Clusters if(NumClusters < 4085) { PartInfo.prPartType = PART_TYPE_FAT12; } else if(NumClusters < 65525) { PartInfo.prPartType = PART_TYPE_FAT16; } else { PartInfo.prPartType = PART_TYPE_FAT32; } SectorsPerCluster = bpb->bpbSecPerClust; printf("SectorsPerCluster = %d\n",SectorsPerCluster); FirstFATSector = bpb->bpbResSectors + PartInfo.prStartLBA; switch (PartInfo.prPartType) { case PART_TYPE_FAT16: FirstDirCluster = 0;//first legal cluster number for FAT16 , the First Data Cluster is 2 , the Root Entry is fixed Fat32Enabled = FALSE; break; case PART_TYPE_FAT32: FirstDirCluster = bpb->bpbRootClust; Fat32Enabled = TRUE; break; default: //Found: No Partition! return 1; } printf("bbb\n\n"); if (Fat32Enabled) { FirstFAT2Sector=FirstFATSector+bpb->bpbBigFATsecs; // initialize Volume Label memcpy(&VolLabel, (u_8*)(bpb->bpbVolLabel), 11); VolLabel[11]='\0'; } else { FirstFAT2Sector=FirstFATSector+bpb->bpbFATsecs; } FSInfo=bpb->bpbFSInfo+PartInfo.prStartLBA; currentDirCluster= FirstDirCluster; return 0; } //***************************************************************************** // Function: fatNextCluster // Parameters: cluster // Returns: the next cluster // // Description: Find next cluster in the FAT chain //***************************************************************************** u_32 fatNextCluster(u_32 cluster) { u_32 nextCluster; u_32 fatMask; u_32 fatOffset; u_32 sector; u_32 offset; // get fat offset in bytes if(Fat32Enabled) { // four FAT bytes (32 bits) for every cluster fatOffset = cluster << 2; // set the FAT bit mask fatMask = FAT32_MASK; } else { // two FAT bytes (16 bits) for every cluster fatOffset = cluster << 1; // set the FAT bit mask fatMask = FAT16_MASK; } // calculate the FAT sector that we're interested in sector = FirstFATSector + (fatOffset / BYTES_PER_SECTOR); // calculate offset of the our entry within that FAT sector offset = fatOffset % BYTES_PER_SECTOR; // if we don't already have this FAT chunk loaded, go get it //Justin modify on 20060518 if(sector != FatInCache) { //printf("\nFAT chunk loaded\n"); HAL_ReadSector( DiskIndex, sector, (u_8*)FAT_CACHE_ADDR, &FatInCache); } // read the nextCluster value nextCluster = (*((u_32*) &((char*)FAT_CACHE_ADDR)[offset])) & fatMask; // check to see if we're at the end of the chain if (nextCluster == (CLUST_EOFE & fatMask)) nextCluster = 0; return nextCluster; } //***************************************************************************** // Function: fatGetFileInfo // Parameters: address of direntry struct, short name of the file // Returns: On SUSCEFULL, return the direntry struct filled out with the file info, // otherwise returns NULL; // // Description: return the direntry struct of a short name file given // this function will search for a filename only in the current // directory, given by currentDirCluster //***************************************************************************** struct direntry *fatGetFileInfo(struct direntry *rde, char *shortName) { u_32 sector=0, cluster; struct direntry *de; u_16 index, isetor; char Name[13]; strncpy(Name, shortName,12); Name[12]='\0'; fatNormalize(Name); // adjust the name to the FAT format cluster= currentDirCluster; // start the search in the current cluster do { for (isetor=0; isetor< SectorsPerCluster; isetor++) // clusters { // read dir data sector = fatClustToSect(cluster) + (u_32)isetor; HAL_ReadSector( DiskIndex, sector, SectorBuffer, &SectorInCache); de = (struct direntry *) SectorBuffer; for (index=1; index<=FAT_DIRENTRIES_PER_SECTOR; index++) { if (*de->deName == 0x00) { return NULL; // there is no more direntries } if((*de->deName != SLOT_DELETED) && (de->deAttributes != ATTR_LONG_FILENAME)) { if (strncmp((const char*)(de->deName), Name, 11) == 0) { memcpy((u_8*)rde, (u_8*)de, DIRENTRY_SIZE); return(de); } } de++; } // end of sector } // end of cluster cluster= fatNextCluster(cluster); }while (sector < FirstFATSector+FatSectors); // end of FatDirentries return NULL; } //***************************************************************************** // Function: fatNormalize // Parameters: file name to be normalized // Returns: the normalized file name // // Description: normalize the file name. Insert spaces betwen the name and the extension. // The file name will be 11 caracters //***************************************************************************** void fatNormalize(char *str_dest) { u_8 o=0, d=0; char str_ori[12]; strncpy(str_ori, str_dest, 12); if (str_ori[0] == '.') // if the file name is "." or ".." { d=1; if (str_ori[1] == '.') d=2; for (;d<11; d++) str_dest[d]=' '; // complete with spaces str_dest[11]='\0'; return; // finish } for (d=0; d<8; d++) // for all the other file name { if (str_ori[o] == '.') // if we found the '.' { o++; break; // break the loop } if (str_ori[o] == '\0') // if we find the file name end break; // break the loop str_dest[d]= str_ori[o++]; } for (; d<8; d++) // complete the eight caracters file name with spaces str_dest[d]= ' '; if (str_ori[o]=='.') // eliminate the '.' o++; for (; d<11; d++) // copy the extension { if (str_ori[o] == '\0') break; str_dest[d]= str_ori[o++]; } for (; d<11; d++) // complete the three caracters extension file name with spaces str_dest[d]= ' '; MX_strupr(str_dest); str_dest[11]='\0'; } //***************************************************************************** // Function: fatFcreate // Parameters: File short name // Returns: A TFILE struct filled with the created file information, or NULL // if an error has ocurred // // Description: Create a file and open it in the current directory TFILE* fatFcreate(char *shortName) { struct direntry *de, rde; u_32 freeCluster, newDirEntrySector, lastCluster; u_16 date, time; char string[12]; TTime t; // if the file already exist if (fatGetFileInfo(&rde, shortName) != NULL) return NULL; // Find a free direntry, returns a pointer to the direntry struct inside SectorBuffer, // until to the end of the FAT chain !! de=fatNextFreeDirEntry(currentDirCluster); // Saves the sector address of this new DirEntry to write it back to the NANDFlah newDirEntrySector= SectorInCache; // if goes until the end of the cluster and don't find a free direntry // needs to create a new direntry in a new cluster to put this new file. if (de == NULL) { freeCluster=fatNextFreeCluster(0); // Find the Free Cluster from cluster0. if (freeCluster == 0) // if disk is full return (FALSE); // returns ERROR lastCluster= fatLastCluster(currentDirCluster); // find the last cluster of the current dir fatWrite(lastCluster, freeCluster); // creates a connection between the last cluster of the current directory and the new cluster created fatWriteEOC(freeCluster); // mark the new cluster with an END OF CLUSTER mark memset (SectorBuffer, '\0', BYTES_PER_SECTOR); // fill the SectorBuffer with ZEROS to informate to the FAT that don't have more direntries after this one that we are creating de= (struct direntry *)SectorBuffer; // de points to the first address in the SectorBuffer newDirEntrySector= fatClustToSect(freeCluster); // Calculate the start sector address of this new cluster SectorInCache= newDirEntrySector; // the sector in memory is this new direntry allocated } // find a free fat cluster to put the content of this new file freeCluster=fatNextFreeCluster(0); // fill with file data information strcpy(string, shortName); string[11]='\0'; fatNormalize(string); fatGetCurTime(&t); time= (u_16)((t.hour)< >DT_2SECONDS_SHIFT); // create time date= (u_16)((t.year-1980)< deName), string, 11); de->deAttributes= ATTR_ARCHIVE; de->deLowerCase=0; // lowercase Names de->deCHundredth= 0x00; // hundredth of seconds in CTime de->deCTime[0]=(u_8)time&0x00FF; de->deCTime[1]=(u_8)((time&0xFF00)>>8); de->deCDate[0]=(u_8)date&0x00FF; de->deCDate[1]=(u_8)((date&0xFF00)>>8); de->deADate[0]=de->deCDate[0]; // access date de->deADate[1]=de->deCDate[1]; // access date de->deHighClust= (u_16)(freeCluster>>16); // high bytes of starting cluster no. de->deMTime[0]=de->deCTime[0]; // last update time de->deMTime[1]=de->deCTime[1]; // last update time de->deMDate[0]=de->deCDate[0]; // last update date de->deMDate[1]=de->deCDate[1]; // last update date de->deStartCluster= (u_16)freeCluster; // low bytes of starting cluster no. of file de->deFileSize=0; // size of file in bytes // write direntry with the file information HAL_WriteSector( DiskIndex, newDirEntrySector, SectorBuffer); // mark the cluster with the content off the new directory created with an END OF CLUSTER mark fatWriteEOC(freeCluster); // open the file to read and write return(fatFopen(shortName)); } //***************************************************************************** // Function: fatNextFreeDirEntry // Parameters: start cluster // Returns: On SUSCEFULL returns the next free dir entry found, NULL otherwise // // Description: Find a free dir entry in the directory started in cluster address // If found a free dir entry, returns the address of this dir entry // The SectorInCache variable will be filled with the sector address // of the free dir entry found. // If goes until the end of the clusters and don't found a free dir // entry, returns NULL. Will be necessary alocate a new cluster //***************************************************************************** struct direntry *fatNextFreeDirEntry(u_32 cluster) { u_16 s,index=0; u_32 sector; struct direntry *de; do { sector = fatClustToSect(cluster); for(s=0; s< SectorsPerCluster ; s++) { HAL_ReadSector(DiskIndex, sector+s, SectorBuffer, &SectorInCache); de = (struct direntry *) SectorBuffer; for (index=0; index deName == SLOT_DELETED) || (*de->deName == 0x00)) return(de); de++; } } cluster=fatNextCluster(cluster); if (cluster == 0)//at the end of the chain return NULL; }while (cluster < NumClusters ); // end of FatDirentries return NULL; } //***************************************************************************** // Function: fatNextFreeCluster // Parameters: start cluster // Returns: On SUSCEFULL returns the next free cluster found, 0 otherwise // // Description: Returns the first free cluster found in Fat table. // If goes until the end of the FAT table and don't found a free cluster. // return 0. //***************************************************************************** u_32 fatNextFreeCluster(u_32 cluster) { u_16 index; u_32 sector; u_32 *fat32Buffer; u_16 *fat16Buffer; fat32Buffer= (u_32 *)FatCache; fat16Buffer= (u_16 *)FatCache; //Calculate the FAT LBA of this cluster no. if (Fat32Enabled) sector= (cluster>>7) + FirstFATSector;// 128 structures of 4 bytes each as a pointer to a cluster else sector= (cluster>>8) + FirstFATSector;// 256 structures of 2 bytes each as a pointer to a cluster index=0; do { HAL_ReadSector( DiskIndex, sector, FatCache, &FatInCache); if (Fat32Enabled) { for (index=0; index < FAT32_STRUCTS_PER_SECTOR; index++) //Read all Clusters in a sector { if ((fat32Buffer[index]&FAT32_MASK) == 0x00000000) return (index + ((sector - FirstFATSector)*FAT32_STRUCTS_PER_SECTOR)); } } else //FAT16 { for (index=0; index < FAT16_STRUCTS_PER_SECTOR; index++) //Read all Clusters in a sector { if ((fat16Buffer[index]&FAT16_MASK) == 0x0000) { return (index + ((sector - FirstFATSector)*FAT16_STRUCTS_PER_SECTOR)); } } } sector++; } while (sector < FirstFATSector+FatSectors); // end of FatDirentries return 0; } //***************************************************************************** // Function: fatLastCluster // Parameters: cluster // Returns: last cluster of the file started in cluster // // Description: Find the last cluster of a file started in "cluster" in fat table //***************************************************************************** u_32 fatLastCluster(u_32 cluster) { u_32 lastCluster; do { lastCluster=cluster; cluster = fatNextCluster(lastCluster); } while (cluster != 0); return lastCluster; } //***************************************************************************** // Function: fatWrite // Parameters: cluster, data to write // Returns: none // // Description: Write the data in FAT in cluster position //***************************************************************************** void fatWrite(u_32 cluster, u_32 data) { u_16 offset; u_32 *Fat32CacheLong, sector; u_16 *Fat16CacheInt; // calculate offset of the our entry within that FAT sector if(Fat32Enabled) offset = (u_16)( cluster % FAT32_STRUCTS_PER_SECTOR ); else offset = (u_16)( cluster % FAT16_STRUCTS_PER_SECTOR ); // read the FAT sector, with has information about the cluster that we are interested in. sector= fatTableClustToSect(cluster); HAL_ReadSector( DiskIndex, sector, FatCache, &FatInCache); // write the data to Fat Cache if (Fat32Enabled) { Fat32CacheLong= (u_32 *)FatCache; Fat32CacheLong[offset]= (Fat32CacheLong[offset]&(~FAT32_MASK)) | (data&FAT32_MASK); } else { Fat16CacheInt= (u_16 *)FatCache; Fat16CacheInt[offset]= (Fat16CacheInt[offset]&(~FAT16_MASK)) | (u_16)(data&FAT16_MASK); } // write Fat Cache in the NANDFlash HAL_WriteSector( DiskIndex, sector, FatCache); // FAT1 HAL_WriteSector( DiskIndex, sector+(FirstFAT2Sector-FirstFATSector), FatCache); // FAT2 } //***************************************************************************** // Function: fatTableClustToSect // Parameters: cluster // Returns: the FAT sector address with has cluster information // // Description: Calculate the FAT sector address with has cluster information //***************************************************************************** u_32 fatTableClustToSect(u_32 cluster) { u_32 sector, fatOffset; // get fat offset in bytes if(Fat32Enabled) fatOffset = cluster << 2; else fatOffset = cluster << 1; // calculate the FAT sector that we're interested in sector = FirstFATSector + (fatOffset / BYTES_PER_SECTOR); return (sector); } //***************************************************************************** // Function: fatWriteEOC // Parameters: cluster // Returns: none // // Description: Write in FAT in cluster position, the END OF CLUSTER mark //***************************************************************************** void fatWriteEOC(u_32 cluster) { fatWrite(cluster, FAT32_MASK & CLUST_EOFE);//Justin modify //fatWrite(cluster, FAT16_MASK & CLUST_EOFE); } //***************************************************************************** // Function: fatFopen // Parameters: File or Directory short name // Returns: A TFILE struct filled with the opened file information, or NULL // if an error has ocurred // // Description: Open a file to read and write. The File struct is filled and // the Sector Buffer in memory is filled with the first sector // of the file opened //***************************************************************************** TFILE* fatFopen(char *shortName) { // if the file don't exist if (fatGetFileInfo(&File.de, shortName) == NULL) return NULL; File.currentSector = fatClustToSect(((u_32)File.de.deHighClust << 16) + File.de.deStartCluster); File.buffer=SectorBuffer; File.bytePointer=0; File.sectorHasChanged=FALSE; HAL_ReadSector( DiskIndex, File.currentSector, File.buffer, &SectorInCache); // read the first file sector return (&File); } //***************************************************************************** // Function: fatGetVolLavel // Parameters: none // Returns: the FAT Volume Name // // Description: Return the FAT Volume Name read in fatInit //***************************************************************************** char* fatGetVolLabel(void) { return VolLabel; } //***************************************************************************** // Function: fatDir // Parameters: initial cluster, offset(sectors) // Returns: On SUSCEFULL returns the sector with direntries info, otherwise // returns NULL // // Description: return the sector with direntries info starting in the cluster, // and with offset sectors from the begining cluster sector //***************************************************************************** u_8 *fatDir(u_32 cluster, u_32 offset) { u_32 index; for (index=0; index < offset/SectorsPerCluster; index++) cluster=fatNextCluster(cluster); //Justin modify for FAT 16 , in FAT16 , cluster 0 means Root dir . if (cluster == 0) { if(Fat32Enabled) return NULL; } HAL_ReadSector(DiskIndex, fatClustToSect(cluster)+ offset%SectorsPerCluster, SectorBuffer, &SectorInCache); return SectorBuffer; } //***************************************************************************** // Function: fatGetCurDirCluster // Parameters: none // Returns: The current dir cluster // // Description: Return the current directory cluster number //***************************************************************************** u_32 fatGetCurDirCluster(void) { return currentDirCluster; } //***************************************************************************** // Function: fatGetFirstDirCluster // Parameters: none // Returns: the cluster number of the first dir entry in FAT // // Description: return the first dir entry cluster in FAT //***************************************************************************** u_32 fatGetFirstDirCluster(void) { return(FirstDirCluster); } //***************************************************************************** // Function: fatMkdir // Parameters: path // Returns: TRUE if the path was created, otherwise FALSE // // Description: Create a new directory on the current directory //***************************************************************************** u_8 fatMkdir(char *path) { struct direntry *de, rde; u_32 freeCluster, newDirEntrySector, lastCluster; u_16 i, date, time; char string[12]; TTime t; // if the file already exist if (fatGetFileInfo(&rde, path) != NULL) { return FALSE; } // Find a free direntry, returns a pointer to the direntry struct inside SectorBuffer, de=fatNextFreeDirEntry(currentDirCluster); // Saves the sector address of this new DirEntry to write it back to the NANDFlah newDirEntrySector= SectorInCache; // if goes until the end of the cluster and don't find a free direntry // needs to create a new direntry in a new cluster to put this new directory. if (de == NULL) { freeCluster=fatNextFreeCluster(0); // find a new free cluster if (freeCluster == 0) // If the disk is full return (FALSE); // return ERROR lastCluster= fatLastCluster(currentDirCluster); // find the last cluster of the current dir fatWrite(lastCluster, freeCluster); // creates a connection between the last cluster of the current directory and the new cluster created fatWriteEOC(freeCluster); // mark the new cluster with an END OF CLUSTER mark memset (SectorBuffer, '\0', BYTES_PER_SECTOR); // fill the SectorBuffer with ZEROS to informate to the FAT that don't have more direntries after this one that we are creating de= (struct direntry *)SectorBuffer; // de points to the first address in the SectorBuffer newDirEntrySector= fatClustToSect(freeCluster); // Calculate the start sector address of this new cluster SectorInCache= newDirEntrySector; // the sector in memory is this new direntry allocated for (i=1; i< SectorsPerCluster; i++) // write zeros in all the new cluster allocated HAL_WriteSector( DiskIndex, newDirEntrySector+i, SectorBuffer); } // in this point we have a direntry in SectorBuffer, and de point to the address of the informations about the new directory // find a FAT free cluster to write the directory content freeCluster=fatNextFreeCluster(0); // fill the direntry strcpy(string, path); string[11]='\0'; fatNormalize(string); fatGetCurTime(&t); time= (u_16)((t.hour)< >DT_2SECONDS_SHIFT); // create time date= (u_16)((t.year-1980)< deName), string, 11); // name of the directory de->deAttributes= ATTR_DIRECTORY; de->deLowerCase=0; // lowercase Names de->deCHundredth= 0x00; // hundredth of seconds in CTime de->deCTime[0]=(u_8)time&0x00FF; de->deCTime[1]=(u_8)((time&0xFF00)>>8); de->deCDate[0]=(u_8)date&0x00FF; de->deCDate[1]=(u_8)((date&0xFF00)>>8); de->deADate[0]=de->deCDate[0]; // access date de->deADate[1]=de->deCDate[1]; // access date de->deHighClust= (u_16)(freeCluster>>16); // high bytes of cluster number de->deMTime[0]=de->deCTime[0]; // last update time de->deMTime[1]=de->deCTime[1]; // last update time de->deMDate[0]=de->deCDate[0]; // last update date de->deMDate[1]=de->deCDate[1]; // last update date de->deStartCluster= (u_16)freeCluster; // starting cluster of file de->deFileSize=0; // size of file in bytes, is a directory, so the size is 0 // write SectorBuffer filled with the new directory information HAL_WriteSector( DiskIndex, newDirEntrySector, SectorBuffer); // create the files "." and ".." de= (struct direntry *)SectorBuffer; //strncpy(de->deName, ". ", 11); memcpy((u_8*)(de->deName), ". ", 11); de->deAttributes= ATTR_DIRECTORY; de->deLowerCase=0; // lowercase Names de->deCHundredth= 0x00; // hundredth of seconds in CTime de->deCTime[0]=(u_8)time&0x00FF; de->deCTime[1]=(u_8)((time&0xFF00)>>8); de->deCDate[0]=(u_8)date&0x00FF; de->deCDate[1]=(u_8)((date&0xFF00)>>8); de->deADate[0]=de->deCDate[0]; // access date de->deADate[1]=de->deCDate[1]; // access date de->deHighClust= (u_16)(freeCluster>>16); // high bytes of cluster number de->deMTime[0]=de->deCTime[0]; // last update time de->deMTime[1]=de->deCTime[1]; // last update time de->deMDate[0]=de->deCDate[0]; // last update date de->deMDate[1]=de->deCDate[1]; // last update date de->deStartCluster= (u_16)freeCluster; // starting cluster of file de->deFileSize=0; // size of file in bytes de++; //strncpy(de->deName, ".. ", 11); memcpy((u_8*)(de->deName), ".. ", 11); de->deAttributes= ATTR_DIRECTORY; de->deLowerCase=0; // lowercase Names de->deCHundredth= 0x00; // hundredth of seconds in CTime de->deCTime[0]=(u_8)time&0x00FF; de->deCTime[1]=(u_8)((time&0xFF00)>>8); de->deCDate[0]=(u_8)date&0x00FF; de->deCDate[1]=(u_8)((date&0xFF00)>>8); de->deADate[0]=de->deCDate[0]; // access date de->deADate[1]=de->deCDate[1]; // access date de->deHighClust= (u_16)(currentDirCluster>>16); // high bytes of cluster number de->deMTime[0]=de->deCTime[0]; // last update time de->deMTime[1]=de->deCTime[1]; // last update time de->deMDate[0]=de->deCDate[0]; // last update date de->deMDate[1]=de->deCDate[1]; // last update date de->deStartCluster= (u_16)currentDirCluster; // starting cluster of file de->deFileSize=0; // size of file in bytes de++; // fill the rest with zeros for (i= (u_16)(((u_8 *)de) - SectorBuffer); i < 512; i++) SectorBuffer[i]= 0; // write the content of the new directory created, including "." and ".." files HAL_WriteSector( DiskIndex, fatClustToSect(freeCluster), SectorBuffer); // fill the entire sector buffer with zeros memset (SectorBuffer, '\0', BYTES_PER_SECTOR); // write all the others sectors of this new cluster. for (i=1; i< SectorsPerCluster; i++) HAL_WriteSector( DiskIndex, fatClustToSect(freeCluster)+i, SectorBuffer); // actualize the sector address in cache SectorInCache= fatClustToSect(freeCluster)+SectorsPerCluster-1; // mark the cluster with the content off the new directory created with an END OF CLUSTER mark fatWriteEOC(freeCluster); return TRUE; } //***************************************************************************** // Function: fatFputc // Parameters: TFILE struct of the file opened, character to be writed // Returns: On SUSCEFULL returns TRUE, and FALSE otherwise // // Description: Write a character to the file. Return false if the disk is full //***************************************************************************** u_8 fatFputc(TFILE *fp, char c) { u_16 bufferPointer; u_32 freeCluster; bufferPointer= (u_16)(fp->bytePointer & 0x001FF); // equal (fp->bytePointer % 512) fp->bytePointer++; if ((fp->bytePointer != 1) && (bufferPointer == 0)) // if we need to allocate a new sector to the file { HAL_WriteSector(DiskIndex, fp->currentSector, fp->buffer); if(fp->de.deFileSize > fp->bytePointer) // sector already exist { // Next Sector is in current Cluster if (fatSectToClust(fp->currentSector) == fatSectToClust(fp->currentSector+1)) { fp->currentSector++; } else // Next Sector is in next Cluster { u_32 cluster; cluster= fatNextCluster(fatSectToClust(fp->currentSector)); fp->currentSector= fatClustToSect(cluster); } HAL_ReadSector( DiskIndex, fp->currentSector, fp->buffer, &SectorInCache); } else // sector isn't used or the cluster isn't allocated { if (fatSectToClust(fp->currentSector) == fatSectToClust(fp->currentSector+1))//the next sector is in current cluster { fp->currentSector++; } else { freeCluster=fatNextFreeCluster(0); if (freeCluster == 0) // if disk is full return (FALSE); fatWrite(fatSectToClust(fp->currentSector), freeCluster); fatWriteEOC(freeCluster); fp->currentSector = fatClustToSect(freeCluster); } } } fp->buffer[bufferPointer]=c; fp->sectorHasChanged=TRUE; if(fp->bytePointer > fp->de.deFileSize) fp->de.deFileSize = fp->bytePointer; return (TRUE); } //***************************************************************************** // Function: fatSectToClust // Parameters: sector // Returns: cluster // // Description: Converts Clusters in Sectors //***************************************************************************** u_32 fatSectToClust(u_32 sect) { return (((sect - FirstDataSector) / SectorsPerCluster) + 2); } //***************************************************************************** // Function: fatFflush // Parameters: TFILE struct of the file to be flushed // Returns: TRUE if the file was corrected flushed, and FALSE otherwise // // Description: write current sector file to hard disk if necessary //***************************************************************************** u_8 fatFflush(TFILE *fp) { if (fp->sectorHasChanged) { HAL_WriteSector( DiskIndex, fp->currentSector, fp->buffer); fp->sectorHasChanged=FALSE; } return TRUE; } //***************************************************************************** // Function: fatFseek // Parameters: TFILE struct of the file opened, offSet, seek mode // Returns: On SUSCEFULL returns TRUE, and FALSE otherwise // // Description: find a byte position in the file and load the corresponded sector in buffer // Modes: SEEK_CUR: from the current position of the file pointer; // SEEK_SET: from the beggining of the file // SEEK_END: from the end of file to back. //***************************************************************************** u_8 fatFseek(TFILE *fp, u_32 offSet, u_8 mode) { u_32 numClusters, curCluster, numSector; // calculate the new byte pointer switch (mode) { case SEEK_END: fp->bytePointer= fp->de.deFileSize - offSet; break; case SEEK_SET: fp->bytePointer= offSet; break; case SEEK_CUR: fp->bytePointer= fp->bytePointer + offSet; break; default: return FALSE; } // calculate the current file cluster curCluster=((u_32)fp->de.deHighClust<<16)+(fp->de.deStartCluster); numClusters=fp->bytePointer/(BYTES_PER_SECTOR*SectorsPerCluster); numSector=(fp->bytePointer/BYTES_PER_SECTOR)%SectorsPerCluster; // calculate the cluster address of the new byte pointer while (numClusters > 0) { curCluster=fatNextCluster(curCluster); numClusters--; } // calculate the Sector address of the new byte pointer fp->currentSector=fatClustToSect(curCluster) + numSector; // read that sector HAL_ReadSector( DiskIndex, fp->currentSector, fp->buffer, &SectorInCache); return TRUE; } //***************************************************************************** // Function: fatFgetc // Parameters: TFILE struct of the file opened // Returns: On SUSCEFULL returns the next character from file, and 0 otherwise // // Description: Get the next character from file, and actualize the byte pointer //***************************************************************************** char fatFgetc(TFILE *fp) { u_16 bufferPointer; if (fatFeof(fp)) // if is the end of file return 0; bufferPointer= (u_16)(fp->bytePointer & 0x001FF); // equal (fp->bytePointer % 512) fp->bytePointer++; //if(fp->bytePointer == 1) , it means reading first char after fopen , //when fopen , it has read the first file sector into fp->buffer. //if(bufferPointer == 0) , it means that the next char is in next sector . if ((fp->bytePointer == 1) || (bufferPointer != 0)) { return(fp->buffer[bufferPointer]); } else { // Next Sector is in current Cluster if (fatSectToClust(fp->currentSector) == fatSectToClust(fp->currentSector+1)) { fp->currentSector++; } else // Next Sector is in next Cluster { u_32 cluster; cluster= fatNextCluster(fatSectToClust(fp->currentSector)); fp->currentSector= fatClustToSect(cluster); } HAL_ReadSector( DiskIndex, fp->currentSector, fp->buffer, &SectorInCache); return(fp->buffer[bufferPointer]); } } //***************************************************************************** // Function: fatFeof // Parameters: TFILE struct of the file opened // Returns: On END OF FILE returns TRUE, and FALSE otherwise // // Description: return TRUE if the byte pointer points to the end of the file //***************************************************************************** u_8 fatFeof(TFILE *fp) { if ((fp->bytePointer) >= (fp->de.deFileSize)) return TRUE; return FALSE; } //***************************************************************************** // Function: fatFclose // Parameters: TFILE struct of the file to be closed // Returns: TRUE if the file was corrected closed, and FALSE otherwise // // Description: write current file to the FAT file system // refresh the file size //***************************************************************************** u_8 fatFclose(TFILE *fp) { struct direntry *de, rde; u_32 fileSize; u_16 date, time; TTime t; fileSize= fp->de.deFileSize; fp->bytePointer=0; if (fatFflush(fp)) { if ((de=fatGetFileInfo(&rde, (char*)(fp->de.deName))) == NULL) // if the file don't exist return FALSE; de->deFileSize= fileSize; // refresh the file size ?? fatGetCurTime(&t); time= (u_16)((t.hour)< >DT_2SECONDS_SHIFT); // create time date= (u_16)((t.year-1980)< deMTime[0]=(u_8)time&0x00FF; // last update time de->deMTime[1]=(u_8)((time&0xFF00)>>8); // last update time de->deMDate[0]=(u_8)date&0x00FF; // last update date de->deMDate[1]=(u_8)((date&0xFF00)>>8); // last update date de->deADate[0]=de->deMDate[0]; // access date de->deADate[1]=de->deMDate[1]; // access date HAL_WriteSector( DiskIndex, SectorInCache, SectorBuffer); HAL_ReadSector( DiskIndex, FSInfo, SectorBuffer, &SectorInCache); // Read FSInfo ((struct fsinfo *)SectorBuffer)->fsinfree[0]=0xFF; // change to Operation System don't to try to correct this field and the FAT ((struct fsinfo *)SectorBuffer)->fsinfree[1]=0xFF; ((struct fsinfo *)SectorBuffer)->fsinfree[2]=0xFF; ((struct fsinfo *)SectorBuffer)->fsinfree[3]=0xFF; ((struct fsinfo *)SectorBuffer)->fsinxtfree[0]=0xFF; ((struct fsinfo *)SectorBuffer)->fsinxtfree[1]=0xFF; ((struct fsinfo *)SectorBuffer)->fsinxtfree[2]=0xFF; ((struct fsinfo *)SectorBuffer)->fsinxtfree[3]=0xFF; HAL_WriteSector( DiskIndex, SectorInCache, SectorBuffer); return(TRUE); } return (FALSE); } //***************************************************************************** // Function: fatCddir // Parameters: path // Returns: On SUSCEFULL returns TRUE, otherwise returns FALSE // // Description: Change the current directory. Only one level path // ex: cd \test // cd \test\test2 IS INVALID, use cd \test cd\test2 instead //***************************************************************************** u_8 fatCddir(char *path) { struct direntry de; // if the path doesn't exist return FALSE if (fatGetFileInfo(&de, path) == NULL) return FALSE; // if the path is a directory if ((de.deAttributes & ATTR_DIRECTORY) == ATTR_DIRECTORY) { // change the current dir cluster to the path information currentDirCluster= (de.deStartCluster) + ((unsigned long)de.deHighClust<<16); //Justin modify for FAT16 if (currentDirCluster == 0 && Fat32Enabled) currentDirCluster = 2; return TRUE; } return FALSE; } //***************************************************************************** // Function: fatRename // Parameters: old name, new name // Returns: TRUE if the name was chanched, otherwise FALSE // // Description: Change the name of a directory or file //***************************************************************************** u_8 fatRename(char *oldShortName, char *newShortName) { struct direntry *de, rde; char string[12]; // if the new file name already exist de=fatGetFileInfo(&rde, newShortName); if (de != NULL) return FALSE; // if the file don't exist de=fatGetFileInfo(&rde, oldShortName); if (de == NULL) return FALSE; strcpy(string, newShortName); string[11]='\0'; fatNormalize(string); memcpy((u_8*)(de->deName), string, 11); HAL_WriteSector( DiskIndex, SectorInCache, SectorBuffer); return TRUE; } //***************************************************************************** // Function: fatRemoveAll // Parameters: none // Returns: none // // Description: Remove all files in currentDirCluster //***************************************************************************** void fatRemoveAll(void) { u_32 offset=0; struct direntry *de = 0; // avoid compiler warning by initializing s_16 index; for (offset=0; ; offset++) { de = (struct direntry *) fatDir(currentDirCluster, offset); if (de == NULL) return; for (index=0; index deName == SLOT_EMPTY) return; // there is no more direntries if (( de->deAttributes & ATTR_VOLUME ) != ATTR_VOLUME) if ((*de->deName != SLOT_DELETED) && (*de->deName != '.')) fatRemove((char*)(de->deName)); de++; } // end of sector } // end of cluster } //***************************************************************************** // Function: fatRemove // Parameters: File or Directory short name // Returns: TRUE if the file was removed, otherwise FALSE // // Description: remove a file or directory //***************************************************************************** u_8 fatRemove(char *shortName) { struct direntry *de, rde; u_32 CurrentDirCluster, NextCluster, fileSector; de=fatGetFileInfo(&rde, shortName); // get file information if (de == NULL) // if the file doesn't exist return FALSE; // return ERROR fileSector=SectorInCache; // save the File sector address // calculate the cluster address of this file CurrentDirCluster = ((u_32)de->deHighClust << 16) + de->deStartCluster; // if the file is a directory if ( de->deAttributes == ATTR_DIRECTORY ) { if (!fatDirectoryIsEmpty(CurrentDirCluster)) // if there are files in the directory return FALSE; // return ERROR } // Read the direntry information about the file HAL_ReadSector( DiskIndex, fileSector, SectorBuffer, &SectorInCache); // mark the file name as deleted *de->deName = SLOT_DELETED; // write the direntry back to the NANDFlash HAL_WriteSector( DiskIndex, SectorInCache, SectorBuffer); // erase fat table do{ NextCluster=fatNextCluster(CurrentDirCluster); fatWrite(CurrentDirCluster,CLUST_FREE); // free the current dir cluster CurrentDirCluster=NextCluster; }while( NextCluster != 0 ); //file erased return TRUE; } //***************************************************************************** // Function: fatDirectoryIsEmpty // Parameters: Start Directory Cluster // Returns: TRUE if the directory is empty, FALSE otherwise // // Description: check to the existance of files in the directory started in DirCluster //***************************************************************************** u_8 fatDirectoryIsEmpty(u_32 DirCluster) { struct direntry *de; u_32 sector, isector; s_16 index; do { sector=fatClustToSect(DirCluster); //read directory clusters for (isector=0; isector < SectorsPerCluster ;isector++) // read one cluster { HAL_ReadSector( DiskIndex, sector + isector, SectorBuffer, &SectorInCache); de= (struct direntry *)SectorBuffer; for (index=0; index deName != '.' ) { if ( *de->deName == SLOT_EMPTY ) return TRUE; if ( *de->deName != SLOT_DELETED) return FALSE; } // If goes until here it's because de->Name is equal '.' or is equal SLOT_DELETED de++; } } DirCluster=fatNextCluster(DirCluster); }while ( DirCluster != 0 ); // if goes until here it's because the all file (directory) is filled with SLOT_DELETED return TRUE; } //***************************************************************************** // Function: fatGetPartInfo // Parameters: none // Returns: FAT partition information // // Description: return the partition information read in fatInit routine //***************************************************************************** struct partrecord *fatGetPartInfo(void) { return (&PartInfo); } //***************************************************************************** // Justin added on 20060517 // Function: fatFread // Parameters: buffer is address of BUFFER to be write into, size is the size of BUFFER , TFILE struct of the file opened // Returns: On SUSCEFULL returns the size has been read, and 0 otherwise // // Description: Get the datas from file and write into BUFFER , and actualize the byte pointer //***************************************************************************** u_16 fatFread(u_8* buffer,u_16 size,TFILE *fp) { u_16 buffer_idx = 0; if (fatFeof(fp)) // if is the end of file return 0; if(!size) return 0; while(buffer_idx < size) { //if(fp->bytePointer == 0) , it means reading first char after fopen , //when fopen , it has read the first file sector into fp->buffer. if (fp->bytePointer != 0 && (fp->bytePointer%512 == 0)) { // Next Sector is in current Cluster if (fatSectToClust(fp->currentSector) == fatSectToClust(fp->currentSector+1)) { fp->currentSector++; } else // Next Sector is in next Cluster { u_32 cluster; cluster= fatNextCluster(fatSectToClust(fp->currentSector)); fp->currentSector= fatClustToSect(cluster); } //Fill one sector into SectorBuffer(fp->buffer) HAL_ReadSector( DiskIndex, fp->currentSector, fp->buffer, &SectorInCache); } if(buffer_idx+512 <= size)//buffer's empty size is enough to fill 512 byte data { if((fp->bytePointer + 512) >= (fp->de.deFileSize))//arriving EOF { u_16 len; if((fp->de.deFileSize - fp->bytePointer) > (512 - fp->bytePointer%512)) len = (u_16)(512 - fp->bytePointer%512); else len = (u_16)(fp->de.deFileSize - fp->bytePointer); memcpy((buffer+buffer_idx), &(fp->buffer[fp->bytePointer%512]), len); buffer_idx += len; fp->bytePointer += len; if(fp->bytePointer == fp->de.deFileSize) break; } else { u_16 len = (u_16)(512-(fp->bytePointer%512)); memcpy((buffer+buffer_idx), &(fp->buffer[fp->bytePointer%512]), len); buffer_idx += len; fp->bytePointer += len; } } else { if((fp->bytePointer + (size-buffer_idx)) >= (fp->de.deFileSize))//arriving EOF { u_16 len; if((fp->de.deFileSize - fp->bytePointer) > (512 - fp->bytePointer%512)) len = (u_16)(512 - fp->bytePointer%512); else len = (u_16)(fp->de.deFileSize - fp->bytePointer); memcpy((buffer+buffer_idx), &(fp->buffer[fp->bytePointer%512]), len); buffer_idx += len; fp->bytePointer += len; if(fp->bytePointer == fp->de.deFileSize) break; } else { u_16 len; if((size - buffer_idx) > (u_16)(512 - fp->bytePointer%512))//arriving end of sector , the remainder sector datas is larger than the buffer empty size. len = (u_16)(512 - fp->bytePointer%512); else len = (u_16)(size - buffer_idx); memcpy((buffer+buffer_idx), &(fp->buffer[fp->bytePointer%512]), len); buffer_idx += len; fp->bytePointer += len; break; } } } return buffer_idx; } #if 0 u_16 fatFread(u_8* buffer,u_16 size,TFILE *fp) { if (fatFeof(fp)) // if is the end of file return 0; //if(fp->bytePointer == 0) , it means reading first char after fopen , //when fopen , it has read the first file sector into fp->buffer. if (fp->bytePointer != 0) { // Next Sector is in current Cluster if (fatSectToClust(fp->currentSector) == fatSectToClust(fp->currentSector+1)) { fp->currentSector++; } else // Next Sector is in next Cluster { u_32 cluster; cluster= fatNextCluster(fatSectToClust(fp->currentSector)); fp->currentSector= fatClustToSect(cluster); } HAL_ReadSector( DiskIndex, fp->currentSector, fp->buffer, &SectorInCache); } if((fp->bytePointer + 512) > (fp->de.deFileSize)) { memcpy(buffer, &(fp->buffer[0]), (fp->de.deFileSize % 512)); fp->bytePointer = fp->de.deFileSize; return (fp->de.deFileSize % 512); } else { memcpy(buffer, &(fp->buffer[0]), 512); fp->bytePointer += 512; return 512; } } #endif