diff options
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/init.c | 4 | ||||
-rw-r--r-- | src/kernel/svc.c | 7 | ||||
-rw-r--r-- | src/kernel/task.c | 5 | ||||
-rw-r--r-- | src/kernel/task.h | 11 | ||||
-rw-r--r-- | src/kernel/vfs.c | 124 | ||||
-rw-r--r-- | src/kernel/vfs.h | 56 |
6 files changed, 169 insertions, 38 deletions
diff --git a/src/kernel/init.c b/src/kernel/init.c index 6bb7eb5..2ba607d 100644 --- a/src/kernel/init.c +++ b/src/kernel/init.c @@ -23,6 +23,7 @@ #include "heap.h"
#include "task.h"
#include "vfs.h"
+#include <fs/initrd.h>
#include <arch/stm/stm32l476xx.h>
extern uint8_t __bss_end__;
@@ -45,6 +46,9 @@ int main(void) heap_init(&__bss_end__);
gpio_init();
+ vfs_init();
+ initrd_init();
+
// enable FPU
//SCB->CPACR |= (0xF << 20);
diff --git a/src/kernel/svc.c b/src/kernel/svc.c index 1e03262..f448ee0 100644 --- a/src/kernel/svc.c +++ b/src/kernel/svc.c @@ -26,6 +26,7 @@ extern void gpio_svc(uint32_t *); extern void clock_svc(uint32_t *); extern void task_svc(uint32_t *); +extern void vfs_svc(uint32_t *args); void SVC_Handler(void) { uint32_t *args; @@ -66,6 +67,12 @@ void SVC_Handler(void) { */ clock_svc(args); break; + case 3: /* Filesystem-related calls + * 0 - mount + * 1 - open + */ + vfs_svc(args); + break; default: break; } diff --git a/src/kernel/task.c b/src/kernel/task.c index e4531db..2550e4b 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -30,11 +30,6 @@ static task_t *task_queue; static uint8_t task_disable = 0; static pid_t task_next_pid = 0; -void task_exit(int code); -int task_fork(void); -pid_t task_getpid(void); -pid_t task_waitpid(pid_t pid, int *wstatus, int options); - void task_svc(uint32_t *args) { switch (args[0]) { diff --git a/src/kernel/task.h b/src/kernel/task.h index d78e1da..30e3e66 100644 --- a/src/kernel/task.h +++ b/src/kernel/task.h @@ -21,7 +21,6 @@ #ifndef TASK_H_ #define TASK_H_ -#include "vfs.h" #include <stdint.h> #define WIFEXITED(w) (w & (1 << 8)) @@ -42,7 +41,6 @@ typedef struct task_t { uint32_t state : 8; uint32_t value : 24; } status; -// vfs_node *cwd; } task_t; enum TASK_STATUS_FLAGS { @@ -76,6 +74,13 @@ void task_hold(uint8_t hold); void task_sleep(uint32_t ms); -//vfs_node *task_getcwd(void); +void task_exit(int code); + +int task_fork(void); + +pid_t task_getpid(void); + +pid_t task_waitpid(pid_t pid, int *wstatus, int options); + #endif // TASK_H_ diff --git a/src/kernel/vfs.c b/src/kernel/vfs.c index a0d9bb4..1720a6b 100644 --- a/src/kernel/vfs.c +++ b/src/kernel/vfs.c @@ -1,15 +1,121 @@ #include "vfs.h" -#include "task.h" -//static vfs_node vfs_root; +#include <kernel/task.h> -int vfs_open(const char *path, int mode) +#define VFS_MAX_VOLS 8 +#define VFS_MAX_FILES 10 + +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[3]) = vfs_mount((vfs_volume_funcs *)args[1], + args[2]); + break; + case 1: + *((int *)args[3]) = vfs_open((const char *)args[1], args[2]); + break; + case 2: + *((int *)args[4]) = vfs_read(args[1], args[2], (uint8_t *)args[3]); + break; + 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) { - (void)path; - (void)mode; -// vfs_node *cd = task_getcwd(); -// if (cd == 0) -// cd = &vfs_root; + 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; - 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; } + diff --git a/src/kernel/vfs.h b/src/kernel/vfs.h index 6874905..a6de690 100644 --- a/src/kernel/vfs.h +++ b/src/kernel/vfs.h @@ -3,30 +3,44 @@ #include <stdint.h> -struct vfs_node; -struct dirent; +typedef struct { + char name[32]; +} vfs_dirent; + +typedef struct { + void *(*open)(const char *file); + void (*close)(void *info); + uint32_t (*read)(void *info, uint32_t count, uint8_t *buffer); + uint32_t (*write)(void *info, uint32_t count, const uint8_t *buffer); + vfs_dirent *(*readdir)(const char *path); +} vfs_volume_funcs; + +#define VFS_MOUNTED (1 << 0) +#define VFS_READONLY (1 << 1) typedef struct { - uint32_t (*read)(struct vfs_node *, uint32_t, uint32_t, uint8_t *); - uint32_t (*write)(struct vfs_node *, uint32_t, uint32_t, const uint8_t *); - void (*open)(struct vfs_node *); - void (*close)(struct vfs_node *); -} vfs_driver; - -typedef struct vfs_node { - char *name; uint32_t flags; + vfs_volume_funcs *funcs; +} vfs_volume; + +#define VFS_FILE_OPEN (1 << 0) +#define VFS_FILE_READ (1 << 1) +#define VFS_FILE_WRITE (1 << 2) +#define VFS_FILE_MODF (1 << 3) +#define VFS_TEMPORARY (1 << 4) +#define VFS_EOF (1 << 5) + +typedef struct { + uint32_t flags; + uint32_t vol; + uint32_t pid; + void *fsinfo; +} vfs_file; + +void vfs_init(void); - struct vfs_node *parent; - union { - struct vfs_node* children; - vfs_driver *access; - } data; -} vfs_node; - -struct dirent { - char *name; - vfs_node *node; -}; +int vfs_mount(vfs_volume_funcs *funcs, uint32_t flags); +int vfs_open(const char *path, uint32_t flags); +uint32_t vfs_read(int fd, uint32_t count, uint8_t *buffer); #endif // VFS_H_ |