Master Boot Record
The master boot record (MBR) describes traits of the memory, bootloader (or bootstrap) code, and most especially the partition tables. A classic MBR is formatted as follows:Address | Description | Size (bytes) | ||
---|---|---|---|---|
Hex | Dec | |||
+000hex | +0 | Bootstrap code area | 446 | |
+1BEhex | +446 | Partition entry №1 | Partition table (for primary partitions) | 16 |
+1CEhex | +462 | Partition entry №2 | 16 | |
+1DEhex | +478 | Partition entry №3 | 16 | |
+1EEhex | +494 | Partition entry №4 | 16 | |
+1FEhex | +510 | 55hex | Boot signature[a] | 2 |
+1FFhex | +511 | AAhex | ||
Total size: 446 + 4×16 + 2 | 512 |
The MBR is located in the first sector of the entire storage device - sector 1. Theoretically this is the equivalent to the memory address '0x0'. There are exactly four partition table entries, no more, no less for historical and compatibility reasons. The end of the boot record is signaled by the signature "0x55AA." MBR addresses are absolute, meaning address 0x000001BE is always going to be the address for partition table entry one.
Define 'Sector': An aligned chunk of data within a memory device. Sectors are usually no less than 512 bytes each. Larger memory devices sometimes use 1024 bytes up to 4096 bytes per sector. SD cards are commonly 512 bytes per sector.
Partition Table Entries
An entry describes where in the memory space each partition is located, how big it is, the partition type, and whether or not the partition is active. Side note: an active partition can be booted from, that is, an operating system or other bootstrap can execute code contained within the partition's own boot record. The byte-code layout of a partition is formatted as follows:Address | Description | Size (bits) | |
---|---|---|---|
Hex | Dec | ||
+0hex | +0 | Active Partition (0x00 - inactive, 0x80 - active, other - invalid) | 8 |
+1hex | +1 | Start Head | 8 |
+2hex | +2 | *Start Sector (bits 0-5) | 8 |
+3hex | +3 | *Start Cylinder (bits 0-7 and bits 6&7 from the previous byte) | 8 |
+4hex | +4 | Partition Type | 8 |
+5hex | +5 | End Head | 8 |
+6hex | +6 | *End Sector (bits 0-5) | 8 |
+7hex | +7 | *End Cylinder (bits 0-7 and bits 6&7 from the previous byte) | 8 |
+8hex | +8 | †Absolute starting sector of the partition | 8 |
+Chex | +12 | †Size of the partition in sectors | 8 |
Total size: 16x8 | 128 |
* Start sector and end sector values are only 6-bits in size. The remaining two bits in the byte are the most significant bits of the 10-bit start and end cylinder values respectively. For example, if the 'Start Sector' byte is 0xFE and the 'Start Cylinder' byte is 0xFF, then their actual values are 0x3E and 0x3FF respectively.
† Multi-byte values are little-endian! So an absolute starting sector with a value of 0x00080000 for example is actually 0x800. Same goes for the sector size.
An (incomplete) list of partition types:
Value (hex) | Description |
---|---|
00 | Empty partition-table entry |
01 | FAT12 |
04 | FAT16 (<= 32 MB) |
05 | Extended Partition |
06 | FAT16 (> 32 MB) |
07 | OS/2 HPFS, Windows NT NTFS, Advanced Unix |
08 | OS/2 v1.0-1.3, AIX Bootable Partition, SplitDrive |
09 | AIX Data Partition |
0A | OS/2 Boot Manager |
0B | FAT32 |
0C | FAT32 (using LBA-mode INT13 extensions) |
0E | FAT16 (> 32 MB using INT13 extensions) |
0F | Extended Partition (using INT13 extensions) |
17 | Hidden NTFS |
1B | Hidden FAT32 |
1C | Hidden FAT32 (using LBA-mode INT13 extensions) |
1E | Hidden LBA VFAT |
42 | Dynamic Disk Volume |
50 | OnTrack Disk Manager (read-only) |
51 | OnTrack Disk Manager (read-write) |
81 | Linux |
82 | Linux Swap, Solaris |
83 | Linux Native (EXT2 / XIAFS) |
85 | Linux EXT |
86 | FAT16 Volume/Stripe (Windows NT) |
87 | HPFS Fault-Tolerant Mirrored, NTFS Volume/Strip |
BE | Solaris Boot |
C0 | DR-DOS / Novell DOS Secured |
C6 | Corrupt FAT16 Volume/Strip |
C7 | Corrupt NTFS Volume/Stripe |
F2 | Secondary Partition |
Cylinder-Head-Sector Geomtery & Logical Block Addressing
Cylinder-Header-Sector (CHS) is the legacy way of locating the start and end sectors of partitions. Historically these values corresponded to the physical reading head, the cylinder or track of data, and the slice or sector within the track. Many modern solid-state and flash devices don't have such features, and CHS itself is limited to a max size of about 7.8 GB. So, most devices now-a-days use the Logical-Block-Addressing (LBA) method to locating partition boundaries. The 'absolute starting sector' in a partition table entry is an example of an LBA. (LBA units are in sectors.) CHS is kept for compatibility reasons.To convert from CHS to LBA, use the following formula:
(C x TH x TS) + (H x TS) + (S - 1) = LBA
Where,
C = cylinder number
H = head number
S = sector number
TH = total heads (255 or 16)
TS = total sectors (63)
Exploration
Try it out! Find a 512 MB - 4 GB SD card or thumb drive and create an image from it using the dd Linux command. Then use a hex editor to inspect the binary values of the image. (The memory size is only for exploratory convenience.) Try searching for partitions and determining their characteristics. (You can use the gparted Linux utility to format the device and fdisk -l /dev/mmcblkX to quickly print out basic MBR info.)If your SD card is listed under the Linux devices as /dev/mmcblk0 for example, you can create a binary image with the command:
sudo dd if=/dev/mmcblk0 of=$(pwd)/mmc.img bs=512 status=progress
You can then open the file mmc.img in a hex editor such as GHex for Linux or HxD on Windows.
Happy Hacking!