4. 主流Bootloader概览:U-Boot、GRUB、LILO、RedBoot、Coreboot、UEFI

Bootloader的世界,其实比大多数人想象的要热闹得多。很多人一提到Bootloader,脑子里蹦出来的就是U-Boot或者GRUB。嗯,这没错,但市面上还有不少“老炮儿”和“新贵”,各有各的看家本领。

我这些年做嵌入式底层,从ARM9一直干到RISC-V,接触过的Bootloader少说也有七八种。每种都有它诞生的历史背景和擅长的领域。今天我就带大家把这些主流选手挨个过一遍,看看它们到底有什么本事,又该在什么场景下选谁。

核心观点:没有最好的Bootloader,只有最合适的。选型的关键在于你的硬件平台、启动速度要求、以及团队的技术栈积累。

4.1 U-Boot:嵌入式领域的“瑞士军刀”

U-Boot,全称是Das U-Boot。这名字有点意思,德语里“U-Boot”是潜艇的意思。我猜作者是想表达它像潜艇一样,能在底层“潜行”,控制一切硬件。

U-Boot是目前嵌入式Linux领域事实上的标准。从ARM、MIPS、PowerPC到RISC-V,几乎你能想到的所有架构,它都支持。我个人习惯把它叫做“硬件初始化大管家”。

它的核心能力:

  • 硬件抽象层(HAL): 同一套代码,换块板子只需要改板级文件。我在项目中遇到过最夸张的一次,只改了200行代码,就把U-Boot从A平台移植到了B平台。
  • 网络启动: TFTP、NFS支持得非常完善。调试内核时,我几乎从来不用烧写Flash,全是网络加载。
  • 命令行交互: 它的Shell虽然简陋,但功能极强。你可以直接读写内存、操作寄存器、甚至烧写整个Flash。

我的经验: 调试新板子时,U-Boot的md(内存显示)和mw(内存写)命令是我的救命稻草。曾经有一次,DDR初始化参数配错了,系统死活跑不起来。我就是用U-Boot的md命令,一点点比对寄存器值,最终定位到问题。

U-Boot的启动流程大致是这样的:

1. 上电 -> CPU从ROM执行固化代码
2. SPL(Secondary Program Loader)初始化DDR和时钟
3. SPL加载U-Boot主程序到DDR
4. U-Boot主程序初始化外设(网卡、Flash、串口等)
5. 读取环境变量,决定启动方式(网络、Flash、SD卡)
6. 加载内核到内存,跳转执行

4.2 GRUB:PC世界的“老大哥”

GRUB,全称GRand Unified Bootloader。如果你用过Linux桌面版,那你一定见过它的启动菜单。GRUB是x86架构下Linux系统的标配。

GRUB有两个主要版本:GRUB Legacy(0.9x系列)和GRUB 2。现在主流发行版用的都是GRUB 2。GRUB 2最大的改进是模块化设计,支持动态加载文件系统驱动。

GRUB 2的特点:

  • 文件系统感知: 它可以直接读取ext4、btrfs、xfs等文件系统。这意味着你不需要单独分一个/boot分区。
  • 脚本支持: GRUB 2的配置文件(grub.cfg)其实是一个脚本。你可以写条件判断、循环,甚至调用外部命令。
  • 安全启动: 配合UEFI,GRUB 2支持签名验证,防止恶意软件篡改启动链。

避坑指南: 我曾经遇到过一个问题:系统更新后,GRUB菜单里出现了两个相同的内核选项。排查了半天,发现是grub-mkconfig脚本把旧内核也扫描进来了。解决方案很简单:手动清理/boot目录下的旧内核文件,然后重新生成grub.cfg。

4.3 LILO:曾经的“元老”

LILO,全称LInux LOader。说实话,现在用LILO的人已经很少了。但它作为Linux历史上最早的Bootloader之一,值得提一笔。

LILO最大的“槽点”是:每次修改内核或配置文件后,必须重新运行/sbin/lilo命令,把启动信息写入磁盘的主引导记录(MBR)。这跟GRUB的“动态读取配置文件”完全不同。

LILO vs GRUB:

特性 LILO GRUB 2
配置文件修改后 需重新安装到MBR 无需操作,自动读取
文件系统支持 有限(依赖BIOS) 丰富(内置驱动)
网络启动 不支持 支持(通过PXE)
维护活跃度 已停止维护 持续更新

如果你现在还在用LILO,我建议你尽快迁移到GRUB 2。原因很简单:LILO对现代硬件(如GPT分区、UEFI)的支持非常差,而且已经没人维护了。

4.4 RedBoot:eCos生态的“遗珠”

RedBoot,全称Red Hat Bootloader。它是eCos实时操作系统的一部分,但也可以独立使用。RedBoot在早期嵌入式领域(尤其是ARM7、ARM9时代)非常流行。

RedBoot最大的特点是轻量级。它的代码量很小,非常适合资源受限的嵌入式系统。而且它内置了GDB调试桩(GDB stub),可以直接通过串口调试内核。

RedBoot的典型应用场景:

  • 工业控制设备
  • 网络路由器/交换机
  • 早期的智能手机(如Nokia N900)

不过,随着U-Boot的崛起,RedBoot逐渐被边缘化了。现在新项目很少用RedBoot,除非你是在维护一个老旧的eCos系统。

4.5 Coreboot:追求极致启动速度

Coreboot,以前叫LinuxBIOS。它的目标很明确:用最少的代码完成硬件初始化,然后快速把控制权交给操作系统。

Coreboot的哲学是“只做必要的事”。它不像U-Boot那样提供丰富的命令行交互,也不像GRUB那样有漂亮的启动菜单。Coreboot的核心任务就是:初始化CPU、内存、芯片组,然后跳转到payload(如SeaBIOS、GRUB、Linux内核)。

Coreboot的启动速度有多快? 我见过一个优化案例:从按下电源键到进入Linux登录界面,只用了不到3秒。这在传统BIOS/UEFI上是很难想象的。

适用场景: Chromebook、数据中心服务器、以及任何对启动速度有极致要求的设备。

4.6 UEFI:现代PC的“新标准”

UEFI,全称Unified Extensible Firmware Interface。它不是传统意义上的Bootloader,而是一个固件接口规范。UEFI定义了操作系统和固件之间的交互方式。

UEFI的出现,是为了取代老旧的BIOS。BIOS有很多限制:只能从MBR启动、不支持2TB以上硬盘、启动速度慢。UEFI则解决了这些问题。

UEFI的核心特性:

  • GPT分区表: 支持2TB以上硬盘,最多128个主分区。
  • 安全启动(Secure Boot): 只允许运行经过签名的启动加载器。
  • 网络启动: 原生支持HTTP Boot,不需要额外的PXE ROM。
  • 驱动模型: UEFI本身就是一个微型操作系统,可以加载各种驱动。

UEFI的启动流程比传统BIOS复杂一些:

1. 上电 -> CPU初始化
2. UEFI固件执行SEC(安全验证)阶段
3. PEI(EFI预初始化)阶段:初始化内存
4. DXE(驱动执行环境)阶段:加载各种驱动
5. BDS(启动设备选择)阶段:选择启动设备
6. 加载UEFI应用(如GRUB或Windows Boot Manager)
7. 加载操作系统内核

我的建议: 如果你在做x86平台的嵌入式开发,尽量使用UEFI+GRUB的组合。UEFI提供了标准化的接口,GRUB提供了灵活的内核加载能力。这个组合在兼容性和可维护性上,远胜于传统的BIOS+LILO。

4.7 知识体系总览

为了让你更直观地理解这些Bootloader之间的关系和适用场景,我画了一张图:

主流Bootloader知识体系总览 Bootloader 按平台分类 嵌入式平台 PC / 服务器 固件接口 U-Boot RedBoot Coreboot Barebox GRUB 2 LILO Syslinux Windows Boot UEFI BIOS (Legacy) 选型建议: • 嵌入式Linux新项目:首选U-Boot,生态最好,社区最活跃 • x86 PC/服务器:GRUB 2 + UEFI,兼容性和功能最均衡 • 极致启动速度:Coreboot + 轻量级payload • 老旧系统维护:根据现有平台选择,尽量迁移到现代方案 • 资源极度受限:考虑RedBoot或Barebox(如果平台支持)

4.8 如何选择?

说了这么多,到底该怎么选?我个人的经验是:

  1. 看硬件平台: ARM/RISC-V用U-Boot,x86用GRUB+UEFI,这基本是行业惯例。
  2. 看启动速度要求: 如果要求秒级启动,考虑Coreboot或U-Boot的SPL优化。
  3. 看团队技术栈: 如果团队熟悉U-Boot,就别强行上Coreboot。学习成本也是成本。
  4. 看生态支持: 选社区活跃、文档丰富的方案。遇到问题能搜到答案,比什么都重要。

最后提醒一句: 不要为了“炫技”而选择冷门Bootloader。我见过一个项目,团队为了追求“极致性能”,自己写了一个Bootloader。结果光调试就花了三个月,最后性能还不如直接用U-Boot。嗯,有时候“随大流”反而是最稳妥的选择。