📄 fat.c
字号:
//---------------------------------------------------------------------
//FileName : fat.c
//Created by : nasif
//Modified by : ZhengYanbo
//Last Modified: 2006.4.8
//function : implementation to interface CF with FAT filesystem
//---------------------------------------------------------------------
#include "fat.h"
#include "global_def.h"
//*******************************************************************
// Convert cluster address to LBA address
unsigned long clust2LBA(unsigned long clust)
//*******************************************************************
{
return ((clust-2) * Sectors_Per_Cluster) + FirstDataSector;
}
/*
//*******************************************************************
// Convert LBA address to cluster address
unsigned long LBA2Cluster(unsigned long LBA)
//*******************************************************************
{
return ((LBA-FirstDataSector)/Sectors_Per_Cluster)+2;
}
*/
//*******************************************************************
// FAT filesystem Init
// Return: FAT type
byte ATA_getFileSystemInfo(void)
//*******************************************************************
{
struct partRec *pr;
struct bootSec710 *boot;
//struct driveID *driveInfo;
dword CountofClusters;
//struct FAT32fsInfo *fsInfo;
dword startSector;
dword FATSz, dataSec, totalSector;
LCDclrscr();
writestring("读文件系统...");
gotoxy(1,0);
writestring("文件系统:");
//---------------------------------------------
//Start to Read MBR sector
//---------------------------------------------
ATA_Read_Sector(0, sectorBuffer.data);
if(sectorBuffer.data[0] == 0xeb)
{ //If first byte is a instruction of JMP,no DPT.
//---------------------------------------------
// debug info here
//---------------------------------------------
}
else
{
//skipping boot code in first 445 bytes.
//Read 64 bytes partition table record
pr = (struct partRec *)§orBuffer.data[0x1BE];
startSector = pr->startLBA;
ATA_Read_Sector(startSector, sectorBuffer.data); //read boot record
}
boot = (struct bootSec710 *) sectorBuffer.data; //Load BPB struct pointer
//All of the following calculations are from Microsoft FAT32 White Paper
Sectors_Per_Cluster = boot->BPB.secPerClust;
Bytes_Per_Sector = boot->BPB.bytesPerSec;
FirstFATSector = boot->BPB.resSectors + startSector;
FATtype=OTHER;
if (boot->BPB.rootDirEnts==0)
{
FATtype=FAT32; //FAT32
FirstRootCluster = boot->BPB.rootClust;
writestring("FAT32");
}
rootDirSectors=(((boot->BPB.rootDirEnts * 32)+ (Bytes_Per_Sector - 1)) / Bytes_Per_Sector);
//-------------- Get FAT Size and total sectors ----------------
//For FAT32,BPB.FATSz16 must equal to 0.
//For FAT12 or FAT16,BPB.FATSz16 is a word wide.
//--------------------------------------------------------------
FATSz = boot->BPB.FATSz16; //For FAT16 or FAT12 Filesystem
if (FATSz==0) FATSz = boot->BPB.FATSz32;
//For FAT16 or FAT12,if(totSec>65536) BPB.totSec16==0.You must get tatal
//sectors from totSec32. !!!For FAT32, BPB.totSec16 Must Equal to 0 !
if (boot->BPB.totSec16 != 0) totalSector=boot->BPB.totSec16;
else totalSector=boot->BPB.totSec32;
dataSec = totalSector - (boot->BPB.resSectors + (boot->BPB.FATs * FATSz) + rootDirSectors);
FirstRootSector = FirstFATSector + (boot->BPB.FATs * FATSz); //for fat16 or fat12
FirstDataSector = boot->BPB.resSectors + (boot->BPB.FATs * FATSz) + rootDirSectors + startSector;
//Number of valid clusters
CountofClusters = dataSec / Sectors_Per_Cluster;
//maxcluster=CountofClusters+2;
//writeNumber(CountofClusters);
//Note also that the CountofClusters value is exactly that: the count of data clusters
//starting at cluster 2. The maximum valid cluster number for the volume is
//CountofClusters + 1, and the "count of clusters including the two reserved clusters"
//is CountofClusters + 2.
//get cluster size(how many bytes?)
Bytes_Per_Cluster = Bytes_Per_Sector * Sectors_Per_Cluster;
//--------------- Determine Filesystem Type --------------------
if(FATtype!=FAT32)
{
FirstRootCluster=0; // for FAT12 and FAT16
if(CountofClusters < 4085)
{
FATtype=FAT12; writestring("FAT12");
} //FAT12
else
{
FATtype=FAT16; writestring("FAT16");
} //FAT16
}
//delay_ms(1000); //delay for showing fat type
//-----------------------------------------
// debug info
//-----------------------------------------
/*
LCDclrscr();
writestring("BPS:");
writeNumber(Bytes_Per_Sector);
writechar(' ');
writestring("SPC:");
writeNumber(Sectors_Per_Cluster);
gotoxy(1,0);
writestring("Start Sector:");
writeNumber(startSector);
//delay_ms(3000); //pause 1000ms
//-------------------------------------------
// rootDirSectors and boot->BPB.rootDirEnts
// This is debugging for fat12 or fat16.
//-------------------------------------------
gotoxy(2,0);
writestring("RootDirEnt:");
writeNumber(boot->BPB.rootDirEnts);
gotoxy(3,0);
writestring("RootDirSect:");
writeNumber(rootDirSectors);
delay_ms(1000);
//-------------------------------------------
// FirstRootSector and FirstDataSector
//-------------------------------------------
LCDclrscr();
writestring("Root Start:");
writeNumber(FirstRootSector);
gotoxy(1,0);
writestring("Data Start:");
writeNumber(FirstDataSector);
delay_ms(1000); */
return(FATtype);
}
//*******************************************************************
//get directory Entry info
//gets a filename.ext, filesize, and start cluster of that file.
//Returns 1 if file is found, returns 0 if no file found and reaches
//end of directory.Each file record in dir is 32 byte long.
//Root Directory Access Only!
//NOTICE: I had copied Extension name for short name, too!!!
unsigned char getDirEntry(byte onlyMP3)
//*******************************************************************
{
word fileNum=0;
dword extension,cluster;
byte i,j,start,longNameFound;
word rootEntries; //root directory count
struct direntry *file;
struct winentry *longFile;
dword dirReadLBA; //directory entry LBA address(fat16 or fat12)
readPos=0;
if((currentFileNum & dirReadOffset.fileNum) ==0)
{ //if reading from start of root dir
dirReadLBA=FirstRootSector;//for fat16 or fat12
subDirLevel=0; //root directory now
dirReadOffset.entryCount=0; //clear entry count
rootEntries=0;
//dirString[0]=2;
//dirString[1]='/';
}
else
{ //Find the previous file record read offset in root directory.
fileNum=dirReadOffset.fileNum; //Last read file number
dirReadLBA=dirReadOffset.dirLBA; //Last LBA address
readPos=dirReadOffset.readPos;
rootEntries=dirReadOffset.entryCount;
GoToSectorOffset(dirReadLBA, readPos);
}
CLEAR: //Jump position if an entry was invalid entry, clear fileName
for(i=0; i<FILE_NAME_LENGTH; i++) fileName[i]=0; //Clear file name
extension=0;
longNameFound=0; //long name flag
do { //loop untill find a file or reach the end of a directory.
//directory entry is in root directory, read 32 bytes of root directory
ATA_Read_Sector_Bytes(dirReadLBA,32,sectorBuffer.data);
//We have read an entry(32 bytes long),increase rootEntries
rootEntries++;
//NOTICE: for fat12/fat16, root directories take up 32 sectors at most.
//Means : total Root Directories < 512
if(rootEntries>512) goto ROOT_DIR_END;
//must to be read a new root dir sector.
if(readPos==0) dirReadLBA++;
//Init file entry pointer
longFile=(struct winentry *) sectorBuffer.data;
file=(struct direntry *) sectorBuffer.data;
if(sectorBuffer.data[0] == 0xE5) { goto CLEAR; } //Deleted entry
//------------------------------------------------------------------
// End of a Root directory block
//------------------------------------------------------------------
if(sectorBuffer.data[0] == 0)
{ //We reached end of a directory
ROOT_DIR_END:
currentFileNum=0;
ATA_lba_close();
return 0; //Done. Finished reading all root entries so return 0
}
//------------------------------------------------------------------------
// Active long name sub-component block
//------------------------------------------------------------------------
if((longFile->Attr & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME)
{ /*
start = 13 *( (longFile->Cnt-1) & 0x0F);
i=0;
while ((start<40)&&(i<13))
{ fileName[start++] = sectorBuffer.data[longNameOffset[i++]]; } */
start = 26 *( (longFile->Cnt-1) & 0x0F); //Fine offset of text in long file name
i=0;
while ((start<(FILE_NAME_LENGTH-2))&&(i<5))
{ fileName[start++]=(byte)(longFile->Part1[i]>>8);
fileName[start++]=(byte)(longFile->Part1[i]);
i++;
}
i=0;
while ((start<(FILE_NAME_LENGTH-2))&&(i<6))
{ fileName[start++]=(byte)(longFile->Part2[i]>>8);
fileName[start++]=(byte)(longFile->Part2[i]);
i++;
}
i=0;
while ((start<(FILE_NAME_LENGTH-2))&&(i<2))
{ fileName[start++]=(byte)(longFile->Part3[i]>>8);
fileName[start++]=(byte)(longFile->Part3[i]);
i++;
}
longNameFound=1;
}//long name process
else
{ //Found Short file entry, now determine its type
for (i=0; i<8; i++)
{
for (j=0; j<47; j++) if (invalidFileChars[j]== file->name[i]) goto CLEAR;
if (longNameFound==0) fileName[i]=file->name[i]; // Reading short file name
}
//----------------------------------------------------------------------
// Copy Extension name, for short file name only
//----------------------------------------------------------------------
if (longNameFound==0)
{
for(i=0; i<3; i++) fileName[i+8] = file->name[i];
}
//----------------------------------------------------------------------
// Found a file
//----------------------------------------------------------------------
if ((file->attributes & 0x18 /*(ATTR_DIRECTORY | ATTR_VOLUME_ID)*/ ) == 0x00)
{ for(i=0;i<3; i++)
{ //Collect the file extension
fileExtension[i]=file->extension[i];
}
extension = (*(dword *)fileExtension) & 0x00FFFFFF;
// we want WMA files
if ((onlyMP3==1)&&(extension!=0x00414D57))
{goto CLEAR;}; //extension = 03PM (little endian struct)
fileNum++;
if(fileNum>currentFileNum)
{ currentFileNum=fileNum;
FileSize = file->fileSize;
currentCluster = file->highClust;
currentCluster = (currentCluster<<16) + file->startCluster;
//Remember the first cluster of the file
firstCluster = currentCluster;
dirReadOffset.dirLBA=dirReadLBA; //save lba address
dirReadOffset.readPos=readPos; //address of current Entry
dirReadOffset.fileNum=fileNum;
dirReadOffset.entryCount=rootEntries;
ATA_lba_close();
return 1;
}//fileNum>currentFileNum
goto CLEAR;
}//Found a file
//-------------------------------------------------------------
// Found a directory
//-------------------------------------------------------------
if ((file->attributes & 0x18) == ATTR_DIRECTORY)
{
goto CLEAR;
}//((file->attributes & 0x18) == ATTR_DIRECTORY)
}//File Entry end
}while (1); //loop until arrived at the end of a directory.
}
//*******************************************************************
// Find next cluster in fat(only for FAT16)
dword findNextCluster()
//*******************************************************************
{
unsigned long FatOffset, sector;
unsigned int offset;
FatOffset = (currentCluster << 1); //Lshift by 1 in FAT16
sector = FirstFATSector + (FatOffset / Bytes_Per_Sector);
offset = FatOffset % Bytes_Per_Sector;
ATA_Read_Sector(sector, sectorBuffer.data);
//FAT16 address return
return (*(unsigned int *)§orBuffer.data[offset]);
}
//======================== End of zfat.c ==========================//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -