vfs, initrd

master
Clyne Sullivan 6 years ago
parent 3a798edb83
commit 2f719330b8

2
.gitignore vendored

@ -1,3 +1,5 @@
*.o
*.swp
*.swo
initrd.img
main.elf

@ -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)

@ -0,0 +1 @@
Hello, world!!

@ -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)

@ -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;
}

@ -0,0 +1,6 @@
#ifndef INTIRD_H_
#define INITRD_H_
void initrd_init(void);
#endif // INITRD_H_

@ -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);

@ -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;
}

@ -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]) {

@ -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_

@ -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;
}

@ -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_

@ -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);

Binary file not shown.

@ -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;
}
Loading…
Cancel
Save