diff --git a/kernel/inc/drivers/fs/vfs.h b/kernel/inc/drivers/fs/vfs.h new file mode 100644 index 0000000..8f5cb49 --- /dev/null +++ b/kernel/inc/drivers/fs/vfs.h @@ -0,0 +1,65 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#ifndef NOX_VFS_H +#define NOX_VFS_H + +#include "utils/stdtypes.h" +#include "utils/string.h" +#include "boot/boot_info.h" + +#define VFS_MAX_NAME_LENGTH 128 + +typedef struct vfs_node_T vfs_node_T; + +typedef enum { + VFS_NODE_DIRECTORY, + VFS_NODE_FILE, + VFS_NODE_MOUNT, + VFS_NODE_BLOCK_DEVICE, + + VFS_NODE_ENUM_END +} vfs_node_type_E; + +typedef struct { + void* buffer; + uint64_t buffer_size; + bool reclaimable; + vfs_node_T* node; +} vfs_node_cache_T; + +struct vfs_node_T{ + char name[VFS_MAX_NAME_LENGTH]; + vfs_node_type_E type; + vfs_node_cache_T* cache; + + vfs_node_T* prev; + vfs_node_T* next; + vfs_node_T* parent; + vfs_node_T* childs; +}; + +extern vfs_node_T* g_vfs_root_node; + +vfs_node_T* vfs_node_create (vfs_node_T* parent, string_t name, vfs_node_type_E type); +vfs_node_T* vfs_node_destruct (vfs_node_T* node); +void vfs_node_dump_info (vfs_node_T* node, uint64_t indent); +vfs_node_T* vfs_node_resolve_child (vfs_node_T* node, string_t child_name); + +void vfs_init (boot_info_T* boot_info); +vfs_node_T* vfs_resolve_path (string_t path); +void vfs_unpack_archive_ustar (); + +#endif //NOX_VFS_H diff --git a/kernel/src/drivers/fs/vfs.c b/kernel/src/drivers/fs/vfs.c new file mode 100644 index 0000000..27babca --- /dev/null +++ b/kernel/src/drivers/fs/vfs.c @@ -0,0 +1,145 @@ +/* Copyright (C) Antifallobst + * + * NoxOS is free software: + * you can redistribute it and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * NoxOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. + * If not, see . + */ + +#include "drivers/fs/vfs.h" +#include "utils/memory.h" +#include "utils/logger.h" + +vfs_node_T* g_vfs_root_node; + +void vfs_node_bring_to_parent_start(vfs_node_T* node) { + if (node->parent == NULL) { return; } + + if (node->parent->childs == node) { + return; + } + + if (node->parent->childs == NULL) { + node->parent->childs = node; + return; + } + + if (node->prev != NULL) { + node->prev->next = node->next; + } + + if (node->next != NULL) { + node->next->prev = node->prev; + } + + node->parent->childs->prev = node; + node->next = node->parent->childs; + node->parent->childs = node; +} + +vfs_node_T* vfs_node_create(vfs_node_T* parent, string_t name, vfs_node_type_E type) { + vfs_node_T* node = memory_allocate(sizeof(vfs_node_T)); + + uint64_t strlen = string_length(name); + if (strlen >= VFS_MAX_NAME_LENGTH) { + log(LOG_WARNING, " name '%s' is too long, shrinking to '%.*s'", name, VFS_MAX_NAME_LENGTH-1, name); + } + memory_copy((void*)name, node->name, VFS_MAX_NAME_LENGTH-1); node->name[VFS_MAX_NAME_LENGTH-1] = '\0'; + + node->parent = parent; + node->type = type; + node->cache = NULL; + node->childs = NULL; + node->prev = NULL; + node->next = NULL; + + vfs_node_bring_to_parent_start(node); + + return node; +} + +void vfs_node_dump_info(vfs_node_T* node, uint64_t indent) { + char buf[indent+1]; + memory_set(buf, ' ', indent); + buf[indent] = '\0'; + + switch (node->type) { + case VFS_NODE_DIRECTORY: { + log(LOG_NONE, "%s[dir] %s", buf, node->name); + vfs_node_T* child = node->childs; + while (child != NULL) { + vfs_node_dump_info(child, indent+2); + child = child->next; + } + break; + } + case VFS_NODE_FILE: { + log(LOG_NONE, "%s[file] %s", buf, node->name); + break; + } + } +} + +vfs_node_T* vfs_node_destruct(vfs_node_T* node) { + +} + + +vfs_node_T* vfs_node_resolve_child(vfs_node_T* node, string_t child_name) { + vfs_node_T* child = node->childs; + while (child != NULL) { + if (!string_compare(child_name, child->name)) { + child = child->next; + continue; + } + + vfs_node_bring_to_parent_start(child); + return child; + } + + return NULL; +} + +void vfs_init(boot_info_T* boot_info) { + g_vfs_root_node = vfs_node_create(NULL, "root", VFS_NODE_DIRECTORY); +} + +vfs_node_T* vfs_resolve_path(string_t path) { + if (*path != '/') { + log(LOG_WARNING, " failed to resolve node from invalid path '%s' (no root prefix)"); + return NULL; + } + + uint32_t length; + vfs_node_T* node = g_vfs_root_node; + + do { + path++; + length = string_find_next(path, '/'); + + char name[length]; + memory_copy((void*)path, name, length); + name[length] = '\0'; + + node = vfs_node_resolve_child(node, name); + if (node == NULL) { + log(LOG_WARNING, " failed to resolve node from invalid path '%s' (node child resolve null)"); + return NULL; + } + + path += length; + } while(*path != '\0'); + + return node; +} + +void vfs_unpack_archive_ustar() { + +} \ No newline at end of file diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index 88c8f09..a0a653e 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -22,6 +22,7 @@ #include "mm/page_map.h" #include "drivers/time/pit.h" #include "drivers/graphics/renderer.h" +#include "drivers/fs/vfs.h" #include "proc/scheduler.h" #include "utils/io.h" @@ -60,6 +61,11 @@ void kernel_init(boot_info_T* boot_info) { graphics_renderer_init(boot_info); graphical_log_init(); limine_terminal_print(boot_info, " ok\n"); + + limine_terminal_print(boot_info, " Initializing virtual file system..."); + vfs_init(boot_info); + limine_terminal_print(boot_info, " ok\n"); + limine_terminal_print(boot_info, " Initializing scheduler..."); scheduler_init(); limine_terminal_print(boot_info, " ok\n"); @@ -75,11 +81,19 @@ void kmain(boot_info_T boot_info) { limine_terminal_print(&boot_info, "Kernel initialized\n"); log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n"); - log(LOG_NONE, "test none"); - log(LOG_INFO, "test info"); - log(LOG_DEBUG, "test debug"); - log(LOG_WARNING, "test warning"); - log(LOG_ERROR, "test error"); + vfs_node_T* node_temp = vfs_node_create(g_vfs_root_node, "temp", VFS_NODE_DIRECTORY); + vfs_node_T* node_system = vfs_node_create(g_vfs_root_node, "system", VFS_NODE_DIRECTORY); + vfs_node_T* node_config = vfs_node_create(node_system, "config", VFS_NODE_DIRECTORY); + vfs_node_T* node_test = vfs_node_create(node_config, "test.conf", VFS_NODE_FILE); + + vfs_node_T* result = vfs_resolve_path("/system/config/test.conf"); + if (result == node_test) { + log(LOG_DEBUG, "resolve test passed"); + } else { + log(LOG_DEBUG, "resolve test failed 0x%x != 0x%x", result, node_test); + } + + vfs_node_dump_info(g_vfs_root_node, 0); CORE_HALT_FOREVER }