Boot Sequence

来自osdev
Zhang3讨论 | 贡献2021年12月17日 (五) 02:30的版本 (创建页面,内容为“== POST == 当计算机被打开或重置时,它会运行一系列被称为POST-“P”ower-“O”n-“elf-“T”est的诊断。 这一顺序的最终结果是按照固件配置的顺序定位可引导设备,如软盘、CD-ROM或硬盘。 == 主引导记录 == (传统)BIOS检查可引导设备的引导签名,即所谓的幻数。 引导签名位于引导扇区(扇区号0)中,它分别在字节偏移量510和511处包含字节序列0x55、0x…”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索

POST

当计算机被打开或重置时,它会运行一系列被称为POST-“P”ower-“O”n-“elf-“T”est的诊断。 这一顺序的最终结果是按照固件配置的顺序定位可引导设备,如软盘、CD-ROM或硬盘。

主引导记录

(传统)BIOS检查可引导设备的引导签名,即所谓的幻数。 引导签名位于引导扇区(扇区号0)中,它分别在字节偏移量510和511处包含字节序列0x55、0xAA。 当BIOS找到这样一个引导扇区时,它被加载到内存中的0x0000:0x7c00(段0,地址0x7c00)。(但是,某些BIOS加载到0x7c0:0x0000(段0x07c0,偏移量0),这解析为相同的物理地址,但可能会令人惊讶。 一个好的实践是在启动扇区的一开始就强制执行CS:IP。)

然后将执行转移到新加载的引导记录。 在软盘上,引导记录的所有512字节(保存最后两个签名字节)可能包含可执行代码。 在硬盘驱动器上,主引导记录(MBR)在偏移量0x0000-0x01bd处保存可执行代码,然后是四个 primary partitions的表项,每个项使用十六个字节(0x01be-0x01fd)和两个字节的签名(0x01fe-0x01ff)。

早期环境

这种早期执行环境是高度实现定义的,这意味着特定BIOS的实现。 “从不”对寄存器的内容做任何假设:它们可能被初始化为0,但也可能包含虚假值。 这包括标志寄存器和SP寄存器,您可能也没有有效的堆栈!唯一可以确定的是,DL寄存器保存了加载引导代码的驱动器代码。

CPU当前处于实模式。 (除非你运行的是一种罕见的BIOS,它认为为你激活保护模式是在帮你的忙。 这意味着您不仅必须编写代码来激活任何“其他”硬件上的保护模式,而且还应添加测试条件(如果已激活)。)

内核

最后,引导加载程序将内核加载到内存中,并将控制权传递给它。

加载

现在我们知道要加载什么了,让我们看看如何加载。

如果从硬盘引导,则只有446字节可用于引导记录。 查看内核映像运行之前要做的事情列表,您会同意这并不多:

  • 确定要从哪个分区启动(通过查找活动分区,或向用户提供要从中选择的已安装操作系统);
  • 确定内核映像在引导分区上的位置(通过解释文件系统或从固定位置加载映像);
  • 将内核映像加载到内存中(需要基本磁盘I/O);
  • 启用保护模式;
  • 为内核准备运行时环境(例如设置堆栈空间);

您不必按此顺序执行操作,但在调用kmain()之前,必须完成所有这些操作。

更糟糕的是,GCC只生成受保护模式的可执行文件,因此这个早期环境的代码是 C做不到的事情之一。

有几种方法可以解决此问题:

  • “极客加载”:将上面列表中的所有内容压缩到启动记录中。这几乎是不可能的,并且不会为任何特殊情况处理或有用的错误消息留下空间。
  • “一阶段加载”:编写一个用于切换的存根程序,并将其链接到内核映像前面。引导记录加载内核映像(低于1mb内存标记,因为在实模式下,这是内存上限!),跳入存根,存根切换到保护模式和运行时准备,跳入内核。
  • “两阶段加载”:编写一个“单独的”存根程序,该程序加载到1mb内存标记以下,并执行上述列表中的所有操作。

传统方式

传统上,MBR将自己重新定位到0x0000:0x0600,从分区表确定活动分区,将该分区的第一个扇区(“分区启动记录”)加载到0x0000:0x7c00(因此前一次重新定位),并跳到该地址。 这被称为“链式装载”。如果您希望自己编写的引导记录能够进行双重引导(例如Windows),则它应该模拟这种行为。

捷径

除非您真的想滚动您自己的引导加载程序(记录/存根)以获得教育价值,否则我们建议使用现成的引导加载程序

最突出的是GRUB,这是一种两级引导加载程序,它不仅提供具有链加载功能的引导菜单,而且将早期环境初始化为定义良好的状态(包括Protected Mode,并从BIOS读取各种感兴趣的信息),可以将通用可执行文件作为内核映像加载(而不像大多数其他引导加载程序那样需要平面二进制文件),支持可选的内核模块、各种文件系统以及if/正确配置,Diskless Booting

一些方法

有许多可能的变体可以引导。以下是方法列表,但可能还有更多方法:

  • 您可以使用一个未使用的分区并加载阶段2“raw”
  • 您可以将阶段2放在MBR和第一个分区的开始之间
  • 您可以(像Lilo那样)编写一个内核文件,然后使用工具检测扇区(或集群)。然后让阶段1从列表中加载扇区。
  • DOS和Windows是这样做的:创建一个空文件系统(格式化),然后将内核放在第一个文件中,将shell放在第二个文件中的空rootdir中。因此,加载程序只需加载rootdir中的第一个条目,然后加载第二个条目。
  • 旧Linux是从软盘引导的。第一个扇区(“boot”)以“raw”模式加载第二个阶段=不带文件系统(scond阶段是“setup”,在“boot”后面的扇区中)。第二个阶段设置了系统(视频模式、内存映射等),然后加载了真正的内核映像(打包在tgz/bz中)。
  • 几年前,这里有一个引导加载程序(称为“nuni”),它切换到pmode并加载一个文件,所有这些都在一个引导扇区中

See Also

外部链接

 de:Bootprozess auf x86