From: Tulio A M Mendes Date: Sat, 6 Jun 2026 18:05:02 +0000 (-0300) Subject: mount: resolve partitions in boot and mount paths X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=d0aa0da73843759e15e525a14e52b7a9238489ae;p=AdrOS.git mount: resolve partitions in boot and mount paths --- diff --git a/include/ata_pio.h b/include/ata_pio.h index 63dbeffc..fbb55505 100644 --- a/include/ata_pio.h +++ b/include/ata_pio.h @@ -36,6 +36,7 @@ int ata_pio_read28(int drive, uint32_t lba, uint8_t* buf512); int ata_pio_write28(int drive, uint32_t lba, const uint8_t* buf512); uint32_t ata_pio_sector_size(void); +uint32_t ata_pio_sector_count(int drive); /* Map device name ("hda".."hdd") to drive ID. Returns -1 if invalid. */ int ata_name_to_drive(const char* name); diff --git a/include/blockdev.h b/include/blockdev.h index edf38f5e..c5e9189c 100644 --- a/include/blockdev.h +++ b/include/blockdev.h @@ -46,6 +46,9 @@ block_device_t* blockdev_find(const char* name); /* Look up a block device by drive_id. Returns pointer or NULL. */ block_device_t* blockdev_by_id(int drive_id); +int blockdev_count(void); +block_device_t* blockdev_get(int index); + /* Increment block device refcount (called when filesystem mounts). */ void blockdev_claim(block_device_t* dev); diff --git a/include/kernel/init.h b/include/kernel/init.h index bbc1bcaa..98bbff13 100644 --- a/include/kernel/init.h +++ b/include/kernel/init.h @@ -16,6 +16,8 @@ int init_start(const struct boot_info* bi); +int init_resolve_mount_device(const char* device, struct block_device** bdev, uint32_t* lba); + /* Mount a filesystem on the given block device at the given mountpoint. * fstype: "fat", "ext2" * bdev: block device (from blockdev_find or blockdev_by_id) @@ -23,6 +25,6 @@ int init_start(const struct boot_info* bi); * mountpoint: e.g. "/disk", "/fat", "/ext2" * flags: mount flags (MS_RDONLY, etc.) — stored in VFS mount table * Returns 0 on success, negative errno on failure. */ -int init_mount_fs(const char* fstype, struct block_device* bdev, uint32_t lba, const char* mountpoint, unsigned long flags); +int init_mount_fs(const char* fstype, struct block_device* bdev, uint32_t lba, const char* mountpoint, unsigned long flags, const char* source_name); #endif diff --git a/src/drivers/ata_pio.c b/src/drivers/ata_pio.c index 97b5842f..ebbade6f 100644 --- a/src/drivers/ata_pio.c +++ b/src/drivers/ata_pio.c @@ -14,6 +14,9 @@ __attribute__((weak)) uint32_t ata_pio_sector_size(void) { return 512; } +__attribute__((weak)) +uint32_t ata_pio_sector_count(int drive) { (void)drive; return 0; } + __attribute__((weak)) int ata_pio_init(void) { return -ENOSYS; } diff --git a/src/hal/x86/ata_pio.c b/src/hal/x86/ata_pio.c index 2d4ab22a..ddede5ee 100644 --- a/src/hal/x86/ata_pio.c +++ b/src/hal/x86/ata_pio.c @@ -46,6 +46,7 @@ static const uint8_t ch_irq_vec[ATA_NUM_CHANNELS] = { 46, 47 }; /* Drive presence flags */ static int drive_present[ATA_MAX_DRIVES]; +static uint32_t drive_sector_count[ATA_MAX_DRIVES]; static int ata_pio_inited = 0; static const char* drive_names[ATA_MAX_DRIVES] = { "hda", "hdb", "hdc", "hdd" }; @@ -129,11 +130,20 @@ static int ata_probe_drive(int channel, int slave) { /* Wait for DRQ */ if (ata_wait_drq(io) < 0) return 0; - /* Read and discard 256 words of identify data */ + uint16_t identify[256]; for (int i = 0; i < 256; i++) { - (void)inw((uint16_t)(io + ATA_REG_DATA)); + identify[i] = inw((uint16_t)(io + ATA_REG_DATA)); } + uint32_t sectors = ((uint32_t)identify[61] << 16) | identify[60]; + if (sectors == 0) { + sectors = ((uint32_t)identify[103] << 16) | identify[102]; + if (sectors == 0) { + sectors = ((uint32_t)identify[101] << 16) | identify[100]; + } + } + drive_sector_count[channel * 2 + slave] = sectors; + return 1; } @@ -143,6 +153,11 @@ uint32_t ata_pio_sector_size(void) { return 512; } +uint32_t ata_pio_sector_count(int drive) { + if (drive < 0 || drive >= ATA_MAX_DRIVES) return 0; + return drive_sector_count[drive]; +} + int ata_pio_init(void) { if (ata_pio_inited) return 0; @@ -158,12 +173,15 @@ int ata_pio_init(void) { if (st == 0xFF) { drive_present[ch * 2] = 0; drive_present[ch * 2 + 1] = 0; + drive_sector_count[ch * 2] = 0; + drive_sector_count[ch * 2 + 1] = 0; continue; } for (int sl = 0; sl < 2; sl++) { int id = ch * 2 + sl; drive_present[id] = ata_probe_drive(ch, sl); + if (!drive_present[id]) drive_sector_count[id] = 0; if (drive_present[id]) found++; } diff --git a/src/kernel/blockdev.c b/src/kernel/blockdev.c index 5eae1a51..c3561ce4 100644 --- a/src/kernel/blockdev.c +++ b/src/kernel/blockdev.c @@ -75,6 +75,23 @@ block_device_t* blockdev_by_id(int drive_id) { return result; } +int blockdev_count(void) { + uintptr_t flags = spin_lock_irqsave(&g_blockdev_lock); + int count = g_blockdev_count; + spin_unlock_irqrestore(&g_blockdev_lock, flags); + return count; +} + +block_device_t* blockdev_get(int index) { + uintptr_t flags = spin_lock_irqsave(&g_blockdev_lock); + block_device_t* result = NULL; + if (index >= 0 && index < g_blockdev_count) { + result = &g_blockdevs[index]; + } + spin_unlock_irqrestore(&g_blockdev_lock, flags); + return result; +} + void blockdev_claim(block_device_t* dev) { if (!dev) return; uintptr_t flags = spin_lock_irqsave(&g_blockdev_lock); @@ -113,7 +130,7 @@ void blockdev_register_ata(void) { memset(&bd, 0, sizeof(bd)); strncpy(bd.name, names[i], sizeof(bd.name) - 1); bd.sector_size = 512; - bd.sector_count = 0; /* unknown */ + bd.sector_count = ata_pio_sector_count(i); bd.drive_id = i; bd.ops = &ata_bd_ops; blockdev_register(&bd); diff --git a/src/kernel/init.c b/src/kernel/init.c index 3c0fe7d3..f2140ad9 100644 --- a/src/kernel/init.c +++ b/src/kernel/init.c @@ -44,7 +44,61 @@ /* ---- Mount helper: used by fstab parser and kconsole 'mount' command ---- */ -int init_mount_fs(const char* fstype, block_device_t* bdev, uint32_t lba, const char* mountpoint, unsigned long flags) { +static void init_build_mount_source_name(const char* source_name, block_device_t* bdev, char* out, size_t out_size) { + if (!out || out_size == 0) return; + + if (source_name && source_name[0] != '\0') { + if (strncmp(source_name, "/dev/", 5) == 0) { + strncpy(out, source_name, out_size - 1); + out[out_size - 1] = '\0'; + return; + } + + strcpy(out, "/dev/"); + char* dp = out + 5; + const char* sp = source_name; + while (*sp && (size_t)(dp - out) < out_size - 1) + *dp++ = *sp++; + *dp = '\0'; + return; + } + + if (!bdev) { + strncpy(out, "none", out_size - 1); + out[out_size - 1] = '\0'; + return; + } + + strcpy(out, "/dev/"); + char* dp = out + 5; + const char* sp = bdev->name; + while (*sp && (size_t)(dp - out) < out_size - 1) + *dp++ = *sp++; + *dp = '\0'; +} + +int init_resolve_mount_device(const char* device, block_device_t** bdev, uint32_t* lba) { + if (!device || !bdev || !lba) return -EINVAL; + + const char* devname = device; + if (strncmp(devname, "/dev/", 5) == 0) devname += 5; + + block_device_t* resolved_bdev = blockdev_find(devname); + if (resolved_bdev) { + *bdev = resolved_bdev; + *lba = 0; + return 0; + } + + partition_t* part = partition_find(devname); + if (!part || !part->parent) return -ENODEV; + + *bdev = part->parent; + *lba = part->start_lba; + return 0; +} + +int init_mount_fs(const char* fstype, block_device_t* bdev, uint32_t lba, const char* mountpoint, unsigned long flags, const char* source_name) { /* Validate mountpoint exists and is a directory */ fs_node_t* mp_node = vfs_lookup(mountpoint); if (!mp_node) { @@ -62,10 +116,13 @@ int init_mount_fs(const char* fstype, block_device_t* bdev, uint32_t lba, const return -EINVAL; } + char devname[32]; + init_build_mount_source_name(source_name, bdev, devname, sizeof(devname)); + vfs_mount_result_t mres = fst->mount(bdev, lba); if (!mres.root) { kprintf("[MOUNT] Failed to mount %s on %s at %s\n", - fstype, bdev ? bdev->name : "?", + fstype, devname, mountpoint); return -ENODEV; } @@ -80,18 +137,6 @@ int init_mount_fs(const char* fstype, block_device_t* bdev, uint32_t lba, const blockdev_claim(bdev); } - /* Build device name for mount table metadata */ - char devname[32] = "none"; - if (bdev) { - strcpy(devname, "/dev/"); - /* Append device name after /dev/ */ - char* dp = devname + 5; - const char* dname = bdev->name; - while (*dname && (dp - devname) < (int)sizeof(devname) - 2) - *dp++ = *dname++; - *dp = '\0'; - } - int rc = vfs_mount_full(mountpoint, mres.root, fstype, devname, flags, bdev, mres.sb); if (rc < 0) { kprintf("[MOUNT] Failed to register mount at %s (err=%d)\n", mountpoint, rc); @@ -293,10 +338,8 @@ int init_start(const struct boot_info* bi) { /* Initialize partition subsystem and scan for partitions */ partition_init_lock(); - for (int i = 0; i < ATA_MAX_DRIVES; i++) { - if (!ata_pio_drive_present(i)) continue; - const char* names[ATA_MAX_DRIVES] = { "hda", "hdb", "hdc", "hdd" }; - block_device_t* bdev = blockdev_find(names[i]); + for (int i = 0; i < blockdev_count(); i++) { + block_device_t* bdev = blockdev_get(i); if (bdev) { partition_scan_mbr(bdev); } @@ -312,16 +355,14 @@ int init_start(const struct boot_info* bi) { * has disk access. /etc/fstab parsing is now done by /sbin/init. */ const char* root_dev = cmdline_get("root"); if (root_dev) { - const char* devname = root_dev; - if (strncmp(root_dev, "/dev/", 5) == 0) - devname = root_dev + 5; - block_device_t* bdev = blockdev_find(devname); - if (bdev) { + block_device_t* bdev = NULL; + uint32_t lba = 0; + if (init_resolve_mount_device(root_dev, &bdev, &lba) == 0) { /* Auto-detect: try ext2, then fat (non-destructive probes). */ static const char* fstypes[] = { "ext2", "fat", NULL }; int mounted = 0; for (int i = 0; fstypes[i]; i++) { - if (init_mount_fs(fstypes[i], bdev, 0, "/disk", 0) == 0) { + if (init_mount_fs(fstypes[i], bdev, lba, "/disk", 0, root_dev) == 0) { kprintf("[INIT] root=%s mounted as %s on /disk\n", root_dev, fstypes[i]); mounted = 1; @@ -339,7 +380,7 @@ int init_start(const struct boot_info* bi) { if (bdev) { static const char* fstypes[] = { "ext2", "fat", NULL }; for (int i = 0; fstypes[i]; i++) { - if (init_mount_fs(fstypes[i], bdev, 0, "/disk", 0) == 0) { + if (init_mount_fs(fstypes[i], bdev, 0, "/disk", 0, "/dev/hda") == 0) { kprintf("[INIT] /dev/hda auto-mounted as %s on /disk\n", fstypes[i]); break; } diff --git a/src/kernel/kconsole.c b/src/kernel/kconsole.c index 01af2357..336b0b78 100644 --- a/src/kernel/kconsole.c +++ b/src/kernel/kconsole.c @@ -362,18 +362,14 @@ static void kconsole_mount(const char* args) { return; } - /* Resolve device to block device */ - const char* devname = device; - if (strncmp(device, "/dev/", 5) == 0) { - devname = device + 5; - } - block_device_t* bdev = blockdev_find(devname); - if (!bdev) { + block_device_t* bdev = NULL; + uint32_t lba = 0; + if (init_resolve_mount_device(device, &bdev, &lba) < 0) { kprintf("mount: unknown device: %s\n", device); return; } - (void)init_mount_fs(fstype, bdev, 0, mountpoint, 0); + (void)init_mount_fs(fstype, bdev, lba, mountpoint, 0, device); } static void kconsole_exec(const char* cmd) { diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 9c6e74e8..fb98c29f 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -13,6 +13,7 @@ #include "process.h" #include "spinlock.h" #include "uaccess.h" +#include "kernel/init.h" #include "blockdev.h" #include "console.h" @@ -5290,15 +5291,14 @@ static void extended_syscall_dispatch(struct registers* regs, uint32_t syscall_n return; } - /* Disk-based: parse /dev/hdX -> block device */ - const char* devname = kdev; - if (strncmp(devname, "/dev/", 5) == 0) devname += 5; - extern block_device_t* blockdev_find(const char* name); - block_device_t* bdev = blockdev_find(devname); - if (!bdev) { sc_ret(regs) = (uint32_t)-ENODEV; return; } + block_device_t* bdev = NULL; + uint32_t lba = 0; + if (init_resolve_mount_device(kdev, &bdev, &lba) < 0) { + sc_ret(regs) = (uint32_t)-ENODEV; + return; + } - extern int init_mount_fs(const char* fstype, const block_device_t* bdev, uint32_t lba, const char* mountpoint, unsigned long flags); - int rc = init_mount_fs(ktype, bdev, 0, kmp, mount_flags); + int rc = init_mount_fs(ktype, bdev, lba, kmp, mount_flags, kdev); sc_ret(regs) = (uint32_t)(rc < 0 ? rc : 0); return; } diff --git a/tests/test_utils.c b/tests/test_utils.c index ea3163e9..5332f866 100644 --- a/tests/test_utils.c +++ b/tests/test_utils.c @@ -88,6 +88,37 @@ partition_t* partition_find_by_device(block_device_t* parent, uint8_t partition_ return NULL; } +static block_device_t g_test_bdev1 = {"hda", 512, 1024*1024, 0}; +static block_device_t g_test_bdev2 = {"vda", 512, 2048*1024, 1}; + +static block_device_t* blockdev_find(const char* name) { + if (!name) return NULL; + if (strcmp(name, g_test_bdev1.name) == 0) return &g_test_bdev1; + if (strcmp(name, g_test_bdev2.name) == 0) return &g_test_bdev2; + return NULL; +} + +static int init_resolve_mount_device_test(const char* device, block_device_t** bdev, uint32_t* lba) { + if (!device || !bdev || !lba) return -1; + + const char* devname = device; + if (strncmp(devname, "/dev/", 5) == 0) devname += 5; + + block_device_t* resolved_bdev = blockdev_find(devname); + if (resolved_bdev) { + *bdev = resolved_bdev; + *lba = 0; + return 0; + } + + partition_t* part = partition_find(devname); + if (!part || !part->parent) return -1; + + *bdev = part->parent; + *lba = part->start_lba; + return 0; +} + /* ---- Minimal test framework ---- */ static int g_tests_run = 0; static int g_tests_passed = 0; @@ -800,7 +831,6 @@ TEST(elf_null) { } /* ======== PARTITION LAYER TESTS ======== */ -static block_device_t g_test_bdev1 = {"hda", 512, 1024*1024, 0}; TEST(part_register_basic) { partition_registry_reset(); @@ -917,6 +947,48 @@ TEST(part_claim_release) { ASSERT_EQ(found->refcount, 0); } +TEST(resolve_mount_device_blockdev) { + partition_registry_reset(); + block_device_t* bdev = NULL; + uint32_t lba = 123; + ASSERT_EQ(init_resolve_mount_device_test("hda", &bdev, &lba), 0); + ASSERT_EQ(bdev, &g_test_bdev1); + ASSERT_EQ(lba, 0); +} + +TEST(resolve_mount_device_blockdev_devpath) { + partition_registry_reset(); + block_device_t* bdev = NULL; + uint32_t lba = 123; + ASSERT_EQ(init_resolve_mount_device_test("/dev/vda", &bdev, &lba), 0); + ASSERT_EQ(bdev, &g_test_bdev2); + ASSERT_EQ(lba, 0); +} + +TEST(resolve_mount_device_partition) { + partition_registry_reset(); + partition_t part; + memset(&part, 0, sizeof(part)); + part.parent = &g_test_bdev1; + part.start_lba = 2048; + part.partition_number = 1; + strcpy(part.name, "hda1"); + partition_register(&part); + + block_device_t* bdev = NULL; + uint32_t lba = 0; + ASSERT_EQ(init_resolve_mount_device_test("/dev/hda1", &bdev, &lba), 0); + ASSERT_EQ(bdev, &g_test_bdev1); + ASSERT_EQ(lba, 2048); +} + +TEST(resolve_mount_device_unknown) { + partition_registry_reset(); + block_device_t* bdev = NULL; + uint32_t lba = 0; + ASSERT_EQ(init_resolve_mount_device_test("/dev/doesnotexist", &bdev, &lba), -1); +} + /* ======== MAIN ======== */ int main(void) { printf("\n=========================================\n"); @@ -1017,6 +1089,10 @@ int main(void) { RUN(part_find_by_device); RUN(part_find_by_device_not_found); RUN(part_claim_release); + RUN(resolve_mount_device_blockdev); + RUN(resolve_mount_device_blockdev_devpath); + RUN(resolve_mount_device_partition); + RUN(resolve_mount_device_unknown); printf("\n %d/%d passed, %d failed\n", g_tests_passed, g_tests_run, g_tests_failed);