默认情况下,Debian 的启动经历了主板启动 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 -e
cp --verbose "$2" /boot/efi/EFI/debian/vmlinuz.efi
|
授予执行权限:
1
| sudo chmod +x /etc/kernel/postinst.d/zz-update-efistub
|
创建脚本 /etc/initramfs/post-update.d/zz-update-efistub
1
2
| sudo mkdir -p /etc/initramfs/post-update.d/
sudo nano /etc/initramfs/post-update.d/zz-update-efistub
|
填入内容:
1
2
3
4
| #!/bin/bash
set -e
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
| update-initramfs: Generating /boot/initrd.img-6.12.63+deb13-amd64
'/boot/initrd.img-6.12.63+deb13-amd64' -> '/boot/efi/EFI/debian/initrd.img'
/etc/kernel/postinst.d/zz-update-efistub:
'/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 {}
|
参考