From 61b888c27d8feab0c7cc81511ab7b7bf1948b7db Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Tue, 26 May 2026 00:56:35 -0300 Subject: [PATCH] partition: add MBR parser (Etapa 2) - Added mbr_partition_entry_t structure for 16-byte partition entries - Implemented partition_scan_mbr() to read and parse MBR sector - Validates MBR signature (0xAA55) at offset 510 - Parses 4 primary partition entries starting at offset 446 - Skips empty partitions (type 0) - Generates partition names (e.g. hda1, vda2) - Silently skips devices without valid MBR (no errors) - Tests: 124/124 PASS --- include/partition.h | 13 ++++++++ src/kernel/init.c | 4 +++ src/kernel/partition.c | 71 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/include/partition.h b/include/partition.h index 8990fba6..07bdf5fa 100644 --- a/include/partition.h +++ b/include/partition.h @@ -58,4 +58,17 @@ void partition_release(partition_t* part); /* Initialize partition subsystem lock */ void partition_init_lock(void); +/* MBR partition entry structure (16 bytes) */ +typedef struct __attribute__((packed)) { + uint8_t boot_indicator; + uint8_t chs_start[3]; + uint8_t partition_type; + uint8_t chs_end[3]; + uint32_t start_lba; + uint32_t sector_count; +} mbr_partition_entry_t; + +/* Scan a block device for MBR partitions and register them */ +int partition_scan_mbr(block_device_t* bdev); + #endif /* PARTITION_H */ diff --git a/src/kernel/init.c b/src/kernel/init.c index b004ab8b..2591986b 100644 --- a/src/kernel/init.c +++ b/src/kernel/init.c @@ -34,6 +34,7 @@ #include "ata_pio.h" #include "blockdev.h" +#include "partition.h" #include "hal/mm.h" #include "heap.h" #include "kernel/cmdline.h" @@ -290,6 +291,9 @@ int init_start(const struct boot_info* bi) { blockdev_init_lock(); blockdev_register_ata(); + /* Initialize partition subsystem (scan will be done later) */ + partition_init_lock(); + /* If root= is specified on the kernel command line, mount that device * as the disk root filesystem. The filesystem type is auto-detected * by trying each supported type in order. diff --git a/src/kernel/partition.c b/src/kernel/partition.c index 46b0eac3..51f59457 100644 --- a/src/kernel/partition.c +++ b/src/kernel/partition.c @@ -94,3 +94,74 @@ void partition_release(partition_t* part) { part->refcount--; spin_unlock_irqrestore(&g_partition_lock, flags); } + +/* MBR signature at offset 510-511 */ +#define MBR_SIGNATURE 0xAA55 + +int partition_scan_mbr(block_device_t* bdev) { + if (!bdev) return -EINVAL; + + /* Skip devices with unknown sector count (likely not present) */ + if (bdev->sector_count == 0) { + return 0; + } + + /* Read MBR sector (LBA 0) */ + uint8_t mbr_sector[512]; + int rc = blockdev_read(bdev, 0, mbr_sector); + if (rc < 0) { + return 0; + } + + /* Check MBR signature */ + uint16_t signature = *(uint16_t*)(mbr_sector + 510); + if (signature != MBR_SIGNATURE) { + return 0; + } + + /* Parse 4 primary partition entries (starting at offset 446) */ + mbr_partition_entry_t* entries = (mbr_partition_entry_t*)(mbr_sector + 446); + int partitions_found = 0; + + for (int i = 0; i < 4; i++) { + mbr_partition_entry_t* entry = &entries[i]; + + /* Skip empty partitions (type 0) */ + if (entry->partition_type == PART_TYPE_EMPTY) + continue; + + /* Create partition structure */ + partition_t part; + memset(&part, 0, sizeof(part)); + + part.parent = bdev; + part.start_lba = entry->start_lba; + part.sector_count = entry->sector_count; + part.partition_type = entry->partition_type; + part.partition_number = i + 1; /* 1-4 for primary partitions */ + part.refcount = 0; + + /* Generate partition name (e.g. "hda1", "vda2") */ + strcpy(part.name, bdev->name); + int name_len = strlen(part.name); + if (name_len < (int)sizeof(part.name) - 2) { + part.name[name_len] = '0' + (i + 1); + part.name[name_len + 1] = '\0'; + } + + /* Register the partition */ + rc = partition_register(&part); + if (rc < 0) { + continue; + } + + kprintf("[PARTITION] %s: type=0x%02X, start_lba=%u, sectors=%u\n", + part.name, part.partition_type, part.start_lba, part.sector_count); + partitions_found++; + } + + if (partitions_found > 0) { + kprintf("[PARTITION] Scanned %s: found %d partition(s)\n", bdev->name, partitions_found); + } + return partitions_found; +} -- 2.43.0