Sfoglia il codice sorgente

feat(node): impl. mknode

greatbridf 2 anni fa
parent
commit
e88af94e05
3 ha cambiato i file con 137 aggiunte e 32 eliminazioni
  1. 45 11
      include/kernel/vfs.h
  2. 92 18
      src/kernel/vfs.cpp
  3. 0 3
      src/kernel_main.c

+ 45 - 11
include/kernel/vfs.h

@@ -1,34 +1,50 @@
 #pragma once
 
+#include "types/stdint.h"
 #include <types/types.h>
 
+#define INODE_FILE (1 << 0)
+#define INODE_DIR (1 << 1)
+#define INODE_MNT (1 << 2)
+#define INODE_NODE (1 << 3)
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 struct inode;
-struct inode_flags;
+union inode_flags;
 struct inode_ops;
 struct stat;
 struct dirent;
+union special_node;
+struct special_node_ops;
 
 typedef size_t (*inode_read)(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n);
 typedef size_t (*inode_write)(struct inode* file, const char* buf, size_t offset, size_t n);
 typedef int (*inode_readdir)(struct inode* dir, struct dirent* entry, size_t i);
 typedef struct inode* (*inode_findinode)(struct inode* dir, const char* filename);
 typedef int (*inode_mkfile)(struct inode* dir, const char* filename);
+typedef int (*inode_mknode)(struct inode* dir, const char* filename, union special_node sn);
 typedef int (*inode_rmfile)(struct inode* dir, const char* filename);
 typedef int (*inode_mkdir)(struct inode* dir, const char* dirname);
 typedef int (*inode_stat)(struct inode* dir, struct stat* stat, const char* dirname);
 
+typedef size_t (*special_node_read)(char* buf, size_t buf_size, size_t offset, size_t n);
+typedef size_t (*special_node_write)(const char* buf, size_t offset, size_t n);
+
 typedef uint32_t ino_t;
 typedef uint32_t blksize_t;
 typedef uint32_t blkcnt_t;
 
-struct inode_flags {
-    uint32_t file : 1;
-    uint32_t directory : 1;
-    uint32_t mount_point : 1;
+union inode_flags {
+    uint32_t v;
+    struct {
+        uint32_t file : 1;
+        uint32_t directory : 1;
+        uint32_t mount_point : 1;
+        uint32_t special_node : 1;
+    } in;
 };
 
 struct inode_ops {
@@ -37,6 +53,7 @@ struct inode_ops {
     inode_readdir readdir;
     inode_findinode findinode;
     inode_mkfile mkfile;
+    inode_mknode mknode;
     inode_rmfile rmfile;
     inode_mkdir mkdir;
     inode_stat stat;
@@ -48,33 +65,50 @@ struct fs_info {
 };
 
 struct inode {
-    struct inode_flags flags;
+    union inode_flags flags;
     uint32_t perm;
     void* impl;
     ino_t ino;
     struct fs_info* fs;
 };
 
+struct dirent {
+    char name[128];
+    uint32_t ino;
+};
+
+union special_node {
+    uint32_t v;
+    struct {
+        uint32_t major : 16;
+        uint32_t minor : 16;
+    } in;
+};
+
+struct special_node_ops {
+    special_node_read read;
+    special_node_write write;
+};
+
 struct stat {
     ino_t st_ino;
+    union special_node st_rdev;
     blksize_t st_blksize;
     blkcnt_t st_blocks;
 };
 
-struct dirent {
-    char name[128];
-    uint32_t ino;
-};
-
 extern struct inode* fs_root;
 
 void init_vfs(void);
 
+void register_special_block(uint16_t major, uint16_t minor, special_node_read read, special_node_write write);
+
 size_t vfs_read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n);
 size_t vfs_write(struct inode* file, const char* buf, size_t offset, size_t n);
 int vfs_readdir(struct inode* dir, struct dirent* entry, size_t i);
 struct inode* vfs_findinode(struct inode* dir, const char* filename);
 int vfs_mkfile(struct inode* dir, const char* filename);
+int vfs_mknode(struct inode* dir, const char* filename, union special_node sn);
 int vfs_rmfile(struct inode* dir, const char* filename);
 int vfs_mkdir(struct inode* dir, const char* dirname);
 

+ 92 - 18
src/kernel/vfs.cpp

@@ -41,12 +41,10 @@ protected:
         return allocator_traits<kernel_allocator<vector<char>>>::allocate_and_construct();
     }
 
-    inline struct inode mk_inode(unsigned int dir, unsigned int file, unsigned int mnt, void* data)
+    inline struct inode mk_inode(union inode_flags flags, void* data)
     {
         struct inode i { };
-        i.flags.directory = dir;
-        i.flags.file = file;
-        i.flags.mount_point = mnt;
+        i.flags.v = flags.v;
         i.fs = &m_fs;
         i.impl = data;
         i.ino = m_last_inode_no++;
@@ -58,6 +56,7 @@ public:
     explicit tmpfs(size_t limit);
     void mklink(struct inode* dir, struct inode* inode, const char* filename);
     void mkfile(struct inode* dir, const char* filename);
+    void mknode(struct inode* dir, const char* filename, union special_node sn);
     void mkdir(struct inode* dir, const char* dirname);
     size_t read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n);
     size_t write(struct inode* file, const char* buf, size_t offset, size_t n);
@@ -97,6 +96,12 @@ int tmpfs_mkfile(struct inode* dir, const char* filename)
     fs->mkfile(dir, filename);
     return GB_OK;
 }
+int tmpfs_mknode(struct inode* dir, const char* filename, union special_node sn)
+{
+    auto* fs = static_cast<tmpfs*>(dir->fs->impl);
+    fs->mknode(dir, filename, sn);
+    return GB_OK;
+}
 // int tmpfs_rmfile(struct inode* dir, const char* filename)
 // {
 //     auto* fs = static_cast<tmpfs*>(dir->fs->impl);
@@ -121,6 +126,7 @@ static const struct inode_ops tmpfs_inode_ops = {
     .readdir = tmpfs_readdir,
     .findinode = tmpfs_findinode,
     .mkfile = tmpfs_mkfile,
+    .mknode = tmpfs_mknode,
     .rmfile = 0,
     .mkdir = tmpfs_mkdir,
     .stat = tmpfs_stat,
@@ -131,7 +137,7 @@ tmpfs::tmpfs(size_t limit)
     , m_fs { .ops = &tmpfs_inode_ops, .impl = this }
     , m_last_inode_no(0)
 {
-    struct inode in = mk_inode(1, 0, 1, mk_fe_vector());
+    struct inode in = mk_inode({ .v = INODE_DIR | INODE_MNT }, mk_fe_vector());
 
     mklink(&in, &in, ".");
     mklink(&in, &in, "..");
@@ -152,14 +158,21 @@ void tmpfs::mklink(struct inode* dir, struct inode* inode, const char* filename)
 
 void tmpfs::mkfile(struct inode* dir, const char* filename)
 {
-    struct inode file = mk_inode(0, 1, 0, mk_data_vector());
+    struct inode file = mk_inode({ .v = INODE_FILE }, mk_data_vector());
     m_inodes.push_back(file);
     mklink(dir, &file, filename);
 }
 
+void tmpfs::mknode(struct inode* dir, const char* filename, union special_node sn)
+{
+    struct inode node = mk_inode({ .v = INODE_NODE }, (void*)sn.v);
+    m_inodes.push_back(node);
+    mklink(dir, &node, filename);
+}
+
 void tmpfs::mkdir(struct inode* dir, const char* dirname)
 {
-    struct inode new_dir = mk_inode(1, 0, 0, mk_fe_vector());
+    struct inode new_dir = mk_inode({ .v = INODE_DIR }, mk_fe_vector());
     m_inodes.push_back(new_dir);
     mklink(&new_dir, &new_dir, ".");
 
@@ -169,7 +182,7 @@ void tmpfs::mkdir(struct inode* dir, const char* dirname)
 
 size_t tmpfs::read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
 {
-    if (file->flags.file != 1)
+    if (file->flags.in.file != 1)
         return 0;
 
     auto* data = static_cast<vector<char>*>(file->impl);
@@ -189,7 +202,7 @@ size_t tmpfs::read(struct inode* file, char* buf, size_t buf_size, size_t offset
 
 size_t tmpfs::write(struct inode* file, const char* buf, size_t offset, size_t n)
 {
-    if (file->flags.file != 1)
+    if (file->flags.in.file != 1)
         return 0;
 
     auto* data = static_cast<vector<char>*>(file->impl);
@@ -204,7 +217,7 @@ size_t tmpfs::write(struct inode* file, const char* buf, size_t offset, size_t n
 
 int tmpfs::readdir(struct inode* dir, struct dirent* entry, size_t i)
 {
-    if (dir->flags.directory != 1) {
+    if (dir->flags.in.directory != 1) {
         errno = ENOTDIR;
         return GB_FAILED;
     }
@@ -252,33 +265,57 @@ int tmpfs::stat(struct inode* dir, struct stat* stat, const char* filename)
     }
 
     stat->st_ino = file_inode->ino;
-    if (file_inode->flags.file) {
+    if (file_inode->flags.in.file) {
+        stat->st_rdev.v = 0;
         stat->st_blksize = 1;
         stat->st_blocks = static_cast<vector<char>*>(file_inode->impl)->size();
     }
-    if (file_inode->flags.directory) {
+    if (file_inode->flags.in.directory) {
+        stat->st_rdev.v = 0;
         stat->st_blksize = sizeof(struct tmpfs_file_entry);
         stat->st_blocks = static_cast<vector<struct tmpfs_file_entry>*>(file_inode->impl)->size();
     }
+    if (file_inode->flags.in.special_node) {
+        stat->st_rdev.v = (uint32_t)file_inode->impl;
+        stat->st_blksize = 0;
+        stat->st_blocks = 0;
+    }
 
     return GB_OK;
 }
 
+// 8 * 8 for now
+static struct special_node_ops sn_ops[8][8];
+
 size_t vfs_read(struct inode* file, char* buf, size_t buf_size, size_t offset, size_t n)
 {
-    if (file->fs->ops->read) {
-        return file->fs->ops->read(file, buf, buf_size, offset, n);
+    if (file->flags.in.special_node) {
+        union special_node sn {
+            .v = (uint32_t)file->impl
+        };
+        auto* ops = &sn_ops[sn.in.major][sn.in.minor];
+        if (ops)
+            return ops->read(buf, buf_size, offset, n);
     } else {
-        return 0;
+        if (file->fs->ops->read)
+            return file->fs->ops->read(file, buf, buf_size, offset, n);
     }
+    return 0;
 }
 size_t vfs_write(struct inode* file, const char* buf, size_t offset, size_t n)
 {
-    if (file->fs->ops->write) {
-        return file->fs->ops->write(file, buf, offset, n);
+    if (file->flags.in.special_node) {
+        union special_node sn {
+            .v = (uint32_t)file->impl
+        };
+        auto* ops = &sn_ops[sn.in.major][sn.in.minor];
+        if (ops)
+            return ops->write(buf, offset, n);
     } else {
-        return 0;
+        if (file->fs->ops->read)
+            return file->fs->ops->write(file, buf, offset, n);
     }
+    return 0;
 }
 int vfs_readdir(struct inode* dir, struct dirent* entry, size_t i)
 {
@@ -304,6 +341,14 @@ int vfs_mkfile(struct inode* dir, const char* filename)
         return 0;
     }
 }
+int vfs_mknode(struct inode* dir, const char* filename, union special_node sn)
+{
+    if (dir->fs->ops->mknode) {
+        return dir->fs->ops->mknode(dir, filename, sn);
+    } else {
+        return 0;
+    }
+}
 int vfs_rmfile(struct inode* dir, const char* filename)
 {
     if (dir->fs->ops->rmfile) {
@@ -400,8 +445,29 @@ int vfs_stat(struct stat* stat, const char* _path)
 struct inode* fs_root;
 static tmpfs* rootfs;
 
+void register_special_block(uint16_t major, uint16_t minor, special_node_read read, special_node_write write)
+{
+    sn_ops[major][minor].read = read;
+    sn_ops[major][minor].write = write;
+}
+
+size_t b_null_read(char* buf, size_t buf_size, size_t, size_t n)
+{
+    if (n >= buf_size)
+        n = buf_size;
+    memset(buf, 0x00, n);
+    return n;
+}
+size_t b_null_write(const char*, size_t, size_t n)
+{
+    return n;
+}
+
 void init_vfs(void)
 {
+    // null
+    register_special_block(0, 0, b_null_read, b_null_write);
+
     rootfs = allocator_traits<kernel_allocator<tmpfs>>::allocate_and_construct(4096 * 1024);
     fs_root = rootfs->root_inode();
 
@@ -413,9 +479,17 @@ void init_vfs(void)
     const char* str = "#/bin/sh\nexec /bin/sh\n";
     vfs_write(init, str, 0, strlen(str));
 
+    auto* dev = vfs_open("/dev");
+    vfs_mknode(dev, "null", { .in { .major = 0, .minor = 0 } });
+    vfs_mknode(dev, "console", { .in { .major = 1, .minor = 0 } });
+    vfs_mknode(dev, "hda", { .in { .major = 2, .minor = 0 } });
+
     struct stat _stat { };
 
     vfs_stat(&_stat, "/init");
     vfs_stat(&_stat, "/");
     vfs_stat(&_stat, "/dev");
+    vfs_stat(&_stat, "/dev/null");
+    vfs_stat(&_stat, "/dev/console");
+    vfs_stat(&_stat, "/dev/hda");
 }

+ 0 - 3
src/kernel_main.c

@@ -196,9 +196,6 @@ void NORETURN kernel_main(void)
 
     init_vfs();
 
-    struct inode* init = vfs_open("/init");
-    vfs_read(init, buf, 128, 1, 10);
-
     printkf("switching execution to the scheduler...\n");
     init_scheduler(&tss);
 }