add first version of a minimal file system and initrd support
This commit is contained in:
parent
2d10d42f0b
commit
d2017a1dd6
6 changed files with 876 additions and 0 deletions
4
fs/Makefile
Normal file
4
fs/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
C_source := fs.c initrd.c
|
||||
MODULE := fs
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
209
fs/fs.c
Normal file
209
fs/fs.c
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <eduos/stdlib.h>
|
||||
#include <eduos/stdio.h>
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/fs.h>
|
||||
#include <eduos/errno.h>
|
||||
#include <eduos/spinlock.h>
|
||||
|
||||
vfs_node_t* fs_root = NULL; // The root of the filesystem.
|
||||
|
||||
ssize_t read_fs(fildes_t* file, uint8_t* buffer, size_t size)
|
||||
{
|
||||
vfs_node_t* node = file->node;
|
||||
ssize_t ret = -EINVAL;
|
||||
|
||||
if (BUILTIN_EXPECT(!node || !buffer, 0))
|
||||
return ret;
|
||||
|
||||
spinlock_lock(&node->lock);
|
||||
// Has the node got a read callback?
|
||||
if (node->read != 0)
|
||||
ret = node->read(file, buffer, size);
|
||||
spinlock_unlock(&node->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t write_fs(fildes_t* file, uint8_t* buffer, size_t size)
|
||||
{
|
||||
vfs_node_t* node = file->node;
|
||||
ssize_t ret = -EINVAL;
|
||||
|
||||
if (BUILTIN_EXPECT(!node || !buffer, 0))
|
||||
return ret;
|
||||
|
||||
spinlock_lock(&node->lock);
|
||||
// Has the node got a write callback?
|
||||
if (node->write != 0)
|
||||
ret = node->write(file, buffer, size);
|
||||
spinlock_unlock(&node->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int open_fs(fildes_t* file, const char* name)
|
||||
{
|
||||
uint32_t ret = 0, i, j = 1;
|
||||
vfs_node_t* file_node = NULL; /* file node */
|
||||
vfs_node_t* dir_node = NULL;
|
||||
char fname[MAX_FNAME];
|
||||
|
||||
if (BUILTIN_EXPECT(!name, 0))
|
||||
return ret;
|
||||
|
||||
if (name[0] == '/')
|
||||
file_node = fs_root;
|
||||
|
||||
while((name[j] != '\0') || ((file_node != NULL) && (file_node->type == FS_DIRECTORY))) {
|
||||
i = 0;
|
||||
while((name[j] != '/') && (name[j] != '\0')) {
|
||||
fname[i] = name[j];
|
||||
i++; j++;
|
||||
}
|
||||
fname[i] = '\0';
|
||||
dir_node = file_node; /* file must be a directory */
|
||||
file_node = finddir_fs(dir_node, fname);
|
||||
if (name[j] == '/')
|
||||
j++;
|
||||
}
|
||||
|
||||
//kprintf("dir_node = %p, file_node = %p, name = %s \n", dir_node, file_node, fname);
|
||||
|
||||
/* file exists */
|
||||
if(file_node) {
|
||||
spinlock_lock(&file_node->lock);
|
||||
file->node = file_node;
|
||||
// Has the file_node got an open callback?
|
||||
if (file_node->open != 0)
|
||||
ret = file->node->open(file, NULL);
|
||||
spinlock_unlock(&file_node->lock);
|
||||
} else if (dir_node) { /* file doesn't exist or opendir was called */
|
||||
spinlock_lock(&dir_node->lock);
|
||||
file->node = dir_node;
|
||||
// Has the dir_node got an open callback?
|
||||
if (dir_node->open != 0)
|
||||
ret = dir_node->open(file, fname);
|
||||
spinlock_unlock(&dir_node->lock);
|
||||
} else {
|
||||
ret = -ENOENT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int close_fs(fildes_t* file)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (BUILTIN_EXPECT(!(file->node), 0))
|
||||
return ret;
|
||||
|
||||
spinlock_lock(&file->node->lock);
|
||||
// Has the node got a close callback?
|
||||
if (file->node->close != 0)
|
||||
ret = file->node->close(file);
|
||||
spinlock_unlock(&file->node->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct dirent* readdir_fs(vfs_node_t * node, uint32_t index)
|
||||
{
|
||||
struct dirent* ret = NULL;
|
||||
|
||||
if (BUILTIN_EXPECT(!node, 0))
|
||||
return ret;
|
||||
|
||||
spinlock_lock(&node->lock);
|
||||
// Is the node a directory, and does it have a callback?
|
||||
if ((node->type == FS_DIRECTORY) && node->readdir != 0)
|
||||
ret = node->readdir(node, index);
|
||||
spinlock_unlock(&node->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vfs_node_t* finddir_fs(vfs_node_t* node, const char *name)
|
||||
{
|
||||
vfs_node_t* ret = NULL;
|
||||
|
||||
if (BUILTIN_EXPECT(!node, 0))
|
||||
return ret;
|
||||
|
||||
spinlock_lock(&node->lock);
|
||||
// Is the node a directory, and does it have a callback?
|
||||
if ((node->type == FS_DIRECTORY) && node->finddir != 0)
|
||||
ret = node->finddir(node, name);
|
||||
spinlock_unlock(&node->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vfs_node_t* mkdir_fs(vfs_node_t* node, const char *name)
|
||||
{
|
||||
vfs_node_t* ret = NULL;
|
||||
|
||||
if (BUILTIN_EXPECT(!node, 0))
|
||||
return ret;
|
||||
|
||||
spinlock_lock(&node->lock);
|
||||
if (node->mkdir != 0)
|
||||
ret = node->mkdir(node, name);
|
||||
spinlock_unlock(&node->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vfs_node_t* findnode_fs(const char* name)
|
||||
{
|
||||
uint32_t i, j = 1;
|
||||
vfs_node_t* ret = NULL;
|
||||
char fname[MAX_FNAME];
|
||||
|
||||
if (BUILTIN_EXPECT(!name, 0))
|
||||
return ret;
|
||||
|
||||
if (name[0] == '/')
|
||||
ret = fs_root;
|
||||
|
||||
while((name[j] != '\0') && ret) {
|
||||
i = 0;
|
||||
while((name[j] != '/') && (name[j] != '\0')) {
|
||||
fname[i] = name[j];
|
||||
i++; j++;
|
||||
}
|
||||
fname[i] = '\0';
|
||||
ret = finddir_fs(ret, fname);
|
||||
if (name[j] == '/')
|
||||
j++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
563
fs/initrd.c
Normal file
563
fs/initrd.c
Normal file
|
@ -0,0 +1,563 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <eduos/stdlib.h>
|
||||
#include <eduos/stdio.h>
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/fs.h>
|
||||
#include <eduos/errno.h>
|
||||
#include <eduos/spinlock.h>
|
||||
#include <asm/multiboot.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
static vfs_node_t initrd_root;
|
||||
|
||||
#define INITRD_MAGIC_NUMBER 0x4711
|
||||
|
||||
/*
|
||||
* Grub maps the initrd as module into the address space of the kernel.
|
||||
* The module begins with the header "initrd_header_t", which describes
|
||||
* the number of mounted files and the mount point. The header follows
|
||||
* by the struct "initrd_file_desc_t" for each file, which will be mounted.
|
||||
* This struct describes the file properties and the position in the
|
||||
* module.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint32_t nfiles;
|
||||
char mount_point[MAX_FNAME];
|
||||
} initrd_header_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t length;
|
||||
uint32_t offset;
|
||||
char fname[MAX_FNAME];
|
||||
} initrd_file_desc_t;
|
||||
|
||||
static ssize_t initrd_read(fildes_t* file, uint8_t* buffer, size_t size)
|
||||
{
|
||||
vfs_node_t* node = file->node;
|
||||
|
||||
uint32_t i, pos = 0, found = 0;
|
||||
off_t offset = 0;
|
||||
char* data = NULL;
|
||||
block_list_t* blist = &node->block_list;
|
||||
|
||||
if (file->flags & O_WRONLY)
|
||||
return -EACCES;
|
||||
|
||||
/* init the tmp offset */
|
||||
offset = file->offset;
|
||||
|
||||
/* searching for the valid data block */
|
||||
if (offset) {
|
||||
pos = offset / node->block_size;
|
||||
offset = offset % node->block_size;
|
||||
}
|
||||
do {
|
||||
for(i=0; i<MAX_DATABLOCKS && !data; i++) {
|
||||
if (blist->data[i]) {
|
||||
found++;
|
||||
if (found > pos)
|
||||
data = (char*) blist->data[i];
|
||||
}
|
||||
}
|
||||
|
||||
blist = blist->next;
|
||||
} while(blist && !data);
|
||||
|
||||
if (BUILTIN_EXPECT(!data, 0))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the data block is not large engough,
|
||||
* we copy only the rest of the current block.
|
||||
* The user has to restart the read operation
|
||||
* for the next block.
|
||||
*/
|
||||
if ((offset + size) >= node->block_size)
|
||||
size = node->block_size - offset;
|
||||
|
||||
memcpy(buffer, data + offset, size);
|
||||
|
||||
file->offset += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t initrd_emu_readdir(fildes_t* file, uint8_t* buffer, size_t size)
|
||||
{
|
||||
vfs_node_t* node = file->node;
|
||||
|
||||
uint32_t i, j, k, count;
|
||||
uint32_t index = file->offset;
|
||||
dirent_t* dirent;
|
||||
dir_block_t* dirblock;
|
||||
block_list_t* blist = &node->block_list;
|
||||
|
||||
do {
|
||||
for(i=0,count=0; i<MAX_DATABLOCKS; i++) {
|
||||
dirblock = (dir_block_t*) blist->data[i];
|
||||
for(j=0; dirblock && j<MAX_DIRENTRIES; j++) {
|
||||
dirent = &dirblock->entries[j];
|
||||
if (dirent->vfs_node) {
|
||||
count++;
|
||||
if (count > index) {
|
||||
k=0;
|
||||
do {
|
||||
buffer[k] = dirent->name[k];
|
||||
k++;
|
||||
} while(dirent->name[k] != '\0');
|
||||
file->offset++;
|
||||
return k;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blist = blist->next;
|
||||
} while(blist);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t initrd_write(fildes_t* file, uint8_t* buffer, size_t size)
|
||||
{
|
||||
uint32_t i, pos = 0, found = 0;
|
||||
off_t offset = 0;
|
||||
char* data = NULL;
|
||||
vfs_node_t* node = file->node;
|
||||
block_list_t* blist = &node->block_list;
|
||||
|
||||
if (file->flags & O_RDONLY)
|
||||
return -EACCES;
|
||||
|
||||
if (file->flags & O_APPEND)
|
||||
file->offset = node->block_size;
|
||||
|
||||
/* init the tmp offset */
|
||||
offset = file->offset;
|
||||
|
||||
/* searching for the valid data block */
|
||||
if (offset) {
|
||||
pos = offset / MAX_DATAENTRIES;
|
||||
offset = offset % MAX_DATAENTRIES;
|
||||
}
|
||||
|
||||
do {
|
||||
for (i = 0; i < MAX_DATABLOCKS && !data; i++) {
|
||||
if ((size + offset) >= MAX_DATAENTRIES)
|
||||
size = MAX_DATAENTRIES - offset;
|
||||
if(!blist->data[i]) {
|
||||
blist->data[i] = (data_block_t*)
|
||||
kmalloc(sizeof(data_block_t));
|
||||
if (blist->data[i])
|
||||
memset(blist->data[i], 0x00,
|
||||
sizeof(data_block_t));
|
||||
}
|
||||
found++;
|
||||
if (found > pos) {
|
||||
data = (char*) blist->data[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!blist->next) {
|
||||
blist->next = (block_list_t*)
|
||||
kmalloc(sizeof(block_list_t));
|
||||
if (blist->next)
|
||||
memset(blist->next, 0x00,
|
||||
sizeof(block_list_t));
|
||||
}
|
||||
blist = blist->next;
|
||||
} while(blist && !data);
|
||||
|
||||
/* you may have to increase nodesize */
|
||||
if (node->block_size < (file->offset + size))
|
||||
node->block_size = file->offset + size;
|
||||
/*
|
||||
* If the data block is not large engough,
|
||||
* we copy only the rest of the current block.
|
||||
* The user has to restart the write operation
|
||||
* for the next block.
|
||||
*/
|
||||
memcpy(data + offset, buffer, size);
|
||||
file->offset += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
static int initrd_open(fildes_t* file, const char* name)
|
||||
{
|
||||
if (file->node->type == FS_FILE) {
|
||||
if ((file->flags & O_CREAT) && (file->flags & O_EXCL))
|
||||
return -EEXIST;
|
||||
|
||||
/* in the case of O_TRUNC kfree all the nodes */
|
||||
if (file->flags & O_TRUNC) {
|
||||
uint32_t i;
|
||||
char* data = NULL;
|
||||
block_list_t* blist = &file->node->block_list;
|
||||
block_list_t* lastblist = NULL;
|
||||
|
||||
/* the first blist pointer have do remain valid. */
|
||||
for(i=0; i<MAX_DATABLOCKS && !data; i++) {
|
||||
if (blist->data[i]) {
|
||||
kfree(blist->data[i],
|
||||
sizeof(data_block_t));
|
||||
}
|
||||
}
|
||||
if (blist->next) {
|
||||
lastblist = blist;
|
||||
blist = blist->next;
|
||||
lastblist->next = NULL;
|
||||
|
||||
/* kfree all other blist pointers */
|
||||
do {
|
||||
for(i=0; i<MAX_DATABLOCKS && !data; i++) {
|
||||
if (blist->data[i]) {
|
||||
kfree(blist->data[i], sizeof(data_block_t));
|
||||
}
|
||||
}
|
||||
lastblist = blist;
|
||||
blist = blist->next;
|
||||
kfree(lastblist, sizeof(block_list_t));
|
||||
} while(blist);
|
||||
}
|
||||
|
||||
/* reset the block_size */
|
||||
file->node->block_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (file->node->type == FS_DIRECTORY) {
|
||||
|
||||
/* opendir was called: */
|
||||
if (name[0] == '\0')
|
||||
return 0;
|
||||
|
||||
/* open file was called: */
|
||||
if (!(file->flags & O_CREAT))
|
||||
return -ENOENT;
|
||||
|
||||
uint32_t i, j;
|
||||
block_list_t* blist = NULL;
|
||||
/* CREATE FILE */
|
||||
vfs_node_t* new_node = kmalloc(sizeof(vfs_node_t));
|
||||
if (BUILTIN_EXPECT(!new_node, 0))
|
||||
return -EINVAL;
|
||||
|
||||
blist = &file->node->block_list;
|
||||
dir_block_t* dir_block;
|
||||
dirent_t* dirent;
|
||||
|
||||
memset(new_node, 0x00, sizeof(vfs_node_t));
|
||||
new_node->type = FS_FILE;
|
||||
new_node->read = initrd_read;
|
||||
new_node->write = initrd_write;
|
||||
new_node->open = initrd_open;
|
||||
spinlock_init(&new_node->lock);
|
||||
|
||||
/* create a entry for the new node in the directory block of current node */
|
||||
do {
|
||||
for(i=0; i<MAX_DATABLOCKS; i++) {
|
||||
if (blist->data[i]) {
|
||||
dir_block = (dir_block_t*) blist->data[i];
|
||||
for(j=0; j<MAX_DIRENTRIES; j++) {
|
||||
dirent = &dir_block->entries[j];
|
||||
if (!dirent->vfs_node) {
|
||||
dirent->vfs_node = new_node;
|
||||
strncpy(dirent->name, (char*) name, MAX_FNAME);
|
||||
goto exit_create_file; // there might be a better Solution ***************
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if all blocks are reserved, we have to allocate a new one */
|
||||
if (!blist->next) {
|
||||
blist->next = (block_list_t*) kmalloc(sizeof(block_list_t));
|
||||
if (blist->next)
|
||||
memset(blist->next, 0x00, sizeof(block_list_t));
|
||||
}
|
||||
|
||||
blist = blist->next;
|
||||
} while(blist);
|
||||
|
||||
exit_create_file:
|
||||
file->node = new_node;
|
||||
file->node->block_size = 0;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static dirent_t* initrd_readdir(vfs_node_t* node, uint32_t index)
|
||||
{
|
||||
uint32_t i, j, count;
|
||||
dirent_t* dirent;
|
||||
dir_block_t* dirblock;
|
||||
block_list_t* blist = &node->block_list;
|
||||
|
||||
do {
|
||||
for(i=0,count=0; i<MAX_DATABLOCKS; i++) {
|
||||
dirblock = (dir_block_t*) blist->data[i];
|
||||
for(j=0; dirblock && j<MAX_DIRENTRIES; j++) {
|
||||
dirent = &dirblock->entries[j];
|
||||
if (dirent->vfs_node) {
|
||||
count++;
|
||||
if (count > index)
|
||||
return dirent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blist = blist->next;
|
||||
} while(blist);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static vfs_node_t* initrd_finddir(vfs_node_t* node, const char *name)
|
||||
{
|
||||
uint32_t i, j;
|
||||
dir_block_t* dirblock;
|
||||
dirent_t* dirent;
|
||||
block_list_t* blist = &node->block_list;
|
||||
|
||||
do {
|
||||
for(i=0; i<MAX_DATABLOCKS; i++) {
|
||||
dirblock = (dir_block_t*) blist->data[i];
|
||||
for(j=0; dirblock && j<MAX_DIRENTRIES; j++) {
|
||||
dirent = &dirblock->entries[j];
|
||||
if (!strncmp(dirent->name, name, MAX_FNAME))
|
||||
return dirent->vfs_node;
|
||||
}
|
||||
}
|
||||
|
||||
blist = blist->next;
|
||||
} while(blist);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static vfs_node_t* initrd_mkdir(vfs_node_t* node, const char* name)
|
||||
{
|
||||
uint32_t i, j;
|
||||
dir_block_t* dir_block;
|
||||
dir_block_t* tmp;
|
||||
dirent_t* dirent;
|
||||
vfs_node_t* new_node;
|
||||
block_list_t* blist = &node->block_list;
|
||||
|
||||
if (BUILTIN_EXPECT(node->type != FS_DIRECTORY, 0))
|
||||
return NULL;
|
||||
|
||||
/* exists already a entry with same name? */
|
||||
if (initrd_finddir(node, name))
|
||||
return NULL;
|
||||
|
||||
new_node = kmalloc(sizeof(vfs_node_t));
|
||||
if (BUILTIN_EXPECT(!new_node, 0))
|
||||
return NULL;
|
||||
|
||||
memset(new_node, 0x00, sizeof(vfs_node_t));
|
||||
new_node->type = FS_DIRECTORY;
|
||||
new_node->read = &initrd_emu_readdir;
|
||||
new_node->readdir = &initrd_readdir;
|
||||
new_node->finddir = &initrd_finddir;
|
||||
new_node->mkdir = &initrd_mkdir;
|
||||
new_node->open = &initrd_open;
|
||||
spinlock_init(&new_node->lock);
|
||||
|
||||
/* create default directory entry */
|
||||
dir_block = (dir_block_t*) kmalloc(sizeof(dir_block_t));
|
||||
if (BUILTIN_EXPECT(!dir_block, 0))
|
||||
goto out;
|
||||
memset(dir_block, 0x00, sizeof(dir_block_t));
|
||||
new_node->block_list.data[0] = dir_block;
|
||||
strncpy(dir_block->entries[0].name, ".", MAX_FNAME);
|
||||
dir_block->entries[0].vfs_node = new_node;
|
||||
strncpy(dir_block->entries[1].name, "..", MAX_FNAME);
|
||||
dir_block->entries[1].vfs_node = node;
|
||||
|
||||
do {
|
||||
/* searching for a free directory block */
|
||||
for(i=0; i<MAX_DATABLOCKS; i++) {
|
||||
if (blist->data[i]) {
|
||||
tmp = (dir_block_t*) blist->data[i];
|
||||
for(j=0; j<MAX_DIRENTRIES; j++) {
|
||||
dirent = &tmp->entries[j];
|
||||
if (!dirent->vfs_node) {
|
||||
dirent->vfs_node = new_node;
|
||||
strncpy(dirent->name, name, MAX_FNAME);
|
||||
return new_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if all blocks are reserved, we have to allocate a new one */
|
||||
if (!blist->next) {
|
||||
blist->next = (block_list_t*) kmalloc(sizeof(block_list_t));
|
||||
if (blist->next)
|
||||
memset(blist->next, 0x00, sizeof(block_list_t));
|
||||
}
|
||||
|
||||
blist = blist->next;
|
||||
} while(blist);
|
||||
|
||||
kfree(dir_block, sizeof(dir_block_t));
|
||||
out:
|
||||
kfree(new_node, sizeof(vfs_node_t));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int initrd_init(void)
|
||||
{
|
||||
dir_block_t* dir_block;
|
||||
vfs_node_t* tmp;
|
||||
uint32_t i, j, k, l;
|
||||
uint32_t mods_count = 0;
|
||||
multiboot_module_t* mmodule = NULL;
|
||||
|
||||
if (mb_info && (mb_info->flags & MULTIBOOT_INFO_MODS)) {
|
||||
mmodule = (multiboot_module_t*) ((size_t) mb_info->mods_addr);
|
||||
mods_count = mb_info->mods_count;
|
||||
}
|
||||
|
||||
/* Initialize the root directory. */
|
||||
fs_root = &initrd_root;
|
||||
memset(&initrd_root, 0x00, sizeof(vfs_node_t));
|
||||
initrd_root.type = FS_DIRECTORY;
|
||||
initrd_root.read = &initrd_emu_readdir;
|
||||
initrd_root.readdir = &initrd_readdir;
|
||||
initrd_root.finddir = &initrd_finddir;
|
||||
initrd_root.mkdir = &initrd_mkdir;
|
||||
initrd_root.open = &initrd_open;
|
||||
spinlock_init(&initrd_root.lock);
|
||||
|
||||
/* create default directory block */
|
||||
dir_block = (dir_block_t*) kmalloc(sizeof(dir_block_t));
|
||||
if (BUILTIN_EXPECT(!dir_block, 0))
|
||||
return -ENOMEM;
|
||||
memset(dir_block, 0x00, sizeof(dir_block_t));
|
||||
initrd_root.block_list.data[0] = dir_block;
|
||||
strncpy(dir_block->entries[0].name, ".", MAX_FNAME);
|
||||
dir_block->entries[0].vfs_node = fs_root;
|
||||
strncpy(dir_block->entries[1].name, "..", MAX_FNAME);
|
||||
dir_block->entries[1].vfs_node = fs_root;
|
||||
|
||||
/* create the directory bin and dev */
|
||||
mkdir_fs(fs_root, "bin");
|
||||
mkdir_fs(fs_root, "sbin");
|
||||
tmp = mkdir_fs(fs_root, "dev");
|
||||
|
||||
/* create the character device "kmessages" */
|
||||
tmp = mkdir_fs(fs_root, "var");
|
||||
kmsg_init(tmp, "log");
|
||||
|
||||
/* For every module.. */
|
||||
for(i=0; i<mods_count; i++) {
|
||||
initrd_header_t* header = (initrd_header_t*) ((size_t) mmodule[i].mod_start);
|
||||
|
||||
initrd_file_desc_t* file_desc;
|
||||
vfs_node_t* new_node;
|
||||
|
||||
if (BUILTIN_EXPECT(header->magic != INITRD_MAGIC_NUMBER, 0)) {
|
||||
kprintf("Invalid magic number for a init ram disk: 0x%x\n", header->magic);
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp = findnode_fs(header->mount_point);
|
||||
if (BUILTIN_EXPECT(!tmp, 0)) {
|
||||
kprintf("Did not found mount point %s.\n", header->mount_point);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BUILTIN_EXPECT(tmp->type != FS_DIRECTORY, 0)) {
|
||||
kprintf("%s is not a valid mount point.\n", header->mount_point);
|
||||
continue;
|
||||
}
|
||||
|
||||
file_desc = (initrd_file_desc_t*) (header + 1);
|
||||
for(j=0; j<header->nfiles; j++) {
|
||||
block_list_t* blist;
|
||||
dir_block_t* dir_block;
|
||||
dirent_t* dirent;
|
||||
|
||||
if (finddir_fs(tmp, file_desc->fname)) {
|
||||
kprintf("Error: %s alreay exits\n", file_desc->fname);
|
||||
goto next_file;
|
||||
}
|
||||
|
||||
/* create a new node and map the module as data block */
|
||||
new_node = kmalloc(sizeof(vfs_node_t));
|
||||
if (BUILTIN_EXPECT(!new_node, 0)) {
|
||||
kprintf("Not enough memory to create new initrd node\n");
|
||||
goto next_file;
|
||||
}
|
||||
memset(new_node, 0x00, sizeof(vfs_node_t));
|
||||
new_node->type = FS_FILE;
|
||||
new_node->read = initrd_read;
|
||||
new_node->write = initrd_write;
|
||||
new_node->open = initrd_open;
|
||||
new_node->block_size = file_desc->length;
|
||||
new_node->block_list.data[0] = ((char*) header) + file_desc->offset;
|
||||
spinlock_init(&new_node->lock);
|
||||
|
||||
/* create a entry for the new node in the directory block of current node */
|
||||
blist = &tmp->block_list;
|
||||
do {
|
||||
for(k=0; k<MAX_DATABLOCKS; k++) {
|
||||
if (blist->data[k]) {
|
||||
dir_block = (dir_block_t*) blist->data[k];
|
||||
for(l=0; l<MAX_DIRENTRIES; l++) {
|
||||
dirent = &dir_block->entries[l];
|
||||
if (!dirent->vfs_node) {
|
||||
dirent->vfs_node = new_node;
|
||||
strncpy(dirent->name, file_desc->fname, MAX_FNAME);
|
||||
goto next_file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if all blocks are reserved, we have to allocate a new one */
|
||||
if (!blist->next) {
|
||||
blist->next = (block_list_t*) kmalloc(sizeof(block_list_t));
|
||||
if (blist->next)
|
||||
memset(blist->next, 0x00, sizeof(block_list_t));
|
||||
}
|
||||
|
||||
blist = blist->next;
|
||||
} while(blist);
|
||||
next_file:
|
||||
file_desc++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -34,6 +34,7 @@ extern "C" {
|
|||
|
||||
#define EDUOS_VERSION "0.1"
|
||||
#define MAX_TASKS 16
|
||||
#define MAX_FNAME 128
|
||||
#define TIMER_FREQ 100 /* in HZ */
|
||||
#define CLOCK_TICK_RATE 1193182 /* 8254 chip's internal oscillator frequency */
|
||||
#define VIDEO_MEM_ADDR 0xB8000 /* the video memory address */
|
||||
|
|
|
@ -126,6 +126,7 @@ static int eduos_init(void)
|
|||
#ifdef CONFIG_UART
|
||||
uart_init();
|
||||
#endif
|
||||
initrd_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -26,9 +26,11 @@
|
|||
*/
|
||||
|
||||
#include <eduos/stdio.h>
|
||||
#include <eduos/stdlib.h>
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/stdarg.h>
|
||||
#include <eduos/spinlock.h>
|
||||
#include <eduos/fs.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/multiboot.h>
|
||||
|
@ -52,6 +54,102 @@ static spinlock_irqsave_t olock = SPINLOCK_IRQSAVE_INIT;
|
|||
static atomic_int32_t kmsg_counter = ATOMIC_INIT(0);
|
||||
static unsigned char kmessages[KMSG_SIZE] __attribute__ ((section(".kmsg"))) = {[0 ... KMSG_SIZE-1] = 0x00};
|
||||
|
||||
static ssize_t kmsg_read(fildes_t* file, uint8_t* buffer, size_t size)
|
||||
{
|
||||
size_t start, i = 0;
|
||||
|
||||
if (BUILTIN_EXPECT(!buffer, 0))
|
||||
return -EINVAL;
|
||||
if (BUILTIN_EXPECT(!size, 0))
|
||||
return 0;
|
||||
|
||||
if (kmessages[(atomic_int32_read(&kmsg_counter) + 1) % KMSG_SIZE] == 0)
|
||||
start = 0;
|
||||
else
|
||||
start = (atomic_int32_read(&kmsg_counter) + 1) % KMSG_SIZE;
|
||||
|
||||
if (((start + file->offset) % KMSG_SIZE) == atomic_int32_read(&kmsg_counter))
|
||||
return 0;
|
||||
if (file->offset >= KMSG_SIZE)
|
||||
return 0;
|
||||
|
||||
for(i=0; i<size; i++, file->offset++) {
|
||||
buffer[i] = kmessages[(start + file->offset) % KMSG_SIZE];
|
||||
if (((start + file->offset) % KMSG_SIZE) == atomic_int32_read(&kmsg_counter))
|
||||
return i;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int kmsg_open(fildes_t* file, const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kmsg_close(fildes_t* file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Init Functions */
|
||||
int kmsg_init(vfs_node_t * node, const char *name)
|
||||
{
|
||||
uint32_t i, j;
|
||||
vfs_node_t* new_node;
|
||||
dir_block_t* blockdir;
|
||||
dirent_t* dirent;
|
||||
block_list_t* blist;
|
||||
|
||||
if (BUILTIN_EXPECT(!node || !name, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (BUILTIN_EXPECT(node->type != FS_DIRECTORY, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (finddir_fs(node, name))
|
||||
return -EINVAL;
|
||||
|
||||
new_node = kmalloc(sizeof(vfs_node_t));
|
||||
if (BUILTIN_EXPECT(!new_node, 0))
|
||||
return -ENOMEM;
|
||||
|
||||
memset(new_node, 0x00, sizeof(vfs_node_t));
|
||||
new_node->type = FS_CHARDEVICE;
|
||||
new_node->open = &kmsg_open;
|
||||
new_node->close = &kmsg_close;
|
||||
new_node->read = &kmsg_read;
|
||||
new_node->write = NULL;
|
||||
spinlock_init(&new_node->lock);
|
||||
|
||||
blist = &node->block_list;
|
||||
do {
|
||||
for (i = 0; i < MAX_DATABLOCKS; i++) {
|
||||
if (blist->data[i]) {
|
||||
blockdir = (dir_block_t *) blist->data[i];
|
||||
for (j = 0; j < MAX_DIRENTRIES; j++) {
|
||||
dirent = &blockdir->entries[j];
|
||||
if (!dirent->vfs_node) {
|
||||
dirent->vfs_node = new_node;
|
||||
strncpy(dirent->name, name, MAX_FNAME);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!blist->next) {
|
||||
blist->next = (block_list_t *) kmalloc(sizeof(block_list_t));
|
||||
if (blist->next)
|
||||
memset(blist->next, 0x00, sizeof(block_list_t));
|
||||
}
|
||||
} while (blist);
|
||||
|
||||
kfree(new_node, sizeof(vfs_node_t));
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int koutput_init(void)
|
||||
{
|
||||
#ifdef CONFIG_VGA
|
||||
|
|
Loading…
Add table
Reference in a new issue