Initial commit

This commit is contained in:
Bahadir Balban
2008-01-13 13:53:52 +00:00
commit e2b791a3d8
789 changed files with 95825 additions and 0 deletions

View File

66
tasks/fs0/SConstruct Normal file
View File

@@ -0,0 +1,66 @@
#
# User space application build script
#
# Copyright (C) 2007 Bahadir Balban
#
import os
import sys
import shutil
from os.path import join
from glob import glob
task_name = "fs0"
# The root directory of the repository where this file resides:
project_root = "../.."
tools_root = join(project_root, "tools")
prev_image = join(project_root, "tasks/blkdev0/blkdev0.axf")
libs_path = join(project_root, "libs")
ld_script = "include/linker.lds"
physical_base_ld_script = "include/physical_base.lds"
# libc paths:
libc_variant = "userspace"
libc_libpath = join(libs_path, "c/build/%s" % libc_variant)
libc_incpath = join(libc_libpath, "include")
libc_crt0 = join(libs_path, "c/build/crt/sys-userspace/arch-arm/crt0.o")
libc_name = "c-%s" % libc_variant
# libl4 paths:
libl4_path = "../libl4"
libl4_incpath1 = join(libl4_path, "include")
# kernel paths:
kernel_incpath = join(project_root, "include")
# If crt0 is in its library path, it becomes hard to link with it.
# For instance the linker script must use an absolute path for it.
def copy_crt0(source, target, env):
os.system("cp " + str(source[0]) + " " + str(target[0]))
def get_physical_base(source, target, env):
os.system(join(tools_root, "pyelf/readelf.py --first-free-page " + \
prev_image + " >> " + physical_base_ld_script))
# The kernel build environment:
env = Environment(CC = 'arm-none-linux-gnueabi-gcc',
# We don't use -nostdinc because sometimes we need standard headers,
# such as stdarg.h e.g. for variable args, as in printk().
CCFLAGS = ['-g', '-nostdlib', '-ffreestanding', '-std=gnu99', '-Wall', '-Werror'],
LINKFLAGS = ['-nostdlib', '-T' + ld_script, "-L" + libc_libpath, "-L" + libl4_path],
ASFLAGS = ['-D__ASSEMBLY__'],
PROGSUFFIX = '.axf', # The suffix to use for final executable
ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path
LIBS = [libc_name, 'gcc', libc_name, \
'libl4'], # libgcc.a - This is required for division routines.
CPPFLAGS = "-D__USERSPACE__",
CPPPATH = ['#include', libl4_incpath1, kernel_incpath, libc_incpath])
src = [glob("src/*.c"), glob("*.c"), glob("src/arch/arm/*.c")]
objs = env.Object(src)
physical_base = env.Command(physical_base_ld_script, prev_image, get_physical_base)
crt0_copied = env.Command("crt0.o", libc_crt0, copy_crt0)
task = env.Program(task_name, objs + [crt0_copied])
env.Alias(task_name, task)
env.Depends(task, physical_base)

8
tasks/fs0/include/bdev.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef __BLOCK_DEV_H__
#define __BLOCK_DEV_H__
void bdev_open(void);
void bdev_readpage(unsigned long offset, void *buf);
void bdev_writepage(unsigned long offset, void *buf);
#endif /* __BLOCK_DEV_H__ */

90
tasks/fs0/include/fs.h Normal file
View File

@@ -0,0 +1,90 @@
/*
* VFS definitions.
*
* Copyright (C) 2007 Bahadir Balban.
*/
#ifndef __FS_H__
#define __FS_H__
#include <l4/lib/list.h>
typedef void (*dentry_op_t)(void);
typedef void (*superblock_op_t)(void);
typedef void (*vnode_op_t)(void);
typedef void (*file_op_t)(void);
struct dentry_ops {
dentry_op_t compare;
};
struct file_ops {
file_op_t open;
file_op_t read;
file_op_t write;
file_op_t close;
file_op_t mmap;
file_op_t seek;
file_op_t flush;
file_op_t fsync;
};
struct vnode_ops {
vnode_op_t create;
vnode_op_t lookup;
vnode_op_t link;
vnode_op_t unlink;
vnode_op_t mkdir;
vnode_op_t rmdir;
vnode_op_t rename;
vnode_op_t getattr;
vnode_op_t setattr;
};
struct superblock_ops {
superblock_op_t read_sb;
superblock_op_t write_sb;
superblock_op_t read_vnode;
superblock_op_t write_vnode;
};
struct dentry;
struct file;
struct filesystem;
struct superblock;
struct vnode;
struct dentry {
int refcnt;
char name[512];
struct dentry *parent; /* Parent dentry */
struct list_head siblings; /* List of dentries with same parent */
struct vnode *vnode; /* The vnode associated with dirent */
struct dentry_ops ops;
};
struct file {
int refcnt;
struct dentry *dentry;
struct file_ops ops;
};
struct vnode {
unsigned long id; /* Filesystem-wide unique vnode id */
int refcnt; /* Reference counter */
struct vnode_ops ops; /* Operations on this vnode */
struct list_head dirents; /* Dirents that refer to this vnode */
struct list_head state_list; /* List for vnode's dirty/clean state */
unsigned long size; /* Total size of vnode in bytes */
};
struct filesystem {
unsigned long magic;
char name[256];
};
struct superblock {
struct filesystem fs;
struct superblock_ops ops;
struct dentry *root_dirent;
};
#endif /* __FS_H__ */

26
tasks/fs0/include/kdata.h Normal file
View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2007 Bahadir Balban
*/
#ifndef __MM_KDATA_H__
#define __MM_KDATA_H__
#include <l4/macros.h>
#include <l4/config.h>
#include <l4/types.h>
#include <l4/generic/physmem.h>
#include INC_PLAT(offsets.h)
#include INC_GLUE(memory.h)
#include INC_GLUE(memlayout.h)
#include INC_ARCH(bootdesc.h)
#include <vm_area.h>
struct initdata {
struct bootdesc *bootdesc;
struct block_device *bdev;
};
extern struct initdata initdata;
int request_initdata(struct initdata *i);
#endif /* __MM_KDATA_H__ */

View File

@@ -0,0 +1,36 @@
/*
* Simple linker script for userspace or svc tasks.
*
* Copyright (C) 2007 Bahadir Balban
*/
/*
* The only catch with this linker script is that everything
* is linked starting at virtual_base, and loaded starting
* at physical_base. virtual_base is the predefined region
* of virtual memory for userland applications. physical_base
* is determined at build-time, it is one of the subsequent pages
* that come after the kernel image's load area.
*/
/* USER_AREA_START, see memlayout.h */
virtual_base = 0x10000000;
__stack = 0x20000000;
INCLUDE "include/physical_base.lds"
/* physical_base = 0x228000; */
offset = virtual_base - physical_base;
ENTRY(_start)
SECTIONS
{
. = virtual_base;
_start_text = .;
.text : AT (ADDR(.text) - offset) { crt0.o(.text) *(.text) }
/* rodata is needed else your strings will link at physical! */
.rodata : AT (ADDR(.rodata) - offset) { *(.rodata) }
.rodata1 : AT (ADDR(.rodata1) - offset) { *(.rodata1) }
.data : AT (ADDR(.data) - offset) { *(.data) }
.bss : AT (ADDR(.bss) - offset) { *(.bss) }
_end = .;
}

7
tasks/fs0/include/task.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef __FS0_TASK_H__
#define __FS0_TASK_H__
#define __TASKNAME__ "FS0"
#endif /* __FS0_TASK_H__ */

82
tasks/fs0/main.c Normal file
View File

@@ -0,0 +1,82 @@
/*
* FS0. Filesystem implementation
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <stdio.h>
#include <string.h>
#include <l4lib/arch/message.h>
#include <l4lib/arch/syscalls.h>
#include <l4lib/kip.h>
#include <l4lib/utcb.h>
#include <l4lib/ipcdefs.h>
#include <fs.h>
/* Synchronise with pager via a `wait' tagged ipc with destination as pager */
void wait_pager(l4id_t partner)
{
u32 tag = L4_IPC_TAG_WAIT;
printf("Going to wait till pager finishes dumping.\n");
l4_ipc(partner, l4_nilthread, tag);
printf("Pager synced with us.\n");
}
void fs_request_handler(struct fs_request *fsreq)
{
}
void handle_fs_requests(void)
{
u32 mr[MR_UNUSED_TOTAL];
l4id_t sender;
int err;
u32 tag;
printf("%s: Listening requests.\n", __TASKNAME__);
if ((err = l4_receive(L4_ANYTHREAD)) < 0) {
printf("%s: %s: IPC Error: %d. Quitting...\n", __TASKNAME__,
__FUNCTION__, err);
BUG();
}
/* Read conventional ipc data */
tag = l4_get_tag();
sender = l4_get_sender();
/* Read mrs not used by syslib */
for (int i = 0; i < MR_UNUSED_TOTAL; i++)
mr[i] = read_mr(i);
switch(tag) {
case L4_IPC_TAG_WAIT:
printf("%s: Synced with waiting thread.\n", __TASKNAME__);
break;
case L4_IPC_TAG_OPEN:
sys_open(sender, (void *)mr[0], (int)mr[1], (u32)mr[2]);
break;
case L4_IPC_TAG_READ:
sys_read(sender, (int)mr[0], (void *)mr[1], (int)mr[2]);
break;
case L4_IPC_TAG_WRITE:
sys_write(sender, (int)mr[0], (void *)mr[1], (int)mr[2]);
break;
case L4_IPC_TAG_LSEEK:
sys_lseek(sender, (int)mr[0], (int)mr[1], (int)mr[2]);
break;
default:
printf("%s: Unrecognised ipc tag (%d)"
"received. Ignoring.\n", __TASKNAME__, mr[MR_TAG]);
}
}
void main(void)
{
wait_pager(PAGER_TID);
while (1) {
handle_fs_requests();
}
}

0
tasks/fs0/src/dentry.c Normal file
View File

63
tasks/fs0/src/kdata.c Normal file
View File

@@ -0,0 +1,63 @@
/*
* Requesting system information from kernel during init.
*
* Copyright (C) 2007 Bahadir Balban
*/
#include <stdio.h>
#include <l4lib/arch/syscalls.h>
#include <kdata.h>
#include <string.h>
#include INC_API(kip.h)
#include <kmalloc/kmalloc.h>
/* Kernel data acquired during initialisation */
struct initdata initdata;
#define BOOTDESC_PREALLOC_SIZE 128
static char bootdesc_memory[BOOTDESC_PREALLOC_SIZE]; /* 128 bytes */
void print_bootdesc(struct bootdesc *bd)
{
for (int i = 0; i < bd->total_images; i++) {
printf("Task Image: %d\n", i);
printf("Name: %s\n", bd->images[i].name);
printf("Start: 0x%x\n", bd->images[i].phys_start);
printf("End: 0x%x\n", bd->images[i].phys_end);
}
}
int request_initdata(struct initdata *initdata)
{
int err;
int bootdesc_size;
/* Read the boot descriptor size */
if ((err = l4_kread(KDATA_BOOTDESC_SIZE, &bootdesc_size)) < 0) {
printf("L4_kdata_read() call failed. Could not complete"
"KDATA_BOOTDESC_SIZE request.\n");
goto error;
}
if (bootdesc_size > BOOTDESC_PREALLOC_SIZE) {
printf("Insufficient preallocated memory for bootdesc. "
"Size too big.\n");
goto error;
}
/* Get preallocated bootdesc memory */
initdata->bootdesc = (struct bootdesc *)&bootdesc_memory;
/* Read the boot descriptor */
if ((err = l4_kread(KDATA_BOOTDESC, initdata->bootdesc)) < 0) {
printf("L4_kdata_read() call failed. Could not complete"
"KDATA_BOOTDESC request.\n");
goto error;
}
return 0;
error:
printf("FATAL: %s failed during initialisation. exiting.\n", __TASKNAME__);
return err;
}

0
tasks/fs0/src/mount.c Normal file
View File

View File

@@ -0,0 +1,86 @@
#include <stdio.h>
#include <block.h>
#include <l4/lib/math.h>
#include <l4/macros.h>
#include <l4/types.h>
#include INC_GLUE(memory.h)
/*
* Romfs superblock descriptor:
*
* All words are Big-Endian.
*
* Word 0: | - | r | o | m |
* Word 1: | 1 | f | s | - |
* Word 2: | Size | The number of bytes in this fs.
* Word 3: | Checksum | The checksum of first 512 bytes.
* Word 4: | Volume Name | The name of volume, padded to 16-byte boundary.
* Rest: | File Headers | The rest of the data.
*/
struct romfs_superblock {
u32 word0;
u32 word1;
u32 size;
u32 checksum;
char name[0];
};
struct romfs_inode {
unsigned long mdata_size; /* Size of metadata */
unsigned long data_offset; /* Offset of data from start of fs */
};
static u32
romfs_checksum(void *data)
{
u32 sum = 0;
u32 *ptr = data;
size >>= 2;
while (size > 0) {
sum += be32_to_cpu(*ptr++);
size--;
}
return sum;
}
int romfs_fill_super(struct superblock *sb)
{
char buf[PAGE_SIZE];
struct romfs_superblock *romfs_sb = (struct romfs_superblock *)buf;
unsigned long vroot_offset;
struct vnode *vroot;
/* Read first page from block device */
bdev_readpage(0, buf);
/* Check superblock sanity */
if (strcmp(be32_to_cpu(romfs_sb->word0), ROMFS_SB_WORD0)) {
printf("Bad magic word 0\n");
}
if (strcmp(be32_to_cpu(romfs_sb->word1), ROMFS_SB_WORD1)) {
printf("Bad magic word 1\n");
}
if (romfs_checksum(romfs_sb, min(romfs_sb->size, PAGE_SIZE))) {
printf("Bad checksum.\n");
}
/* Copy some params to generic superblock */
sb->size = be32_to_cpu(romfs_sb->size);
sb->magic = ROMFS_MAGIC;
sb->ops = romfs_ops;
/* Offset of first vnode, which is the root vnode */
vroot_offset = align_up(strnlen(romfs_sb->name, ROMFS_MAXNAME) + 1, 16);
if (!(vroot = romfs_read_vnode(s, vroot_offset))) {
printf("Error, could not get root inode.\n");
}
/* Get the dirent for this vnode */
if (!(sb->root = new_dentry(vroot))) {
printf("Error: Could not get new dentry for root vnode.\n");
}
}

View File

@@ -0,0 +1,43 @@
#ifndef __ROMFS_H__
#define __ROMFS_H__
#define ROMFS_MAGIC 0x7275
#define ROMFS_FTYPE_MSK 0xF /* File mask */
#define ROMFS_FTYPE_HRD 0 /* Hard link */
#define ROMFS_FTYPE_DIR 1 /* Directory */
#define ROMFS_FTYPE_REG 2 /* Regular file */
#define ROMFS_FTYPE_SYM 3 /* Symbolic link */
#define ROMFS_FTYPE_BLK 4 /* Block device */
#define ROMFS_FTYPE_CHR 5 /* Char device */
#define ROMFS_FTYPE_SCK 6 /* Socket */
#define ROMFS_FTYPE_FIF 7 /* FIFO */
#define ROMFS_FTYPE_EXE 8 /* Executable */
#define ROMFS_NAME_ALIGN 16 /* Alignment size of names */
#define ROMFS_SB_WORD0 "-rom"
#define ROMFS_SB_WORD1 "1fs-"
/*
* Romfs superblock descriptor:
*
* All words are Big-Endian.
*
* Word 0: | - | r | o | m |
* Word 1: | 1 | f | s | - |
* Word 2: | Size | The number of bytes in this fs.
* Word 3: | Checksum | The checksum of first 512 bytes.
* Word 4: | Volume Name | The name of volume, padded to 16-byte boundary.
* Rest: | File Headers | The rest of the data.
*/
struct romfs_superblock {
u32 word0;
u32 word1;
u32 size;
u32 checksum;
char name[0];
};
#endif /* __ROMFS_H__ */

View File

@@ -0,0 +1,61 @@
#ifndef __LINUX_ROMFS_FS_H
#define __LINUX_ROMFS_FS_H
/* The basic structures of the romfs filesystem */
#define ROMBSIZE BLOCK_SIZE
#define ROMBSBITS BLOCK_SIZE_BITS
#define ROMBMASK (ROMBSIZE-1)
#define ROMFS_MAGIC 0x7275
#define ROMFS_MAXFN 128
#define __mkw(h,l) (((h)&0x00ff)<< 8|((l)&0x00ff))
#define __mkl(h,l) (((h)&0xffff)<<16|((l)&0xffff))
#define __mk4(a,b,c,d) cpu_to_be32(__mkl(__mkw(a,b),__mkw(c,d)))
#define ROMSB_WORD0 __mk4('-','r','o','m')
#define ROMSB_WORD1 __mk4('1','f','s','-')
/* On-disk "super block" */
struct romfs_super_block {
__be32 word0;
__be32 word1;
__be32 size;
__be32 checksum;
char name[0]; /* volume name */
};
/* On disk inode */
struct romfs_inode {
__be32 next; /* low 4 bits see ROMFH_ */
__be32 spec;
__be32 size;
__be32 checksum;
char name[0];
};
#define ROMFH_TYPE 7
#define ROMFH_HRD 0
#define ROMFH_DIR 1
#define ROMFH_REG 2
#define ROMFH_SYM 3
#define ROMFH_BLK 4
#define ROMFH_CHR 5
#define ROMFH_SCK 6
#define ROMFH_FIF 7
#define ROMFH_EXEC 8
/* Alignment */
#define ROMFH_SIZE 16
#define ROMFH_PAD (ROMFH_SIZE-1)
#define ROMFH_MASK (~ROMFH_PAD)
#ifdef __KERNEL__
/* Not much now */
#endif /* __KERNEL__ */
#endif

0
tasks/fs0/src/sb.c Normal file
View File

View File

@@ -0,0 +1,31 @@
/*
* A basic unix-like read/writeable filesystem.
*
* Copyright (C) 2007 Bahadir Balban
*/
#define SIMPLEFS_BLOCK_SIZE 1024
/*
* Simplefs superblock
*/
struct simplefs_sb {
unsigned long magic; /* Filesystem magic */
unsigned long ioffset; /* Offset of first inode */
unsigned long bsize; /* Fs block size */
};
struct simplefs_sb *sb;
static void simplefs_fill_super(struct superblock *sb)
{
char buf[SIMPLEFS_BLOCK_SIZE];
bdev_read(0, SIMPLEFS_BLOCK_SIZE, buf);
}
static void simplefs_read_vnode(struct vnode *)
{
}

28
tasks/fs0/src/vfs.c Normal file
View File

@@ -0,0 +1,28 @@
#include <stdio.h>
#include <l4/api/ipc.h>
#include <l4lib/kip.h>
#include <l4lib/arch/syscalls.h>
/* Simply calls a wait ipc to sync with the given partner thread */
void wait_task(l4id_t partner)
{
u32 tag = L4_IPC_TAG_WAIT;
l4_ipc(partner, l4_nilthread, tag);
printf("%d synced with us.\n", (int)partner);
}
void mount_root(void)
{
l4id_t blkdev_shmid;
/*
* We know the primary block device from compile-time.
* It is expected to have the root filesystem.
*/
wait_task(BLKDEV_TID);
/* Set up a shared memory area with the block device */
l4_receive_shm(
}

0
tasks/fs0/src/vnode.c Normal file
View File

View File

@@ -0,0 +1,27 @@
#!/usr/bin/python
import os
import sys
compiler_prefix = "arm-linux-"
objdump = "objdump"
command = "-t"
image_name = "roottask.axf"
linkoutput_file_suffix = "-linkinfo.txt"
linkoutput_file = image_name + linkoutput_file_suffix
def generate_bootdesc():
command = compiler_prefix + objdump + " -t " + image_name + " > " + linkoutput_file
print command
os.system(command)
f = open(linkoutput_file, "r")
while True:
line = f.readline()
if len(line) is 0:
break
if "_start" in line or "_end" in line:
print line
f.close()
if __name__ == "__main__":
generate_bootdesc()