为什么 GNU Parted 将数据写入 MBR 的前 440 字节?

Wil*_*ley 7 mbr parted

我的理解是MBR是512字节。前440 个字节(根据实现的不同,给出或取几个字节包含引导加载程序/引导程序代码区域。其余字节包含有关分区表的信息。

如果我将磁盘的 MBR 清零...

# Zero out the MBR
dd if=/dev/zero of=/dev/sdX bs=1 count=512
Run Code Online (Sandbox Code Playgroud)

然后,使用fdisk将分区表写入/dev/sdX...

# Create a 2GiB partition starting at 2048 (default).
fdisk /dev/sdX

...
Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier ...
...

(fdisk) n
(fdisk) p
(fdisk) 1
(fdisk) 2048
(fdisk) +2G
(fdisk) w
Run Code Online (Sandbox Code Playgroud)

然后读回前 440 个字节......

dd if=/dev/sdX bs=1 count=440
Run Code Online (Sandbox Code Playgroud)

第一个440字节仍然全为零。fdisk没有碰它们,根据我上面发布的链接,这是有道理的。fdisk正在写入分区信息,因此它应该/不需要触及第一个440.

接下来的6字节非零。我假设这些字节是现代标准 MBR 磁盘签名的一部分。

$ dd if=/dev/sdX bs=1 count=6 skip=440 | hexdump -e '4/1 "%02x " "\n"'
9a 29 97 e7
Run Code Online (Sandbox Code Playgroud)

到目前为止,根据我对 MBR 布局方式的理解,这是有意义的。这些第一个440字节被忽略,fdisk因为它们是引导加载程序的域,并且fdisk只与分区表有关。

然而,parted这让我陷入了困境。

如果我再次将同一磁盘的 MBR 清零...

# Zero out the MBR
dd if=/dev/zero of=/dev/sdX bs=1 count=512
Run Code Online (Sandbox Code Playgroud)

然后,使用parted创建一个磁盘标签(这fdisk似乎是上面自动为我做的)...

parted /dev/sdX mklabel msdos
Run Code Online (Sandbox Code Playgroud)

然后读回第一个440字节......

$ dd if=/dev/sdX bs=1 count=440 | hexdump -e '16/1 "%02x " "\n"'
fa b8 00 10 8e d0 bc 00 b0 b8 00 00 8e d8 8e c0
fb be 00 7c bf 00 06 b9 00 02 f3 a4 ea 21 06 00
00 be be 07 38 04 75 0b 83 c6 10 81 fe fe 07 75
f3 eb 16 b4 02 b0 01 bb 00 7c b2 80 8a 74 01 8b
4c 02 cd 13 ea 00 7c 00 00 eb fe 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Run Code Online (Sandbox Code Playgroud)

有非零字节!根据我目前对 MBR 应该如何布局以及 GNU 分离应该完成什么的理解,这似乎没有意义。

GNU Parted 是一个用于创建和操作分区表的程序。

为什么parted要向第一个440字节写入数据?这些字节不是用于引导加载程序吗?分开不应该像以前那样留下这些字节吗fdisk

Wil*_*ley 3

看来我不是唯一注意到这种行为人。对于某些磁盘上有引导加载程序可能会导致问题的环境来说,这似乎尤其是一个问题。arm

问题在于,parted 本身(并且默默地)将代码放在那里,因此嵌入式系统认为存在有效的引导加载程序代码并愉快地挂起。

...和...

是否有任何选项可以分开以避免添加此代码(并且行为类似于 fdisk)?

看来这个行为parted故意的。正如邮件链接上的用户parted所询问的:

问题是parted从MBR的最开始生成以下代码:

...

这段代码的目的是什么?为什么它被放在那里?

答案似乎是:

这是通常用于引导 BIOS 系统的 MBR 引导代码。如果它在非 x86 系统上引起问题,您应该将其清零(或在分区后编写系统引导加载程序)。

似乎是mklabel为了将通用引导加载程序写入磁盘而设计的。至少,当msdos使用 的标签时。我认为这是有道理的,但是从fdisk和来看syslinux,分区管理器修改引导加载程序扇区似乎有点不寻常。

如果存在非零数据,似乎不应该parted覆盖这些扇区。

不,唯一不会写入的情况是已经存在某些内容(例如,不是 0x00)。因此,如果您可以让 SDK 首先编写它的引导加载程序,然后对其进行分区,parted 将使其保持不变。

然而,这不是看到的行为。如果我从 写入垃圾/dev/urandom,然后运行parted mklabel,我的非零数据肯定会被破坏。

如果我从分离的存储库mbr.s中组装文件,我可以看到这些字节来自哪里。libparted

$ as86 -b /dev/stdout mbr.s | hexdump -e '16/1 "%02x " "\n"'
fa b8 00 10 8e d0 bc 00 b0 b8 00 00 8e d8 8e c0
fb be 00 7c bf 00 06 b9 00 02 f3 a4 ea 21 06 00
00 be be 07 38 04 75 0b 83 c6 10 81 fe fe 07 75
f3 eb 16 b4 02 b0 01 bb 00 7c b2 80 8a 74 01 8b
4c 02 cd 13 ea 00 7c 00 00 eb fe
Run Code Online (Sandbox Code Playgroud)

这正是parted的磁盘上生成的字节序列。