]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: /dev/hdX block device nodes and /proc/dmesg
authorTulio A M Mendes <[email protected]>
Tue, 17 Feb 2026 08:01:55 +0000 (05:01 -0300)
committerTulio A M Mendes <[email protected]>
Tue, 17 Feb 2026 08:01:55 +0000 (05:01 -0300)
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.

src/drivers/ata_pio.c
src/hal/x86/ata_pio.c
src/kernel/init.c
src/kernel/procfs.c

index 62c7fd3c9ec2d0afce78a33b38949f7b729739b4..f15eacbf0f37e38b95fedbdcf2a68773b737cf9a 100644 (file)
@@ -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) { }
index 93380ed0578298d7c0ca9cb06745f3bf41ed3bba..aaf65ecfa174f3a96bf41bb23381b5625114af9e 100644 (file)
@@ -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++) {
index 6291dbd2f19c6a50f287073b729c22c143c8f5d8..e29b2f8c2ca68d20901c8983ec7d75d96f30e118 100644 (file)
@@ -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.
index 05cb34e1ec0e989afec2fe329e29d8ab57d4ef84..607389fcf507f3d6546e20ccce1ef0abc68c97ce 100644 (file)
@@ -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;
 }