*.o
*.swp
*.swo
+initrd.img
+main.elf
CROSS = arm-none-eabi-
CC = gcc
AS = as
+OBJCOPY = objcopy
MCUFLAGS = -mthumb -mcpu=cortex-m4 #-mfloat-abi=hard -mfpu=fpv4-sp-d16
AFLAGS = $(MCUFLAGS)
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)
--- /dev/null
+Hello, world!!
--- /dev/null
+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)
+
+
--- /dev/null
+#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;
+}
+
--- /dev/null
+#ifndef INTIRD_H_
+#define INITRD_H_
+
+void initrd_init(void);
+
+#endif // INITRD_H_
#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
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
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;
*/
clock_svc(args);
break;
+ case 3: /* Filesystem-related calls
+ * 0 - mount
+ * 1 - open
+ */
+ vfs_svc(args);
+ break;
default:
break;
}
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]) {
#ifndef TASK_H_
#define TASK_H_
-#include "vfs.h"
#include <stdint.h>
#define WIFEXITED(w) (w & (1 << 8))
uint32_t state : 8;
uint32_t value : 24;
} status;
-// vfs_node *cwd;
} task_t;
enum TASK_STATUS_FLAGS {
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_
#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;
}
+
#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_
-#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)
{
{
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);
--- /dev/null
+/**
+ * @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;
+}