📄 fat.c
字号:
/************************************************** * * fat.c * * CVS ID: $Id: * Author: Michal Chlapik [ MCH ] - STM * Date: $Date: 2007/08/15 09:25:20 $ * Revision: $Revision: 1.26 $ * * Description: * * <...> * *************************************************** * * COPYRIGHT (C) ST Microelectronics 2005 * All Rights Reserved * **************************************************** * * STM CVS Log: * * $Log: FAT.c,v $ * Revision 1.26 2007/08/15 09:25:20 trubac * error handling improved in FAT entry parsing * * Revision 1.25 2007/07/24 15:50:10 trubac * Fix for slow FAT mounting, FatEntryCheck added * * Revision 1.24 2007/06/04 16:58:44 longauer * USBtask rearrangement in order to support more logical units; new file usb_pri.h added with USBtask private declarations; USB compilation switches added; constants renaming; * * Revision 1.23 2007/05/09 07:31:09 chlapik * handling of situation if some cluster is marked as bad in FAT table * * Revision 1.22 2007/01/30 12:35:21 chlapik * max device block size as #define set to 2048B * * Revision 1.21 2007/01/29 14:32:00 chlapik * support for USB devices with any block size (not only 512B) * * Revision 1.20 2006/10/23 13:47:10 belardi * Added variable initialization to remove compiler warning * * Revision 1.19 2006/09/18 09:55:22 belardi * Corrected CVS keyword usage * * Revision 1.18 2006/09/18 09:24:02 belardi * Added Log CVS keyword into file header * * ***************************************************/#include "configuration.h"#if (HAVE_FAT)#include "apdevsys.h"#include "debug.h"#include "utf8.h"#include <ctype.h>#include "xfile.h"#include "filesys.h"#include "FAT.h"#include "usb.h"uint32 Get_RootDirSectors(BPB_boot_common_t *BPB_boot_common){ if(BPB_boot_common->RootEntCnt) return ( (((uint32)(BPB_boot_common->RootEntCnt)<<5)+BPB_boot_common->BytesPerSec-1)>>get_val_log2(BPB_boot_common->BytesPerSec) ); else return 0;}uint32 Get_FirstDataSector(BPB_boot_common_t *BPB_boot_common){ uint32 FATSz; if((BPB_boot_common->FATSz16) != 0) FATSz = BPB_boot_common->FATSz16; else FATSz = BPB_boot_common->FATSz32Estim; return BPB_boot_common->RsvdSecCnt+BPB_boot_common->NumFATs*(uint32)FATSz+Get_RootDirSectors(BPB_boot_common);}uint32 Get_FirstSectorofCluster(BPB_boot_common_t *BPB_boot_common, uint32 FirstDataSector, uint32 Cluster){ return (Cluster-2)*BPB_boot_common->SecPerClust+FirstDataSector;}uint32 Get_FAT12_16_FirstRootDirSecNum(BPB_boot_common_t *BPB_boot_common){ //FAT 12 or 16 return BPB_boot_common->RsvdSecCnt+BPB_boot_common->NumFATs*(uint32)(BPB_boot_common->FATSz16);}uint8 ParseShortEntryName(uint8 *ShortEntry, uint16 *Name, uint8 *Ext){ uint8 Character; uint8 i,j=0,k; //scan first 8 characters for(i=0;i<8;i++) { if((Character=ShortEntry[i])==0x20) break; Name[i]=(uint16)Character; } //scan for ext if(ShortEntry[8]!=0x20) { //there is ext Name[i]=0x2E; i++; for(j=0;j<3;j++) { if((Character=ShortEntry[8+j])==0x20) break; Name[i+j]=(uint16)Character; Ext[j]=Character; } //fill the rest of Ext with 0x20 for(k=0;k<3-j;k++) Ext[k+j]=0x20; } else { //no ext, fill Ext array with 0x20 for(k=0;k<3;k++) Ext[k]=0x20; } return (i+j);}uint8 ParseLongEntryName(uint8 *LongEntry, uint16 *Name){ uint16 Character; uint8 NumOfCharacters=0; uint8 i; //scan 5 characters, 1-5 for(i=0;i<5;i++) {#ifdef DSP if((Character=*((PACKED uint16*)&LongEntry[1+2*i])) != 0x0)#else if((Character=*((uint16*)&LongEntry[1+2*i])) != 0x0)#endif { Name[i] = Character; NumOfCharacters++; } else return NumOfCharacters; } //scan 6 characters, 6-11 for(i=0;i<6;i++) {#ifdef DSP if((Character=*((PACKED uint16*)&LongEntry[14+2*i])) != 0x0)#else if((Character=*((uint16*)&LongEntry[14+2*i])) != 0x0)#endif { Name[i+5] = Character; NumOfCharacters++; } else return NumOfCharacters; } //scan 2 characters, 12-13 for(i=0;i<2;i++) {#ifdef DSP if((Character=*((PACKED uint16*)&LongEntry[28+2*i])) != 0x0)#else if((Character=*((uint16*)&LongEntry[28+2*i])) != 0x0)#endif { Name[i+11] = Character; NumOfCharacters++; } else return NumOfCharacters; } return NumOfCharacters;}uint8 ChkSum(uint8 *Name){ uint8 Sum; int FcbNameLen; Sum = 0; for(FcbNameLen=11;FcbNameLen!=0;FcbNameLen--) Sum = ((Sum & 1) ? 0x80 : 0) + (Sum >> 1) + *Name++; return Sum;}boolean CmpExts(uint8 *ExtTblItem, uint8 *Ext){ uint32 j; for(j=0;j<3;j++) { if(ExtTblItem[j]!=Ext[j]) return false; } return true;}boolean FindExtInTbl(uint8 ExtTbl[][3], uint8 *Ext, uint32 ExtTblLen){ uint32 i; for(i=0;i<ExtTblLen;i++) { //tbl item if(CmpExts(ExtTbl[i],Ext)) return true; } return false;}boolean CheckIfEOF(BPB_boot_common_t *BPB_boot_common, uint32 FATContent){ switch(BPB_boot_common->FATType) { case 1: if(FATContent >= 0x0FF8) return true; break; case 2: if(FATContent >= 0xFFF8) return true; break; case 0: if(FATContent >= 0x0FFFFFF8) return true; break; } return false;}boolean CheckIfBadCluster(BPB_boot_common_t *BPB_boot_common, uint32 FATContent){ switch(BPB_boot_common->FATType) { case 1: if(FATContent == 0x0FF7) return true; break; case 2: if(FATContent == 0xFFF7) return true; break; case 0: if(FATContent == 0x0FFFFFF7) return true; break; } return false;}SectorAndOffset_t Get_SectorAndOffset(BPB_boot_common_t *BPB_boot_common, uint32 Cluster){ uint32 FATOffset; SectorAndOffset_t SectorAndOffset; switch(BPB_boot_common->FATType) { case 0: FATOffset = (Cluster<<2); //FAT 32 break; case 1: FATOffset = Cluster + (Cluster>>1); //FAT 12 break; default: // [RB] initialize to some sane value to avoid compiler warning case 2: FATOffset = (Cluster<<1); //FAT 16 break; } SectorAndOffset.Sector = BPB_boot_common->RsvdSecCnt + (FATOffset>>get_val_log2(BPB_boot_common->BytesPerSec)); //SectorAndOffset.Offset = FATOffset - temp*BPB_boot_common->BytesPerSec; SectorAndOffset.Offset = (FATOffset & (BPB_boot_common->BytesPerSec-1)); return SectorAndOffset;}GRESULT Get_FATEntry(FS_DESCRIPTOR *fsd, uint32 *FATClusEntryVal, uint8 *SecBuff){ //uint8 SecBuff[4096]; //alloc memory for sector of size BytesPerSec SectorAndOffset_t FATEntry; uint32 Cluster = *FATClusEntryVal; GRESULT ReturnCode; uint32 i,FATSz; FATEntry = Get_SectorAndOffset(&(fsd->PD.FAT_pd.BPB_boot_common),Cluster); if((fsd->PD.FAT_pd.BPB_boot_common.FATSz16) != 0) FATSz = fsd->PD.FAT_pd.BPB_boot_common.FATSz16; else FATSz = fsd->PD.FAT_pd.BPB_boot_common.FATSz32Estim; //read sector for Cluster for(i=0;i<fsd->PD.FAT_pd.BPB_boot_common.NumFATs;i++) { //scan all FAT tables in case of unavailable block if ((ReturnCode=Get_SectorRel(SecBuff,FATEntry.Sector+i*FATSz,fsd)) == S_OK) break; else if(ReturnCode == E_FORCED_UNPLUG) break; } if(ReturnCode != S_OK) { #ifdef DEBUGGING printf("Can't read sector, EOF!\n");#endif return ReturnCode; } switch(fsd->PD.FAT_pd.BPB_boot_common.FATType) { case 2: //FAT16#ifdef DSP *FATClusEntryVal = *((PACKED uint16*)&SecBuff[FATEntry.Offset]);#else *FATClusEntryVal = *((uint16*)&SecBuff[FATEntry.Offset]);#endif return S_OK; case 0: //FAT32#ifdef DSP *FATClusEntryVal = (*((PACKED uint32*)&SecBuff[FATEntry.Offset])) & 0x0FFFFFFF;#else *FATClusEntryVal = (*((uint32*)&SecBuff[FATEntry.Offset])) & 0x0FFFFFFF;#endif return S_OK; case 1: //FAT12 if((FATEntry.Offset) == (fsd->PD.FAT_pd.BPB_boot_common.BytesPerSec-1)) { //continue of FAT entry is in the next sector, so read it *FATClusEntryVal = SecBuff[fsd->PD.FAT_pd.BPB_boot_common.BytesPerSec-1]; //read sector for next Cluster for(i=0;i<fsd->PD.FAT_pd.BPB_boot_common.NumFATs;i++) { //scan all FAT tables in case of unavailable block if ((ReturnCode=Get_SectorRel(SecBuff,FATEntry.Sector+1+i*FATSz,fsd)) == S_OK) break; else if(ReturnCode == E_FORCED_UNPLUG) break; } if(ReturnCode != S_OK) { #ifdef DEBUGGING printf("Can't read sector, EOF!\n");#endif return ReturnCode; } *FATClusEntryVal = (((uint32)(SecBuff[0]))<<8) | (*FATClusEntryVal); } else#ifdef DSP *FATClusEntryVal = *((PACKED uint16*)&SecBuff[FATEntry.Offset]);#else *FATClusEntryVal = *((uint16*)&SecBuff[FATEntry.Offset]);#endif if(Cluster&0x0001) *FATClusEntryVal = *FATClusEntryVal >> 4; //Cluster number is ODD else *FATClusEntryVal = *FATClusEntryVal & 0x0FFF; //Cluster number is EVEN return S_OK; } return E_PARAMETER_OUT_OF_RANGE; // should not come to this point}/*void FillExtTbl(FS_DESCRIPTOR *fsd, char ExtTblOEM[][4], uint32 ExtTblLen){ uint32 i,j,k;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -