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