【Linux内核】从开机加电到main函数执行(1)

IsanaYashiro 2020-01-28

从开机加电到main函数执行(1)

启动BIOS,准备中断

BIOS的任务是将硬盘中的操作系统加载到内存中。

BIOS加载中断处理程序

BIOS的启动由硬件完成。8086系列在加电时进入16位实模式,将CS置为0xFFFF,IP置为0x0000, CS:IP指向0xFFFF0,指向了BIOS对应的地址。

CS是代码段寄存器,IP是指令指针寄存器,两者组合形成的地址是要执行的指令的内存地址,在实模式下是绝对地址

如果这个位置没有可执行代码会就此死机。有代码的话就会执行。BIOS会执行自检程序,检查显卡、内存,并建立中断向量表和中断服务程序。

BIOS在内存最开始的地方建立中断向量表(0x00000~0x003ff),在下面的256字节的内存构建BIOS数据区(0x00400~0x004FF),在56KB之后的内存中加载8KB左右的中断向量表对应的中断服务程序。

【Linux内核】从开机加电到main函数执行(1)

中断向量表中一共有256个中断向量,每个中断向量4个字节,每个中断向量对应一个中断处理程序。

加载内核程序

下面要进行的boot操作是把操作系统加载到内存,对于Linux而言,分三次将操作系统加载到内存中,第一批由BIOS中断int服务加载操作系统的bootsect,第二批和第三批由bootsect加载。

第一批bootsect

BIOS结束自检之后,执行一个int中断,对应启动加载服务程序。任务是找到硬盘并加载第一扇区,拷贝到0x07c00处。这个扇区中的内容是bootsect.s。

第二批setup

bootsect首先做的工作是规划内存。在实模式下,最大寻址空间是1MB,bootsect设计了如下的分布:

名字含义地址
SETUPLENsetup程序的扇区数4
BOOTSEG启动扇区被BIOS加载的位置0x07c0
INITSEG将要移动到的新位置0x9000
SETUPSEGsetup程序加载到的位置0x9020
SYSSEG内核加载的位置0x1000
ENDSEG内核的末尾位置

接下来,bootsect会将他自身(512B内容)从BOOTSEG位置复制到INITSEG位置。复制之后CS从BOOTSEG位置跳转到INITSEG位置。

然后bootsect初始化寄存器,将数据段寄存器(DS),附加段寄存器(ES),栈基址寄存器(SS)设置成CS的位置,将栈顶sp指向0xFF00处,如下图:

【Linux内核】从开机加电到main函数执行(1)

下面,bootsec程序将setup加载到内存中。

第三批system

由bootsect模块将系统模块载入内存,加载的扇区大小是240,加载到SYSSEG后面。

最后加载完成之后确定根设备号,将根设备号保存在root_dev中。

根文件系统设备:文件系统管理方式。要求系统有一个根文件系统,其他文件挂载在根文件上。Linux的启动需要两部分数据,内核镜像和根文件系统。(格式化好的设备)

bootsect的任务到此结束。下面进行setup程序。

setup的第一件事情是利用BIOS的中断服务从设备上提取及其系统数据,包括光标位置和显示页面等数据,并从0x41和0x46两个向量的内存地址处获得硬盘参数表,将这些数据加载到0x90000~0x901FC

相关推荐