似乎我--boot-directory
在使用时总是必须将文件安装到 a grub-install
。
/boot
如果我的分区上已经有现有的 grub 文件怎么办?难道我不应该只需要安装 grub 的 MBR 部分并将其指向我现有的分区之一吗/boot/grub
?我找不到这样的选择。
我已将 GPT 降级为 MBR 并删除了 BIOS 引导分区,这意味着我需要将 Grub 重新安装到 MBR(如果我没有误解任何内容的话)。如果不这样做,我会留下一个 grub 救援提示,在执行 .txt 文件时甚至无法列出我的分区ls
。我意识到将 grub 重新安装到 MBR 后,我的菜单项可能仍然无法工作,因为它们引用了诸如 之类的分区hd0,gpt5
,但是有一个可用的提示就足够了,它可以让我更轻松地确认我对 grub 的理解。
每当我想安装 grub 时是否都必须写入 a --boot-directory
,即使目录已经存在?
答案1
当 GRUB 从 MBR 引导时,它在引导过程开始时需要执行的传统 BIOS 兼容性步骤的数量意味着 MBR 中实际的代码只能加载一个磁盘块其 LBA 号在安装时已修补到 MBR 代码中。该块通常是第一个块GRUB 核心映像。它包含加载更多块的代码,以及定义 GRUB 核心映像其余部分所在位置的块编号列表。
在 MBR 分区磁盘上,MBR 和第一个分区的开头之间通常有未使用的空间。对于 MS-DOS,最初的约定是在下一个磁盘磁道的开始处启动第一个分区,这通常意味着在第一个分区之前至少有 63 个磁盘块,包括 MBR。在现代系统上,第一个 MBR 分区现在更常见地放置在距磁盘开头正好 1MiB 处,即块 #2048 处,以优化可能内部使用块的磁盘、SSD 和 SAN 存储系统的数据对齐大小大于 512 字节。
因此,在 MBR 分区的磁盘上,磁盘的开头通常是这样排列的:
- 块#0:MBR
- block #1:GRUB 核心映像的第一个块,包含块列表
- 块 #2...#n:GRUB 核心映像的其余部分
- 块#2048:第一个分区的开始。
请注意,GRUB 核心映像的加载完全按照预先确定的块号进行:在 GRUB 核心映像完全加载和提取之前,GRUB 将不知道分区表或任何类型的文件系统。
在 GPT 分区磁盘上,紧接在块 #0 之后的块被 GPT 分区表占用,因此 GRUB 核心映像被嵌入到“BIOS 引导分区”中。这只是意味着嵌入到 MBR 中的块编号不会是 1,而是 BIOS 引导分区的第一个块的编号,并且属于核心映像的其余块也将同样移位。因此,在带有 BIOS 样式 GRUB 的 GPT 分区磁盘上,物理布局将如下所示,假设 BIOS 引导分区是磁盘上的第一个分区:
- 块 #0:GPT 保护 MBR,嵌入 GRUB MBR 代码
- 块#1...#(x-1):实际的 GPT 分区表
- block #x:BIOS 引导分区的第一个块,包含 GRUB 核心映像的第一个块以及块列表
- 块 #(x+1)...#(x+n):GRUB 核心映像的其余部分
事实上,您仍然可以进入 GRUB 救援模式,这表明虽然您说您删除了 BIOS 引导分区,但您还没有删除覆盖其块;尽管 BIOS 启动分区占用的空间现在可能是分区之间未分配的空间,或另一个已调整大小的分区中未使用的空间,但它仍然有旧内容,GRUB 仍然可以加载这些块并找到其核心映像。但现在没有什么特别的东西可以保护这些块不被覆盖:一旦发生这种情况,无论出于何种原因,GRUB 核心映像将被破坏,GRUB 甚至无法进入救援模式。
GRUB 核心映像的内容
GRUB 核心映像包含以下几项内容:
- GRUB 内核:从技术上来说,这是进入 GRUB 救援模式所需的唯一部分。
- 嵌入的初始 GRUB 根路径,以指示其中的哪个磁盘、分区和目录保存 GRUB 配置文件和 GRUB 模块目录。在Linux中,当Linux系统正常运行时,这些通常分别显示为
/boot/grub/grub.cfg
和。/boot/grub/i386-pc
- 一组嵌入式 GRUB 模块,至少包含用于读取和理解分区表以及初始 GRUB 根路径引用的分区上使用的文件系统类型的代码。由于核心映像可能需要容纳少于 63 个磁盘块,因此在 MBR 系统上这组模块通常保持尽可能少。
- 可选地,一个嵌入式 GRUB 配置文件使用一个或多个 GRUB 命令
- 可选的嵌入式磁盘映像,类似于
memdisk
SYSLINUX 引导加载程序系列工具使用的映像 - (可选)用于签署其他 GRUB 模块和操作系统内核的 GPG 公钥以确保安全(并满足 UEFI 版本 GRUB 的安全启动接受要求)
所有这些都经过 LZMA 压缩以最小化其大小,因此无法轻松读取或手动修改。
由于您现在进入救援模式并且无法列出分区,这表明 GRUB 核心映像包含 GPT ( part_gpt.mod
) 的分区模块,但不包含 MBR ( part_msdos.mod
) 的分区模块。如果没有 MBR 分区模块,它就无法访问包含/boot/grub/i386-pc
目录的分区,即使 GRUB 核心映像包含适用于它的文件系统驱动程序模块......因此 GRUB 无法加载normal.mod
使您可以超越救援模式的程序。
现在需要做什么
- GRUB 核心映像可能需要重写到安全位置,可能是 MBR 和第一个分区开头之间的空间,该空间之前被 GPT 分区表的结构占用。由于 BIOS 引导分区已被删除,当前位置并不安全:它可能会被重新分配到另一个分区,并在将来在没有警告的情况下被覆盖。
- 重写GRUB核心镜像时,需要将其中嵌入的GPT分区模块替换为MBR分区模块。由于所有组件都应该以未压缩的形式存在(在
/usr/lib/grub/i386-pc
或类似的目录中),因此最简单的方法就是获取所有适当的未压缩组件,从中构建一个新的核心映像并对其进行压缩。解压旧的并修改它根本不值得这么麻烦:当重用最初从头开始安装 GRUB 时使用的代码就可以正常工作时,为什么还要编写另一段代码呢? - 由于 GRUB 核心映像的位置很可能会发生变化,因此 MBR 代码也需要重写。
- 该
grub-install
命令需要以某种方式确保normal.mod
位于的 GRUB 模块和其他 GRUB 模块/boot/grub/i386-pc
与新 GRUB 核心映像的版本相同。当然,它可以将现有文件与用于重建核心映像的文件集进行比较,但是同样......当简单地使用/boot/grub/i386-pc
已经存在的 GRUB 安装例程覆盖现有内容时,为什么还要为另一种特殊情况编写和调试代码工作得很好吗?
所有 GRUB 组件的未压缩总大小i386-pc
绝对小于 4 MiB。没什么。如果它已经存在,那么尝试避免重写根本不值得,除非您使用的是特殊的东西,例如旧的第一代 PATA SSD,其可用的写入周期数量非常有限。
原生 UEFI 如何做到这一点?
由于 UEFI 固件标准包括 FAT32 文件系统支持,因此 GRUB 引导加载程序的本机 UEFI 版本可以打包为grubx64.efi
包含所有必要模块的单个文件,包括 normal.mod
如果你希望。它作为常规文件加载:根本不需要摆弄固定磁盘位置中的块号或嵌入代码。