UEFI 引导永远不会从 /dev/sda 运行,但可以从救援 DVD 运行

UEFI 引导永远不会从 /dev/sda 运行,但可以从救援 DVD 运行

我的 Windows 10 笔记本电脑上安装了 Hyper-V,其中第一代虚拟机运行 RHEL 7.9。我正在尝试使用 UEFI 引导将其更新为在第 2 代 VM 上运行。

作为迁移到第 2 代虚拟机的一部分,我需要将 UEFI 启动代码安装到 /boot 分区中。

我安装了以下软件包,我认为这是我所需要的:

grub2-efi-x64.x86_64         (1:2.02-0.07.el7_9.9)
shim-x64.x86_64              (15-11.el7)
grub2-efi-x64-modules.noarch (1:2.02-0.07.el7_9.9)
shim-unsigned-x64.x86_64     (15-9.el7)

efibootmgr -v显示以下内容:

在此输入图像描述

正如您所看到的,我通过 尝试了几种不同的配置efibootmgr,但似乎都不起作用。

VM 的启动设置:

在此输入图像描述

因此从理论上讲,虚拟机应该从 启动\EFI\redhat\shimx64.efi,据我了解,它应该是该/boot/efi/EFI/redhat/shimx64.efi文件,该文件确实存在:

在此输入图像描述

df -h显示通过救援 DVD 启动时/boot安装在/dev/sda1I 之后。chroot /mnt/sysimage

正如您从 /boot 分区的屏幕截图中看到的,在我看来,有一个内核的有效 initramfs 文件(不过我认为我们还没有走到这一步):

在此输入图像描述

我还尝试过重置 grubs 配置:

grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg

grub.cfg文件包含从内核版本的角度来看看起来正确的菜单条目,但是我什至从未看到过 grub 菜单,所以我再次认为我们还没有走到这一步。对我来说听起来像是 UEFI 引导加载程序问题,但我不知道如何解决该问题。

当我取出 DVD 并启动计算机时,Hyper-V 会向下移动启动顺序,直到到达网络适配器。

在此输入图像描述

最终,Hyper-V 显示了这一点:

在此输入图像描述

我究竟做错了什么?

如果我从救援 DVD 启动,然后在 grub 菜单中进入命令行(通过c)并运行configfile (hd0,gpt1)/efi/EFI/redhat/grub.cfg,我就能够启动已安装的 Linux 操作系统。

mount | grep -i "boot"从启动的操作系统显示:

/dev/sda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

答案1

您需要了解,使用 UEFI,不再有“引导块”之类的东西:UEFI固件可以理解文件系统加载文件

引导*.efi文件需要位于 UEFI 固件(或虚拟机管理程序)可以理解的文件系统中。 UEFI规范仅要求固件必须了解FAT32;其他文件系统类型可能如果需要的话可以添加。

但RHEL 7.x的默认文件系统类型是XFS,并且HyperV的虚拟固件不包括XFS文件系统支持。

所以你应该在你的系统磁盘上添加一个小分区(512M可能就足够了,甚至小于这个值也可能足够了;尽管我认为对于现代磁盘,以小于1GB的单位对磁盘进行分区是微观管理的),并设置它在分区表中键入,就好像0xef您的系统磁盘是 MBR 分区一样,或者如果您使用 GPT 分区,只需使用您选择的分区工具将分区类型设置为 ESP(= EFI 系统分区)即可。然后mkfs.fat在分区上运行,将其挂载到可以将当前内容移动/boot/efi到新分区的位置,并将新分区挂载到/boot/efi.

之后,您可以使用该efibootmgr命令清除旧的尝试,然后grub2-install再次运行以自动构建正确的 UEFI 引导变量条目。或者efibootmgr,如果您愿意,您也可以自己做。请注意,显示的启动项上的 UUID 字符串efibootmgr -v应与安装到 的 FAT32 分区的 PARTUUID 匹配/boot/efi。 (您可以使用 进行检查lsblk -o +PARTUUID。)

答案2

目前上面的答案非常好,但没有充分强调问题的根本原因。

从您的信息转储中读取,您可能只有 linux 格式的 /boot 分区,但这不足以启动 UEFI 机器。

您的磁盘与 UEFI 规定的可启动磁盘布局不匹配。

正如上面已经提到的,通过 UEFI,我们正在进入一个如何设置引导加载程序的新世界,并且要求与旧的 BIOS 方法完全不同。 UEFI 使用全新的分区表格式并且现在可以理解文件系统(!)。

这是 UEFI 固件将您的磁盘识别为 UEFI 可引导并从以下位置引导的最简单的基本要求:

  1. 磁盘必须使用 GPT 分区方案进行分区
  2. 在磁盘的某处,GPT分区表中,一定有一且恰好一存在分区,必须标记为EFI System Partition,即所谓 ESP;在像 redhat anaconda 这样的自动化简化设置中,这通常是大小约为 512 MB 的 GPT 分区 1。
  3. 该分区必须格式化为文件系统,其驱动程序存在于 UEFI 固件中(即已“安装”到主板芯片内部的 UEFI 安装中 - 即使在 VM 模拟的 UEFI 芯片中也是如此)
  4. 在任何 UEFI 安装中,唯一始终强制安装(根据 UEFI 规范)的 UEFI 文件系统驱动程序是 FAT32,即,这是对 ESP 进行格式化的最安全(/唯一)选择
  5. 在给定的 ESP 分区上,\EFI\BOOT\BOOTx64.EFI必须存在一个特殊的 UEFI EXE(如果是 64 位系统)并且必须是有效的可运行引导加载程序 exe
  6. 如果找不到此文件,则会检查其他几个路径,但 EFIVAR 可以使用自定义引导加载程序 exe 路径覆盖所有这些路径;这就是efibootmgr用作编辑器的用途。

在您的设置中,似乎只有一个sda1带有xfs文件系统的分区 挂载到 中/boot

当然,你的UEFI没有安装XFS驱动程序,因此无法读取该分区(即使有XFS驱动程序,除非该分区也是ESP类型,否则仍然无法从该分区启动)。

这是我最好的猜测,因为你忘记添加fdisk -l.

在现代 UEFI 中,linux 不安装 ESP /boot,而是安装在 /boot 内更深的位置,如 /boot/efi!

修复相对简单:您需要确保您的分区表是GPT类型(根据您的grub行它已经是)并添加新分区ESP type,然后将其格式化为FAT32,并确保您的分区/boot表不被标记为ESP./boot应标记为普通Linux filesystem类型。

在 GPT 方案中,分区类型是 UUID(但不要将它们(分区类型 UUID)与分区标识 UUID 混淆!),因此 ESP 是EFI System (C12A7328-F81F-11D2-BA4B-00A0C93EC93B)exaclty 类型,而Linux filesystem是多种类型之一:例如Linux root (x86-64) (4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709).甚至可能有一种明确的 Linux 类型/boot

现在,UEFI 只关心 ESP,只要它能找到它,它就会运行它能在那里找到的任何 UEFI exe - 这个“神奇”的 exe 就是以前被称为“bootloader”的东西:它是一个程序,这应该加载您的实际操作系统。

鉴于“安装”引导加载程序现在就像将 exe 复制到 FAT32 格式的 ESP 上一样简单,引导加载程序的安装过程对用户来说变得“更简单”。由于 UEFI exe 是从 Windows PE exe 派生的众所周知的格式,因此现在编写引导加载程序也变得更加容易。因此,现在还有更多的引导加载程序可供选择。

举几个例子:

  • 重新寻找
  • systemd-boot
  • 橡胶靴
  • 系统Linux
  • linux(!!!)
  • 和...grub

是的,你没看错,用 EFI 存根(大多数都是)编译的现代 Linux 内核是功能齐全的 UEFI 引导加载程序。实际上它可以直接从 ESP 启动,不需要任何中间的垃圾。因此您已经可以轻松地从 UEFI 直接启动到 Linux。

不幸的是,在我在这里提到的所有引导加载程序中,grub 可能是最糟糕的。由于这种无可否认的品质,去选择在市场上 95% 的 Linux 发行版上(这种行为在 Linux 生态系统中很常见)。

这种选择的原因通常非常挑剔,这可能是由于 grub 提供的启动时无用的内核选择菜单,以及由于发行版花费了时间来完善其脚本以将出现在该菜单中的新内核安装集成到包管理器中。

所以现在,即使你准备好 ESP 并正确格式化它,并且你可以从它正确地直接启动到 Linux,你现在仍然遇到第二个大的 Linux 启动问题,称为“grub 问题”。

GRUB 早于 UEFI,它解决了旧 BIOS 的许多启动问题,其方式与 UEFI 相同。现在您应该意识到 UEFI 基本上是它自己的 Windows 98 级别操作系统,只是它直接预装到主板中。它也非常复杂。

同样,GRUB 是它自己的特殊迷你操作系统,预安装到传统/boot分区中(它有自己的文件系统驱动程序,就像 UEFI 一样,它有自己的 shell,就像 UEFI 一样,还有其他愚蠢的东西,就像 UEFI 一样,只有没有人知道/记得如何使用和处理它们)。您可以放弃它,但是当您希望自动内核更新与内核包更新(通过 yum/dnf)结合使用时,您现在需要修复它。

因此,在您的情况下,您的引导链必须类似于 UEFI(OS)->GRUB(OS)->LINUX(OS)。

因此,在修复上面列出的 UEFI 先决条件后,您现在必须修复 GRUB 先决条件。 GRUB 必须正确安装到 ESP 中,以便 UEFI 可以引导到 ESP,然后必须将其配置为引导 Linux。

现在,在你的 Linux/树中将 ESP 安装到哪里才能工作,高度依赖于发行版,所以这超出了我的范围,但我想这/boot/efi是 Redhat 系列的默认设置。

因此,您需要rm -rf将该目录/boot设置为空,然后使用 vfat 驱动程序将您格式化的空 ESP 挂载到该目录 ( /boot/efi)。完成此操作后,您需要 chroot 进入安装,并强制本地 grub 在 UEFI 模式下将其安装重新生成为/boot/efi“/dev/sda/esp”。

这是高度特定于发行版的,并且还取决于 grub 版本,并且可以是以下之间的任何值:

grub-install /dev/sdX
update-grub

grub-install --target=x86_64-efi /dev/sdbX
grub-install --recheck /dev/sdX

从 chroot 内部。

如果你做对了,你现在应该看到 GRUB 安装文件出现在原来空的 ESP 分区中,并且新的 EFIVAR 应该/可能出现,指向类似\EFI\redhat\shimx64.efiinto 的东西ESP(通过 UUID)。

我建议在efbootmgrgrub 重新生成/重新安装之前删除所有过时的引导 efivars,以便您可以验证添加的条目。

完成后,重新启动后您应该会看到 grub 内核启动菜单。

与该问题相关的建议晚安读物:

https://en.wikipedia.org/wiki/GUID_Partition_Table

https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface

http://www.rodsbooks.com/efi-bootloaders/

答案3

为未来的访客准确记录我必须做的事情。如果没有其他答案中提供的详细信息,这将会困难得多。

我正在将我的 Hyper-V 计算机从“第一代”转换为“第二代”。最大的区别在于引导机制从让 BIOS 将引导扇区直接加载到内存并执行它的经过测试、尝试过的真实方法,到让 UEFI 固件寻找“ESP”或“BOOT”分区,并从那里加载 EFI 启动文件。

UEFI 启动要求 UEFI 固件将分区标记为可启动,并且 UEFI 固件可能除了 FAT 格式的分区之外什么都不识别。由于 Hyper-V 是 Microsoft 产品,因此它可能也了解如何从 NTFS 格式的分区启动。

Red Hat Enterprise Linux 7 默认使用 XFS 文件系统,UEFI 固件无法读取该文件系统。

所以,我采取的步骤:

  1. 备份我的/boot文件系统。我的虚拟机上附加了一个辅助 VHDX 磁盘,安装为/data,因此我将其用作备份位置:

    mkdir /data/old_boot
    cp --archive /boot /data/old_boot
    
  2. 用于lsblk确定哪个设备包含/boot文件系统:

    > lsblk
    
    NAME          MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
    sda             8:0    0   129G  0 disk
    ├─sda1          8:1    0   499M  0 part /boot
    └─sda2          8:2    0 126.5G  0 part
      ├─rhel-root 253:0    0    50G  0 lvm  /
      ├─rhel-swap 253:1    0   7.9G  0 lvm  [SWAP]
      └─rhel-home 253:2    0  68.6G  0 lvm  /home
    sdb             8:16   0   512G  0 disk /data
    
  3. 用于parted删除现有/boot分区:

    > parted /dev/sda
    print
    Model: Msft Virtual Disk (scsi)
    Disk /dev/sda: 139GB
    Sector size (logical/physical): 512B/4096B
    Partition Table: gpt
    Disk Flags:
    
    Number  Start   End    Size   File system  Name       Flags
     1      1049kB  524MB  523MB  xfs          primary    
     2      525MB   136GB  136GB               Linux LVM  lvm
    

    在上面,我启动parted并执行了print命令,该命令显示了 上的分区列表/dev/sda,因此我要删除的分区是-和/dev/sda1之间的大小差异是由于使用 1GB = 1,000,000,000 字节,而使用 1GB = 1,073,741,824 字节。lsblkpartedpartedlsblk

    此命令在 shell 内运行parted,实际上删除了分区:

    rm 1
    
  4. 创建新分区,并为其分配efiboot标志,以向 UEFI 固件发出信号,表明这是我们将尝试从中启动的分区:

    > parted
    (parted) mkpart primary fat32 1 524
    (parted) print
    Model: Msft Virtual Disk (scsi)
    Disk /dev/sda: 139GB
    Sector size (logical/physical): 512B/4096B
    Partition Table: gpt
    Disk Flags:
    
    Number  Start   End    Size   File system  Name       Flags
     1      1049kB  524MB  523MB  fat32        primary    
     2      525MB   136GB  136GB               Linux LVM  lvm    
    

    设置boot标志:

    (parted) set 1 boot on
    (parted) print
    Model: Msft Virtual Disk (scsi)
    Disk /dev/sda: 139GB
    Sector size (logical/physical): 512B/4096B
    Partition Table: gpt
    Disk Flags:
    
    Number  Start   End    Size   File system  Name       Flags
     1      1049kB  524MB  523MB  fat32        primary    boot
     2      525MB   136GB  136GB               Linux LVM  lvm
    

    如您所见,boot现在为分区号 1 设置了标志。

  5. 接下来,我们将格式化新分区:

    > mkfs.fat -F 32 /dev/sda1
    
  6. 我们需要确保/etc/fstab显示正确的项目,否则当 Linux 按照Timed out waiting for device和 的方式启动时,我们会遇到一些令人讨厌的意外Dependency failed for /boot。我们需要引导设备的分区 UUID,通过lsblk

    > lsblk -o +PARTUUID
    NAME          MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT   PARTUUID
    sda             8:0    0   129G  0 disk
    ├─sda1          8:1    0   499M  0 part /boot        93be2242-cfa5-4759-86a8-e563092da88d
    └─sda2          8:2    0 126.5G  0 part              484a1ac4-eba0-49b4-9910-b6471462d8b0
      ├─rhel-root 253:0    0    50G  0 lvm  /
      ├─rhel-swap 253:1    0   7.9G  0 lvm  [SWAP]
      └─rhel-home 253:2    0  68.6G  0 lvm  /home
    

    就我而言,分区 UUID 是93be2242-cfa5-4759-86a8-e563092da88d- 你的将要是不同的,因为这些标识符在设计上是普遍唯一的。

    接下来,我们确保该/etc/fstab文件包含设备的正确分区 UUID /boot

    > cat /etc/fstab
    #
    # /etc/fstab
    # Created by anaconda on Mon Jan 16 22:52:23 2017
    #
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    #
    /dev/mapper/rhel-root   /                       xfs     defaults        0 0
    /dev/sda1               /boot                   vfat    defaults        0 0
    /dev/mapper/rhel-home   /home                   xfs     defaults        0 0
    /dev/mapper/rhel-swap   swap                    swap    defaults        0 0
    

    在上面的示例中,我们看到设备/boot/dev/sda1,我需要确保该行在系统启动之前PARTUUID=93be2242-cfa5-4759-86a8-e563092da88d而不是。/dev/sda1我用了进行更改,但请随意使用不会让您发疯的编辑器。我更改后,内容如下所示:

    #
    # /etc/fstab
    # Created by anaconda on Mon Jan 16 22:52:23 2017
    #
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    #
    /dev/mapper/rhel-root   /                       xfs     defaults        0 0
    PARTUUID=93be2242-cfa5-4759-86a8-e563092da88d /boot                   vfat    defaults        0 0
    /dev/mapper/rhel-home   /home                   xfs     defaults        0 0
    /dev/mapper/rhel-swap   swap                    swap    defaults        0 0
    
  7. /boot使用以下命令从旧分区恢复文件cp

    > cp --archive /data/old_boot /boot
    
  8. 更新 grub 配置:

    > grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg
    
  9. 安装必要的 UEFI 启动组件:

    > yum reinstall grub2 grub2-efi-x64 grubby shim-x64
    
  10. 用于efibootmgr创建指向 .efi 引导文件的条目:

    > efibootmgr -c -d /dev/sda -p 1 -l '\efi\EFI\redhat\shimx64.efi' -L 'Red Hat Enterprise Linux'
    

    然后查看efibootmgrUEFI 启动选项列表:

    > efibootmgr -v
    BootCurrent: 0006
    Timeout: 0 seconds
    BootOrder: 0000
    Boot0000* Red Hat Enterprise Linux      HD(1,GPT,93be2242-cfa5-4759-86a8-e563092da88d,0x800,0xf9800)/File(\efi\EFI\redhat\shimx64.efi)
    

此时我可以重新启动,并且 Linux 可以正确启动。

相关内容