Really hack VFS implementation
This commit is contained in:
parent
22f04f137b
commit
8dd2686b40
0
hdd/dev/hello
Normal file
0
hdd/dev/hello
Normal file
0
hdd/dev/null
Normal file
0
hdd/dev/null
Normal file
0
hdd/dev/ttyS0
Normal file
0
hdd/dev/ttyS0
Normal file
0
hdd/dev/ttyS1
Normal file
0
hdd/dev/ttyS1
Normal file
0
hdd/dev/ttyS2
Normal file
0
hdd/dev/ttyS2
Normal file
0
hdd/dev/ttyS3
Normal file
0
hdd/dev/ttyS3
Normal file
@ -1108,7 +1108,7 @@ void ext2_disk_mount(uint32_t offset_sector, uint32_t max_sector) {
|
||||
debug_print(NOTICE, "Oh dear...");
|
||||
}
|
||||
debug_print(NOTICE, "Root file system is ready.");
|
||||
fs_root = RN;
|
||||
vfs_mount("/", RN);
|
||||
debug_print(NOTICE, "Mounted EXT2 disk, root VFS node is at 0x%x", RN);
|
||||
}
|
||||
|
||||
|
54
kernel/fs/hellodev.c
Normal file
54
kernel/fs/hellodev.c
Normal file
@ -0,0 +1,54 @@
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* A device that returns "hello world" when read from.
|
||||
*/
|
||||
|
||||
#include <system.h>
|
||||
#include <fs.h>
|
||||
|
||||
uint32_t read_hello(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
|
||||
uint32_t write_hello(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
|
||||
void open_hello(fs_node_t *node, uint8_t read, uint8_t write);
|
||||
void close_hello(fs_node_t *node);
|
||||
|
||||
char hello[] = "hello world";
|
||||
|
||||
uint32_t read_hello(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
|
||||
uint32_t s = 0;
|
||||
int d = strlen(hello);
|
||||
while (s < size) {
|
||||
buffer[offset] = hello[offset % d];
|
||||
offset++;
|
||||
s++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t write_hello(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
|
||||
return size;
|
||||
}
|
||||
|
||||
void open_hello(fs_node_t * node, uint8_t read, uint8_t write) {
|
||||
return;
|
||||
}
|
||||
|
||||
void close_hello(fs_node_t * node) {
|
||||
return;
|
||||
}
|
||||
|
||||
fs_node_t * hello_device_create() {
|
||||
fs_node_t * fnode = malloc(sizeof(fs_node_t));
|
||||
memset(fnode, 0x00, sizeof(fs_node_t));
|
||||
fnode->inode = 0;
|
||||
strcpy(fnode->name, "hello");
|
||||
fnode->uid = 0;
|
||||
fnode->gid = 0;
|
||||
fnode->length = strlen(hello);
|
||||
fnode->flags = FS_CHARDEVICE;
|
||||
fnode->read = read_hello;
|
||||
fnode->write = write_hello;
|
||||
fnode->open = open_hello;
|
||||
fnode->close = close_hello;
|
||||
fnode->readdir = NULL;
|
||||
fnode->finddir = NULL;
|
||||
return fnode;
|
||||
}
|
@ -32,11 +32,12 @@ void close_null(fs_node_t * node) {
|
||||
|
||||
fs_node_t * null_device_create() {
|
||||
fs_node_t * fnode = malloc(sizeof(fs_node_t));
|
||||
memset(fnode, 0x00, sizeof(fs_node_t));
|
||||
fnode->inode = 0;
|
||||
strcpy(fnode->name, "null");
|
||||
fnode->uid = 0;
|
||||
fnode->gid = 0;
|
||||
fnode->flags = 0;
|
||||
fnode->flags = FS_CHARDEVICE;
|
||||
fnode->read = read_null;
|
||||
fnode->write = write_null;
|
||||
fnode->open = open_null;
|
||||
|
@ -46,6 +46,7 @@ void close_serial(fs_node_t * node) {
|
||||
|
||||
fs_node_t * serial_device_create(int device) {
|
||||
fs_node_t * fnode = malloc(sizeof(fs_node_t));
|
||||
memset(fnode, 0x00, sizeof(fs_node_t));
|
||||
fnode->inode = device;
|
||||
strcpy(fnode->name, "serial");
|
||||
fnode->uid = 0;
|
||||
@ -64,3 +65,19 @@ fs_node_t * serial_device_create(int device) {
|
||||
|
||||
return fnode;
|
||||
}
|
||||
|
||||
void serial_mount_devices() {
|
||||
|
||||
fs_node_t * ttyS0 = serial_device_create(SERIAL_PORT_A);
|
||||
vfs_mount("/dev/ttyS0", ttyS0);
|
||||
|
||||
fs_node_t * ttyS1 = serial_device_create(SERIAL_PORT_B);
|
||||
vfs_mount("/dev/ttyS1", ttyS1);
|
||||
|
||||
fs_node_t * ttyS2 = serial_device_create(SERIAL_PORT_C);
|
||||
vfs_mount("/dev/ttyS2", ttyS2);
|
||||
|
||||
fs_node_t * ttyS3 = serial_device_create(SERIAL_PORT_D);
|
||||
vfs_mount("/dev/ttyS3", ttyS3);
|
||||
|
||||
}
|
||||
|
214
kernel/fs/vfs.c
214
kernel/fs/vfs.c
@ -9,7 +9,8 @@
|
||||
#include <process.h>
|
||||
#include <logging.h>
|
||||
|
||||
fs_node_t *fs_root = 0;
|
||||
tree_t * fs_tree = NULL; /* File system mountpoint tree */
|
||||
fs_node_t * fs_root = NULL; /* Pointer to the root mount fs_node (must be some form of filesystem, even ramdisk) */
|
||||
|
||||
/**
|
||||
* read_fs: Read a file system node based on its underlying type.
|
||||
@ -323,63 +324,191 @@ char *canonicalize_path(char *cwd, char *input) {
|
||||
return output;
|
||||
}
|
||||
|
||||
struct vfs_entry {
|
||||
char * name;
|
||||
fs_node_t * file; /* Or null */
|
||||
};
|
||||
|
||||
void vfs_install() {
|
||||
/* Initialize the mountpoint tree */
|
||||
fs_tree = tree_create();
|
||||
|
||||
struct vfs_entry * root = malloc(sizeof(struct vfs_entry));
|
||||
|
||||
root->name = strdup("[root]");
|
||||
root->file = NULL; /* Nothing mounted as root */
|
||||
|
||||
tree_set_root(fs_tree, root);
|
||||
}
|
||||
|
||||
/**
|
||||
* vfs_mount - Mount a file system to the specified path.
|
||||
*
|
||||
* For example, if we have an EXT2 filesystem with a root node
|
||||
* of ext2_root and we want to mount it to /, we would run
|
||||
* vfs_mount("/", ext2_root); - or, if we have a procfs node,
|
||||
* we could mount that to /dev/procfs. Individual files can also
|
||||
* be mounted.
|
||||
*
|
||||
* Paths here must be absolute.
|
||||
*/
|
||||
int vfs_mount(char * path, fs_node_t * local_root) {
|
||||
if (!fs_tree) {
|
||||
debug_print(ERROR, "VFS hasn't been initialized, you can't mount things yet!");
|
||||
return 1;
|
||||
}
|
||||
if (!path || path[0] != '/') {
|
||||
debug_print(ERROR, "Path must be absolute for mountpoint.");
|
||||
return 2;
|
||||
}
|
||||
|
||||
int ret_val = 0;
|
||||
|
||||
char * p = strdup(path);
|
||||
char * i = p;
|
||||
|
||||
int path_len = strlen(p);
|
||||
|
||||
/* Chop the path up */
|
||||
while (i < p + path_len) {
|
||||
if (*i == PATH_SEPARATOR) {
|
||||
*i = '\0';
|
||||
}
|
||||
i++;
|
||||
}
|
||||
/* Clean up */
|
||||
p[path_len] = '\0';
|
||||
i = p + 1;
|
||||
|
||||
/* Root */
|
||||
tree_node_t * root_node = fs_tree->root;
|
||||
|
||||
if (*i == '\0') {
|
||||
/* Special case, we're trying to set the root node */
|
||||
struct vfs_entry * root = (struct vfs_entry *)root_node->value;
|
||||
if (root->file) {
|
||||
debug_print(WARNING, "Path %s already mounted, unmount before trying to mount something else.", path);
|
||||
ret_val = 3;
|
||||
goto _vfs_cleanup;
|
||||
}
|
||||
root->file = local_root;
|
||||
/* We also keep a legacy shortcut around for that */
|
||||
fs_root = local_root;
|
||||
} else {
|
||||
tree_node_t * node = root_node;
|
||||
char * at = i;
|
||||
while (1) {
|
||||
if (at >= p + path_len) {
|
||||
break;
|
||||
}
|
||||
int found = 0;
|
||||
debug_print(INFO, "Searching for %s", at);
|
||||
foreach(child, node->children) {
|
||||
tree_node_t * tchild = (tree_node_t *)child->value;
|
||||
struct vfs_entry * ent = (struct vfs_entry *)tchild->value;
|
||||
if (!strcmp(ent->name, at)) {
|
||||
found = 1;
|
||||
node = tchild;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
debug_print(INFO, "Did not find %s, making it.", at);
|
||||
struct vfs_entry * ent = malloc(sizeof(struct vfs_entry));
|
||||
ent->name = strdup(at);
|
||||
ent->file = NULL;
|
||||
node = tree_node_insert_child(fs_tree, node, ent);
|
||||
}
|
||||
at = at + strlen(at) + 1;
|
||||
}
|
||||
struct vfs_entry * ent = (struct vfs_entry *)node->value;
|
||||
if (ent->file) {
|
||||
debug_print(WARNING, "Path %s already mounted, unmount before trying to mount something else.", path);
|
||||
ret_val = 3;
|
||||
goto _vfs_cleanup;
|
||||
}
|
||||
ent->file = local_root;
|
||||
}
|
||||
|
||||
_vfs_cleanup:
|
||||
free(p);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
void debug_print_vfs_tree_node(tree_node_t * node, size_t height) {
|
||||
/* End recursion on a blank entry */
|
||||
if (!node) return;
|
||||
/* Indent output */
|
||||
for (uint32_t i = 0; i < height; ++i) { kprintf(" "); }
|
||||
/* Get the current process */
|
||||
struct vfs_entry * fnode = (struct vfs_entry *)node->value;
|
||||
/* Print the process name */
|
||||
if (fnode->file) {
|
||||
kprintf("%s → 0x%x (%s)", fnode->name, fnode->file, fnode->file->name);
|
||||
} else {
|
||||
kprintf("%s → (empty)", fnode->name);
|
||||
}
|
||||
/* Linefeed */
|
||||
kprintf("\n");
|
||||
foreach(child, node->children) {
|
||||
/* Recursively print the children */
|
||||
debug_print_vfs_tree_node(child->value, height + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void debug_print_vfs_tree() {
|
||||
debug_print_vfs_tree_node(fs_tree->root, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* get_mount_point
|
||||
*
|
||||
*/
|
||||
fs_node_t *get_mount_point(char * path, size_t path_depth) {
|
||||
#if 0
|
||||
fs_node_t *get_mount_point(char * path, size_t path_depth, char **outpath) {
|
||||
size_t depth;
|
||||
|
||||
kprintf("[root]");
|
||||
for (depth = 0; depth <= path_depth; ++depth) {
|
||||
kprintf("%s%c", path, (depth == path_depth) ? '\n' : '/');
|
||||
path += strlen(path) + 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
tree_node_t * tnode = from;
|
||||
foreach(node, tnode->children) {
|
||||
tree_node_t * _node = (tree_node_t *)node->value;
|
||||
shm_node_t * snode = (shm_node_t *)_node->value;
|
||||
/* Last available node */
|
||||
fs_node_t * last = fs_root;
|
||||
tree_node_t * node = fs_tree->root;
|
||||
|
||||
if (!strcmp(snode->name, pch)) {
|
||||
if (*save == '\0') {
|
||||
return snode;
|
||||
char * at = *outpath;
|
||||
|
||||
while (1) {
|
||||
if (at >= path) {
|
||||
break;
|
||||
}
|
||||
int found = 0;
|
||||
debug_print(INFO, "Searching for %s", at);
|
||||
foreach(child, node->children) {
|
||||
tree_node_t * tchild = (tree_node_t *)child->value;
|
||||
struct vfs_entry * ent = (struct vfs_entry *)tchild->value;
|
||||
if (!strcmp(ent->name, at)) {
|
||||
found = 1;
|
||||
node = tchild;
|
||||
at = at + strlen(at) + 1;
|
||||
if (ent->file) {
|
||||
last = ent->file;
|
||||
*outpath = at;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return _get_node(save, create, _node);
|
||||
}
|
||||
if (!found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
for (depth = 0; depth < path_depth; ++depth) {
|
||||
/* Search the active directory for the requested directory */
|
||||
node_next = finddir_fs(node_ptr, path_offset);
|
||||
free(node_ptr);
|
||||
node_ptr = node_next;
|
||||
if (!node_ptr) {
|
||||
/* We failed to find the requested directory */
|
||||
/* XXX: This is where we should be checking other file system mappings */
|
||||
free((void *)path);
|
||||
return NULL;
|
||||
} else if (depth == path_depth - 1) {
|
||||
/* We found the file and are done, open the node */
|
||||
open_fs(node_ptr, 1, 0);
|
||||
free((void *)path);
|
||||
return node_ptr;
|
||||
}
|
||||
/* We are still searching... */
|
||||
path_offset += strlen(path_offset) + 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return fs_root;
|
||||
return last;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* kopen: Open a file by name.
|
||||
*
|
||||
@ -446,7 +575,12 @@ fs_node_t *kopen(char *filename, uint32_t flags) {
|
||||
uint32_t depth;
|
||||
fs_node_t *node_ptr = malloc(sizeof(fs_node_t));
|
||||
/* Find the mountpoint for this file */
|
||||
fs_node_t *mount_point = get_mount_point(path, path_depth);
|
||||
fs_node_t *mount_point = get_mount_point(path, path_depth, &path_offset);
|
||||
|
||||
if (path_offset >= path+path_len) {
|
||||
free(path);
|
||||
return mount_point;
|
||||
}
|
||||
/* Set the active directory to the mountpoint */
|
||||
memcpy(node_ptr, mount_point, sizeof(fs_node_t));
|
||||
fs_node_t *node_next = NULL;
|
||||
|
@ -86,6 +86,9 @@ struct stat {
|
||||
extern fs_node_t *fs_root;
|
||||
extern fs_node_t * null_device_create();
|
||||
extern fs_node_t * serial_device_create(int device);
|
||||
extern void serial_mount_devices();
|
||||
|
||||
extern fs_node_t * hello_device_create();
|
||||
|
||||
uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
|
||||
uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
|
||||
@ -99,4 +102,10 @@ fs_node_t *kopen(char *filename, uint32_t flags);
|
||||
char *canonicalize_path(char *cwd, char *input);
|
||||
fs_node_t *clone_fs(fs_node_t * source);
|
||||
|
||||
void vfs_install();
|
||||
int vfs_mount(char * path, fs_node_t * local_root);
|
||||
|
||||
/* Debug purposes only, please */
|
||||
void debug_print_vfs_tree();
|
||||
|
||||
#endif
|
||||
|
@ -114,6 +114,8 @@ int main(struct multiboot *mboot, uint32_t mboot_mag, uintptr_t esp) {
|
||||
paging_install(mboot_ptr->mem_upper + mboot_ptr->mem_lower); /* Paging */
|
||||
heap_install(); /* Kernel heap */
|
||||
|
||||
vfs_install();
|
||||
|
||||
/* Hardware drivers */
|
||||
timer_install(); /* PIC driver */
|
||||
serial_install(); /* Serial console */
|
||||
@ -132,6 +134,20 @@ int main(struct multiboot *mboot, uint32_t mboot_mag, uintptr_t esp) {
|
||||
parse_args(cmdline);
|
||||
}
|
||||
|
||||
/*
|
||||
vfs_mount("/foo/bar/baz", fs_root);
|
||||
vfs_mount("/foo/bar/loof", fs_root);
|
||||
vfs_mount("/raz/daz/bar", fs_root);
|
||||
*/
|
||||
|
||||
serial_mount_devices();
|
||||
vfs_mount("/dev/null", null_device_create());
|
||||
vfs_mount("/dev/hello", hello_device_create());
|
||||
|
||||
debug_print_vfs_tree();
|
||||
|
||||
//assert(0);
|
||||
|
||||
if (ramdisk && !fs_root) {
|
||||
kprintf("---- ramdisk[0x%x:0x%x]\n", ramdisk, ramdisk_top);
|
||||
for (uintptr_t i = (uintptr_t)ramdisk; i <= (uintptr_t)ramdisk_top; i += 0x1000) {
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "lib/pthread.h"
|
||||
#include "../kernel/include/signal.h"
|
||||
|
||||
DEFN_SYSCALL1(serial, 44, int);
|
||||
int fd = 0;
|
||||
|
||||
int child_pid = 0;
|
||||
@ -35,25 +34,19 @@ void *print_serial_stuff(void * garbage) {
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
int device = 0x2F8;
|
||||
pthread_t receive_thread;
|
||||
pthread_t flush_thread;
|
||||
char * device = argv[1];
|
||||
|
||||
if (argc > 1) {
|
||||
if (!strcmp(argv[1], "com1")) {
|
||||
device = 0x3F8;
|
||||
} else if (!strcmp(argv[1], "com2")) {
|
||||
device = 0x2F8;
|
||||
} else {
|
||||
fprintf(stderr, "Unrecognized com device, try com1 or com2; default is com2.\n");
|
||||
return 1;
|
||||
}
|
||||
if (argc < 1) {
|
||||
device = "/dev/ttyS0";
|
||||
}
|
||||
|
||||
printf("\033[1560z");
|
||||
fflush(stdout);
|
||||
|
||||
fd = syscall_serial(device);
|
||||
fd = syscall_open(device, 0, 0);
|
||||
|
||||
pthread_create(&receive_thread, NULL, print_serial_stuff, NULL);
|
||||
|
||||
while (1) {
|
||||
|
Loading…
Reference in New Issue
Block a user