From: Tulio A M Mendes Date: Tue, 17 Feb 2026 08:01:55 +0000 (-0300) Subject: feat: /dev/hdX block device nodes and /proc/dmesg X-Git-Url: https://projects.tadryanom.me/docs/static/gitweb.js?a=commitdiff_plain;h=099db025ccdb1ab9f283e1a3f721c15dc4151953;p=AdrOS.git feat: /dev/hdX block device nodes and /proc/dmesg 1. ATA block devices in devfs: Detected ATA drives (hda, hdb, hdc, hdd) are now registered as block device nodes in /dev via ata_register_devfs(). Each node supports read/write at byte offsets (with sector-aligned I/O internally). Previously, drives were detected but invisible in /dev, so 'ls /dev' showed no disk devices and mount had to use ata_name_to_drive() internally. 2. /proc/dmesg: Added /proc/dmesg to procfs that reads the kprintf ring buffer via klog_read(). Uses heap allocation (16KB) to avoid kernel stack overflow. The 'dmesg' command now works correctly. --- diff --git a/src/drivers/ata_pio.c b/src/drivers/ata_pio.c index 62c7fd3..f15eacb 100644 --- a/src/drivers/ata_pio.c +++ b/src/drivers/ata_pio.c @@ -26,3 +26,6 @@ int ata_name_to_drive(const char* name) { (void)name; return -1; } __attribute__((weak)) const char* ata_drive_to_name(int drive) { (void)drive; return 0; } + +__attribute__((weak)) +void ata_register_devfs(void) { } diff --git a/src/hal/x86/ata_pio.c b/src/hal/x86/ata_pio.c index 93380ed..aaf65ec 100644 --- a/src/hal/x86/ata_pio.c +++ b/src/hal/x86/ata_pio.c @@ -263,6 +263,80 @@ int ata_pio_write28(int drive, uint32_t lba, const uint8_t* buf512) { return 0; } +/* --- Register detected ATA drives in devfs --- */ + +#include "devfs.h" + +static fs_node_t ata_dev_nodes[ATA_MAX_DRIVES]; + +static uint32_t ata_dev_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) { + int drive = (int)node->inode; + if (!buffer || size == 0) return 0; + + uint32_t lba = offset / 512; + uint32_t off_in_sect = offset % 512; + uint32_t total = 0; + uint8_t tmp[512]; + + while (total < size) { + if (ata_pio_read28(drive, lba, tmp) < 0) break; + uint32_t avail = 512 - off_in_sect; + uint32_t want = size - total; + if (want > avail) want = avail; + memcpy(buffer + total, tmp + off_in_sect, want); + total += want; + lba++; + off_in_sect = 0; + } + return total; +} + +static uint32_t ata_dev_write(fs_node_t* node, uint32_t offset, uint32_t size, const uint8_t* buffer) { + int drive = (int)node->inode; + if (!buffer || size == 0) return 0; + + uint32_t lba = offset / 512; + uint32_t off_in_sect = offset % 512; + uint32_t total = 0; + uint8_t tmp[512]; + + while (total < size) { + uint32_t want = size - total; + if (off_in_sect != 0 || want < 512) { + /* Read-modify-write for partial sector */ + if (ata_pio_read28(drive, lba, tmp) < 0) break; + uint32_t avail = 512 - off_in_sect; + if (want > avail) want = avail; + memcpy(tmp + off_in_sect, buffer + total, want); + } else { + want = 512; + memcpy(tmp, buffer + total, 512); + } + if (ata_pio_write28(drive, lba, tmp) < 0) break; + total += want; + lba++; + off_in_sect = 0; + } + return total; +} + +static const struct file_operations ata_dev_fops = { + .read = ata_dev_read, + .write = ata_dev_write, +}; + +void ata_register_devfs(void) { + for (int i = 0; i < ATA_MAX_DRIVES; i++) { + if (!drive_present[i]) continue; + memset(&ata_dev_nodes[i], 0, sizeof(fs_node_t)); + strcpy(ata_dev_nodes[i].name, drive_names[i]); + ata_dev_nodes[i].flags = FS_BLOCKDEVICE; + ata_dev_nodes[i].inode = (uint32_t)i; + ata_dev_nodes[i].f_ops = &ata_dev_fops; + devfs_register_device(&ata_dev_nodes[i]); + } +} + int ata_name_to_drive(const char* name) { if (!name) return -1; for (int i = 0; i < ATA_MAX_DRIVES; i++) { diff --git a/src/kernel/init.c b/src/kernel/init.c index 6291dbd..e29b2f8 100644 --- a/src/kernel/init.c +++ b/src/kernel/init.c @@ -254,6 +254,10 @@ int init_start(const struct boot_info* bi) { * (primary/secondary x master/slave). */ (void)ata_pio_init(); + /* Register detected ATA drives as /dev/hdX block device nodes */ + extern void ata_register_devfs(void); + ata_register_devfs(); + /* 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/procfs.c b/src/kernel/procfs.c index 05cb34e..607389f 100644 --- a/src/kernel/procfs.c +++ b/src/kernel/procfs.c @@ -16,6 +16,7 @@ static fs_node_t g_proc_self_status; static fs_node_t g_proc_uptime; static fs_node_t g_proc_meminfo; static fs_node_t g_proc_cmdline; +static fs_node_t g_proc_dmesg; #define PID_NODE_POOL 8 static fs_node_t g_pid_dir[PID_NODE_POOL]; @@ -81,6 +82,25 @@ static uint32_t proc_self_status_read(fs_node_t* node, uint32_t offset, uint32_t return size; } +extern size_t klog_read(char* out, size_t out_size); + +static uint32_t proc_dmesg_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) { + (void)node; + /* Allocate from heap — too large for kernel stack */ + char* tmp = kmalloc(16384); + if (!tmp) return 0; + size_t len = klog_read(tmp, 16384); + uint32_t ret = 0; + if (offset < (uint32_t)len) { + uint32_t avail = (uint32_t)len - offset; + if (size > avail) size = avail; + memcpy(buffer, tmp + offset, size); + ret = size; + } + kfree(tmp); + return ret; +} + static uint32_t proc_cmdline_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) { (void)node; const char* raw = cmdline_raw(); @@ -378,6 +398,7 @@ static fs_node_t* proc_root_finddir(fs_node_t* node, const char* name) { if (strcmp(name, "uptime") == 0) return &g_proc_uptime; if (strcmp(name, "meminfo") == 0) return &g_proc_meminfo; if (strcmp(name, "cmdline") == 0) return &g_proc_cmdline; + if (strcmp(name, "dmesg") == 0) return &g_proc_dmesg; if (is_numeric(name)) return proc_get_pid_dir(parse_uint(name)); return NULL; } @@ -390,8 +411,8 @@ static int proc_root_readdir(fs_node_t* node, uint32_t* inout_index, void* buf, uint32_t idx = *inout_index; struct vfs_dirent* d = (struct vfs_dirent*)buf; - static const char* fixed[] = { "self", "uptime", "meminfo", "cmdline" }; - if (idx < 4) { + static const char* fixed[] = { "self", "uptime", "meminfo", "cmdline", "dmesg" }; + if (idx < 5) { d->d_ino = 200 + idx; d->d_type = (idx == 0) ? FS_DIRECTORY : FS_FILE; d->d_reclen = sizeof(struct vfs_dirent); @@ -404,7 +425,7 @@ static int proc_root_readdir(fs_node_t* node, uint32_t* inout_index, void* buf, } /* After fixed entries, list numeric PIDs (under sched_lock) */ - uint32_t pi = idx - 4; + uint32_t pi = idx - 5; uint32_t count = 0; int found = 0; { @@ -468,6 +489,10 @@ static const struct file_operations procfs_cmdline_fops = { .read = proc_cmdline_read, }; +static const struct file_operations procfs_dmesg_fops = { + .read = proc_dmesg_read, +}; + static const struct file_operations procfs_pid_dir_fops = {0}; static const struct inode_operations procfs_pid_dir_iops = { @@ -520,5 +545,10 @@ fs_node_t* procfs_create_root(void) { g_proc_cmdline.flags = FS_FILE; g_proc_cmdline.f_ops = &procfs_cmdline_fops; + memset(&g_proc_dmesg, 0, sizeof(g_proc_dmesg)); + strcpy(g_proc_dmesg.name, "dmesg"); + g_proc_dmesg.flags = FS_FILE; + g_proc_dmesg.f_ops = &procfs_dmesg_fops; + return &g_proc_root; }