1.44MB 软盘镜像文件FDT/FAT简析
Charles Chan @ 2009-09-27 #Fat #FileSystem @OperatingSystem
Contents:
准备:
FAT12的结构网上有很多,这里不进行累述。 下面是针对镜像文件进行的数据分析(下面提到的地址范围只指用UE等打开之后看到的地址)。
0面0道第2扇区到第10扇区的9个扇区是FAT表的存放位置。
FAT地址范围:0x0200 ~ 0x13FF
0面0道的第11扇区到1面0道第1扇区的9个扇区是第2个FAT表的存放位置,这第2个FAT是备用的。
备份FAT地址范围:0x1400 ~ 0x25FF
1面0道的第2扇区起到1面0道的第15扇区(共14个扇区)用于存放 FDT。
FDT起始地址:0x2600 ~ 0x41FF
以IO.SYS为例:
0x2600~0x260A :文件名
0x260B:07:只读、隐藏的系统文件
0x260C~0x2615:保留
0x2616~0x2617:20A0=0xA020(10100 000001 00000):文件最后修改时间20:01:00
0x2618~0x2619:D324=0x24D3(0010010 0110 10011):文件最后修改日期1998/06/19
0x261A~0x261B:0200:文件首簇号002,其他附后
0x261C~0x261F:966B0300=0x00036B96:文件的长度224150Byte
文件簇号分析: 其中,簇号0x002可知:
逻辑扇区号 = 0x002+31 = 33
因此,IO.SYS文件的存储起始位置为:逻辑扇区号 * 512 = 0x04200
文件首簇号002指向的位置为:0x200+(0x002*3/2)=0x200+3=0x203+0(簇号从0x203开始)。
因为0能被3整除(姑且这样认为),因此,簇号002指向的位置为0x203+0=0x203的位置。
0x203位置的数据为034000=0x004003,即第二簇为003
以MSDOS.SYS为例: 文件首簇号0x23F,可知:
逻辑扇区号 = 0x23F+31 = 606
因此,MSDOS.SYS文件的存储起始位置为:逻辑扇区号 * 512 = 0x4BC00
文件首簇号23F指向的位置为:0x200+(0x23F*3/2)=0x200+862.5=0x203+859.5。
因为858能被3整除,因此,簇号23F指向的位置为0x203+858=0x55D后面的1.5个位置。
0x55D位置的数据为FFFFFF=0xFFFFFF,因此簇号23F指向的内容为高12bit的0xFFF。
即MSDOS.SYS的第一簇为文件的最后一簇。
FAT12文件系统FDT读取类(简版)
目前的版本,仅支持对根目录的文件表进行读取。子目录下面的没研究……
#ifndef _MYFDT_H_
#define _MYFDT_H_
typedef unsigned char U8;
typedef unsigned short int U16;
typedef unsigned long int U32;
typedef U8 Type_FDTIndex;
typedef struct{
U16 u16Year;
U8 u8Month;
U8 u8Day;
}MyDate_st;
typedef struct{
U8 u8Hour;
U8 u8Minute;
U8 u8Second;
}MyTime_st;
class CMyFDT{
protected:
#define FDT_START_ADDR (0x2600U)
#define FDT_END_ADDR (0x41FFU)
#define FDT_INFO_LENGTH (32U)
#define FDT_INDEX_MAX ((Type_FDTIndex)((FDT_END_ADDR-FDT_START_ADDR+1U)/FDT_INFO_LENGTH))
typedef struct{
TCHAR tcFileName[9];
TCHAR tcExtName[4];
U8 u8Ability;
U8 u8NoUse[11];
U16 u16ModifyTime;
U16 u16ModifyDate;
U16 u16FisrtCluster;
U32 u32FileLength;
}MyFDTElement_st;
MyFDTElement_st m_FDT[FDT_INDEX_MAX];
Type_FDTIndex m_IndexCnt;
public:
CMyFDT();
BOOL LoadFDTInfo(TCHAR u8File_p[]);// 参数为磁盘镜像文件首地址
Type_FDTIndex GetIndexCnt();
TCHAR *GetFileName(Type_FDTIndex uIndex,TCHAR *u8FileName_p=NULL);
TCHAR *GetExtName(Type_FDTIndex uIndex,TCHAR *u8ExtName_p=NULL);
BOOL GetFileExist(Type_FDTIndex uIndex);
U8 GetAbility(Type_FDTIndex uIndex);
void GetModifyDate(Type_FDTIndex uIndex,MyDate_st *);
void GetModifyTime(Type_FDTIndex uIndex,MyTime_st *);
U16 GetFisrtCluster(Type_FDTIndex uIndex);
U32 GetFileLength(Type_FDTIndex uIndex);
};
#endif /* _MYFDT_H_ */
#include "MyFDT.h"
TCHAR *TrimRight(TCHAR *tcBuff)
{
U32 u32Len;
u32Len = _z_Strlen(tcBuff);
for(U32 i=u32Len;i>0;i--){
if((U8)(tcBuff[i-1]) == ' '){
tcBuff[i-1] = '/0';
}
else{
break;
}
}
return tcBuff;
}
CMyFDT::CMyFDT()
{
m_IndexCnt = 0;
memset(m_FDT,'/0',sizeof(m_FDT));
}
BOOL CMyFDT::LoadFDTInfo(TCHAR u8FilePt[])
{
TCHAR *tcCrt_p;
BOOL bRet;
bRet = TRUE;
tcCrt_p = u8FilePt + FDT_START_ADDR;
while(tcCrt_p[0] != '/0'){
TCHAR tcFileBuff[9];
memset(tcFileBuff,'/0',sizeof(tcFileBuff));
memcpy(tcFileBuff,&tcCrt_p[0],8);
memcpy(m_FDT[m_IndexCnt].tcFileName,TrimRight(tcFileBuff),8);
memset(tcFileBuff,'/0',sizeof(tcFileBuff));
memcpy(tcFileBuff,&tcCrt_p[8],3);
memcpy(m_FDT[m_IndexCnt].tcExtName,TrimRight(tcFileBuff),3);
m_FDT[m_IndexCnt].u8Ability = (TBYTE)tcCrt_p[11];
memcpy(m_FDT[m_IndexCnt].u8NoUse,&(tcCrt_p[12]),10);
m_FDT[m_IndexCnt].u16ModifyTime = (U8)tcCrt_p[22] + ((U8)tcCrt_p[23]*0x100);
m_FDT[m_IndexCnt].u16ModifyDate = (U8)tcCrt_p[24] + ((U8)tcCrt_p[25]*0x100);
m_FDT[m_IndexCnt].u16FisrtCluster = (U8)tcCrt_p[26] + ((U8)tcCrt_p[27]*0x100);
m_FDT[m_IndexCnt].u32FileLength = (U8)tcCrt_p[28] + ((U8)tcCrt_p[29]*0x100)+ ((U8)tcCrt_p[30]*0x10000)+ ((U8)tcCrt_p[31]*0x1000000);
tcCrt_p += FDT_INFO_LENGTH;
m_IndexCnt ++;
}
if(m_IndexCnt==0){
bRet = FALSE;
}
return bRet;
}
Type_FDTIndex CMyFDT::GetIndexCnt()
{
return m_IndexCnt;
}
TCHAR *CMyFDT::GetFileName(Type_FDTIndex uIndex,TCHAR *u8FileName_p)
{
if(u8FileName_p!=NULL){
strcpy(u8FileName_p,m_FDT[uIndex].tcFileName);
}
return m_FDT[uIndex].tcFileName;
}
TCHAR *CMyFDT::GetExtName(Type_FDTIndex uIndex,TCHAR *u8ExtName_p)
{
if(u8ExtName_p!=NULL){
_z_Strcpy(u8ExtName_p,(PTCHAR)m_FDT[uIndex].tcExtName);
}
return m_FDT[uIndex].tcExtName;
}
BOOL CMyFDT::GetFileExist(Type_FDTIndex uIndex)
{
BOOL bRet = TRUE;
if((U8)m_FDT[uIndex].tcFileName[0] == 0xE5){
bRet = FALSE;
}
else if((U8)m_FDT[uIndex].tcFileName[0] == 0x00U){
bRet = FALSE;
}
return bRet;
}
U8 CMyFDT::GetAbility(Type_FDTIndex uIndex)
{
return m_FDT[uIndex].u8Ability;
}
void CMyFDT::GetModifyDate(Type_FDTIndex uIndex,MyDate_st *stDate_p)
{
stDate_p->u16Year = ((m_FDT[uIndex].u16ModifyDate & 0xFE00) >> 9) + 1980;
stDate_p->u8Month = (m_FDT[uIndex].u16ModifyDate & 0x01E0) >> 5;
stDate_p->u8Day = (m_FDT[uIndex].u16ModifyDate & 0x001F);
}
void CMyFDT::GetModifyTime(Type_FDTIndex uIndex,MyTime_st *stTime_p)
{
stTime_p->u8Hour = ((m_FDT[uIndex].u16ModifyTime & 0xF800) >> 11);
stTime_p->u8Minute = (m_FDT[uIndex].u16ModifyTime & 0x07E0) >> 5;
stTime_p->u8Second = (m_FDT[uIndex].u16ModifyTime & 0x001F);
}
U16 CMyFDT::GetFisrtCluster(Type_FDTIndex uIndex)
{
return m_FDT[uIndex].u16FisrtCluster;
}
U32 CMyFDT::GetFileLength(Type_FDTIndex uIndex)
{
return m_FDT[uIndex].u32FileLength;
}