-------之FAT文件系统简析
简介: 本文主要介绍U盘启动盘的有关内容,并借此介绍FAT文件系统。
其中启动代码将被写入第一扇区,也即启动扇区。下面是FREEDOS的一个启动代码片断,由这个启动代码组织,我们可以了解到一些信息。
segment .text %define BASE 0x7c00 org BASE Entry: jmp short real_start nop ; bp is initialized to 7c00h %define bsOemName bp+0x03 ; OEM label %define bsBytesPerSec bp+0x0b ; bytes/sector %define bsSecPerClust bp+0x0d ; sectors/allocation unit %define bsResSectors bp+0x0e ; # reserved sectors %define bsFATs bp+0x10 ; # of fats %define bsRootDirEnts bp+0x11 ; # of root dir entries %define bsSectors bp+0x13 ; # sectors total in image %define bsMedia bp+0x15 ; media descrip: fd=2side9sec, ; etc... %define sectPerFat bp+0x16 ; # sectors in a fat %define sectPerTrack bp+0x18 ; # sectors/track %define nHeads bp+0x1a ; # heads %define nHidden bp+0x1c ; # hidden sectors %define nSectorHuge bp+0x20 ; # sectors if > 65536 %define drive bp+0x24 ; drive number %define extBoot bp+0x26 ; extended boot signature %define volid bp+0x27 %define vollabel bp+0x2b %define filesys bp+0x36 %define LOADSEG 0x0060 %define FATBUF 0x2000 ; offset of temporary buffer ; for FAT chain ; Some extra variables ;%define StoreSI bp+3h ;temp store ; To save space, functions that are just called once are ; implemented as macros instead. Four bytes are saved by ; avoiding the call / ret instructions. ; GETDRIVEPARMS: Calculate start of some disk areas. ; %macro GETDRIVEPARMS 0 mov si, word [nHidden] mov di, word [nHidden+2] add si, word [bsResSectors] adc di, byte 0 ; DI:SI = first FAT sector mov word [fat_start], si mov word [fat_start+2], di mov al, [bsFATs] cbw mul word [sectPerFat] ; DX:AX = total number of ; FAT sectors add si, ax adc di, dx ; DI:SI = first root ; directory sector mov word [root_dir_start], si mov word [root_dir_start+2], di ; Calculate how many sectors the root directory occupies. mov bx, [bsBytesPerSec] mov cl, 5 ; divide BX by 32 shr bx, cl ; BX = directory entries ; per sector mov ax, [bsRootDirEnts] xor dx, dx div bx mov word [RootDirSecs], ax ; AX = sectors per root directory add si, ax adc di, byte 0 ; DI:SI = first data sector mov [data_start], si mov [data_start+2], di %endmacro ......诸如,我们发现启动代码的入口是一条跳转指令,紧接着定义了一个数据结构,其中是一些磁盘及文件系统的相关参数。再后面又是启动代码的其余部分。将来这部分代码就是写入启动扇区的代码,所以对FAT16而言,它的大小不会超过一个扇区(512byte)。
对于FAT16组织的后面部分,即两个FAT1,FAT2(其中FAT2是FAT1的一个备份),ROOT FOLDER,其位置及大小并不固定,他们可以由我们上面启动代码中谈及的数据结构中的相关内容计算得到。比如FAT1的大小就可以由 sectPerFat得到,而其扇区位置又可由bsResSectors参数得到。FAT2大小同FAT1,而其扇区位置又可由bsResSectors+sectPerFat计算得到。
紧跟在ROOT FOLDER后面就是文件及目录本身内容了,他们均以扇区(一般是512Byte)对齐。那么启动过程如何呢?对FREEDOS来说,其启动的第一阶段就是由BIOS读位于启动扇区的启动代码boot,而后再由boot加载kernel文件。其中kernel的读取就需要用到 FAT及ROOT FOLDER。他们反映了kernel的大小及位置,由此对kernel进行访问。
至此,我们已经可以了解到了要想正确启动,除了FAT需符合规范外,启动代码也必须正确,也就是说你不能用一个FAT32的启动代码去让它在FAT16上工作。
好了,了解了FAT,我们就可以动手将启动代码及相关数据写入相应扇区,来实现U盘的自启动。我们从上面了解到,其实难点在于如何得到启动代码而不是启动参数。下面介绍一个简单的方法,首先找到一份可启动的软盘映像文件,然后将其克隆到U盘的相应扇区即可。当然这样做成的U盘,由于是“克隆“而成,其U盘的容量参数将会改变,所以还需要相应处理。磁盘映像的提取可以自己写代码完成,也可以使用WINHEX等软件进提取。不过,有些人现在连软盘也找不到了,那么怎么办?不要紧,我已经帮你做好了一个,使用这个软件就可以直接做成启动U盘了,并且启动系统为FREEDOS.不过现在仅支持FAT16,也即最大容量2G,超出部分就认不到了。