文章目录
背景
- 每个操作系统(OS)在设计时都会考虑对boot loader的支持,OS的安装通常也涉及boot loader的预安装。在支持多OS的物理服务器使用场景中,通过链式机制让一个OS去引导另一个OS显然效率低下;定义一套boot loader和OS之间的接口,让遵循接口的所有boot loader都可以引导遵循相同接口的OS,才是更合理的解决方案。多OS兼容的场景我们称为Multiboot,boot loader和OS之间的接口规范我们称为Multiboot Specification。
- GRUB是遵循Multiboot Specification的boot loader之一。1995年,Erich Boleyn和Brian Ford在GNU Hurd项目的开发过程中设计了Multiboot规范,并将GNU Hurd的boot loader作为规范的实现引导并其微内核GNU Mach。之后Erich尝试修改FreeBSD的boot loader让其兼容Multiboot规范,发现与其修改FressBSD的boot loader,不如直接从零开始单独写一个软件,至此GRUB诞生。可以说,GRUB就是为兼容多OS场景而生的。
- GRUB在之后不断扩展以满足新的需求和场景,但很快,开发者发现GRUB遵循的Multiboot规范存在一些致命的缺陷导致对某些新功能的支持非常困难,并且设计导致的bug也不断增多,因此在2002年,Yoshinori K. Okuji开始重写GRUB的核心代码并将其重命名为GRUB2,原来的GRUB被重命名为GRUB Legacy,GRUB2遵循了Multiboot2规范。约2007年,GNU/Linux的发行版开始使用GRUB2,到2009年,大多数的Linux发行版已经将GRUB2作为默认版本安装。
目标
- 分析多OS使用场景,Multiboot规范需要考虑以下需求:
- 支持多种方式的OS启动;包括光盘启动,硬盘启动以及网络等
- 支持启动阶段对OS的动态配置;规范需要定义配置的标准方式
- 避免对OS紧耦合;方便OS功能的独立开发
- 支持启动模块;部分OS的启动无法独立完成,它们依赖其它预先启动的模块,如微内核操作系统Mach,规范需要考虑对启动模块的通用支持
- 分析boot loader和OS的交互逻辑,可以将两者的接口定义从以下三个方面拆分:
- OS image format - 对OS镜像格式的定义,便于boot loader识别镜像并加载其内核到内存
- Machine state - 对boot loader状态的定义,便于OS判断其引导者boot loader的状态
- Boot information format - 对boot loader与OS之间传输信息的格式定义,便于控制OS的某些行为
- Multiboot与Multiboot2都基于以上的分析而设计,Multiboot2在具体定义上扩展性更强,标准化做的更好,下面我们基于以上三点对比介绍两个规范的具体内容。
OS image format
- OS image通常是一个普通的可执行文件(遵循ELF规范),其payload就是OS的section。通常boot loader将OS image加载到load address(ELF规范中section entry的sh_addr)对应的内存,之后跳转到entry address,最后将控制权交给OS。
- 如果所有的OS image都遵循ELF规范,那么boot loader总是可以根据规范找到OS image中包含的section并提取其load address,将其正确加载到load address指定的地址,但是,Muli