Chinaunix首页 | 论坛 | 博客
  • 博客访问: 539666
  • 博文数量: 120
  • 博客积分: 3030
  • 博客等级: 中校
  • 技术积分: 1445
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-05 01:00
文章存档

2011年(1)

2009年(2)

2008年(32)

2007年(33)

2006年(52)

我的朋友

分类: LINUX

2006-03-12 00:58:21

编写MBR从硬盘启动linux0.11

作者:    日期: 2005.4.3

    计算机启动时BIOS会把启动盘第一个扇区的数据读入内存0x7C00开始处,然后跳到这里继续执行。从硬盘启动和从软盘启动唯一的区别就是映象文件存储方式的不同:

1.    对于从软盘启动的方式,映象文件连续地存放在软盘开始的位置处。放在第一个扇区的bootsect.s被BIOS读入内存后,就会把余下的映象文件读入内存,然后继续执行

2.    对于从硬盘启动的方式,映象文件存放在Minix格式的硬盘分区里,MBR(硬盘第一个扇区)中的程序需要根据硬盘的参数和Minix文件系统的存储格式读出它

本文描述了如何编写MBR中的程序,把存放在硬盘第一个分区根目录下的linux0.11映像文件Image读入内存。

文章中小字体的括号里的数字表示参考文献的编号(见后面的参考文献列表)。

本文分5个部分:  1、硬盘简介

                  2、Minix 1.0文件系统简介

                  3、程序流程

                  4、上机实验

                  5、程序代码(以附件形式给出)

一.硬盘简介(1)

   

1. 硬盘扇区编号(此图来源文献1)

    我们需要了解的是物理扇区编号方式和绝对扇区编号方式。物理扇区号直接按柱面、磁头、扇区3者的组合来定位某个扇区。对于硬盘的第一个扇区,其编号为“0柱面0磁头1扇区”。我们假设硬盘磁头数为16,每磁道扇区数为63,下面描述遍历整个硬盘时柱面号、磁头号、扇区号的变化规律(以(x,y,z)表示x柱面y磁头z扇区):  (0,0,1)、(0,0,2)、……、(0,0,63)、

(0,1,1)、(0,1,2)、……、(0,1,63)、

(0,2,1)、(0,2,2)、……、(0,2,63)、

……

(0,15,1)、(0,15,2)、……、(0,15,63)、

(1,0,1)、(1,0,2)、……、(1,0,63)、

(1,1,1)、(1,1,2)、……、(1,1,63)、

    换句话说就是扇区号是从1到63的63进制,磁头号是0到15的16进制,“百位”是柱面号,“十位”是磁头号,“个位”是扇区号。

    绝对扇区号从0开始,遍历硬盘时依次增1。

    两者的换算关系如下(abs_sector表示绝对扇区号,cyl表示柱面号,head表示磁头号,sector表示扇区号,nheads表示磁头数,nspt表示每磁道扇区数):

       sector = abs_sector % nspt + 1

       track  = abs_sector / nspt

       head   = track % nheads

       cyl    = track / nheads

    如何知道上面说的磁头数nheads、每磁道扇区数nspt呢?启动时BIOS会把硬盘参数表放在内存某个位置。对于第一个硬盘,硬盘参数表的首地址放在中断0x41处,即内存地址4*0x41=0x104开始的4个字节表示硬盘参数表的段地址(后面2字节)和偏移地址(前面2字节)。硬盘参数表的结构如下:

dw  cylinders

db  nheads

dw  0

dw  write pre-comp

db  0

db  0 "control byte"

db  0, 0, 0

dw  landing zone

db  nspt(sectors/track)

db  0

    第二个硬盘的参数表地址放在BIOS中断向量0x46处。

    对于硬盘,我们还需要稍微知道一点分区表的信息。分区表放在硬盘第一个扇区的0x1be~0x1fd处(共64字节,第一个分区的信息在0x1be~0x1ce)。我们需要使用的仅仅是存放在0x1c6处的“分区起始绝对扇区号”(对应于程序中的start_sect变量)

二.Minix 1.0文件系统简介(2) (3)

    关于Minix 1.0文件系统的更详细知识请参考文献2、3,下面仅介绍理解本程序需要了解的知识。

    Minix 1.0格式的分区结构如下:

引导块

超级块

i点位图块…

逻辑块位图块

i节点块…

数据区………

    1、对于Minix 1.0,每个盘块占1k字节(即2个扇区)。引导块的第一个扇区就是本分区的第一个扇区,扇区号存在MBR中0x1c6处(就是上文的“分区起始绝对扇区号”)。盘块从0开始编号,对于盘块n,其绝对扇区号 = 2*n +分区起始绝对扇区号。

    2、i点位图块和逻辑块位图块的大小、数据区的起始盘块号等信息存放在超级块中,超级块的数据结构如下:

    struct d_super_block{

       unsigned short s_ninodes;       //节点数

       unsigned short s_nzones;        //逻辑块数

       unsigned short s_imap_blocks;   //i节点位图所占用的数据块数

       unsigned short s_zmap_blocks;   //逻辑块位图所占用的数据块数

       unsigned short s_firstdatazone; //第一个数据逻辑块

       unsigned short s_log_zone_size; //log2(数据块数/逻辑块)

       unsigned long  s_max_size;      //文件最大长度

       unsigned short s_magic;};      //文件系统魔数

    我们只需要知道开始存放i节点的盘块号inode_start_zone和第一个数据逻辑块号firstdatazone:

inode_start_zone = 2 + s_imap_blocks + s_zmap_blocks

firstdatazone    = s_firstdatazone

    3、每个i节点占32字节,其数据结构如下:

       struct d_inode{

           unsigned short i_mode;      //文件类型和属性

           unsigned short i_uid;       //用户id

           unsigned long  i_size;      //文件大小(字节数)

           unsigned long  i_time;      //修改时间(1970.1.1:0算起,秒)

           unsigned char  i_gid;       //组id

           unsigned char  i_nlinks;    //链接数

unsigned short i_zone[9];}; //直接(0~6)、间接(7)、双重间接

                            //(8)逻辑块号

    根据其中的i_size可以计算出文件占用的盘块数 = (i_size + 1023) / 1024

    文件数据的前面7k存放在称为直接块的7个盘块中,这7个盘块的盘块号存在i_zone[0]~i_zone[6]中。如果文件大于7k,则需要使用到一次间接块(i_zone[7]),它对应的盘块里存放的不是文件数据,而是7k之后的文件数据存放的盘块号。比如一次间接块的第1、2字节指出第8k文件数据存放的盘块号码。一次间接块可以存放512个盘块号。如果文件大于(512+7)k,则需要使用二次间接块i_zone[8]。图示如下:

   

2. 文件数据存储结构(此图来源文献3)

    根据i_zone[0]~i_zone[6],可以直接读出前面7k数据;然后读出一次间接块i_zone[7],根据其中的盘块号即可读出其余的数据;忽略i_zone[8],因为linux0.11映像文件没那么大。

    图3是映像文件Image一次间接块的前面部分数据。每两个字节表示一个盘块号。“00 00”表示这1k的数据都是0(比如红圈里的),蓝圈里的“70 05”表示这1k数据存放的盘块号是0x0570。

3. 映像文件Image一次间接块的前面部分数据

    4、第一个数据块存放的就是根目录文件的前1k数据,根目录文件存放的是称为目录项的信息。其数据结构如下:

       struct dir_entry{

           unsigned short inode;    //i节点

           char name[14];};         //文件名

      

       图4就是根目录文件第一个盘块的部分信息,图中红圈里面的数据表示本本目录项的i节点,蓝圈里面的数据表示该目录形的名称是Image。从图上我们可以看到,前面两个目录项分别是目录“.”和目录“..”,紧随其后的是bin、dev、etc、mnt、root、tmp、usr等目录,再后面的是hello.c、Image、image文件(至于是目录还是文件,需要找出相应的i节点根据其i_mode项来判断)。

4. 根目录文件第一个数据块部分信息

三.程序流程

    现在可以描述查找映像文件并读出它的过程了:

a.    获取硬盘参数——磁头数、每磁道扇区数(以便计算绝对扇区号对应的柱面号、磁头号、扇区号),获取分区参数——第一个分区起始绝对扇区号(以定位Minix文件系统的逻辑块)

b.    读出超级块,计算出i节点开始存放的盘块号inode_start_zone和第一个数据逻辑块号firstdatazone

c.    读出根目录文件(本程序只读出了它前面的1k数据——即第一个数据逻辑块)

阅读(2224) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~