我的 Windows 10 笔记本电脑上有 Hyper-V,第一代 VM 运行 RHEL 7.9。我正在尝试使用 UEFI 引导更新它以在第 2 代 VM 上运行。
作为迁移到第 2 代 VM 的一部分,我需要将 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/sda1
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)
您需要了解,使用 UEFI,不再有“引导块”之类的东西:UEFI 固件可以理解文件系统和加载文件。
*.efi
引导文件需要位于 UEFI 固件(或管理程序)能够理解的文件系统中。UEFI规范只要求固件必须理解FAT32;如果需要,可以添加其他文件系统类型。但是 RHEL 7.x 的默认文件系统类型是 XFS,HyperV 的虚拟固件不包括 XFS 文件系统支持。
所以你应该在你的系统盘上添加一个小分区(512M可能就可以了,甚至更少可能就足够了;虽然我认为对于现代磁盘,以小于1 GB为单位的分区磁盘是微管理的),并设置它在分区表中键入,就像
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
。)目前上面的答案很好,但没有充分强调问题的根本原因。
通过阅读您的信息转储,您可能只有 linux 格式化的 /boot 分区,但这还不足以让 UEFI 机器启动。
您的磁盘与 UEFI 规定的可引导磁盘布局不匹配。
正如上面已经提到的,使用 UEFI,我们正在进入一个如何设置引导加载程序的新世界,并且要求与旧的 BIOS 方法完全不同。UEFI 使用全新的分区表格式并且现在可以理解文件系统(!)。
这是让您的磁盘被 UEFI 固件识别为 UEFI 可引导并从以下位置引导的最简单的基本要求:
EFI System Partition
,即所谓的 ESP;在像 redhat anaconda 这样的自动化流线型设置中,这通常是大小约为 512 MB 的 GPT 分区 1。\EFI\BOOT\BOOTx64.EFI
(在 64 位系统的情况下)必须存在一个特殊的 UEFI EXE,并且必须是有效的可运行引导加载程序 exeefibootmgr
用作编辑器的内容。在您的设置中,您似乎只有一个分区
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)
. even可能有一种明确的 Linux 类型/boot
。现在,UEFI 只关心 ESP,只要它可以找到它,它就会运行它可以在那里找到的任何 UEFI exe - 这个“神奇”的 exe 是以前称为“bootloader”的东西:它是一个程序,那应该加载您的实际操作系统。
鉴于“安装”引导加载程序现在就像将 exe 复制到 FAT32 格式的 ESP 一样简单,引导加载程序的安装过程对用户来说“更简单”了。因为 UEFI exe 是从 windows PE exe 派生的众所周知的格式,所以现在编写引导加载程序也容易得多。因此,从现在开始还有更多的引导加载程序可供选择。
举几个例子:
是的,您没看错,使用 EFI 存根(其中大多数是)编译的现代 linux 内核是功能齐全的 UEFI 引导加载程序。实际上它可以直接从 ESP 引导到自身,而不需要任何中间的废话。所以你可以很容易地直接从 UEFI 直接启动到 linux。
不幸的是,在我在这里提到的所有引导加载程序中,grub 可能是最糟糕的。由于这种不可否认的质量,它是市场上 95% 的 linux 发行版的首选(这种行为在 linux 生态系统中经常出现)。
这种选择的原因通常非常挑剔,这可能是由于 grub 在启动时提供的无用的内核选择菜单,以及由于发行版花费了时间来完善脚本以将出现在此菜单中的新内核安装集成到包管理器中。
所以现在,即使在你准备好 ESP 并正确格式化它并且你可以直接从它正确引导到 linux 之后,你现在有第二个大的 linux 引导问题,称为“grub 问题”。
GRUB 早于 UEFI,它解决了旧 BIOS 与 UEFI 相同的许多引导问题。现在你应该意识到 UEFI 基本上是它自己的,Windows 98 级别的操作系统,只是它是直接预装在主板上的。它也非常复杂。
同样,GRUB 是它自己的特殊 mini-OS 预安装到传统
/boot
分区中(它有自己的文件系统驱动程序,就像 UEFI 一样,它自己的 shell 像 UEFI,以及其他愚蠢的东西,就像 UEFI 一样,只有没人知道/记得如何使用和处理它们)。您可以放弃它,但是由于您希望自动内核更新与内核包更新(通过 yum/dnf)一起工作,您现在需要修复它。因此,在您的情况下,您的引导链必须看起来像 UEFI(OS)->GRUB(OS)->LINUX(OS)。
因此,在您修复了上面列出的 UEFI 前提条件之后,您现在必须修复您的 GRUB 前提条件。GRUB 必须正确安装到 ESP 中,以便 UEFI 可以引导到其中,然后必须将其配置为引导您的 Linux。
现在,在你的 in-linux
/
树中安装 ESP 以使其工作是高度依赖于发行版的,所以这超出了我的范围,但我想/boot/efi
这是 redhat 系列的默认设置。所以,你需要
rm -rf
那个目录/boot
是空的,然后用 vfat 驱动程序将你格式化的空 ESP 挂载到那里(/boot/efi
)。完成后,您需要 chroot 进入安装,并强制本地 grub 将其在 UEFI 模式下的安装重新生成为/boot/efi
又名“/dev/sda/esp”。这是高度特定于发行版的,也取决于 grub 版本,可以是以下之间的任何内容:
至
从 chroot 内部。
如果您做得对,您现在应该会看到 GRUB 安装文件出现在最初为空的 ESP 分区中,并且新的 EFIVAR 应该/可能会出现指向类似
\EFI\redhat\shimx64.efi
intoESP
(通过 UUID)的东西。我建议在 grub 重新生成/重新安装之前删除所有过时的引导 efivars,
efbootmgr
以便您可以验证添加的条目。完成后,您现在应该会在重新启动后看到 grub 内核启动菜单。
与该问题相关的建议晚安阅读:
https://en.wikipedia.org/wiki/GUID_Partition_Table
https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface
http://www.rodsbooks.com/efi-bootloaders/
Documenting exactly what I had to do, for future visitors. Without the details provided in the other answers, this would have been far more difficult.
I was converting my Hyper-V machine from "Generation 1" to "Generation 2". This big difference there is the boot mechanism goes from the tested, tried, and true method of having the BIOS load the boot sector directly into memory, and executing it, to having the UEFI firmware looking for an "ESP" or "BOOT" partition, and loading an EFI boot file from there.
UEFI boot requires a partition to be marked as bootable by the UEFI firmware, and chances are the UEFI firmware doesn't understand anything but a FAT-formatted partition. Since Hyper-V is a Microsoft product, it likely understands how to boot from NTFS formatted partitions as well.
Red Hat Enterprise Linux 7 uses the XFS filesystem by default, which cannot be read by the the UEFI firmware.
So, steps I took:
Take a backup of my
/boot
file system. I have a secondary VHDX disk attached to my VM, mounted as/data
, so I used that as the location for my backup:Use
lsblk
to determine which device contains the/boot
filesystem:Use
parted
to drop the existing/boot
partition:In the above, I've started
parted
and executed theprint
command, which shows the list of partitions on/dev/sda
, so the partition I want to drop is/dev/sda1
- the size differences betweenlsblk
andparted
is due toparted
using 1GB = 1,000,000,000 bytes, whereaslsblk
uses 1GB = 1,073,741,824 bytes.This command, run inside the
parted
shell, actually deletes the partition:Make the new partition, and assign it the
efi
orboot
flag, to signal the UEFI firmware that this is the partition we'll attempt to boot from:Set the
boot
flag:As you can see, the
boot
flag is now set for partition number 1.Next, we'll format the new partition:
We need to ensure that
/etc/fstab
shows the correct items, otherwise we'll get some nasty surprises when Linux boots along the lines ofTimed out waiting for device
andDependency failed for /boot
. We need the partition UUID for the boot device, vialsblk
:In my case, the partition UUID is
93be2242-cfa5-4759-86a8-e563092da88d
- yours will be different, since these identifiers are universally unique by design.接下来,我们确保
/etc/fstab
文件包含/boot
设备的正确分区 UUID:在上面的示例中,我们看到
/boot
设备是/dev/sda1
,我需要确保该行拥有PARTUUID=93be2242-cfa5-4759-86a8-e563092da88d
而不是/dev/sda1
在系统启动之前。我使用vi进行更改,但请随意使用不会让您发疯的编辑器。更改后,内容如下所示:使用以下命令从旧
/boot
分区恢复文件cp
:更新 grub 配置:
安装必要的 UEFI 引导组件:
用于
efibootmgr
创建指向 .efi 引导文件的条目:然后看看
efibootmgr
UEFI 启动选项列表:此时我能够重新启动,并且 Linux 正确启动。