首先得获得U盘的主引导扇区,即MBR,获得分区信息,因为U盘无主引导扇区,所以重新获得逻辑盘信息,并打开文件系统的0号扇区,获得DBR中的BPB,即BIOS参数,使得DiskInfo结构体实例化。
代码如下:
void AddFileDriver(U16 (* DiakCommand)(U8 Cammand, void *Parameter),UdiskFSDisk * UdiskFSDiskInfo)//安装文件系统
{
U8 i,j,k;
U8 *Buf;
U8 MBR[512];//定义硬盘的主引导记录,共512字节
U8 partiontemp[MAX_DRIVES][PARTION_BYTES]; //MAX_DRIVES=1;PARTION_BYTES=16
U16 temp;//存储磁盘总扇区数
U32 temp1;//用于保存分区起始逻辑扇区,共4字节
Disk_RW_Parameter Dp;
Disk_Info * disk;
Partion sdpartions[MAX_DRIVES];
if (DiakCommand == NULL) // 参数无效退出
{
return;
}
Dp.RsvdForLow = UdiskFSDiskInfo;
Dp.Buf = MBR;//MBR绑定
//初始化驱动程序,底层驱动初始化不成功退出
if (DiakCommand(DISK_INIT, &Dp) != DISK_INIT_OK)
{
return;
}
//判断读取的物理第一扇区第一字节
//0:为分区表信息
//非0:为文件BPB信息
if(MBR[0]==0x00||MBR[0]!=0xeb)
{
for(i=0;i<MAX_DRIVES;i++)//一个分区
{
temp1 = 0;
for(j=0;j<PARTION_BYTES;j++)
{
partiontemp[i][j] = MBR[PARTION_TABLE_ADDRESS+i*PARTION_BYTES+j];
}//PARTION_TABLE_ADDRESS=0x1BE
temp1 = partiontemp[i][8] | partiontemp[i][9]<<8 |partiontemp[i][10]<<16|partiontemp[i][11]<<24;//保存该分区起始逻辑扇区
sdpartions[i].Index = i;//分区编号
if(temp1 !=0)
{
sdpartions[i].StartSec = temp1;//U盘分区的起始扇区赋值
sdpartions[i].TotalSecs = partiontemp[i][12] | partiontemp[i][13]<<8 |partiontemp[i][14]<<16|partiontemp[i][15]<<24;
//该分区占用的总扇区数赋值
}
else
{
sdpartions[i].StartSec = 0;
sdpartions[i].TotalSecs = 0;
break;
}
}
for(i=0;i<MAX_DRIVES; i++)
{
//判断是否有分区信息
if(sdpartions[i].StartSec!=0)
{
//设置驱动器号
disk = GetEmptyDiskInfoAddr();
disk->RsvdForLow = UdiskFSDiskInfo; //底层驱动
disk->DiakCommand = DiakCommand;
disk->StartSec = sdpartions[i].StartSec;
}
else
{
break;
}
}
}
else
{
//只有一个分区,起始扇区为文件BPB扇区
disk = GetEmptyDiskInfoAddr();
disk->RsvdForLow = UdiskFSDiskInfo;
disk->DiakCommand = DiakCommand;
disk->StartSec = 0;
}
/* 重新获取逻辑盘信息 */
for (i = 0; i < MAX_DRIVES; i++)
{
if (DiskInfo[i].Drive != EMPTY_DRIVE) /* 逻辑盘已分配 */
{
Buf = OpenSec(DiskInfo[i].Drive, 0); /* 打开扇区0(保留扇区) 读取DBR,DBR分为两部分:DOS引导程序和BPB(BIOS参数块)*/
ReadSec(DiskInfo[i].Drive, 0);
if (Buf != NULL)
{
/* 每扇区字节数 */
DiskInfo[i].BytsPerSec = Buf[11] | (Buf[12] << 8); //0BH-0CH 每扇区字节数
/* 每簇扇区数 */
DiskInfo[i].SecPerClus = Buf[13];//0DH 每簇扇区数
/* FAT开始扇区号,为逻辑扇区号 */
DiskInfo[i].FATStartSec = Buf[14] | (Buf[15] << 8);// 0EH-0FH 保留扇区数
/* FAT表个数 */
DiskInfo[i].NumFATs = Buf[16];//10H FAT备份数
/* 根目录占扇区数 */
DiskInfo[i].RootSecCnt = ((Buf[17] | (Buf[18] << 8)) * 32 + //11H-12H 根目录项数
DiskInfo[i].BytsPerSec - 1) //一项根目录32字节
/DiskInfo[i].BytsPerSec;
/* 逻辑盘(卷)占扇区数 */
temp = Buf[19] | (Buf[20] << 8);//13H-14H 磁盘总扇区数
if (temp != 0)
{
DiskInfo[i].SecPerDisk = temp;//逻辑驱动器包含的扇区数赋值
}
else
{
DiskInfo[i].SecPerDisk = Buf[32] | (Buf[33] << 8);
DiskInfo[i].SecPerDisk |= (((U32)Buf[34] << 16) | ((U32)Buf[35] << 24));
}
/* FAT表占用扇区数 */
temp = Buf[22] | (Buf[23] << 8);
if (temp != 0)
{
DiskInfo[i].FATSecCnt = temp;
}
else
{
DiskInfo[i].FATSecCnt = Buf[36] | (Buf[37] << 8);//20H-23H 总扇区数
DiskInfo[i].FATSecCnt |= (((U32)Buf[38] << 16) | (U32)(Buf[39] << 24));
}
/* 当前目录为根目录 */
DiskInfo[i].PathClusIndex = 0;
}
/* 根目录开始扇区号 */
DiskInfo[i].RootDirTable = DiskInfo[i].NumFATs * DiskInfo[i].FATSecCnt + DiskInfo[i].FATStartSec;
/* 数据区开始扇区号 */
DiskInfo[i].DataStartSec = DiskInfo[i].RootDirTable + DiskInfo[i].RootSecCnt;
temp1 = DiskInfo[i].SecPerDisk - DiskInfo[i].DataStartSec;//DATA可占的扇区数
temp1 = temp1 / DiskInfo[i].SecPerClus;//DATA可占的簇数
DiskInfo[i].ClusPerData = temp1;//数据区包含的簇数
/* 根据可用簇数,判断是FAT12、FAT16还是FAT32 */
if (temp1 < 4085)
{
DiskInfo[i].FATType = FAT12;
}
else if (temp1 < 65525)
{
DiskInfo[i].FATType = FAT16;
}
else
{
DiskInfo[i].FATType = FAT32;
/* FAT32 RootDirTable为开始簇号 */
DiskInfo[i].RootDirTable = Buf[44] | (Buf[45] << 8);
DiskInfo[i].RootDirTable |= (((U32)Buf[46] << 16) | ((U32)Buf[47] << 24));
DiskInfo[i].PathClusIndex = DiskInfo[i].RootDirTable;
}
CloseSec(DiskInfo[i].Drive, 0); /* 关闭扇区 */
}
}
}