默认情况下,Debian 的启动过程分为主板 UEFI 启动 Grub2, 再由 Grub2 启动 Linux 系统。
然而从 Debian Wheezy 起,Debian Linux 内核包含了一个自己的 BootLoader
叫作 EFI stub
(或者叫作 EFI boot stub
)。
因此可以从 UEFI 直接启动内核,而不需要额外的 bootloader 例如 Grub2.
要实现以上所述,需要进行一些设置,大致可以分为以下两步:
- 复制 kernel 和 initrd 到 EFI 分区
- 创建 UEFI 启动条目
复制 kernel 和 initrd 到 EFI 分区
根据 EFIStub - Debian Wiki
, UEFI 启动只能从 EFI 分区加载文件。因此需要将内核文件和 initrd 文件放置到 EFI 分区。
使用 lsblk 查看分区挂载情况:
1
2
3
4
5
6
7
8
9
10
| $ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
...
nvme0n1 259:0 0 476.9G 0 disk
|-nvme0n1p1 259:1 0 976M 0 part /boot/efi
|-nvme0n1p2 259:2 0 977M 0 part /boot
`-nvme0n1p3 259:3 0 475G 0 part
|-Debian-root 254:0 0 31.3G 0 lvm /
...
|
手动复制内核和 initrd
默认情况下,Debian 的内核和 initrd 文件位于 Boot 分区,即 /boot/ 下,例如:
1
2
3
4
| $ ls -Alhs /boot/{vmlinuz,initrd}*
45M -rw-r--r-- 1 root root 45M Dec 31 03:37 /boot/initrd.img-6.12.63+deb13-amd64
12M -rw-r--r-- 1 root root 12M Dec 31 03:37 /boot/vmlinuz-6.12.63+deb13-amd64
|
复制内核文件
1
| sudo cp --verbose "/boot/vmlinuz-$(uname -r)" /boot/efi/EFI/debian/vmlinuz.efi
|
复制 initrd 文件
1
| sudo cp --verbose "/boot/initrd.img-$(uname -r)" /boot/efi/EFI/debian/initrd.img
|
自动复制内核和 initrd
自动化复制内核
创建文件 /etc/kernel/postinst.d/zz-update-efistub
1
| sudo nano /etc/kernel/postinst.d/zz-update-efistub
|
填入内容:
1
2
3
4
| #!/bin/bash
set -eux -o pipefail
cp --verbose "$2" /boot/efi/EFI/debian/vmlinuz.efi
|
授予执行权限:
1
| sudo chmod +x /etc/kernel/postinst.d/zz-update-efistub
|
自动化复制 initrd
创建文件 /etc/initramfs/post-update.d/zz-update-efistub
1
2
| sudo mkdir -pv /etc/initramfs/post-update.d/
sudo nano /etc/initramfs/post-update.d/zz-update-efistub
|
填入内容:
1
2
3
4
| #!/bin/bash
set -eux -o pipefail
cp --verbose "$2" /boot/efi/EFI/debian/initrd.img
|
授予执行权限:
1
| sudo chmod +x /etc/initramfs/post-update.d/zz-update-efistub
|
警告
根据 EFIStub - Debian Wiki
,以上脚本会在每一个 kernel 或 initrd 更新时被执行,根据更新操作的顺序可能会导致复制错误版本的文件到 EFI 分区,可能无法正常启动系统。因此建议保留其他启动手段如 Grub2 或 rEFInd 作为备用。
测试脚本是否正常运行
执行:
1
| sudo dpkg-reconfigure linux-image-$(uname -r)
|
从输出的日志中,可以看到前面创建的脚本被运行,内核文件和 initrd 文件被复制到 EFI 分区。
1
2
3
4
5
6
7
8
| /etc/kernel/postinst.d/initramfs-tools:
update-initramfs: Generating /boot/initrd.img-6.12.63+deb13-amd64
+ cp --verbose /boot/initrd.img-6.12.63+deb13-amd64 /boot/efi/EFI/debian/initrd.img
'/boot/initrd.img-6.12.63+deb13-amd64' -> '/boot/efi/EFI/debian/initrd.img'
/etc/kernel/postinst.d/zz-update-efistub:
+ cp --verbose /boot/vmlinuz-6.12.63+deb13-amd64 /boot/efi/EFI/debian/vmlinuz.efi
'/boot/vmlinuz-6.12.63+deb13-amd64' -> '/boot/efi/EFI/debian/vmlinuz.efi'
|
创建 UEFI 启动条目
本文使用 efibootmgr 为例创建 UEFI 条目,使用其他工具或方法也是可行的。
使用 efibootmgr 创建 UEFI 启动条目,如:
1
2
3
4
5
| sudo efibootmgr --create \
--disk /dev/sdX --part YY \
--label "LABEL_NAME" \
--loader /EFI/debian/vmlinuz.efi \
--unicode "root=BLOCK_DEVICE_IDENTIFIER ro quiet initrd=\\EFI\\debian\\initrd.img"
|
--disk 指定硬盘设备。--part 指定硬盘第几个分区为 EFI 分区。--label 指定自己喜欢的名字,会显示在主板开机启动项菜单中。BLOCK_DEVICE_IDENTIFIER 填写系统根目录 / 所在分区的标识符,一般是 UUID=******* 的形式。可以通过 lsblk -f 或者 blkid 查询。也可以参照 Grub2 的配置文件进行设置 sudo cat /boot/grub/grub.cfg | grep -i 'root='
该命令在不指定 --index 参数的情况下,创建的条目将会被放在启动顺序 0 的位置, 即开机时第一个启动。
示例
以我的电脑为例,我的硬盘为 /dev/nvme0n1, 第 1 个分区为 EFI 分区。因为我将根分区安装在 LVM 中,参考 Grub2 的配置文件写作 root=/dev/mapper/Debian-root
1
2
3
4
5
| $ sudo cat /boot/grub/grub.cfg | grep -i 'root='
...
linux /vmlinuz-6.12.63+deb13-amd64 root=/dev/mapper/Debian-root ro quiet
...
|
1
2
3
4
5
6
7
8
9
10
11
12
| $ sudo efibootmgr --create \
--disk /dev/nvme0n1 --part 1 \
--label "Debian EFIstub" \
--loader /EFI/debian/vmlinuz.efi \
--unicode "root=/dev/mapper/Debian-root ro quiet initrd=\\EFI\\debian\\initrd.img"
BootCurrent: 0000
Timeout: 2 seconds
BootOrder: 0000,0002,0010,0011,0012,0013,0018,0019,001A,0017,0016,001B
Boot0002* debian HD(1,GPT,c7bzfazx-bap4-q7ch-bd3m-bucyj939s4hq,0x800,0x1e8000)/File(\EFI\debian\shimx64.efi)
...
Boot0000* Debian EFIstub HD(1,GPT,c7bzfazx-bap4-q7ch-bd3m-bucyj939s4hq,0x800,0x1e8000)/File(\EFI\debian\vmlinuz.efi)root=/dev/mapper/Debian-root ro quiet initrd=EFI\debian\initrd.img
|
可以看到新增了一个 Boot0000 的条目,名为 Debian EFIstub 。
而 Boot0002 debian 是原有的 Grub2 的 UEFI 启动条目。
测试
完成以上设置后,正常情况下,重启电脑,成功通过 UEFI 直接启动 Debian,而无须经由 Grub2 启动。
提示
根据 EFIStub - Debian Wiki
和 EFI boot stub CONs
的建议,最好保留例如 Grub2 这样 bootloader 以避免意外情况下无法启动系统。
有关 efibootmgr
显示所有 UEFI 启动条目
1
2
3
4
5
6
7
8
9
10
| $ sudo efibootmgr -u
BootCurrent: 0000
Timeout: 2 seconds
BootOrder: 0000,0002,0010,0011,0012,0013,0018,0019,001A,0017,0016,001B
Boot0000* Debian EFIstub HD(1,GPT,c7bzfazx-bap4-q7ch-bd3m-bucyj939s4hq,0x800,0x1e8000)/File(\EFI\debian\vmlinuz.efi)root=/dev/mapper/Debian-root ro quiet initrd=EFI\debian\initrd.img
Boot0002* debian HD(1,GPT,c7bzfazx-bap4-q7ch-bd3m-bucyj939s4hq,0x800,0x1e8000)/File(\EFI\debian\shimx64.efi)
...
...
...
|
删除 UEFI 启动条目
本文写作时,efibootmgr 没有编辑条目的功能,但可以删除指定条目:
1
| sudo efibootmgr --delete-bootnum --bootnum YYYY
|
批量删除所有名为 Debian EFIstub 的条目:
1
| sudo efibootmgr | grep 'Debian EFIstub' | awk -F'Boot' '{print substr($2, 1, 4)}' | xargs -I {} sudo efibootmgr --delete-bootnum --bootnum {}
|
参考