上一个名字用的时间太长了,换个名字吧。
一、通过格式化命令-看磁盘文件系统的建立过程<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
1、添加format命令,单步调试
所有的底层驱动函数都已经准备好。添加格式化命令format后,编译下载。
Format命令的执行主要是调用f_mkfs()函数,下面进行单步调试。
以下主要列出函数的主要执行步骤:
res=f_mkfs( 0, 1, 4096 ); //1表示不需要引导扇区。4096是8个扇区。
进入f_mkfs()函数,这里只列出主要执行步骤:
if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_part) != RES_OK || n_part < MIN_SECTOR)
return FR_MKFS_ABORTED;这个函数调用后,n_part=0x<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />000F,3400 = 996 352,这是SD的总块数。
allocsize /= SS(fs); 等于8/* Number of sectors per cluster */
n_clst = n_part / allocsize; //等于0x1E680 = 124 544 簇。
if (n_clst >= 0xFFF5) fmt = FS_FAT32; 所以文件系统确定为FAT32类型。
n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); 等于0x3CE = 974,表示FAT要占据974个扇区。
n_rsv = 33 - partition; 保留扇区32个。
n_dir = 0;
b_fat = b_part + n_rsv; /* FATs start sector 32扇区*/
b_dir = b_fat + n_fat * N_FATS; /* Directory start sector 0x3EE =1006,由于FAT表个数设为1个,所以目录区=FAT起始+FAT占用扇区数*/
b_data = b_dir + n_dir; /* Data start sector */
以上三项确定 FAT区域、根目录区、数据区的起始扇区。
disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK,这个函数调用没有正确返回 可擦出扇区的总数。接下来程序会出错,因此退出,修改disk_ioctl()函数后,再次分析。把这个函数返回值直接改为32。并且把FAT表的个数定义为2.
N_FATS改为2后,根目录区、数据区的起始扇区的起始扇区变为0x7BC=1980扇区。继续往下执行。
n = (b_data + n - 1) & ~(n - 1);
n_fat += (n - b_data) / N_FATS;这两句话对fat所占扇区数进行了修正,保证擦除时,以32个扇区为一个单位。
n_clst = (n_part - n_rsv - n_fat * N_FATS - n_dir) / allocsize; =0x1E588。
tbl = fs->win; /* Clear buffer */
mem_set(tbl, 0, SS(fs)); 清零文件系统缓冲区。
mem_set(tbl, 0, SS(fs));
ST_DWORD(tbl+BS_jmpBoot, 0x90FEEB); /* Boot code (jmp $, nop) */
ST_WORD(tbl+BPB_BytsPerSec, SS(fs)); /* Sector size */
tbl[BPB_SecPerClus] = (BYTE)allocsize; /* Sectors per cluster */
ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */
上面的工作主要是填充 引导扇区缓冲区,也就是常说的DBR扇区缓冲,等所有的参数写好,就可以写回磁盘。
ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature */
if (disk_write(drv, tbl, b_part+0, 1) != RES_OK)
return FR_DISK_ERR; //这就是在写有效引导标志 sec[510]=0x55, sec[511]=0xAA。
if (fmt == FS_FAT32)
disk_write(drv, tbl, b_part+6, 1); //FAT32在第六扇区有个备份引导扇区。
for (m = 0; m < N_FATS; m++) {
mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */
if (fmt != FS_FAT32) {
n = (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00;
n |= partition;
ST_DWORD(tbl, n); /* Reserve cluster #0-1 (FAT12/16) */
} else {
ST_DWORD(tbl+0, 0xFFFFFFF8); /* Reserve cluster #0-1 (FAT32) */
ST_DWORD(tbl+4, 0xFFFFFFFF);
ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */ } //簇0和簇1保留,簇2分配给根目录区。
if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)
return FR_DISK_ERR;
mem_set(tbl, 0, SS(fs)); /* Following FAT entries are filled by zero */ //接下来所有的扇区都清0,表示该簇未被占用。
for (n = 1; n < n_fat; n++) {
if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)
return FR_DISK_ERR;
} //第一次是写从0x21扇区开始,总共 0x3CF个扇区(第一个扇区已经写了)。第二次开始时是备份引导扇区,0x20+0x3D0=0x3F0。同理,第一扇区与0x21扇区相同,后面都清零。
Format命令要执行较长的时间,主要就是FAT表接近2000个扇区要清零。
m = (BYTE)((fmt == FS_FAT32) ? allocsize : n_dir); m=8,每簇8扇区。
do {
if (disk_write(drv, tbl, b_fat++, 1) != RES_OK)
return FR_DISK_ERR;
} while (--m); //以上部分是将根目录区的8个扇区清零,表示目录项未被占用。
if (fmt == FS_FAT32) {
ST_WORD(tbl+BS_55AA, 0xAA55);
ST_DWORD(tbl+FSI_LeadSig, 0x41615252);
ST_DWORD(tbl+FSI_StrucSig, 0x61417272);
ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); //根目录区已经用掉了一簇。
ST_DWORD(tbl+FSI_Nxt_Free, 0xFFFFFFFF);
disk_write(drv, tbl, b_part+1, 1); //分别写入1号和7号扇区。
disk_write(drv, tbl, b_part+7, 1);
} //这是写FAT32文件系统的FSI扇区,包括空闲簇总数和上次分配的簇号。
FAT32文件系统的格式化到此完成。
2、再以Fdisk的方式格式化一次,这时候格式系统要写 MBR扇区,FAT引导扇区不在 0号扇区了。同时MBR要建立分区表,以找到DBR引导扇区。其过程与上述差不多,只是多执行了以下代码,详细过程就不叙述了。
if (!partition) {
DWORD n_disk = b_part + n_part;
mem_set(fs->win, 0, SS(fs));
tbl = fs->win+MBR_Table; //分区表从0x1BE开始。
ST_DWORD(tbl, 0x00010180); /* Partition start in CHS */ Table[0x1BE] = 0x80,表明该分区是活动扇区。00表示开始柱面,01、01表示开始扇区、开始磁头。
if (n_disk < 63UL * 255 * 1024) { /* Partition end in CHS */
n_disk = n_disk / 63 / 255;
tbl[7] = (BYTE)n_disk; //表示结束的柱面。
tbl[6] = (BYTE)((n_disk >> 2) | 63); //结束的扇区。
} else {
ST_WORD(&tbl[6], 0xFFFF); //
}
tbl[5] = 254; //结束的磁头。
if (fmt != FS_FAT32) /* System ID */
tbl[4] = (n_part < 0x10000) ? 0x04 : 0x06;
else
tbl[4] = 0x0c; // 表示该分区类型为win95 FAT32
ST_DWORD(tbl+8, 63); /*起始扇区 0x3F in LBA */
ST_DWORD(tbl+12, n_part); /*分区的大小,总扇区数减去MBR及其占据的一个柱面。 */
ST_WORD(tbl+64, 0xAA55); /* Signature */
if (disk_write(drv, fs->win, 0, 1) != RES_OK)
return FR_DISK_ERR;
partition = 0xF8; //MBR标志。
} else {
partition = 0xF0;
}
3、观察在有MBR区域的情况下,如何检查文件系统
fmt = check_fs(fs, bsect = 0); /* 检查0扇区的时候,没有发现FAT文件系统扇区,但是有0x55 0xAA标志,说明这是有效磁盘,但是返回1. */
if (fmt == 1) { /* 表明可能存在分区 */
/* Check a partition listed in top of the partition table */
tbl = &fs->win[MBR_Table + LD2PT(vol) * 16]; /* Partition table */
if (tbl[4]) { 实际这里应该是0x0c,表示FAT32系统。
bsect = LD_DWORD(&tbl[8]); /* 这个是文件系统 引导扇区的号码。 */
fmt = check_fs(fs, bsect); /* 再到这个扇区检查是否存在 FAT文件系统标志。 */ } }
执行过后,仍然能够建立完整的 文件系统信息 结构体,只是里面的 FAT分配起始扇区、数据区起始扇区地址相对 没有MBR的时候改变了,其它都差不多。
tengjingshu_112148725 2010-3-30 00:08