Skip to content

Implement partition table parsing (GPT and MBR) #420

@pbalduino

Description

@pbalduino

Goal

Implement GPT (GUID Partition Table) and MBR (Master Boot Record) partition table parsing to support multi-partition disk layouts for ext2 dual-boot configuration.

Context

Currently, meniOS assumes a single partition on the boot disk. To support the dual-partition layout (FAT32 /boot + ext2 /), we need to:

  • Detect partition table type (GPT or MBR)
  • Parse partition entries
  • Identify partition types (FAT32, ext2, Linux, etc.)
  • Provide partition metadata to filesystem drivers

This is a prerequisite for #228 (dual partition mount).

Dependencies

Required (Blocking)

Blocks (Downstream)

Priority

Medium - Required for dual-partition boot, not blocking current development

Justification

Implementation Scope

Phase 1: MBR Parsing (3-4 days)

// MBR partition table (sector 0)
struct mbr_partition {
    uint8_t  status;           // 0x80 = bootable
    uint8_t  first_chs[3];     // CHS address (legacy)
    uint8_t  type;             // Partition type
    uint8_t  last_chs[3];      // CHS address (legacy)
    uint32_t lba_start;        // LBA start sector
    uint32_t sector_count;     // Number of sectors
} __attribute__((packed));

struct mbr {
    uint8_t  bootcode[446];
    struct mbr_partition partitions[4];
    uint16_t signature;        // 0xAA55
} __attribute__((packed));

// Common partition types
#define MBR_TYPE_FAT32_CHS    0x0B
#define MBR_TYPE_FAT32_LBA    0x0C
#define MBR_TYPE_LINUX        0x83
#define MBR_TYPE_EXTENDED     0x05
#define MBR_TYPE_GPT_PROTECT  0xEE

Phase 2: GPT Parsing (4-5 days)

// GPT header (sector 1)
struct gpt_header {
    char     signature[8];     // "EFI PART"
    uint32_t revision;
    uint32_t header_size;
    uint32_t header_crc32;
    uint32_t reserved;
    uint64_t current_lba;
    uint64_t backup_lba;
    uint64_t first_usable_lba;
    uint64_t last_usable_lba;
    uint8_t  disk_guid[16];
    uint64_t partition_entries_lba;
    uint32_t num_partitions;
    uint32_t partition_entry_size;
    uint32_t partition_array_crc32;
} __attribute__((packed));

// GPT partition entry
struct gpt_partition {
    uint8_t  type_guid[16];
    uint8_t  partition_guid[16];
    uint64_t first_lba;
    uint64_t last_lba;
    uint64_t attributes;
    uint16_t name[36];         // UTF-16LE
} __attribute__((packed));

// Common type GUIDs
// EFI System: C12A7328-F81F-11D2-BA4B-00A0C93EC93B
// Linux filesystem: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
// Linux swap: 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F

Phase 3: Unified API (2-3 days)

// Unified partition interface
enum partition_type {
    PART_TYPE_UNKNOWN,
    PART_TYPE_FAT32,
    PART_TYPE_EXT2,
    PART_TYPE_EXT3,
    PART_TYPE_EXT4,
    PART_TYPE_LINUX_SWAP,
    PART_TYPE_EFI_SYSTEM,
};

struct partition_info {
    uint32_t index;            // Partition number (0-based)
    enum partition_type type;
    uint64_t start_lba;
    uint64_t sector_count;
    uint64_t size_bytes;
    char label[64];            // Partition label
    bool bootable;
};

struct partition_table {
    enum { PT_NONE, PT_MBR, PT_GPT } type;
    uint32_t num_partitions;
    struct partition_info *partitions;
};

// API functions
int parse_partition_table(struct block_device *bdev, struct partition_table *pt);
struct partition_info *find_partition_by_type(struct partition_table *pt, enum partition_type type);
struct partition_info *find_partition_by_index(struct partition_table *pt, uint32_t index);
void free_partition_table(struct partition_table *pt);

Phase 4: Integration (2 days)

  • Boot sequence integration
  • Partition enumeration at boot
  • Mount root partition by type or index
  • Kernel command line parsing (root=/dev/sda2)

Definition of Done

  • MBR partition table parsing working
  • GPT partition table parsing working
  • Partition type identification (FAT32, Linux/ext2)
  • Unified partition API
  • Boot sequence can enumerate partitions
  • Can identify boot and root partitions
  • Unit tests for MBR and GPT parsing
  • Integration with block device layer
  • Documentation

Implementation Details

MBR Detection

int detect_mbr(struct block_device *bdev) {
    uint8_t sector[512];
    
    // Read sector 0
    if (block_read(bdev, 0, sector, 512) < 0) {
        return -EIO;
    }
    
    // Check signature
    if (sector[510] != 0x55 || sector[511] != 0xAA) {
        return -EINVAL;
    }
    
    // Check if protective GPT
    struct mbr *mbr = (struct mbr *)sector;
    if (mbr->partitions[0].type == MBR_TYPE_GPT_PROTECT) {
        return PT_GPT;
    }
    
    return PT_MBR;
}

GPT Detection

int detect_gpt(struct block_device *bdev) {
    uint8_t sector[512];
    
    // Read sector 1 (GPT header)
    if (block_read(bdev, 1, sector, 512) < 0) {
        return -EIO;
    }
    
    struct gpt_header *gpt = (struct gpt_header *)sector;
    
    // Check signature
    if (memcmp(gpt->signature, "EFI PART", 8) != 0) {
        return -EINVAL;
    }
    
    // Validate CRC32
    uint32_t crc = calculate_crc32(gpt, gpt->header_size);
    if (crc != gpt->header_crc32) {
        kprintf("GPT: header CRC mismatch\n");
        return -EINVAL;
    }
    
    return 0;
}

Partition Type Mapping

enum partition_type identify_partition_type(uint8_t mbr_type, const uint8_t *gpt_guid) {
    // MBR type codes
    if (mbr_type == MBR_TYPE_FAT32_CHS || mbr_type == MBR_TYPE_FAT32_LBA) {
        return PART_TYPE_FAT32;
    }
    if (mbr_type == MBR_TYPE_LINUX) {
        return PART_TYPE_EXT2;  // Could be ext2/3/4, need to probe
    }
    
    // GPT type GUIDs
    if (gpt_guid) {
        if (memcmp(gpt_guid, GUID_LINUX_FILESYSTEM, 16) == 0) {
            return PART_TYPE_EXT2;  // Could be ext2/3/4
        }
        if (memcmp(gpt_guid, GUID_EFI_SYSTEM, 16) == 0) {
            return PART_TYPE_EFI_SYSTEM;
        }
    }
    
    return PART_TYPE_UNKNOWN;
}

Testing Strategy

Test MBR

# Create MBR disk with 2 partitions
dd if=/dev/zero of=test_mbr.img bs=1M count=100
parted test_mbr.img mklabel msdos
parted test_mbr.img mkpart primary fat32 1MiB 50MiB
parted test_mbr.img mkpart primary ext2 50MiB 100%

# Test parsing
hexdump -C test_mbr.img | head -n 32  # Check MBR structure

Test GPT

# Create GPT disk with 2 partitions
dd if=/dev/zero of=test_gpt.img bs=1M count=100
parted test_gpt.img mklabel gpt
parted test_gpt.img mkpart primary fat32 1MiB 50MiB
parted test_gpt.img mkpart primary ext2 50MiB 100%
parted test_gpt.img set 1 boot on

# Test parsing
hexdump -C test_gpt.img | head -n 64  # Check GPT header

Unit Tests

  • Parse valid MBR
  • Parse valid GPT
  • Detect invalid partition tables
  • Handle protective MBR for GPT
  • Identify partition types correctly
  • Handle empty partition slots
  • Validate sector ranges

Files to Create

  • src/kernel/fs/partition.c - Partition table parsing
  • src/kernel/fs/mbr.c - MBR-specific code
  • src/kernel/fs/gpt.c - GPT-specific code
  • include/kernel/fs/partition.h - Partition API
  • test/test_partition.c - Partition parsing tests

Deliverables

  • MBR parsing implementation
  • GPT parsing implementation
  • Unified partition API
  • Boot sequence integration
  • Unit tests
  • Documentation

Performance Goals

  • Partition detection < 10ms
  • Cached partition table (no re-parsing)
  • Minimal memory overhead

Error Handling

  • Validate partition table signatures
  • Check CRC32 for GPT
  • Validate partition sector ranges
  • Handle corrupted partition tables gracefully
  • Detect overlapping partitions

Related Issues

Current Status

Ready to Start - Block device driver complete, can begin implementation

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestkernelKernel-level implementation

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions