EFI Stub 初探

EFI stub 是 Linux 内核的一项特性,允许 UEFI 固件直接把 Linux 内核作为 efi 可执行文件进行加载。也就是说,如果在支持 UEFI 的机器上采用了 EFI stub,那么 grub 这类 bootloader 就完全多余了,因为 UEFI 固件自身就能直接执行 Linux 内核,无需再经过一层 bootloader 来中转。

如果想使用 EFI stub,必须满足以下几项条件:

1、Linux 内核版本至少为 3.3,且开启了 EFI stub 支持。

2、主板支持完整的 UEFI 功能,能够识别和编辑 Windows 以外的 boot entry(部分 UEFI 主板只支持 Windows 的 boot entry)。

3、主板可关闭 Secure Boot。

如果以上条件都满足,那么就可以进行下面的操作了。

首先,用 efibootmgr 查看当前的 boot entry 情况(以我的为例):

# efibootmgr
BootCurrent: 0002
Timeout: 1 seconds
BootOrder: 0002,0000
Boot0000* Arch
Boot0002* Gentoo

可以看到,我总共只有两个 boot entry,一个是 Arch,一个是 Gentoo。接着,把 ESP 挂载到 /boot/efi,我的 ESP 是 /dev/sda1

# mount /dev/sda1 /boot/efi

然后,把内核和 initramfs 复制到 ESP 的根目录(也可在 ESP 里面自己建立其他目录,为了方便起见,我复制到根目录):

# cp /boot/vmlinuz-4.2.0-gentoo /boot/efi/
# cp /boot/initramfs-4.2.0-gentoo.img /boot/efi/

接下来就需要为 Linux 内核建立一个 boot entry 了,同时,也要注意传递必要的内核参数。

# efibootmgr -d /dev/sda -p 1 -c -L "Gentoo Linux-4.2.0" -l /vmlinuz-4.2.0-gentoo -u "root=de10ba6f-9361-4dc0-ba01-57c4c3ac2c67 rootflags=subvol=@gentoo initrd=/initramfs-4.2.0-gentoo.img"

这里我说明一下几个参数的含义,以明确这么做的原理。

-d 指定内核所处的磁盘
-p ESP 的分区编号,从 1 开始
-c 创建新的 boot entry
-L boot entry 的标签(即名称)
-l 内核在 ESP 中的绝对路径
-u 需要传递给内核的参数,我指定了根分区的 UUID(也可以指定根分区的块设备名)、从哪个 btrfs subvolume 启动,以及 initramfs 在 ESP 中的绝对路径

创建完成以后,再用 efibootmgr 验证一下:

# efibootmgr
BootCurrent: 0002
Timeout: 1 seconds
BootOrder: 0003,0002,0000
Boot0000* Arch
Boot0002* Gentoo
Boot0003* Gentoo Linux-4.2.0

然后就可以重启,用 Boot Menu 快捷键选择刚刚创建的 boot entry 进行测试了。

启动速度并没有什么优势,只是少了个中间环节而已。

但是 EFI stub 也有弊端:

1、ESP 的空间需要足够大,可以容纳多个版本的内核和 initramfs。由于是通过 UEFI 固件直接加载内核,所以内核和 initramfs 必须放在 ESP 内。

2、每次内核和 initramfs 升级以后需要重新复制过去,并创建新的 boot entry(Arch 例外,原因大家都知道)。当然,可以通过脚本来实现自动化。

因此,要不要用,就看个人喜好了。