Linux开机那点事:BIOS以及实模式内存布局


想写好操作系统,还得先学明白BIOS有什么用

计算机开机那点事:BIOS以及实模式内存布局

Linux开机那点事:BIOS以及实模式内存布局

BIOS全称叫Base Input & Output System,即基本输入输出系统

人们给任何事物起名字,肯定都不是乱起的,必然是根据该事物的特点,通过总结、精练出一些文字来表示视图的特征,这个便是对一般事物取名的方法。通过名字,就能够反应出该事物的特性。例如:抽油机在抽石油的时候,就像“磕头”一样,所以大家给其起了更形象的名宇一一“磕头机”。

回到BIOS上我们就需要搞清楚BIOS到底干了什么,我们才能够理解BIOS的名字。

1 开机后CPU的运行模式

CPU有两种运行模式:

  • 实模式
  • 保护模式

实模式指的就是Intel 8086 CPU的运行模式。而保护模式则在实模式的基础上,进行了诸如地址检查权限检查等等功能,因此称为保护模式

实模式最大的特点就是运行原理简单,但是能够支持的功能非常少,保护模式提供了更多的功能,因此现代操作系统都是运行在保护模式下的。

我们这里不关注每种模式具体得内容,而是关注于开机之后CPU的模式。

开机之后,CPU是默认处于实模式的,此时CPU相当于一个Intel 8086 CPU,需要我们自己手动在代码中从实模式切换到保护模式下。

但是手动从实模式切换到保护模式是需要在操作系统的BootLoader中实现的,因此我们在开机后,运行BIOS时还是处于实模式。此时CPU寻址内存访问什么的都和Intel 8086 CPU一模一样。

2 BIOS介绍

BIOSBasic Input Output System的缩写,直译过来后中文名称就是基本输入输出系统

BIOS全称应该是ROM-BIOS,意思是只读存储器基本输入输出系统,而称其为ROM-BIOS,则是因为:

  • ROM:之所以要将其称为ROM-BIOS,其实是因为BIOS这个程序,是写死在计算机内主板上一个ROM芯片上的程序,而储存BIOS的芯片是主板上一块长方型或正方型芯片。主板上的BIOS芯片或许是主板上唯一贴有标签的芯片,一般它是一块32针的双列直插式的集成电路,上面印有"BIOS"字样。
    • 586以前的ROM多为可重写EPROM芯片,上面的标签起着保护BIOS内容的作用(紫外线照射会使EPROM内容丢失),不能随便撕下
    • 586以后的ROM多采用EEPROM(电可擦写只读ROM),通过跳线开关和系统配带的驱动程序盘,可以对EEPROM进行重写,方便地实现BIOS升级。
  • 基本输入输出BIOS保存着计算机最重要的基本输入输出的程序、系统设置信息、开机上电自检程序和系统启动自举程序

  • 系统:有人认为既然BIOS是程序,那它就应该是属于软件,感觉就像自己常用的WordExcel。但是事实上BIOS与一般的软件还是有一些区别,而且它与硬件的联系也是相当地紧密:

    • 一方面:BIOS是写死在硬件上的软件,因此是固件
    • 另一方面:BIOS直接操作硬件,负责硬件的初始化

    因此,相比于单传的说BIOS是硬件/软件/固件,还是说其是一个系统更叫形象,因为他负责统筹、关系系统上的硬件,它是连接软件程序与硬件设备的一座桥梁,负责解决硬件的即时要求

3 BIOS的功能/工作流程

BIOS的功能主要分为三个部分:

  • 自检
  • 初始化
  • 引导操作系统

这三个功能其实就是BIOS的运行流程,即先自检,然后初始化,最后引导操作系统

3.1 自检

自检指的是,BIOS在电脑刚接通电源时对硬件部分的检测,也叫做加电自检Power On Self Test,简称POST)。POST功能是检查电脑是否良好

通常完整的POST自检将包括对CPU、640K基本内存、1M以上的扩展内存、ROM、主板、CMOS存储器、串并口、显卡、软硬盘子系统及键盘进行测试

检查的流程就是BIOS在启动时会读取硬件参数的实际值,然后后设置值进行比较,如果不符合,就表示硬件没有正常启动,或者缺少硬件,此时就会影响系统的启动,因此就无法启动。例如,对于绝大部分系统,开机时候没有键盘和鼠标都是可以的,但是对于一些图形工作站,要求在开机的时候要插入鼠标,所以如果开机的时候没有鼠标,就会响几声然后关机,这个其实就是因为BIOS开机检测到没有鼠标。

一旦在自检中发现问题,系统将给出提示信息或鸣笛警告。例如如果没插内存条开机,会“滴滴滴”响五声报警,这个就是来自BIOS的报警。而关于响几声、几长几短所表示的含义,需要查BIOS手册。

此外,自检中如发现有错误,将按两种情况处理:

  • 对于严重故障(致命性故障)则停机,此时由于各种初始化操作还没完成,不能给出任何提示或信号
  • 对于非严重故障则给出提示或声音报警信号,等待用户处理。

3.2 初始化

BIOS的第二个功能,就是初始化。而初始化具体干的事情,包括:创建中断向量设置寄存器对一些外部设备进行初始化和检测等

3.3 引导操作系统

BIOS第三个功能是引导DOS或其他操作系统启动。

BIOS在第二步在初始化的时候已经知道了系统上有多少个软盘、硬盘。而后BIOS会循环检查每个软盘和硬盘中是否有操作系统的BootLoader程序:

  • 如果有的话,BIOS会从软盘或硬盘中读取BootLoader,然后就把电脑的控制权转给BootLoader,然后运行BootLoader
  • 如果没有的话,则会在显示器上显示没有可以启动的设备(No Bootable Deveice

BootLoader是操作系统开发者开发的一个程序,目的是把操作系统装入电脑,所以在BIOS把电脑控制权给BootLoader的时候,BIOS其实就已经结束运行了。

No Bootable Device错误

上面我们其实已经讲完了BIOS到底干了什么,我们下面讲解一些重要的内容

4 实模式下的1MB内存布局

我们上面说到,在BIOS在初始化的时候会创建中断向量表(中断向量表也在内存中),在引导操作系统的时候会把操作系统的BootLoader读取到内存中。

所以,我们还得讲讲BIOS在启动的时候,内存底端1MB的布局

4.1 为什么是底端1MB

在正式开始讲内存底端1MB的布局前,我们可能会有一个疑问,就是为什么要将内存底端1MB,而不是整个内存?也不是高端10MB

之所以是低端1MB,其实是由Intel 8086 CPU的实模式决定的。Intel 8086 CPU内部的地址总线宽度是20位的,也就是说有20 条地址线,故其可以访问的内存空间地址是从0x00000~0xFFFFF(地址范围若按十六进制来表示),而能够访问的内存大小就是$2^{20}\ B = 1048576\ B =1\ MB$

Intel 8086之所以有20个地址总线,这个就是硬件工程师的设计了,反正我是不知道硬件工程师设计的初衷是什么,可能就是比较容易设计吧。总之在计算机开机之后,CPU处于实模式下,此时所有的运行方式都是和8086一样的,所以虽然现在的CPU更加高端,能够有64位地址总线,但是CPU还是只能够利用其中的20位。

因此,不管是什么CPU,在切换到保护模式之前,都只能利用、读取1MB内存。

4.2 内存还是寻址空间?

我们在计算机基础知识的那篇文章里面讲到,CPU输出的实际上是地址空间,只不过内存映射到了地址空间。

因此,我们这里讲的内存底端1MB,到底是CPU眼中的地址空间,还是真实的物理内存中的低端1MB?答案其实是,这里讲的1MB其实是地址空间的底端1MB。因为这里都是CPU输出的地址。

4.3 底端1MB内存布局

BIOS运行结束后,内存底端1MB的布局如下:

内存底端1MB布局

0x00000~0x9FFFF

寻址空间的0x00000~0x9FFFF被映射到内存DRAMDynamic Random Access Memory),即动态随机访问内存。我们所装的内存条的学术名称其实就是DRAM,而根据其所使用的技术,就有DDRDDR2等等区分。

寻址空间0x00000~0x9FFFF的空间范围是640KB,这片地址对应到了DRAM,也就是插在主板上的内存条。所以在开机的时候,不管你的内存条有多大,都只能使用前面的640KB

DRAM中的动态是什么意思?

动态实际上是来源于DRAM内存条中的存储单元。存储单元的存储介质由于本身电气元件的性质,需要定期地刷新。所以是动态。

更加详细的来说,存储单元中中的每一位都是由电容和晶体管组成的。那么既然是电容,就会存在漏电问题,何况现在内存都是4GB起步,内存条那么小的面积,电容得有多小。如此小的电容,漏电更快了。

所以为了保证存储的数据不丢失,电容漏电了就要及时把电补充上去,这样数据才不至于丢失。这个补充电的过程就称为刷新。其实不仅是电容需要刷新,就连电信号也是一样的。我们平时使用的网线,也是需要在每隔一定长度距离时接个中继放大器,这个就是来放大电信号的,因为物理链路越长,信号衰减就越严重,只能通过这种打气的方式来保持稳定了

0xF0000~0xFFFFF

寻址空间顶部的OxFOOOO~0xFFFFF,这64KB的寻址空间映射到了BIOS程序在的ROM芯片。

BIOS的主要工作我们上面介绍过了,就是检测、初始化硬件。而硬件是怎么初始化的?其实硬件本身也会有一个BIOS,主要负责硬件的初始化,因此硬件其实自己提供了一些初始化的功能调用,主板上的BIOS直接调用就好了。

这里最关键的一件事就是,BIOS建立了中断向量表,这样就可以通过int 中断号来实现相关的硬件调用。当然BIOS其实只提供了硬件基础的IO操作,也就是提供了硬件最基础的输入输出,但由于就BIOS就只有64KB大小的空间,不可能把所有硬件的IO实现的面面俱到。但其实也没必要实现那么多,毕竟是在实模式之下,对硬件支持得再丰富也自搭,精彩的世界是在进入保护模式以后才开始,所以挑一些重要的、保证计算机能运行的那些硬件的基本IO操作去实现即可。这就是 BIOS 称为基本输入输出系统的原因

0x07C00~0x07DFF

上面的表中,寻址空间0x07C00~0x07DFF512KB的内容存储MBR

那么什么是MBR?MBR其实就是硬盘中一片512字节大小的区域,操作系统的BootLoader就在其中,所以其实引导操作启动的BootLoader程序就会被加载到内存中0x07C00~0x07DFF这片内存中。

为什么是0x07C00

我们可能有一个问题,就是BIOS Area Data0x07C00中间有30KB的空余空间,那为什么要把MBR放到0x07C00中?这样不是会造成内存浪费么?

0x7C00 的来源其实非常久远,并不是Intel的规定,而是BIOS的规定。而BIOS是伴随个人计算机诞生的,因此还得先讲讲最早的个人计算机

1981月,IBM公司生产了世界上第一台个人计算机PC 5150 ,它是现代 x86 个人计算机的祖先。而0x07C00最早就出现在IBM PC 5150BIOS

IBM PC 5150

IBM PC 5150BIOS中调用了int 19h中断处理程序。通电开机之后,IMB PC 5150BIOS处理程序开始自检,在最后调用0x19h ,即call int l9h

而在19h中断处理函数中, IBM PC 5150 BIOS要检测这台计算机有多少硬盘或软盘,如果检测到了任何可用的磁盘,IBM PC 5150 BIOS就把它的第 一个扇区加载到0x7c00,所以0x7c00就是来源于此。

所以想要搞清楚为什么是0x7C00就得搞明白,IBM PC 5150当时的寻址空间。在这台计算机上,运行的操作系统是DOS 1.0,此系统要求是32KB,搜所以PC 5150 BIOS研发工程师就假定内存是32KB的,所以PC 5150 BIOS是按最小内存32K研发的。

MBR不是随便放在哪里都行的,首先不能覆盖己有的数据,其次,不能过早地被其他数据覆盖。

  • 不覆盖己有数据,这个好理解。
  • 而由于MBR中的BootLoader的任务是加载某个程序(这个程序一般是内核加载器,很少有直接加载内核的)到指定位置,并将控制权交给它。所谓的交控制权就是jmp指令。在之后MBR就没用了,被覆盖也没关系。所以所说的过早被覆盖,是指不能让MBR破坏自己,比如被加载的程序(如内核加载器),其放置的内存位置若是MBR自己所在的范围,这不就是破坏自己了吗,这就是我所说的过早了,怎么也得等MBR执行完才行。

最后,重现一下IMB PC 5150当时的内存使用情况:

  • 0x00000~0x003FF存放中断向量表,所以此处不能动了,再选新的地方看看
  • DOS 1.0要求的最小内存32KBMBR希望给人家尽可能多的预留空间,这样也是保全自己的作法,免得过早被覆盖。所以 MBR 只能放在32KB的末尾

  • MBR 本身也是程序,是程序就要用到栈,栈也是在内存中的,MBR虽然本身只有512字节,但还要为其所用的栈分配点空间,所以其实际所用的内存空间要大于512字节,但1KB内存够用了

结合以上三点,选择32KB中的最后1KB来存放MBR中的BootLoader最为合适,那此地址是多少呢? 32KB换算为十六进制为0x8000,减去1KB的大小(0x400)的话,就等于0x7C00

以上就是MBR中的BootLoader被加载到的Ox7C00的由来

0xA0000~0xBFFFF

寻址空间的0xA0000~0xBFFFF这段空间被映射到显存里面去了。而显卡由于工作模式不同,有:

  • 黑白图像模式
  • 彩色图像模式
  • 字符模式

所以将显存分为三个区域,分别存储需要显示的内容。

0xC0000~0xC7FF

这2048字节的内容映射到了显卡的BIOS

0xC8000~0xEFFFF

160KB的内容映射到了其他硬件


文章作者: Jack Wang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Jack Wang !
  目录