From eb7d9c8f588646dabcc6e92cc2c6532ad8159075 Mon Sep 17 00:00:00 2001 From: Babz Date: Sun, 19 Sep 2021 20:52:05 +0200 Subject: [PATCH] implement minimal virtual file system --- CMakeLists.txt | 1 + src/main.c | 4 ++ src/syscalls.S | 16 ++++++ src/vfs/vfs.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++ src/vfs/vfs.h | 26 +++++++++ 5 files changed, 194 insertions(+) create mode 100644 src/vfs/vfs.c create mode 100644 src/vfs/vfs.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c8f54d4..9ed941e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ set(SOURCES src/job.c src/wren_utils.c src/utf8.c + src/vfs/vfs.c ) set(SOURCES_WREN wren/src/wren_compiler.c diff --git a/src/main.c b/src/main.c index 24e7807..822853d 100644 --- a/src/main.c +++ b/src/main.c @@ -15,6 +15,7 @@ #include "job.h" #include "term.h" #include "ui.h" +#include "vfs/vfs.h" #include "wren_utils.h" static int tick_ctr = 0; @@ -113,6 +114,9 @@ __attribute__((noreturn)) static void halt(void) { int main(int isappli, int optnum) { term_kprintf("main(%d, %d)", isappli, optnum); + vfs_init(); + halt(); + timer_sched = timer_configure(TIMER_ANY, 10 * 1000, GINT_CALL(callback_sched)); // 100 Hz <=> 10 ms timer_redraw = timer_configure(TIMER_ANY, 31250, GINT_CALL(callback_redraw)); // 32 Hz diff --git a/src/syscalls.S b/src/syscalls.S index b71c696..49d74fb 100644 --- a/src/syscalls.S +++ b/src/syscalls.S @@ -3,6 +3,10 @@ .global __battery_type .global __set_backlight .global __set_quit_handler +.global __name_to_str +.global __str_to_name +.global __find_first +.global __find_next .section ".text" @@ -38,6 +42,18 @@ __set_backlight: __set_quit_handler: syscall(0x1E6E) +__name_to_str: + syscall(0x1ddb) + +__str_to_name: + syscall(0x1ddc) + +__find_first: + syscall(0x1db6) + +__find_next: + syscall(0x1db8) + syscall_table: .long 0x80020070 diff --git a/src/vfs/vfs.c b/src/vfs/vfs.c new file mode 100644 index 0000000..bc4ca94 --- /dev/null +++ b/src/vfs/vfs.c @@ -0,0 +1,147 @@ +#include "vfs.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "../term.h" + +extern void _name_to_str(char *dest, const uint16_t *source, int n); +extern void _str_to_name(uint16_t *dest, const char *source, int n); +extern int _find_first(const uint16_t *pathname, int *FindHandle, const uint16_t *foundfile, struct BFile_FileInfo *fileinfo); +extern int _find_next(int FindHandle, const uint16_t *foundfile, struct BFile_FileInfo *fileinfo); + +static vfs_entry_t vfs_root; + +static vfs_entry_t *vfs_new_dir(const char *name, vfs_entry_t *parent) { + vfs_entry_t *newdir = kmalloc(sizeof(vfs_entry_t), NULL); + + strcpy((char *)&newdir->name, name); + newdir->parent = parent; + newdir->type = vfs_dir; + newdir->driver = 0; + newdir->childs = NULL; + newdir->next = NULL; + + newdir->next = parent->childs; + parent->childs = newdir; + + return newdir; +} + +static vfs_entry_t *vfs_new_file(const char *name, vfs_entry_t *parent) { + vfs_entry_t *newfile = kmalloc(sizeof(vfs_entry_t), NULL); + + strcpy((char *)&newfile->name, name); + newfile->parent = parent; + newfile->type = vfs_file; + newfile->driver = 0; + newfile->childs = NULL; + newfile->next = NULL; + + newfile->next = parent->childs; + parent->childs = newfile; + + return newfile; +} + +static void vfs_debug_tree_(int indent, vfs_entry_t *subtree) { + vfs_entry_t *child = subtree->childs; + + while (child != NULL) { + for (int i = 0; i < indent; i++) + term_print(" "); + + if (child->type == vfs_file) + term_printf("%s\n", child->name); + else if (child->type == vfs_dir) { + term_printf("%s/\n", child->name); + vfs_debug_tree_(indent + 1, child); + } + + child = child->next; + } +} + +static void vfs_debug_tree(void) { + term_print("/\n"); + vfs_debug_tree_(1, &vfs_root); +} + +static int shandle; +static void populate_vfs(const char *path, vfs_entry_t *dir) { + char glob[64]; + strcpy(glob, path); + strcat(glob, "\\*"); + + uint16_t glob_c16[64]; + _str_to_name(glob_c16, glob, 64); + + uint16_t foundfile[64]; + struct BFile_FileInfo fileinfo; + int ret = _find_first(glob_c16, &shandle, foundfile, &fileinfo); + while (ret == 0) { + char foundfile_str[64]; + _name_to_str(foundfile_str, foundfile, 64); + + if (foundfile_str[0] != '@' && strcmp(foundfile_str, ".") != 0 && strcmp(foundfile_str, "..") != 0) { + if (fileinfo.type == BFile_Type_Directory) { + vfs_new_dir(foundfile_str, dir); + } else { + vfs_new_file(foundfile_str, dir); + } + } + + ret = _find_next(shandle, foundfile, &fileinfo); + } + BFile_FindClose(shandle); + + // we do the recursive search when the search handle + // has been closed to avoid using too much handles + + vfs_entry_t *child = dir->childs; + while (child != NULL) { + if (child->type == vfs_dir) { + char new_path[64]; + sprintf(new_path, "%s\\%s", path, child->name); + + populate_vfs(new_path, child); + } + + child = child->next; + } +} + +void vfs_init(void) { + // init fs root + strcpy((char *)&vfs_root.name, ""); + vfs_root.parent = NULL; + vfs_root.type = vfs_dir; + vfs_root.driver = 0; + vfs_root.childs = NULL; + vfs_root.next = NULL; + + vfs_entry_t *native = vfs_new_dir("native", &vfs_root); + vfs_entry_t *flash = vfs_new_dir("flash", native); + + cpu_atomic_start(); + // gint_world_switch_in(gint_world_addin, gint_world_os); + populate_vfs("\\\\fls0", flash); + // gint_world_switch_in(gint_world_os, gint_world_addin); + cpu_atomic_end(); + + vfs_debug_tree(); +} + +// const vfs_entry_t *vfs_get_root(void) { return &vfs_root; } + +// vfs_entry* find_entry(const char* path) { +// // TODO +// } \ No newline at end of file diff --git a/src/vfs/vfs.h b/src/vfs/vfs.h new file mode 100644 index 0000000..3ee258a --- /dev/null +++ b/src/vfs/vfs.h @@ -0,0 +1,26 @@ +#ifndef UNS_VFS_H +#define UNS_VFS_H + +#include + +enum vfs_entry_type { + vfs_file = 1, + vfs_dir = 2, +}; + +typedef struct vfs_entry { + char name[64]; + struct vfs_entry *parent; + + enum vfs_entry_type type; + uint16_t driver; + + // dir only + struct vfs_entry *childs; + struct vfs_entry *next; +} vfs_entry_t; + +void vfs_init(void); +// const vfs_entry_t *vfs_get_root(void); + +#endif // #ifndef UNS_VFS_H \ No newline at end of file