فهرست منبع

change: improve module arch. and fix some bugs

fix: open(".") should return exact the same dentry as cwd
fix: handle recursive mounts correctly

modules have a better definition syntax
greatbridf 7 ماه پیش
والد
کامیت
d75905e322
16فایلهای تغییر یافته به همراه201 افزوده شده و 151 حذف شده
  1. 1 1
      .gdbinit
  2. 3 2
      CMakeLists.txt
  3. 1 0
      gblibc/include/errno.h
  4. 23 20
      include/kernel/module.hpp
  5. 0 5
      include/kernel/vfs.hpp
  6. 3 2
      init_script.sh
  7. 71 0
      src/dev/builtin-chardev.cc
  8. 7 9
      src/fs/fat.cpp
  9. 18 23
      src/fs/procfs.cc
  10. 33 10
      src/fs/tmpfs.cc
  11. 6 9
      src/kernel/hw/ahci.cc
  12. 8 9
      src/kernel/hw/serial.cc
  13. 23 10
      src/kernel/module.cc
  14. 2 12
      src/kernel/process.cpp
  15. 2 35
      src/kernel/vfs.cpp
  16. 0 4
      src/kinit.cpp

+ 1 - 1
.gdbinit

@@ -7,5 +7,5 @@ symbol-file build/kernel.out
 target remote:1234
 target remote:1234
 
 
 # layout src
 # layout src
-b process.cpp:271
+b tmpfs::mkdir
 c
 c

+ 3 - 2
CMakeLists.txt

@@ -34,7 +34,9 @@ set(BOOTLOADER_SOURCES src/boot.s
                        src/asm/interrupt.s
                        src/asm/interrupt.s
                        )
                        )
 
 
-set(KERNEL_MAIN_SOURCES src/fs/fat.cpp
+set(KERNEL_MAIN_SOURCES src/dev/builtin-chardev.cc
+                        src/fs/fat.cpp
+                        src/fs/tmpfs.cc
                         src/fs/procfs.cc
                         src/fs/procfs.cc
                         src/kinit.cpp
                         src/kinit.cpp
                         src/kernel/async/waitlist.cc
                         src/kernel/async/waitlist.cc
@@ -64,7 +66,6 @@ set(KERNEL_MAIN_SOURCES src/fs/fat.cpp
                         src/kernel/vfs/dentry.cc
                         src/kernel/vfs/dentry.cc
                         src/kernel/vfs/filearr.cc
                         src/kernel/vfs/filearr.cc
                         src/kernel/vfs/inode.cc
                         src/kernel/vfs/inode.cc
-                        src/kernel/vfs/tmpfs.cc
                         src/kernel/vfs/vfs.cc
                         src/kernel/vfs/vfs.cc
                         src/kernel/signal.cpp
                         src/kernel/signal.cpp
                         src/types/elf.cpp
                         src/types/elf.cpp

+ 1 - 0
gblibc/include/errno.h

@@ -27,6 +27,7 @@ extern int* __errno_location(void);
 #define EINVAL 22
 #define EINVAL 22
 #define ENOTTY 25
 #define ENOTTY 25
 #define ESPIPE 29
 #define ESPIPE 29
+#define EROFS 30
 #define EPIPE 32
 #define EPIPE 32
 #define ELOOP 40
 #define ELOOP 40
 
 

+ 23 - 20
include/kernel/module.hpp

@@ -1,34 +1,37 @@
 #pragma once
 #pragma once
 
 
+#include <memory>
+
 #include <types/types.h>
 #include <types/types.h>
 
 
-#define INTERNAL_MODULE(name, func) \
-    SECTION(".kmods")               \
-    __attribute__((used)) kernel::module::module_loader const name = (func)
+#define MODULE_LOADER(name) \
+    static std::unique_ptr<kernel::kmod::kmod> __module##name##_loader()
+
+#define INTERNAL_MODULE(name, type)                                         \
+    MODULE_LOADER(name);                                                    \
+    SECTION(".kmods")                                                       \
+    __attribute__((used))                                                   \
+    std::unique_ptr<kernel::kmod::kmod> (*const __module##name##_entry)() = \
+        __module##name##_loader;                                            \
+    MODULE_LOADER(name) {                                                   \
+        return std::make_unique<type>();                                    \
+    }
 
 
-namespace kernel::module {
+namespace kernel::kmod {
 
 
-struct module {
+struct kmod {
     const char* const name;
     const char* const name;
 
 
-    explicit module(const char* name);
+    explicit kmod(const char* name);
 
 
-    virtual ~module() = default;
-    module(const module&) = delete;
-    module& operator=(const module&) = delete;
+    virtual ~kmod() = default;
+    kmod(const kmod&) = delete;
+    kmod& operator=(const kmod&) = delete;
 
 
     virtual int init() = 0;
     virtual int init() = 0;
 };
 };
 
 
-using module_loader = module* (*)();
-
-constexpr int MODULE_SUCCESS = 0;
-constexpr int MODULE_FAILED = 1;
-constexpr int MODULE_DELAYED = 2;
-
-// TODO: unique_ptr and Deleter
-int insmod(module* mod);
-
-extern "C" module_loader KMOD_LOADERS_START[];
+extern "C" std::unique_ptr<kmod> (*const KMOD_LOADERS_START[])();
+void load_internal_modules();
 
 
-} // namespace kernel::module
+} // namespace kernel::kmod

+ 0 - 5
include/kernel/vfs.hpp

@@ -89,9 +89,6 @@ using create_fs_func_t =
 
 
 int register_fs(const char* name, create_fs_func_t);
 int register_fs(const char* name, create_fs_func_t);
 
 
-// in tmpfs.cc
-int register_tmpfs();
-
 void partprobe();
 void partprobe();
 
 
 ssize_t block_device_read(dev_t node, char* buf, size_t buf_size, size_t offset,
 ssize_t block_device_read(dev_t node, char* buf, size_t buf_size, size_t offset,
@@ -127,5 +124,3 @@ std::pair<dentry_pointer, int> open(const fs_context& context, dentry* cwd,
                                     int recurs_no = 0);
                                     int recurs_no = 0);
 
 
 } // namespace fs
 } // namespace fs
-
-extern "C" void init_vfs(void);

+ 3 - 2
init_script.sh

@@ -4,8 +4,9 @@ BUSYBOX=/mnt/busybox
 
 
 $BUSYBOX mkdir -p /dev
 $BUSYBOX mkdir -p /dev
 
 
-$BUSYBOX mknod -m 666 /dev/console c 2 0
-$BUSYBOX mknod -m 666 /dev/null c 1 0
+$BUSYBOX mknod -m 666 /dev/console c 5 1
+$BUSYBOX mknod -m 666 /dev/null c 1 3
+$BUSYBOX mknod -m 666 /dev/zero c 1 5
 $BUSYBOX mknod -m 666 /dev/sda b 8 0
 $BUSYBOX mknod -m 666 /dev/sda b 8 0
 $BUSYBOX mknod -m 666 /dev/sda1 b 8 1
 $BUSYBOX mknod -m 666 /dev/sda1 b 8 1
 
 

+ 71 - 0
src/dev/builtin-chardev.cc

@@ -0,0 +1,71 @@
+#include <kernel/module.hpp>
+#include <kernel/tty.hpp>
+#include <kernel/vfs.hpp>
+
+using namespace kernel::kmod;
+using namespace kernel::tty;
+
+static ssize_t null_read(char*, size_t, size_t) {
+    return 0;
+}
+
+static ssize_t null_write(const char*, size_t n) {
+    return n;
+}
+
+static ssize_t zero_read(char* buf, size_t buf_size, size_t n) {
+    if (n > buf_size)
+        n = buf_size;
+
+    memset(buf, 0, n);
+    return n;
+}
+
+static ssize_t zero_write(const char*, size_t n) {
+    return n;
+}
+
+// TODO: add interface to bind console device to other devices
+ssize_t console_read(char* buf, size_t buf_size, size_t n) {
+    return console->read(buf, buf_size, n);
+}
+
+ssize_t console_write(const char* buf, size_t n) {
+    size_t orig_n = n;
+    while (n--)
+        console->putchar(*(buf++));
+
+    return orig_n;
+}
+
+class builtin_chardev : public virtual kmod {
+   public:
+    builtin_chardev() : kmod("builtin-chardev") {}
+    int init() override {
+        using namespace fs;
+        // null
+        chrdev_ops null_ops{
+            .read = null_read,
+            .write = null_write,
+        };
+        register_char_device(make_device(1, 3), null_ops);
+
+        // zero
+        chrdev_ops zero_ops{
+            .read = zero_read,
+            .write = zero_write,
+        };
+        register_char_device(make_device(1, 5), zero_ops);
+
+        // console
+        chrdev_ops console_ops{
+            .read = console_read,
+            .write = console_write,
+        };
+        register_char_device(make_device(5, 1), console_ops);
+
+        return 0;
+    }
+};
+
+INTERNAL_MODULE(builtin_chardev, builtin_chardev);

+ 7 - 9
src/fs/fat.cpp

@@ -17,6 +17,8 @@
 #define VFAT_FILENAME_LOWERCASE (0x08)
 #define VFAT_FILENAME_LOWERCASE (0x08)
 #define VFAT_EXTENSION_LOWERCASE (0x10)
 #define VFAT_EXTENSION_LOWERCASE (0x10)
 
 
+using namespace kernel::kmod;
+
 namespace fs::fat {
 namespace fs::fat {
 
 
 // buf MUST be larger than 512 bytes
 // buf MUST be larger than 512 bytes
@@ -236,9 +238,9 @@ static fat32* create_fat32(const char* source, unsigned long, const void*) {
     return new fat32(fs::make_device(8, 1));
     return new fat32(fs::make_device(8, 1));
 }
 }
 
 
-class fat32_module : public virtual kernel::module::module {
+class fat32_module : public virtual kmod {
    public:
    public:
-    fat32_module() : module("fat32") {}
+    fat32_module() : kmod("fat32") {}
     ~fat32_module() {
     ~fat32_module() {
         // TODO: unregister filesystem
         // TODO: unregister filesystem
     }
     }
@@ -247,16 +249,12 @@ class fat32_module : public virtual kernel::module::module {
         int ret = fs::register_fs("fat32", create_fat32);
         int ret = fs::register_fs("fat32", create_fat32);
 
 
         if (ret != 0)
         if (ret != 0)
-            return kernel::module::MODULE_FAILED;
+            return ret;
 
 
-        return kernel::module::MODULE_SUCCESS;
+        return 0;
     }
     }
 };
 };
 
 
 } // namespace fs::fat
 } // namespace fs::fat
 
 
-static kernel::module::module* fat32_module_init() {
-    return new fs::fat::fat32_module;
-}
-
-INTERNAL_MODULE(fat32_module_loader, fat32_module_init);
+INTERNAL_MODULE(fat32, fs::fat::fat32_module);

+ 18 - 23
src/fs/procfs.cc

@@ -11,6 +11,8 @@
 #include <kernel/vfs.hpp>
 #include <kernel/vfs.hpp>
 #include <kernel/vfs/vfs.hpp>
 #include <kernel/vfs/vfs.hpp>
 
 
+using namespace kernel::kmod;
+
 struct mount_flags_opt {
 struct mount_flags_opt {
     unsigned long flag;
     unsigned long flag;
     const char* name;
     const char* name;
@@ -97,6 +99,17 @@ class procfs : public virtual fs::vfs {
 
 
     ino_t free_ino = 1;
     ino_t free_ino = 1;
 
 
+    procfs(const char* _source)
+        : vfs(make_device(0, 10), 4096), source{_source} {
+        auto* ind = alloc_inode(0);
+        ind->mode = S_IFDIR | 0777;
+
+        create_file("mounts", mounts_read, nullptr);
+        create_file("schedstat", schedstat_read, nullptr);
+
+        register_root_node(ind);
+    }
+
    public:
    public:
     static procfs* create(const char* source, unsigned long, const void*) {
     static procfs* create(const char* source, unsigned long, const void*) {
         // TODO: flags
         // TODO: flags
@@ -116,17 +129,6 @@ class procfs : public virtual fs::vfs {
         return inserted ? 0 : -EEXIST;
         return inserted ? 0 : -EEXIST;
     }
     }
 
 
-    procfs(const char* _source)
-        : vfs(make_device(0, 10), 4096), source{_source} {
-        auto* ind = alloc_inode(0);
-        ind->mode = S_IFDIR | 0777;
-
-        create_file("mounts", mounts_read, nullptr);
-        create_file("schedstat", schedstat_read, nullptr);
-
-        register_root_node(ind);
-    }
-
     ssize_t read(inode* file, char* buf, size_t buf_size, size_t n,
     ssize_t read(inode* file, char* buf, size_t buf_size, size_t n,
                  off_t offset) override {
                  off_t offset) override {
         if (file->ino == 0)
         if (file->ino == 0)
@@ -185,22 +187,15 @@ class procfs : public virtual fs::vfs {
     }
     }
 };
 };
 
 
-class procfs_module : public virtual kernel::module::module {
+class procfs_module : public virtual kmod {
    public:
    public:
-    procfs_module() : module("procfs") {}
+    procfs_module() : kmod("procfs") {}
 
 
     virtual int init() override {
     virtual int init() override {
-        int ret = fs::register_fs("procfs", procfs::create);
-        if (ret != 0)
-            return kernel::module::MODULE_FAILED;
-        return kernel::module::MODULE_SUCCESS;
+        return fs::register_fs("procfs", procfs::create);
     }
     }
 };
 };
 
 
-static kernel::module::module* procfs_init() {
-    return new procfs_module;
-}
-
-INTERNAL_MODULE(procfs, procfs_init);
-
 } // namespace fs::proc
 } // namespace fs::proc
+
+INTERNAL_MODULE(procfs, fs::proc::procfs_module);

+ 33 - 10
src/kernel/vfs/tmpfs.cc → src/fs/tmpfs.cc

@@ -4,8 +4,10 @@
 
 
 #include <assert.h>
 #include <assert.h>
 #include <stdint.h>
 #include <stdint.h>
+#include <sys/mount.h>
 
 
 #include <kernel/log.hpp>
 #include <kernel/log.hpp>
+#include <kernel/module.hpp>
 #include <kernel/vfs.hpp>
 #include <kernel/vfs.hpp>
 
 
 using namespace fs;
 using namespace fs;
@@ -23,6 +25,7 @@ class tmpfs : public virtual vfs {
 
 
    private:
    private:
     ino_t m_next_ino;
     ino_t m_next_ino;
+    bool m_readonly;
 
 
    private:
    private:
     ino_t assign_ino() { return m_next_ino++; }
     ino_t assign_ino() { return m_next_ino++; }
@@ -62,8 +65,10 @@ class tmpfs : public virtual vfs {
         return nread;
         return nread;
     }
     }
 
 
-   public:
-    explicit tmpfs() : vfs(make_device(0, 2), 4096), m_next_ino{1} {
+    explicit tmpfs(unsigned long flags)
+        : vfs(make_device(0, 2), 4096)
+        , m_next_ino{1}
+        , m_readonly(flags & MS_RDONLY) {
         auto* in = alloc_inode(assign_ino());
         auto* in = alloc_inode(assign_ino());
 
 
         in->fs_data = make_vfe();
         in->fs_data = make_vfe();
@@ -75,6 +80,11 @@ class tmpfs : public virtual vfs {
         register_root_node(in);
         register_root_node(in);
     }
     }
 
 
+   public:
+    static tmpfs* create(const char*, unsigned long flags, const void*) {
+        return new tmpfs(flags);
+    }
+
     virtual ssize_t read(struct inode* file, char* buf, size_t buf_size,
     virtual ssize_t read(struct inode* file, char* buf, size_t buf_size,
                          size_t count, off_t offset) override {
                          size_t count, off_t offset) override {
         if (!S_ISREG(file->mode))
         if (!S_ISREG(file->mode))
@@ -97,6 +107,8 @@ class tmpfs : public virtual vfs {
 
 
     virtual ssize_t write(struct inode* file, const char* buf, size_t count,
     virtual ssize_t write(struct inode* file, const char* buf, size_t count,
                           off_t offset) override {
                           off_t offset) override {
+        if (m_readonly)
+            return -EROFS;
         if (!S_ISREG(file->mode))
         if (!S_ISREG(file->mode))
             return -EINVAL;
             return -EINVAL;
 
 
@@ -113,6 +125,8 @@ class tmpfs : public virtual vfs {
 
 
     virtual int creat(struct inode* dir, struct dentry* at,
     virtual int creat(struct inode* dir, struct dentry* at,
                       mode_t mode) override {
                       mode_t mode) override {
+        if (m_readonly)
+            return -EROFS;
         if (!S_ISDIR(dir->mode))
         if (!S_ISDIR(dir->mode))
             return -ENOTDIR;
             return -ENOTDIR;
         assert(at->parent && at->parent->inode == dir);
         assert(at->parent && at->parent->inode == dir);
@@ -130,6 +144,8 @@ class tmpfs : public virtual vfs {
 
 
     virtual int mknod(struct inode* dir, struct dentry* at, mode_t mode,
     virtual int mknod(struct inode* dir, struct dentry* at, mode_t mode,
                       dev_t dev) override {
                       dev_t dev) override {
+        if (m_readonly)
+            return -EROFS;
         if (!S_ISDIR(dir->mode))
         if (!S_ISDIR(dir->mode))
             return -ENOTDIR;
             return -ENOTDIR;
         assert(at->parent && at->parent->inode == dir);
         assert(at->parent && at->parent->inode == dir);
@@ -153,6 +169,8 @@ class tmpfs : public virtual vfs {
 
 
     virtual int mkdir(struct inode* dir, struct dentry* at,
     virtual int mkdir(struct inode* dir, struct dentry* at,
                       mode_t mode) override {
                       mode_t mode) override {
+        if (m_readonly)
+            return -EROFS;
         if (!S_ISDIR(dir->mode))
         if (!S_ISDIR(dir->mode))
             return -ENOTDIR;
             return -ENOTDIR;
         assert(at->parent && at->parent->inode == dir);
         assert(at->parent && at->parent->inode == dir);
@@ -173,6 +191,8 @@ class tmpfs : public virtual vfs {
 
 
     virtual int symlink(struct inode* dir, struct dentry* at,
     virtual int symlink(struct inode* dir, struct dentry* at,
                         const char* target) override {
                         const char* target) override {
+        if (m_readonly)
+            return -EROFS;
         if (!S_ISDIR(dir->mode))
         if (!S_ISDIR(dir->mode))
             return -ENOTDIR;
             return -ENOTDIR;
         assert(at->parent && at->parent->inode == dir);
         assert(at->parent && at->parent->inode == dir);
@@ -209,6 +229,8 @@ class tmpfs : public virtual vfs {
     }
     }
 
 
     virtual int unlink(struct inode* dir, struct dentry* at) override {
     virtual int unlink(struct inode* dir, struct dentry* at) override {
+        if (m_readonly)
+            return -EROFS;
         if (!S_ISDIR(dir->mode))
         if (!S_ISDIR(dir->mode))
             return -ENOTDIR;
             return -ENOTDIR;
         assert(at->parent && at->parent->inode == dir);
         assert(at->parent && at->parent->inode == dir);
@@ -253,6 +275,8 @@ class tmpfs : public virtual vfs {
     }
     }
 
 
     virtual int truncate(inode* file, size_t size) override {
     virtual int truncate(inode* file, size_t size) override {
+        if (m_readonly)
+            return -EROFS;
         if (!S_ISREG(file->mode))
         if (!S_ISREG(file->mode))
             return -EINVAL;
             return -EINVAL;
 
 
@@ -263,12 +287,11 @@ class tmpfs : public virtual vfs {
     }
     }
 };
 };
 
 
-static tmpfs* create_tmpfs(const char*, unsigned long, const void*) {
-    // TODO: flags
-    return new tmpfs;
-}
+class tmpfs_module : public virtual kernel::kmod::kmod {
+   public:
+    tmpfs_module() : kmod{"tmpfs"} {}
+
+    int init() override { return fs::register_fs("tmpfs", tmpfs::create); }
+};
 
 
-int fs::register_tmpfs() {
-    fs::register_fs("tmpfs", {create_tmpfs});
-    return 0;
-}
+INTERNAL_MODULE(tmpfs, tmpfs_module);

+ 6 - 9
src/kernel/hw/ahci.cc

@@ -19,7 +19,7 @@
         ++(spin);                        \
         ++(spin);                        \
     if ((spin) == MAX_SPINS)
     if ((spin) == MAX_SPINS)
 
 
-using namespace kernel::module;
+using namespace kernel::kmod;
 using namespace kernel::hw::pci;
 using namespace kernel::hw::pci;
 using namespace kernel::mem::paging;
 using namespace kernel::mem::paging;
 
 
@@ -432,14 +432,14 @@ struct ahci_port {
     }
     }
 };
 };
 
 
-class ahci_module : public virtual kernel::module::module {
+class ahci_module : public virtual kmod {
    private:
    private:
     hba_ghc* ghc{};
     hba_ghc* ghc{};
     pci_device* dev{};
     pci_device* dev{};
     std::vector<ahci_port*> ports;
     std::vector<ahci_port*> ports;
 
 
    public:
    public:
-    ahci_module() : module("ahci") {}
+    ahci_module() : kmod("ahci") {}
     ~ahci_module() {
     ~ahci_module() {
         // TODO: release PCI device
         // TODO: release PCI device
         for (auto& item : ports) {
         for (auto& item : ports) {
@@ -501,14 +501,11 @@ class ahci_module : public virtual kernel::module::module {
             });
             });
 
 
         if (ret != 0)
         if (ret != 0)
-            return MODULE_FAILED;
-        return MODULE_SUCCESS;
+            return ret;
+        return 0;
     }
     }
 };
 };
 
 
 } // namespace ahci
 } // namespace ahci
 
 
-kernel::module::module* ahci_module_init() {
-    return new ahci::ahci_module();
-}
-INTERNAL_MODULE(ahci_module_loader, ahci_module_init);
+INTERNAL_MODULE(ahci, ahci::ahci_module);

+ 8 - 9
src/kernel/hw/serial.cc

@@ -9,6 +9,8 @@
 
 
 using namespace kernel::tty;
 using namespace kernel::tty;
 using namespace kernel::hw;
 using namespace kernel::hw;
+using namespace kernel::irq;
+using namespace kernel::kmod;
 
 
 constexpr int PORT0 = 0x3f8;
 constexpr int PORT0 = 0x3f8;
 constexpr int PORT1 = 0x2f8;
 constexpr int PORT1 = 0x2f8;
@@ -79,14 +81,14 @@ class serial_tty : public virtual tty {
     }
     }
 };
 };
 
 
-class serial_module : public virtual kernel::module::module {
+class serial_module : public virtual kmod {
    public:
    public:
-    serial_module() : module("serial-tty") {}
+    serial_module() : kmod("serial-tty") {}
 
 
     virtual int init() override {
     virtual int init() override {
         if (int ret = _init_port(port0); ret == 0) {
         if (int ret = _init_port(port0); ret == 0) {
             auto* dev = new serial_tty(port0, 0);
             auto* dev = new serial_tty(port0, 0);
-            kernel::irq::register_handler(4, _serial0_receive_data_interrupt);
+            register_handler(4, _serial0_receive_data_interrupt);
 
 
             if (int ret = register_tty(dev); ret != 0)
             if (int ret = register_tty(dev); ret != 0)
                 kmsg("[serial] cannot register ttyS0");
                 kmsg("[serial] cannot register ttyS0");
@@ -94,17 +96,14 @@ class serial_module : public virtual kernel::module::module {
 
 
         if (int ret = _init_port(port1); ret == 0) {
         if (int ret = _init_port(port1); ret == 0) {
             auto* dev = new serial_tty(port1, 0);
             auto* dev = new serial_tty(port1, 0);
-            kernel::irq::register_handler(3, _serial1_receive_data_interrupt);
+            register_handler(3, _serial1_receive_data_interrupt);
 
 
             if (int ret = register_tty(dev); ret != 0)
             if (int ret = register_tty(dev); ret != 0)
                 kmsg("[serial] cannot register ttyS1");
                 kmsg("[serial] cannot register ttyS1");
         }
         }
 
 
-        return kernel::module::MODULE_SUCCESS;
+        return 0;
     }
     }
 };
 };
 
 
-kernel::module::module* serial_module_init() {
-    return new serial_module();
-}
-INTERNAL_MODULE(serial_module_loader, serial_module_init);
+INTERNAL_MODULE(serial, serial_module);

+ 23 - 10
src/kernel/module.cc

@@ -1,18 +1,31 @@
+#include <map>
+
+#include <assert.h>
+
+#include <kernel/log.hpp>
 #include <kernel/module.hpp>
 #include <kernel/module.hpp>
 
 
-namespace kernel::module {
+namespace kernel::kmod {
 
 
-module::module(const char* name) :name(name) {}
+kmod::kmod(const char* name) : name(name) {}
 
 
-int insmod(module* mod) {
-    int ret = mod->init();
+static std::map<std::string, std::unique_ptr<kmod>> modules;
 
 
-    if (ret == MODULE_FAILED) {
-        delete mod;
-        return MODULE_FAILED;
-    }
+void load_internal_modules() {
+    for (auto loader = KMOD_LOADERS_START; *loader; ++loader) {
+        auto mod = (*loader)();
+        if (!mod)
+            continue;
 
 
-    return MODULE_SUCCESS;
+        if (int ret = mod->init(); ret != 0) {
+            kmsgf("[kernel] An error(%x) occured while loading \"%s\"", ret,
+                  mod->name);
+            continue;
+        }
+
+        auto [_, inserted] = modules.try_emplace(mod->name, std::move(mod));
+        assert(inserted);
+    }
 }
 }
 
 
-} // namespace kernel::module
+} // namespace kernel::kmod

+ 2 - 12
src/kernel/process.cpp

@@ -208,6 +208,8 @@ void NORETURN _kernel_init(kernel::mem::paging::pfn_t kernel_stack_pfn) {
     kernel::mem::paging::free_pages(kernel_stack_pfn, 9);
     kernel::mem::paging::free_pages(kernel_stack_pfn, 9);
     release_kinit();
     release_kinit();
 
 
+    kernel::kmod::load_internal_modules();
+
     asm volatile("sti");
     asm volatile("sti");
 
 
     // mount rootfs
     // mount rootfs
@@ -226,18 +228,6 @@ void NORETURN _kernel_init(kernel::mem::paging::pfn_t kernel_stack_pfn) {
     // interrupt enabled
     // interrupt enabled
     // ------------------------------------------
     // ------------------------------------------
 
 
-    // load kmods
-    for (auto loader = kernel::module::KMOD_LOADERS_START; *loader; ++loader) {
-        auto* mod = (*loader)();
-        if (!mod)
-            continue;
-
-        if (auto ret = insmod(mod); ret == kernel::module::MODULE_SUCCESS)
-            continue;
-
-        kmsgf("[kernel] An error occured while loading \"%s\"", mod->name);
-    }
-
     const auto& context = current_process->fs_context;
     const auto& context = current_process->fs_context;
 
 
     // mount fat32 /mnt directory
     // mount fat32 /mnt directory

+ 2 - 35
src/kernel/vfs.cpp

@@ -259,7 +259,7 @@ std::pair<fs::dentry_pointer, int> fs::open(const fs_context& context,
 
 
     for (; path; ++path) {
     for (; path; ++path) {
         auto item = *path;
         auto item = *path;
-        if (item.empty())
+        if (item.empty() || item == ".")
             continue;
             continue;
 
 
         if (!(cwd->flags & D_PRESENT))
         if (!(cwd->flags & D_PRESENT))
@@ -286,7 +286,7 @@ std::pair<fs::dentry_pointer, int> fs::open(const fs_context& context,
                 return {nullptr, status};
                 return {nullptr, status};
         }
         }
 
 
-        if (cwd->flags & D_MOUNTPOINT) {
+        while (cwd->flags & D_MOUNTPOINT) {
             auto iter = mounts.find(cwd.get());
             auto iter = mounts.find(cwd.get());
             assert(iter);
             assert(iter);
 
 
@@ -518,26 +518,6 @@ ssize_t fs::char_device_write(dev_t node, const char* buf, size_t n) {
     return write(buf, n);
     return write(buf, n);
 }
 }
 
 
-ssize_t b_null_read(char*, size_t, size_t) {
-    return 0;
-}
-
-ssize_t b_null_write(const char*, size_t n) {
-    return n;
-}
-
-static ssize_t console_read(char* buf, size_t buf_size, size_t n) {
-    return kernel::tty::console->read(buf, buf_size, n);
-}
-
-static ssize_t console_write(const char* buf, size_t n) {
-    size_t orig_n = n;
-    while (n--)
-        kernel::tty::console->putchar(*(buf++));
-
-    return orig_n;
-}
-
 fs::pipe::pipe(void) : buf{PIPE_SIZE}, flags{READABLE | WRITABLE} {}
 fs::pipe::pipe(void) : buf{PIPE_SIZE}, flags{READABLE | WRITABLE} {}
 
 
 void fs::pipe::close_read(void) {
 void fs::pipe::close_read(void) {
@@ -631,16 +611,3 @@ int fs::pipe::read(char* buf, size_t n) {
     waitlist_w.notify_all();
     waitlist_w.notify_all();
     return orig_n - n;
     return orig_n - n;
 }
 }
-
-SECTION(".text.kinit")
-void init_vfs(void) {
-    using namespace fs;
-    // null
-    register_char_device(make_device(1, 0), {b_null_read, b_null_write});
-    // console (supports serial console only for now)
-    // TODO: add interface to bind console device to other devices
-    register_char_device(make_device(2, 0), {console_read, console_write});
-
-    // register tmpfs
-    fs::register_tmpfs();
-}

+ 0 - 4
src/kinit.cpp

@@ -32,8 +32,6 @@ struct PACKED bootloader_data {
     kernel::mem::e820_mem_map_entry meminfo_entries[(1024 - 4 * 4) / 24];
     kernel::mem::e820_mem_map_entry meminfo_entries[(1024 - 4 * 4) / 24];
 };
 };
 
 
-extern void init_vfs();
-
 namespace kernel::kinit {
 namespace kernel::kinit {
 
 
 SECTION(".text.kinit")
 SECTION(".text.kinit")
@@ -77,8 +75,6 @@ void NORETURN real_kernel_init(mem::paging::pfn_t kernel_stack_pfn) {
 
 
     init_pci();
     init_pci();
 
 
-    // TODO: remove this
-    init_vfs();
     init_syscall_table();
     init_syscall_table();
 
 
     init_scheduler(kernel_stack_pfn);
     init_scheduler(kernel_stack_pfn);