查找 GRUB 的确切位置 / 复制磁盘映像后 GRUB 不起作用

查找 GRUB 的确切位置 / 复制磁盘映像后 GRUB 不起作用

我使用 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 个块。

相关内容