如何使用 EFI 存根 (efistub) 加载程序引导加载内核?

Pro*_*kup 15 boot grub2 kernel uefi

我在 UEFI 模式下运行 Ubuntu 14.04 作为唯一的操作系统,这里没有双启动。内核版本为 3.13.0-24-generic。有一个 EFI 分区。在这种情况下,EFI 分区不是默认值,/dev/sda1而是/dev/sda3因为我确实将 BIOS 模式转换为 EFI 模式。我已经使用了这个grub-efi-amd64包,尽管它实际上是从 UEFI 固件启动菜单(UEFI 启动加载\EFI\ubuntu\grubx64.efi)加载 GRUB 启动菜单。

我想跳过那个双启动菜单加载步骤,直接从 UEFI 启动到内核中。自 12.10 以来Ubuntu 内核具有“内核 EFI 存根加载程序”功能。

我知道我确实需要将 Ubuntu 内核复制到 EFI 分区(可能重命名)并在 UEFI 启动菜单中创建一个条目(例如使用efibootmgr)。执行此操作需要哪些确切的终端命令?

Pro*_*kup 16

下面的命令比内核版本 3.13.0-35 更通用。

1.挂载efi分区并将内核文件复制到那里

$ mount /dev/sda3 /boot/efi

$ mkdir -pv /boot/efi/EFI/ubuntu/

$ cp -uv /boot/vmlinuz-* /boot/initrd.img-* /boot/efi/EFI/ubuntu/
'/boot/vmlinuz-3.13.0-35-generic' -> '/boot/efi/EFI/ubuntu/vmlinuz-3.13.0-35-generic'
'/boot/initrd.img-3.13.0-35-generic' -> '/boot/efi/EFI/ubuntu/initrd.img-3.13.0-35-generic'
Run Code Online (Sandbox Code Playgroud)

2.更改内核文件名

通过删除来缩短内核文件名,-generic因为似乎有 39 个字符的路径长度限制和 Rename kernel file(s) to end in .efi,这确保了与大多数系统的兼容性

$ for f in /boot/efi/EFI/ubuntu/vmlinuz-*-generic; do mv -uv -- "$f" "${f//-generic/}.efi"; done
'/boot/efi/EFI/ubuntu/vmlinuz-3.13.0-35-generic' -> '/boot/efi/EFI/ubuntu/vmlinuz-3.13.0-35-generic.efi'`
Run Code Online (Sandbox Code Playgroud)

对于已dpkg安装的主线内核,上述名称内核文件名的缩短是不够的,因为例如/EFI/ubuntu/vmlinuz-3.16.0-031600rc6.efiwithout-generic仍然是 40 个字符长。

3.在EFI启动菜单中添加新条目

3.13.0-35在此示例中替换为您的特定内核版本

$ kv=3.13.0-35;efibootmgr -c -p 3 -L $kv -l \EFI\ubuntu\vmlinuz-$kv.efi -u root=/dev/sda1 initrd=\\EFI\\ubuntu\\initrd.img-$kv-generic ro rootfstype=ext4 debug ignore_loglevel libata.force=dump_id crashkernel=384M-:128M

这个新的启动菜单条目将成为您默认的新启动选项。

你可能不需要额外的调试参数debugignore_loglevellibata.force=dump_idcrashkernel=384M-:128MInitrd必须存在,否则引导挂起在“切换到时钟源 tsc。 ”因为无法打开根设备 sda1。


Léo*_*Lam 7

根据Debian wiki 的说法,这可以通过几个简单的步骤来完成,这些步骤将在内核更新后继续存在

注意:这假设您有一个 EFI 分区安装在/boot/efi.

  1. /etc/kernel/postinst.d/zz-update-efistub使用以下内容创建:

    #!/bin/sh
    cp /vmlinuz /initrd.img /boot/efi/EFI/ubuntu/
    
    Run Code Online (Sandbox Code Playgroud)

    这是一个将在内核更新时运行的钩子,用于将最新的内核映像和 initrd 复制到适当的位置。然后使其可执行并运行它:

    sudo chmod +x /etc/kernel/postinst.d/zz-update-efistub
    sudo /etc/kernel/postinst.d/zz-update-efistub
    
    Run Code Online (Sandbox Code Playgroud)
  2. 添加启动项:

    sudo efibootmgr -c -d /dev/sdb -p 1 -L "Ubuntu (efistub)" -l /EFI/ubuntu/vmlinuz -u "root=/dev/sdb2 rw initrd=/EFI/ubuntu/initrd.img quiet splash"
    
    Run Code Online (Sandbox Code Playgroud)

    不要忘记根据 EFI 系统分区的位置更改-d-p参数。就我而言,它是 /dev/sdb1,但这对您来说可能有所不同。您可能还必须root=将内核 cmdline 中的值更改为您的根分区。

    (您可以通过更改-L参数将标签更改为您想要的任何内容。)

    您刚刚添加的引导条目将成为默认条目。它不会在内核更新后中断,因为钩子将确保vmlinuzinitrd.img始终更新。