首先对硬盘0磁头0柱面1扇区,也就是MBR(Main Boot Record)分析它自0X1BE处开始,16字节为一个数据结构,称为分区信息,具体格式请参考下面实例程序,一般有不超过4个.
这个数据结构可以得到各个分区的始末CHS参数,方便对各个分区的读取.
数据量较小,实例程序需要CCDOS中文支持,贴图为我的486 4.3G硬盘2个FAT分区.
下一篇文章,将会进行BPB数据结构的建立和分析,离我们读取目录,文件很近了..继续关注哦..
/*
This programme is for read the MBR sector and analyze its content
Writen by Lunzi QingFeng Studio 2008/01/07
E-mail:Dragon123321@hotmail.com QQ:123685049
*/
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <mem.h>
#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned long
struct MBR_FatInfo
{
UINT8 ActiveMark;
UINT8 ParStartHeader;
UINT8 ParStartSector;
UINT8 ParStartCylder;
UINT8 SystemMark;
UINT8 ParEndHeader;
UINT8 ParEndSector;
UINT8 ParEndCylder;
UINT32 NumOfAheadSector;
UINT32 NumOfTotalSector;
};
void readSector(UINT8 buff[]);
void showSector(UINT8 buff[]);
int writeToFile(UINT8 buff[]);
void readSector(UINT8 buff[])
{
union REGS inr,outr;
inr.h.ah=0x02; /*NO 2. fuction*/
inr.h.al=0x01; /*the number of sectors wanted read*/
inr.x.bx=buff; /*save back buffer address ES:BX */
inr.h.ch=0x00; /*Num of cylder*/
inr.h.cl=0x01; /*Num of sector*/
inr.h.dh=0x00; /*Num of header*/
inr.h.dl=0x80; /*Num of destnition disk*/
int86(0x13,&inr,&outr);
}
void showSector(UINT8 buff[])
{
int i;
for(i=0;i<512;i++){
if(i%24==0){
printf("/n");
printf("%4x : ",i);
}
printf("%2x ",buff[i]);
}
}
int writeToFile(UINT8 buff[])
{
FILE *fp;
int i;
if((fp=fopen("C://MyPro//DiskSec.bin","wat"))==NULL)
{
printf("Error:Could not create or open the log file ./n");
fclose(fp);
return(0);
}
for(i=0;i<512;i++){
fputc(buff[i],fp);
}
fclose(fp);
return(1);
}
/*************Main FUNCTION*************/
int main()
{
UINT8 mbr[512];
int key_Input;
/******/
struct MBR_FatInfo mfi;
char *ptr;
int c=0;
readSector(mbr);
/*
showSector(mbr);
printf("/nWrite the content to a log file press y or Y others for exit !/n");
key_Input=getch();
if(key_Input=='y' || key_Input=='Y')
{
if(writeToFile(mbr)==1) printf("Successfully write into the log file !");
else printf("Failed write into the log file!");
}
printf("/nAnalyze this sector press y or Y others for exit !/n");
key_Input=getch();
if(key_Input=='y' || key_Input=='Y')
{
printf("This sector is the MBR sector,More info:");
}
*/
for(c=0;c<4;c++){
ptr=memcpy(&mfi,&mbr[(0x1be+c*16)],16);
if(ptr)
{
printf("/n启动标志 : %2x ",mfi.ActiveMark);
printf("/n分区起始柱头 : %2x (%d)",mfi.ParStartHeader,mfi.ParStartHeader );
printf("/t分区起始扇区 : %2x (%d)",mfi.ParStartSector,mfi.ParStartSector);
printf("/t分区起始柱面 : %2x (%d)",mfi.ParStartCylder,mfi.ParStartCylder);
printf("/n系统标志 : %2x",mfi.SystemMark);
printf("/n分区结束柱头 : %2x (%d)",mfi.ParEndHeader,mfi.ParEndHeader);
printf("/t分区结束扇区 : %2x (%d)",mfi.ParEndSector,mfi.ParEndSector);
printf("/t分区结束柱面 : %2x (%d)",mfi.ParEndCylder,mfi.ParEndCylder);
printf("/n分区前置扇区数 : %u",mfi.NumOfAheadSector);
printf("/n分区扇区总数 : %u",mfi.NumOfTotalSector);
printf("/n");
}
else
printf("Error:Can't copy the memory!");
}
return (0);
}
到武汉这一个星期的时间里,发生了很多事情,有喜有忧,以致于阻碍了我发文章的速度。
永亮的走让我再次感到了生活的现实与压力之可怕,希望他能在非洲平安,早日回归武汉亲人们的怀抱。。
值得高兴,我找到工作了,呵呵。。好多人呼了一口气,可算放心了,是吧?
有喜有忧,还是平常心吧。。。
今天会连发两篇文章,下面这个是读取了0磁道 1柱头 1扇区的内容,它里面包含了DBR和BPB这两个重要的数据结构,我已经建立了该数据结构,由于我的用机环境的限制,我使用的FAT16文件系统,但是程序稍加修改即可使用于FAT32的BPB读取(白皮书所提到的FAT16和FAT32通过程序计算的方法,我想单独拿出来做--等建驱动库的时候吧,呵呵,好遥远哦)。
本程序仍然使用了中文输出,请在CCDOS环境下编译运行。
关于几个重要参数的计算,是本节的关键:
首先计算根目录所占扇区数:RootDirSectors
然后计算数据区起始地址: FirstDataSector
接着计算根目录扇区号: FirstRootDirSecNum
下一节,重点是如何由这几个参数计算出FAT分区的逻辑第一簇的第一个扇区的地址,并从中取出根目录的信息。
/*
This programme is for read the BPB sector and caculate the FAT
Writen by Lunzi QingFeng Studio 2008/01/07
E-mail:Dragon123321@hotmail.com QQ:123685049
*/
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <mem.h>
#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned long
typedef struct BPB_FAT16
{
UINT8 BS_drvNum;
UINT8 BS_Reserved1;
UINT8 BS_BootSig;
UINT8 BS_VolId[4];
UINT8 BS_VolLab[11];
UINT8 BS_FileSysType[8];
};
typedef struct BPB_FAT32
{
UINT32 BPB_FATSz32;
UINT16 BPB_ExtFlags;
UINT16 BPB_FSVer;
UINT32 BPB_RootClus;
UINT16 BPB_FSInfo;
UINT16 BPB_BkBootSec;
UINT8 BPB_Reserved[12];
UINT8 BS_DrvNum;
UINT8 BS_Reserved1;
UINT8 BS_BootSig;
UINT8 BS_VolId[4];
UINT8 BS_FilSysType[19];
};
typedef struct BPB_Info
{
UINT8 BS_jmpBoot[3];
UINT8 BS_OEMName[8];
UINT16 BPB_BytsPerSec;
UINT8 BPB_SecPerClus;
UINT16 BPB_RsvdSecCnt;
UINT8 BPB_NumFATs;
UINT16 BPB_RootEntCnt;
UINT16 BPB_TotSec16;
UINT8 BPB_Media;
UINT16 BPB_FATSz16;
UINT16 BPB_SecPerTrk;
UINT16 BPB_NumHeads;
UINT32 BPB_HiddSec;
UINT32 BPB_TotSec32;
union BPB_FATs
{
struct BPB_FAT16 FAT16;
struct BPB_FAT32 FAT32;
} BPB_FAT;
};
void readSector(int cyl,int header,int sec,UINT8 buff[]);
void showSector(UINT8 buff[]);
int writeToFile(UINT8 buff[]);
void readSector(int cyl,int header,int sec,UINT8 buff[])
{
union REGS inr,outr;
inr.h.ah=0x02; /*NO 2. fuction*/
inr.h.al=0x01; /*the number of sectors wanted read*/
inr.x.bx=buff; /*save back buffer address ES:BX */
inr.h.ch=0x3a; /*Num of cylder*/
inr.h.cl=0x01; /*Num of sector*/
inr.h.dh=0x00; /*Num of header*/
inr.h.dl=0x80; /*Num of destnition disk*/
int86(0x13,&inr,&outr);
}
void showSector(UINT8 buff[])
{
int i;
for(i=0;i<512;i++){
if(i%24==0){
printf("/n");
printf("%4x : ",i);
}
printf("%2x ",buff[i]);
}
}
int writeToFile(UINT8 buff[])
{
FILE *fp;
int i;
if((fp=fopen("C://MyPro//DiskSec.bin","wab"))==NULL)
{
printf("Error:Could not create or open the log file ./n");
fclose(fp);
return(0);
}
for(i=0;i<512;i++){
fputc(buff[i],fp);
}
fclose(fp);
return(1);
}
/*************Main FUNCTION*************/
int main(int argc,char *argv[])
{
UINT8 mbr[512];
int cyl,sec,header;
int key_Input;
/*DBR*/
struct BPB_Info bpb;
char * ptr;
int c;
/*FAT*/
UINT16 RootDirSectors;
UINT16 FirstDataSector;
UINT16 FirstSectorofCluster;
UINT16 FATSz;
/*FAT ROOT DIR*/
UINT16 FirstRootDirSecNum;
/*
if(argc <= 3 ){
printf("This Programme need three parameters:Cylder Header Sector /n");
exit(1);
}
*/
cyl=atoi(argv[1]);
header=atoi(argv[2]);
sec=atoi(argv[3]);
readSector(58,0,1,mbr);
/*
readSector(cyl,header,sec,mbr);
showSector(mbr);
printf("/nWrite the content to a log file press Y others for exit !/n");
key_Input=getch();
if(key_Input=='y' || key_Input=='Y')
{
if(writeToFile(mbr)==1) printf("Successfully write into the log file !");
else printf("Failed write into the log file!");
}
size=62
printf("%d ",sizeof(bpb));
*/
ptr=memcpy(&bpb,&mbr[0],sizeof(bpb));
if(ptr)
{
printf("启动代码:");
for(c=0;c<3;c++) printf("%2x ",bpb.BS_jmpBoot[c]);
printf("/tOEM名称:");
for(c=0;c<8;c++) printf("%c",bpb.BS_OEMName[c]);
printf("/t每扇区字节数:");
printf("%d",bpb.BPB_BytsPerSec);
printf("/n每簇扇区数:");
printf("%d",bpb.BPB_SecPerClus);
printf("/t保留扇区的数目:");
printf("%d",bpb.BPB_RsvdSecCnt);
printf("/t本卷中FAT表数目:");
printf("%d",bpb.BPB_NumFATs);
printf("/n根目录中的目录数:");
printf("%d",bpb.BPB_RootEntCnt);
printf("/t本卷中总扇区数16bit:");
printf("%d",bpb.BPB_TotSec16);
printf("/t存储介质类型:");
printf("0X%2x",bpb.BPB_Media);
printf("/n一个FAT表所占的扇区数:");
printf("%d",bpb.BPB_FATSz16);
printf("/t每磁道扇区数:");
printf("%d",bpb.BPB_SecPerTrk);
printf("/t磁头数:");
printf("%d",bpb.BPB_NumHeads);
printf("/n此FAT表之前的隐藏扇区数:");
printf("%u",bpb.BPB_HiddSec);
printf("/t本卷中总扇区数32bit:");
printf("%u",bpb.BPB_TotSec32);
printf("/n/n以下内容16和32有所区别,下面的程序以16为介绍:");
printf("/n驱动器类型参数:");
printf("0X%2x",bpb.BPB_FAT.FAT16.BS_drvNum);
printf("/t保留(供NTFS使用):");
printf("%d",bpb.BPB_FAT.FAT16.BS_Reserved1);
printf("/t拓展启动标志:");
printf("0X%2x",bpb.BPB_FAT.FAT16.BS_BootSig);
printf("/n磁盘卷标:");
for(c=0;c<11;c++) printf("%c",bpb.BPB_FAT.FAT16.BS_VolLab[c]);
printf("/tFAT文件系统类型:");
for(c=0;c<8;c++) printf("%c",bpb.BPB_FAT.FAT16.BS_FileSysType[c]);
printf("/n/n以下为计算FAT的一般步骤:");
RootDirSectors=((bpb.BPB_RootEntCnt*32)+(bpb.BPB_BytsPerSec))/bpb.BPB_BytsPerSec;
if(bpb.BPB_FATSz16!=0)
FATSz=bpb.BPB_FATSz16;
else
{
printf("ERROR:Your FS isn't FAT16,Please change this programme./n");
exit(0);
}
FirstDataSector=bpb.BPB_RsvdSecCnt+(bpb.BPB_NumFATs*FATSz)+RootDirSectors;
FirstRootDirSecNum=bpb.BPB_RsvdSecCnt+(bpb.BPB_NumFATs*bpb.BPB_FATSz16);
printf("/n1 首先计算根目录所占扇区数: %d",RootDirSectors);
printf("/n2 然后计算数据区起始地址: %d",FirstDataSector);
printf("/n3 接着计算根目录扇区号: %d",FirstRootDirSecNum);
}
else
{
printf("Can't copy the DBR to the memory!/n");
}
return (0);
}