implement minimal virtual file system

This commit is contained in:
Babz 2021-09-19 20:52:05 +02:00
parent 291eea1bfa
commit eb7d9c8f58
5 changed files with 194 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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

147
src/vfs/vfs.c Normal file
View File

@ -0,0 +1,147 @@
#include "vfs.h"
#include <stdlib.h>
#include <string.h>
#include <gint/bfile.h>
#include <gint/cpu.h>
#include <gint/drivers.h>
#include <gint/keyboard.h>
#include <gint/kmalloc.h>
#include <printf.h>
#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
// }

26
src/vfs/vfs.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef UNS_VFS_H
#define UNS_VFS_H
#include <stdint.h>
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