📄 fat.c
字号:
/**********************************************************************************************
**
** Copyright(c) Semitek
**
** 模 块 名:fat.c
**
** 模块功能:实现有关FAT16文件系统的操作
**
** 修改日期:2007年4月5日
**
**********************************************************************************************/
#include "fat.h"
BYTE cluster_size = 0;//每簇的扇区数
WORD sector_size = 0;//每扇区的字节数
DWORD RootDir_Start_SecNum = 0;//根目录开始扇区号
DWORD Data_Start_SecNum = 0;//数据区开始扇区号
DWORD FAT1_Start_SecNum = 0;//FAT1开始扇区号
DWORD FAT2_Start_SecNum = 0;//FAT2开始扇区号
WORD DIR_FstClusHI = 0;//起始簇号的高16位
WORD DIR_FstClusLO = 0;//起始簇号的低16位
DWORD EmptyCluster = 0;//FAT中空闲的簇号
DWORD TotalSector = 0;
DWORD WriteData_Addr = 0;//写数据地址
extern BYTE MMCRDData[MMC_DATA_SIZE];
extern BYTE MMCWRData[MMC_DATA_SIZE];
/**********************************************************************************************
**
** 函数名称:GetFatInfo
**
** 函数功能:读MMC的0扇区,获得有关FAT的基本信息
**
** 输入参数:无
**
** 返 回 值:无
**
** 影响参数:cluster_size,fat_offset,cluster_offset,RootDir_Start_SecNum,Data_Start_SecNum
**
** 调用模块:mmc_read_block()
**
** 说 明:无
**
**********************************************************************************************/
void GetFatInfo()
{
BYTE BS_jmpBoot[3]; //跳转指令
BYTE BS_OEMName[8]; //制造商名称
WORD BPB_BytesPerSec;//字节/扇区
BYTE BPB_SecPerClus; //扇区/簇
WORD BPB_RsvdSecCnt; //保留扇区数
BYTE BPB_NumFATs; //FAT表数目
WORD BPB_RootEntCnt; //根目录项数
WORD BPB_TotSec16; //小于32MB的扇区数
BYTE BPB_Media; //媒体描述符
WORD BPB_FATSz16; //每个FAT表所占扇区数
WORD BPB_SecPerTrk; //每磁道上的扇区数
WORD BPB_NumHeads; //磁头数
DWORD BPB_HiddSec; //隐藏扇区数
DWORD BPB_TotSec32; //大于32MB的扇区数
mmc_read_block(MASTER_BOOT_RECORD);
BPB_BytesPerSec = MMCRDData[OFFSET_BPB_BytesPerSec] | (MMCRDData[OFFSET_BPB_BytesPerSec+1]<<8);
BPB_SecPerClus = MMCRDData[OFFSET_BPB_SecPerClus];
BPB_RsvdSecCnt = MMCRDData[OFFSET_BPB_RsvdSec] | (MMCRDData[OFFSET_BPB_RsvdSec+1]<<8);
BPB_NumFATs = MMCRDData[OFFSET_BPB_NumFATs];
BPB_RootEntCnt = MMCRDData[OFFSET_BPB_RootEntCnt] | (MMCRDData[OFFSET_BPB_RootEntCnt+1]<<8);
BPB_TotSec16 = MMCRDData[OFFSET_BPB_TotSec16] | (MMCRDData[OFFSET_BPB_TotSec16+1]<<8);
BPB_Media = MMCRDData[OFFSET_BPB_Media];
BPB_FATSz16 = MMCRDData[OFFSET_BPB_FATSz16] | (MMCRDData[OFFSET_BPB_FATSz16+1]<<8);
BPB_SecPerTrk = MMCRDData[OFFSET_BPB_SecPerTrk] | (MMCRDData[OFFSET_BPB_SecPerTrk+1]<<8);
BPB_NumHeads = MMCRDData[OFFSET_BPB_NumHeads] | (MMCRDData[OFFSET_BPB_NumHeads+1]<<8);
BPB_HiddSec = MMCRDData[OFFSET_BPB_HiddSec] | (MMCRDData[OFFSET_BPB_HiddSec+1]<<8) | (MMCRDData[OFFSET_BPB_HiddSec+2]<<16) | (MMCRDData[OFFSET_BPB_HiddSec+3]<<24);
BPB_TotSec32 = MMCRDData[OFFSET_BPB_TotSec32] | (MMCRDData[OFFSET_BPB_TotSec32+1]<<8) | (MMCRDData[OFFSET_BPB_TotSec32+2]<<16) | (MMCRDData[OFFSET_BPB_TotSec32+3]<<24);
RootDir_Start_SecNum = BPB_RsvdSecCnt + (BPB_NumFATs * BPB_FATSz16);
Data_Start_SecNum = RootDir_Start_SecNum + (32*BPB_RootEntCnt + (BPB_BytesPerSec -1))/BPB_BytesPerSec;
cluster_size = BPB_SecPerClus;
sector_size = BPB_BytesPerSec;
FAT1_Start_SecNum = BPB_RsvdSecCnt;
FAT2_Start_SecNum = BPB_RsvdSecCnt + BPB_FATSz16;
TotalSector = BPB_TotSec32;
return;
}
/**********************************************************************************************
**
** 函数名称:UpDataRootDir
**
** 函数功能:更新根目录内容
**
** 输入参数:文件名,文件大小
**
** 返 回 值:暂无
**
** 影响参数:暂无
**
** 调用模块:mmc_read_block,mmc_write_block
**
** 说 明:根目录是以32字节为单位进行读写,读写前要将文件名转换成大写字母
**
**********************************************************************************************/
void UpDataRootDir(BYTE *Name,DWORD FileSize,BYTE FileAttrib)
{
BYTE Buffer[11];
BYTE i,j,k = 0;
for(i=0;i<8;i++)
{
if(*Name != '.' && *Name != '\0')
{
Buffer[i] = *Name;
}
else
{
goto Label;
}
Name++;
Label: Buffer[i+1] = 0x20;
}
for(i=0;i<3;i++)
{
Name++;
if(*Name != 0) Buffer[i+8] = *Name;
else Buffer[i+8] = 0x20;
}
mmc_read_block(RootDir_Start_SecNum);
for(i=0;i<16;i++)
{
if(MMCRDData[i*32] == 0x00 || MMCRDData[i*32] == 0xE5)
{
break;
}
}
k = i << 5;
for(j=0;j<11;j++)
MMCRDData[k + j] = Buffer[j];//主文件名+扩展文件名,为8.3格式
MMCRDData[k + 11] = FileAttrib;//文件属性
MMCRDData[k + 12] = 0x00;//仅长文件名目录使用,对于FAT16不使用
MMCRDData[k + 13] = 0x00;
MMCRDData[k + 14] = 0X79;//文件建立时间
MMCRDData[k + 15] = 0X6C;
MMCRDData[k + 16] = 0X85;//文件建立日期
MMCRDData[k + 17] = 0X36;
MMCRDData[k + 18] = 0x85;//文件最近访问日期
MMCRDData[k + 19] = 0x36;
MMCRDData[k + 20] = 0x00;//系统保留
MMCRDData[k + 21] = 0x00;
MMCRDData[k + 22] = 0x68;//最新修改时间
MMCRDData[k + 23] = 0X77;
MMCRDData[k + 24] = 0x83;//最新修改日期
MMCRDData[k + 25] = 0x36;
MMCRDData[k + 26] = (DIR_FstClusLO & 0x00FF) >> 0x00;//起始簇号16位
MMCRDData[k + 27] = (DIR_FstClusLO & 0xFF00) >> 0x08;
MMCRDData[k + 28] = (FileSize & 0x000000FF) >> 0x00;//文件大小
MMCRDData[k + 29] = (FileSize & 0x0000FF00) >> 0x08;
MMCRDData[k + 30] = (FileSize & 0x00FF0000) >> 0x10;
MMCRDData[k + 31] = (FileSize & 0xFF000000) >> 0x18;
mmc_write_block(RootDir_Start_SecNum,MMCRDData);
return;
}
/**********************************************************************************************
**
** 函数名称:FATGetNextClus
**
** 函数功能:返回FAT表指定簇的下一个簇号
**
** 输入参数:从FAT表中读到的数组
**
** 返 回 值:下一个簇号
**
** 影响参数:暂无
**
** 调用模块:暂无
**
** 说 明:暂无
**
**********************************************************************************************/
DWORD FATGetNextClus(BYTE *Buf)
{
WORD i;
for(i=0;i<512;i+=2)
{
if(*(Buf+i) == 0xFF && *(Buf+i+1)== 0xFF && *(Buf+i+2) == 0x00 && *(Buf+i+3) == 0x00) break;
}
return ((i+2) >> 1);
}
/**********************************************************************************************
**
** 函数名称:UpDataFAT
**
** 函数功能:更新FAT表
**
** 输入参数:文件大小
**
** 返 回 值:暂无
**
** 影响参数:暂无
**
** 调用模块:mmc_read_block,mmc_write_block,FATGetNextClus
**
** 说 明:FAT表是个链表,在根目录中得到簇号,然后根据文件所占的簇数进行写入
**
**********************************************************************************************/
void UpDataFAT(DWORD FileSize)
{
DWORD File_TolCluster = 0;
WORD i = 0,j = 0,k = 0,cluster = 0;
for(k=0;k<64;k++)
{
mmc_read_block(FAT1_Start_SecNum+k);
if(k ==0)
{
EmptyCluster = FATGetNextClus(MMCRDData);
j = EmptyCluster+1;
cluster = EmptyCluster;
}
for(i = 0;i < 512;i += 2)
{
cluster++;
if(k == 0)
{
MMCRDData[i+4] = cluster & 0x00FF;
MMCRDData[i+5] = (cluster & 0xFF00) >> 8;
if(i == 506) break;
}
else
{
MMCRDData[i] = cluster & 0x00FF;
MMCRDData[i+1] = (cluster & 0xFF00) >> 8;
}
}
if(k == 63)
{
MMCRDData[i-2] = 0xFF;
MMCRDData[i-1] = 0xFF;
}
mmc_write_block(FAT1_Start_SecNum+k,MMCRDData);
mmc_write_block(FAT2_Start_SecNum+k,MMCRDData);
}
DIR_FstClusHI = (EmptyCluster & 0xFFFF0000) >> 0x10;
DIR_FstClusLO = (EmptyCluster & 0x0000FFFF) >> 0x00;
File_TolCluster = FileSize >> 0x0A; //文件所占的簇数 = 文件大小 >> 10
WriteData_Addr = Data_Start_SecNum + (EmptyCluster - 2) * sector_size;//文件内容所写的地址=数据区起始扇区号+(簇号-2)*每扇区所占字节数
return;
}
/**********************************************************************************************
**
** 函数名称:CreateFile
**
** 函数功能:创建以FileName为文件名、WriteData为文件内容的文件
**
** 输入参数:FileName->文件名;WriteData->待写数据
**
** 返 回 值:暂无
**
** 影响参数:暂无
**
** 调用模块:UpDataFAT,UpDataRootDir,WriteFile
**
** 说 明:创建文件流程:WriteFat->WriteRootDir->WriteData
**
**********************************************************************************************/
void CreateFile(BYTE *FileName,BYTE *WriteData,DWORD FileSize)
{
BYTE Rt,Name_Buffer[12];
DWORD Time=0,LastAddr = 0;
memcpy(Name_Buffer,FileName,12);
strupr(Name_Buffer);
Time = GetRecord();
LastAddr = FindFileEnd();
Rt = ChkFileExist(Name_Buffer);
if(Rt == 0)//文件不存在,新建文件并写入数据
{
UpDataFAT(FileSize);//写FAT表
UpDataRootDir(Name_Buffer,FileSize,0x01);//写根目录
WriteFile(WriteData_Addr,FileSize,WriteData);//写数据
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -