Merge remote-tracking branch 'origin/ohligs'
This commit is contained in:
commit
89eeef276b
22 changed files with 1087 additions and 178 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -7,14 +7,18 @@
|
|||
*.img
|
||||
*.a
|
||||
*.log
|
||||
*.swp
|
||||
*.DS_Store
|
||||
*.swp
|
||||
tags
|
||||
Makefile
|
||||
include/metalsvm/config.h
|
||||
tools/make_initrd
|
||||
newlib/examples/hello
|
||||
newlib/examples/jacobi
|
||||
newlib/examples/echo
|
||||
newlib/examples/tests
|
||||
newlib/examples/jacobi
|
||||
newlib/examples/mshell
|
||||
newlib/examples/server
|
||||
newlib/examples/client
|
||||
newlib/tmp/*
|
||||
|
|
|
@ -59,7 +59,6 @@ newlib:
|
|||
RANLIB_FOR_TARGET=$(RANLIB_FOR_TARGET) \
|
||||
STRIP_FOR_TARGET=$(STRIP_FOR_TARGET) \
|
||||
READELF_FOR_TARGET=$(READELF_FOR_TARGET) -C newlib
|
||||
|
||||
tools:
|
||||
$(MAKE) -C tools
|
||||
|
||||
|
|
|
@ -43,6 +43,18 @@ extern "C" {
|
|||
*/
|
||||
void keyboard_init(void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* buffer;
|
||||
size_t maxsize;
|
||||
size_t size;
|
||||
tid_t tid;
|
||||
} kb_buffer_t;
|
||||
|
||||
extern kb_buffer_t kb_buffer;
|
||||
|
||||
void kb_flush();
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -17,13 +17,26 @@
|
|||
* This file is part of MetalSVM.
|
||||
*/
|
||||
|
||||
#include <metalsvm/stdlib.h>
|
||||
#include <metalsvm/stdio.h>
|
||||
#include <metalsvm/string.h>
|
||||
#include <metalsvm/tasks.h>
|
||||
#include <asm/kb.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#ifdef CONFIG_KEYBOARD
|
||||
|
||||
kb_buffer_t kb_buffer = {NULL, 0, 0, 0 };
|
||||
|
||||
void kb_flush() {
|
||||
kfree(kb_buffer.buffer, (kb_buffer.maxsize * sizeof(char)));
|
||||
kb_buffer.buffer = NULL;
|
||||
kb_buffer.size = 0;
|
||||
kb_buffer.maxsize = 0;
|
||||
kb_buffer.tid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* KBDUS means US Keyboard Layout. This is a scancode table
|
||||
* used to layout a standard US keyboard. I have left some
|
||||
|
@ -42,8 +55,8 @@ static const unsigned char kbdus[128] = { 0, 27, '1', '2', '3', '4', '5', '6', '
|
|||
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */
|
||||
'm', ',', '.', '/', 0, /* Right shift */
|
||||
'*', 0, /* Alt */
|
||||
' ', /* Space bar */
|
||||
0, /* Caps lock */
|
||||
' ', /* 57 - Space bar */
|
||||
0, /* 58 - Caps lock */
|
||||
0, /* 59 - F1 key ... > */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, /* < ... F10 */
|
||||
0, /* 69 - Num lock */
|
||||
|
@ -98,7 +111,26 @@ static void keyboard_handler(struct state *r)
|
|||
* held. If shift is held using the larger lookup table,
|
||||
* you would add 128 to the scancode when you look for it
|
||||
*/
|
||||
kputchar(kbdus[scancode]);
|
||||
if (kb_buffer.size <= kb_buffer.maxsize && kb_buffer.buffer != NULL) {
|
||||
if (scancode == 14) {
|
||||
if (kb_buffer.size != 0) {
|
||||
kb_buffer.size--;
|
||||
kputchar(kbdus[scancode]);
|
||||
kputchar(kbdus[57]);
|
||||
kputchar(kbdus[scancode]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
kputchar(kbdus[scancode]);
|
||||
memcpy(kb_buffer.buffer + kb_buffer.size, &kbdus[scancode], 1);
|
||||
kb_buffer.size++;
|
||||
}
|
||||
if (scancode == 28 || scancode == 15 || kb_buffer.size >= kb_buffer.maxsize) {
|
||||
kputchar(kbdus[scancode]);
|
||||
wakeup_task(kb_buffer.tid);
|
||||
reschedule();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
C_source := null.c
|
||||
C_source := stdio.c socket.c
|
||||
|
||||
MODULE := drivers_char
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
||||
|
|
65
drivers/char/null.c → drivers/char/socket.c
Normal file → Executable file
65
drivers/char/null.c → drivers/char/socket.c
Normal file → Executable file
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2010 Stefan Lankes, Chair for Operating Systems,
|
||||
* Copyright 2011 Marian Ohligs, Chair for Operating Systems,
|
||||
* RWTH Aachen University
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -22,32 +22,67 @@
|
|||
#include <metalsvm/stdio.h>
|
||||
#include <metalsvm/errno.h>
|
||||
#include <metalsvm/fs.h>
|
||||
#include <metalsvm/spinlock.h>
|
||||
#include <lwip/opt.h>
|
||||
|
||||
/* Implementation of a simple null device */
|
||||
#if defined(CONFIG_LWIP) && LWIP_SOCKET
|
||||
#include <lwip/mem.h>
|
||||
#include <lwip/raw.h>
|
||||
#include <lwip/icmp.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <lwip/sys.h>
|
||||
#include <lwip/timers.h>
|
||||
#include <lwip/inet_chksum.h>
|
||||
#include <lwip/ip.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/inet.h>
|
||||
#include <lwip/err.h>
|
||||
#endif
|
||||
|
||||
static ssize_t null_read(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset)
|
||||
|
||||
/* Implementation of a simple netio device */
|
||||
|
||||
static ssize_t socket_read(fildes_t* file, uint8_t* buffer, size_t size)
|
||||
{
|
||||
memset(buffer, 0x00, size);
|
||||
int ret = 0;
|
||||
#if defined(CONFIG_LWIP) && LWIP_SOCKET
|
||||
ret = lwip_read((int)file->offset, buffer, size);
|
||||
|
||||
return size;
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
#endif
|
||||
kprintf("return size: %i", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t null_write(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset)
|
||||
static ssize_t socket_write(fildes_t* file, uint8_t* buffer, size_t size)
|
||||
{
|
||||
return size;
|
||||
int ret = 0;
|
||||
#if defined(CONFIG_LWIP) && LWIP_SOCKET
|
||||
ret = lwip_write(file->offset, buffer, size);
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int null_open(vfs_node_t* node)
|
||||
static int socket_open(fildes_t* file, const char* name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int null_close(vfs_node_t* node)
|
||||
static int socket_close(fildes_t* file)
|
||||
{
|
||||
return 0;
|
||||
int ret = 0;
|
||||
#if defined(CONFIG_LWIP) && LWIP_SOCKET
|
||||
//ret = lwip_close(file->offset);
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int null_init(vfs_node_t* node, const char* name)
|
||||
int socket_init(vfs_node_t* node, const char* name)
|
||||
{
|
||||
uint32_t i, j;
|
||||
vfs_node_t* new_node;
|
||||
|
@ -70,10 +105,10 @@ int null_init(vfs_node_t* node, const char* name)
|
|||
|
||||
memset(new_node, 0x00, sizeof(vfs_node_t));
|
||||
new_node->type = FS_CHARDEVICE;
|
||||
new_node->open = &null_open;
|
||||
new_node->close = &null_close;
|
||||
new_node->read = &null_read;
|
||||
new_node->write = &null_write;
|
||||
new_node->open = &socket_open;
|
||||
new_node->close = &socket_close;
|
||||
new_node->read = &socket_read;
|
||||
new_node->write = &socket_write;
|
||||
spinlock_init(&new_node->lock);
|
||||
|
||||
blist= &node->block_list;
|
325
drivers/char/stdio.c
Normal file
325
drivers/char/stdio.c
Normal file
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* Copyright 2011 Marian Ohligs, Chair for Operating Systems,
|
||||
* RWTH Aachen University
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of MetalSVM.
|
||||
*/
|
||||
|
||||
#include <metalsvm/stdlib.h>
|
||||
#include <metalsvm/string.h>
|
||||
#include <metalsvm/stdio.h>
|
||||
#include <metalsvm/errno.h>
|
||||
#include <metalsvm/fs.h>
|
||||
#include <asm/kb.h>
|
||||
#include <metalsvm/tasks.h>
|
||||
#include <metalsvm/spinlock.h>
|
||||
|
||||
/* Functions of a simple null device */
|
||||
|
||||
static ssize_t null_read(fildes_t* file, uint8_t* buffer, size_t size)
|
||||
{
|
||||
memset(buffer, 0x00, size);
|
||||
|
||||
file->offset += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t null_write(fildes_t* file, uint8_t* buffer, size_t size)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
static int null_open(fildes_t* file, const char* name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int null_close(fildes_t* file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read Function of a stdio device */
|
||||
|
||||
static ssize_t stdio_read(fildes_t* file, uint8_t* buffer, size_t size)
|
||||
{
|
||||
kb_buffer.buffer = kmalloc(size * sizeof(char));
|
||||
kb_buffer.maxsize = size;
|
||||
kb_buffer.size = 0;
|
||||
kb_buffer.tid = per_core(current_task)->id;
|
||||
block_current_task();
|
||||
//per_core(current_task)->status = TASK_BLOCKED;
|
||||
reschedule();
|
||||
|
||||
size = kb_buffer.size;
|
||||
memcpy(buffer, kb_buffer.buffer, size);
|
||||
|
||||
/*cleaning up */
|
||||
kb_flush();
|
||||
|
||||
//kprintf("Size: %i, offset: %i, buffer: %s", size, buffer, offset);
|
||||
file->offset += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Write Function of a stdio device */
|
||||
|
||||
static ssize_t stdio_write(fildes_t* file, uint8_t* buffer, size_t size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i<size; i++, buffer++) {
|
||||
kputchar(*buffer);
|
||||
}
|
||||
|
||||
file->offset += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Init Functions */
|
||||
|
||||
int null_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 = &null_open;
|
||||
new_node->close = &null_close;
|
||||
new_node->read = &null_read;
|
||||
new_node->write = &null_write;
|
||||
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 stdin_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 = &null_open;
|
||||
new_node->close = &null_close;
|
||||
new_node->read = &stdio_read;
|
||||
new_node->write = &null_write;
|
||||
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 stdout_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 = &null_open;
|
||||
new_node->close = &null_close;
|
||||
new_node->read = &null_read;
|
||||
new_node->write = &stdio_write;
|
||||
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 stderr_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 = &null_open;
|
||||
new_node->close = &null_close;
|
||||
new_node->read = &null_read;
|
||||
new_node->write = &stdio_write;
|
||||
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;
|
||||
}
|
73
fs/fs.c
73
fs/fs.c
|
@ -17,15 +17,18 @@
|
|||
* This file is part of MetalSVM.
|
||||
*/
|
||||
|
||||
#include <metalsvm/stdlib.h>
|
||||
#include <metalsvm/stdio.h>
|
||||
#include <metalsvm/string.h>
|
||||
#include <metalsvm/fs.h>
|
||||
#include <metalsvm/errno.h>
|
||||
#include <metalsvm/spinlock.h>
|
||||
|
||||
vfs_node_t* fs_root = NULL; // The root of the filesystem.
|
||||
|
||||
ssize_t read_fs(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset)
|
||||
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))
|
||||
|
@ -34,56 +37,87 @@ ssize_t read_fs(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset)
|
|||
spinlock_lock(&node->lock);
|
||||
// Has the node got a read callback?
|
||||
if (node->read != 0)
|
||||
ret = node->read(node, buffer, size, offset);
|
||||
ret = node->read(file, buffer, size);
|
||||
spinlock_unlock(&node->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t write_fs(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset)
|
||||
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?
|
||||
// Has the node got a write callback?
|
||||
if (node->write != 0)
|
||||
ret = node->write(node, buffer, size, offset);
|
||||
ret = node->write(file, buffer, size);
|
||||
spinlock_unlock(&node->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int open_fs(vfs_node_t* node, uint8_t read, uint8_t write)
|
||||
int open_fs(fildes_t* file, const char* name)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
uint32_t ret = 0, i, j = 1;
|
||||
vfs_node_t* file_node = NULL; /* file node */
|
||||
vfs_node_t* dir_node = NULL;
|
||||
char* fname = kmalloc(sizeof(char)*MAX_FNAME);
|
||||
|
||||
if (BUILTIN_EXPECT(!node, 0))
|
||||
if (BUILTIN_EXPECT(!name, 0))
|
||||
return ret;
|
||||
|
||||
spinlock_lock(&node->lock);
|
||||
// Has the node got an open callback?
|
||||
if (node->open != 0)
|
||||
ret = node->open(node);
|
||||
spinlock_unlock(&node->lock);
|
||||
if (name[0] == '/')
|
||||
file_node = fs_root;
|
||||
|
||||
while((name[j] != '\0') && (file_node != NULL)) {
|
||||
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 dictionary */
|
||||
file_node = finddir_fs(dir_node, fname);
|
||||
if (name[j] == '/')
|
||||
j++;
|
||||
}
|
||||
|
||||
/* 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 { /* file doesn't exist */
|
||||
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);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int close_fs(vfs_node_t* node)
|
||||
int close_fs(fildes_t* file)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (BUILTIN_EXPECT(!node, 0))
|
||||
if (BUILTIN_EXPECT(!(file->node), 0))
|
||||
return ret;
|
||||
|
||||
spinlock_lock(&node->lock);
|
||||
spinlock_lock(&file->node->lock);
|
||||
// Has the node got a close callback?
|
||||
if (node->close != 0)
|
||||
ret = node->close(node);
|
||||
spinlock_unlock(&node->lock);
|
||||
if (file->node->close != 0)
|
||||
ret = file->node->close(file);
|
||||
spinlock_unlock(&file->node->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -161,4 +195,3 @@ vfs_node_t* findnode_fs(const char* name)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
195
fs/initrd.c
195
fs/initrd.c
|
@ -23,7 +23,10 @@
|
|||
#include <metalsvm/fs.h>
|
||||
#include <metalsvm/errno.h>
|
||||
#include <asm/multiboot.h>
|
||||
#include <metalsvm/spinlock.h>
|
||||
#include <asm/processor.h>
|
||||
#include <metalsvm/spinlock.h>
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/icc.h>
|
||||
#endif
|
||||
|
@ -52,18 +55,25 @@ typedef struct {
|
|||
char fname[MAX_FNAME];
|
||||
} initrd_file_desc_t;
|
||||
|
||||
static ssize_t initrd_read(vfs_node_t* node, uint8_t* buffer, size_t size, off_t offset)
|
||||
static ssize_t initrd_read(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_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]) {
|
||||
|
@ -85,14 +95,178 @@ static ssize_t initrd_read(vfs_node_t* node, uint8_t* buffer, size_t size, off_t
|
|||
* The user has to restart the read operation
|
||||
* for the next block.
|
||||
*/
|
||||
if (offset+size >= node->block_size)
|
||||
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_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) {
|
||||
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;
|
||||
|
@ -167,9 +341,10 @@ static vfs_node_t* initrd_mkdir(vfs_node_t* node, const char* name)
|
|||
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 block */
|
||||
/* create default directory entry */
|
||||
dir_block = (dir_block_t*) kmalloc(sizeof(dir_block_t));
|
||||
if (BUILTIN_EXPECT(!dir_block, 0))
|
||||
goto out;
|
||||
|
@ -237,6 +412,7 @@ int initrd_init(void)
|
|||
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 */
|
||||
|
@ -257,6 +433,15 @@ int initrd_init(void)
|
|||
tmp = mkdir_fs(fs_root, "dev");
|
||||
/* create the character device "null" */
|
||||
null_init(tmp, "null");
|
||||
/* create the standart input device "stdin" */
|
||||
stdin_init(tmp, "stdin");
|
||||
/* create the standart output device "stdout" */
|
||||
stdout_init(tmp, "stdout");
|
||||
/* create the standart error-output device "stderr" */
|
||||
stderr_init(tmp, "stderr");
|
||||
/* create the standart device "netchar" */
|
||||
socket_init(tmp, "socket");
|
||||
|
||||
|
||||
/* For every module.. */
|
||||
#ifdef CONFIG_MULTIBOOT
|
||||
|
@ -305,6 +490,8 @@ int initrd_init(void)
|
|||
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);
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define __FS_H__
|
||||
|
||||
#include <metalsvm/stddef.h>
|
||||
#include <metalsvm/spinlock.h>
|
||||
#include <metalsvm/spinlock_types.h>
|
||||
|
||||
#define FS_FILE 0x01
|
||||
#define FS_DIRECTORY 0x02
|
||||
|
@ -37,8 +37,38 @@
|
|||
//#define FS_SYMLINK 0x06
|
||||
//#define FS_MOUNTPOINT 0x08 // Is the file an active mountpoint?
|
||||
|
||||
struct vfs_node;
|
||||
|
||||
/*file descriptor init*/
|
||||
#define NR_OPEN 100
|
||||
|
||||
/*open flags*/
|
||||
|
||||
#define O_RDONLY 0
|
||||
#define O_WRONLY 1
|
||||
#define O_RDWR 2
|
||||
|
||||
#define O_CREAT 64
|
||||
#define O_EXCL 128
|
||||
//#define O_NOCTTY 256
|
||||
#define O_TRUNC 512
|
||||
#define O_APPEND 1024
|
||||
//#define O_NDELAY 2048
|
||||
//#define O_SYNC 4096
|
||||
//#define O_ASYNC 8192
|
||||
|
||||
/*lseek defines*/
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0 /* set file offset to offset */
|
||||
#endif
|
||||
#ifndef SEEK_CUR
|
||||
#define SEEK_CUR 1 /* set file offset to current plus offset */
|
||||
#endif
|
||||
#ifndef SEEK_END
|
||||
#define SEEK_END 2 /* set file offset to EOF plus offset */
|
||||
#endif
|
||||
|
||||
struct vfs_node;
|
||||
struct fildes;
|
||||
/** @defgroup fsprototypes FS access function prototypes
|
||||
*
|
||||
* These typedefs define the type of callbacks - called when read/write/open/close are called.\n
|
||||
|
@ -48,13 +78,13 @@ struct vfs_node;
|
|||
*/
|
||||
|
||||
/** @brief Read function pointer */
|
||||
typedef ssize_t (*read_type_t) (struct vfs_node *, uint8_t*, size_t, off_t);
|
||||
typedef ssize_t (*read_type_t) (struct fildes *, uint8_t*, size_t);
|
||||
/** @brief Write function pointer */
|
||||
typedef ssize_t (*write_type_t) (struct vfs_node *, uint8_t*, size_t, off_t);
|
||||
typedef ssize_t (*write_type_t) (struct fildes *, uint8_t*, size_t);
|
||||
/** @brief Open function pointer */
|
||||
typedef int (*open_type_t) (struct vfs_node *);
|
||||
typedef int (*open_type_t) (struct fildes *, const char *name);
|
||||
/** @brief Close function pointer */
|
||||
typedef int (*close_type_t) (struct vfs_node *);
|
||||
typedef int (*close_type_t) (struct fildes *);
|
||||
/** @brief Read directory function pointer */
|
||||
typedef struct dirent *(*readdir_type_t) (struct vfs_node *, uint32_t);
|
||||
/** @brief Find directory function pointer */
|
||||
|
@ -66,6 +96,8 @@ typedef struct vfs_node *(*mkdir_type_t) (struct vfs_node *, const char *name);
|
|||
|
||||
#define MAX_DATABLOCKS 12
|
||||
#define MAX_DIRENTRIES 32
|
||||
#define MAX_DATAENTRIES 4096
|
||||
|
||||
|
||||
/** @brief Block list structure. VFS nodes keep those in a list */
|
||||
typedef struct block_list {
|
||||
|
@ -106,8 +138,16 @@ typedef struct vfs_node {
|
|||
block_list_t block_list;
|
||||
} vfs_node_t;
|
||||
|
||||
/** @brief file descriptor structure */
|
||||
typedef struct fildes {
|
||||
vfs_node_t* node; /* */
|
||||
off_t offset; /* */
|
||||
int flags; /* */
|
||||
int mode; /* */
|
||||
} fildes_t;
|
||||
|
||||
/** @brief Directory entry structure */
|
||||
typedef struct dirent{
|
||||
typedef struct dirent {
|
||||
/// Directory name
|
||||
char name[MAX_FNAME];
|
||||
/// Corresponding VFS node pointer
|
||||
|
@ -120,6 +160,11 @@ typedef struct {
|
|||
dirent_t entries[MAX_DIRENTRIES];
|
||||
} dir_block_t;
|
||||
|
||||
typedef struct {
|
||||
///Array of data entries
|
||||
char entries[MAX_DATAENTRIES];
|
||||
} data_block_t;
|
||||
|
||||
extern vfs_node_t* fs_root; // The root of the filesystem.
|
||||
|
||||
/** @defgroup fsfunc FS related functions
|
||||
|
@ -140,7 +185,7 @@ extern vfs_node_t* fs_root; // The root of the filesystem.
|
|||
* - number of bytes copied (size)
|
||||
* - 0 on error
|
||||
*/
|
||||
ssize_t read_fs(vfs_node_t * node, uint8_t* buffer, size_t size, off_t offset);
|
||||
ssize_t read_fs(fildes_t* file, uint8_t* buffer, size_t size);
|
||||
|
||||
/** @brief Write into the file system from the buffer
|
||||
* @param node Pointer to the node to write to
|
||||
|
@ -151,12 +196,12 @@ ssize_t read_fs(vfs_node_t * node, uint8_t* buffer, size_t size, off_t offset);
|
|||
* - number of bytes copied (size)
|
||||
* - 0 on error
|
||||
*/
|
||||
ssize_t write_fs(vfs_node_t * node, uint8_t* buffer, size_t size, off_t offset);
|
||||
ssize_t write_fs(fildes_t* file, uint8_t* buffer, size_t size);
|
||||
|
||||
/** @brief Yet to be documented */
|
||||
int open_fs(vfs_node_t * node, uint8_t read, uint8_t write);
|
||||
int open_fs(fildes_t* file, const char* fname);
|
||||
/** @brief Yet to be documented */
|
||||
int close_fs(vfs_node_t * node);
|
||||
int close_fs(fildes_t * file);
|
||||
|
||||
/** @brief Get dir entry at index
|
||||
* @param node VFS node to get dir entry from
|
||||
|
@ -196,6 +241,10 @@ vfs_node_t* findnode_fs(const char* name);
|
|||
/* @} */
|
||||
|
||||
int null_init(vfs_node_t* node, const char* name);
|
||||
int stdin_init(vfs_node_t* node, const char* name);
|
||||
int stdout_init(vfs_node_t* node, const char* name);
|
||||
int stderr_init(vfs_node_t* node, const char* name);
|
||||
int socket_init(vfs_node_t* node, const char* name);
|
||||
int initrd_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <metalsvm/stddef.h>
|
||||
#include <metalsvm/vma.h>
|
||||
#include <metalsvm/spinlock_types.h>
|
||||
#include <metalsvm/fs.h>
|
||||
#include <metalsvm/mailbox_types.h>
|
||||
#include <asm/tasks_types.h>
|
||||
#include <asm/atomic.h>
|
||||
|
@ -91,6 +92,8 @@ typedef struct task {
|
|||
spinlock_t vma_lock;
|
||||
/// List of VMAs
|
||||
vma_t* vma_list;
|
||||
/// Filedescriptor table
|
||||
fildes_t* fildes_table;
|
||||
/// starting time/tick of the task
|
||||
uint64_t start_tick;
|
||||
/// Start address of the heap
|
||||
|
|
|
@ -177,6 +177,10 @@ static void list_fs(vfs_node_t* node, uint32_t depth)
|
|||
{
|
||||
int j, i = 0;
|
||||
dirent_t* dirent = NULL;
|
||||
fildes_t* file = kmalloc(sizeof(fildes_t));
|
||||
file->offset = 0;
|
||||
file->flags = 0;
|
||||
|
||||
|
||||
while ((dirent = readdir_fs(node, i)) != 0) {
|
||||
for(j=0; j<depth; j++)
|
||||
|
@ -188,8 +192,12 @@ static void list_fs(vfs_node_t* node, uint32_t depth)
|
|||
if (new_node) {
|
||||
if (new_node->type == FS_FILE) {
|
||||
char buff[16] = {[0 ... 15] = 0x00};
|
||||
|
||||
file->node = new_node;
|
||||
file->offset = 0;
|
||||
file->flags = 0;
|
||||
|
||||
read_fs(new_node, (uint8_t*)buff, 8, 0);
|
||||
read_fs(file, (uint8_t*)buff, 8);
|
||||
for(j=0; j<depth+1; j++)
|
||||
kputs(" ");
|
||||
kprintf("content: %s\n", buff);
|
||||
|
@ -199,6 +207,7 @@ static void list_fs(vfs_node_t* node, uint32_t depth)
|
|||
|
||||
i++;
|
||||
}
|
||||
kfree(file, sizeof(fildes_t));
|
||||
}
|
||||
|
||||
static void list_root(void) {
|
||||
|
|
254
kernel/syscall.c
254
kernel/syscall.c
|
@ -21,6 +21,7 @@
|
|||
#include <metalsvm/stdio.h>
|
||||
#include <metalsvm/syscall.h>
|
||||
#include <metalsvm/tasks.h>
|
||||
#include <metalsvm/string.h>
|
||||
#include <metalsvm/errno.h>
|
||||
#include <metalsvm/spinlock.h>
|
||||
#include <metalsvm/time.h>
|
||||
|
@ -39,25 +40,131 @@
|
|||
#include <lwip/inet.h>
|
||||
#include <lwip/err.h>
|
||||
|
||||
/*
|
||||
* We set the a bit LWIP_FD_BIT to determine,
|
||||
* if the descriptor belongs to LwIP or MetalSVM.
|
||||
*/
|
||||
#define LWIP_FD_BIT (1 << 28)
|
||||
#endif
|
||||
|
||||
static int sys_write(int fildes, const char *buf, size_t len)
|
||||
static int get_fildes(){
|
||||
int fd;
|
||||
|
||||
for (fd = 0; fd < NR_OPEN; fd++) {
|
||||
if (per_core(current_task)->fildes_table[fd].node == NULL) {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
|
||||
/* can't get any free fd */
|
||||
return -EMFILE;
|
||||
}
|
||||
|
||||
static int sys_open(const char* name, int flags, int mode)
|
||||
{
|
||||
int i;
|
||||
int fd, check;
|
||||
fildes_t* file = NULL;
|
||||
|
||||
if (BUILTIN_EXPECT(!buf, 0))
|
||||
return -1;
|
||||
fd = get_fildes();
|
||||
/* validate the fd */
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
for (i = 0; i<len; i++, buf++) {
|
||||
kputchar(*buf);
|
||||
file = &(per_core(current_task)->fildes_table[fd]);
|
||||
file->offset = 0;
|
||||
file->mode = mode;
|
||||
file->flags = flags;
|
||||
|
||||
check = open_fs(file, (char*) name);
|
||||
if (check < 0) {
|
||||
/* file doesn't exist! */
|
||||
file->node = NULL;
|
||||
return check;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_LWIP) && LWIP_SOCKET
|
||||
static int sys_socket(int domain, int type, int protocol)
|
||||
{
|
||||
int fd;
|
||||
fildes_t* file = NULL;
|
||||
|
||||
fd = get_fildes();
|
||||
/* validate the fd */
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
file = &(per_core(current_task)->fildes_table[fd]);
|
||||
file->offset = lwip_socket(domain, type, protocol);
|
||||
file->mode = 0;
|
||||
file->flags = 0;
|
||||
file->node = findnode_fs("/dev/socket");
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int sys_accept(int s, struct sockaddr* addr, socklen_t* addrlen)
|
||||
{
|
||||
int fd;
|
||||
fildes_t* file = NULL;
|
||||
|
||||
fd = get_fildes();
|
||||
/* validate the fd */
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
file = &(per_core(current_task)->fildes_table[fd]);
|
||||
file->offset = lwip_accept(s, addr, addrlen);
|
||||
file->mode = 0;
|
||||
file->flags = 0;
|
||||
file->node = findnode_fs("/dev/socket");
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static int sys_close(int fd)
|
||||
{
|
||||
fildes_t* file = &(per_core(current_task)->fildes_table[fd]);
|
||||
close_fs(file);
|
||||
file->node = NULL;
|
||||
file->offset = 0;
|
||||
file->mode = 0;
|
||||
file->flags = 0;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int sys_lseek(int fd, off_t pos, int origin)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
fildes_t* file = &(per_core(current_task)->fildes_table[fd]);
|
||||
|
||||
// Disabled for testing purposes
|
||||
if (BUILTIN_EXPECT(file->node->type != FS_FILE
|
||||
&& file->node->type != FS_CHARDEVICE, 0));
|
||||
return -EINVAL;
|
||||
|
||||
switch(origin)
|
||||
{
|
||||
case SEEK_SET: { /* set file offset to offset */
|
||||
file->offset = pos;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
case SEEK_CUR: { /* set file offset to current plus offset */
|
||||
ret = pos + file->offset;
|
||||
break;
|
||||
}
|
||||
case SEEK_END: { /* set file offset to EOF plus offset */
|
||||
file->offset = pos + file->node->block_size;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sys_sbrk(int incr)
|
||||
|
@ -102,37 +209,44 @@ int syscall_handler(uint32_t sys_nr, ...)
|
|||
ret = 0;
|
||||
break;
|
||||
case __NR_write: {
|
||||
int fildes = va_arg(vl, int);
|
||||
int fd = va_arg(vl, int);
|
||||
const char* buf = va_arg(vl, const char*);
|
||||
size_t len = va_arg(vl, size_t);
|
||||
|
||||
#if defined(CONFIG_LWIP) && LWIP_SOCKET
|
||||
if (fildes & LWIP_FD_BIT) {
|
||||
ret = lwip_write(fildes & ~LWIP_FD_BIT, buf, len);
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
} else ret = sys_write(fildes, buf, len);
|
||||
#else
|
||||
ret = sys_write(fildes, buf, len);
|
||||
#endif
|
||||
if (fd >= 0)
|
||||
ret = write_fs(&(per_core(current_task)->fildes_table[fd]),
|
||||
(uint8_t*)buf, len);
|
||||
break;
|
||||
}
|
||||
case __NR_open: {
|
||||
const char* name = va_arg(vl, const char*);
|
||||
int flags = va_arg(vl, int);
|
||||
int mode = va_arg(vl, int);
|
||||
ret = sys_open(name, flags, mode);
|
||||
break;
|
||||
}
|
||||
case __NR_open:
|
||||
ret = 1;
|
||||
break;
|
||||
case __NR_close: {
|
||||
#if defined(CONFIG_LWIP) && LWIP_SOCKET
|
||||
int s = va_arg(vl, int);
|
||||
if (s & LWIP_FD_BIT) {
|
||||
ret = lwip_close(s & ~LWIP_FD_BIT);
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
} else ret = 0;
|
||||
#else
|
||||
ret = 0;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
int fd = va_arg(vl, int);
|
||||
if (fd >= 0)
|
||||
ret = sys_close(fd);
|
||||
break;
|
||||
}
|
||||
case __NR_read: {
|
||||
int fd = va_arg(vl, int);
|
||||
const char* buf = va_arg(vl, const char*);
|
||||
size_t len = va_arg(vl, size_t);
|
||||
if (fd >= 0)
|
||||
ret = read_fs(&(per_core(current_task)->fildes_table[fd]),
|
||||
(uint8_t*)buf, len);
|
||||
break;
|
||||
}
|
||||
case __NR_lseek: {
|
||||
int fd = va_arg(vl, int);
|
||||
off_t pos = va_arg(vl, off_t);
|
||||
int origin = va_arg(vl, int);
|
||||
if (fd >= 0)
|
||||
ret = sys_lseek(fd, pos, origin);
|
||||
break;
|
||||
}
|
||||
case __NR_sbrk: {
|
||||
int incr = va_arg(vl, int);
|
||||
|
||||
|
@ -167,30 +281,14 @@ int syscall_handler(uint32_t sys_nr, ...)
|
|||
break;
|
||||
}
|
||||
#if defined(CONFIG_LWIP) && LWIP_SOCKET
|
||||
case __NR_read: {
|
||||
int s = va_arg(vl, int);
|
||||
void* mem = va_arg(vl, void*);
|
||||
size_t len = va_arg(vl, size_t);
|
||||
|
||||
if (!(s & LWIP_FD_BIT)) {
|
||||
ret = -ENOTSOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = lwip_read(s & ~LWIP_FD_BIT, mem, len);
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
break;
|
||||
}
|
||||
case __NR_closesocket: {
|
||||
int s = va_arg(vl, int);
|
||||
int fd = va_arg(vl, int);
|
||||
|
||||
if (BUILTIN_EXPECT(!(s & LWIP_FD_BIT), 0)) {
|
||||
if (fd < 0) {
|
||||
ret = -ENOTSOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = lwip_close(s & ~LWIP_FD_BIT);
|
||||
//ret = lwip_close(per_core(current_task)->fildes_table[fd].offset);
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
break;
|
||||
|
@ -200,71 +298,65 @@ int syscall_handler(uint32_t sys_nr, ...)
|
|||
int type = va_arg(vl, int);
|
||||
int protocol = va_arg(vl, int);
|
||||
|
||||
ret = lwip_socket(domain, type, protocol);
|
||||
if (ret >= 0)
|
||||
ret |= LWIP_FD_BIT;
|
||||
else
|
||||
ret = -errno;
|
||||
ret = sys_socket(domain, type, protocol);
|
||||
break;
|
||||
}
|
||||
case __NR_connect: {
|
||||
int s = va_arg(vl, int);
|
||||
int fd = va_arg(vl, int);
|
||||
const struct sockaddr* name = va_arg(vl, const struct sockaddr*);
|
||||
socklen_t namelen = va_arg(vl, socklen_t);
|
||||
|
||||
if (BUILTIN_EXPECT(!(s & LWIP_FD_BIT), 0)) {
|
||||
if (per_core(current_task)->fildes_table[fd].offset < 0) {
|
||||
ret = -ENOTSOCK;
|
||||
break;
|
||||
}
|
||||
//kprintf("lwip_connect: %p with lenght %i and Socket %i", name, namelen, per_core(current_task)->fildes_table[fd].offset);
|
||||
|
||||
ret = lwip_connect(s & ~LWIP_FD_BIT, name, namelen);
|
||||
|
||||
ret = lwip_connect(per_core(current_task)->fildes_table[fd].offset, name, namelen);
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
break;
|
||||
}
|
||||
case __NR_bind: {
|
||||
int s = va_arg(vl, int);
|
||||
int fd = va_arg(vl, int);
|
||||
const struct sockaddr* name = va_arg(vl, const struct sockaddr*);
|
||||
socklen_t namelen = va_arg(vl, socklen_t);
|
||||
|
||||
if (BUILTIN_EXPECT(!(s & LWIP_FD_BIT), 0)) {
|
||||
if (per_core(current_task)->fildes_table[fd].offset < 0) {
|
||||
ret = -ENOTSOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = lwip_bind(s & ~LWIP_FD_BIT, name, namelen);
|
||||
ret = lwip_bind(per_core(current_task)->fildes_table[fd].offset, name, namelen);
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
break;
|
||||
}
|
||||
case __NR_listen:{
|
||||
int s = va_arg(vl, int);
|
||||
case __NR_listen: {
|
||||
int fd = va_arg(vl, int);
|
||||
int backlog = va_arg(vl, int);
|
||||
|
||||
if (BUILTIN_EXPECT(!(s & LWIP_FD_BIT), 0)) {
|
||||
if (per_core(current_task)->fildes_table[fd].offset < 0) {
|
||||
ret = -ENOTSOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = lwip_listen(s & ~LWIP_FD_BIT, backlog);
|
||||
ret = lwip_listen(per_core(current_task)->fildes_table[fd].offset, backlog);
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
break;
|
||||
}
|
||||
case __NR_accept: {
|
||||
int s = va_arg(vl, int);
|
||||
int fd = va_arg(vl, int);
|
||||
struct sockaddr* addr = va_arg(vl, struct sockaddr*);
|
||||
socklen_t* addrlen = va_arg(vl, socklen_t*);
|
||||
|
||||
if (BUILTIN_EXPECT(!(s & LWIP_FD_BIT), 0)) {
|
||||
if (per_core(current_task)->fildes_table[fd].offset < 0) {
|
||||
ret = -ENOTSOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = lwip_accept(s & ~LWIP_FD_BIT, addr, addrlen);
|
||||
if (ret >= 0)
|
||||
ret |= LWIP_FD_BIT;
|
||||
else
|
||||
ret = sys_accept(per_core(current_task)->fildes_table[fd].offset, addr, addrlen);
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -47,8 +47,9 @@
|
|||
* A task's id will be its position in this array.
|
||||
*/
|
||||
static task_t task_table[MAX_TASKS] = { \
|
||||
[0] = {0, TASK_IDLE, 0, 0, 0, NULL, NULL, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0, 0}, \
|
||||
[1 ... MAX_TASKS-1] = {0, TASK_INVALID, 0, 0, 0, NULL, NULL, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, 0, 0, 0, 0}};
|
||||
[0] = {0, TASK_IDLE, 0, 0, 0, NULL, NULL, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, NULL, 0, 0, 0, 0}, \
|
||||
[1 ... MAX_TASKS-1] = {0, TASK_INVALID, 0, 0, 0, NULL, NULL, 0, ATOMIC_INIT(0), SPINLOCK_INIT, NULL, SPINLOCK_INIT, NULL, NULL, 0, 0, 0, 0}};
|
||||
|
||||
static spinlock_irqsave_t table_lock = SPINLOCK_IRQSAVE_INIT;
|
||||
#if MAX_CORES > 1
|
||||
static runqueue_t runqueues[MAX_CORES] = { \
|
||||
|
@ -190,6 +191,10 @@ static void NORETURN do_exit(int arg) {
|
|||
kfree((void*) tmp, sizeof(vma_t));
|
||||
}
|
||||
|
||||
//remove fildes_table
|
||||
if(!curr_task->fildes_table)
|
||||
kfree(curr_task->fildes_table, sizeof(fildes_t)*NR_OPEN);
|
||||
|
||||
spinlock_unlock(&curr_task->vma_lock);
|
||||
|
||||
drop_pgd(); // delete page directory and its page tables
|
||||
|
@ -320,7 +325,7 @@ create_task_out:
|
|||
int sys_fork(void)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
unsigned int i, core_id;
|
||||
unsigned int i, core_id, fd_i;
|
||||
task_t* parent_task = per_core(current_task);
|
||||
vma_t** child;
|
||||
vma_t* parent;
|
||||
|
@ -364,6 +369,16 @@ int sys_fork(void)
|
|||
tmp = *child;
|
||||
child = &((*child)->next);
|
||||
}
|
||||
|
||||
|
||||
/* init fildes_table */
|
||||
task_table[i].fildes_table = kmalloc(sizeof(fildes_t)*NR_OPEN);
|
||||
memset(task_table[i].fildes_table, 0x00, sizeof(fildes_t)*NR_OPEN);
|
||||
|
||||
// copy filedescriptors
|
||||
for (fd_i = 0; fd_i < NR_OPEN; fd_i++) {
|
||||
task_table[i].fildes_table[fd_i].node = per_core(current_task)->fildes_table[fd_i].node;
|
||||
}
|
||||
|
||||
mailbox_wait_msg_init(&task_table[i].inbox);
|
||||
memset(task_table[i].outbox, 0x00, sizeof(mailbox_wait_msg_t*)*MAX_TASKS);
|
||||
|
@ -492,6 +507,12 @@ static int load_task(load_args_t* largs)
|
|||
elf_header_t header;
|
||||
elf_program_header_t prog_header;
|
||||
//elf_section_header_t sec_header;
|
||||
///!!! kfree is missing!
|
||||
fildes_t *file = kmalloc(sizeof(fildes_t));
|
||||
file->offset = 0;
|
||||
file->flags = 0;
|
||||
|
||||
//TODO: init the hole fildes_t struct!
|
||||
vfs_node_t* node;
|
||||
task_t* curr_task = per_core(current_task);
|
||||
int err;
|
||||
|
@ -499,16 +520,15 @@ static int load_task(load_args_t* largs)
|
|||
if (!largs)
|
||||
return -EINVAL;
|
||||
|
||||
node = largs->node;
|
||||
if (!node)
|
||||
file->node = largs->node;
|
||||
if (!file->node)
|
||||
return -EINVAL;
|
||||
|
||||
err = read_fs(node, (uint8_t*)&header, sizeof(elf_header_t), 0);
|
||||
read_fs(file, (uint8_t*)&header, sizeof(elf_header_t));
|
||||
if (err < 0) {
|
||||
kprintf("read_fs failed: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (BUILTIN_EXPECT(header.ident.magic != ELF_MAGIC, 0))
|
||||
goto invalid;
|
||||
|
||||
|
@ -529,7 +549,8 @@ static int load_task(load_args_t* largs)
|
|||
|
||||
// interpret program header table
|
||||
for (i=0; i<header.ph_entry_count; i++) {
|
||||
if (read_fs(node, (uint8_t*)&prog_header, sizeof(elf_program_header_t), header.ph_offset+i*header.ph_entry_size) == 0) {
|
||||
file->offset = header.ph_offset+i*header.ph_entry_size;
|
||||
if (read_fs(file, (uint8_t*)&prog_header, sizeof(elf_program_header_t)) == 0) {
|
||||
kprintf("Could not read programm header!\n");
|
||||
continue;
|
||||
}
|
||||
|
@ -562,7 +583,8 @@ static int load_task(load_args_t* largs)
|
|||
curr_task->start_heap = curr_task->end_heap = prog_header.virt_addr+prog_header.mem_size;
|
||||
|
||||
// load program
|
||||
read_fs(node, (uint8_t*)prog_header.virt_addr, prog_header.file_size, prog_header.offset);
|
||||
file->offset = prog_header.offset;
|
||||
read_fs(file, (uint8_t*)prog_header.virt_addr, prog_header.file_size);
|
||||
|
||||
flags = VMA_CACHEABLE;
|
||||
if (prog_header.flags & PF_R)
|
||||
|
@ -608,7 +630,8 @@ static int load_task(load_args_t* largs)
|
|||
#if 0
|
||||
// interpret section header table
|
||||
for (i=0; i<header.sh_entry_count; i++) {
|
||||
if (read_fs(node, (uint8_t*)&sec_header, sizeof(elf_section_header_t), header.sh_offset+i*header.sh_entry_size) == 0) {
|
||||
file.offset = header.sh_offset+i*header.sh_entry_size;
|
||||
if (read_fs(&file, (uint8_t*)&sec_header, sizeof(elf_section_header_t)) == 0) {
|
||||
kprintf("Could not read section header!\n");
|
||||
continue;
|
||||
}
|
||||
|
@ -716,7 +739,7 @@ static int STDCALL user_entry(void* arg)
|
|||
int create_user_task(tid_t* id, const char* fname, char** argv)
|
||||
{
|
||||
vfs_node_t* node;
|
||||
int argc = 0;
|
||||
int argc = 0, ret = 0;
|
||||
size_t i, buffer_size = 0;
|
||||
load_args_t* load_args = NULL;
|
||||
char *dest, *src;
|
||||
|
@ -750,7 +773,25 @@ int create_user_task(tid_t* id, const char* fname, char** argv)
|
|||
while ((*dest++ = *src++) != 0);
|
||||
}
|
||||
|
||||
return create_task(id, user_entry, load_args, NORMAL_PRIO);
|
||||
|
||||
/*
|
||||
* if 'tid_t' id is not initalized, create_task will not set 'tid_t id'
|
||||
* We need the tid to initalize the fildes, thus we have to check this
|
||||
*/
|
||||
if (!id)
|
||||
id = kmalloc(sizeof(tid_t));
|
||||
|
||||
/* == === create new task === == */
|
||||
ret = create_task(id, user_entry, load_args, NORMAL_PRIO);
|
||||
|
||||
/* init fildes_table */
|
||||
task_table[*id].fildes_table = kmalloc(sizeof(fildes_t)*NR_OPEN);
|
||||
memset(task_table[*id].fildes_table, 0x00, sizeof(fildes_t)*NR_OPEN);
|
||||
task_table[*id].fildes_table[0].node = findnode_fs("/dev/stdin");
|
||||
task_table[*id].fildes_table[1].node = findnode_fs("/dev/stdout");
|
||||
task_table[*id].fildes_table[2].node = findnode_fs("/dev/stderr");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Used by the execve-Systemcall */
|
||||
|
|
|
@ -404,13 +404,14 @@ void* client_task(void* e)
|
|||
|
||||
int test_init(void)
|
||||
{
|
||||
char* argv[] = {"/bin/tests", NULL};
|
||||
char* server_argv[] = {"/bin/server", "6789", NULL};
|
||||
char* client_argv[] = {"/bin/client", "127.0.0.1", "6789", NULL};
|
||||
char* argv[] = {"/bin/mshell", NULL};
|
||||
// char* argv[] = {"/bin/tests", NULL};
|
||||
// char* server_argv[] = {"/bin/server", "6789", NULL};
|
||||
// char* client_argv[] = {"/bin/client", "127.0.0.1", "6789", NULL};
|
||||
|
||||
sem_init(&producing, 1);
|
||||
sem_init(&consuming, 0);
|
||||
mailbox_int32_init(&mbox);
|
||||
//sem_init(&producing, 1);
|
||||
//sem_init(&consuming, 0);
|
||||
//mailbox_int32_init(&mbox);
|
||||
|
||||
#if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK)
|
||||
|
||||
|
@ -425,16 +426,16 @@ int test_init(void)
|
|||
// create_kernel_task(NULL,client_task,NULL);
|
||||
#endif
|
||||
|
||||
create_kernel_task(NULL, foo, "Hello from foo1", NORMAL_PRIO);
|
||||
create_kernel_task(NULL, join_test, NULL, NORMAL_PRIO);
|
||||
//create_kernel_task(NULL, foo, "Hello from foo1", NORMAL_PRIO);
|
||||
//create_kernel_task(NULL, join_test, NULL, NORMAL_PRIO);
|
||||
|
||||
//create_kernel_task(NULL, producer, , NORMAL_PRIO);
|
||||
//create_kernel_task(NULL, consumer, NULL, NORMAL_PRIO);
|
||||
//create_kernel_task(NULL, mail_ping, NULL, NORMAL_PRIO);
|
||||
//create_kernel_task(NULL, mail_noise, NULL, NORMAL_PRIO);
|
||||
//create_kernel_task(NULL, svm_test, NULL, NORMAL_PRIO);
|
||||
//create_user_task(NULL, "/bin/hello", argv);
|
||||
create_user_task(NULL, "/bin/tests", argv);
|
||||
//create_user_task(NULL, "/bin/jacobi", argv);
|
||||
create_user_task(NULL, "/bin/mshell", argv);
|
||||
//create_user_task(NULL, "/bin/jacobi", argv);
|
||||
//create_user_task(NULL, "/bin/server", server_argv);
|
||||
//sleep(5);
|
||||
|
|
|
@ -11,7 +11,7 @@ LDFLAGS =
|
|||
|
||||
default: all
|
||||
|
||||
all: hello tests jacobi server client
|
||||
all: hello tests jacobi mshell server client
|
||||
|
||||
jacobi: jacobi.o
|
||||
$(CC_FOR_TARGET) -T link.ld -o $@ $(LDFLAGS) $< -lm
|
||||
|
@ -31,6 +31,12 @@ hello: hello.o
|
|||
$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@
|
||||
chmod a-x $@.sym
|
||||
|
||||
mshell: mshell.o
|
||||
$(CC_FOR_TARGET) -T link.ld -o $@ $(LDFLAGS) $<
|
||||
$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym
|
||||
$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $@
|
||||
chmod a-x $@.sym
|
||||
|
||||
server: server.o
|
||||
$(CC_FOR_TARGET) -T link.ld -o $@ $(LDFLAGS) $< -lsocket
|
||||
$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $@ $@.sym
|
||||
|
|
|
@ -22,22 +22,33 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#undef errno
|
||||
extern int errno;
|
||||
|
||||
/*file descriptor init*/
|
||||
#define NR_OPEN 10
|
||||
#define FS_INIT { [0 ... NR_OPEN-1] = {NULL, 0, 0} }
|
||||
|
||||
/*open flags*/
|
||||
|
||||
//#define O_RDONLY 0
|
||||
//#define O_WRONLY 1
|
||||
#define O_RDWR 2
|
||||
|
||||
#define O_CREAT 64
|
||||
#define O_EXCL 128
|
||||
//#define O_NOCTTY 256
|
||||
#define O_TRUNC 512
|
||||
#define O_APPEND 1024
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int i;
|
||||
const char str[] = "Hello World!!!\n";
|
||||
|
||||
for(i=0; environ[i]; i++)
|
||||
printf("environ[%d] = %s\n", i, environ[i]);
|
||||
for(i=0; i<argc; i++)
|
||||
printf("argv[%d] = %s\n", i, argv[i]);
|
||||
|
||||
write(1, str, strlen(str));
|
||||
|
||||
printf("Hello from printf!!!\n");
|
||||
char* teststr = malloc(sizeof(char)*100);
|
||||
int testfile = open("/bin/test2", O_CREAT | O_EXCL, "wr");
|
||||
write(testfile, "hello in new file '/bin/test2'", 30);
|
||||
lseek(testfile, 0, SEEK_SET);
|
||||
read(testfile, teststr, 100);
|
||||
close(testfile);
|
||||
printf("Gelesen aus neuer Datei: %s", teststr);
|
||||
|
||||
return errno;
|
||||
}
|
||||
|
|
57
newlib/examples/mshell.c
Normal file
57
newlib/examples/mshell.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright 2011 Marian Ohligs, Chair for Operating Systems,
|
||||
* RWTH Aachen University
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
void showlogo() {
|
||||
printf("\n\n");
|
||||
printf("================================================================================\n");
|
||||
printf(" m(etalsvm)shell\n\n");
|
||||
printf("================================================================================\n");
|
||||
}
|
||||
|
||||
void help() {
|
||||
printf("possible commands: \n");
|
||||
printf("exit > exit shell \n");
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
char* command = malloc(1024*sizeof(char));
|
||||
|
||||
int size, status = 0;
|
||||
pid_t pid;
|
||||
system("clear");
|
||||
showlogo();
|
||||
while(1) {
|
||||
printf("$ ");
|
||||
size = scanf("%s", command);
|
||||
if(!strcmp(command, "exit")) {
|
||||
return 0;
|
||||
}
|
||||
if(!strcmp(command, "help")) {
|
||||
help();
|
||||
} else {
|
||||
pid = fork();
|
||||
if (pid == 0) { //child
|
||||
char* newargv[] = {command, NULL};
|
||||
char* newenv[] = {"USER=root", "PATH=/bin:/sbin:/usr/bin", "PWD=/", "TEMP=/tmp", NULL};
|
||||
|
||||
execve(command, newargv, newenv);
|
||||
return errno;
|
||||
} else {
|
||||
wait(&status);
|
||||
}
|
||||
}
|
||||
}
|
||||
return errno;
|
||||
}
|
||||
|
3
newlib/examples/test
Normal file
3
newlib/examples/test
Normal file
|
@ -0,0 +1,3 @@
|
|||
test
|
||||
hallo
|
||||
huso
|
|
@ -40,12 +40,21 @@
|
|||
#undef errno
|
||||
extern int errno;
|
||||
#include "warning.h"
|
||||
#include "syscall.h"
|
||||
|
||||
int
|
||||
_DEFUN (lseek, (file, ptr, dir),
|
||||
_DEFUN (_lseek, (file, ptr, dir),
|
||||
int file _AND
|
||||
int ptr _AND
|
||||
int dir)
|
||||
{
|
||||
return 0;
|
||||
int ret;
|
||||
|
||||
ret = SYSCALL3(__NR_lseek, file, ptr, dir);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ _DEFUN (_open, (file, flags, mode),
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = SYSCALL2(__NR_open, flags, mode);
|
||||
ret = SYSCALL3(__NR_open, file, flags, mode);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
ret = -1;
|
||||
|
|
|
@ -7,7 +7,7 @@ LDFLGAS =
|
|||
DEFINES=
|
||||
NASM = nasm
|
||||
NASMFLAGS = -fbin
|
||||
EXECFILES = $(shell find ../newlib/examples -perm -u+r+x -type f)
|
||||
EXECFILES = $(shell find ../newlib/examples -perm -u+r+x -type f) ../newlib/examples/test
|
||||
|
||||
# other implicit rules
|
||||
%.o : %.c
|
||||
|
|
Loading…
Add table
Reference in a new issue