📄 fat.h
字号:
#ifndef __Fat_h__
#define __Fat_h__
// 以下默认每扇区512字节
// sizeof(FILE_INFO) = 32
typedef struct
{
uint16 SectorBytes; //每扇区字节数
uint8 SectorsPerCluster; //每簇扇区数
uint16 ReservedSectors; //保留扇区数
uint8 NbrFat; //FAT的个数
uint16 RootEntry; //根目录项数
uint16 TotalSectors; //分区总扇区数(分区小于32M时)
uint8 Media; //分区介质标识
uint16 SectorsPerFAT; //每个FAT占的扇区数
uint16 SectorsPerTrack; //每道扇区数
uint16 Heads; //磁头数
uint32 HiddenSectors; //隐含扇区数
uint32 BigTotalSectors; //分区总扇区数(分区大于32M时)
uint32 FATSz32; //FAT32中每个FAT占的扇区数
uint16 ExtFlags;
uint16 FSVer;
uint32 RootClus;
}BPB_FAT16;
typedef struct
{
uint8 BootFlag; //启动标志
uint8 StartCHS[3]; //分区开始的柱面、磁头、扇区
uint8 SystemID; //分区类型
uint8 EndCHS[3]; //分区结束的柱面、磁头、扇区
uint32 RelativeSectors; //分区相对扇区数,指分区相对于记录该分区的分区表的扇区位置之差
uint32 TotalSectors; //分区总扇区数
}PARTITION_TABLE;
typedef struct
{
uint8 FileName[8]; //文件正名
uint8 FileExtName[3]; //文件扩展名
uint8 Attribute; //文件属性
uint8 Nouse0[2]; //仅长文件名目录项用,用来存储其对应的短文件名目录项的文件名字节校验和等。
uint16 FileTime; //16位二进制的文件建立时间,其中的高5位为小时,次6位为分钟。
uint16 FileDate; //16位二进制的文件建立日期,其中的高7位为相对于1980年的年份值,次4位为月份,后5位为月内日期。
uint16 FileNewAccessDate; //16位二进制的文件访问日期,其中的高7位为相对于1980年的年份值,次4位为月份,后5位为月内日期。
uint16 High16; //起始簇号的高16位。
uint16 FileNewModifyTime; //16位二进制的文件最新修改时间,其中的高5位为小时,次6位为分钟,后5位的二倍为秒数。
uint16 FileNewModifyDate; //16位二进制的文件最新修改日期
uint16 Low16; //起始簇号的低16位。
uint32 FileLength; //32位的文件字节长度。
}FILE_INFO;
typedef struct
{
uint32 StartClusterNum; // 簇链指针
uint32 StartAddress; // 当前簇的起始扇区地址
uint8 NowSectorInCluster; // 当前簇中的第几扇区
uint16 NowDataInSector; // 当前扇区的数据指针
}FILE_INFO_RW;
PARTITION_TABLE First_Partition;
BPB_FAT16 Bpb_Fat16;
FILE_INFO File_Information;
uint8 FAT_ID = 0x06;
uint32 FAT1Start;
uint32 FAT2Start;
uint32 DIRStart;
uint32 DIREnd;
uint32 SecondClusterStart;
uint16 FAT1[259];
uint8 FAT1num;
#define MAXFILENUMREAD 1
#define MAXFILENUMWRITE 1
#define MAXFILENUM MAXFILENUMREAD+MAXFILENUMWRITE
#define MAXFILECHAINLEN 2048
// 能处理文件最大大小为MAXFILECHAINLEN*SectorsPerCluster*SectorBytes
uint8 RWFileStatus[MAXFILENUM];
FILE_INFO RWFileInfo[MAXFILENUM];
uint32 RWFileClusterChain[MAXFILENUM][MAXFILECHAINLEN];
uint8 RWFileTempBuffer[MAXFILENUMWRITE][512];
FILE_INFO_RW FileInfoRW[MAXFILENUM];
// 文件号最大到MAX(0xFE,MAXFILENUM)
uint8 FindUnusedFileNum(uint8 sel)
{
uint8 i;
if( sel == 0)
{
for(i=0;i<MAXFILENUMWRITE;i++) if(RWFileStatus[i] == 0) return i;
}
else if( sel == 1 )
{
for(i=MAXFILENUMWRITE;i<MAXFILENUM;i++) if(RWFileStatus[i] == 0) return i;
}
return 0xFF;
}
uint8 DiscardFile(uint8 filenum)
{
if(filenum < MAXFILENUM) RWFileStatus[filenum] = 0;
else return 0x10;
return 0x00;
}
void DiscardAllFiles(void)
{
uint8 i;
for(i=0;i<MAXFILENUM;i++) RWFileStatus[i]= 0;
}
uint8 Fat_Initial(void)
{
uint16 i,j;
UFI_Read10(0);
if(ReadBlockData[0] == 0xfa && ReadBlockData[1] == 0x33)
{
for(i = 0; i< 16; i++) ((uint8*)&First_Partition)[i] = ReadBlockData[446+i]; // 0x01BE
if(First_Partition.SystemID != 0x06 && First_Partition.SystemID != 0x04 && First_Partition.SystemID != 0x01 && First_Partition.SystemID != 0x0B)
{
puts("Not Fat16 or FAT12 or FAT32 File system1!\n");
return 0x10;
}
FAT_ID = First_Partition.SystemID;
}
else if(ReadBlockData[0] == 0x33 && ReadBlockData[1] == 0xc0)
{
for(i = 0; i< 16; i++) ((uint8*)&First_Partition)[i] = ReadBlockData[446+i]; // 0x01BE
if(First_Partition.SystemID != 0x06 && First_Partition.SystemID != 0x04 && First_Partition.SystemID != 0x01 && First_Partition.SystemID != 0x0B)
{
puts("Not Fat16 or FAT12 or FAT32 File system2!\n");
return 0x10;
}
FAT_ID = First_Partition.SystemID;
}
else
{
First_Partition.RelativeSectors = 0; // First_Partition.RelativeSectors 不一定可用,所以强制赋0
if(ReadBlockData[0x39] == 0x31)
{
if(ReadBlockData[0x3A] == 0x32) FAT_ID = 0x01;
else if(ReadBlockData[0x3A] == 0x36) FAT_ID = 0x06;
else
{
puts("Not Fat16 or FAT12 or FAT32 File system3!\n");
return 0x09;
}
}
else if(ReadBlockData[0x39] == 0x33 && ReadBlockData[0x3a] == 0x32)
{
FAT_ID = 0x0B;
}
else
{
puts("Not Fat16 or FAT12 or FAT32 File system4!\n");
return 0x10;
}
}
printf("FAT_ID is %x\n",FAT_ID);
UFI_Read10(First_Partition.RelativeSectors);
if( ReadBlockData[0]!=0xEB && ReadBlockData[0]!=0xE9)
{
printf("Error sector!");
return 0x11;
}
for(i = 0; i< 37; i++) ((uint8*)&Bpb_Fat16)[i] = ReadBlockData[11+i]; // 0x0B
if( Bpb_Fat16.SectorBytes != 512)//每个扇区为512字节
{
puts("Bytes per sector is not 512! Not supportted!\n");
return 0x12;
}
if( FAT_ID == 0x0B )
{
FAT1Start = First_Partition.RelativeSectors+Bpb_Fat16.ReservedSectors;
FAT2Start = FAT1Start + Bpb_Fat16.FATSz32;
DIRStart = FAT2Start + Bpb_Fat16.FATSz32;
DIREnd = DIRStart + Bpb_Fat16.RootClus*Bpb_Fat16.SectorsPerCluster - 1;
SecondClusterStart = DIRStart;
}
else
{
FAT1Start = First_Partition.RelativeSectors+Bpb_Fat16.ReservedSectors;
FAT2Start = FAT1Start + Bpb_Fat16.SectorsPerFAT;
DIRStart = FAT2Start + Bpb_Fat16.SectorsPerFAT;
SecondClusterStart = DIRStart + (Bpb_Fat16.RootEntry/Bpb_Fat16.SectorBytes)*32;
DIREnd = SecondClusterStart - 1;
}
printf("FAT1Start = %x\n",FAT1Start);
printf("FAT2Start = %x\n",FAT2Start);
printf("DIRStart = %x\n",DIRStart);
printf("DIREnd = %x\n",DIREnd);
printf("SecondClusterStart = %x\n",SecondClusterStart);
UFI_Read10(FAT1Start);
if(ReadBlockData[0] != 0xF8)
{
puts("Wrong FAT!");
return 0x13;
}
//puts("Good!");while(1);
for(i=0;i<512;i++) ((uint8*)&FAT1)[i] = ReadBlockData[i];
FAT1num = 0;
DiscardAllFiles();
for(i=0;i<MAXFILENUM;i++)
{
for(j=0;j<MAXFILECHAINLEN;j++) RWFileClusterChain[i][j] = 0;
}
return 0;
}
uint8 Printf_Directory(void)
{
uint8 i,j,k;
uint32 StartAddress;
UFI_Read10(DIRStart);
Printf_ReadBlockDatabuffer();
for(i=0;i<16;i++)
{
puts("File:");
for(j=0;j<32;j++) ((uint8*)&File_Information)[j] = ReadBlockData[i*32 + j];
if(File_Information.FileName[0] == 0) break;
if(File_Information.FileName[0] == 0xE5) continue;
if(File_Information.FileName[0] == 0x05) File_Information.FileName[0] = 0xE5;
for(k=0;k<8;k++) putchar(File_Information.FileName[k]);
putchar('.');
for(k=0;k<3;k++) putchar(File_Information.FileExtName[k]);
printf(" Start@ ");
StartAddress = ((File_Information.High16*65536 + File_Information.Low16)-2)*Bpb_Fat16.SectorsPerCluster+SecondClusterStart;
printf("0x%lx ",StartAddress);
printf("Length: 0x%lx bytes\n",File_Information.FileLength);
}
return 0;
}
uint16 NextCluster(uint16 StartCluster)
{
uint16 temp;
uint16 i;
uint8 tag;
uint16 number;
uint16 NextCluster;
if(FAT_ID == 0x0B)
{
temp = StartCluster/128;
if( (temp+FAT1Start) >= FAT2Start) return 0x20;
if( temp != FAT1num)
{
UFI_Read10(FAT1Start + temp);
FAT1num = temp;
for(i=0;i<512;i++) ((uint8*)&FAT1)[i] = ReadBlockData[i];
}
temp = StartCluster%128;
return ((uint32*)&FAT1)[temp];
}
else if(FAT_ID == 0x01)
{
number = StartCluster*3>>1;
if(number<<1 == StartCluster*3) tag = 0;
else tag = 1;
temp = number>>9;
if( (temp+FAT1Start) >= FAT2Start) return 0x20;
if( temp != FAT1num)
{
UFI_Read10(FAT1Start + temp);
FAT1num = temp;
for(i=0;i<512;i++) ((uint8*)&FAT1)[i] = ReadBlockData[i];
}// end of if( temp != FAT1num)
if(tag == 0)
{
if(number%512 == 511)
{
NextCluster = ((uint8*)&FAT1)[511];
UFI_Read10(FAT1Start + temp + 1);
FAT1num = temp+1;
for(i=0;i<512;i++) ((uint8*)&FAT1)[i] = ReadBlockData[i];
NextCluster += (((uint8*)&FAT1)[0] & 0x0F)<<8;
}
else
{
NextCluster = ((uint8*)&FAT1)[number%512] + (((uint8*)&FAT1)[number%512+1]& 0x0F)<<8;
}
}
else
{
if(number%512 == 511)
{
NextCluster = (((uint8*)&FAT1)[511]& 0xF0)>>4;
UFI_Read10(FAT1Start + temp + 1);
FAT1num = temp+1;
for(i=0;i<512;i++) ((uint8*)&FAT1)[i] = ReadBlockData[i];
NextCluster += (((uint8*)&FAT1)[0])<<4;
}
else
{
NextCluster = (((uint8*)&FAT1)[number%512]& 0xF0)>>4 + (((uint8*)&FAT1)[number%512+1])<<4;
}
} // end of if(tag == 0)
return NextCluster;
}
else
{
temp = StartCluster/256;
if( (temp+FAT1Start) >= FAT2Start) return 0x20;
if( temp != FAT1num)
{
UFI_Read10(FAT1Start + temp);
FAT1num = temp;
for(i=0;i<512;i++) ((uint8*)&FAT1)[i] = ReadBlockData[i];
}
temp = StartCluster%256;
return FAT1[temp];
} // end of if(FAT_ID == 0x01)
}
void List_Fat(void)
{
unsigned int i;
UFI_Read10(DIRStart);
for(i=0;i<512;i++)
{
Fat_data[i] = ReadBlockData[i];//Fat
}
}
uint8 ReadFile4Print(uint8* FileName)
{
uint8 i,j,k;
uint32 StartCluster,StartAddress;
uint32 SectorAddress;
uint16 len;
for(SectorAddress=DIRStart;SectorAddress <=DIREnd ;SectorAddress++)
{
UFI_Read10(SectorAddress);
for(i=0;i<16;i++)
{
for(j=0;j<32;j++) ((uint8*)&File_Information)[j] = ReadBlockData[i*32 + j];//Fat
if(File_Information.FileName[0] == 0) return 0x10;
if(File_Information.FileName[0] == 0xE5) continue; //已删除
if(File_Information.FileName[0] == 0x2E) continue; //目录信息
if(File_Information.FileName[0] == 0x05) File_Information.FileName[0] = 0xE5; //本身为 e5h
for(k=0;k<11;k++) if(FileName[k] != File_Information.FileName[k]) break;
if(k==11)
{
StartCluster = File_Information.High16*65536 + File_Information.Low16;
StartAddress = (StartCluster-2)*Bpb_Fat16.SectorsPerCluster+SecondClusterStart;
//goto PrintFile_;
}
}
}
return 0x20;
PrintFile_:
//
UFI_Read10(StartAddress);
for(len = 0; len < File_Information.FileLength; len++)
{
putchar(ReadBlockData[len]);
if(len == 511)
{
StartCluster = NextCluster(StartCluster);
if( FAT_ID == 0x0B)
{
if(StartCluster >= 0xFFFFFFF0) return 0x30;
}
else if( FAT_ID == 0x01)
{
if(StartCluster >= 0xFF0) return 0x31;
}
else
{
if(StartCluster >= 0xFFF0) return 0x32;
}
UFI_Read10((StartCluster-2)*Bpb_Fat16.SectorsPerCluster+SecondClusterStart);
len = 0;
File_Information.FileLength -= 512;
}
}
return 0;
}
// if file exist return 0x01 else return 0
uint8 DetectFile(uint8* FileName)
{
uint8 i,j,k,filenum;
uint32 StartCluster,StartAddress;
uint32 SectorAddress;
uint16 len;
for(SectorAddress=DIRStart;SectorAddress <= DIREnd;SectorAddress++)
{
UFI_Read10(SectorAddress);
for(i=0;i<16;i++)
{
for(j=0;j<32;j++) ((uint8*)&File_Information)[j] = ReadBlockData[i*32 + j];
if(File_Information.FileName[0] == 0) return 0;
if(File_Information.FileName[0] == 0xE5) continue;
if(File_Information.FileName[0] == 0x2E) continue;
if(File_Information.Attribute & 0x18 ) continue; //是目录或者卷标
if(File_Information.FileName[0] == 0x05) File_Information.FileName[0] = 0xE5;
for(k=0;k<11;k++) if(FileName[k] != File_Information.FileName[k]) break;
if(k==11) return 0x01;
} // end of for(i=0;i<16;i++)
} // end of for(SectorAddress=DIRStart;SectorAddress <= DIREnd;SectorAddress++)
return 0;
}
// if success return filenum else return 0xFF = failure
uint8 OpenFile(uint8* FileName)
{
uint8 i,j,k,filenum;
uint32 StartCluster,StartAddress;
uint32 SectorAddress;
uint16 len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -