mirror of
https://github.com/drasko/codezero.git
synced 2026-01-10 17:56:38 +01:00
Updated LICENSE/README files, removed unused code from tasks.
This commit is contained in:
5
LICENSE
5
LICENSE
@@ -2,14 +2,13 @@
|
||||
The source code under the codezero directory tree is governed by the
|
||||
license below and this version only, unless it is stated otherwise as
|
||||
part of the file. To be more precise, for every source file where it
|
||||
says: "Copyright (C) 2007, 2008 Bahadir Balban" or a similar wording
|
||||
says: "Copyright (C) 2007-2009 Bahadir Balban" or a similar wording
|
||||
(capitalisation, years or the format of the name may change), the below
|
||||
license has effect. Any other source file may or may not be inclusive.
|
||||
For questions please contact me on bbalban@b-labs.co.uk
|
||||
For questions please contact me on bahadir@l4dev.org
|
||||
|
||||
Bahadir Balban
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
|
||||
197
README
197
README
@@ -1,100 +1,44 @@
|
||||
|
||||
Codezero Microkernel Pre-release
|
||||
Codezero Microkernel v0.1 Release
|
||||
|
||||
Copyright (C) 2007, 2008 Bahadir Balban
|
||||
Copyright (C) 2007-2009 Bahadir Bilgehan Balban
|
||||
|
||||
1.) What is Codezero?
|
||||
|
||||
Codezero is a new L4 microkernel that has been written from scratch. It is a
|
||||
modern microkernel implementation that provides capabilities for virtualization
|
||||
and implementation of native OS services. Codezero can act as a virtualisation
|
||||
platform, a hardware abstraction layer, and as a basis for developing operating
|
||||
system services. Codezero's primary focus is on embedded systems.
|
||||
|
||||
|
||||
What is Codezero?
|
||||
|
||||
Codezero is a new microkernel that has been developed for embedded systems. It
|
||||
implements a simple API that is based on the L4 Microkernel, and it can be used
|
||||
as a base to develop or run new operating systems. As part of the project,
|
||||
server tasks are provided that implement memory management and a virtual
|
||||
filesystem layer. These servers are built upon the base Codezero API, and they
|
||||
currently support a small but essential subset of the POSIX API.
|
||||
|
||||
Codezero targets high-end embedded systems that support virtual memory and it
|
||||
has an emphasis on the ARM architecture. Open source development practices are
|
||||
used in its development. Users can use Codezero's POSIX-like server tasks or
|
||||
another operating system built upon it, or both at the same time. Codezero aims
|
||||
to differ from other systems by implementing a modern embedded operating system
|
||||
and yet provide more flexibility than a single operating system API.
|
||||
|
||||
|
||||
Why the name Codezero?
|
||||
2.) Why the name Codezero?
|
||||
|
||||
The project focuses on simplicity and clarity in software design. Everything is
|
||||
kept simple, from the user-level tasks down to the build system that does not
|
||||
take part in the actual microkernel.
|
||||
kept simple, from the user-level services down to the build system that does
|
||||
not take part in the actual microkernel. Codezero is a microkernel that is
|
||||
easy-to-use and modify, providing a rapid kernel software development
|
||||
environment.
|
||||
|
||||
|
||||
Who could use Codezero?
|
||||
3.) Why use Codezero?
|
||||
|
||||
Currently, Codezero can be used on any embedded system that requires
|
||||
multitasking and virtual memory support but not all the detailed features of a
|
||||
complex operating system. Codezero's initial advantage in that respect would be
|
||||
its clarity and simplicity that makes it easier for users to grasp and use. In
|
||||
the near future, the real-time features will be optimised and it will also be a
|
||||
good candidate for real-time applications. Finally it will be used on systems
|
||||
that require high dependability. Tightly integrated embedded systems are one
|
||||
such example where multiple isolated application domains exist side-by-side,
|
||||
sharing the same cpu and memory system.
|
||||
Codezero aims to provide easy hands-on experience; you may simply download the
|
||||
source tree, install the tools using this guide, and get up and running with
|
||||
development on your virtual embedded platform from the comfort of your host PC.
|
||||
|
||||
Codezero strives to incorporate the most modern design features and presents
|
||||
them in a well-written source code base. In other words, Codezero strives to be
|
||||
technically cutting edge. Updates are rapid and open community is encouraged to
|
||||
get involved in core development.
|
||||
|
||||
|
||||
What are the design features?
|
||||
4.) What is the license?
|
||||
|
||||
Codezero attempts to incorporate many modern features that are present in
|
||||
today's operating systems. Some of them are presented below.
|
||||
|
||||
Based on the L4 microkernel design principles, there are only a few system
|
||||
calls in Codezero. These system calls provide purely mechanism; threads and
|
||||
address spaces, and the methods of inter-process communication between them.
|
||||
Anything beyond these are policy and they are implemented in the userspace. Due
|
||||
to this rigorously simple design the same microkernel can be used to design
|
||||
completely different operating systems.
|
||||
|
||||
In terms of other features, the microkernel is preemptive, and smp-ready.
|
||||
Currently only synchronous communication is implemented, but this will change
|
||||
in the near future. The microkernel also incorporates a simple priority-based
|
||||
scheduler, and all blocking operations (locking, ipc, waiting) are
|
||||
interruptible. Even though the microkernel needs to be optimised in its
|
||||
real-time capabilities, it does incorporate the necessary architecture to
|
||||
support real-time performance.
|
||||
|
||||
There are two system tasks built upon the base microkernel that manage memory
|
||||
and file-based I/O, called MM0 and FS0. MM0 is the system task that implements
|
||||
memory management. It contains allocators and manages the page cache. It
|
||||
implements demand paging by managing page faults, physical pages and their
|
||||
file/task associations. MM0 provides the default paging mechanism on Codezero.
|
||||
|
||||
FS0 is the system task that implements a simple, modern virtual filesystem
|
||||
layer. It is designed to serve file requests from MM0. Since it abstracts the
|
||||
low-level filesystem details, it is a relatively easy job to port a new
|
||||
filesystem to be used under FS0.
|
||||
|
||||
MM0 and FS0 both reside in the userspace, and they are not mandatory services.
|
||||
For example the virtual and physical memory resources can be partitioned by
|
||||
Codezero among pagers, and a third-party pager can override Codezero's pager on
|
||||
the same run-time, and implement an independent paging behaviour for its own
|
||||
memory partition. This feature provides the option of having an adjustable
|
||||
mixture of generalisation and specialisation of system services at the same
|
||||
run-time. For instance, Codezero's abstract posix-like page/file management
|
||||
services can be used in combination with an application-specific pager that
|
||||
depends on its own paging abilities. A critical task could both use mm0 and
|
||||
fs0's posix-like files benefiting from the abstraction and simplification that
|
||||
it brings, but at the same time rely on its own specialised page-fault handling
|
||||
mechanism for its critical data. Similarly, a complete operating system can be
|
||||
virtualised and both native and virtualised applications can run on the same
|
||||
run-time.
|
||||
|
||||
|
||||
What will the license be?
|
||||
|
||||
The current release is distributed under GNU General Public License Version 3
|
||||
and this version only. Any next version will be released in the same license,
|
||||
but there are intentions to keep the project in a dual-licensed manner. In any
|
||||
case, one version of the source code will always be released as open source as
|
||||
in the OSI definition.
|
||||
The current release is distributed under GNU General Public License Version 3.
|
||||
For contributions we ask for a copyright share agreement and you may freely
|
||||
contribute to the project this way. This is our current model, but if you
|
||||
object to this, feel free to mention your ideas in our mailing list.
|
||||
|
||||
The third party source code under the directories loader/ tools/ libs/c
|
||||
libs/elf have their own copyright and licenses, separate from this project. All
|
||||
@@ -102,79 +46,22 @@ third party source code is open source in the OSI definition. Please check
|
||||
these directories for their respective licenses.
|
||||
|
||||
|
||||
Why yet another POSIX microkernel?
|
||||
5.) Why not improve on a popular open source kernel instead of Codezero?
|
||||
|
||||
There are many open source POSIX operating systems with advanced features such
|
||||
as BSD versions and Linux. However, neither of these were originally designed
|
||||
for embedded systems. Multiple problems arise due to this fact.
|
||||
Open source POSIX kernels are not designed for running on embedded platforms.
|
||||
* Their source code is encumbered and cluttered with legacy or unrelated
|
||||
components.
|
||||
* Their user bases are saturated, their core developers are engaged and
|
||||
focused on non-embedded platforms.
|
||||
* Their source code base is too complex to grasp and most components enforce
|
||||
unnecessary policy on embedded applications.
|
||||
|
||||
Unix itself and all the tools built upon weren't meant for using on small
|
||||
devices. Accordingly, existing Unix operating systems contain a lot of
|
||||
historical code. Their code base is so big, that it gets more and more
|
||||
difficult to understand how their internals work. On these systems usually much
|
||||
of the existing code base is irrelevant to newly developed software, and
|
||||
embedded systems need new software often. Codezero is written from scratch to
|
||||
solely target embedded systems and as such the source code is %100 relevant.
|
||||
It is small and free from legacy code.
|
||||
Codezero is simple, clean, and focused on embedded systems. Still, existing
|
||||
open source kernels are valuable with some of their features and drivers. As a
|
||||
result, we attempt to virtualize them on top of Codezero.
|
||||
|
||||
From a design perspective, these kernels have a monolithic design, and as such
|
||||
they may have issues with dependability due to much of the code sharing the
|
||||
same address space. This is an important issue on embedded systems since their
|
||||
operation is more sensitive to disruptions. Being a microkernel design,
|
||||
Codezero aims to defeat this problem and increase dependability.
|
||||
|
||||
From a support perspective, most unix operating systems like BSD and Linux have
|
||||
a highly saturated user base. The developers focus on these existing users and
|
||||
often the systems they support are not embedded computers. Codezero will focus
|
||||
completely on embedded systems, aiming to meet the support need for this type
|
||||
of systems.
|
||||
|
||||
Other than modern Unix kernels, there are established operating systems
|
||||
targeting embedded devices. Codezero will contrast and compete with some of
|
||||
them by its simplicity, some by its openness and some by its feature set, but
|
||||
mostly by providing a more flexible development model.
|
||||
|
||||
Finally, POSIX compliance is only a step, or a partial aim for the Codezero
|
||||
microkernel. It is not limited to the goal of just complying with POSIX, which
|
||||
has been done many times by other operating systems. Codezero microkernel will
|
||||
provide a dependable software environment where isolated application domains
|
||||
can run side-by-side in the same run-time. In addition, user-level servers MM0
|
||||
and FS0 will implement native system services and provide a POSIX-like API for
|
||||
these application domains. By supplying a variety of system software options,
|
||||
the applications will be able to choose among different speed, safety,
|
||||
determinism policies at the same run-time. This is expected to prove useful in
|
||||
embedded systems.
|
||||
|
||||
Furthermore there are new ideas in literature that would improve systems
|
||||
software but aren't implemented either because they have no existing users or
|
||||
may break compatibility (e.g. some are presented in Plan 9). For example file
|
||||
abstractions could be used more liberally to cover data exchange and control of
|
||||
devices, services and network communication. Existing kernels already have
|
||||
established methods of doing such operations and they would oppose major design
|
||||
overhauls, which limits their innovation capability for this kind of
|
||||
experimentation. In contrast, Codezero's partitioned nature provides the
|
||||
opportunity to implement innovative feature services in small and isolated
|
||||
parts, without cluttering the rest of the system. As well as natively
|
||||
supporting existing APIs such as POSIX, Codezero project aims to keep up with
|
||||
the latest OS literature and provide the opportunity to incorporate the latest
|
||||
ideas in OS technology.
|
||||
|
||||
|
||||
Can you summarise? Why should I use Codezero, again?
|
||||
|
||||
Codezero is an operating system that targets embedded systems with virtual
|
||||
memory support. It implements modern features such as demand-paging and a
|
||||
virtual filesystem layer under a POSIX-like API. Different from most other
|
||||
POSIX-like systems, it is based on a microkernel design. The microkernel has
|
||||
been carefully designed so that it is small and well-focused. It has a cleanly
|
||||
separated set of system services that can be used as a base for implementing or
|
||||
running other operating systems. It can also be used as a barebones system that
|
||||
provides multitasking and thread communication. Its source code is also freely
|
||||
available (See LICENSE heading for details). Codezero aims to differ from other
|
||||
systems by implementing an open and modern embedded operating system that
|
||||
provides more flexibility than a single operating system API. Since currently
|
||||
there's a very small user base, it can be easily adopted for any custom
|
||||
embedded system project that needs focused developer attention.
|
||||
Other embedded open source kernels are also out there. Codezero aims to differ
|
||||
by clarity, simplicity and its cutting edge features.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
#
|
||||
# User space application build script
|
||||
#
|
||||
# Copyright (C) 2007 Bahadir Balban
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
from string import split
|
||||
from os.path import join
|
||||
from glob import glob
|
||||
|
||||
task_name = "blkdev0"
|
||||
|
||||
# The root directory of the repository where this file resides:
|
||||
project_root = "../.."
|
||||
tools_root = join(project_root, "tools")
|
||||
prev_image = join(project_root, "tasks/mm0/mm0.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_incpath = join(libl4_path, "include")
|
||||
|
||||
#libmem paths:
|
||||
libmem_path = "../libmem"
|
||||
libmem_incpath = "../libmem"
|
||||
|
||||
# kernel paths:
|
||||
kernel_incpath = join(project_root, "include")
|
||||
|
||||
# Kernel config header.
|
||||
config_h = join(project_root, "include/l4/config.h")
|
||||
|
||||
|
||||
# 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, "-L" + libmem_path],
|
||||
ASFLAGS = ['-D__ASSEMBLY__'],
|
||||
PROGSUFFIX = '.axf', # The suffix to use for final executable
|
||||
ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path
|
||||
LIBS = [libc_name, 'libl4', 'libmm', 'libmc', 'libkm', \
|
||||
'gcc', libc_name], # libgcc.a - This is required for division routines.
|
||||
CPPFLAGS = "-D__USERSPACE__",
|
||||
CPPPATH = ['#include', libl4_incpath, libc_incpath, kernel_incpath, libmem_incpath])
|
||||
|
||||
def extract_arch_subarch_plat(config_header):
|
||||
'''
|
||||
From the autogenerated kernel config.h, extracts platform, archictecture,
|
||||
subarchitecture information. This is used to include the relevant headers
|
||||
from the kernel directories.
|
||||
'''
|
||||
arch = None
|
||||
subarch = None
|
||||
plat = None
|
||||
|
||||
if not os.path.exists(config_header):
|
||||
print "\n\nconfig.h does not exist. "\
|
||||
"Please run: `scons configure' first\n\n"
|
||||
sys.exit()
|
||||
f = open(config_h, "r")
|
||||
while True:
|
||||
line = f.readline()
|
||||
if line == "":
|
||||
break
|
||||
parts = split(line)
|
||||
if len(parts) > 0:
|
||||
if parts[0] == "#define":
|
||||
if parts[1] == "__ARCH__":
|
||||
arch = parts[2]
|
||||
elif parts[1] == "__PLATFORM__":
|
||||
plat = parts[2]
|
||||
elif parts[1] == "__SUBARCH__":
|
||||
subarch = parts[2]
|
||||
f.close()
|
||||
if arch == None:
|
||||
print "Error: No config symbol found for architecture"
|
||||
sys.exit()
|
||||
if subarch == None:
|
||||
print "Error: No config symbol found for subarchitecture"
|
||||
sys.exit()
|
||||
if plat == None:
|
||||
print "Error: No config symbol found for platform"
|
||||
sys.exit()
|
||||
return arch, subarch, plat
|
||||
|
||||
def create_symlinks(arch):
|
||||
arch_path = "include/arch"
|
||||
arch_path2 ="src/arch"
|
||||
if os.path.exists(arch_path):
|
||||
os.system("rm %s" % (arch_path))
|
||||
os.system("ln -s %s %s" % ("arch-" + arch, arch_path))
|
||||
if os.path.exists(arch_path2):
|
||||
os.system("rm %s" % (arch_path2))
|
||||
os.system("ln -s %s %s" % ("arch-" + arch, arch_path2))
|
||||
|
||||
arch, subarch, plat = extract_arch_subarch_plat(config_h)
|
||||
|
||||
create_symlinks(arch) # Creates symlinks to architecture specific directories.
|
||||
|
||||
src = [glob("src/*.c"), glob("fsbin/*.S"), glob("*.c"), glob("src/arch/*.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)
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
#
|
||||
# Binary to elf build script
|
||||
# Works by including a binary in an assembler file and linking it.
|
||||
#
|
||||
# Copyright (C) 2007 Bahadir Balban
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
from os.path import join
|
||||
from glob import glob
|
||||
|
||||
elfimg_name = "romfs"
|
||||
|
||||
# The root directory of the repository where this file resides:
|
||||
project_root = "../.."
|
||||
tools_root = join(project_root, "tools")
|
||||
prev_image = join(project_root, "tasks/test0/test0.axf")
|
||||
ld_script = "include/linker.lds"
|
||||
physical_base_ld_script = "include/physical_base.lds"
|
||||
|
||||
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],
|
||||
ASFLAGS = ['-D__ASSEMBLY__'],
|
||||
PROGSUFFIX = '.axf', # The suffix to use for final executable
|
||||
ENV = {'PATH' : os.environ['PATH']}, # Inherit shell path
|
||||
CPPFLAGS = "-D__USERSPACE__",
|
||||
CPPPATH = ['#include'])
|
||||
|
||||
src = [glob("*.S")]
|
||||
objs = env.Object(src)
|
||||
physical_base = env.Command(physical_base_ld_script, prev_image, get_physical_base)
|
||||
task = env.Program(elfimg_name, objs)
|
||||
env.Alias(elfimg_name, task)
|
||||
env.Depends(task, physical_base)
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
|
||||
/* This is used to place a binary file into an elf section */
|
||||
.section .data.fs
|
||||
|
||||
.incbin "fsbin/romfs.bin"
|
||||
.align 4
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
arch-arm
|
||||
@@ -1,31 +0,0 @@
|
||||
#ifndef __BLKDEV_H__
|
||||
#define __BLKDEV_H__
|
||||
|
||||
#include <l4lib/types.h>
|
||||
|
||||
struct block_device;
|
||||
|
||||
struct block_device_ops {
|
||||
int (*init)(struct block_device *bdev);
|
||||
int (*open)(struct block_device *bdev);
|
||||
int (*read)(struct block_device *bdev, unsigned long offset,
|
||||
int size, void *buf);
|
||||
int (*write)(struct block_device *bdev, unsigned long offset,
|
||||
int size, void *buf);
|
||||
int (*read_page)(struct block_device *bdev,
|
||||
unsigned long pfn, void *buf);
|
||||
int (*write_page)(struct block_device *bdev,
|
||||
unsigned long pfn, void *buf);
|
||||
};
|
||||
|
||||
struct block_device {
|
||||
char *name;
|
||||
void *private; /* Low-level device specific data */
|
||||
u64 size;
|
||||
struct block_device_ops ops;
|
||||
};
|
||||
|
||||
|
||||
void init_blkdev(void);
|
||||
|
||||
#endif /* __BLKDEV_H__ */
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
. = ALIGN(4K);
|
||||
_start_ramdisk0 = .;
|
||||
*(.data.romfs)
|
||||
_end_ramdisk0 = .;
|
||||
. = ALIGN(4K);
|
||||
_start_ramdisk1 = .;
|
||||
*(.data.sfs)
|
||||
_end_ramdisk1 = .;
|
||||
*(.data)
|
||||
}
|
||||
.bss : AT (ADDR(.bss) - offset) { *(.bss) }
|
||||
_end = .;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#ifndef __RAMDISK_H__
|
||||
#define __RAMDISK_H__
|
||||
|
||||
extern struct block_device ramdisk[];
|
||||
extern struct block_device ramdisk[];
|
||||
|
||||
#endif
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* High-level block device handling.
|
||||
*
|
||||
* Copyright (C) 2007, 2008 Bahadir Balban
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <blkdev.h>
|
||||
|
||||
/*
|
||||
* Handles block device requests from fs0 using a combination of
|
||||
* server-specific and posix shm semantics
|
||||
*/
|
||||
void handle_block_device_request()
|
||||
{
|
||||
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_BLOCK_OPEN:
|
||||
sys_open(sender, (void *)mr[0], (int)mr[1], (u32)mr[2]);
|
||||
break;
|
||||
default:
|
||||
printf("%s: Unrecognised ipc tag (%d)"
|
||||
"received. Ignoring.\n", __TASKNAME__, mr[MR_TAG]);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* Initialise the block devices */
|
||||
init_blkdev();
|
||||
|
||||
while (1) {
|
||||
handle_block_device_request();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
|
||||
|
||||
#include <blkdev.h>
|
||||
#include <ramdisk.h>
|
||||
|
||||
|
||||
void init_blkdev(void)
|
||||
{
|
||||
ramdisk[0].ops.init(&ramdisk[0]);
|
||||
ramdisk[1].ops.init(&ramdisk[1]);
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* A basic ramdisk implementation.
|
||||
*
|
||||
* Copyright (C) 2007, 2008 Bahadir Balban
|
||||
*
|
||||
* The ramdisk binary is embedded in the data section of the ramdisk device
|
||||
* executable. Read/writes simply occur to this area. The disk area could
|
||||
* have any filesystem layout e.g. romfs, which is irrelevant for this code.
|
||||
*/
|
||||
#include <blkdev.h>
|
||||
#include <ramdisk.h>
|
||||
#include <l4/macros.h>
|
||||
#include <l4/config.h>
|
||||
#include <l4/types.h>
|
||||
#include <string.h>
|
||||
#include INC_SUBARCH(mm.h)
|
||||
#include INC_GLUE(memory.h)
|
||||
|
||||
/* Ramdisk section markers for ramdisk inside this executable image */
|
||||
extern char _start_ramdisk0[];
|
||||
extern char _end_ramdisk0[];
|
||||
extern char _start_ramdisk1[];
|
||||
extern char _end_ramdisk1[];
|
||||
|
||||
struct ramdisk_data {
|
||||
u64 base;
|
||||
u64 end;
|
||||
};
|
||||
|
||||
struct ramdisk_data rddata[2];
|
||||
|
||||
__attribute__((section(".data.sfs"))) char sfsdisk[SZ_16MB];
|
||||
|
||||
int ramdisk_init(struct block_device *ramdisk)
|
||||
{
|
||||
struct ramdisk_data *rddata = ramdisk->private;
|
||||
|
||||
if (!strcmp("ramdisk0", ramdisk->name)) {
|
||||
rddata->base = (u64)(unsigned long)_start_ramdisk0;
|
||||
rddata->end = (u64)(unsigned long)_end_ramdisk0;
|
||||
ramdisk->size = (u64)((unsigned long)_end_ramdisk0 -
|
||||
(unsigned long)_start_ramdisk0);
|
||||
} else if (!strcmp("ramdisk1", ramdisk->name)) {
|
||||
rddata->base = (u64)(unsigned long)_start_ramdisk1;
|
||||
rddata->end = (u64)(unsigned long)_end_ramdisk1;
|
||||
ramdisk->size = (u64)((unsigned long)_end_ramdisk1 -
|
||||
(unsigned long)_start_ramdisk1);
|
||||
} else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ramdisk_open(struct block_device *ramdisk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ramdisk_read(struct block_device *b, unsigned long offset, int size, void *buf)
|
||||
{
|
||||
struct ramdisk_data *data = b->private;
|
||||
void *src = (void *)(unsigned long)(data->base + offset);
|
||||
|
||||
memcpy(buf, src, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ramdisk_write(struct block_device *b, unsigned long offset,
|
||||
int size, void *buf)
|
||||
{
|
||||
struct ramdisk_data *data = b->private;
|
||||
void *dst = (void *)(unsigned long)(data->base + offset);
|
||||
|
||||
memcpy(dst, buf, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ramdisk_readpage(struct block_device *b, unsigned long pfn, void *buf)
|
||||
{
|
||||
ramdisk_read(b, __pfn_to_addr(pfn), PAGE_SIZE, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ramdisk_writepage(struct block_device *b, unsigned long pfn, void *buf)
|
||||
{
|
||||
ramdisk_write(b, __pfn_to_addr(pfn), PAGE_SIZE, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct block_device ramdisk[2] = {
|
||||
[0] = {
|
||||
.name = "ramdisk0",
|
||||
.private = &rddata[0],
|
||||
.ops = {
|
||||
.init = ramdisk_init,
|
||||
.open = ramdisk_open,
|
||||
.read = ramdisk_read,
|
||||
.write = ramdisk_write,
|
||||
.read_page = ramdisk_readpage,
|
||||
.write_page = ramdisk_writepage,
|
||||
},
|
||||
},
|
||||
[1] = {
|
||||
.name = "ramdisk1",
|
||||
.private = &rddata[1],
|
||||
.ops = {
|
||||
.init = ramdisk_init,
|
||||
.open = ramdisk_open,
|
||||
.read = ramdisk_read,
|
||||
.write = ramdisk_write,
|
||||
.read_page = ramdisk_readpage,
|
||||
.write_page = ramdisk_writepage,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import os
|
||||
import sys
|
||||
|
||||
compiler_prefix = "arm-none-linux-gnueabi-"
|
||||
objdump = "objdump"
|
||||
command = "-t"
|
||||
image_name = "inittask.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()
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
struct channel {
|
||||
int dir; /* Direction */
|
||||
char *name; /* Name */
|
||||
int cd; /* Channel descriptor */
|
||||
};
|
||||
|
||||
|
||||
struct interface {
|
||||
struct channel chan[];
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
void *buf = malloc(sizeof(struct channel)*10);
|
||||
struct interface *intf = buf;
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Lightweight and simple RPC primitives.
|
||||
*
|
||||
* Copyright (c) 2007 Bahadir Balban
|
||||
*
|
||||
* Some methodology is needed for efficient and functional message passing
|
||||
* among processes, particulary when shared memory or same address space
|
||||
* messaging is available. The rpc primitives here attempt to fill this gap.
|
||||
*
|
||||
* The idea is to generate as little bloat as possible. To that end we don't
|
||||
* need encryption, marshalling, type tracking and discovery. Also Very minor
|
||||
* boilerplated code is produced from C macros rather than a notorious rpc tool.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* What default value arg0 is given for rpc calls */
|
||||
#define ARG0 8
|
||||
#define PAGE_SIZE 0x1000
|
||||
char pagebuf[PAGE_SIZE];
|
||||
|
||||
struct ipc_shmem {
|
||||
unsigned long vaddr;
|
||||
};
|
||||
|
||||
struct tlmsg {
|
||||
struct ipc_shmem shmem;
|
||||
unsigned long arg[3];
|
||||
unsigned long ret;
|
||||
unsigned long method_num;
|
||||
};
|
||||
|
||||
typedef int (*remote_call_t)(struct tlmsg *m);
|
||||
|
||||
int square(int i)
|
||||
{
|
||||
printf("%s: Entering...\n", __FUNCTION__);
|
||||
return i*i;
|
||||
}
|
||||
|
||||
/* Hand coded wrapper for non-complex argument types. */
|
||||
int rpc_square(struct tlmsg *m)
|
||||
{
|
||||
printf("%s: Entering...\n", __FUNCTION__);
|
||||
return square(m->arg[0]);
|
||||
}
|
||||
|
||||
struct complex_struct {
|
||||
int item;
|
||||
int item2;
|
||||
};
|
||||
|
||||
/* Use this to declare an RPC wrapper for your function. Your function
|
||||
* must return a primitive type (e.g, int, float, long etc.) and can
|
||||
* have a ref to a single argument of complex type (e.g. a struct). Apart
|
||||
* from these limitations it is essentially a regular C function. Note
|
||||
* that one can pass a lot of data back and forth using a single struct.
|
||||
* The wrappers are very lightweight, and thanks to many possibilities of
|
||||
* shared memory (e.g. same address-space, shared pages) data need not be
|
||||
* copied when passed back and forth. */
|
||||
#define DECLARE_RPC_BYREF(ret, func, type0) \
|
||||
static inline ret rpc_byref_##func(struct tlmsg *m) \
|
||||
{ /* Find struct address */ \
|
||||
unsigned long multiword_struct = m->arg[0] + \
|
||||
m->shmem.vaddr; /* Data passed by a shared entity */ \
|
||||
return func((type0 *)multiword_struct); /* Call real function */\
|
||||
}
|
||||
|
||||
/* Same as above, but passing a structure by value instead of reference.
|
||||
* This is much slower due to lots of copying involved. It is not
|
||||
* recommended but included for completion. */
|
||||
#define DECLARE_RPC_BYVAL(ret, func, type0) \
|
||||
static inline ret rpc_byval_##func(struct tlmsg *m) \
|
||||
{ /* Find struct address */ \
|
||||
unsigned long multiword_struct = m->arg[0] + \
|
||||
m->shmem.vaddr; /* Data passed by a shared entity */ \
|
||||
/* Call real function, by value */ \
|
||||
return func((type0)(*(type0 *)multiword_struct)); \
|
||||
}
|
||||
/* Use these directly to declare the function, *and* its RPC wrapper. */
|
||||
#define RPC_FUNC_BYREF(ret, func, type0) \
|
||||
ret func(type0 *); \
|
||||
DECLARE_RPC_BYREF(ret, func, type0) \
|
||||
ret func(type0 *arg0)
|
||||
|
||||
#define RPC_FUNC_BYVAL(ret, func, type0) \
|
||||
ret func(type0); \
|
||||
DECLARE_RPC_BYVAL(ret, func, type0) \
|
||||
ret func(type0 arg0)
|
||||
|
||||
RPC_FUNC_BYVAL(int, complex_byval, struct complex_struct)
|
||||
{
|
||||
printf("%s: Entering...\n", __FUNCTION__);
|
||||
arg0.item++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
RPC_FUNC_BYREF(int, complex_byref, struct complex_struct)
|
||||
{
|
||||
printf("%s: Entering...\n", __FUNCTION__);
|
||||
arg0->item++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RPC_NAME(func, by) rpc_##by##_##func
|
||||
remote_call_t remote_call_array[] = {
|
||||
rpc_square,
|
||||
RPC_NAME(complex_byval, byval),
|
||||
RPC_NAME(complex_byref, byref),
|
||||
};
|
||||
|
||||
struct tlmsg *getmsg(int x)
|
||||
{
|
||||
struct tlmsg *m = (struct tlmsg *)malloc(sizeof(struct tlmsg));
|
||||
m->method_num = x;
|
||||
m->arg[0] = ARG0;
|
||||
m->shmem.vaddr = (unsigned long)&pagebuf;
|
||||
return m;
|
||||
}
|
||||
|
||||
void putmsg(struct tlmsg *m)
|
||||
{
|
||||
free((void *)m);
|
||||
}
|
||||
|
||||
void check_rpc_success()
|
||||
{
|
||||
struct complex_struct *cs = (struct complex_struct *)(pagebuf + ARG0);
|
||||
|
||||
printf("complex struct at offset 0x%x. cs->item: %d, expected: 1.\n", ARG0, cs->item);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct tlmsg *m[3];
|
||||
unsigned int ret;
|
||||
remote_call_t call[3];
|
||||
memset((void *)pagebuf, 0, PAGE_SIZE);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m[i] = getmsg(i);
|
||||
printf("Calling remote function %d according to incoming msg.\n", i);
|
||||
call[i] = remote_call_array[m[i]->method_num];
|
||||
ret = call[i](m[i]); /* i.e. call rpc function number i, with
|
||||
* message number i as argument */
|
||||
printf("Call returned %d\n", ret);
|
||||
m[i]->ret = ret;
|
||||
putmsg(m[i]);
|
||||
}
|
||||
check_rpc_success();
|
||||
}
|
||||
|
||||
|
||||
|
||||
BIN
tasks/sigma0/rpc
BIN
tasks/sigma0/rpc
Binary file not shown.
Reference in New Issue
Block a user