MBR vs GPT Partition Table Structures in Ventoy: Key Differences Explained
The key difference is that Ventoy detects MBR disks by reading a simple 512-byte sector with four 16-byte partition entries, while GPT disks require a protective MBR flag (0xEE) followed by a 512-byte GPT header with a signature of "EFI PART" and a 128-entry partition array.
Ventoy supports both legacy BIOS (MBR) and modern UEFI (GPT) boot schemes, handling each through distinct code paths in the ventoy/Ventoy repository. Understanding these partition table structures is essential for developers working with Ventoy's disk management utilities or debugging boot loader interactions across different firmware types.
Structural Layout Differences
MBR (Master Boot Record) Structure
The MBR layout occupies exactly 512 bytes in sector 0. According to vtoycli/vtoycli.h, this sector contains 446 bytes of boot code, followed by four 16-byte partition entries (PART_TABLE), and ends with the magic bytes 0x55AA.
Each PART_TABLE entry (lines 46-62) contains:
Active– boot indicator flagFsFlag– filesystem type identifierStartSectorId– starting sector numberSectorCount– partition size in sectors
Ventoy limits MBR to 4 primary partitions (or extended partitions via chaining), accessing the EFI partition through the second entry MBR.PartTbl[1].
GPT (GUID Partition Table) Structure
GPT uses a protective MBR in sector 0 (with FsFlag == 0xEE) followed by a dedicated GPT header and partition array. As defined in vtoycli/vtoycli.h (lines 80-108), the structure includes:
- Header (
VTOY_GPT_HDR): 512-byte sector containing an 8-byte ASCII signature"EFI PART", version info, CRC checksums, and the backup header location (EfiBackupLBA) - Partition Array: 128 entries (
VTOY_GPT_PART_TBL), each 128 bytes, storing GUIDs for partition type and unique ID, 64-bit LBA ranges (StartLBA,LastLBA), attributes, and UTF-16 names
Ventoy stores a backup copy of the GPT header and partition array at the end of the disk, unlike MBR which maintains no redundant table.
Detection Logic in Ventoy Source Code
Protective MBR Flag Check
Ventoy branches its disk-handling logic early by checking the first partition entry's filesystem flag. In vtoyjump/vtoyjump.c (lines 973-996), the code reads sector 0 into an MBR_HEAD structure and tests:
if (MBR.PartTbl[0].FsFlag == 0xEE) {
// GPT handling path
} else {
// MBR handling path
}
This 0xEE flag indicates a protective MBR that reserves the entire disk for GPT usage, preventing legacy tools from accidentally destroying the partition table.
GPT Signature Verification
After detecting the protective flag, Ventoy validates the GPT header by reading the VTOY_GPT_INFO structure and verifying the signature. In vtoycli/partresize.c (lines 84-90), the detection logic confirms:
if (pGPT->MBR.PartTbl[0].FsFlag == 0xEE &&
memcmp(pGPT->Head.Signature, "EFI PART", 8) == 0) {
// Valid GPT disk confirmed
}
Only when both conditions pass does Ventoy proceed with GPT-specific calculations using 64-bit LBA addressing.
Data Structure Definitions in vtoycli.h
MBR Structures
The legacy structure uses simple 32-bit sector addressing. From vtoycli/vtoycli.h:
typedef struct {
UINT8 Active; // 0x80 = active
UINT8 StartHead;
UINT16 StartSector; // bits 0-5
UINT8 StartCylinder; // bits 6-15
UINT8 FsFlag; // 0xEE for protective MBR
UINT8 EndHead;
UINT16 EndSector;
UINT8 EndCylinder;
UINT32 StartSectorId; // 32-bit LBA
UINT32 SectorCount; // 32-bit size
} PART_TABLE;
typedef struct {
UINT8 BootCode[446];
PART_TABLE PartTbl[4]; // Four primary entries
UINT8 Signature[2]; // 0x55 0xAA
} MBR_HEAD;
GPT Structures
Modern GUID-based addressing uses 128-bit identifiers and 64-bit LBAs:
typedef struct {
CHAR8 Signature[8]; // "EFI PART"
UINT32 Version;
UINT32 HeaderSize;
UINT32 Crc32;
UINT32 Reserved;
UINT64 EfiStartLBA; // My LBA (always 1)
UINT64 EfiBackupLBA; // Backup header location
UINT64 PartAreaStartLBA; // First usable sector
UINT64 PartAreaEndLBA;
CHAR8 DiskGuid[16];
UINT64 PartTblStartLBA; // Usually 2
UINT32 PartTblTotCnt; // 128 entries
UINT32 PartTblSize; // 128 bytes each
UINT8 Reserved2[420];
} VTOY_GPT_HDR;
typedef struct {
CHAR8 PartType[16]; // GUID type identifier
CHAR8 PartGuid[16]; // Unique partition GUID
UINT64 StartLBA; // 64-bit start address
UINT64 LastLBA; // 64-bit end address
UINT64 Attr;
CHAR16 Name[36]; // UTF-16 partition name
} VTOY_GPT_PART_TBL;
Practical Implementation Examples
Reading the EFI Partition Start Sector
The cross-platform function GetVentoyEfiPartStartSector in vtoyjump/vtoyjump.c (lines 955-1002) handles both layouts:
UINT64 GetVentoyEfiPartStartSector(HANDLE hDrive) {
MBR_HEAD MBR;
VTOY_GPT_INFO *pGpt = NULL;
UINT64 StartSector = 0;
DWORD dwSize;
SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
if (MBR.PartTbl[0].FsFlag == 0xEE) { // GPT path
pGpt = malloc(sizeof(VTOY_GPT_INFO));
SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
ReadFile(hDrive, pGpt, sizeof(VTOY_GPT_INFO), &dwSize, NULL);
StartSector = pGpt->PartTbl[1].StartLBA; // EFI partition
free(pGpt);
} else { // MBR path
StartSector = MBR.PartTbl[1].StartSectorId;
}
return StartSector;
}
Creating Protective MBR Entries
When Ventoy CLI detects a GPT disk, it marks the drive info structure accordingly in Ventoy2Disk/ventoy_cli.c (line 269):
if (MBR.PartTbl[0].FsFlag == 0xEE) {
pDrvInfo->PartStyle = 1; // 1 = GPT, 0 = MBR
memcpy(&(pDrvInfo->MBR), &MBR, sizeof(MBR));
}
Dumping GPT Header Information
For debugging and validation, vtoycli/vtoygpt.c (lines 143-226) provides dump utilities:
void DumpHead(VTOY_GPT_HDR *pHead) {
// Prints signature, version, and CRC validation
}
void DumpPartTable(VTOY_GPT_PART_TBL *Tbl) {
// Iterates all 128 entries displaying GUIDs and LBA ranges
}
Key Source Files
vtoycli/vtoycli.h– Core structure definitions forMBR_HEAD,VTOY_GPT_HDR, andVTOY_GPT_PART_TBLvtoyjump/vtoyjump/vtoyjump.c– Runtime detection logic and EFI partition location retrievalvtoycli/partresize.c– Linux-side GPT/MBR detection and partition resizing operationsvtoycli/vtoygpt.c– GPT header dumping and manipulation utilitiesVentoy2Disk/ventoy_cli.c– CLI entry point for drive classificationVentoy2Disk/Ventoy2Disk/ff14/source/ff.c– Low-level filesystem checks for protective MBR flags
Summary
- MBR uses 512-byte sectors with four primary partition entries and 32-bit sector addressing; Ventoy identifies it when
FsFlag != 0xEE. - GPT uses protective MBR + header + array, supporting 128 partitions with 64-bit LBA addressing and GUID identifiers; detected via
FsFlag == 0xEEand"EFI PART"signature. - Backup redundancy exists only in GPT, with primary and backup headers at opposite ends of the disk.
- EFI partition location is read from
PartTbl[1].StartSectorId(MBR) orPartTbl[1].StartLBA(GPT) depending on the detected layout. - All detection branches on the protective flag before parsing the appropriate
VTOY_GPT_INFOorMBR_HEADstructure.
Frequently Asked Questions
How does Ventoy detect whether a disk uses MBR or GPT?
Ventoy reads the first 512 bytes of the drive into an MBR_HEAD structure and checks if MBR.PartTbl[0].FsFlag == 0xEE. If true, it reads the subsequent GPT header and verifies the "EFI PART" signature; otherwise, it processes the legacy MBR layout directly.
What is the protective MBR in GPT disks used by Ventoy?
The protective MBR is a dummy MBR structure with a single partition entry marked 0xEE that covers the entire disk. This prevents legacy partitioning tools from treating the disk as unpartitioned or creating conflicting MBR entries that would destroy the GPT data.
How many partition entries does Ventoy allocate for GPT disks?
According to vtoycli/vtoycli.h, Ventoy allocates the full 128-entry array specified by the GPT standard, with each entry consuming 128 bytes. This provides space for multiple OS installations and utility partitions beyond MBR's four-entry limit.
Where does Ventoy store the EFI partition in MBR vs GPT layouts?
In MBR disks, Ventoy places the EFI partition at the location specified by MBR.PartTbl[1].StartSectorId. In GPT disks, it uses the second partition entry pGpt->PartTbl[1].StartLBA, which typically resides immediately after the GPT header and partition array sectors.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →