From 0a7d4a530d4808a4af10da05c63e19b3c6a510de Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 11 Oct 2022 19:21:16 +0200 Subject: [PATCH] VFS, DeviceFS: Implement a device filesystem For now, we just have a version device. (this will allow us to get rid of sys_getversion!!) More should be implemented soon. --- apps/src/init.c | 38 +++++++++++++++++++++++++--- kernel/include/fs/VFS.h | 1 + kernel/include/fs/devices/DeviceFS.h | 9 +++++++ kernel/include/fs/devices/Version.h | 9 +++++++ kernel/src/fs/VFS.cpp | 5 ++++ kernel/src/fs/devices/DeviceFS.cpp | 35 +++++++++++++++++++++++++ kernel/src/fs/devices/Version.cpp | 26 +++++++++++++++++++ kernel/src/main.cpp | 24 +++--------------- 8 files changed, 123 insertions(+), 24 deletions(-) create mode 100644 kernel/include/fs/devices/DeviceFS.h create mode 100644 kernel/include/fs/devices/Version.h create mode 100644 kernel/src/fs/devices/DeviceFS.cpp create mode 100644 kernel/src/fs/devices/Version.cpp diff --git a/apps/src/init.c b/apps/src/init.c index fbac251f..564fe74e 100644 --- a/apps/src/init.c +++ b/apps/src/init.c @@ -8,6 +8,39 @@ typedef long ssize_t; +int print_version() +{ + char version[4096]; + + FILE* verfile = fopen("/dev/version", "r"); + if (!verfile) + { + perror("fopen"); + return 1; + } + + size_t nread = fread(version, 4096, 1, verfile); + if (ferror(verfile)) + { + perror("fread"); + return 1; + } + + printf("Read %zd bytes\n", nread); + + version[nread] = 0; + + if (fclose(verfile) < 0) + { + perror("fclose"); + return 1; + } + + printf("Your kernel version is %s\n\n", version); + + return 0; +} + int main() { if (gettid() == 0) // why are we the idle task? @@ -21,10 +54,7 @@ int main() sleep(1); - char version[40]; - syscall(SYS_getversion, version, sizeof(version)); - - printf("Your kernel version is %s\n\n", version); + if (print_version()) return 1; sleep(2); diff --git a/kernel/include/fs/VFS.h b/kernel/include/fs/VFS.h index b250bed8..809053c7 100644 --- a/kernel/include/fs/VFS.h +++ b/kernel/include/fs/VFS.h @@ -38,6 +38,7 @@ namespace VFS Node* resolve_path(const char* filename, Node* root = nullptr); void mount(Node* mountpoint, Node* mounted); + void mount(const char* pathname, Node* mounted); void unmount(Node* mountpoint); diff --git a/kernel/include/fs/devices/DeviceFS.h b/kernel/include/fs/devices/DeviceFS.h new file mode 100644 index 00000000..5c0ae2e4 --- /dev/null +++ b/kernel/include/fs/devices/DeviceFS.h @@ -0,0 +1,9 @@ +#pragma once +#include "fs/VFS.h" + +namespace DeviceFS +{ + VFS::Node* get(); + + VFS::Node* finddir(VFS::Node* node, const char* filename); +} \ No newline at end of file diff --git a/kernel/include/fs/devices/Version.h b/kernel/include/fs/devices/Version.h new file mode 100644 index 00000000..100f7253 --- /dev/null +++ b/kernel/include/fs/devices/Version.h @@ -0,0 +1,9 @@ +#pragma once +#include "fs/VFS.h" + +namespace VersionDevice +{ + VFS::Node* create_new(); + + ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer); +} \ No newline at end of file diff --git a/kernel/src/fs/VFS.cpp b/kernel/src/fs/VFS.cpp index 6be9314c..e9d775f9 100644 --- a/kernel/src/fs/VFS.cpp +++ b/kernel/src/fs/VFS.cpp @@ -134,6 +134,11 @@ void VFS::mount(Node* mountpoint, Node* mounted) mountpoint->flags |= VFS_MOUNTPOINT; } +void VFS::mount(const char* pathname, Node* mounted) +{ + return mount(resolve_path(pathname), mounted); +} + void VFS::unmount(Node* mountpoint) { if (!mountpoint) return; diff --git a/kernel/src/fs/devices/DeviceFS.cpp b/kernel/src/fs/devices/DeviceFS.cpp new file mode 100644 index 00000000..387c9eef --- /dev/null +++ b/kernel/src/fs/devices/DeviceFS.cpp @@ -0,0 +1,35 @@ +#include "fs/devices/DeviceFS.h" +#include "fs/devices/Version.h" +#include "std/stdlib.h" +#include "std/string.h" + +#define DEVFS_MAX_FILES 32 + +VFS::Node* devfs_root = nullptr; + +VFS::Node* devfs_files[DEVFS_MAX_FILES]; +int devfs_file_count = 0; + +VFS::Node* DeviceFS::get() +{ + if (devfs_root) return devfs_root; + devfs_root = new VFS::Node; + devfs_root->length = 0; + devfs_root->inode = 0; + devfs_root->type = VFS_DIRECTORY; + devfs_root->find_func = DeviceFS::finddir; + strncpy(devfs_root->name, "dev", sizeof(devfs_root->name)); + + devfs_files[devfs_file_count++] = VersionDevice::create_new(); + return devfs_root; +} + +VFS::Node* DeviceFS::finddir(VFS::Node* node, const char* filename) +{ + if (!node) return 0; + for (int i = 0; i < devfs_file_count; i++) + { + if (strncmp(devfs_files[i]->name, filename, sizeof(VFS::Node::name)) == 0) { return devfs_files[i]; } + } + return 0; +} \ No newline at end of file diff --git a/kernel/src/fs/devices/Version.cpp b/kernel/src/fs/devices/Version.cpp new file mode 100644 index 00000000..1dbcbb1c --- /dev/null +++ b/kernel/src/fs/devices/Version.cpp @@ -0,0 +1,26 @@ +#include "fs/devices/Version.h" +#include "config.h" +#include "std/stdio.h" +#include "std/stdlib.h" +#include "std/string.h" + +VFS::Node* VersionDevice::create_new() +{ + VFS::Node* dev = new VFS::Node; + dev->read_func = VersionDevice::read; + dev->inode = 0; + dev->length = strlen(moon_version()) + 5; + dev->type = VFS_FILE; + strncpy(dev->name, "version", sizeof(dev->name)); + return dev; +} + +ssize_t VersionDevice::read(VFS::Node* node, size_t offset, size_t size, char* buffer) +{ + if (!node) return -1; + if (offset > node->length) return -1; + if (offset + size > node->length) { size = node->length - offset; } + if (offset > 0) return -1; + snprintf(buffer, size + 1, "moon %s", moon_version()); // FIXME: Support offseting this read + return (ssize_t)size; +} \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index b209e0c9..81e73876 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -5,6 +5,7 @@ #include "config.h" #include "cpu/CPU.h" #include "fs/VFS.h" +#include "fs/devices/DeviceFS.h" #include "gdt/GDT.h" #include "init/Init.h" #include "init/InitRD.h" @@ -158,30 +159,13 @@ extern "C" void _start() Init::finish_kernel_boot(); + VFS::mkdir("/", "dev"); + VFS::mount("/dev", DeviceFS::get()); + Interrupts::enable(); kinfoln("Interrupts enabled"); - kinfoln("Trying VFS"); - - if (VFS::mkdir("/", "rootfs") < 0) { kerrorln("Unable to create directory rootfs"); } - else - { - VFS::mount(VFS::resolve_path("/rootfs"), VFS::root()); - VFS::Node* node = VFS::resolve_path("/rootfs/sys/config"); - if (!node) kerrorln("unable to find /sys/config in VFS"); - else - { - kinfoln("Found '%s'", node->name); - char* buffer = (char*)kmalloc(node->length + 1); - buffer[node->length] = 0; - ssize_t nread = VFS::read(node, 0, node->length, buffer); - kdbgln("Read %zd bytes", nread); - kinfoln("Read: %s", buffer); - kfree(buffer); - } - } - PCI::scan([](PCI::Device& dev) { kinfoln("Found PCI device %x:%x, %s", dev.id().vendor, dev.id().device, pci_type_name(dev.type())); });