FAT32文件系统启动扇区的实现

      看了于渊写的《自己动手写操作系统》后,想把启动代码由软盘FAT12文件系统迁移到硬盘FAT32文件系统中,毕竟目前软盘几乎已经不再使用了,而硬盘和U盘是主流。基本想法是在实模式下,使用汇编代码,读取硬盘MBR,分析硬盘分区表,找到第一个FAT32活动分区,分析FAT32分区,在该分区中找到OSLOADER.BIN文件,将该OSLOADER.BIN文件加载到内存指定地址,将执行权交给OSLOADER.BIN。

环境:
Ubuntu 14.04
bochs

背景知识:
MBR,即硬盘主引导记录,是硬盘的第一个扇区,MBR扇区共512字节,前446字节为引导代码,之后64字节是分区表项,最后两字节是有效标志0xAA55,即MBR结构如下:
 0x0000~0x01BD: 主引导程序
 0x01BE~0x01FD:主分区表
 0x01FE~0x01FF:有效标记,0xAA55

主分区表由4项组成,每项16字节,共64字节,每项描述一个分区的基本信息。
16字节分区表项结构:
0x00:引导指示符,指明该分区是否是活动分区
0x01:开始磁头
0x02:开始扇区,只用了0~5位,后面2位被开始柱面所使用
0x03:开始柱面,使用了开始扇区的最后2位,共10位,最大值1023
0x04:系统ID,定义了分区的类型
0x05:结束磁头
0x06:结束扇区,只使用了0~5位,最后2位被结束柱面所使用
0x07:结束柱面,使用了结束扇区的最后2位,共10位,最大值为1023
0x08:从该磁盘开始到该分区的开始的位移量,以扇区为单位,即相对扇区数
0x0C:该分区的总扇区数

FAT32文件系统
在FAT32分区的第一个扇区里,记录了FAT32分区的相关参数,如FAT表之前的保留扇区数,FAT表个数,FAT表占用的扇区数,每簇占用的扇区数,根目录所在的簇号等等。其结构如下:
0x00~0x02:3字节,跳转指令
0x03~0x0A:8字节,文件系统标志和版本号
0x0B~0x0C:2字节,每扇区字节数
0x0D~0x0D:1字节,每簇扇区数
0x0E~0x0F:2字节,保留扇区数,即FAT1相对于分区起始地址的扇区数
0x10~0x10:1字节,FAT表个数,通常为2
0x11~0x12:2字节,FAT32必须等于0,FAT12/FAT16为根目录中目录的个数
0x13~0x14:2字节,FAT32必须等于0,FAT12/FAT16为扇区总数
0x15~0x15:1字节,哪种存储介质,0xF8标准值,可移动存储介质,常用的 0xF0
0x16~0x17:2字节,FAT32必须为0,FAT12/FAT16为一个FAT 表所占的扇区数。
0x18~0x19:2字节,每磁道扇区数,只对于有“特殊形状”(由磁头和柱面每 分割为若干磁道)的存储介质有效
0x1A~0x1B:2字节,磁头数,只对特殊的介质才有效
0x1C~0x1F:4字节,EBR分区之前所隐藏的扇区数
0x20~0x23:4字节,文件系统总扇区数
0x24~0x27:4字节,每个FAT表占用扇区数
0x28~0x29:2字节,标记,此域FAT32 特有
0x2A~0x2B:2字节,FAT32版本号0.0,FAT32特有
0x2C~0x2F:4字节,根目录所在第一个簇的簇号,通常情况下还是起始于2号簇
0x30~0x31:2字节,FSINFO(文件系统信息扇区)扇区号1,该扇区为操作系统提供关于空簇总数及下一可用簇的信息
0x32~0x33:2字节,备份引导扇区的位置。备份引导扇区总是位于文件系统 的6号扇区
0x34~0x3F:12字节,用于以后FAT 扩展使用
0x40~0x40:1字节,与FAT12/16 的定义相同,只不过两者位于启动扇区不同的位置而已
0x41~0x41:1字节,与FAT12/16 的定义相同,只不过两者位于启动扇区不同的位置而已
0x42~0x42:1字节,扩展引导标志,0x29。与FAT12/16 的定义相同,只不过 两者位于启动扇区不同的位置而已
0x43~0x46:4字节,卷序列号。通常为一个随机值
0x47~0x51:11字节,卷标(ASCII码),如果建立文件系统的时候指定了卷标,会保存在此
0x52~0x59:8字节,文件系统格式的ASCII码,FAT32
0x5A~0x1FD:90~509共410字节,未使用。该部分没有明确的用途
0x1FE~0x1FF:签名标志0xAA55

FAT表
FAT表记录某个簇是否被使用,每个表项占用4个字节。由于簇号起始于2号,所以FAT表项的0号表项与1号表项不与任何簇对应。FAT32的0号表项值总是“F8FFFF0F”, 1号表项可能被用于记录脏标志,以说明文件系统没有被正常卸载或者磁盘表面存在错误。不过这个值并不重要。正常情况下1号表项的值为“FFFFFFFF”或“FFFFFF0F”。
如果某个簇未被分配使用,它对应的FAT表项内容为0;
当某个簇已被分配使用,则它对应的FAT表项内的FAT表项值也就是该文件的下一个存储位置的簇号。如果该文件结束于该簇,则在它的FAT表项中记录的是一个文件结束标记,对于FAT32而言,代表文件结束的FAT表项值为0x0FFFFFFF。
如果某个簇存在坏扇区,则整个簇会用0xFFFFFF7标记为坏簇,这个坏簇标记就记录在它所对应的FAT表项中。

FAT32根目录区,每个目录表项占用32字节,对于短文件名而言,32字节已足够,对于长文件名将使用多个目录表项,具体可参考其他文章。
FAT32短文件目录结构:
FAT32文件系统启动扇区的实现_第1张图片


以上是MBR,主分区表和FAT32分区信息的简要介绍,有了以上信息就可以通过汇编语言将FAT32中的文件读到内存中,并跳转到该文件去执行。

建立实验环境:
在Ubuntu系统中使用bochs工具bximage生成一块100M的虚拟硬盘文件c.img
对c.img进行分区,这里只分一个区就行了
对c.img的分区进行格式化,使用mkfs.vfat将分区格式化为FAT32文件系统
挂载该FAT32分区,将osloader.bin文件复制到该分区


我们用汇编实现FAT32启动扇区,其主要流程是:

计算机启动,将MBR扇区加载到内存地址0x7c00处执行,其中MBR扇区的前446字节是我们写的汇编代码。首先调用INT 13获取磁盘参数,然后分析主分区表,找到第一个活动分区,即分区表项第一个字节为0x80的分区,通过INT 13读取 该分区的第一个扇区,获取FAT32分区参数,然后检索FAT32根目录,寻找OSLOADER.BIN文件所占用的簇,读取该文件到内存指定地址,跳转到该地址继续执行。




你可能感兴趣的:(文件系统,操作系统,汇编,fat32)