I've been struggling to figure out a boot problem with the RaspberryPi 3 (I've not tested other models) using a modified Raspbian Jessie Lite image, and finally narrowed down to something to do with the MBR -- but now I'm baffled and curious as to what exactly the problem is.
In short: if I adjust partitions with parted
, the Pi doesn't boot. If I do the exact same adjustment with fdisk
, it works fine.
Fair warning: this question involves reading hex dumps of the master boot record.
Basically I'm expanding a stock Raspbian image and then resizing the second partition, then writing it to an SD card. However, the same problem happens if I write the stock Raspbian image to an SD card and modify the SD card partition there.
Here's the starting partition layout, for reference:
gregmac:~$ gdisk -l 2017-04-10-raspbian-jessie-lite.img
Disk 2017-04-10-raspbian-jessie-lite.img: 2534888 sectors, 1.2 GiB
Logical sector size: 512 bytes
Number Start (sector) End (sector) Size Code Name
1 8192 92159 41.0 MiB 0700 Microsoft basic data
2 92160 2534887 1.2 GiB 8300 Linux filesystem
(Note: I removed a bunch of extraneous output from this command for brevity -- this question is long enough)
Using parted
First I add 300MiB, then resize the second partition to end at the last sector:
gregmac:~$ cp 2017-04-10-raspbian-jessie-lite.img test-parted.img
gregmac:~$ truncate -s +300M test-parted.img
gregmac:~$ parted test-parted.img resizepart 2 3149287s
And the resulting layout:
gregmac:~$ gdisk -l test-parted.img
Disk test-parted.img: 3149288 sectors, 1.5 GiB
Logical sector size: 512 bytes
Number Start (sector) End (sector) Size Code Name
1 8192 92159 41.0 MiB 0700 Microsoft basic data
2 92160 3149287 1.5 GiB 8300 Linux filesystem
The problem is: this image will not boot. The green LED flashes rapidly with activity for a second or two, then the screen just displays 4 raspberries indefinitely while the green LED blinks once every second for several minutes and eventually stops (the screen stays the same).
Using fdisk
Frustratingly, I eventually figured out that I can do exactly this same modification using fdisk
and the Pi boots just fine.
gregmac:~$ cp 2017-04-10-raspbian-jessie-lite.img test-fdisk.img
gregmac:~$ truncate -s +300M test-fdisk.img
gregmac:~$ fdisk test-fdisk.img
Command (m for help): p
Disk test-truncate-fdisk.img: 1612 MB, 1612435456 bytes
255 heads, 63 sectors/track, 196 cylinders, total 3149288 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x84fa8189
Device Boot Start End Blocks Id System
test-fdisk.img1 8192 92159 41984 c W95 FAT32 (LBA)
test-fdisk.img2 92160 2534887 1221364 83 Linux
Command (m for help): d
Partition number (1-4): 2
Command (m for help): n
Partition type:
p primary (1 primary, 0 extended, 3 free)
e extended
Select (default p): p
Partition number (1-4, default 2): 2
First sector (2048-3149287, default 2048): 92160
Last sector, +sectors or +size{K,M,G} (92160-3149287, default 3149287):
Using default value 3149287
Command (m for help): w
The partition table has been altered!
Syncing disks.
And resulting partition layout:
gregmac:~$ gdisk -l test-fdisk.img
Disk test-fdisk.img: 3149288 sectors, 1.5 GiB
Logical sector size: 512 bytes
Number Start (sector) End (sector) Size Code Name
1 8192 92159 41.0 MiB 0700 Microsoft basic data
2 92160 3149287 1.5 GiB 8300 Linux filesystem
(hint: 100% identical to the parted version!)
MBR differences
So after much messing around (and a couple dozen SD card writes to a few different cards), I eventually resorted to binary diffs of the files.
Quick master boot record primer/refresher: the MBR is 512 bytes:
- First 446 bytes: "Bootstrap code area"
- Next 16 bytes: Partition 1
- Next 16 bytes: Partition 2
- Next 16 bytes: Partition 3
- Next 16 bytes: Partition 4
- Remaining 2 bytes: Boot signature
There are three differences in my images:
1) The stock image is exactly 300 MB smaller
Expected, because I added 300MB to my images.
2) Partition 2 is different
Well, of course, because I explicitly modified it. Notably though, the two images I created are identical, even though parted
did one and fdisk
did the other.
For reference, dumping the 16-byte partition 2 table:
gregmac:~$ hexdump -C -s $((446+16)) -n 16 2017-04-10-raspbian-jessie-lite.img
000001ce 00 bb 37 05 83 c9 14 9d 00 68 01 00 e8 45 25 00 |..7......h...E%.|
gregmac:~$ hexdump -C -s $((446+16)) -n 16 test-parted.img
000001ce 00 bb 37 05 83 08 2c c4 00 68 01 00 e8 a5 2e 00 |..7...,..h......|
gregmac:~$ hexdump -C -s $((446+16)) -n 16 test-fdisk.img
000001ce 00 bb 37 05 83 08 2c c4 00 68 01 00 e8 a5 2e 00 |..7...,..h......|
3) The bootstrap code area is very different in the parted
image
The bootstrap code in my fdisk
-created image is identical to the stock Raspbian image, and it looks like this:
gregmac:~$ hexdump -C -n 446 2017-04-10-raspbian-jessie-lite.img
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000001b0 00 00 00 00 00 00 00 00 89 81 fa 84 00 00 |..............|
The bootstrap code in the parted
-created image, however, is entirely different:
gregmac:~$ hexdump -C -n 446 test-parted.img
00000000 fa b8 00 10 8e d0 bc 00 b0 b8 00 00 8e d8 8e c0 |................|
00000010 fb be 00 7c bf 00 06 b9 00 02 f3 a4 ea 21 06 00 |...|.........!..|
00000020 00 be be 07 38 04 75 0b 83 c6 10 81 fe fe 07 75 |....8.u........u|
00000030 f3 eb 16 b4 02 b0 01 bb 00 7c b2 80 8a 74 01 8b |.........|...t..|
00000040 4c 02 cd 13 ea 00 7c 00 00 eb fe 00 00 00 00 00 |L.....|.........|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000001b0 00 00 00 00 00 00 00 00 41 da 04 00 00 00 |........A.....|
Specifically:
- the disk signature (offset 0x01B8) of the
parted
image is41 da 04 00
, but in the other two it is89 81 fa 84
- The first 75 bytes of bootstrap code in the
parted
image has some code in it, but is zeroed-out in the other two
I am pretty sure the "disk signature" doesn't have any actual meaning here. For comparison the disk signature in 2016-09-23-raspbian-jessie-lite.img
is a1 89 70 5a
-- which leads me to believe this value is unimportant.
Question
So my questions:
- Why is parted doing this? (and what is this bootstrap code doing?)
- According to NOOBs documentation (and elsewhere): "a Raspberry Pi doesn't use any of the bootstrap code stored in the MBR.". So why is the different bootstrap code causing a failure to boot?
- Despite my assumption, is the disk signature difference actually causing the problem? In that case, why does the 2016-09-23 Raspbian image work even though it's also different? Why is parted setting it incorrectly and how do I make it not do that?