www.pudn.com > arm_uDisk.rar > F_FAT.c
/***************************************************************/
/*
* F_FAT.c, 20070206, denny
*
* A Marconix Software Product
* Copyright(c) Marconix Co., Ltd. 2007
* All Rights Reserved. Reproduction, adaption, or
* translation without prior written permission is
* prohibited, except as allowed under the copyright laws.
*/
/***************************************************************/
#include "inc.h"
#include "F_system.h"
#include "F_driver.h"
#include "F_FAT.h"
tHANDLE hFile;
u8 SectorBuffer[F_SectorSize] = {0};
u8 *prSectorBuf = SectorBuffer;
FAT_HANDLE CurrentHandle;
u8 FATBuffer[FAT_BUF_SIZE] = {0};
u8 *prFATBuffer = FATBuffer;
u8 g_lfnflag = 0;
c8 g_CurrentDir[20] = ":\\";
u16 g_longfilename[MAX_LFN_BUF] = {0};
c8 g_direntry[MAX_LAYER][MAX_DIR_LEN] = {0};
u32 BufferDataGet(u8 num, u8 *buffer)
{
u8 i = 0;
u32 u32data = 0;
for(;ibpbBytesPerSec = (u16)BufferDataGet(2, buffer);buffer+=2;
bpb->bpbSecPerClust = (u8)BufferDataGet(1, buffer);buffer+=1;
bpb->bpbResSectors = (u16)BufferDataGet(2, buffer);buffer+=2;
bpb->bpbFATs = (u8)BufferDataGet(1, buffer);buffer+=1;
bpb->bpbRootDirEnts = (u16)BufferDataGet(2, buffer);buffer+=2;
bpb->bpbSectors = (u16)BufferDataGet(2, buffer);buffer+=2;
bpb->bpbMedia = (u8)BufferDataGet(1, buffer);buffer+=1;
bpb->bpbFATsecs = (u16)BufferDataGet(2, buffer);buffer+=2;
bpb->bpbSecPerTrack = (u16)BufferDataGet(2, buffer);buffer+=2;
bpb->bpbHeads = (u16)BufferDataGet(2, buffer);buffer+=2;
bpb->bpbHiddenSecs = BufferDataGet(4, buffer);buffer+=4;
bpb->bpbHugeSectors = BufferDataGet(4, buffer);buffer+=4;
bpb->bpbBigFATsecs = BufferDataGet(4, buffer);buffer+=4;
bpb->bpbExtFlags = (u16)BufferDataGet(2, buffer);buffer+=2;
bpb->bpbFSVers = (u16)BufferDataGet(2, buffer);buffer+=2;
bpb->bpbRootClust = BufferDataGet(4, buffer);buffer+=4;
bpb->bpbFSInfo = (u16)BufferDataGet(2, buffer);buffer+=2;
bpb->bpbBackup = (u16)BufferDataGet(2, buffer);buffer+=2;
for(;j<12;)
bpb->bpbReserved[j++] = (u8)BufferDataGet(1, buffer);buffer+=1;
}
u8 F_FAT_Init( u8 Index)
{
F_bpb710 bpb;
F_partrecord PartInfo;
u32 TotalSectors = 0;
FAT_HANDLE *F_Handle = &CurrentHandle;
PartInfo.prStartLBA = 0;
if(F_ReadSector(hFile, PartInfo.prStartLBA, 1, prSectorBuf))
return F_ERR_DRIVER_READ_FAILURE;
if(prSectorBuf[0] == 0xE9 || (prSectorBuf[0] == 0xEB && prSectorBuf[2] == 0x90))//It's Boot Sector
{
// Uart_Printf("Boot sector\n");
if(prSectorBuf[510] != BOOTSIG0 || prSectorBuf[511] != BOOTSIG1 )
return F_ERR_INVALID_BOOT_SECTOR;
}
else//It's MBR
{
// Uart_Printf("MBR\n");
if(prSectorBuf[510] != BOOTSIG0 || prSectorBuf[511] != BOOTSIG1 )
return F_ERR_INVALID_MBR;
PartInfo.prStartLBA = (u32)((((u32)prSectorBuf[0x1C9])<<24) + (((u32)prSectorBuf[0x1C8])<<16)+ (((u32)prSectorBuf[0x1C7])<<8) + (prSectorBuf[0x1C6]));
if(F_ReadSector(hFile, PartInfo.prStartLBA, 1, prSectorBuf))
return F_ERR_DRIVER_READ_FAILURE;
if(prSectorBuf[510] != BOOTSIG0 || prSectorBuf[511] != BOOTSIG1 )
return F_ERR_INVALID_BOOT_SECTOR;
}
F_FAT_GetBPB(&bpb, (u8 *)(((F_bootsector710*)prSectorBuf)->bsBPB));
F_Handle->FirstDataSector = PartInfo.prStartLBA;
if(bpb.bpbFATsecs)
{
F_Handle->FatSectors = bpb.bpbFATsecs;
}
else
{
F_Handle->FatSectors = bpb.bpbBigFATsecs;
}
F_Handle->RootDirSectors = ((bpb.bpbRootDirEnts * 32) + (bpb.bpbBytesPerSec -1))/bpb.bpbBytesPerSec;
F_Handle->FirstDataSector += (bpb.bpbResSectors + bpb.bpbFATs * F_Handle->FatSectors) + F_Handle->RootDirSectors;
if(bpb.bpbSectors)
{
TotalSectors = bpb.bpbSectors;
}
else
{
TotalSectors = bpb.bpbHugeSectors;
}
F_Handle->NumClusters = (TotalSectors - (bpb.bpbResSectors + (bpb.bpbFATs * F_Handle->FatSectors) + F_Handle->RootDirSectors))/ bpb.bpbSecPerClust;
//FAT Type Determination by count of Clusters
if(F_Handle->NumClusters < 4085)
{
F_Handle->PartType = PART_TYPE_FAT12;
}
else if(F_Handle->NumClusters < 65525)
{
F_Handle->PartType = PART_TYPE_FAT16;
}
else
{
F_Handle->PartType = PART_TYPE_FAT32;
}
F_Handle->SectorsPerCluster = bpb.bpbSecPerClust;
F_Handle->FirstFATSector = bpb.bpbResSectors + PartInfo.prStartLBA;
switch (F_Handle->PartType)
{
case PART_TYPE_FAT16:
F_Handle->FirstDirCluster = 0;//first legal cluster number for FAT16 , the First Data Cluster is 2 , the Root Entry is fixed
break;
case PART_TYPE_FAT32:
F_Handle->FirstDirCluster = bpb.bpbRootClust;//Usually 2 but not required to be 2 , it should be 2 unless it's marked bad.
break;
default:
return F_ERR_UNSUPPORTED_PARTITION_TYPE;
}
if (F_Handle->PartType == PART_TYPE_FAT32)
{
F_Handle->FirstFAT2Sector=F_Handle->FirstFATSector+bpb.bpbBigFATsecs;
}
else
{
F_Handle->FirstFAT2Sector=F_Handle->FirstFATSector+bpb.bpbFATsecs;
}
F_Handle->BytesPerSector = bpb.bpbBytesPerSec;
F_Handle->currentDirCluster= F_Handle->FirstDirCluster;
/*
Uart_Printf("F_Handle->PartType = %d\n",F_Handle->PartType);
Uart_Printf("F_Handle->BytesPerSector = %d\n",F_Handle->BytesPerSector);
Uart_Printf("F_Handle->FirstDataSector = %d\n",F_Handle->FirstDataSector);
Uart_Printf("F_Handle->SectorsPerCluster = %d\n",F_Handle->SectorsPerCluster);
Uart_Printf("F_Handle->FirstFATSector = %d\n",F_Handle->FirstFATSector);
Uart_Printf("F_Handle->FirstDirCluster = %d\n",F_Handle->FirstDirCluster);
Uart_Printf("F_Handle->FatSectors = %d\n",F_Handle->FatSectors);
Uart_Printf("F_Handle->NumClusters = %d\n",F_Handle->NumClusters);
Uart_Printf("F_Handle->currentDirCluster = %d\n",F_Handle->currentDirCluster);
*/
return ERR_NONE;
}
u8 F_FAT_FolderChange(FAT_HANDLE *pHandle, c8 *FolderName)
{
F_BrowsingCursor cursor;
F_direntry de;
F_FolderInfo folderInfo;
u16 unicode[MAX_LFN_BUF] = {0};
c8 tmpname[MAX_LFN_BUF] = {0};
c8 tmpname1[MAX_LFN_BUF] = {0};
if(!strcmp(FolderName, "\\\\"))
{
F_FAT_DirInit(pHandle);
}
else
{
strcpy(tmpname, FolderName);
strupr(tmpname);
g_lfnflag = 0;
memset((u8 *)g_longfilename, 0, MAX_LFN_BUF);
F_FAT_BrowsingReset(pHandle, &cursor);
for(;F_FAT_GetNextDirEntry(pHandle, &de, &cursor, MAX_LFN_BUF, g_longfilename) == 0;)
{
if(de.deAttributes == ATTR_DIRECTORY)
{
if(g_lfnflag)
{
memcpy((u8 *)unicode, (u8 *)g_longfilename, MAX_LFN_BUF);
MX_UniStrToGB2312Str(unicode, folderInfo.folderINF_Name);
g_lfnflag = 0;
strcpy(tmpname1, folderInfo.folderINF_Name);
strupr(tmpname1);
if(!strcmp(tmpname, tmpname1))
{
folderInfo.folderINF_start_cluster = de.deStartCluster + (de.deHighClust<<16);
//printf("(LFN)File Name: %s,\tStart Cluster:%d,\n", folderInfo.folderINF_Name, folderInfo.folderINF_start_cluster);
F_FAT_DirSet(folderInfo.folderINF_Name);
pHandle->currentDirCluster = folderInfo.folderINF_start_cluster;
return ERR_NONE;
}
}
else
{
F_FAT_DirEntryToSFN(&de, folderInfo.folderINF_Name, 13);
strcpy(tmpname1, folderInfo.folderINF_Name);
strupr(tmpname1);
if(!strcmp(tmpname, tmpname1))
{
folderInfo.folderINF_start_cluster = de.deStartCluster + (de.deHighClust<<16);
//printf("(SFN) File Name: %s,\tStart Cluster:%d,\n", folderInfo.folderINF_Name, folderInfo.folderINF_start_cluster);
F_FAT_DirSet(folderInfo.folderINF_Name);
pHandle->currentDirCluster = folderInfo.folderINF_start_cluster;
return ERR_NONE;
}
}
}
g_lfnflag = 0;
memset((u8 *)g_longfilename, 0, MAX_LFN_BUF);
}
}
return F_ERR_FILE_NOT_EXIST;
}
void F_FAT_DirSet(c8 *dirname)
{
u32 dirlen = strlen(dirname);
u32 latestlen = strlen(g_CurrentDir);
u8 i=0,j=0;
if(!strcmp(dirname, ".."))
{
if(latestlen <= 3)
return ;
else
{
for(i = (latestlen-2);i>2;i--)
{
if(g_CurrentDir[i] != '\\')
g_CurrentDir[i] = '\0';
else
break;
}
}
}
else
{
for(i=latestlen;iPartType == PART_TYPE_FAT32)
{
if (Cluster == 0)
Cluster=pHandle->FirstDirCluster;
}
else
{
if (Cluster == 0)
return pHandle->FirstDataSector - pHandle->RootDirSectors;
}
return ((Cluster-2) * pHandle->SectorsPerCluster) + pHandle->FirstDataSector;
}
u32 F_FAT_SectorToCluster(FAT_HANDLE *pHandle,u32 Sector)
{
if(Sector >= pHandle->FirstDataSector)
return (((Sector - pHandle->FirstDataSector) / pHandle->SectorsPerCluster) + 2);
else//FAT16 Root Folder
return 0;
}
u8 F_FAT_GetNextDirEntry(FAT_HANDLE *pHandle, F_direntry *pde, F_BrowsingCursor *Cursor, u16 LFNlen, u16 *LFNBuf)
{
u8 Error = ERR_NONE, i = 0;
u32 u32currnetsector = 0, nextCluster = 0, nextSector = 0;
F_direntry *de;
for(;;Cursor->SectorOffset++)
{
if((Cursor->SectorOffset%pHandle->SectorsPerCluster == 0)&&(Cursor->DirEntryIndex == 0))
{
if(Cursor->SectorOffset == 0 && Cursor->CurrentSectorAddr == F_FAT_ClusterToSector(pHandle, pHandle->currentDirCluster))
{
if(F_ReadSector(hFile, Cursor->CurrentSectorAddr, 1, prSectorBuf))
return F_ERR_DRIVER_READ_FAILURE;
de = (F_direntry *)prSectorBuf;
}
else
{
Cursor->SectorOffset = 0;
nextCluster = F_FAT_GetNextCluster(pHandle, F_FAT_SectorToCluster(pHandle, Cursor->CurrentSectorAddr));
if(nextCluster == 0)
return EOF_FATCHAIN;
nextSector = F_FAT_ClusterToSector(pHandle, nextCluster);
Cursor->CurrentSectorAddr = nextSector;
if(F_ReadSector(hFile, Cursor->CurrentSectorAddr, 1, prSectorBuf))
return F_ERR_DRIVER_READ_FAILURE;
de = (F_direntry *)prSectorBuf;
}
}
else
{
if(Cursor->DirEntryIndex == 0)
{
Cursor->CurrentSectorAddr ++;//= Cursor->SectorOffset;
}
if(F_ReadSector(hFile, Cursor->CurrentSectorAddr, 1, prSectorBuf))
return F_ERR_DRIVER_READ_FAILURE;
de = (F_direntry *)prSectorBuf;
}
if(de == NULL)
return EOF_CLUSTER;
for(de += Cursor->DirEntryIndex;Cursor->DirEntryIndex<(pHandle->BytesPerSector/DIRENTRY_SIZE); Cursor->DirEntryIndex++)
{
if(*de->deName == SLOT_EMPTY)
{
return EOF_CLUSTER;
}
if((LFNlen!=0)&&(*de->deName != SLOT_DELETED)&&(de->deAttributes== ATTR_LONG_FILENAME))
{
F_FAT_GetLFN((u8 *)de, LFNBuf);
g_lfnflag = 1;
}
if((*de->deName != SLOT_DELETED)&&(de->deAttributes != ATTR_LONG_FILENAME))
{
*pde = *de;
Cursor->DirEntryIndex++;
return ERR_NONE;
}
else
{
de++;
}
}
Cursor->DirEntryIndex = 0;
}
return EOF_FATCHAIN;
}
u32 F_FAT_GetNextCluster(FAT_HANDLE *pHandle, u32 Cluster)
{
u32 u32currnetsector = 0, nextCluster = 0;
u32 sectorIndex = 0, fatmask = 0xffffffff;
u16 sectorOffset = 0;
u8 Buffer[512] = {0}, fatoffset = 0;
if(pHandle->PartType == PART_TYPE_FAT32)
{
if(Cluster == 0)
Cluster = pHandle->FirstDirCluster;
fatoffset = 4;
fatmask = FAT32_MASK;
}
else if(pHandle->PartType == PART_TYPE_FAT16)
{
if(Cluster == 0)
return 0;
fatoffset = 2;
fatmask = FAT16_MASK;
}
sectorIndex = Cluster/(pHandle->BytesPerSector/fatoffset);
sectorOffset = Cluster%(pHandle->BytesPerSector/fatoffset);//by bytes * 4
u32currnetsector = pHandle->FirstFATSector + sectorIndex;
if(F_ReadSector(hFile, u32currnetsector, 1, prFATBuffer))
return F_ERR_DRIVER_READ_FAILURE;
nextCluster = *((u32 *)(&prFATBuffer[sectorOffset*fatoffset])) & fatmask;
if(nextCluster == fatmask)
nextCluster = 0;
return nextCluster;
}
void F_FAT_BrowsingReset(FAT_HANDLE *pHandle, F_BrowsingCursor *Cursor)
{
Cursor->CurrentEntryIndex = 0;
Cursor->CurrentSectorAddr = F_FAT_ClusterToSector(pHandle, pHandle->currentDirCluster);
Cursor->DirEntryIndex = 0;
Cursor->SectorOffset = 0;
}
void F_FAT_GetLFN(u8 *debuf, u16 *LFN)
{
u8 i = 0, LfnCounter = 0, j = 0;
LfnCounter = debuf[i++]&0x0F;
for(j = 0;j<5;j++,i +=2)
LFN[(LfnCounter-1)*13 + j] = debuf[i] + (debuf[i+1]<<8);
i += 3;
for(j = 5;j<11;j++,i+=2)
LFN[(LfnCounter-1)*13 + j] = debuf[i] + (debuf[i+1]<<8);
i += 2;
for(j = 11;j<13;j++,i+=2)
LFN[(LfnCounter-1)*13 + j] = debuf[i] + (debuf[i+1]<<8);
}
u8 F_FAT_DirEntryToSFN(F_direntry *pde, c8 *SFNBuf, u8 SFNlen)
{
u8 i,j = 0;
if(SFNlen < 13)
return 1;
memset(SFNBuf,0,SFNlen);
for(i=0;i<8;i++)
{
if(pde->deName[i] == 0x20)
break;
else
SFNBuf[i] = (c8)(pde->deName[i]);
}
if((pde->deLowerCase & LCASE_BASE) == LCASE_BASE)
strlwr(SFNBuf);
if(pde->deExtension[0] != 0x20)
{
SFNBuf[strlen(SFNBuf)] = '.';
i = strlen(SFNBuf);
for(j=0;j<3;j++)
{
if(pde->deExtension[j] == 0x20)
break;
else
SFNBuf[i+j] = (c8)(pde->deExtension[j]);
}
if((pde->deLowerCase & LCASE_EXT) == LCASE_EXT)
strlwr(&SFNBuf[i]);
}
return 0;
}
u8 F_FAT_GetFileInfo(F_direntry *pde, F_FileInfo *fileInfo)
{
u16 date, time;
fileInfo->fileINF_size = pde->deFileSize;
fileInfo->fileINF_start_cluster = pde->deStartCluster + (pde->deHighClust<<16);
return 0;
}
u8 F_FAT_CheckIfLFN(c8 *filename, u8 *fdbnum)
{
u16 i = 0;
c8 *ePtr;
u16 eNameLen,eNameOff=0;
c8 c;
u16 FirstSpacePos=0;
u8 SpaceCount=0;
u16 FirstDotPos=0;
u8 DotNum=0;
u16 ExtPos=0;
u8 ExtFlag=0;
u8 SpecialCharExist=0;
u16 unicode[MAX_LFN_BUF] = {0};
eNameLen = strlen(filename);
ePtr = filename;
eNameOff=i;
ePtr+=i;
for(i=eNameOff;i 12)
||(ExtPos>3)||(DotNum>1)
||(((FirstSpacePos+SpaceCount)<(eNameLen-eNameOff))&&(SpaceCount>0))
||(SpecialCharExist)
|| ((FirstDotPos==0)&&(eNameLen-eNameOff > 8)))
{
eNameLen = MX_GB2312StrToUniStr((u8 *)filename, unicode);
*fdbnum += eNameLen/13;
if(eNameLen%13 !=0)
*fdbnum +=1;
return 1;
}else
{
return 0;
}
}
u8 F_FAT_GetExtName(c8 * filename, c8 * ExtName)
{
u8 i = 0,j = 0, namelen = strlen(filename);
for(i = 0; i> 1)) + shortname[i];
}
return Sum;
}
void F_FAT_NormalizeName(c8 *oriname, c8 *tarname)
{
u8 i =0, len = strlen(tarname);
c8 extname[4] = {0};
for(;icurrentDirCluster = pHandle->FirstDirCluster;
}
u8 F_FAT_GetDirLayer(c8 *Direntry, u8 *Layer)
{
u8 i = 0, layer = 0, j= 0;
if(Direntry[0]!= g_CurrentDir[0])
return ERR_DIRENTRY;
memset((u8 *)g_direntry, 0, MAX_DIR_LEN*MAX_LAYER);
for(layer = 0; layer