8

My understanding is that an MBR is 512 bytes. The first 440 bytes (give or take a few bytes, depending on the implementation) contain the boot loader/bootstrap code area. The remaining bytes contain information about the partition table.

If I zero out the MBR of a disk...

# Zero out the MBR
dd if=/dev/zero of=/dev/sdX bs=1 count=512

Then, use fdisk to write a partition table to /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

And then read back the first 440 bytes...

dd if=/dev/sdX bs=1 count=440

The first 440 bytes are still all zero. fdisk did not touch them, which makes sense based on the links I posted above. fdisk is writing partition information, so it should/would not need to touch the first 440.

The next 6 bytes are non-zero. I'm assuming these bytes are part of the disk signature of a modern standard MBR.

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

So far, that makes sense with my understanding of how the MBR is laid out. Those first 440 bytes are ignored by fdisk because they're the domain of the bootloader, and fdisk is only concerned with partition tables.

However, parted is throwing me for a loop.

If I zero out the MBR of that same disk again...

# Zero out the MBR
dd if=/dev/zero of=/dev/sdX bs=1 count=512

Then, use parted to create a disk label (which fdisk seemed to do automatically for me up above)...

parted /dev/sdX mklabel msdos

And then read back the first 440 bytes...

$ 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

There are non-zero bytes! That does not seem to make sense with my current understanding of how the MBR should be laid out and what GNU parted is supposed to accomplish.

GNU Parted is a program for creating and manipulating partition tables.

Why is parted writing data to those first 440 bytes? Aren't those bytes meant for a bootloader? Shouldn't parted leave those bytes alone like fdisk did?

1 Answers1

4

It would appear I am not the only one to notice this behavior. It seems to especially be an issue for some arm environments where having a bootloader on the disk can cause issues.

The problem is that parted itself (and silently) puts the code there and hence the embedded system thinks that there is a valid bootloader code and happily hangs.

...and...

Is there any option to parted to avoid adding this code (and behave like fdisk)?

It seems that this behavior by parted is intentional. As a user on the parted mailing lisk asks:

The problem is that parted is generating following code from the very beginning of the MBR:

...

What is the purpose of this code? Why is has been put there?

And the answer seems to be:

That's the MBR boot code normally used to boot a BIOS system. If it causes problems on a non-x86 system you should zero it out (or write the system bootloader after partitioning).

It seems that mklabel is designed to write a generic bootloader to the disk. At least, when a label of msdos is being used. I suppose that makes sense, but coming from fdisk and syslinux, it seems a bit unusual for a partition manager to modify bootloader sectors.

It seems like parted should not be overwriting those sectors if non-zero data is present.

No, the only time it won't write it is if there is something already there (eg. not 0x00). So if you could get the SDK to write it's bootloader first, then partition it, parted will leave it untouched.

However, that is not the behavior I am seeing. If I write garbage from /dev/urandom, then run parted mklabel, my non-zero data is definitely being clobbered.

If I assemble the mbr.s file in libparted from the parted repo, I can see where those bytes are coming from.

$ 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

That is exactly the byte sequence that parted seems to generate on my disk.