Click here to Skip to main content
13,052,022 members (65,947 online)
Click here to Skip to main content
Add your own
alternative version


31 bookmarked
Posted 2 Nov 2012

Partition Tables Explained

, 2 Nov 2012
Rate this:
Please Sign up or sign in to vote.
An article describing the format of the partition table accompanied with a GUI demonstration tool.



I've always been curious about how disks are partitioned, and how the partition table looks like. This article will explain the format of the partition table and will provide a small tool (Partition Viewer) to demonstrate what we explained.

The information in this article apply for x86 systems, I don't know about disk partitioning on other systems.
You are not required to have prior knowledge about disk partitioning; The goal of this article is to provide just the needed knowledge to understand disk partitioning, hence many details are left out for the readers to investigate by themselves.

Please note that this article does NOT cover the GPT (GUID Partition table).


In this section I will introduce some concepts that are needed to understand the article.

When you purchase a new hard-disk with a given capacity, all you can do with it is read/write raw data from first address up to last address. You can achieve that with special tools that can read an unformatted/unpartitioned disk. The data you read/write have no standard structure but the structure you devise.

When we partition a disk, we are simply dividing the disk's space into partitions (logical boundaries). For example a 10GB can be divided (theoratically) into as many partitions as one desires, say 3GB, 4GB and 3GB partitions.

[======10 GB============] (before partitioning)
[(3GB===)(4GB====)(3GB===)] (after partitioning)

Practically, disk partitioning is more than just dividing the disk's space into smaller partitions, but also attaching a given structure to each partition.
Those structures are named "File systems". You may have heard of FAT and NTFS file systems (supported by Microsoft Operating systems).

File systems are a way to allow you to store your data in an organized manner (manageable by the host operating system). That is why disk-partitioning has rules and limits (discussed later). For example, you can create a 10GB partition but you cannot attach to it the FAT16 file system, since FAT16 can only manage up to 2GB of disk space. Each file system has its cons and pros, which are not discussed in this document.

To finalize the disk partitioning and file system relationship, you can imagine that a raw non-partitioned disk can be compared to a big room with no divisions where every employee scatters his stuff here and there, but when we divide (partitioning) that space with cubicles we have organized offices and rooms (File system).

Disk addressing and capacity limitation

In this section we will try to explain the disk addressing concepts.

Cylinder/Head/Sector (CHS) addressing

CHS stands for (C)ylinder/(H)ead/(S)ector addressing mode. Those three component together designates the target disk address.

Logical Block Addressing (LBA)

LBA is linear addressing mode, starting from address 0 up to the maximum addressable location in the disk.
As opposed to CHS addressing, LBA is much simpler and easier to understand and is used in modern operating systems.

MBR and partition table format

In this section we will explain about the MBR (Master Boot record) and the format of the partition table and where it is located on the physical disk.

The master boot record (MBR) is a structure that holds the boot loader program and the partition table. The MBR is always located at the very start of the disk, at LBA 0 or 0,0,1 in CHS addressing.

The length of the MBR structure is 512 bytes.



Offset (hex)Size (in bytes)Item
0x0-0x1BD446Boot loader
0x1BE-0x1FD64Partition table
0x1FE-0x1FF2Signature (should be 0x55, 0xAA)



Usually, the role of the MBR is to find which partition table is active, load its boot sector and execute it

The MBR loader can be infected with an MBR virus (sometimes referred to as bootkits) that runs even before the operating system boots (or the boot sector executes) 

Boot Loader

The boot loader is a program whose sole purpose is to interpret the partition table and decide which partition should be booted from.

The boot loader can be infected with a boot-sector virus that runs even before the operating system boots

Here are the usual steps that are done by the boot loader:

  1. Load the partition table
  2. Iterate through its entries looking for a partition entry marked as active
  3. Once an active partition is found, we load the correspondence boot sector of that partition
  4. If no active partitions are found then we halt
  5. Once an active partition is found and its corresponding boot sector is loaded, then MBR executes the MBR code


Boot Sector

In the previous section we introduced the term "boot sector" which is not to be confused with MBR's "boot loader". The boot sector and the MBR are two different things.

A boot sector is yet another structure, 512 bytes in size, that is file-system specific. Its function is to initiate the operating system and load it from the disk. Since the MBR will load a boot sector and execute it, the least requirements for a boot sector are:

  1. Offset 0 should have a valid x86 instruction so that when MBR runs it, the code does not crash the system
  2. Offset 0x1FE should have the signature 0x55 0xAA (like the MBR)

In the case of MS-DOS, the boot sector program is responsible for loading IO.SYS and MS-DOS.SYS which will in turn load the COMMAND.COM


Partition Table

The partition table is 64 bytes long and is located inside the MBR at sector 0x1BE.

The partition table is an array of 4 partition table entries each of 16 bytes thus: 16x4 = 64.

The format of each partition table entry is the following:

0x001Boot indicator; 0x80 = Active partition / 0x00 Inactive partition (boot_indicator)
0x011partition start: head (chs_start.head)
0x021partition start: sector (chs_start.sect)
0x031partition start: cylinder (chs_start.cyl)
0x041Partition ID (example ID=1 for FAT12) (system_indicator)
0x051partition end: head (chs_end.head)
0x061partition end: sector (chs_end.sector)
0x071partition end: cylinder (chs_end.cyl)
0x084Number of sectors before the beginning of this partition (sectors_before)
0x0C4Number of sectos in this partition (number_of_sectors)

You should note that the start and end CHS values are not as they are stored, instead, we have to extract their values from the bits.

real cylinder value = ((chs.sector >> 6) << 8) | (chs.cyl). We take bits 6-7 from chs_sector which are the high bits of real_cyl_value and then combine them with chs_cyl which are the low bits of real_cyl_value.

The reason they are encoded that way, is because the BIOS INT 0x13/AH=0x02 function (which reads a sector) requires this encoding:

	AH = 02h
	AL = number of sectors to read (must be nonzero)
	CH = low eight bits of cylinder number
	CL = sector number 1-63 (bits 0-5)
	     high two bits of cylinder (bits 6-7, hard disk only)
	DH = head number
	DL = drive number (bit 7 set for hard disk)
	ES:BX -> data buffer

The number_of_sectors field describes how many sectors are in this partition. This field can be used to determine the length of the partition. Similarly we can use (CHS_END - CHS_START) to determine the length of the partition.

The number of sectors before (at offset 8) designate where the partition data begins starting from the partition table definition. If in the MBR, an entry has sectors_before equal 63 then this means that the boot sector of that partition is located at sector 63

Primary and Extended Partitions

A primary partition is a partition entry with an ID different than 5 and 15 and can have file system associated with it.

Extended partitions unlike primary partitions, have IDs 5 or 15 and cannot have a file system associated with them, instead they point to another partition table that have at most two partition table entries. The second one can be an extended partition, thus nesting more partitions inside of it). Extended partitions can be considered as just containers of other partitions. We will demonstrate partition table nesting next.

Partition Table Rules

The following partition table rules are take from other sources, I list only the most relevant ones (in the context of this article):

  • Only partition can be active at a time
  • In the MBR partition table: at most 4 primary partitions can be created, or 3 primary partitions and 1 extended partition
  • In the extended partition table: there can be 0 or 1 extended partition link and 0 or 1 non-extended partition (thus two in total)
  • Partition table entries can have any order (we can exchange entry 1 with 2, etc...)


Nested Partitions

Because of the structure of the partition table located in the MBR, we realize that we can have at most 4 partiton table entries in each partition table. To overcome this limitation, special partition table entries are introduced that allow us to have an unlimited number of partitions that are linked together.

Inside the MBR, the extended partition entry describes the size of all the partitions that will be contained inside of it (using the nb_of_sectors field), whereas the NbSectorsBefore or CHS_START will be used to compute the link to the next partition table which can contain at most 2 partition table entries.

Those two entries are: (1) A normal partition entry (2) another extended partition entry pointing to the next linked partition.

Interpreting a Partition Table Manually with a Hex Editor

In this section we will demonstrate how to interpret the partition table manually using a hex editor that can display disk sectors.

This screenshot shows the first sector of the disk. The bytes marked in yellow are the boot loader code. The bytes marked in red are the signature of the MBR which should always be 0x55 0xAA.

The green area shows a complete partition table entry (16 bytes):

  • 00 : Boot indicator -> Inactive
  • 01 01 00 : CHS_START -> Head = 1, Sector = 1, Cyl = 0
  • 06: System Indicator -> FAT16B (>= 32 MB)
  • FE 3F 0B: CHS_END -> Head=254, Sector = 63, Cyl = 11
  • 3F 00 00 00: Sectors Before -> 63
  • CD F0 02 00: Number of sectors -> 192717

Which means that this is a FAT16 partition of ~96MB. In the same manner we can interpret the result of the table and read it as:

Entry #Boot IndicatorCHS_STARTSystem IDCHS_ENDSectors BeforeNb Sectors
100,1,16: FAT16B (>= 32 MB)11,254,6363192717
20166,0,115: Win95 Extended (LBA)12543,254,63266679026748225
3013,0,123: Hidden IFS (HPFS/NTFS)154,254,632088452281230
4012543,0,128: Hidden Win95 FAT32 (LBA)12543,254,63294150154128705

Notice that entry #2 is an extended partition (sysid = 15) of size: (26748225 * 512) = 13695091200 bytes = 13060 GB
This partition starts at sector 2666790 (sectors_before), let us go there and see the partition table pointed by it:

Entry#Boot IndicatorCHS_STARTSystem IDCHS_ENDSectors BeforeNb Sectors
10166,1,111: Win95 FAT32178,254,6363208782
20184,0,15: Extended209,254,63289170417690

As we said, now every partition table that is pointed from the initial extended parition table entry have at most two entries. The first entry is a normal entry and the second entry (type = extended) is a link to another partition table. To compute the LBA of the second entry, we add to the sectors before the "sectors before" value from the extended partition table entry of the MBR, that is: 2666790+289170 = sector 2955960.

Now we go there and read the partition table:

Entry#Boot IndicatorCHS_STARTSystem IDCHS_ENDSectors BeforeNb Sectors
10184,1,16: FAT16B (>= 32 MB)209,254,6363417627
20240,0,15: Extended255,254,255118881017462655

Next partition table is at: 2666790+1188810 = sector 3855600.

Entry#Boot IndicatorCHS_STARTSystem IDCHS_ENDSectors BeforeNb Sectors
10240,1,17: Installable File System (NTFS, HPFS)255,254,2556317462592
20255,0,1935: Extended255,254,255190691553919860

Next partition table is at: 2666790+19069155 = sector 21735945.

Entry#Boot IndicatorCHS_STARTSystem IDCHS_ENDSectors BeforeNb Sectors
10255,1,1936: FAT16B (>= 32 MB)255,254,255633919797
20255,0,1935: Extended255,254,25523246055433755

Next partition table is at: 2666790+23246055 = sector 25912845.

Entry#Boot IndicatorCHS_STARTSystem IDCHS_ENDSectors BeforeNb Sectors
10255,1,193130: Linux swap / Solaris255,254,25563433692
20255,0,1935: Extended255,254,255236798103068415

Next partition table is at: 2666790+23679810 = sector 26346600.

Entry#Boot IndicatorCHS_STARTSystem IDCHS_ENDSectors BeforeNb Sectors
10255,1,19311: Win95 FAT32255,254,255633068352

No next entry; end of partition nesting.

Some Partition Table System IDs

The table below lists some of the known system ids (or file system ids).

0x02XENIX root
0x03XENIX usr
0x04FAT16 <32MB
0x06FAT16B (>= 32 MB)
0x07Installable File System (NTFS HPFS)
0x09AIX bootable
0x0AOS/2 Boot Manager
0x0BWin95 FAT32
0x0CWin95 FAT32 (LBA)
0x0EWin95 FAT16 (LBA)
0x0FWin95 Extended (LBA)
0x11Hidden FAT12
0x12Compaq diagnostics
0x14Hidden FAT16 <32MB
0x16Hidden FAT16
0x17Hidden IFS (HPFS/NTFS)
0x18AST SmartSleep
0x1BHidden Win95 FAT32
0x1CHidden Win95 FAT32 (LBA)
0x1EHidden Win95 FAT16 (LBA)
0x2CWildFile/Adaptec GOBack
0x39Plan 9
0x3CPowerQuest Recoverable Partition
0x40Venix 80286
0x41PPC PReP Boot
0x42Veritas Logical Disk Manager
0x4eQNX4.x 2nd part
0x4fQNX4.x 3rd part
0x50OnTrack DM
0x51OnTrack DM6 Aux1
0x53OnTrack DM6 Aux3
0x56Golden Bow
0x5cPriam Edisk
0x63GNU HURD or SysV
0x64Novell Netware 286
0x65Novell Netware (3.11 and 4.1)
0x66Novell Netware 386
0x70DiskSecure Multi-Boot
0x80Old Minix
0x81Linux/Minix v1.4b+
0x82Linux swap / Solaris
0x83Linux native file system (Ext2/3)
0x84OS/2 hiding type 04h partition
0x85Linux extended
0x86NT FAT volume set
0x87NT IFS volume set
0x8eLinux LVM
0x93Amoeba/Hidden Linux native file system (Ext2/3)
0x94Amoeba BBT
0xA0IBM Thinkpad hibernation
0xB7BSDI fs
0xb8BSDI swap
0xbbBoot Wizard hidden
0xc1DRDOS / sec (FAT-12)
0xc4DRDOS / sec (FAT-16 < 32M)
0xc6Disabled NT FAT (FAT-16) volume set/DRDOS
0xc7Syrinx / Disabled NT IFS volume set
0xdaNon-FS data
0xdbCP/M / CTOS / ...
0xdeDell Corporation diagnostic partition
0xe1DOS access
0xe3DOS R/O
0xebBeOS fs
0xefEFI (FAT-12/16/32)
0xf0Linux/PA-RISC boot
0xf2DOS secondary
0xfdLinux raid autodetect
0xffBad Track Table

PartitionViewer Tool

For the sake of demonstration, I wrote a tool that ships with the following components:

  • DiskSector.cpp/.h - A class to read/write raw disk sectors
  • partitionmanager.cpp/.h - A class that parses partition tables
  • MyDrawBar.cpp/.h - MFC static component to draw the partition tables
  • MyHistory.cpp/.h - MFC static component to draw the partition tables
  • PartitionViewer[Dlg].cpp/.h - The UI that uses the above helper classes

The PartitionViewer tool hardcodes only a small subset of the system IDs and colors:

static const MYHISTORYBARTYPECOLOR part_colors[] = 
  {0x0,  RGB(255,255,255), "Free space"},
  {0x6,  RGB(100,10,0), "FAT16B (>= 32 MB)"},
  {0xC,  RGB(255,0,128), "Win95 FAT32 (LBA)"},
  {0xE,  RGB(0,110,110), "Win95 FAT16 (LBA)"},
  {0x7,  RGB(200,0,20), "Installable File System (NTFS, HPFS)"},
  {0x0B, RGB(10,100,0), "Win95 FAT32"},
  {0x83, RGB(20,200,0), "Linux native file system (Ext2/3)"},
  {0x17, RGB(10,0,100), "Hidden IFS (HPFS/NTFS)"},
  {0x82, RGB(101, 12, 130), "Linux swap / Solaris"},
  {0x1C, RGB(90, 127, 30), "Hidden Win95 FAT32 (LBA)"},
  {0x1E, RGB(0, 0, 255), "Hidden Win95 FAT16 (LBA)"},
  {0x04, RGB(101, 12, 130), "FAT16 <32MB"}

Feel free to extend that list.

This program requires admin privilege to work because it accesses the disk sectors.

Once executed:

the partitions will be visualized.

  • Use the dropdown list to select another drive then press the "Represent" button
  • Hover the mouse over the drawn area to display the partition information in the panel just below the drive dropdown list


I hope you found this article useful. In the future, another article can be written to cover the GPT. Please leave your comments or suggestions below and I will try to answer questions or fix the code as much as my (limited) time and my knowledge allow.


I will like to acknowledge all the people who wrote all those articles, open source programs and references that made the writing of this article possible.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Elias Bachaalany
Web Developer
United States United States
Elias (aka lallousx86, @0xeb) has always been interested in the making of things and their inner workings.

His computer interests include system programming, reverse engineering, writing libraries, tutorials and articles.

In his free time, and apart from researching, his favorite reading topics include: dreams, metaphysics, philosophy, psychology and any other human/mystical science.

Former employee of Hex-Rays (the creators of IDA Pro), was responsible about many debugger plugins, IDAPython project ownership and what not.

Elias currently works at Microsoft as a software security engineer.

More articles and blog posts can be found here:


You may also be interested in...


Comments and Discussions

GeneralMany issues with source code Pin
Michael Haephrati14-Oct-16 9:48
professionalMichael Haephrati14-Oct-16 9:48 
QuestionHow to take Clone or Image of the HardDisk Pin
Member 37611485-Mar-16 5:11
memberMember 37611485-Mar-16 5:11 
QuestionPartition Tables Explained Pin
@wanderer14-Oct-15 1:12
member@wanderer14-Oct-15 1:12 
AnswerRe: Partition Tables Explained Pin
Elias Bachaalany23-Feb-16 9:07
memberElias Bachaalany23-Feb-16 9:07 
GeneralRe: Partition Tables Explained Pin
@wanderer24-Mar-16 1:56
member@wanderer24-Mar-16 1:56 
GeneralMy vote of 5 Pin
R. Hoffmann5-Nov-12 19:26
memberR. Hoffmann5-Nov-12 19:26 
GeneralRe: My vote of 5 Pin
Elias Bachaalany5-Nov-12 20:02
memberElias Bachaalany5-Nov-12 20:02 
Thank youSmile | :)
QuestionNB Sectors Pin
ledtech32-Nov-12 17:31
memberledtech32-Nov-12 17:31 
AnswerRe: NB Sectors Pin
Elias Bachaalany15-Nov-12 15:04
memberElias Bachaalany15-Nov-12 15:04 
GeneralRe: NB Sectors Pin
ledtech315-Nov-12 15:05
memberledtech315-Nov-12 15:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170713.1 | Last Updated 2 Nov 2012
Article Copyright 2012 by Elias Bachaalany
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid