AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 708160
Accepted
Hannah Vernon
Hannah Vernon
Asked: 2022-07-01 08:56:53 +0800 CST2022-07-01 08:56:53 +0800 CST 2022-07-01 08:56:53 +0800 CST

UEFI 引导从不从 /dev/sda 运行,但从救援 DVD 运行

  • 772

我的 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/sda1chroot /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)

rhel uefi
  • 3 3 个回答
  • 203 Views

3 个回答

  • Voted
  1. telcoM
    2022-07-07T12:22:29+08:002022-07-07T12:22:29+08:00

    您需要了解,使用 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。)

    • 2
  2. Best Answer
    etosan
    2022-07-07T16:43:08+08:002022-07-07T16:43:08+08:00

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

    通过阅读您的信息转储,您可能只有 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(在 64 位系统的情况下)必须存在一个特殊的 UEFI EXE,并且必须是有效的可运行引导加载程序 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). even可能有一种明确的 Linux 类型/boot。

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

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

    举几个例子:

    • 重新查找
    • 系统引导
    • 口香糖
    • 系统Linux
    • linux(!!!)
    • 和...蛴螬

    是的,您没看错,使用 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 版本,可以是以下之间的任何内容:

    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)的东西。

    我建议在 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/

    • 1
  3. Hannah Vernon
    2022-07-08T09:50:15+08:002022-07-08T09:50:15+08:00

    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:

    1. 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:

      mkdir /data/old_boot
      cp --archive /boot /data/old_boot
      
    2. Use lsblk to determine which device contains the /boot filesystem:

      > 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. Use parted to drop the existing /boot partition:

      > 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
      

      In the above, I've started parted and executed the print command, which shows the list of partitions on /dev/sda, so the partition I want to drop is /dev/sda1 - the size differences between lsblk and parted is due to parted using 1GB = 1,000,000,000 bytes, whereas lsblk uses 1GB = 1,073,741,824 bytes.

      This command, run inside the parted shell, actually deletes the partition:

      rm 1
      
    4. Make the new partition, and assign it the efi or boot flag, to signal the UEFI firmware that this is the partition we'll attempt to boot from:

      > 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    
      

      Set the boot flag:

      (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
      

      As you can see, the boot flag is now set for partition number 1.

    5. Next, we'll format the new partition:

      > mkfs.fat -F 32 /dev/sda1
      
    6. We need to ensure that /etc/fstab shows the correct items, otherwise we'll get some nasty surprises when Linux boots along the lines of Timed out waiting for device and Dependency failed for /boot. We need the partition UUID for the boot device, via 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
      

      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:

      > 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在系统启动之前。我使用vi进行更改,但请随意使用不会让您发疯的编辑器。更改后,内容如下所示:

      #
      # /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 正确启动。

    • 1

相关问题

  • 为什么 Linux 会杀死我的进程?

  • linux redhat 7 ( 或 centos 7 ) + firewalld 屏蔽防火墙

  • systemctl 命令在 RHEL 6 中不起作用

  • 如何在 RHEL 7 上离线安装 docker?

  • 在 Gnome3 中禁用窗口的自动最大化

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve