MBR (Master Boot Record) partition table is a traditional way of MS-DOS to partition larger hard disc drives into distinct partitions.
This table is stored in the end of the boot sector (first sector) of the drive, after the bootstrap code. Original DOS 2.0 specification allowed only 4 partitions per disc, but DOS 3.2 introduced concept of "extended partitions", which work as nested extra "boot records" which are pointed to by original ("primary") partitions in MBR.
This page hosts a formal specification of MBR (Master Boot Record) partition table using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.
import (
"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
"bytes"
)
/**
* MBR (Master Boot Record) partition table is a traditional way of
* MS-DOS to partition larger hard disc drives into distinct
* partitions.
*
* This table is stored in the end of the boot sector (first sector) of
* the drive, after the bootstrap code. Original DOS 2.0 specification
* allowed only 4 partitions per disc, but DOS 3.2 introduced concept
* of "extended partitions", which work as nested extra "boot records"
* which are pointed to by original ("primary") partitions in MBR.
*/
type MbrPartitionTable struct {
BootstrapCode []byte
Partitions []*MbrPartitionTable_PartitionEntry
BootSignature []byte
_io *kaitai.Stream
_root *MbrPartitionTable
_parent kaitai.Struct
}
func NewMbrPartitionTable() *MbrPartitionTable {
return &MbrPartitionTable{
}
}
func (this MbrPartitionTable) IO_() *kaitai.Stream {
return this._io
}
func (this *MbrPartitionTable) Read(io *kaitai.Stream, parent kaitai.Struct, root *MbrPartitionTable) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp1, err := this._io.ReadBytes(int(446))
if err != nil {
return err
}
tmp1 = tmp1
this.BootstrapCode = tmp1
for i := 0; i < int(4); i++ {
_ = i
tmp2 := NewMbrPartitionTable_PartitionEntry()
err = tmp2.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Partitions = append(this.Partitions, tmp2)
}
tmp3, err := this._io.ReadBytes(int(2))
if err != nil {
return err
}
tmp3 = tmp3
this.BootSignature = tmp3
if !(bytes.Equal(this.BootSignature, []uint8{85, 170})) {
return kaitai.NewValidationNotEqualError([]uint8{85, 170}, this.BootSignature, this._io, "/seq/2")
}
return err
}
type MbrPartitionTable_Chs struct {
Head uint8
B2 uint8
B3 uint8
_io *kaitai.Stream
_root *MbrPartitionTable
_parent *MbrPartitionTable_PartitionEntry
_f_cylinder bool
cylinder int
_f_sector bool
sector int
}
func NewMbrPartitionTable_Chs() *MbrPartitionTable_Chs {
return &MbrPartitionTable_Chs{
}
}
func (this MbrPartitionTable_Chs) IO_() *kaitai.Stream {
return this._io
}
func (this *MbrPartitionTable_Chs) Read(io *kaitai.Stream, parent *MbrPartitionTable_PartitionEntry, root *MbrPartitionTable) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp4, err := this._io.ReadU1()
if err != nil {
return err
}
this.Head = tmp4
tmp5, err := this._io.ReadU1()
if err != nil {
return err
}
this.B2 = tmp5
tmp6, err := this._io.ReadU1()
if err != nil {
return err
}
this.B3 = tmp6
return err
}
func (this *MbrPartitionTable_Chs) Cylinder() (v int, err error) {
if (this._f_cylinder) {
return this.cylinder, nil
}
this._f_cylinder = true
this.cylinder = int(this.B3 + (this.B2 & 192) << 2)
return this.cylinder, nil
}
func (this *MbrPartitionTable_Chs) Sector() (v int, err error) {
if (this._f_sector) {
return this.sector, nil
}
this._f_sector = true
this.sector = int(this.B2 & 63)
return this.sector, nil
}
type MbrPartitionTable_PartitionEntry struct {
Status uint8
ChsStart *MbrPartitionTable_Chs
PartitionType uint8
ChsEnd *MbrPartitionTable_Chs
LbaStart uint32
NumSectors uint32
_io *kaitai.Stream
_root *MbrPartitionTable
_parent *MbrPartitionTable
}
func NewMbrPartitionTable_PartitionEntry() *MbrPartitionTable_PartitionEntry {
return &MbrPartitionTable_PartitionEntry{
}
}
func (this MbrPartitionTable_PartitionEntry) IO_() *kaitai.Stream {
return this._io
}
func (this *MbrPartitionTable_PartitionEntry) Read(io *kaitai.Stream, parent *MbrPartitionTable, root *MbrPartitionTable) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp7, err := this._io.ReadU1()
if err != nil {
return err
}
this.Status = tmp7
tmp8 := NewMbrPartitionTable_Chs()
err = tmp8.Read(this._io, this, this._root)
if err != nil {
return err
}
this.ChsStart = tmp8
tmp9, err := this._io.ReadU1()
if err != nil {
return err
}
this.PartitionType = tmp9
tmp10 := NewMbrPartitionTable_Chs()
err = tmp10.Read(this._io, this, this._root)
if err != nil {
return err
}
this.ChsEnd = tmp10
tmp11, err := this._io.ReadU4le()
if err != nil {
return err
}
this.LbaStart = uint32(tmp11)
tmp12, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumSectors = uint32(tmp12)
return err
}