aboutsummaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/init.c4
-rw-r--r--src/kernel/svc.c7
-rw-r--r--src/kernel/task.c5
-rw-r--r--src/kernel/task.h11
-rw-r--r--src/kernel/vfs.c124
-rw-r--r--src/kernel/vfs.h56
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_