SeaBIOS(3) - 启动流程

SeaBIOS程序的各种入口点都在src/romlayout.S这个文件中定义了,启动包括了vCPU上电后开始执行的起点src/romlayout.S:reset_vector,该位置会被QEMU加载到vCPU物理空间的0xFFFFFFF0位置。该处的指令是一个跳转指令,该指令会跳转到src/romlayout.S:entry_post位置,然后判断是否是系统resume,如果不是则跳转到post.c:handle_post()函数处,开始POST(Power On Self Test)阶段。


post.c:handle_post()主要执行如下操作:

  1. 初始化debug串口

  2. 将SeaBIOS程序拷贝到0xC0000 ~ 0x100000内存区域,并且将这段内存区域的属性设置为可写的。

  3. 检测当前平台信息,如使用的芯片组类型,内存大小等,创建相应的E820表表项,设置内存分配函数分配内存时从哪些内存区域获取内存。

  4. 跳转到maininit()函数


maininit()函数会对各种系统资源进行初始化,然后寻找可启动的设备,详细步骤如下:

  1. 对系统的各种接口进行初始化,主要是软件上的接口,没怎么动到其他硬件

    1. 对fw_cfg设备进行初始化,该设备是QEMU传递Firmware信息给SeaBIOS的一个模拟设备,SeaBIOS通过fw_cfg设备可以获取到SMBIOS、ACPI、E820表等信息。

    2. 初始化中断向量表

    3. 初始化BDA(BIOS Data Area)、EBDA(Extended BIOS Data Area)数据区,这两个区域是BIOS标准中定义的,用于存放一些BIOS相关的信息,并且有一些指定的用途。

  2. 配置平台硬件

    1. 配置平台DMA控制器

    2. 配置中断控制器

    3. 配置PCI设备,搜索系统中的PCI设备,并为各个PCI设备分配I/O和Memory地址空间,让系统能够正确地访问PCI设备,并配置相应的中断。

    4. 配置好SMRAM的内存入口点,并将其隐藏起来

    5. 配置好MTRR(Memory Type Range Register)寄存器,即配置不同内存区间的内存属性(从CPU的角度看)

    6. 给其他非BSP(Bootstrap Processor)CPU,即AP(Application Processor)发送IPI中断,让AP对其自身进行初始化。并等待其他AP执行完毕。

    7. 建立MP表,SMBIOS表和ACPI表

    8. 配置时钟和定时器

  3. 选取系统的显卡,并执行其PCI Option ROM对显卡进行初始化,这步完成后,显示器就被点亮了,并且可以开始显示启动过程

  4. 对各种外设进行初始化,如USB控制器,磁盘控制器,键鼠控制器等等,由于外设比较多,并且速度慢,所以在对这些设备进行初始化的时候,SeaBIOS引入了Thread的概念(其实更应该叫做协程),让多个设备的初始化同时执行,并不是严格的并行执行,此时只有一个CPU在执行,它在多个设备的初始化程序中来回切换,确保不会在一个设备的初始化中卡住很长时间

  5. 执行其他PCI设备的Option ROM,初始化相应的PCI设备

  6. 收集可启动选项,并且调用0x19中断,开始OS的启动。


至此,SeaBIOS的执行过程已经大致理清,其中还包含了很多细节没有提到,想要了解其中的细节还需要看具体的代码。

同时也欢迎关注同名微信公众号“河马虚拟化”第一时间获取最新文章。


猜你喜欢

转载自blog.csdn.net/lindahui2008/article/details/81025064