fat.c
来自「老外的一个开源项目」· C语言 代码 · 共 1,460 行 · 第 1/4 页
C
1,460 行
if(drEntry.FileName[0] == DIRENTRY_NEVERUSED){
break; // no used entry, exit
}
// compare filename, if match update ppCurItem to next
if(CompareFileName(drEntry.FileName, ppCurItem)){
// update pFileInfo to new entry
InitFileInfo(pFileInfo, pFileInfo->PartitionNumber,
drEntry.StartingCluster, drEntry.FileLength, drEntry.Attribute);
return TRUE;
}
}
return FALSE;
}
// help routine for initialization
static DWORD GetDefaultSectorSize(){
return DEFAULT_SECTOR_SIZE;
}
static BOOL InitPartition(BOOL fBootable, DWORD dwFileSystem, DWORD dwStart, DWORD dwLength){
DWORD dwFileType;
DWORD dwFATSectors, dwTotalSectors;
DWORD dwRootStart, dwRootSectors, dwRootLength;
DWORD dwDataStart, dwDataSectors, dwDataClusters;
UINT8 buf[DEFAULT_SECTOR_SIZE];
PRAWPARTITION pPart = (PRAWPARTITION)buf;
// we just support 26 partition
if(PartitionNumber >= MAX_PARTITION){
return FALSE;
}
// read first sector
if(FATReadDisk(pPart, sizeof(*pPart), dwStart) != sizeof(*pPart)){
return FALSE;
}
// check field
if(pPart->SectorSize == 0){
return FALSE;
}
if(pPart->SectorPerCluster == 0){
return FALSE;
}
if(pPart->ReservedSector == 0){
return FALSE;
}
if(pPart->NumberOfFAT == 0){
return FALSE;
}
if(pPart->NumberOfRootEntry==0 && pPart->FAT32.RootEntryCluster==0){
return FALSE;
}
if(pPart->TotalSector != 0){
if(pPart->TotalSector2 != 0){
return FALSE;
}
}
else if(pPart->TotalSector2 == 0){
return FALSE;
}
if(pPart->SectorPerFAT==0 && pPart->FAT32.SectorPerFAT==0){
return FALSE;
}
if(pPart->EFDCSignature!=RAWPARTITION_EFDCSIGNATURE &&
pPart->FAT32.EFDCSignature!=RAWPARTITION_EFDCSIGNATURE){
return FALSE;
}
if(pPart->Signature != RAWPARTITION_SIGNATURE){
return FALSE;
}
// determine FAT type
if(pPart->SectorPerFAT){
dwFATSectors = pPart->NumberOfFAT*pPart->SectorPerFAT;
}
else{
dwFATSectors = pPart->NumberOfFAT*pPart->FAT32.SectorPerFAT;
}
if(pPart->TotalSector){
dwTotalSectors = pPart->TotalSector;
}
else{
dwTotalSectors = pPart->TotalSector2;
}
dwRootStart = pPart->SectorSize*(pPart->ReservedSector+dwFATSectors);
dwRootLength = 32*pPart->NumberOfRootEntry;
dwRootSectors = (dwRootLength+pPart->SectorSize-1)/pPart->SectorSize;
dwDataStart = dwRootStart+pPart->SectorSize*dwRootSectors;
dwDataSectors = dwTotalSectors-pPart->ReservedSector-dwFATSectors-dwRootSectors;
dwDataClusters = dwDataSectors/pPart->SectorPerCluster;
if(dwDataClusters < 4085){
dwFileType = PART_FAT12;
}
else if(dwDataClusters < 65525){
dwFileType = PART_FAT16;
}
else{
dwFileType = PART_FAT32;
dwRootStart = pPart->FAT32.RootEntryCluster;
}
// check consistent
if(dwFileSystem != dwFileType){
if(dwFileSystem != PART_UNKNOWN){
return FALSE;
}
}
// validated FAT, update global state
Partition[PartitionNumber].Bootable = fBootable;
Partition[PartitionNumber].FileSystem = dwFileType;
Partition[PartitionNumber].StartingPartition = dwStart;
Partition[PartitionNumber].PartitionLength = dwLength;
Partition[PartitionNumber].StartingFATEntry = pPart->SectorSize*pPart->ReservedSector;
Partition[PartitionNumber].FATEntryNumber = dwDataClusters+2; // +2 for format identifier
Partition[PartitionNumber].StartingRootEntry = dwRootStart;
Partition[PartitionNumber].RootEntryLength = dwRootLength;
Partition[PartitionNumber].StartingCluster = dwDataStart;
Partition[PartitionNumber].LengthPerCluster = pPart->SectorSize*pPart->SectorPerCluster;
memcpy(&RawPartition[PartitionNumber++], pPart, sizeof(*pPart));
return TRUE;
}
static BOOL InitMasterBootRecord(DWORD dwStart, DWORD dwLength){
int i, j;
BOOL fBootable;
UINT8 buf[DEFAULT_SECTOR_SIZE];
PARTITION_TABLE EmptyPart = {0}; // all zero
PPARTITION_TABLE pPart1, pPart2;
DWORD dwPartStart, dwPartLength;
PMASTERBOOT_RECORD pMBR = (PMASTERBOOT_RECORD)buf;
// we just support 26 MBR
if(MasterBootRecordNumber >= MAX_PARTITION){
return FALSE;
}
// read first sector
if(FATReadDisk(pMBR, sizeof(*pMBR), dwStart) != sizeof(*pMBR)){
return FALSE;
}
// check signature
if(pMBR->Signature != MASTERBOOT_SIGNATURE){
return FALSE;
}
// check partition table
for(i = 0; i < PARTITION_NUMBER; ++i){
pPart1 = &pMBR->Partition[i];
// check empty partition
if(pPart1->SystemId == PARTITION_EMPTY){
if(memcmp(pPart1, &EmptyPart, sizeof(EmptyPart)) != 0){
return FALSE; // empty partition should be all zero
}
continue; // skip follow check
}
// check boot indicator
if(pPart1->BootIndicator!=PARTITION_NORMAL && pPart1->BootIndicator!=PARTITION_SYSTEM){
return FALSE;
}
// check header(0-254)
if(pPart1->StartingHead==0xFF || pPart1->EndingHead==0xFF){
return FALSE;
}
// check sector(1-63)
if(pPart1->StartingSector==0 || pPart1->EndingSector==0){
return FALSE;
}
// check start&length
dwPartStart = pPart1->RelativeSector*GetDefaultSectorSize();
dwPartLength = pPart1->TotalSector*GetDefaultSectorSize();
if(dwPartStart >= dwLength){
return FALSE;
}
if(dwPartLength==0 || dwPartStart+dwPartLength>dwLength){
return FALSE;
}
// check overlap
for(j = i+1; j < PARTITION_NUMBER; ++j){
pPart2 = &pMBR->Partition[j];
// skip empty
if(pPart2->SystemId == PARTITION_EMPTY){
continue;
}
// check start point
if(pPart2->RelativeSector>=pPart1->RelativeSector &&
pPart2->RelativeSector<pPart1->RelativeSector+pPart1->TotalSector){
return FALSE;
}
// check end point
if(pPart2->RelativeSector+pPart2->TotalSector>pPart1->RelativeSector &&
pPart2->RelativeSector+pPart2->TotalSector<=pPart1->RelativeSector+pPart1->TotalSector){
return FALSE;
}
}
}
// validated MBR, copy it!
memcpy(&MasterBootRecord[MasterBootRecordNumber++], pMBR, sizeof(*pMBR));
// init individual partition
for(i = 0; i < PARTITION_NUMBER; ++i){
pPart1 = &pMBR->Partition[i];
fBootable = (pPart1->BootIndicator==PARTITION_SYSTEM);
dwPartStart = dwStart + GetDefaultSectorSize()*pPart1->RelativeSector;
dwPartLength = GetDefaultSectorSize()*pPart1->TotalSector;
switch(pPart1->SystemId){
case PARTITION_FAT12: // FAT12
InitPartition(fBootable, PART_FAT12, dwPartStart, dwPartLength);
break;
case PARTITION_FAT16: // FAT16
case PARTITION_FAT16B:
case PARTITION_FAT16L:
InitPartition(fBootable, PART_FAT16, dwPartStart, dwPartLength);
break;
case PARTITION_FAT32: // FAT32
case PARTITION_FAT32L:
InitPartition(fBootable, PART_FAT32, dwPartStart, dwPartLength);
break;
case PARTITION_EXT: // Extend
case PARTITION_EXTL:
InitMasterBootRecord(dwPartStart, dwPartLength); // recursion!
break;
case PARTITION_EMPTY:
break; // no action
default:
//InitPartition(PART_UNKNOWN, dwPartStart, dwPartLength); // try it?
break;
}
}
return TRUE;
}
// disk function
BOOL FATInitDisk(){
// try to init MBR
if(InitMasterBootRecord(0, FATGetDiskSize())){
return TRUE;
}
// no MBR, try to init partition
if(InitPartition(TRUE, PART_UNKNOWN, 0, FATGetDiskSize())){
return TRUE;
}
// no FAT partition, fail!
return FALSE;
}
DWORD FATGetDiskSize(){
return 0xFFFFFFFF; // TODO: get from SD Card
}
DWORD FATReadDisk(PVOID pBuffer, DWORD dwLength, DWORD dwAddress)
{
// cache for speed up
static DWORD CacheAddress = -1;
static BYTE CacheBuffer[DEFAULT_SECTOR_SIZE];
DWORD dwBytesRead;
// parameter check
if(dwAddress >= FATGetDiskSize())
{
return 0;
}
// adjust dwLength if need
if(dwAddress+dwLength > FATGetDiskSize()){
dwLength = FATGetDiskSize()-dwAddress;
}
dwBytesRead = dwLength;
while(dwLength){
// 1. check cache hit
if(dwAddress>=CacheAddress && dwAddress<CacheAddress+DEFAULT_SECTOR_SIZE)
{
DWORD dwOffset = dwAddress-CacheAddress;
DWORD dwCopyLen = DEFAULT_SECTOR_SIZE-dwOffset;
if(dwLength > dwCopyLen)
{
memcpy(pBuffer, CacheBuffer+dwOffset, dwCopyLen);
(PBYTE)pBuffer += dwCopyLen;
dwAddress += dwCopyLen;
dwLength -= dwCopyLen;
}
else
{
memcpy(pBuffer, CacheBuffer+dwOffset, dwLength);
break;
}
}
if(dwLength<=DEFAULT_SECTOR_SIZE || dwAddress%DEFAULT_SECTOR_SIZE)
{
// fill cache in following condition:
// 1.read buffer less than one block length
// 2.address doesn't align on block length
if (ReadSectors((dwAddress&BLOCK_MASK)/DEFAULT_SECTOR_SIZE, 1, CacheBuffer))
{
return FAT_ERROR;
}
CacheAddress = dwAddress&BLOCK_MASK; // update cache start address
}
else
{
// directly read if space is enough and address is alignment
if (!ReadSectors((dwAddress&BLOCK_MASK)/DEFAULT_SECTOR_SIZE, 1, pBuffer))
{
(PBYTE)pBuffer += DEFAULT_SECTOR_SIZE;
dwAddress += DEFAULT_SECTOR_SIZE;
dwLength -= DEFAULT_SECTOR_SIZE;
}
else
{
return FAT_ERROR;
}
}
}
return dwBytesRead;
}
// partition function
DWORD FATGetPartitionNumber(){
return PartitionNumber;
}
DWORD FATGetPartitionSize(DWORD dwPartNo){
return dwPartNo<PartitionNumber?Partition[dwPartNo].PartitionLength:FAT_ERROR;
}
DWORD FATReadPartition(DWORD dwPartNo, PVOID pBuffer, DWORD dwLength, DWORD dwPos){
// parameter check
if(dwPartNo >= PartitionNumber){
return FAT_ERROR;
}
if(dwPos >= Partition[dwPartNo].PartitionLength){
return 0;
}
// adjust dwLength if need
if(dwPos+dwLength > Partition[dwPartNo].PartitionLength){
dwLength = Partition[dwPartNo].PartitionLength-dwPos;
}
return FATReadDisk(pBuffer, dwLength, Partition[dwPartNo].StartingPartition+dwPos);
}
// file function
BOOL FATOpenFile(PFILEINFO pFileInfo, PCSTR pFileName){
FILEINFO fnFileInfo;
// invalid pFileInfo
ClearFileInfo(pFileInfo);
// find root directory
if(!FindRootDirEntry(&fnFileInfo, &pFileName)){
return FALSE;
}
// find each directory and last file
while(*pFileName){
if(!FATIsDirectory(&fnFileInfo)){ // not directory
return FALSE;
}
if(!FindNextDirEntry(&fnFileInfo, &pFileName)){
return FALSE;
}
}
// copy it
memcpy(pFileInfo, &fnFileInfo, sizeof(*pFileInfo));
return TRUE;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?