]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: add /dev/zero, /dev/random, /dev/urandom, /dev/console device nodes
authorTulio A M Mendes <[email protected]>
Tue, 10 Feb 2026 12:31:13 +0000 (09:31 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 02:20:50 +0000 (23:20 -0300)
- /dev/zero: returns zeroes on read, discards writes
- /dev/random: xorshift32 PRNG seeded from PIT tick counter
- /dev/urandom: alias to /dev/random (same PRNG)
- /dev/console: aliases to TTY read/write (like /dev/tty)
- All registered in devfs finddir + readdir (8 devices total)
- cppcheck clean, 19/19 smoke tests pass

src/kernel/devfs.c

index 9bb782ada56cecc218654300219dd2836523344a..eec1583a1098f6febcf2ff8a528287083e4e513e 100644 (file)
@@ -5,18 +5,26 @@
 #include "pty.h"
 #include "utils.h"
 
+extern uint32_t get_tick_count(void);
+
 struct devfs_root {
     fs_node_t vfs;
 };
 
 static struct devfs_root g_dev_root;
 static fs_node_t g_dev_null;
+static fs_node_t g_dev_zero;
+static fs_node_t g_dev_random;
+static fs_node_t g_dev_urandom;
+static fs_node_t g_dev_console;
 static fs_node_t g_dev_tty;
 static fs_node_t g_dev_ptmx;
 static fs_node_t g_dev_pts_dir;
 static fs_node_t g_dev_pts0;
 static uint32_t g_devfs_inited = 0;
 
+static uint32_t prng_state = 0x12345678;
+
 static uint32_t dev_null_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
     (void)node;
     (void)offset;
@@ -32,6 +40,73 @@ static uint32_t dev_null_write(fs_node_t* node, uint32_t offset, uint32_t size,
     return size;
 }
 
+static uint32_t dev_zero_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+    (void)node;
+    (void)offset;
+    if (buffer && size > 0)
+        memset(buffer, 0, size);
+    return size;
+}
+
+static uint32_t dev_zero_write(fs_node_t* node, uint32_t offset, uint32_t size, const uint8_t* buffer) {
+    (void)node;
+    (void)offset;
+    (void)buffer;
+    return size;
+}
+
+static uint32_t prng_next(void) {
+    uint32_t s = prng_state;
+    s ^= s << 13;
+    s ^= s >> 17;
+    s ^= s << 5;
+    prng_state = s;
+    return s;
+}
+
+static uint32_t dev_random_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+    (void)node;
+    (void)offset;
+    if (!buffer || size == 0) return 0;
+    prng_state ^= get_tick_count();
+    for (uint32_t i = 0; i < size; i++) {
+        if ((i & 3) == 0) {
+            uint32_t r = prng_next();
+            buffer[i] = (uint8_t)(r & 0xFF);
+        } else {
+            buffer[i] = (uint8_t)((prng_next() >> ((i & 3) * 8)) & 0xFF);
+        }
+    }
+    return size;
+}
+
+static uint32_t dev_random_write(fs_node_t* node, uint32_t offset, uint32_t size, const uint8_t* buffer) {
+    (void)node;
+    (void)offset;
+    if (buffer && size >= 4) {
+        uint32_t seed = 0;
+        memcpy(&seed, buffer, 4);
+        prng_state ^= seed;
+    }
+    return size;
+}
+
+static uint32_t dev_console_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+    (void)node;
+    (void)offset;
+    int rc = tty_read_kbuf(buffer, size);
+    if (rc < 0) return 0;
+    return (uint32_t)rc;
+}
+
+static uint32_t dev_console_write(fs_node_t* node, uint32_t offset, uint32_t size, const uint8_t* buffer) {
+    (void)node;
+    (void)offset;
+    int rc = tty_write_kbuf((const uint8_t*)buffer, size);
+    if (rc < 0) return 0;
+    return (uint32_t)rc;
+}
+
 static uint32_t dev_tty_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
     (void)node;
     (void)offset;
@@ -85,6 +160,10 @@ static struct fs_node* devfs_finddir_impl(struct fs_node* node, const char* name
     if (!name || name[0] == 0) return 0;
 
     if (strcmp(name, "null") == 0) return &g_dev_null;
+    if (strcmp(name, "zero") == 0) return &g_dev_zero;
+    if (strcmp(name, "random") == 0) return &g_dev_random;
+    if (strcmp(name, "urandom") == 0) return &g_dev_urandom;
+    if (strcmp(name, "console") == 0) return &g_dev_console;
     if (strcmp(name, "tty") == 0) return &g_dev_tty;
     if (strcmp(name, "ptmx") == 0) return &g_dev_ptmx;
     if (strcmp(name, "pts") == 0) return &g_dev_pts_dir;
@@ -104,12 +183,16 @@ static int devfs_readdir_impl(struct fs_node* node, uint32_t* inout_index, void*
     if (buf_len < sizeof(struct vfs_dirent)) return -1;
 
     static const struct { const char* name; uint32_t ino; uint8_t type; } devs[] = {
-        { "null", 2, FS_CHARDEVICE },
-        { "tty",  3, FS_CHARDEVICE },
-        { "ptmx", 4, FS_CHARDEVICE },
-        { "pts",  5, FS_DIRECTORY },
+        { "null",    2,  FS_CHARDEVICE },
+        { "zero",    7,  FS_CHARDEVICE },
+        { "random",  8,  FS_CHARDEVICE },
+        { "urandom", 9,  FS_CHARDEVICE },
+        { "console", 10, FS_CHARDEVICE },
+        { "tty",     3,  FS_CHARDEVICE },
+        { "ptmx",    4,  FS_CHARDEVICE },
+        { "pts",     5,  FS_DIRECTORY },
     };
-    enum { NDEVS = 4 };
+    enum { NDEVS = 8 };
 
     uint32_t idx = *inout_index;
     uint32_t cap = buf_len / (uint32_t)sizeof(struct vfs_dirent);
@@ -203,6 +286,34 @@ static void devfs_init_once(void) {
     g_dev_null.close = 0;
     g_dev_null.finddir = 0;
 
+    memset(&g_dev_zero, 0, sizeof(g_dev_zero));
+    strcpy(g_dev_zero.name, "zero");
+    g_dev_zero.flags = FS_CHARDEVICE;
+    g_dev_zero.inode = 7;
+    g_dev_zero.read = &dev_zero_read;
+    g_dev_zero.write = &dev_zero_write;
+
+    memset(&g_dev_random, 0, sizeof(g_dev_random));
+    strcpy(g_dev_random.name, "random");
+    g_dev_random.flags = FS_CHARDEVICE;
+    g_dev_random.inode = 8;
+    g_dev_random.read = &dev_random_read;
+    g_dev_random.write = &dev_random_write;
+
+    memset(&g_dev_urandom, 0, sizeof(g_dev_urandom));
+    strcpy(g_dev_urandom.name, "urandom");
+    g_dev_urandom.flags = FS_CHARDEVICE;
+    g_dev_urandom.inode = 9;
+    g_dev_urandom.read = &dev_random_read;
+    g_dev_urandom.write = &dev_random_write;
+
+    memset(&g_dev_console, 0, sizeof(g_dev_console));
+    strcpy(g_dev_console.name, "console");
+    g_dev_console.flags = FS_CHARDEVICE;
+    g_dev_console.inode = 10;
+    g_dev_console.read = &dev_console_read;
+    g_dev_console.write = &dev_console_write;
+
     memset(&g_dev_tty, 0, sizeof(g_dev_tty));
     strcpy(g_dev_tty.name, "tty");
     g_dev_tty.flags = FS_CHARDEVICE;