From f3d7e220ac552adf594679ee415a3663728a62a6 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 8 Oct 2022 21:22:46 +0200 Subject: [PATCH] The beginnings of a VFS implementation!! --- kernel/include/fs/VFS.h | 22 ++++++++++++++++ kernel/src/fs/VFS.cpp | 24 ++++++++++++++++++ kernel/src/init/InitRD.cpp | 51 ++++++++++++++++++++++++++++++++++++++ kernel/src/main.cpp | 16 ++++++++++++ 4 files changed, 113 insertions(+) create mode 100644 kernel/include/fs/VFS.h create mode 100644 kernel/src/fs/VFS.cpp diff --git a/kernel/include/fs/VFS.h b/kernel/include/fs/VFS.h new file mode 100644 index 00000000..2ab19a1c --- /dev/null +++ b/kernel/include/fs/VFS.h @@ -0,0 +1,22 @@ +#pragma once +#include + +namespace VFS +{ + struct Node; + + typedef int32_t (*node_read)(Node*, uint32_t, uint32_t, char*); + typedef Node* (*node_finddir)(Node*, const char*); + + struct Node + { + char name[64]; + uint64_t inode; + node_read read_func; + node_finddir find_func; + }; + + int32_t read(Node* node, uint32_t offset, uint32_t length, char* buffer); + Node* open(const char* filename); + void mount_root(Node* root); +} \ No newline at end of file diff --git a/kernel/src/fs/VFS.cpp b/kernel/src/fs/VFS.cpp new file mode 100644 index 00000000..e196b7ea --- /dev/null +++ b/kernel/src/fs/VFS.cpp @@ -0,0 +1,24 @@ +#include "fs/VFS.h" + +static VFS::Node* vfs_root; + +int32_t VFS::read(Node* node, uint32_t offset, uint32_t length, char* buffer) +{ + if (!node) return -1; + if (!node->read_func) return -1; + + return node->read_func(node, offset, length, buffer); +} + +VFS::Node* VFS::open(const char* filename) +{ + if (!vfs_root) return 0; + if (!vfs_root->find_func) return 0; + + return vfs_root->find_func(vfs_root, filename); +} + +void VFS::mount_root(Node* root) +{ + vfs_root = root; +} \ No newline at end of file diff --git a/kernel/src/init/InitRD.cpp b/kernel/src/init/InitRD.cpp index ee921098..195efd93 100644 --- a/kernel/src/init/InitRD.cpp +++ b/kernel/src/init/InitRD.cpp @@ -2,6 +2,7 @@ #include "init/InitRD.h" #include "bootboot.h" +#include "fs/VFS.h" #include "io/Serial.h" #include "log/Log.h" #include "memory/MemoryManager.h" @@ -14,6 +15,8 @@ extern BOOTBOOT bootboot; static void* initrd_base; static bool initrd_initialized = false; +static VFS::Node initrd_root; + bool InitRD::is_initialized() { return initrd_initialized; @@ -112,10 +115,58 @@ void InitRD::for_each(void (*callback)(File& f)) } } +static InitRD::File files[32]; +static uint32_t total_files = 0; + +static VFS::Node nodes[32]; + +int32_t initrd_read(VFS::Node* node, uint32_t offset, uint32_t length, char* buffer) +{ + if (!node) return -1; + if (node->inode >= total_files) return -1; + InitRD::File& file = files[node->inode]; + if (offset > file.size) return -1; + if (offset + length > file.size) { length = (uint32_t)file.size - offset; } + memcpy(buffer, (void*)((uint64_t)file.addr + offset), length); + return (int32_t)length; +} + +VFS::Node* initrd_scan_root(VFS::Node*, const char* filename) +{ + for (uint32_t i = 0; i < total_files; i++) + { + if (strncmp(nodes[i].name, filename, sizeof(VFS::Node::name)) == 0) { return &nodes[i]; } + } + return 0; +} + +void initrd_scan() +{ + InitRD::for_each([](InitRD::File& f) { + if (total_files >= 32) return; + kdbgln("registering file %s", f.name); + files[total_files++] = f; + }); + for (uint32_t i = 0; i < total_files; i++) + { + VFS::Node& node = nodes[i]; + node.inode = i; + node.read_func = initrd_read; + strncpy(node.name, files[i].name, sizeof(node.name)); + } +} + void InitRD::init() { initrd_base = MemoryManager::get_unaligned_mappings((void*)bootboot.initrd_ptr, bootboot.initrd_size / PAGE_SIZE + 1); kdbgln("physical base at %lx, size %lx, mapped to %p", bootboot.initrd_ptr, bootboot.initrd_size, initrd_base); + kdbgln("total blocks: %ld", get_total_blocks()); + initrd_scan(); + initrd_root.inode = (uint64_t)-1; + strncpy(initrd_root.name, "initrd", 7); + initrd_root.find_func = initrd_scan_root; + VFS::mount_root(&initrd_root); + kdbgln("mounted initrd at VFS root, total files: %d", total_files); initrd_initialized = true; } \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 4b5c71b9..1b55ac69 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -4,6 +4,7 @@ #include "assert.h" #include "config.h" #include "cpu/CPU.h" +#include "fs/VFS.h" #include "gdt/GDT.h" #include "init/Init.h" #include "init/InitRD.h" @@ -159,6 +160,21 @@ extern "C" void _start() kinfoln("Interrupts enabled"); + kinfoln("Trying VFS"); + + VFS::Node* node = VFS::open("sys/moon.sym"); + if (!node) { kerrorln("Unable to find file in VFS"); } + else + { + kinfoln("Found '%s'", node->name); + char buffer[256]; + kinfoln("Reading 255 bytes at offset 128..."); + int nwritten = VFS::read(node, 128, 255, buffer); + kinfoln("Read a total of %d bytes", nwritten); + buffer[255] = 0; + kinfoln("Read: %s", buffer); + } + PCI::scan([](PCI::Device& dev) { kinfoln("Found PCI device %x:%x, %s", dev.id().vendor, dev.id().device, pci_type_name(dev.type())); });