]> code.bitgloo.com Git - clyne/stmos.git/commitdiff
vfs, initrd
authorClyne Sullivan <tullivan99@gmail.com>
Mon, 5 Nov 2018 04:46:12 +0000 (23:46 -0500)
committerClyne Sullivan <tullivan99@gmail.com>
Mon, 5 Nov 2018 04:46:12 +0000 (23:46 -0500)
15 files changed:
.gitignore
Makefile
initrd/hello [new file with mode: 0644]
src/fs/Makefile [new file with mode: 0644]
src/fs/initrd.c [new file with mode: 0644]
src/fs/initrd.h [new file with mode: 0644]
src/kernel/init.c
src/kernel/svc.c
src/kernel/task.c
src/kernel/task.h
src/kernel/vfs.c
src/kernel/vfs.h
src/user/user.c
tools/rba [new file with mode: 0755]
tools/rba.cpp [new file with mode: 0644]

index 8bbd2c8eafea90619d7af1f75ac91f1a14492c66..56b48db138d5ede094425ee591e63d564914cc67 100644 (file)
@@ -1,3 +1,5 @@
 *.o
 *.swp
 *.swo
+initrd.img
+main.elf
index c131a32d58c649870fa78300064234151bd5a358..0d4d85c35c2271989aa1963480a13ed62d37f63b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,7 @@
 CROSS = arm-none-eabi-
 CC = gcc
 AS = as
+OBJCOPY = objcopy
 
 MCUFLAGS = -mthumb -mcpu=cortex-m4 #-mfloat-abi=hard -mfpu=fpv4-sp-d16
 AFLAGS = $(MCUFLAGS) 
@@ -37,14 +38,19 @@ export
 
 all: 
        @$(MAKE) -C src/kernel
+       @$(MAKE) -C src/fs
        @$(MAKE) -C src/user
+       @echo "  INITRD"
+       @tools/rba initrd.img $$(find initrd/*)
+       @$(CROSS)$(OBJCOPY) -B arm -I binary -O elf32-littlearm initrd.img initrd.img.o
        @echo "  LINK   " $(OUT)
-       @$(CROSS)$(CC) $(CFLAGS) $(LFLAGS) -o $(OUT) $$(find src/ -name "*.o")
+       @$(CROSS)$(CC) $(CFLAGS) $(LFLAGS) -o $(OUT) $$(find src/ -name "*.o") initrd.img.o
 
 
 clean:
        @echo "  CLEAN"
        @$(MAKE) -C src/kernel clean
+       @$(MAKE) -C src/fs clean
        @$(MAKE) -C src/user clean
        @rm -f $(OUT)
 
diff --git a/initrd/hello b/initrd/hello
new file mode 100644 (file)
index 0000000..5d437a5
--- /dev/null
@@ -0,0 +1 @@
+Hello, world!!
diff --git a/src/fs/Makefile b/src/fs/Makefile
new file mode 100644 (file)
index 0000000..d22fbf3
--- /dev/null
@@ -0,0 +1,22 @@
+CFILES = $(wildcard *.c)
+AFILES = $(wildcard *.s) 
+OFILES = $(patsubst %.c, %.o, $(CFILES)) \
+        $(patsubst %.s, %.asm.o, $(AFILES))
+
+CFLAGS += -I.. -I../arch/cmsis
+
+all: $(OFILES)
+
+%.o: %.c
+       @echo "  CC     " $<
+       @$(CROSS)$(CC) $(CFLAGS) -c $< -o $@
+
+%.asm.o: %.s
+       @echo "  AS     " $<
+       @$(CROSS)$(AS) $(AFLAGS) -c $< -o $@
+
+clean:
+       @echo "  CLEAN"
+       @rm -f $(OFILES)
+
+
diff --git a/src/fs/initrd.c b/src/fs/initrd.c
new file mode 100644 (file)
index 0000000..efa430c
--- /dev/null
@@ -0,0 +1,97 @@
+#include <stdint.h>
+#include <string.h>
+
+#include <kernel/heap.h>
+#include <kernel/vfs.h>
+
+typedef struct {
+       char *address;
+       uint32_t pos;
+       uint32_t size;
+} initrd_info;
+
+extern uint8_t _binary_initrd_img_start[];
+extern uint8_t _binary_initrd_img_size[];
+
+static const uint8_t *initrd_start = (uint8_t *)_binary_initrd_img_start;
+static const uint32_t initrd_size = (uint32_t)_binary_initrd_img_size;
+
+void *initrd_open(const char *file);
+uint32_t initrd_read(void *info, uint32_t count, uint8_t *buffer);
+
+char *initrd_getfile(uint32_t offset);
+
+static const vfs_volume_funcs initrd_funcs = {
+       initrd_open,
+       0, // close
+       initrd_read,
+       0, // write
+       0  // readdir
+};
+
+void initrd_init(void)
+{
+       vfs_mount(&initrd_funcs, VFS_READONLY);
+}
+
+void *initrd_open(const char *file)
+{
+       char *ptr;
+       for (uint32_t i = 0; ptr = initrd_getfile(i), ptr != 0; i++) {
+               uint32_t len = *((uint32_t *)ptr);
+               if (!strncmp(file, ptr + 4, len)) {
+                       initrd_info *file = (initrd_info *)malloc(
+                               sizeof(initrd_info));
+                       file->address = ptr + len + 8;
+                       file->pos = 0;
+                       file->size = *(uint32_t *)(ptr + len + 4);
+                       return file;
+               }
+       }
+
+       return 0;
+}
+
+uint32_t initrd_read(void *info, uint32_t count, uint8_t *buffer)
+{
+       initrd_info *iinfo = (initrd_info *)info;
+       if (iinfo == 0 || iinfo->address == 0)
+               return 0;
+       
+       uint32_t i;
+       for (i = 0; i < count; i++) {
+               if (iinfo->pos >= iinfo->size)
+                       break;
+
+               buffer[iinfo->pos] = iinfo->address[iinfo->pos];
+               iinfo->pos++;
+       }
+
+       return i;
+}
+
+/*char *readfile(const char *name)
+{
+       char *ptr;
+       for (uint32_t i = 0; ptr = getfile(i), ptr != 0; i++) {
+               uint32_t len = *((uint32_t *)ptr);
+               if (!strncmp(name, ptr + 4, len))
+                       return ptr + len + 8;
+       }
+       return 0;
+}*/
+
+char *initrd_getfile(uint32_t offset)
+{
+       char *ptr = (char *)initrd_start;
+       for (uint32_t i = 0; i < offset; i++) {
+               uint32_t len = *((uint32_t *)ptr);
+               uint32_t datalen = *((uint32_t *)(ptr + 4 + len));
+               ptr += len + datalen + 8;
+               if (ptr >= (char *)(initrd_start + initrd_size))
+                       return 0;
+       }
+
+       return ptr;
+}
+
diff --git a/src/fs/initrd.h b/src/fs/initrd.h
new file mode 100644 (file)
index 0000000..dbc0079
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef INTIRD_H_
+#define INITRD_H_
+
+void initrd_init(void);
+
+#endif // INITRD_H_
index 6bb7eb59c75a28c7245d11026715321003595389..2ba607daec83afb5f568c74dbeeec97ecf635d4d 100644 (file)
@@ -23,6 +23,7 @@
 #include "heap.h"\r
 #include "task.h"\r
 #include "vfs.h"\r
+#include <fs/initrd.h>\r
 #include <arch/stm/stm32l476xx.h>\r
 \r
 extern uint8_t __bss_end__;\r
@@ -45,6 +46,9 @@ int main(void)
        heap_init(&__bss_end__);\r
        gpio_init();\r
 \r
+       vfs_init();\r
+       initrd_init();\r
+\r
        // enable FPU\r
        //SCB->CPACR |= (0xF << 20);\r
 \r
index 1e03262349f3b641c938dd7229f07d9d74e668fa..f448ee0f2a5b4f49c2969dd7f3ea8afbf275dca9 100644 (file)
@@ -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;
        }
index e4531db203346fa55d592a80332305cf3ce5ea02..2550e4b61de68927e42622f0f030b756bd4174a1 100644 (file)
@@ -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]) {
index d78e1dafdd7e80f49a5aeb484a308169026b4f3c..30e3e66d526ab893cba63d0bfcebcd2b6b93faa8 100644 (file)
@@ -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_
index a0d9bb41c2d675dd59687f1687c837a2c77b2463..1720a6b69ae73d3ed01f4b8216eaf0c70719356a 100644 (file)
 #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;
 }
+
index 6874905fca7484de7bc32560f182287a9df6ba19..a6de690378bbc4625c27ae22d58aa9fabaa9b84d 100644 (file)
@@ -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_
index 620ffd0bb24c90c53d6aed14d971acb676a999fe..eb2d6626cdfe5691cc52f9d514eefbd22c493d6e 100644 (file)
@@ -1,6 +1,8 @@
-#include <kernel/clock.h>
 #include "priv_gpio.h"
-#include <kernel/task.h>
+
+#include <kernel/clock.h>
+#include <kernel/heap.h>
+#include <kernel/vfs.h>
 
 void user_delay(uint32_t ms)
 {
@@ -28,6 +30,11 @@ void user_main(void)
 {
        gpio(GPIO_MODE, 5, OUTPUT);
 
+       int test = vfs_open("A:/hello", VFS_FILE_READ);
+       char *buf = malloc(20);
+       int count = vfs_read(test, 20, (uint8_t *)buf);
+       (void)count;
+
        if (fork() == 0) {
                while (1) {
                        gpio(GPIO_OUT, 5, 1);
diff --git a/tools/rba b/tools/rba
new file mode 100755 (executable)
index 0000000..52f37cb
Binary files /dev/null and b/tools/rba differ
diff --git a/tools/rba.cpp b/tools/rba.cpp
new file mode 100644 (file)
index 0000000..03ae1d9
--- /dev/null
@@ -0,0 +1,72 @@
+/**
+ * @file rba.cpp
+ * A "really basic archiver"
+ *
+ * Copyright (C) 2018 Clyne Sullivan
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cstdint>
+
+int main(int argc, char *argv[])
+{
+       // check args
+       if (argc < 3) {
+               std::cout << "Usage: " << argv[0] << " archive files...\n";
+               return 0;
+       }
+
+       std::ofstream archive (argv[1], std::ios::out);
+       for (int i = 2; i < argc; i++) {
+               // attempt to read file contents
+               std::string fileName (argv[i]);
+               std::ifstream contents (fileName, std::ios::in | std::ios::ate);
+               std::string shortName;
+               if (auto pos = fileName.rfind('/'); pos != std::string::npos)
+                       shortName = fileName.substr(pos + 1);
+               else
+                       shortName = fileName;
+
+               if (contents.good()) {
+                       uint32_t size = contents.tellg();
+                       contents.seekg(0);
+                       std::cout << "Adding file " << fileName <<" ("
+                               << size << " bytes)...\n";
+
+                       // read in file
+                       char *buffer = new char[size];
+                       contents.read(buffer, size);
+
+                       // write name size/text
+                       uint32_t nameSize = shortName.size();
+                       archive.write((char *)&nameSize, sizeof(uint32_t));
+                       archive.write(shortName.data(), nameSize);
+                       // write data size/content
+                       archive.write((char *)&size, sizeof(uint32_t));
+                       archive.write(buffer, size);
+
+                       delete[] buffer;
+               } else {
+                       std::cout << "Failed to add file " << fileName
+                               << ", continuing...\n";
+               }
+       }
+
+       std::cout << "Created archive " << argv[1] << '\n';
+       return 0;
+}