直接从 UEFI 启动内核

直接从 UEFI 启动内核

我想直接从 UEFI 启动 Arch Linux。

我的想法是使用该工具创建启动项efibootmgr;我使用了这个命令:

efibootmgr --create --label "arch-test" --loader /vmlinuz-linux --unicode 'root=PARTUUID=f2083749-8bbc-570b-ab3b-e79d72fa08ac rw initrd=\initramfs-linux.img' --verbose

我跟着EFISTUB 上的 Arch Wiki 页面我创建了该条目,但是当我尝试从该条目启动时,系统在很早的阶段就陷入启动状态,并显示以下消息:

VFS: unable to mount root fs on unknown-block(0,0)

PS:我想把它作为紧急/救援工具;即最新的systemd升级破坏了启动管理器(systemd-boot),使我的机器无法使用;借助外部实时 USB,我能够恢复我的系统。我想以后避免这种情况!


更新:
1. 有或没有/斜杠或反斜杠,之前initrd并不重要
2. 尝试同时使用UUIDand PARTUUID,没有任何变化
3. my /bootis on /dev/sda1while4./dev/sda3
也是/bootESP

    # fdisk -l /dev/sda
    [...]
    Disklabel type: gpt
    [...]

    Device         Start       End   Sectors   Size Type
    /dev/sda1       2048   2099199   2097152     1G EFI System
    /dev/sda2    2099200  18874367  16775168     8G Linux swap
    /dev/sda3   18874368 104857599  85983232    41G Linux filesystem
    [...]
    # minfo -i /dev/sda1 :: | grep 'disk type'
    disk type="FAT32   "
  1. 根据您的评论,我尝试了UEFI外壳。我已将此选项保留为最新选项,因为我的计算机没有内部 UEFI Shell (是否可以?)。无论如何,我有:

    • 从下载了一份天诺核心
    • 放入Shell.efi/boot/EFI/Boot/
    • 添加了一个条目

      efibootmgr --create --label "TIANO-0" --loader /EFI/Boot/Shell.efi --verbose
      
    • 重新启动到这个外壳程序,我输入fs0:vmlinuz-linux root=/dev/sda3

    • 导致同样的错误:

      VFS: unable to mount root fs on unknown-block(0,0)
      
  2. 看起来initrd是强制性的(至少对于 Arch Linux 来说);
    命令vmlinuz-linux initrd=initramfs-linux.img root=/dev/sda3创造魔法

  3. 我的系统是 Dell XPS 9343 笔记本电脑,我发现它存在一个错误:无法启动 EFISTUB(ArchWiki 上报告)这里
    我认为这解释了失败(首先提到的)正确程序!
    ArchWiki 页面也建议了一种解决方法,但目前我已经尝试过。


答案1

   -l | --loader NAME
              Specify a loader (defaults to \\elilo.efi)

带有 EFI-stub 的内核仍然不是一个装载机。要从 BIOS 启动,它必须是 EFI-应用。所有引导加载程序都有 .EFI 后缀。我认为可以将内核变成这样一个直接可引导的对象,但通常它是启动的引导加载程序之一(提供或不提供选择)。

但你可以使用UEFI外壳(在现代系统上)作为交互式引导加载程序。这非常适合测试。你像BIOS中的启动设备一样激活它,cdfs0:ESP,然后你就可以

fs0:> bzImage root=/dev/sda3 

几天前我刚刚编译了第一个bzImage。首先,我忘记了 CONFIG_EFI_STUB 并且 UEFI shell 将内核视为非二进制文件。第二个版本确实启动了,但没有任何 initrd=。除了 EFI_STUB=y 之外,我只是关闭了一些选项并保留默认值。

但确实大多数发行版都有这样做的内核不是拥有基本的块设备驱动程序 - 他们需要该initrd=IMAGE选项。


我使用 Uefi Shell 作为引导加载程序。这不是超级优雅,但非常简单和灵活。作为紧急选项,我认为它是完美的,因为 Uefi Shell 是内置的,而分区上的引导加载程序可以删除。


这是来自文档/efi-stub.txt

> Passing kernel parameters from the EFI shell
> --------------------------------------------
> 
> Arguments to the kernel can be passed after bzImage.efi, e.g.::
> 
>     fs0:> bzImage.efi console=ttyS0 root=/dev/sda4

我有相同的 Uefi Shell 提示符fs0:>,但我发现所有常用的发行版都有 EFI_STUB 内核,并且名称根本不重要。最常见的是“vmlinuz”(= 围绕压缩的 vmlinux 的加载程序)。

如果您保留“.efi”和“console=”选项,则留下:

fs0:> bzImage root=/dev/sda4

这是相同的最小引导命令,除了我有sda3: Uefi Shell 通过 启动 bzImage stub,内核被解压并启动,内置模块识别 SATA 磁盘。如果root=设备无效,您就会感到VFS: unable to mount恐慌。


我无法像 grub64.EFI 那样直接从 BIOS 启动 bzImage(或 vmlinuz,或...)。


UEFI - 应用程序(维基百科):

除了加载操作系统之外,UEFI 还可以运行 UEFI 应用程序,这些应用程序作为文件驻留在 EFI 系统分区上。它们可以从 UEFI 命令 shell 执行,通过固件的启动管理器,或其他 UEFI 应用程序。 UEFI 应用程序可以独立于系统制造商进行开发和安装。

UEFI 应用程序的一种是操作系统加载程序,例如 GRUB、rEFInd、Gummiboot 和 Windows Boot Manager;它将操作系统文件加载到内存中并执行它。此外,操作系统加载程序可以提供用户界面以允许选择另一个要运行的 UEFI 应用程序。 UEFI shell 等实用程序也是 UEFI 应用程序

这证实了我的观点,即 UEFI Shell 位于固件引导加载程序和内核之间。


Gentoo也有类似的例子;他们坚持用 .EFI 后缀命名内核。

如果由于某种原因需要 initramfs,它可以嵌入到内核中或用作单独的文件。

...

然而,一些 UEFI 实现好像不支持传递参数从 NVRAM 到 EFI 存根内核。

答案2

似乎某些具有旧 UEFI 固件的旧机器不会将命令行参数传递给 EFI 二进制文件(例如启用 EFISTUB 的 Linux 内核)。这使得无法在启动时向内核传递重要参数,例如root=和。initrd=

我使用了完全相同的过程直接从 UEFI 启动内核(具体来说,是在https://wiki.debian.org/EFIStub,但我实际上是在两台不同的机器上的 Ubuntu 上进行的。在我用了三年的华擎主板上,它运行得非常完美。在我用了 11 年的戴尔笔记本电脑上,它只是忽略内核命令行参数。

因此,如果您的固件不支持命令行参数,您可能会运气不好。我将继续尝试,如果我找到解决方法,我将发布后续内容。

相关内容