diff options
Diffstat (limited to 'src/kernel/vfs.c')
-rw-r--r-- | src/kernel/vfs.c | 115 |
1 files changed, 103 insertions, 12 deletions
diff --git a/src/kernel/vfs.c b/src/kernel/vfs.c index 538fbee..1720a6b 100644 --- a/src/kernel/vfs.c +++ b/src/kernel/vfs.c @@ -1,30 +1,121 @@ #include "vfs.h" -#include "task.h" -typedef unsigned int size_t; +#include <kernel/task.h> -//static vfs_node vfs_root; +#define VFS_MAX_VOLS 8 +#define VFS_MAX_FILES 10 -int vfs_open(const char *path, int flags, int mode); -size_t vfs_read(int fd, void *buf, size_t count); -size_t vfs_write(int fd, const void *buf, size_t count); -int vfs_close(int fd); +static vfs_volume vfs_volumes[VFS_MAX_VOLS]; +static vfs_file vfs_files[VFS_MAX_FILES]; void vfs_svc(uint32_t *args) { switch (args[0]) { case 0: - *((int *)args[4]) = vfs_open(args[1], args[2], args[3]); + *((int *)args[3]) = vfs_mount((vfs_volume_funcs *)args[1], + args[2]); break; case 1: - *((int *)args[4]) = vfs_read(args[1], args[2], args[3]); + *((int *)args[3]) = vfs_open((const char *)args[1], args[2]); break; case 2: - *((int *)args[4]) = vfs_write(args[1], args[2], args[3]); + *((int *)args[4]) = vfs_read(args[1], args[2], (uint8_t *)args[3]); break; - case 3: - *((int *)args[2]) = vfs_close(args[1]); + default: break; } } +void vfs_init(void) +{ + for (int i = 0; i < VFS_MAX_VOLS; i++) + vfs_volumes[i].flags = 0; + for (int i = 0; i < VFS_MAX_FILES; i++) + vfs_files[i].flags = 0; +} + +int vfs_mount(vfs_volume_funcs *funcs, uint32_t flags) +{ + for (int i = 0; i < VFS_MAX_VOLS; i++) { + if (!(vfs_volumes[i].flags && VFS_MOUNTED)) { + vfs_volumes[i].flags = VFS_MOUNTED | flags; + vfs_volumes[i].funcs = funcs; + return i; + } + } + + return -1; +} + +int vfs_get_drive(const char *path) +{ + // Validate parameters + if (path[0] == '\0' || path[1] == '\0' || path[1] != ':' || + path[2] == '\0' || path[2] != '/') + return -1; + + // Find chosen drive + int drive = -1; + for (int i = 0; i < VFS_MAX_VOLS; i++) { + if (path[0] == ('a' + i) || path[0] == ('A' + i)) { + drive = i; + break; + } + } + + if (drive == -1 || !(vfs_volumes[drive].flags && VFS_MOUNTED)) + return -1; + + return drive; +} + +int vfs_open(const char *path, uint32_t flags) +{ + int drive = vfs_get_drive(path); + if (drive == -1) + return -1; + if (vfs_volumes[drive].funcs->open == 0) + return -1; + + // Find available file handle + int file = -1; + for (int i = 0; i < VFS_MAX_FILES; i++) { + if (!(vfs_files[i].flags & VFS_FILE_OPEN)) { + file = i; + break; + } + } + + if (file == -1) + return -1; + + vfs_files[file].flags = VFS_FILE_OPEN | flags; + vfs_files[file].vol = drive; + vfs_files[file].pid = task_getpid(); + vfs_files[file].fsinfo = + vfs_volumes[drive].funcs->open(path + 3); + + return file; +} + +uint32_t vfs_read(int fd, uint32_t count, uint8_t *buffer) +{ + if (fd < 0 || fd > VFS_MAX_FILES || count == 0 || buffer == 0) + return 0; + if (vfs_volumes[vfs_files[fd].vol].funcs->read == 0) + return -1; + if (vfs_files[fd].pid != task_getpid()) + return 0; + if ((!(vfs_files[fd].flags & VFS_FILE_READ)) || (vfs_files[fd].flags & + VFS_EOF)) + return 0; + + uint32_t ret = vfs_volumes[vfs_files[fd].vol].funcs->read(vfs_files[fd].fsinfo, + count, buffer); + + if (ret < count) + vfs_files[fd].flags |= VFS_EOF; + + return ret; +} + |