我自己终于找到了解决方案。由于VBoxManage internalcommands createrawvmdk -filename sdb2.vmdk -rawdisk /dev/sdb -partitions 2 命令基于当前 磁盘结构生成两个有效文件,唯一需要的更改是从旧的sdb2-pt.vmdk 文件恢复Windows 引导加载程序,这是一个相当简单的过程。如果你只想学习恢复步骤,可以跳过下面的理论部分。
有关 VMDK 文件格式的一些背景信息
VMWare 磁盘格式 (VMDK) 由两个文件组成 - 一个描述符文件(原始问题中的sdb2.vmdk)和一个扩展文件(sdb2-pt.vmdk)。它们的内部结构在 VMWare 的specification 中得到了很好的定义。我将总结最重要的部分:
描述符文件 (sdb2.vmdk) 包含一个注释为 # Extent description 的部分,它可能看起来像这样:
# Extent description
RW 63 FLAT "sdb2-pt.vmdk" 0
RW 41943040 ZERO
RW 83886080 FLAT "/dev/sdb" 58722304
RW 2 FLAT "sdb2-pt.vmdk" 63
RW 1191843568 ZERO
一个范围描述(上面的一行)具有以下结构:
Access Size in sectors Type of extent Filename (Offset)
offset 参数(仅为FLAT 类型extents 指定)指定文件Filename 中给定extent 的偏移量(以扇区为单位)。请注意,文件 sdb2-pt.vmdk 包含两个区段,前 63 个扇区长,第二个只有 2 个扇区长。
FLAT 范围文件 sdb2-pt.vmdk 是一个原始数据二进制文件,与您将获得的文件相同,例如在类 Unix 系统上使用 dd 命令。由于在我的情况下扇区大小为512 bytes(我不知道这是否是一般规则),sdb2-pt.vmdk 文件(基于上述范围描述中描述的新磁盘分区)为(63+2)*512 bytes 长。
现在到第二个范围(只有 2 个扇区大小的范围)。这是扩大 Windows 分区后在我的新分区表中出现的填充范围(描述表中的第三个范围)。由于我之前的分区表不包含任何此类填充,因此旧的 sdb2-pt.vmdk 文件仅包含前 63 个扇区长范围,因此比 VBoxManage internalcommands createrawvmdk -filename sdb2.vmdk -rawdisk /dev/sdb -partitions 2 命令生成的新分区小 1024 字节。这显然导致旧的extent文件和新的extent文件不兼容。
恢复过程
请注意,以下步骤仅适用于旧的 MBR 磁盘结构!
您肯定希望保留新的分区结构并将分区表中所做的任何更改传播到 VMDK 文件。继续执行以下步骤:
- 备份旧的描述文件 (
sdb2.vmdk) 和扩展文件 (sdb2-pt.vmdk)。在以下步骤中,您只需要第二个步骤,但您永远不知道还会发生什么。
-
生成新的描述符和扩展文件发出命令:
VBoxManage internalcommands createrawvmdk -filename sdb2.vmdk -rawdisk /dev/sdb -partitions 2
-
现在,新描述文件 (sdb2.vmdk) 中的第一个扩展区条目应如下所示:
RW ## FLAT "sdb2-pt.vmdk" 0
知道您要保留新分区表(以及以下所有内容)并仅恢复存储在备份扩展文件(旧 sdb2-pt.vmdk)中的 Windows 引导加载程序,您必须复制第一个 @987654347 @(引导加载程序)从旧的扩展文件到新的。这可以使用十六进制编辑器(复制从地址 0x0 到 0x1B8 唯一的所有值)或在类 Unix 系统上使用以下命令完成:
dd if=old-sdb2-pt.vmdk of=sdb2-pt.vmdk bs=1 count=440
中提琴。