我使用 VirtualBox 准备了一个 Ubuntu 服务器映像。为了将映像传输到服务器的 SSD,我首先dd
编辑了 MBR(512 字节),然后编辑了 LVM 分区(包含根分区的 PV 缩小到 3GB)。由于缺少 GRUB 的某些部分,服务器无法启动。grub 救援提示出现了。
正如我从 GRUB 的文档中了解到的那样,这是有道理的,因为它的部分内容(通常)存储在 MBR 和第一个分区之间的磁盘空间中。
但我怎样才能知道具体位置呢?
我知道我可以复制第一个分区前面的整个空间,但我很好奇是否有一些命令可以显示 GRUB 各个部分的确切位置。
澄清:没有单独的启动分区。只有包含根分区(带有 /boot 文件夹)的 LVM 物理卷。还可以通过chroot
进入复制的映像并执行 来解决启动问题grub-install
。
答案1
在 GRUB2 创建的 MBR 中,从偏移量 0x5c 开始,有一个小端序的 64 位值,表示下一个要加载的磁盘块的编号。这通常是块 0x00000000 00000001,即 MBR 之后的下一个块。
(按照古老的 DOS 惯例,第一个分区将从 1 号柱面的开头开始,因此 MBR 之后的 0 号柱面通常会有许多未使用的块。在现代系统中,第一个分区通常从 2048 号块开始对齐,即从磁盘开头开始正好 1 MB。这使得在第一个分区开始之前有更多的空闲块。)
第二个块包含更多 GRUB 内核代码,以及一个阻止列表,该列表指定要从中加载 GRUB 核心映像其余部分的块。阻止列表位于此块的最末尾。每个阻止列表条目长度为 12 个字节,结构如下:
struct __attribute__ ((packed)) g2_blist_entry {
uint64_t start_lba; # the LBA block number of the first block covered by this entry
uint16_t num_blocks; # number of blocks to read
uint16_t startseg; # segment address in memory to write them to
};
通常,块列表只有一个条目,涵盖要读取的所有剩余块,从块 0x00000000 00000002 开始。
GRUB 核心映像的长度根据 GRUB 版本和附加到 GRUB 内核的模块数量而有所不同。
例如,在我使用传统 MBR 启动的 Debian 9 系统上,GRUB 包含 MBR 后总共 103 个块。在 RHEL 7.4 VM 上,MBR 后的总长度为 107 个块。