vfs, initrd
parent
3a798edb83
commit
2f719330b8
@ -1,3 +1,5 @@
|
|||||||
*.o
|
*.o
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
|
initrd.img
|
||||||
|
main.elf
|
||||||
|
@ -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_
|
@ -1,15 +1,121 @@
|
|||||||
#include "vfs.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)
|
||||||
{
|
{
|
||||||
(void)path;
|
int drive = vfs_get_drive(path);
|
||||||
(void)mode;
|
if (drive == -1)
|
||||||
// vfs_node *cd = task_getcwd();
|
return -1;
|
||||||
// if (cd == 0)
|
if (vfs_volumes[drive].funcs->open == 0)
|
||||||
// cd = &vfs_root;
|
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)
|
||||||
|
{
|
||||||
|
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;
|
return 0;
|
||||||
|
if ((!(vfs_files[fd].flags & VFS_FILE_READ)) || (vfs_files[fd].flags &
|
||||||
|
VFS_EOF))
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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…
Reference in New Issue