Skip to content

Implement partition table parsing (GPT and MBR) #420

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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