第4课

第4课 - 主引导程序的扩展(上)

1. 主引导程序的限制

  在前面的课程中讲到,主引导程序的代码量不能超过 512 字节!!

  那这 512 个字节存储的主引导程序可以完成操作系统的功能吗?答案显然是否定的。

  因此主引导程序最大只能是 512 字节就成为了一种限制,那如何突破这种限制呢?

2. 突破限制的思路

  主引导程序完成以下功能:

    (1)主引导程序首先完成最基本的初始化工作

    (2)然后从存储介质中加载程序到内存中,这一步是重中之重

    (3)最后将控制权交由新加载的程序执行(跳转到新加载程序的第一句代码),上面这三步可以在 512 字节的代码量内完成

    (4)......

  用图表示,如下图所示:

     

  第(1)个功能和第(3)个功能实现起来比较容易,重点是第(2)个功能的实现主引导程序如何加载存储介质中的其它程序?

3. 文件系统

  文件系统就是指存储介质上组织文件数据的方法(数据组织的方式),下面是 FAT12 文件系统的格式:

                    

3.1 文件系统的示例

  (1)FAT12 是 DOS 时代的早期文件系统

  (2)FAT12 结构非常简单一直沿用于软盘

  (3)FAT12 的基本组织单位

      字节(Byte):基本数据单位

      扇区(Sector):磁盘中的最小数据单元

      簇(Cluster):一个或多个扇区

 3.2 主引导程序大小受限的解决方案

  (1)使用 FAT12 对软盘(data.img)进行格式化

  (2)编写可执行程序(Loader),并将其拷贝到软盘中

  (3)主引导程序(Boot)在文件系统中查找 Loader

  (4)将 Loader 复制到内存中,并跳转到入口处执行

3.3 实验:往虚拟软盘中写入文件

  — 原材料FreeDosBochsbximage

    • Bochs 和 bximage 在前面的课程中已经介绍过了
    • FreeDos 是一个古老的 dos 操作系统,在本节课中使用 FreeDos 将软盘 data.img 格式化为 FAT12 格式的文件系统

         FreeDos 官网http://www.freedos.org/

      可以在官网上下载 FreeDos 的软盘镜像:(下载界面:http://www.freedos.org/download/

      

  — 步骤

    • 使用 bximage 工具创建虚拟软盘 data.img

      

    • 在 freeDos 中进行格式化(FAT12)

      更改上节课中的 bochsrc 配置文件,将 freedos.img 作为启动软盘,另外将 data.img 这个软盘插入到 freeDos 系统中。  

 1 ###############################################################
 2 # Configuration file for Bochs
 3 ###############################################################
 4 
 5 # how much memory the emulated machine will have
 6 megs: 32
 7 
 8 # filename of ROM images
 9 romimage: file=/usr/local/share/bochs/BIOS-bochs-latest
10 vgaromimage: file=/usr/share/vgabios/vgabios.bin
11 
12 # what disk images will be used
13 floppya: 1_44=freedos.img, status=inserted
14 floppyb: 1_44=data.img, status=inserted
15 # choose the boot disk.
16 boot: a
17 
18 # where do we send log messages?
19 # log: bochsout.txt
20 
21 # disable the mouse
22 mouse: enabled=0
23 
24 # enable key mapping, using US layout as default.
25 keyboard_mapping: enabled=1, map=/usr/local/share/bochs/keymaps/x11-pc-us.map
bochsrc配置文件

      启动 Bochs ,进入到 freeDos 系统界面:

      

      执行以下操作:

      

    • 将 data.img 挂载到 Linux 中,并写入文件

      将 data.img 挂载到 linux 中,然后创建一个 test.txt 文件并将该文件写入到挂载点,最后卸载 data.img

      

      在 Bochs 中查看 B 盘就看到了刚才写入的 test.txt 文件,表明文件写入成功。后面按照同样的方式将 Loader 写入到 data.img 中。

      

4. Boot 查找目标文件(Loader)

  把 Loader 按照上面的方式写入到 FAT12 格式的虚拟软盘中,下一步的工作就是:Boot 查找目标文件(Loader),并读取文件的内容!

4.1 深入 FAT12 文件系统

  FAT12 文件系统由引导区FAT 表根目录项表文件数据区组成。

    

4.2 FAT12 的主引导区

  主引导区存储的比较重要的信息文件系统的类型文件系统逻辑扇区总数每簇包含的扇区数等。

  主引导区最后以 0x55AA 两个字节作为结束,共占用一个扇区(第 0 扇区)。

  第 0 扇区中的部分内容如下表所示:

    

4.3 实验:读取 data.img 中的文件系统信息

  — 步骤

    • 创建 Fat12Header 结构体类型(根据上面表格的内容而来)
    • 使用文件流读取前 512 字节的内容
    • 解析并打印相关的信息  

编程实验:读取 FAT12 文件系统信息】

   在 QT 中使用下面的代码查看 FAT12 文件系统第 0 扇区的内容,并对照上面的表格进行验证。

 1 #include <QtCore/QCoreApplication>
 2 #include <QFile>
 3 #include <QDataStream>
 4 #include <QDebug>
 5 
 6 #pragma pack(push)
 7 #pragma pack(1)
 8 
 9 struct Fat12Header
10 {
11     char BS_OEMName[8];
12     ushort BPB_BytsPerSec;
13     uchar BPB_SecPerClus;
14     ushort BPB_RsvdSecCnt;
15     uchar BPB_NumFATs;
16     ushort BPB_RootEntCnt;
17     ushort BPB_TotSec16;
18     uchar BPB_Media;
19     ushort BPB_FATSz16;
20     ushort BPB_SecPerTrk;
21     ushort BPB_NumHeads;
22     uint BPB_HiddSec;
23     uint BPB_TotSec32;
24     uchar BS_DrvNum;
25     uchar BS_Reserved1;
26     uchar BS_BootSig;
27     uint BS_VolID;
28     char BS_VolLab[11];
29     char BS_FileSysType[8];
30 };
31 
32 #pragma pack(pop)
33 
34 void PrintHeader(Fat12Header& rf, QString p)
35 {
36     QFile file(p);
37 
38     if( file.open(QIODevice::ReadOnly) )
39     {
40         QDataStream in(&file);
41 
42         file.seek(3);
43 
44         in.readRawData(reinterpret_cast<char*>(&rf), sizeof(rf));
45 
46         rf.BS_OEMName[7] = 0;
47         rf.BS_VolLab[10] = 0;
48         rf.BS_FileSysType[7] = 0;
49 
50         qDebug() << "BS_OEMName: " << rf.BS_OEMName;
51         qDebug() << "BPB_BytsPerSec: " << hex << rf.BPB_BytsPerSec;
52         qDebug() << "BPB_SecPerClus: " << hex << rf.BPB_SecPerClus;
53         qDebug() << "BPB_RsvdSecCnt: " << hex << rf.BPB_RsvdSecCnt;
54         qDebug() << "BPB_NumFATs: " << hex << rf.BPB_NumFATs;
55         qDebug() << "BPB_RootEntCnt: " << hex << rf.BPB_RootEntCnt;
56         qDebug() << "BPB_TotSec16: " << hex << rf.BPB_TotSec16;
57         qDebug() << "BPB_Media: " << hex << rf.BPB_Media;
58         qDebug() << "BPB_FATSz16: " << hex << rf.BPB_FATSz16;
59         qDebug() << "BPB_SecPerTrk: " << hex << rf.BPB_SecPerTrk;
60         qDebug() << "BPB_NumHeads: " << hex << rf.BPB_NumHeads;
61         qDebug() << "BPB_HiddSec: " << hex << rf.BPB_HiddSec;
62         qDebug() << "BPB_TotSec32: " << hex << rf.BPB_TotSec32;
63         qDebug() << "BS_DrvNum: " << hex << rf.BS_DrvNum;
64         qDebug() << "BS_Reserved1: " << hex << rf.BS_Reserved1;
65         qDebug() << "BS_BootSig: " << hex << rf.BS_BootSig;
66         qDebug() << "BS_VolID: " << hex << rf.BS_VolID;
67         qDebug() << "BS_VolLab: " << rf.BS_VolLab;
68         qDebug() << "BS_FileSysType: " << rf.BS_FileSysType;
69 
70         file.seek(510);
71 
72         uchar b510 = 0;
73         uchar b511 = 0;
74 
75         in.readRawData(reinterpret_cast<char*>(&b510), sizeof(b510));
76         in.readRawData(reinterpret_cast<char*>(&b511), sizeof(b511));
77 
78         qDebug() << "Byte 510: " << hex << b510;
79         qDebug() << "Byte 511: " << hex << b511;
80     }
81 
82     file.close();
83 }
84 
85 int main(int argc, char *argv[])
86 {
87     QCoreApplication a(argc, argv);
88 
89     Fat12Header f12;
90 
91     PrintHeader(f12, "E:\data.img");
92     
93     return a.exec();
94 }
查看FAT12文件系统第0扇区的内容

     

  扇区 0 中除了保存 FAT12 文件系统的信息外,还有一个主引导程序(FreeDOS 中的 format 程序格式化时生成),从上面的表格中也可以看到,扇区 0 的第一条指令就是跳转到 BOOT_CODE 上(表格左侧蓝色的箭头),有两个方法可以进行验证。

  方法1:查看 data.img 的内容

    

  方法2:在 Bochs 中将data.img 作为启动软盘,查看打印信息,红色部分就是 format 程序生成的主引导程序。

    

实验结论

  (1)FreeDos 中的 format 程序在格式化软盘的时候自动在第 0扇区生成了一个主引导程序,这个主引导程序只打印一个字符串。

  (2)文件格式和文件系统都是用于定义数据如何存放的规则,只要遵循这个规则就能够成功读写目标数据。

5. 小结

  (1)主引导程序的代码量不能超过 512 字节

  (2)可以通过主引导程序加载新程序的方式突破限制

  (3)加载新程序需要依赖于文件系统

  (4)FAT12 是一种早期用于软盘的简单文件系统

  (5)FAT12 文件系统的重要信息存储于 0 扇区

注:本文整理于《狄泰12月提升计划》课程内容

狄泰QQ群:199546072

本人QQ号:502218614

原文地址:https://www.cnblogs.com/shiwenjie/p/8993021.html