Subversion Repositories HelenOS

Compare Revisions

No changes between revisions

Ignore whitespace Rev 3424 → Rev 3425

/branches/tracing/contrib/toolchain/toolchain.ppc32.sh
15,8 → 15,12
fi
}
 
if [ -z "${CROSS_PREFIX}" ] ; then
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
GCC_VERSION="4.3.2"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
29,7 → 33,7
PLATFORM="ppc"
WORKDIR=`pwd`
TARGET="${PLATFORM}-linux-gnu"
PREFIX="/usr/local/${PLATFORM}"
PREFIX="${CROSS_PREFIX}/${PLATFORM}"
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
OBJDIR="${WORKDIR}/gcc-obj"
/branches/tracing/contrib/toolchain/toolchain.amd64.sh
15,8 → 15,12
fi
}
 
if [ -z "${CROSS_PREFIX}" ] ; then
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
GCC_VERSION="4.3.2"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
29,7 → 33,7
PLATFORM="amd64"
WORKDIR=`pwd`
TARGET="${PLATFORM}-linux-gnu"
PREFIX="/usr/local/${PLATFORM}"
PREFIX="${CROSS_PREFIX}/${PLATFORM}"
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
OBJDIR="${WORKDIR}/gcc-obj"
/branches/tracing/contrib/toolchain/toolchain.ppc64.sh
15,6 → 15,10
fi
}
 
if [ -z "${CROSS_PREFIX}" ] ; then
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
 
29,7 → 33,7
PLATFORM="ppc64"
WORKDIR=`pwd`
TARGET="${PLATFORM}-linux-gnu"
PREFIX="/usr/local/${PLATFORM}"
PREFIX="${CROSS_PREFIX}/${PLATFORM}"
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
OBJDIR="${WORKDIR}/gcc-obj"
/branches/tracing/contrib/toolchain/toolchain.ia32.sh
15,8 → 15,12
fi
}
 
if [ -z "${CROSS_PREFIX}" ] ; then
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
GCC_VERSION="4.3.2"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
29,7 → 33,7
PLATFORM="i686"
WORKDIR=`pwd`
TARGET="${PLATFORM}-pc-linux-gnu"
PREFIX="/usr/local/${PLATFORM}"
PREFIX="${CROSS_PREFIX}/${PLATFORM}"
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
OBJDIR="${WORKDIR}/gcc-obj"
/branches/tracing/contrib/toolchain/toolchain.mipsel32.sh
15,6 → 15,10
fi
}
 
if [ -z "${CROSS_PREFIX}" ] ; then
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
 
29,7 → 33,7
PLATFORM="mipsel"
WORKDIR=`pwd`
TARGET="${PLATFORM}-linux-gnu"
PREFIX="/usr/local/${PLATFORM}"
PREFIX="${CROSS_PREFIX}/${PLATFORM}"
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
OBJDIR="${WORKDIR}/gcc-obj"
/branches/tracing/contrib/toolchain/toolchain.sparc64.sh
15,6 → 15,10
fi
}
 
if [ -z "${CROSS_PREFIX}" ] ; then
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
 
29,7 → 33,7
PLATFORM="sparc64"
WORKDIR=`pwd`
TARGET="${PLATFORM}-linux-gnu"
PREFIX="/usr/local/${PLATFORM}"
PREFIX="${CROSS_PREFIX}/${PLATFORM}"
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
OBJDIR="${WORKDIR}/gcc-obj"
/branches/tracing/contrib/toolchain/toolchain.ia64.sh
15,8 → 15,12
fi
}
 
if [ -z "${CROSS_PREFIX}" ] ; then
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
GCC_VERSION="4.3.2"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
29,7 → 33,7
PLATFORM="ia64"
WORKDIR=`pwd`
TARGET="${PLATFORM}-pc-linux-gnu"
PREFIX="/usr/local/${PLATFORM}"
PREFIX="${CROSS_PREFIX}/${PLATFORM}"
INCLUDESDIR="${WORKDIR}/include"
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
/branches/tracing/contrib/toolchain/toolchain.arm32.sh
15,8 → 15,12
fi
}
 
if [ -z "${CROSS_PREFIX}" ] ; then
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
GCC_VERSION="4.3.2"
 
BINUTILS="binutils-${BINUTILS_VERSION}.tar.gz"
GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
29,7 → 33,7
PLATFORM="arm"
WORKDIR=`pwd`
TARGET="${PLATFORM}-linux-gnu"
PREFIX="/usr/local/${PLATFORM}"
PREFIX="${CROSS_PREFIX}/${PLATFORM}"
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
OBJDIR="${WORKDIR}/gcc-obj"
/branches/tracing/contrib/toolchain/toolchain.mipseb32.sh
15,6 → 15,10
fi
}
 
if [ -z "${CROSS_PREFIX}" ] ; then
CROSS_PREFIX="/usr/local"
fi
 
BINUTILS_VERSION="2.18"
GCC_VERSION="4.3.1"
 
29,7 → 33,7
PLATFORM="mips"
WORKDIR=`pwd`
TARGET="${PLATFORM}-sgi-irix5"
PREFIX="/usr/local/${PLATFORM}"
PREFIX="${CROSS_PREFIX}/${PLATFORM}"
BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
OBJDIR="${WORKDIR}/gcc-obj"
/branches/tracing/contrib/conf/bootindy
File deleted
/branches/tracing/contrib/conf/msim.conf
2,12 → 2,14
# MSIM configuration script
#
 
add dcpu mips1
add dcpu cpu0
 
add rwm mainmem 0x00000000 8M
add rwm mainmem 0x00000000
mainmem generic 16M
mainmem load "/dev/zero"
 
add rom bootmem 0x1fc00000 2048k
add rom bootmem 0x1fc00000
bootmem generic 4096k
bootmem load "image.boot"
 
add dprinter printer 0x10000000
/branches/tracing/kernel/test/mm/slab2.c
216,7 → 216,7
printf("Running stress test with size %d\n", size);
condvar_initialize(&thread_starter);
mutex_initialize(&starter_mutex);
mutex_initialize(&starter_mutex, MUTEX_PASSIVE);
 
thr_cache = slab_cache_create("thread_cache", size, 0, NULL, NULL, 0);
semaphore_initialize(&thr_sem,0);
/branches/tracing/kernel/kernel.config
81,7 → 81,6
@ "simics" Virtutech Simics simulator
@ "lgxemul" GXEmul Little Endian
@ "bgxemul" GXEmul Big Endian
@ "indy" SGI Indy
! [ARCH=mips32] MACHINE (choice)
 
# Framebuffer support
168,9 → 167,3
 
# Compile kernel tests
! CONFIG_TEST (y/n)
 
 
## Experimental features
 
# Enable experimental features
! CONFIG_EXPERIMENTAL (n/y)
/branches/tracing/kernel/doc/BUGS_FOUND
File deleted
/branches/tracing/kernel/doc/AUTHORS
1,12 → 1,12
Jakub Jermar <jermar@helenos.eu>
Martin Decky <decky@helenos.eu>
Ondrej Palkovsky <palkovsky@helenos.eu>
Jakub Vana <vana@helenos.eu>
Josef Cejka <cejka@helenos.eu>
Michal Kebrt <michalek.k@seznam.cz>
Sergey Bondari <bondari@helenos.eu>
Pavel Jancik <alfik.009@seznam.cz>
Petr Stepan <stepan.petr@volny.cz>
Michal Konopa <mkonopa@seznam.cz>
Jakub Jermar
Martin Decky
Ondrej Palkovsky
Jiri Svoboda
Jakub Vana
Josef Cejka
Michal Kebrt
Sergey Bondari
Pavel Jancik
Petr Stepan
Michal Konopa
Vojtech Mencl
 
/branches/tracing/kernel/doc/arch/mips32
3,11 → 3,9
 
mips32 is the second port of SPARTAN kernel originally written by Jakub Jermar.
It was first developed to run on MIPS R4000 32-bit simulator.
Now it can run on real hardware as well.
It can be compiled and run either as little- or big-endian.
 
HARDWARE REQUIREMENTS
o SGI Indy R4600
o emulated MIPS 4K CPU
 
CPU
/branches/tracing/kernel/genarch/include/mm/page_pt.h
116,9 → 116,7
#define PTE_WRITABLE(p) PTE_WRITABLE_ARCH((p))
#define PTE_EXECUTABLE(p) PTE_EXECUTABLE_ARCH((p))
 
#ifndef __OBJC__
extern as_operations_t as_pt_operations;
#endif
extern page_mapping_operations_t pt_mapping_operations;
 
extern void page_mapping_insert_pt(as_t *as, uintptr_t page, uintptr_t frame,
/branches/tracing/kernel/genarch/src/mm/as_ht.c
72,7 → 72,7
{
if (flags & FLAG_AS_KERNEL) {
hash_table_create(&page_ht, PAGE_HT_ENTRIES, 2, &ht_operations);
mutex_initialize(&page_ht_lock);
mutex_initialize(&page_ht_lock, MUTEX_PASSIVE);
}
return NULL;
}
/branches/tracing/kernel/genarch/src/mm/as_pt.c
52,31 → 52,6
static void pt_lock(as_t *as, bool lock);
static void pt_unlock(as_t *as, bool unlock);
 
#ifdef __OBJC__
@implementation as_t
 
+ (pte_t *) page_table_create: (int) flags
{
return ptl0_create(flags);
}
 
+ (void) page_table_destroy: (pte_t *) page_table
{
ptl0_destroy(page_table);
}
 
- (void) page_table_lock: (bool) _lock
{
pt_lock(self, _lock);
}
 
- (void) page_table_unlock: (bool) unlock
{
pt_unlock(self, unlock);
}
 
@end
#else
as_operations_t as_pt_operations = {
.page_table_create = ptl0_create,
.page_table_destroy = ptl0_destroy,
83,7 → 58,6
.page_table_lock = pt_lock,
.page_table_unlock = pt_unlock
};
#endif
 
/** Create PTL0.
*
/branches/tracing/kernel/generic/include/config.h
40,8 → 40,6
 
#define STACK_SIZE PAGE_SIZE
 
#define CONFIG_MEMORY_SIZE (8 * 1024 * 1024)
 
#define CONFIG_INIT_TASKS 32
 
typedef struct {
/branches/tracing/kernel/generic/include/proc/task.h
145,7 → 145,6
#endif
 
extern unative_t sys_task_get_id(task_id_t *uspace_task_id);
extern unative_t sys_task_spawn(void *image, size_t size);
 
#endif
 
/branches/tracing/kernel/generic/include/proc/thread.h
252,8 → 252,6
extern void thread_update_accounting(void);
extern bool thread_exists(thread_t *t);
 
extern thread_t *thread_create_program(void *program_addr, char *name);
 
/** Fpu context slab cache. */
extern slab_cache_t *fpu_context_slab;
 
/branches/tracing/kernel/generic/include/proc/program.h
0,0 → 1,65
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genericproc
* @{
*/
/** @file
*/
 
#ifndef KERN_PROGRAM_H_
#define KERN_PROGRAM_H_
 
#include <arch/types.h>
 
struct task;
struct thread;
 
/** Program info structure.
*
* A program is an abstraction of a freshly created (not yet running)
* userspace task containing a main thread along with its userspace stack.
*/
typedef struct program {
struct task *task; /**< Program task */
struct thread *main_thread; /**< Program main thread */
} program_t;
 
extern void *program_loader;
 
extern void program_create(as_t *as, uintptr_t entry_addr, program_t *p);
extern int program_create_from_image(void *image_addr, program_t *p);
extern int program_create_loader(program_t *p);
extern void program_ready(program_t *p);
 
extern unative_t sys_program_spawn_loader(int *uspace_phone_id);
 
#endif
 
/** @}
*/
/branches/tracing/kernel/generic/include/lib/objc_ext.h
File deleted
/branches/tracing/kernel/generic/include/lib/objc.h
File deleted
/branches/tracing/kernel/generic/include/lib/elf.h
114,7 → 114,8
#define EE_MEMORY 2 /* Cannot allocate address space */
#define EE_INCOMPATIBLE 3 /* ELF image is not compatible with current architecture */
#define EE_UNSUPPORTED 4 /* Non-supported ELF (e.g. dynamic ELFs) */
#define EE_IRRECOVERABLE 5
#define EE_LOADER 5 /* The image is actually a program loader */
#define EE_IRRECOVERABLE 6
 
/**
* ELF section types
338,6 → 339,10
 
extern char *elf_error(unsigned int rc);
 
/* Interpreter string used to recognize the program loader */
#define ELF_INTERP_ZSTR "kernel"
#define ELF_INTERP_ZLEN sizeof(ELF_INTERP_ZSTR)
 
#endif
 
/** @}
/branches/tracing/kernel/generic/include/synch/mutex.h
39,20 → 39,26
#include <synch/semaphore.h>
#include <synch/synch.h>
 
typedef enum {
MUTEX_PASSIVE,
MUTEX_ACTIVE
} mutex_type_t;
 
typedef struct {
mutex_type_t type;
semaphore_t sem;
} mutex_t;
 
#define mutex_lock(mtx) \
#define mutex_lock(mtx) \
_mutex_lock_timeout((mtx), SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE)
#define mutex_trylock(mtx) \
#define mutex_trylock(mtx) \
_mutex_lock_timeout((mtx), SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NON_BLOCKING)
#define mutex_lock_timeout(mtx, usec) \
#define mutex_lock_timeout(mtx, usec) \
_mutex_lock_timeout((mtx), (usec), SYNCH_FLAGS_NON_BLOCKING)
 
extern void mutex_initialize(mutex_t *mtx);
extern int _mutex_lock_timeout(mutex_t *mtx, uint32_t usec, int flags);
extern void mutex_unlock(mutex_t *mtx);
extern void mutex_initialize(mutex_t *, mutex_type_t);
extern int _mutex_lock_timeout(mutex_t *, uint32_t, int);
extern void mutex_unlock(mutex_t *);
 
#endif
 
/branches/tracing/kernel/generic/include/synch/smc.h
0,0 → 1,43
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sync
* @{
*/
/** @file
*/
 
#ifndef KERN_SMC_H_
#define KERN_SMC_H_
 
extern unative_t sys_smc_coherence(uintptr_t va, size_t size);
 
#endif
 
/** @}
*/
/branches/tracing/kernel/generic/include/mm/frame.h
57,15 → 57,14
/** Maximum number of zones in system. */
#define ZONES_MAX 16
 
/** If possible, merge with neighbouring zones. */
#define ZONE_JOIN 0x1
 
/** Convert the frame address to kernel va. */
#define FRAME_KA 0x1
/** Do not panic and do not sleep on failure. */
#define FRAME_ATOMIC 0x2
#define FRAME_ATOMIC 0x2
/** Do not start reclaiming when no free memory. */
#define FRAME_NO_RECLAIM 0x4
#define FRAME_NO_RECLAIM 0x4
/** Do not allocate above 4 GiB. */
#define FRAME_LOW_4_GiB 0x8
 
static inline uintptr_t PFN2ADDR(pfn_t frame)
{
90,30 → 89,30
}
 
#define IS_BUDDY_ORDER_OK(index, order) \
((~(((unative_t) -1) << (order)) & (index)) == 0)
((~(((unative_t) -1) << (order)) & (index)) == 0)
#define IS_BUDDY_LEFT_BLOCK(zone, frame) \
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
#define IS_BUDDY_RIGHT_BLOCK(zone, frame) \
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
(((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
#define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
#define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
(((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
 
#define frame_alloc(order, flags) \
frame_alloc_generic(order, flags, NULL)
frame_alloc_generic(order, flags, NULL)
 
extern void frame_init(void);
extern void *frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone);
extern void frame_free(uintptr_t frame);
extern void frame_reference_add(pfn_t pfn);
extern void *frame_alloc_generic(uint8_t, int, unsigned int *);
extern void frame_free(uintptr_t);
extern void frame_reference_add(pfn_t);
 
extern int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags);
extern void *frame_get_parent(pfn_t frame, unsigned int hint);
extern void frame_set_parent(pfn_t frame, void *data, unsigned int hint);
extern void frame_mark_unavailable(pfn_t start, count_t count);
extern uintptr_t zone_conf_size(count_t count);
extern void zone_merge(unsigned int z1, unsigned int z2);
extern int zone_create(pfn_t, count_t, pfn_t, int);
extern void *frame_get_parent(pfn_t, unsigned int);
extern void frame_set_parent(pfn_t, void *, unsigned int);
extern void frame_mark_unavailable(pfn_t, count_t);
extern uintptr_t zone_conf_size(count_t);
extern void zone_merge(unsigned int, unsigned int);
extern void zone_merge_all(void);
extern uint64_t zone_total_size(void);
 
121,7 → 120,7
* Console functions
*/
extern void zone_print_list(void);
extern void zone_print_one(unsigned int znum);
extern void zone_print_one(unsigned int);
 
#endif
 
/branches/tracing/kernel/generic/include/mm/page.h
39,11 → 39,6
#include <mm/as.h>
#include <memstr.h>
 
/**
* Macro for computing page color.
*/
#define PAGE_COLOR(va) (((va) >> PAGE_WIDTH) & ((1 << PAGE_COLOR_BITS) - 1))
 
/** Operations to manipulate page mappings. */
typedef struct {
void (* mapping_insert)(as_t *as, uintptr_t page, uintptr_t frame,
/branches/tracing/kernel/generic/include/mm/slab.h
53,7 → 53,8
#define SLAB_INSIDE_SIZE (PAGE_SIZE >> 3)
 
/** Maximum wasted space we allow for cache */
#define SLAB_MAX_BADNESS(cache) (((unsigned int) PAGE_SIZE << (cache)->order) >> 2)
#define SLAB_MAX_BADNESS(cache) \
(((unsigned int) PAGE_SIZE << (cache)->order) >> 2)
 
/* slab_reclaim constants */
 
99,7 → 100,7
int flags;
 
/* Computed values */
uint8_t order; /**< Order of frames to be allocated */
uint8_t order; /**< Order of frames to be allocated */
unsigned int objects; /**< Number of objects that fit in */
 
/* Statistics */
121,14 → 122,13
slab_mag_cache_t *mag_cache;
} slab_cache_t;
 
extern slab_cache_t * slab_cache_create(char *name, size_t size, size_t align,
int (*constructor)(void *obj, int kmflag), int (*destructor)(void *obj),
int flags);
extern void slab_cache_destroy(slab_cache_t *cache);
extern slab_cache_t *slab_cache_create(char *, size_t, size_t,
int (*)(void *, int), int (*)(void *), int);
extern void slab_cache_destroy(slab_cache_t *);
 
extern void * slab_alloc(slab_cache_t *cache, int flags);
extern void slab_free(slab_cache_t *cache, void *obj);
extern count_t slab_reclaim(int flags);
extern void * slab_alloc(slab_cache_t *, int);
extern void slab_free(slab_cache_t *, void *);
extern count_t slab_reclaim(int);
 
/* slab subsytem initialization */
extern void slab_cache_init(void);
138,9 → 138,9
extern void slab_print_list(void);
 
/* malloc support */
extern void * malloc(unsigned int size, int flags);
extern void * realloc(void *ptr, unsigned int size, int flags);
extern void free(void *ptr);
extern void *malloc(unsigned int, int);
extern void *realloc(void *, unsigned int, int);
extern void free(void *);
#endif
 
/** @}
/branches/tracing/kernel/generic/include/mm/as.h
53,10 → 53,6
#include <adt/btree.h>
#include <lib/elf.h>
 
#ifdef __OBJC__
#include <lib/objc.h>
#endif
 
/**
* Defined to be true if user address space and kernel address space shadow each
* other.
84,47 → 80,6
/** The page fault was caused by memcpy_from_uspace() or memcpy_to_uspace(). */
#define AS_PF_DEFER 2
 
#ifdef __OBJC__
@interface as_t : base_t {
@public
/** Protected by asidlock. */
link_t inactive_as_with_asid_link;
/**
* Number of processors on wich is this address space active.
* Protected by asidlock.
*/
count_t cpu_refcount;
/**
* Address space identifier.
* Constant on architectures that do not support ASIDs.
* Protected by asidlock.
*/
asid_t asid;
/** Number of references (i.e tasks that reference this as). */
atomic_t refcount;
 
mutex_t lock;
/** B+tree of address space areas. */
btree_t as_area_btree;
/** Non-generic content. */
as_genarch_t genarch;
/** Architecture specific content. */
as_arch_t arch;
}
 
+ (pte_t *) page_table_create: (int) flags;
+ (void) page_table_destroy: (pte_t *) page_table;
- (void) page_table_lock: (bool) _lock;
- (void) page_table_unlock: (bool) unlock;
 
@end
 
#else
 
/** Address space structure.
*
* as_t contains the list of as_areas of userspace accessible
168,7 → 123,6
void (* page_table_lock)(as_t *as, bool lock);
void (* page_table_unlock)(as_t *as, bool unlock);
} as_operations_t;
#endif
 
/**
* This structure contains information associated with the shared address space
249,10 → 203,7
 
extern as_t *AS_KERNEL;
 
#ifndef __OBJC__
extern as_operations_t *as_operations;
#endif
 
extern link_t inactive_as_with_asid_head;
 
extern void as_init(void);
269,6 → 220,7
extern int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags);
int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
as_t *dst_as, uintptr_t dst_base, int dst_flags_mask);
extern int as_area_change_flags(as_t *as, int flags, uintptr_t address);
 
extern int as_area_get_flags(as_area_t *area);
extern bool as_area_check_access(as_area_t *area, pf_access_t access);
301,11 → 253,19
extern mem_backend_t elf_backend;
extern mem_backend_t phys_backend;
 
extern unsigned int elf_load(elf_header_t *header, as_t *as);
/**
* This flags is passed when running the loader, otherwise elf_load()
* would return with a EE_LOADER error code.
*/
#define ELD_F_NONE 0
#define ELD_F_LOADER 1
 
extern unsigned int elf_load(elf_header_t *header, as_t *as, int flags);
 
/* Address space area related syscalls. */
extern unative_t sys_as_area_create(uintptr_t address, size_t size, int flags);
extern unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags);
extern unative_t sys_as_area_change_flags(uintptr_t address, int flags);
extern unative_t sys_as_area_destroy(uintptr_t address);
 
/* Introspection functions. */
/branches/tracing/kernel/generic/include/mm/buddy.h
66,7 → 66,6
void (*mark_available)(struct buddy_system *, link_t *);
/** Find parent of block that has given order */
link_t *(* find_block)(struct buddy_system *, link_t *, uint8_t);
void (* print_id)(struct buddy_system *, link_t *);
} buddy_system_operations_t;
 
typedef struct buddy_system {
78,14 → 77,13
void *data;
} buddy_system_t;
 
extern void buddy_system_create(buddy_system_t *b, uint8_t max_order,
buddy_system_operations_t *op, void *data);
extern link_t *buddy_system_alloc(buddy_system_t *b, uint8_t i);
extern bool buddy_system_can_alloc(buddy_system_t *b, uint8_t order);
extern void buddy_system_free(buddy_system_t *b, link_t *block);
extern void buddy_system_structure_print(buddy_system_t *b, size_t elem_size);
extern size_t buddy_conf_size(int max_order);
extern link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block);
extern void buddy_system_create(buddy_system_t *, uint8_t,
buddy_system_operations_t *, void *);
extern link_t *buddy_system_alloc(buddy_system_t *, uint8_t);
extern bool buddy_system_can_alloc(buddy_system_t *, uint8_t);
extern void buddy_system_free(buddy_system_t *, link_t *);
extern size_t buddy_conf_size(int);
extern link_t *buddy_system_alloc_block(buddy_system_t *, link_t *);
 
#endif
 
/branches/tracing/kernel/generic/include/macros.h
40,20 → 40,20
#define isdigit(d) (((d) >= '0') && ((d) <= '9'))
#define islower(c) (((c) >= 'a') && ((c) <= 'z'))
#define isupper(c) (((c) >= 'A') && ((c) <= 'Z'))
#define isalpha(c) (is_lower(c) || is_upper(c))
#define isalphanum(c) (is_alpha(c) || is_digit(c))
#define isalpha(c) (is_lower((c)) || is_upper((c)))
#define isalphanum(c) (is_alpha((c)) || is_digit((c)))
#define isspace(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || \
((c) == '\r'))
((c) == '\r'))
 
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
 
/** Return true if the interlvals overlap.
/** Return true if the intervals overlap.
*
* @param s1 Start address of the first interval.
* @param sz1 Size of the first interval.
* @param s2 Start address of the second interval.
* @param sz2 Size of the second interval.
* @param s1 Start address of the first interval.
* @param sz1 Size of the first interval.
* @param s2 Start address of the second interval.
* @param sz2 Size of the second interval.
*/
static inline int overlaps(uintptr_t s1, size_t sz1, uintptr_t s2, size_t sz2)
{
64,11 → 64,15
}
 
/* Compute overlapping of physical addresses */
#define PA_overlaps(x, szx, y, szy) overlaps(KA2PA(x), szx, KA2PA(y), szy)
#define PA_overlaps(x, szx, y, szy) \
overlaps(KA2PA((x)), (szx), KA2PA((y)), (szy))
 
#define SIZE2KB(size) (size >> 10)
#define SIZE2MB(size) (size >> 20)
#define SIZE2KB(size) ((size) >> 10)
#define SIZE2MB(size) ((size) >> 20)
 
#define KB2SIZE(kb) ((kb) << 10)
#define MB2SIZE(mb) ((mb) << 20)
 
#define STRING(arg) STRING_ARG(arg)
#define STRING_ARG(arg) #arg
 
/branches/tracing/kernel/generic/include/syscall/syscall.h
44,13 → 44,15
SYS_THREAD_GET_ID,
SYS_TASK_GET_ID,
SYS_TASK_SPAWN,
SYS_PROGRAM_SPAWN_LOADER,
SYS_FUTEX_SLEEP,
SYS_FUTEX_WAKEUP,
SYS_SMC_COHERENCE,
SYS_AS_AREA_CREATE,
SYS_AS_AREA_RESIZE,
SYS_AS_AREA_CHANGE_FLAGS,
SYS_AS_AREA_DESTROY,
SYS_IPC_CALL_SYNC_FAST,
/branches/tracing/kernel/generic/include/ipc/ipc.h
287,27 → 287,33
 
/** Buffer for IPC_M_DATA_WRITE and IPC_M_DATA_READ. */
uint8_t *buffer;
 
/*
* The forward operation can masquerade the caller phone. For those
* cases, we must keep it aside so that the answer is processed
* correctly.
*/
phone_t *caller_phone;
} call_t;
 
extern void ipc_init(void);
extern call_t * ipc_wait_for_call(answerbox_t *box, uint32_t usec, int flags);
extern void ipc_answer(answerbox_t *box, call_t *request);
extern int ipc_call(phone_t *phone, call_t *call);
extern void ipc_call_sync(phone_t *phone, call_t *request);
extern void ipc_phone_init(phone_t *phone);
extern void ipc_phone_connect(phone_t *phone, answerbox_t *box);
extern void ipc_call_free(call_t *call);
extern call_t * ipc_call_alloc(int flags);
extern void ipc_answerbox_init(answerbox_t *box, struct task *task);
extern void ipc_call_static_init(call_t *call);
extern call_t * ipc_wait_for_call(answerbox_t *, uint32_t, int);
extern void ipc_answer(answerbox_t *, call_t *);
extern int ipc_call(phone_t *, call_t *);
extern int ipc_call_sync(phone_t *, call_t *);
extern void ipc_phone_init(phone_t *);
extern void ipc_phone_connect(phone_t *, answerbox_t *);
extern void ipc_call_free(call_t *);
extern call_t * ipc_call_alloc(int);
extern void ipc_answerbox_init(answerbox_t *, struct task *);
extern void ipc_call_static_init(call_t *);
extern void task_print_list(void);
extern int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox,
int mode);
extern int ipc_forward(call_t *, phone_t *, answerbox_t *, int);
extern void ipc_cleanup(void);
extern int ipc_phone_hangup(phone_t *phone);
extern void ipc_backsend_err(phone_t *phone, call_t *call, unative_t err);
extern void ipc_print_task(task_id_t taskid);
extern int ipc_connect_kbox(task_id_t taskid);
extern int ipc_phone_hangup(phone_t *);
extern void ipc_backsend_err(phone_t *, call_t *, unative_t);
extern void ipc_print_task(task_id_t);
extern int ipc_connect_kbox(task_id_t);
 
extern answerbox_t *ipc_phone_0;
 
/branches/tracing/kernel/generic/include/errno.h
56,6 → 56,7
#define EINVAL -13 /* Invalid value */
#define EBUSY -14 /* Resource is busy */
#define EOVERFLOW -15 /* The result does not fit its size. */
#define EINTR -16 /* Operation was interrupted. */
 
#endif
 
/branches/tracing/kernel/generic/src/synch/rwlock.c
82,7 → 82,7
*/
void rwlock_initialize(rwlock_t *rwl) {
spinlock_initialize(&rwl->lock, "rwlock_t");
mutex_initialize(&rwl->exclusive);
mutex_initialize(&rwl->exclusive, MUTEX_PASSIVE);
rwl->readers_in = 0;
}
 
/branches/tracing/kernel/generic/src/synch/mutex.c
38,42 → 38,54
#include <synch/mutex.h>
#include <synch/semaphore.h>
#include <synch/synch.h>
#include <debug.h>
 
/** Initialize mutex
/** Initialize mutex.
*
* Initialize mutex.
*
* @param mtx Mutex.
* @param mtx Mutex.
* @param type Type of the mutex.
*/
void mutex_initialize(mutex_t *mtx)
void mutex_initialize(mutex_t *mtx, mutex_type_t type)
{
mtx->type = type;
semaphore_initialize(&mtx->sem, 1);
}
 
/** Acquire mutex
/** Acquire mutex.
*
* Acquire mutex.
* Timeout mode and non-blocking mode can be requested.
*
* @param mtx Mutex.
* @param usec Timeout in microseconds.
* @param flags Specify mode of operation.
* @param mtx Mutex.
* @param usec Timeout in microseconds.
* @param flags Specify mode of operation.
*
* For exact description of possible combinations of
* usec and flags, see comment for waitq_sleep_timeout().
*
* @return See comment for waitq_sleep_timeout().
* @return See comment for waitq_sleep_timeout().
*/
int _mutex_lock_timeout(mutex_t *mtx, uint32_t usec, int flags)
{
return _semaphore_down_timeout(&mtx->sem, usec, flags);
int rc;
 
if (mtx->type == MUTEX_PASSIVE) {
rc = _semaphore_down_timeout(&mtx->sem, usec, flags);
} else {
ASSERT(mtx->type == MUTEX_ACTIVE);
ASSERT(usec == SYNCH_NO_TIMEOUT);
ASSERT(!(flags & SYNCH_FLAGS_INTERRUPTIBLE));
do {
rc = semaphore_trydown(&mtx->sem);
} while (SYNCH_FAILED(rc) &&
!(flags & SYNCH_FLAGS_NON_BLOCKING));
}
 
return rc;
}
 
/** Release mutex
/** Release mutex.
*
* Release mutex.
*
* @param mtx Mutex.
* @param mtx Mutex.
*/
void mutex_unlock(mutex_t *mtx)
{
/branches/tracing/kernel/generic/src/synch/smc.c
0,0 → 1,60
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup sync
* @{
*/
 
/**
* @file
* @brief Self-modifying code barriers.
*/
 
#include <arch.h>
#include <macros.h>
#include <errno.h>
#include <arch/barrier.h>
#include <synch/smc.h>
 
unative_t sys_smc_coherence(uintptr_t va, size_t size)
{
if (overlaps(va, size, NULL, PAGE_SIZE))
return EINVAL;
 
if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
if (overlaps(va, size, KERNEL_ADDRESS_SPACE_START,
KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START))
return EINVAL;
}
 
smc_coherence_block((void *) va, size);
return 0;
}
 
/** @}
*/
/branches/tracing/kernel/generic/src/synch/condvar.c
43,7 → 43,7
 
/** Initialize condition variable.
*
* @param cv Condition variable.
* @param cv Condition variable.
*/
void condvar_initialize(condvar_t *cv)
{
50,11 → 50,10
waitq_initialize(&cv->wq);
}
 
/**
* Signal the condition has become true
* to the first waiting thread by waking it up.
/** Signal the condition has become true to the first waiting thread by waking
* it up.
*
* @param cv Condition variable.
* @param cv Condition variable.
*/
void condvar_signal(condvar_t *cv)
{
61,11 → 60,10
waitq_wakeup(&cv->wq, WAKEUP_FIRST);
}
 
/**
* Signal the condition has become true
* to all waiting threads by waking them up.
/** Signal the condition has become true to all waiting threads by waking
* them up.
*
* @param cv Condition variable.
* @param cv Condition variable.
*/
void condvar_broadcast(condvar_t *cv)
{
74,17 → 72,17
 
/** Wait for the condition becoming true.
*
* @param cv Condition variable.
* @param mtx Mutex.
* @param usec Timeout value in microseconds.
* @param flags Select mode of operation.
* @param cv Condition variable.
* @param mtx Mutex.
* @param usec Timeout value in microseconds.
* @param flags Select mode of operation.
*
* For exact description of meaning of possible combinations
* of usec and flags, see comment for waitq_sleep_timeout().
* Note that when SYNCH_FLAGS_NON_BLOCKING is specified here,
* ESYNCH_WOULD_BLOCK is always returned.
* For exact description of meaning of possible combinations of usec and flags,
* see comment for waitq_sleep_timeout(). Note that when
* SYNCH_FLAGS_NON_BLOCKING is specified here, ESYNCH_WOULD_BLOCK is always
* returned.
*
* @return See comment for waitq_sleep_timeout().
* @return See comment for waitq_sleep_timeout().
*/
int _condvar_wait_timeout(condvar_t *cv, mutex_t *mtx, uint32_t usec, int flags)
{
/branches/tracing/kernel/generic/src/main/kinit.c
47,6 → 47,7
#include <proc/scheduler.h>
#include <proc/task.h>
#include <proc/thread.h>
#include <proc/program.h>
#include <panic.h>
#include <func.h>
#include <cpu.h>
146,7 → 147,8
/*
* Create kernel console.
*/
t = thread_create(kconsole, (void *) "kconsole", TASK, 0, "kconsole", false);
t = thread_create(kconsole, (void *) "kconsole", TASK, 0, "kconsole",
false);
if (t)
thread_ready(t);
else
158,7 → 160,7
* Create user tasks, load RAM disk images.
*/
count_t i;
thread_t *threads[CONFIG_INIT_TASKS];
program_t programs[CONFIG_INIT_TASKS];
for (i = 0; i < init.cnt; i++) {
if (init.tasks[i].addr % FRAME_SIZE) {
166,24 → 168,28
continue;
}
 
threads[i] = thread_create_program(
(void *) init.tasks[i].addr, "uspace");
if (threads[i] != NULL) {
int rc = program_create_from_image((void *) init.tasks[i].addr,
&programs[i]);
 
if (rc == 0 && programs[i].task != NULL) {
/*
* Set capabilities to init userspace tasks.
*/
cap_set(threads[i]->task, CAP_CAP | CAP_MEM_MANAGER |
cap_set(programs[i].task, CAP_CAP | CAP_MEM_MANAGER |
CAP_IO_MANAGER | CAP_PREEMPT_CONTROL | CAP_IRQ_REG);
if (!ipc_phone_0)
ipc_phone_0 = &threads[i]->task->answerbox;
ipc_phone_0 = &programs[i].task->answerbox;
} else if (rc == 0) {
/* It was the program loader and was registered */
} else {
/* RAM disk image */
int rd = init_rd((rd_header_t *) init.tasks[i].addr,
init.tasks[i].size);
if (rd != RE_OK)
printf("Init binary %" PRIc " not used, error code %d.\n", i, rd);
printf("Init binary %" PRIc " not used, error "
"code %d.\n", i, rd);
}
}
191,9 → 197,9
* Run user tasks with reasonable delays
*/
for (i = 0; i < init.cnt; i++) {
if (threads[i] != NULL) {
if (programs[i].task != NULL) {
thread_usleep(50000);
thread_ready(threads[i]);
program_ready(&programs[i]);
}
}
 
/branches/tracing/kernel/generic/src/main/main.c
61,6 → 61,7
#include <main/kinit.h>
#include <main/version.h>
#include <console/kconsole.h>
#include <console/console.h>
#include <cpu.h>
#include <align.h>
#include <interrupt.h>
80,8 → 81,8
#include <adt/btree.h>
#include <smp/smp.h>
#include <ddi/ddi.h>
#include <console/console.h>
 
 
/** Global configuration structure. */
config_t config;
 
235,8 → 236,8
/* Slab must be initialized after we know the number of processors. */
LOG_EXEC(slab_enable_cpucache());
printf("Detected %" PRIc " CPU(s), %" PRIu64" MB free memory\n",
config.cpu_count, SIZE2MB(zone_total_size()));
printf("Detected %" PRIc " CPU(s), %" PRIu64" MiB free memory\n",
config.cpu_count, SIZE2MB(zone_total_size()));
LOG_EXEC(cpu_init());
252,8 → 253,8
count_t i;
for (i = 0; i < init.cnt; i++)
printf("init[%" PRIc "].addr=%#" PRIp ", init[%" PRIc
"].size=%#" PRIs "\n", i, init.tasks[i].addr,
i, init.tasks[i].size);
"].size=%#" PRIs "\n", i, init.tasks[i].addr, i,
init.tasks[i].size);
} else
printf("No init binaries found\n");
/branches/tracing/kernel/generic/src/sysinfo/sysinfo.c
281,10 → 281,15
return ret;
}
 
#define SYSINFO_MAX_LEN 1024
 
unative_t sys_sysinfo_valid(unative_t ptr, unative_t len)
{
char *str;
sysinfo_rettype_t ret = {0, 0};
 
if (len > SYSINFO_MAX_LEN)
return ret.valid;
str = malloc(len + 1, 0);
ASSERT(str);
299,6 → 304,9
{
char *str;
sysinfo_rettype_t ret = {0, 0};
if (len > SYSINFO_MAX_LEN)
return ret.val;
str = malloc(len + 1, 0);
ASSERT(str);
/branches/tracing/kernel/generic/src/console/kconsole.c
169,7 → 169,7
}
 
/** Try to find a command beginning with prefix */
static const char * cmdtab_search_one(const char *name,link_t **startpos)
static const char *cmdtab_search_one(const char *name,link_t **startpos)
{
size_t namelen = strlen(name);
const char *curname;
203,7 → 203,7
*/
static int cmdtab_compl(char *name)
{
static char output[MAX_SYMBOL_NAME+1];
static char output[MAX_SYMBOL_NAME + 1];
link_t *startpos = NULL;
const char *foundtxt;
int found = 0;
213,7 → 213,7
while ((foundtxt = cmdtab_search_one(name, &startpos))) {
startpos = startpos->next;
if (!found)
strncpy(output, foundtxt, strlen(foundtxt)+1);
strncpy(output, foundtxt, strlen(foundtxt) + 1);
else {
for (i = 0; output[i] && foundtxt[i] &&
output[i] == foundtxt[i]; i++)
240,11 → 240,11
}
 
static char * clever_readline(const char *prompt, chardev_t *input)
static char *clever_readline(const char *prompt, chardev_t *input)
{
static int histposition = 0;
 
static char tmp[MAX_CMDLINE+1];
static char tmp[MAX_CMDLINE + 1];
int curlen = 0, position = 0;
char *current = history[histposition];
int i;
257,7 → 257,8
if (c == '\n') {
putchar(c);
break;
} if (c == '\b') { /* Backspace */
}
if (c == '\b') { /* Backspace */
if (position == 0)
continue;
for (i = position; i < curlen; i++)
543,7 → 544,8
buf = (char *) cmd->argv[i].buffer;
strncpy(buf, (const char *) &cmdline[start],
min((end - start) + 2, cmd->argv[i].len));
buf[min((end - start) + 1, cmd->argv[i].len - 1)] = '\0';
buf[min((end - start) + 1, cmd->argv[i].len - 1)] =
'\0';
break;
case ARG_TYPE_INT:
if (parse_int_arg(cmdline + start, end - start + 1,
560,8 → 562,8
'\0';
cmd->argv[i].intval = (unative_t) buf;
cmd->argv[i].vartype = ARG_TYPE_STRING;
} else if (!parse_int_arg(cmdline + start, end - start + 1,
&cmd->argv[i].intval)) {
} else if (!parse_int_arg(cmdline + start,
end - start + 1, &cmd->argv[i].intval)) {
cmd->argv[i].vartype = ARG_TYPE_INT;
} else {
printf("Unrecognized variable argument.\n");
/branches/tracing/kernel/generic/src/proc/scheduler.c
451,8 → 451,8
/*
* Entering state is unexpected.
*/
panic("tid%" PRIu64 ": unexpected state %s\n", THREAD->tid,
thread_states[THREAD->state]);
panic("tid%" PRIu64 ": unexpected state %s\n",
THREAD->tid, thread_states[THREAD->state]);
break;
}
 
504,9 → 504,9
THREAD->state = Running;
 
#ifdef SCHEDULER_VERBOSE
printf("cpu%u: tid %" PRIu64 " (priority=%d, ticks=%" PRIu64 ", nrdy=%ld)\n",
CPU->id, THREAD->tid, THREAD->priority, THREAD->ticks,
atomic_get(&CPU->nrdy));
printf("cpu%u: tid %" PRIu64 " (priority=%d, ticks=%" PRIu64
", nrdy=%ld)\n", CPU->id, THREAD->tid, THREAD->priority,
THREAD->ticks, atomic_get(&CPU->nrdy));
#endif
 
/*
640,9 → 640,9
*/
spinlock_lock(&t->lock);
#ifdef KCPULB_VERBOSE
printf("kcpulb%u: TID %" PRIu64 " -> cpu%u, nrdy=%ld, "
"avg=%ld\n", CPU->id, t->tid, CPU->id,
atomic_get(&CPU->nrdy),
printf("kcpulb%u: TID %" PRIu64 " -> cpu%u, "
"nrdy=%ld, avg=%ld\n", CPU->id, t->tid,
CPU->id, atomic_get(&CPU->nrdy),
atomic_get(&nrdy) / config.cpu_active);
#endif
t->flags |= THREAD_FLAG_STOLEN;
/branches/tracing/kernel/generic/src/proc/task.c
35,10 → 35,8
* @brief Task management.
*/
 
#include <main/uinit.h>
#include <proc/thread.h>
#include <proc/task.h>
#include <proc/uarg.h>
#include <mm/as.h>
#include <mm/slab.h>
#include <atomic.h>
46,23 → 44,16
#include <synch/waitq.h>
#include <arch.h>
#include <arch/barrier.h>
#include <panic.h>
#include <adt/avl.h>
#include <adt/btree.h>
#include <adt/list.h>
#include <ipc/ipc.h>
#include <security/cap.h>
#include <memstr.h>
#include <ipc/ipcrsc.h>
#include <print.h>
#include <lib/elf.h>
#include <errno.h>
#include <func.h>
#include <syscall/copy.h>
 
#ifndef LOADED_PROG_STACK_PAGES_NO
#define LOADED_PROG_STACK_PAGES_NO 1
#endif
 
/** Spinlock protecting the tasks_tree AVL tree. */
SPINLOCK_INITIALIZE(tasks_lock);
 
80,11 → 71,7
 
static task_id_t task_counter = 0;
 
/** Initialize tasks
*
* Initialize kernel tasks support.
*
*/
/** Initialize kernel tasks support. */
void task_init(void)
{
TASK = NULL;
92,7 → 79,8
}
 
/*
* The idea behind this walker is to remember a single task different from TASK.
* The idea behind this walker is to remember a single task different from
* TASK.
*/
static bool task_done_walker(avltree_node_t *node, void *arg)
{
107,9 → 95,7
return true; /* continue the walk */
}
 
/** Kill all tasks except the current task.
*
*/
/** Kill all tasks except the current task. */
void task_done(void)
{
task_t *t;
141,15 → 127,13
} while (t != NULL);
}
 
/** Create new task
/** Create new task with no threads.
*
* Create new task with no threads.
* @param as Task's address space.
* @param name Symbolic name.
*
* @param as Task's address space.
* @param name Symbolic name.
* @return New task's structure.
*
* @return New task's structure
*
*/
task_t *task_create(as_t *as, char *name)
{
189,7 → 173,7
ipc_phone_connect(&ta->phones[0], ipc_phone_0);
atomic_set(&ta->active_calls, 0);
 
mutex_initialize(&ta->futexes_lock);
mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE);
btree_create(&ta->futexes);
ipl = interrupts_disable();
212,7 → 196,7
 
/** Destroy task.
*
* @param t Task to be destroyed.
* @param t Task to be destroyed.
*/
void task_destroy(task_t *t)
{
245,116 → 229,32
 
/** Syscall for reading task ID from userspace.
*
* @param uspace_task_id Userspace address of 8-byte buffer where to store
* current task ID.
* @param uspace_task_id userspace address of 8-byte buffer
* where to store current task ID.
*
* @return 0 on success or an error code from @ref errno.h.
* @return Zero on success or an error code from @ref errno.h.
*/
unative_t sys_task_get_id(task_id_t *uspace_task_id)
{
/*
* No need to acquire lock on TASK because taskid
* remains constant for the lifespan of the task.
* No need to acquire lock on TASK because taskid remains constant for
* the lifespan of the task.
*/
return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid,
sizeof(TASK->taskid));
}
 
unative_t sys_task_spawn(void *image, size_t size)
{
void *kimage = malloc(size, 0);
if (kimage == NULL)
return ENOMEM;
int rc = copy_from_uspace(kimage, image, size);
if (rc != EOK)
return rc;
 
/*
* Not very efficient and it would be better to call it on code only,
* but this whole function is a temporary hack anyway and one day it
* will go in favor of the userspace dynamic loader.
*/
smc_coherence_block(kimage, size);
uspace_arg_t *kernel_uarg;
kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
if (kernel_uarg == NULL) {
free(kimage);
return ENOMEM;
}
kernel_uarg->uspace_entry =
(void *) ((elf_header_t *) kimage)->e_entry;
kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS;
kernel_uarg->uspace_thread_function = NULL;
kernel_uarg->uspace_thread_arg = NULL;
kernel_uarg->uspace_uarg = NULL;
as_t *as = as_create(0);
if (as == NULL) {
free(kernel_uarg);
free(kimage);
return ENOMEM;
}
unsigned int erc = elf_load((elf_header_t *) kimage, as);
if (erc != EE_OK) {
as_destroy(as);
free(kernel_uarg);
free(kimage);
return ENOENT;
}
as_area_t *area = as_area_create(as,
AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS,
AS_AREA_ATTR_NONE, &anon_backend, NULL);
if (area == NULL) {
as_destroy(as);
free(kernel_uarg);
free(kimage);
return ENOMEM;
}
task_t *task = task_create(as, "app");
if (task == NULL) {
as_destroy(as);
free(kernel_uarg);
free(kimage);
return ENOENT;
}
// FIXME: control the capabilities
cap_set(task, cap_get(TASK));
thread_t *thread = thread_create(uinit, kernel_uarg, task,
THREAD_FLAG_USPACE, "user", false);
if (thread == NULL) {
task_destroy(task);
as_destroy(as);
free(kernel_uarg);
free(kimage);
return ENOENT;
}
thread_ready(thread);
return EOK;
}
 
/** Find task structure corresponding to task ID.
*
* The tasks_lock must be already held by the caller of this function
* and interrupts must be disabled.
* The tasks_lock must be already held by the caller of this function and
* interrupts must be disabled.
*
* @param id Task ID.
* @param id Task ID.
*
* @return Task structure address or NULL if there is no such task ID.
* @return Task structure address or NULL if there is no such task
* ID.
*/
task_t *task_find_by_id(task_id_t id)
{
avltree_node_t *node;
task_t *task_find_by_id(task_id_t id) { avltree_node_t *node;
node = avltree_search(&tasks_tree, (avltree_key_t) id);
 
365,11 → 265,13
 
/** Get accounting data of given task.
*
* Note that task lock of 't' must be already held and
* interrupts must be already disabled.
* Note that task lock of 't' must be already held and interrupts must be
* already disabled.
*
* @param t Pointer to thread.
* @param t Pointer to thread.
*
* @return Number of cycles used by the task and all its threads
* so far.
*/
uint64_t task_get_accounting(task_t *t)
{
401,9 → 303,9
* This function is idempotent.
* It signals all the task's threads to bail it out.
*
* @param id ID of the task to be killed.
* @param id ID of the task to be killed.
*
* @return 0 on success or an error code from errno.h
* @return Zero on success or an error code from errno.h.
*/
int task_kill(task_id_t id)
{
424,7 → 326,7
spinlock_unlock(&tasks_lock);
/*
* Interrupt all threads except ktaskclnp.
* Interrupt all threads.
*/
spinlock_lock(&ta->lock);
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
/branches/tracing/kernel/generic/src/proc/thread.c
683,74 → 683,6
return node != NULL;
}
 
 
/** Create new user task with 1 thread from image
*
* @param program_addr Address of program executable image.
* @param name Program name.
*
* @return Initialized main thread of the task or NULL on error.
*/
thread_t *thread_create_program(void *program_addr, char *name)
{
as_t *as;
as_area_t *area;
unsigned int rc;
task_t *task;
uspace_arg_t *kernel_uarg;
kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
if (kernel_uarg == NULL)
return NULL;
kernel_uarg->uspace_entry =
(void *) ((elf_header_t *) program_addr)->e_entry;
kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS;
kernel_uarg->uspace_thread_function = NULL;
kernel_uarg->uspace_thread_arg = NULL;
kernel_uarg->uspace_uarg = NULL;
 
as = as_create(0);
if (as == NULL) {
free(kernel_uarg);
return NULL;
}
 
rc = elf_load((elf_header_t *) program_addr, as);
if (rc != EE_OK) {
free(kernel_uarg);
as_destroy(as);
return NULL;
}
/*
* Create the data as_area.
*/
area = as_area_create(as,
AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS,
AS_AREA_ATTR_NONE, &anon_backend, NULL);
if (area == NULL) {
free(kernel_uarg);
as_destroy(as);
return NULL;
}
task = task_create(as, name);
if (task == NULL) {
free(kernel_uarg);
as_destroy(as);
return NULL;
}
/*
* Create the main thread.
*/
return thread_create(uinit, kernel_uarg, task, THREAD_FLAG_USPACE,
"uinit", false);
}
 
 
/** Update accounting of current thread.
*
* Note that thread_lock on THREAD must be already held and
/branches/tracing/kernel/generic/src/proc/program.c
0,0 → 1,239
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup genericproc
* @{
*/
 
/**
* @file
* @brief Running userspace programs.
*/
 
#include <main/uinit.h>
#include <proc/thread.h>
#include <proc/task.h>
#include <proc/uarg.h>
#include <mm/as.h>
#include <mm/slab.h>
#include <arch.h>
#include <adt/list.h>
#include <ipc/ipc.h>
#include <ipc/ipcrsc.h>
#include <security/cap.h>
#include <lib/elf.h>
#include <errno.h>
#include <print.h>
#include <syscall/copy.h>
#include <proc/program.h>
 
#ifndef LOADED_PROG_STACK_PAGES_NO
#define LOADED_PROG_STACK_PAGES_NO 1
#endif
 
/**
* Points to the binary image used as the program loader. All non-initial
* tasks are created from this executable image.
*/
void *program_loader = NULL;
 
/** Create a program using an existing address space.
*
* @param as Address space containing a binary program image.
* @param entry_addr Program entry-point address in program address space.
* @param p Buffer for storing program information.
*/
void program_create(as_t *as, uintptr_t entry_addr, program_t *p)
{
as_area_t *a;
uspace_arg_t *kernel_uarg;
 
kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
kernel_uarg->uspace_entry = (void *) entry_addr;
kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS;
kernel_uarg->uspace_thread_function = NULL;
kernel_uarg->uspace_thread_arg = NULL;
kernel_uarg->uspace_uarg = NULL;
p->task = task_create(as, "app");
ASSERT(p->task);
 
/*
* Create the data as_area.
*/
a = as_area_create(as, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS,
AS_AREA_ATTR_NONE, &anon_backend, NULL);
 
/*
* Create the main thread.
*/
p->main_thread = thread_create(uinit, kernel_uarg, p->task,
THREAD_FLAG_USPACE, "uinit", false);
ASSERT(p->main_thread);
}
 
/** Parse an executable image in the kernel memory.
*
* If the image belongs to a program loader, it is registered as such,
* (and *task is set to NULL). Otherwise a task is created from the
* executable image. The task is returned in *task.
*
* @param image_addr Address of an executable program image.
* @param p Buffer for storing program info. If image_addr
* points to a loader image, p->task will be set to
* NULL and EOK will be returned.
*
* @return EOK on success or negative error code.
*/
int program_create_from_image(void *image_addr, program_t *p)
{
as_t *as;
unsigned int rc;
 
as = as_create(0);
ASSERT(as);
 
rc = elf_load((elf_header_t *) image_addr, as, 0);
if (rc != EE_OK) {
as_destroy(as);
p->task = NULL;
p->main_thread = NULL;
if (rc != EE_LOADER)
return ENOTSUP;
/* Register image as the program loader */
ASSERT(program_loader == NULL);
program_loader = image_addr;
printf("Registered program loader at 0x%" PRIp "\n",
image_addr);
return EOK;
}
 
program_create(as, ((elf_header_t *) image_addr)->e_entry, p);
 
return EOK;
}
 
/** Create a task from the program loader image.
*
* @param p Buffer for storing program info.
* @return EOK on success or negative error code.
*/
int program_create_loader(program_t *p)
{
as_t *as;
unsigned int rc;
void *loader;
 
as = as_create(0);
ASSERT(as);
 
loader = program_loader;
if (!loader) {
printf("Cannot spawn loader as none was registered\n");
return ENOENT;
}
 
rc = elf_load((elf_header_t *) program_loader, as, ELD_F_LOADER);
if (rc != EE_OK) {
as_destroy(as);
return ENOENT;
}
 
program_create(as, ((elf_header_t *) program_loader)->e_entry, p);
 
return EOK;
}
 
/** Make program ready.
*
* Switch program's main thread to the ready state.
*
* @param p Program to make ready.
*/
void program_ready(program_t *p)
{
thread_ready(p->main_thread);
}
 
/** Syscall for creating a new loader instance from userspace.
*
* Creates a new task from the program loader image, connects a phone
* to it and stores the phone id into the provided buffer.
*
* @param uspace_phone_id Userspace address where to store the phone id.
*
* @return 0 on success or an error code from @ref errno.h.
*/
unative_t sys_program_spawn_loader(int *uspace_phone_id)
{
program_t p;
int fake_id;
int rc;
int phone_id;
 
fake_id = 0;
 
/* Before we even try creating the task, see if we can write the id */
rc = (unative_t) copy_to_uspace(uspace_phone_id, &fake_id,
sizeof(fake_id));
if (rc != 0)
return rc;
 
phone_id = phone_alloc();
if (phone_id < 0)
return ELIMIT;
 
rc = program_create_loader(&p);
if (rc != 0)
return rc;
 
phone_connect(phone_id, &p.task->answerbox);
 
/* No need to aquire lock before task_ready() */
rc = (unative_t) copy_to_uspace(uspace_phone_id, &phone_id,
sizeof(phone_id));
if (rc != 0) {
/* Ooops */
ipc_phone_hangup(&TASK->phones[phone_id]);
task_kill(p.task->taskid);
return rc;
}
 
// FIXME: control the capabilities
cap_set(p.task, cap_get(TASK));
 
program_ready(&p);
 
return EOK;
}
 
/** @}
*/
/branches/tracing/kernel/generic/src/lib/objc_ext.c
File deleted
/branches/tracing/kernel/generic/src/lib/objc.c
File deleted
/branches/tracing/kernel/generic/src/lib/rd.c
48,14 → 48,14
 
/**
* RAM disk initialization routine. At this point, the RAM disk memory is shared
* and information about the share is provided as sysinfo values to the userspace
* tasks.
* and information about the share is provided as sysinfo values to the
* userspace tasks.
*/
int init_rd(rd_header_t *header, size_t size)
{
/* Identify RAM disk */
if ((header->magic[0] != RD_MAG0) || (header->magic[1] != RD_MAG1) ||
(header->magic[2] != RD_MAG2) || (header->magic[3] != RD_MAG3))
(header->magic[2] != RD_MAG2) || (header->magic[3] != RD_MAG3))
return RE_INVALID;
/* Identify version */
86,7 → 86,8
if ((uint64_t) hsize + dsize > size)
dsize = size - hsize;
rd_parea.pbase = ALIGN_DOWN((uintptr_t) KA2PA((void *) header + hsize), FRAME_SIZE);
rd_parea.pbase = ALIGN_DOWN((uintptr_t) KA2PA((void *) header + hsize),
FRAME_SIZE);
rd_parea.vbase = (uintptr_t) ((void *) header + hsize);
rd_parea.frames = SIZE2FRAMES(dsize);
rd_parea.cacheable = true;
95,8 → 96,8
sysinfo_set_item_val("rd", NULL, true);
sysinfo_set_item_val("rd.header_size", NULL, hsize);
sysinfo_set_item_val("rd.size", NULL, dsize);
sysinfo_set_item_val("rd.address.physical", NULL, (unative_t)
KA2PA((void *) header + hsize));
sysinfo_set_item_val("rd.address.physical", NULL,
(unative_t) KA2PA((void *) header + hsize));
 
return RE_OK;
}
/branches/tracing/kernel/generic/src/lib/elf.c
57,7 → 57,7
};
 
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf,
as_t *as);
as_t *as, int flags);
static int section_header(elf_section_header_t *entry, elf_header_t *elf,
as_t *as);
static int load_segment(elf_segment_header_t *entry, elf_header_t *elf,
67,9 → 67,10
*
* @param header Pointer to ELF header in memory
* @param as Created and properly mapped address space
* @param flags A combination of ELD_F_*
* @return EE_OK on success
*/
unsigned int elf_load(elf_header_t *header, as_t * as)
unsigned int elf_load(elf_header_t *header, as_t * as, int flags)
{
int i, rc;
 
110,7 → 111,7
 
seghdr = &((elf_segment_header_t *)(((uint8_t *) header) +
header->e_phoff))[i];
rc = segment_header(seghdr, header, as);
rc = segment_header(seghdr, header, as, flags);
if (rc != EE_OK)
return rc;
}
151,8 → 152,10
* @return EE_OK on success, error code otherwise.
*/
static int segment_header(elf_segment_header_t *entry, elf_header_t *elf,
as_t *as)
as_t *as, int flags)
{
char *interp;
 
switch (entry->p_type) {
case PT_NULL:
case PT_PHDR:
162,6 → 165,16
break;
case PT_DYNAMIC:
case PT_INTERP:
interp = (char *)elf + entry->p_offset;
/* FIXME */
/*if (memcmp((uintptr_t)interp, (uintptr_t)ELF_INTERP_ZSTR,
ELF_INTERP_ZLEN) != 0) {
return EE_UNSUPPORTED;
}*/
if ((flags & ELD_F_LOADER) == 0) {
return EE_LOADER;
}
break;
case PT_SHLIB:
case PT_NOTE:
case PT_LOPROC:
/branches/tracing/kernel/generic/src/lib/memstr.c
34,12 → 34,10
* @file
* @brief Memory string operations.
*
* This file provides architecture independent functions
* to manipulate blocks of memory. These functions
* are optimized as much as generic functions of
* this type can be. However, architectures are
* free to provide even more optimized versions of these
* functions.
* This file provides architecture independent functions to manipulate blocks of
* memory. These functions are optimized as much as generic functions of this
* type can be. However, architectures are free to provide even more optimized
* versions of these functions.
*/
 
#include <memstr.h>
46,45 → 44,46
#include <arch/types.h>
#include <align.h>
 
/** Copy block of memory
/** Copy block of memory.
*
* Copy cnt bytes from src address to dst address.
* The copying is done word-by-word and then byte-by-byte.
* The source and destination memory areas cannot overlap.
* Copy cnt bytes from src address to dst address. The copying is done
* word-by-word and then byte-by-byte. The source and destination memory areas
* cannot overlap.
*
* @param src Origin address to copy from.
* @param dst Origin address to copy to.
* @param cnt Number of bytes to copy.
* @param src Source address to copy from.
* @param dst Destination address to copy to.
* @param cnt Number of bytes to copy.
*
* @return Destination address.
*/
void *_memcpy(void * dst, const void *src, size_t cnt)
void *_memcpy(void *dst, const void *src, size_t cnt)
{
unsigned int i, j;
if (ALIGN_UP((uintptr_t) src, sizeof(unative_t)) != (uintptr_t) src ||
ALIGN_UP((uintptr_t) dst, sizeof(unative_t)) != (uintptr_t) dst) {
ALIGN_UP((uintptr_t) dst, sizeof(unative_t)) != (uintptr_t) dst) {
for (i = 0; i < cnt; i++)
((uint8_t *) dst)[i] = ((uint8_t *) src)[i];
} else {
for (i = 0; i < cnt / sizeof(unative_t); i++)
((unative_t *) dst)[i] = ((unative_t *) src)[i];
for (j = 0; j < cnt % sizeof(unative_t); j++)
((uint8_t *)(((unative_t *) dst) + i))[j] = ((uint8_t *)(((unative_t *) src) + i))[j];
((uint8_t *)(((unative_t *) dst) + i))[j] =
((uint8_t *)(((unative_t *) src) + i))[j];
}
return (char *) src;
return (char *) dst;
}
 
/** Fill block of memory
*
* Fill cnt bytes at dst address with the value x.
* The filling is done byte-by-byte.
* Fill cnt bytes at dst address with the value x. The filling is done
* byte-by-byte.
*
* @param dst Origin address to fill.
* @param cnt Number of bytes to fill.
* @param x Value to fill.
* @param dst Destination address to fill.
* @param cnt Number of bytes to fill.
* @param x Value to fill.
*
*/
void _memsetb(void *dst, size_t cnt, uint8_t x)
96,14 → 95,14
p[i] = x;
}
 
/** Fill block of memory
/** Fill block of memory.
*
* Fill cnt words at dst address with the value x.
* The filling is done word-by-word.
* Fill cnt words at dst address with the value x. The filling is done
* word-by-word.
*
* @param dst Origin address to fill.
* @param cnt Number of words to fill.
* @param x Value to fill.
* @param dst Destination address to fill.
* @param cnt Number of words to fill.
* @param x Value to fill.
*
*/
void _memsetw(void *dst, size_t cnt, uint16_t x)
115,16 → 114,16
p[i] = x;
}
 
/** Copy string
/** Copy string.
*
* Copy string from src address to dst address.
* The copying is done char-by-char until the null
* character. The source and destination memory areas
* cannot overlap.
* Copy string from src address to dst address. The copying is done
* char-by-char until the null character. The source and destination memory
* areas cannot overlap.
*
* @param src Origin string to copy from.
* @param dst Origin string to copy to.
* @param src Source string to copy from.
* @param dst Destination string to copy to.
*
* @return Address of the destination string.
*/
char *strcpy(char *dest, const char *src)
{
/branches/tracing/kernel/generic/src/mm/slab.c
794,30 → 794,77
/* Print list of slabs */
void slab_print_list(void)
{
slab_cache_t *cache;
link_t *cur;
ipl_t ipl;
ipl = interrupts_disable();
spinlock_lock(&slab_cache_lock);
int skip = 0;
 
printf("slab name size pages obj/pg slabs cached allocated"
" ctl\n");
printf("---------------- -------- ------ ------ ------ ------ ---------"
" ---\n");
for (cur = slab_cache_list.next; cur != &slab_cache_list;
cur = cur->next) {
 
while (true) {
slab_cache_t *cache;
link_t *cur;
ipl_t ipl;
int i;
 
/*
* We must not hold the slab_cache_lock spinlock when printing
* the statistics. Otherwise we can easily deadlock if the print
* needs to allocate memory.
*
* Therefore, we walk through the slab cache list, skipping some
* amount of already processed caches during each iteration and
* gathering statistics about the first unprocessed cache. For
* the sake of printing the statistics, we realese the
* slab_cache_lock and reacquire it afterwards. Then the walk
* starts again.
*
* This limits both the efficiency and also accuracy of the
* obtained statistics. The efficiency is decreased because the
* time complexity of the algorithm is quadratic instead of
* linear. The accuracy is impacted because we drop the lock
* after processing one cache. If there is someone else
* manipulating the cache list, we might omit an arbitrary
* number of caches or process one cache multiple times.
* However, we don't bleed for this algorithm for it is only
* statistics.
*/
 
ipl = interrupts_disable();
spinlock_lock(&slab_cache_lock);
 
for (i = 0, cur = slab_cache_list.next;
i < skip && cur != &slab_cache_list;
i++, cur = cur->next)
;
 
if (cur == &slab_cache_list) {
spinlock_unlock(&slab_cache_lock);
interrupts_restore(ipl);
break;
}
 
skip++;
 
cache = list_get_instance(cur, slab_cache_t, link);
 
char *name = cache->name;
uint8_t order = cache->order;
size_t size = cache->size;
unsigned int objects = cache->objects;
long allocated_slabs = atomic_get(&cache->allocated_slabs);
long cached_objs = atomic_get(&cache->cached_objs);
long allocated_objs = atomic_get(&cache->allocated_objs);
int flags = cache->flags;
spinlock_unlock(&slab_cache_lock);
interrupts_restore(ipl);
printf("%-16s %8" PRIs " %6d %6u %6ld %6ld %9ld %-3s\n",
cache->name, cache->size, (1 << cache->order),
cache->objects, atomic_get(&cache->allocated_slabs),
atomic_get(&cache->cached_objs),
atomic_get(&cache->allocated_objs),
cache->flags & SLAB_CACHE_SLINSIDE ? "in" : "out");
name, size, (1 << order), objects, allocated_slabs,
cached_objs, allocated_objs,
flags & SLAB_CACHE_SLINSIDE ? "in" : "out");
}
spinlock_unlock(&slab_cache_lock);
interrupts_restore(ipl);
}
 
void slab_cache_init(void)
/branches/tracing/kernel/generic/src/mm/backend_anon.c
78,7 → 78,6
int anon_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access)
{
uintptr_t frame;
bool dirty = false;
 
if (!as_area_check_access(area, access))
return AS_PF_FAULT;
106,7 → 105,7
*/
for (i = 0; i < leaf->keys; i++) {
if (leaf->key[i] ==
ALIGN_DOWN(addr, PAGE_SIZE)) {
ALIGN_DOWN(addr, PAGE_SIZE) - area->base) {
allocate = false;
break;
}
114,7 → 113,6
if (allocate) {
frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
dirty = true;
/*
* Insert the address of the newly allocated
145,7 → 143,6
*/
frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
dirty = true;
}
/*
/branches/tracing/kernel/generic/src/mm/as.c
82,7 → 82,6
#include <arch/mm/cache.h>
#endif /* CONFIG_VIRT_IDX_DCACHE */
 
#ifndef __OBJC__
/**
* Each architecture decides what functions will be used to carry out
* address space operations such as creating or locking page tables.
93,7 → 92,6
* Slab for as_t objects.
*/
static slab_cache_t *as_slab;
#endif
 
/**
* This lock serializes access to the ASID subsystem.
113,13 → 111,11
/** Kernel address space. */
as_t *AS_KERNEL = NULL;
 
static int area_flags_to_page_flags(int aflags);
static as_area_t *find_area_and_lock(as_t *as, uintptr_t va);
static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
as_area_t *avoid_area);
static void sh_info_remove_reference(share_info_t *sh_info);
static int area_flags_to_page_flags(int);
static as_area_t *find_area_and_lock(as_t *, uintptr_t);
static bool check_area_conflicts(as_t *, uintptr_t, size_t, as_area_t *);
static void sh_info_remove_reference(share_info_t *);
 
#ifndef __OBJC__
static int as_constructor(void *obj, int flags)
{
as_t *as = (as_t *) obj;
126,7 → 122,7
int rc;
 
link_initialize(&as->inactive_as_with_asid_link);
mutex_initialize(&as->lock);
mutex_initialize(&as->lock, MUTEX_PASSIVE);
rc = as_constructor_arch(as, flags);
139,7 → 135,6
 
return as_destructor_arch(as);
}
#endif
 
/** Initialize address space subsystem. */
void as_init(void)
146,10 → 141,8
{
as_arch_init();
 
#ifndef __OBJC__
as_slab = slab_cache_create("as_slab", sizeof(as_t), 0,
as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED);
#endif
AS_KERNEL = as_create(FLAG_AS_KERNEL);
if (!AS_KERNEL)
159,20 → 152,14
 
/** Create address space.
*
* @param flags Flags that influence way in wich the address space is created.
* @param flags Flags that influence the way in wich the address space
* is created.
*/
as_t *as_create(int flags)
{
as_t *as;
 
#ifdef __OBJC__
as = [as_t new];
link_initialize(&as->inactive_as_with_asid_link);
mutex_initialize(&as->lock);
(void) as_constructor_arch(as, flags);
#else
as = (as_t *) slab_alloc(as_slab, 0);
#endif
(void) as_create_arch(as, 0);
btree_create(&as->as_area_btree);
199,6 → 186,8
* zero), the address space can be destroyed.
*
* We know that we don't hold any spinlock.
*
* @param as Address space to be destroyed.
*/
void as_destroy(as_t *as)
{
263,11 → 252,7
 
interrupts_restore(ipl);
 
#ifdef __OBJC__
[as free];
#else
slab_free(as_slab, as);
#endif
}
 
/** Create address space area of common attributes.
274,19 → 259,19
*
* The created address space area is added to the target address space.
*
* @param as Target address space.
* @param flags Flags of the area memory.
* @param size Size of area.
* @param base Base address of area.
* @param attrs Attributes of the area.
* @param backend Address space area backend. NULL if no backend is used.
* @param backend_data NULL or a pointer to an array holding two void *.
* @param as Target address space.
* @param flags Flags of the area memory.
* @param size Size of area.
* @param base Base address of area.
* @param attrs Attributes of the area.
* @param backend Address space area backend. NULL if no backend is used.
* @param backend_data NULL or a pointer to an array holding two void *.
*
* @return Address space area on success or NULL on failure.
* @return Address space area on success or NULL on failure.
*/
as_area_t *
as_area_create(as_t *as, int flags, size_t size, uintptr_t base, int attrs,
mem_backend_t *backend, mem_backend_data_t *backend_data)
mem_backend_t *backend, mem_backend_data_t *backend_data)
{
ipl_t ipl;
as_area_t *a;
312,7 → 297,7
a = (as_area_t *) malloc(sizeof(as_area_t), 0);
 
mutex_initialize(&a->lock);
mutex_initialize(&a->lock, MUTEX_PASSIVE);
a->as = as;
a->flags = flags;
338,13 → 323,14
 
/** Find address space area and change it.
*
* @param as Address space.
* @param address Virtual address belonging to the area to be changed. Must be
* page-aligned.
* @param size New size of the virtual memory block starting at address.
* @param flags Flags influencing the remap operation. Currently unused.
* @param as Address space.
* @param address Virtual address belonging to the area to be changed.
* Must be page-aligned.
* @param size New size of the virtual memory block starting at
* address.
* @param flags Flags influencing the remap operation. Currently unused.
*
* @return Zero on success or a value from @ref errno.h otherwise.
* @return Zero on success or a value from @ref errno.h otherwise.
*/
int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags)
{
399,7 → 385,7
if (pages < area->pages) {
bool cond;
uintptr_t start_free = area->base + pages*PAGE_SIZE;
uintptr_t start_free = area->base + pages * PAGE_SIZE;
 
/*
* Shrinking the area.
409,7 → 395,7
/*
* Start TLB shootdown sequence.
*/
tlb_shootdown_start(TLB_INVL_PAGES, AS->asid, area->base +
tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base +
pages * PAGE_SIZE, area->pages - pages);
 
/*
452,8 → 438,10
cond = false; /* we are almost done */
i = (start_free - b) >> PAGE_WIDTH;
if (!used_space_remove(area, start_free, c - i))
panic("Could not remove used space.\n");
if (!used_space_remove(area, start_free,
c - i))
panic("Could not remove used "
"space.\n");
} else {
/*
* The interval of used space can be
460,7 → 448,8
* completely removed.
*/
if (!used_space_remove(area, b, c))
panic("Could not remove used space.\n");
panic("Could not remove used "
"space.\n");
}
for (; i < c; i++) {
522,10 → 511,10
 
/** Destroy address space area.
*
* @param as Address space.
* @param address Address withing the area to be deleted.
* @param as Address space.
* @param address Address within the area to be deleted.
*
* @return Zero on success or a value from @ref errno.h on failure.
* @return Zero on success or a value from @ref errno.h on failure.
*/
int as_area_destroy(as_t *as, uintptr_t address)
{
622,18 → 611,19
* sh_info of the source area. The process of duplicating the
* mapping is done through the backend share function.
*
* @param src_as Pointer to source address space.
* @param src_base Base address of the source address space area.
* @param acc_size Expected size of the source area.
* @param dst_as Pointer to destination address space.
* @param dst_base Target base address.
* @param src_as Pointer to source address space.
* @param src_base Base address of the source address space area.
* @param acc_size Expected size of the source area.
* @param dst_as Pointer to destination address space.
* @param dst_base Target base address.
* @param dst_flags_mask Destination address space area flags mask.
*
* @return Zero on success or ENOENT if there is no such task or if there is no
* such address space area, EPERM if there was a problem in accepting the area
* or ENOMEM if there was a problem in allocating destination address space
* area. ENOTSUP is returned if the address space area backend does not support
* sharing.
* @return Zero on success or ENOENT if there is no such task or if
* there is no such address space area, EPERM if there was
* a problem in accepting the area or ENOMEM if there was a
* problem in allocating destination address space area.
* ENOTSUP is returned if the address space area backend
* does not support sharing.
*/
int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
as_t *dst_as, uintptr_t dst_base, int dst_flags_mask)
694,7 → 684,7
sh_info = src_area->sh_info;
if (!sh_info) {
sh_info = (share_info_t *) malloc(sizeof(share_info_t), 0);
mutex_initialize(&sh_info->lock);
mutex_initialize(&sh_info->lock, MUTEX_PASSIVE);
sh_info->refcount = 2;
btree_create(&sh_info->pagemap);
src_area->sh_info = sh_info;
752,10 → 742,11
*
* The address space area must be locked prior to this call.
*
* @param area Address space area.
* @param access Access mode.
* @param area Address space area.
* @param access Access mode.
*
* @return False if access violates area's permissions, true otherwise.
* @return False if access violates area's permissions, true
* otherwise.
*/
bool as_area_check_access(as_area_t *area, pf_access_t access)
{
771,21 → 762,181
return true;
}
 
/** Change adress space area flags.
*
* The idea is to have the same data, but with a different access mode.
* This is needed e.g. for writing code into memory and then executing it.
* In order for this to work properly, this may copy the data
* into private anonymous memory (unless it's already there).
*
* @param as Address space.
* @param flags Flags of the area memory.
* @param address Address withing the area to be changed.
*
* @return Zero on success or a value from @ref errno.h on failure.
*/
int as_area_change_flags(as_t *as, int flags, uintptr_t address)
{
as_area_t *area;
uintptr_t base;
link_t *cur;
ipl_t ipl;
int page_flags;
uintptr_t *old_frame;
index_t frame_idx;
count_t used_pages;
 
/* Flags for the new memory mapping */
page_flags = area_flags_to_page_flags(flags);
 
ipl = interrupts_disable();
mutex_lock(&as->lock);
 
area = find_area_and_lock(as, address);
if (!area) {
mutex_unlock(&as->lock);
interrupts_restore(ipl);
return ENOENT;
}
 
if (area->sh_info || area->backend != &anon_backend) {
/* Copying shared areas not supported yet */
/* Copying non-anonymous memory not supported yet */
mutex_unlock(&area->lock);
mutex_unlock(&as->lock);
interrupts_restore(ipl);
return ENOTSUP;
}
 
base = area->base;
 
/*
* Compute total number of used pages in the used_space B+tree
*/
used_pages = 0;
 
for (cur = area->used_space.leaf_head.next;
cur != &area->used_space.leaf_head; cur = cur->next) {
btree_node_t *node;
unsigned int i;
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
used_pages += (count_t) node->value[i];
}
}
 
/* An array for storing frame numbers */
old_frame = malloc(used_pages * sizeof(uintptr_t), 0);
 
/*
* Start TLB shootdown sequence.
*/
tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
 
/*
* Remove used pages from page tables and remember their frame
* numbers.
*/
frame_idx = 0;
 
for (cur = area->used_space.leaf_head.next;
cur != &area->used_space.leaf_head; cur = cur->next) {
btree_node_t *node;
unsigned int i;
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t b = node->key[i];
count_t j;
pte_t *pte;
for (j = 0; j < (count_t) node->value[i]; j++) {
page_table_lock(as, false);
pte = page_mapping_find(as, b + j * PAGE_SIZE);
ASSERT(pte && PTE_VALID(pte) &&
PTE_PRESENT(pte));
old_frame[frame_idx++] = PTE_GET_FRAME(pte);
 
/* Remove old mapping */
page_mapping_remove(as, b + j * PAGE_SIZE);
page_table_unlock(as, false);
}
}
}
 
/*
* Finish TLB shootdown sequence.
*/
 
tlb_invalidate_pages(as->asid, area->base, area->pages);
/*
* Invalidate potential software translation caches (e.g. TSB on
* sparc64).
*/
as_invalidate_translation_cache(as, area->base, area->pages);
tlb_shootdown_finalize();
 
/*
* Set the new flags.
*/
area->flags = flags;
 
/*
* Map pages back in with new flags. This step is kept separate
* so that the memory area could not be accesed with both the old and
* the new flags at once.
*/
frame_idx = 0;
 
for (cur = area->used_space.leaf_head.next;
cur != &area->used_space.leaf_head; cur = cur->next) {
btree_node_t *node;
unsigned int i;
node = list_get_instance(cur, btree_node_t, leaf_link);
for (i = 0; i < node->keys; i++) {
uintptr_t b = node->key[i];
count_t j;
for (j = 0; j < (count_t) node->value[i]; j++) {
page_table_lock(as, false);
 
/* Insert the new mapping */
page_mapping_insert(as, b + j * PAGE_SIZE,
old_frame[frame_idx++], page_flags);
 
page_table_unlock(as, false);
}
}
}
 
free(old_frame);
 
mutex_unlock(&area->lock);
mutex_unlock(&as->lock);
interrupts_restore(ipl);
 
return 0;
}
 
 
/** Handle page fault within the current address space.
*
* This is the high-level page fault handler. It decides
* whether the page fault can be resolved by any backend
* and if so, it invokes the backend to resolve the page
* fault.
* This is the high-level page fault handler. It decides whether the page fault
* can be resolved by any backend and if so, it invokes the backend to resolve
* the page fault.
*
* Interrupts are assumed disabled.
*
* @param page Faulting page.
* @param access Access mode that caused the fault (i.e. read/write/exec).
* @param istate Pointer to interrupted state.
* @param page Faulting page.
* @param access Access mode that caused the page fault (i.e.
* read/write/exec).
* @param istate Pointer to the interrupted state.
*
* @return AS_PF_FAULT on page fault, AS_PF_OK on success or AS_PF_DEFER if the
* fault was caused by copy_to_uspace() or copy_from_uspace().
* @return AS_PF_FAULT on page fault, AS_PF_OK on success or
* AS_PF_DEFER if the fault was caused by copy_to_uspace()
* or copy_from_uspace().
*/
int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate)
{
831,9 → 982,8
page_table_lock(AS, false);
/*
* To avoid race condition between two page faults
* on the same address, we need to make sure
* the mapping has not been already inserted.
* To avoid race condition between two page faults on the same address,
* we need to make sure the mapping has not been already inserted.
*/
if ((pte = page_mapping_find(AS, page))) {
if (PTE_PRESENT(pte)) {
887,8 → 1037,8
*
* When this function is enetered, no spinlocks may be held.
*
* @param old Old address space or NULL.
* @param new New address space.
* @param old Old address space or NULL.
* @param new New address space.
*/
void as_switch(as_t *old_as, as_t *new_as)
{
1159,9 → 1309,9
 
/** Convert address space area flags to page flags.
*
* @param aflags Flags of some address space area.
* @param aflags Flags of some address space area.
*
* @return Flags to be passed to page_mapping_insert().
* @return Flags to be passed to page_mapping_insert().
*/
int area_flags_to_page_flags(int aflags)
{
1189,9 → 1339,9
* The address space area must be locked.
* Interrupts must be disabled.
*
* @param a Address space area.
* @param a Address space area.
*
* @return Flags to be used in page_mapping_insert().
* @return Flags to be used in page_mapping_insert().
*/
int as_area_get_flags(as_area_t *a)
{
1200,23 → 1350,20
 
/** Create page table.
*
* Depending on architecture, create either address space
* private or global page table.
* Depending on architecture, create either address space private or global page
* table.
*
* @param flags Flags saying whether the page table is for kernel address space.
* @param flags Flags saying whether the page table is for the kernel
* address space.
*
* @return First entry of the page table.
* @return First entry of the page table.
*/
pte_t *page_table_create(int flags)
{
#ifdef __OBJC__
return [as_t page_table_create: flags];
#else
ASSERT(as_operations);
ASSERT(as_operations->page_table_create);
return as_operations->page_table_create(flags);
#endif
}
 
/** Destroy page table.
1223,18 → 1370,14
*
* Destroy page table in architecture specific way.
*
* @param page_table Physical address of PTL0.
* @param page_table Physical address of PTL0.
*/
void page_table_destroy(pte_t *page_table)
{
#ifdef __OBJC__
return [as_t page_table_destroy: page_table];
#else
ASSERT(as_operations);
ASSERT(as_operations->page_table_destroy);
as_operations->page_table_destroy(page_table);
#endif
}
 
/** Lock page table.
1246,36 → 1389,28
* prior to this call. Address space can be locked prior to this
* call in which case the lock argument is false.
*
* @param as Address space.
* @param lock If false, do not attempt to lock as->lock.
* @param as Address space.
* @param lock If false, do not attempt to lock as->lock.
*/
void page_table_lock(as_t *as, bool lock)
{
#ifdef __OBJC__
[as page_table_lock: lock];
#else
ASSERT(as_operations);
ASSERT(as_operations->page_table_lock);
as_operations->page_table_lock(as, lock);
#endif
}
 
/** Unlock page table.
*
* @param as Address space.
* @param unlock If false, do not attempt to unlock as->lock.
* @param as Address space.
* @param unlock If false, do not attempt to unlock as->lock.
*/
void page_table_unlock(as_t *as, bool unlock)
{
#ifdef __OBJC__
[as page_table_unlock: unlock];
#else
ASSERT(as_operations);
ASSERT(as_operations->page_table_unlock);
as_operations->page_table_unlock(as, unlock);
#endif
}
 
 
1283,11 → 1418,11
*
* The address space must be locked and interrupts must be disabled.
*
* @param as Address space.
* @param va Virtual address.
* @param as Address space.
* @param va Virtual address.
*
* @return Locked address space area containing va on success or NULL on
* failure.
* @return Locked address space area containing va on success or
* NULL on failure.
*/
as_area_t *find_area_and_lock(as_t *as, uintptr_t va)
{
1339,15 → 1474,15
*
* The address space must be locked and interrupts must be disabled.
*
* @param as Address space.
* @param va Starting virtual address of the area being tested.
* @param size Size of the area being tested.
* @param avoid_area Do not touch this area.
* @param as Address space.
* @param va Starting virtual address of the area being tested.
* @param size Size of the area being tested.
* @param avoid_area Do not touch this area.
*
* @return True if there is no conflict, false otherwise.
* @return True if there is no conflict, false otherwise.
*/
bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,
as_area_t *avoid_area)
bool
check_area_conflicts(as_t *as, uintptr_t va, size_t size, as_area_t *avoid_area)
{
as_area_t *a;
btree_node_t *leaf, *node;
1436,7 → 1571,7
 
ipl = interrupts_disable();
src_area = find_area_and_lock(AS, base);
if (src_area){
if (src_area) {
size = src_area->pages * PAGE_SIZE;
mutex_unlock(&src_area->lock);
} else {
1450,11 → 1585,11
*
* The address space area must be already locked.
*
* @param a Address space area.
* @param page First page to be marked.
* @param count Number of page to be marked.
* @param a Address space area.
* @param page First page to be marked.
* @param count Number of page to be marked.
*
* @return 0 on failure and 1 on success.
* @return Zero on failure and non-zero on success.
*/
int used_space_insert(as_area_t *a, uintptr_t page, count_t count)
{
1724,8 → 1859,8
}
}
 
panic("Inconsistency detected while adding %" PRIc " pages of used space at "
"%p.\n", count, page);
panic("Inconsistency detected while adding %" PRIc " pages of used "
"space at %p.\n", count, page);
}
 
/** Mark portion of address space area as unused.
1732,11 → 1867,11
*
* The address space area must be already locked.
*
* @param a Address space area.
* @param page First page to be marked.
* @param count Number of page to be marked.
* @param a Address space area.
* @param page First page to be marked.
* @param count Number of page to be marked.
*
* @return 0 on failure and 1 on success.
* @return Zero on failure and non-zero on success.
*/
int used_space_remove(as_area_t *a, uintptr_t page, count_t count)
{
1903,8 → 2038,8
}
 
error:
panic("Inconsistency detected while removing %" PRIc " pages of used space "
"from %p.\n", count, page);
panic("Inconsistency detected while removing %" PRIc " pages of used "
"space from %p.\n", count, page);
}
 
/** Remove reference to address space area share info.
1911,7 → 2046,7
*
* If the reference count drops to 0, the sh_info is deallocated.
*
* @param sh_info Pointer to address space area share info.
* @param sh_info Pointer to address space area share info.
*/
void sh_info_remove_reference(share_info_t *sh_info)
{
1966,6 → 2101,12
return (unative_t) as_area_resize(AS, address, size, 0);
}
 
/** Wrapper for as_area_change_flags(). */
unative_t sys_as_area_change_flags(uintptr_t address, int flags)
{
return (unative_t) as_area_change_flags(AS, flags, address);
}
 
/** Wrapper for as_area_destroy(). */
unative_t sys_as_area_destroy(uintptr_t address)
{
1974,7 → 2115,7
 
/** Print out information about address space.
*
* @param as Address space.
* @param as Address space.
*/
void as_print(as_t *as)
{
1996,9 → 2137,9
as_area_t *area = node->value[i];
mutex_lock(&area->lock);
printf("as_area: %p, base=%p, pages=%" PRIc " (%p - %p)\n",
area, area->base, area->pages, area->base,
area->base + FRAMES2SIZE(area->pages));
printf("as_area: %p, base=%p, pages=%" PRIc
" (%p - %p)\n", area, area->base, area->pages,
area->base, area->base + FRAMES2SIZE(area->pages));
mutex_unlock(&area->lock);
}
}
/branches/tracing/kernel/generic/src/mm/buddy.c
35,8 → 35,7
* @brief Buddy allocator framework.
*
* This file contains buddy system allocator framework.
* Specialized functions are needed for this abstract framework
* to be useful.
* Specialized functions are needed for this abstract framework to be useful.
*/
 
#include <mm/buddy.h>
46,7 → 45,7
#include <print.h>
#include <macros.h>
 
/** Return size needed for the buddy configuration data */
/** Return size needed for the buddy configuration data. */
size_t buddy_conf_size(int max_order)
{
return sizeof(buddy_system_t) + (max_order + 1) * sizeof(link_t);
53,21 → 52,20
}
 
 
/** Create buddy system
/** Create buddy system.
*
* Allocate memory for and initialize new buddy system.
*
* @param b Preallocated buddy system control data.
* @param max_order The biggest allocable size will be 2^max_order.
* @param op Operations for new buddy system.
* @param data Pointer to be used by implementation.
* @param b Preallocated buddy system control data.
* @param max_order The biggest allocable size will be 2^max_order.
* @param op Operations for new buddy system.
* @param data Pointer to be used by implementation.
*
* @return New buddy system.
* @return New buddy system.
*/
void buddy_system_create(buddy_system_t *b,
uint8_t max_order,
buddy_system_operations_t *op,
void *data)
void
buddy_system_create(buddy_system_t *b, uint8_t max_order,
buddy_system_operations_t *op, void *data)
{
int i;
 
81,7 → 79,7
ASSERT(op->mark_busy);
 
/*
* Use memory after our own structure
* Use memory after our own structure.
*/
b->order = (link_t *) (&b[1]);
93,14 → 91,15
b->data = data;
}
 
/** Check if buddy system can allocate block
/** Check if buddy system can allocate block.
*
* @param b Buddy system pointer
* @param i Size of the block (2^i)
* @param b Buddy system pointer.
* @param i Size of the block (2^i).
*
* @return True if block can be allocated
* @return True if block can be allocated.
*/
bool buddy_system_can_alloc(buddy_system_t *b, uint8_t i) {
bool buddy_system_can_alloc(buddy_system_t *b, uint8_t i)
{
uint8_t k;
/*
107,12 → 106,13
* If requested block is greater then maximal block
* we know immediatly that we cannot satisfy the request.
*/
if (i > b->max_order) return false;
if (i > b->max_order)
return false;
 
/*
* Check if any bigger or equal order has free elements
*/
for (k=i; k <= b->max_order; k++) {
for (k = i; k <= b->max_order; k++) {
if (!list_empty(&b->order[k])) {
return true;
}
119,12 → 119,11
}
return false;
}
 
/** Allocate PARTICULAR block from buddy system
/** Allocate PARTICULAR block from buddy system.
*
* @ return Block of data or NULL if no such block was found
* @return Block of data or NULL if no such block was found.
*/
link_t *buddy_system_alloc_block(buddy_system_t *b, link_t *block)
{
135,7 → 134,7
ASSERT(left);
list_remove(left);
while (1) {
if (! b->op->get_order(b,left)) {
if (!b->op->get_order(b, left)) {
b->op->mark_busy(b, left);
return left;
}
143,8 → 142,8
order = b->op->get_order(b, left);
 
right = b->op->bisect(b, left);
b->op->set_order(b, left, order-1);
b->op->set_order(b, right, order-1);
b->op->set_order(b, left, order - 1);
b->op->set_order(b, right, order - 1);
 
tmp = b->op->find_block(b, block, BUDDY_SYSTEM_INNER_BLOCK);
 
161,10 → 160,10
 
/** Allocate block from buddy system.
*
* @param b Buddy system pointer.
* @param i Returned block will be 2^i big.
* @param b Buddy system pointer.
* @param i Returned block will be 2^i big.
*
* @return Block of data represented by link_t.
* @return Block of data represented by link_t.
*/
link_t *buddy_system_alloc(buddy_system_t *b, uint8_t i)
{
218,13 → 217,12
buddy_system_free(b, hlp);
return res;
}
 
/** Return block to buddy system.
*
* @param b Buddy system pointer.
* @param block Block to return.
* @param b Buddy system pointer.
* @param block Block to return.
*/
void buddy_system_free(buddy_system_t *b, link_t *block)
{
268,7 → 266,8
b->op->set_order(b, hlp, i + 1);
 
/*
* Recursively add the coalesced block to the list of order i + 1.
* Recursively add the coalesced block to the list of
* order i + 1.
*/
buddy_system_free(b, hlp);
return;
279,46 → 278,7
* Insert block into the list of order i.
*/
list_append(block, &b->order[i]);
 
}
 
/** Prints out structure of buddy system
*
* @param b Pointer to buddy system
* @param elem_size Element size
*/
void buddy_system_structure_print(buddy_system_t *b, size_t elem_size) {
index_t i;
count_t cnt, elem_count = 0, block_count = 0;
link_t *cur;
 
printf("Order\tBlocks\tSize \tBlock size\tElems per block\n");
printf("-----\t------\t--------\t----------\t---------------\n");
for (i = 0;i <= b->max_order; i++) {
cnt = 0;
if (!list_empty(&b->order[i])) {
for (cur = b->order[i].next; cur != &b->order[i]; cur = cur->next)
cnt++;
}
printf("#%" PRIi "\t%5" PRIc "\t%7" PRIc "K\t%8" PRIi "K\t%6u\t",
i, cnt, SIZE2KB(cnt * (1 << i) * elem_size), SIZE2KB((1 << i) * elem_size), 1 << i);
if (!list_empty(&b->order[i])) {
for (cur = b->order[i].next; cur != &b->order[i]; cur = cur->next) {
b->op->print_id(b, cur);
printf(" ");
}
}
printf("\n");
block_count += cnt;
elem_count += (1 << i) * cnt;
}
printf("-----\t------\t--------\t----------\t---------------\n");
printf("Buddy system contains %" PRIc " free elements (%" PRIc " blocks)\n" , elem_count, block_count);
}
 
/** @}
*/
/branches/tracing/kernel/generic/src/mm/frame.c
58,6 → 58,8
#include <debug.h>
#include <adt/list.h>
#include <synch/spinlock.h>
#include <synch/mutex.h>
#include <synch/condvar.h>
#include <arch/asm.h>
#include <arch.h>
#include <print.h>
103,6 → 105,14
 
static zones_t zones;
 
/*
* Synchronization primitives used to sleep when there is no memory
* available.
*/
mutex_t mem_avail_mtx;
condvar_t mem_avail_cv;
unsigned long mem_avail_frames = 0; /**< Number of available frames. */
unsigned long mem_avail_gen = 0; /**< Generation counter. */
 
/********************/
/* Helper functions */
129,11 → 139,9
return (frame - zone->frames);
}
 
/** Initialize frame structure
/** Initialize frame structure.
*
* Initialize frame structure.
*
* @param frame Frame structure to be initialized.
* @param frame Frame structure to be initialized.
*/
static void frame_initialize(frame_t *frame)
{
145,11 → 153,10
/* Zoneinfo functions */
/**********************/
 
/**
* Insert-sort zone into zones list
/** Insert-sort zone into zones list.
*
* @param newzone New zone to be inserted into zone list
* @return zone number on success, -1 on error
* @param newzone New zone to be inserted into zone list.
* @return Zone number on success, -1 on error.
*/
static int zones_add_zone(zone_t *newzone)
{
171,7 → 178,8
for (i = 0; i < zones.count; i++) {
/* Check for overflow */
z = zones.info[i];
if (overlaps(newzone->base, newzone->count, z->base, z->count)) {
if (overlaps(newzone->base, newzone->count, z->base,
z->count)) {
printf("Zones overlap!\n");
return -1;
}
192,17 → 200,16
return i;
}
 
/**
* Try to find a zone where can we find the frame
/** Try to find a zone where can we find the frame.
*
* Assume interrupts are disabled.
*
* @param frame Frame number contained in zone
* @param pzone If not null, it is used as zone hint. Zone index
* is filled into the variable on success.
* @return Pointer to locked zone containing frame
* @param frame Frame number contained in zone.
* @param pzone If not null, it is used as zone hint. Zone index is
* filled into the variable on success.
* @return Pointer to locked zone containing frame.
*/
static zone_t * find_zone_and_lock(pfn_t frame, unsigned int *pzone)
static zone_t *find_zone_and_lock(pfn_t frame, unsigned int *pzone)
{
unsigned int i;
unsigned int hint = pzone ? *pzone : 0;
229,7 → 236,7
i++;
if (i >= zones.count)
i = 0;
} while(i != hint);
} while (i != hint);
 
spinlock_unlock(&zones.lock);
return NULL;
245,16 → 252,21
*
* Assume interrupts are disabled.
*
* @param order Size (2^order) of free space we are trying to find
* @param pzone Pointer to preferred zone or NULL, on return contains zone
* number
* @param order Size (2^order) of free space we are trying to find.
* @param flags Required flags of the target zone.
* @param pzone Pointer to preferred zone or NULL, on return contains
* zone number.
*/
static zone_t * find_free_zone_and_lock(uint8_t order, unsigned int *pzone)
static zone_t *
find_free_zone_and_lock(uint8_t order, int flags, unsigned int *pzone)
{
unsigned int i;
zone_t *z;
unsigned int hint = pzone ? *pzone : 0;
/* Mask off flags that are not applicable. */
flags &= FRAME_LOW_4_GiB;
 
spinlock_lock(&zones.lock);
if (hint >= zones.count)
hint = 0;
264,17 → 276,24
spinlock_lock(&z->lock);
 
/* Check if the zone has 2^order frames area available */
if (zone_can_alloc(z, order)) {
spinlock_unlock(&zones.lock);
if (pzone)
*pzone = i;
return z;
/*
* Check whether the zone meets the search criteria.
*/
if ((z->flags & flags) == flags) {
/*
* Check if the zone has 2^order frames area available.
*/
if (zone_can_alloc(z, order)) {
spinlock_unlock(&zones.lock);
if (pzone)
*pzone = i;
return z;
}
}
spinlock_unlock(&z->lock);
if (++i >= zones.count)
i = 0;
} while(i != hint);
} while (i != hint);
spinlock_unlock(&zones.lock);
return NULL;
}
283,12 → 302,13
/* Buddy system functions */
/**************************/
 
/** Buddy system find_block implementation
/** Buddy system find_block implementation.
*
* Find block that is parent of current list.
* That means go to lower addresses, until such block is found
*
* @param order - Order of parent must be different then this parameter!!
* @param order Order of parent must be different then this
* parameter!!
*/
static link_t *zone_buddy_find_block(buddy_system_t *b, link_t *child,
uint8_t order)
309,24 → 329,12
return NULL;
}
 
static void zone_buddy_print_id(buddy_system_t *b, link_t *block)
{
frame_t *frame;
zone_t *zone;
index_t index;
 
frame = list_get_instance(block, frame_t, buddy_link);
zone = (zone_t *) b->data;
index = frame_index(zone, frame);
printf("%" PRIi, index);
}
 
/** Buddy system find_buddy implementation
/** Buddy system find_buddy implementation.
*
* @param b Buddy system.
* @param block Block for which buddy should be found
* @param b Buddy system.
* @param block Block for which buddy should be found.
*
* @return Buddy for given block if found
* @return Buddy for given block if found.
*/
static link_t *zone_buddy_find_buddy(buddy_system_t *b, link_t *block)
{
345,9 → 353,11
 
ASSERT(is_left ^ is_right);
if (is_left) {
index = (frame_index(zone, frame)) + (1 << frame->buddy_order);
index = (frame_index(zone, frame)) +
(1 << frame->buddy_order);
} else { /* if (is_right) */
index = (frame_index(zone, frame)) - (1 << frame->buddy_order);
index = (frame_index(zone, frame)) -
(1 << frame->buddy_order);
}
if (frame_index_valid(zone, index)) {
360,14 → 370,15
return NULL;
}
 
/** Buddy system bisect implementation
/** Buddy system bisect implementation.
*
* @param b Buddy system.
* @param block Block to bisect
* @param b Buddy system.
* @param block Block to bisect.
*
* @return right block
* @return Right block.
*/
static link_t * zone_buddy_bisect(buddy_system_t *b, link_t *block) {
static link_t *zone_buddy_bisect(buddy_system_t *b, link_t *block)
{
frame_t *frame_l, *frame_r;
 
frame_l = list_get_instance(block, frame_t, buddy_link);
376,13 → 387,14
return &frame_r->buddy_link;
}
 
/** Buddy system coalesce implementation
/** Buddy system coalesce implementation.
*
* @param b Buddy system.
* @param block_1 First block
* @param block_2 First block's buddy
* @param b Buddy system.
* @param block_1 First block.
* @param block_2 First block's buddy.
*
* @return Coalesced block (actually block that represents lower address)
* @return Coalesced block (actually block that represents lower
* address).
*/
static link_t *zone_buddy_coalesce(buddy_system_t *b, link_t *block_1,
link_t *block_2)
395,39 → 407,41
return frame1 < frame2 ? block_1 : block_2;
}
 
/** Buddy system set_order implementation
/** Buddy system set_order implementation.
*
* @param b Buddy system.
* @param block Buddy system block
* @param order Order to set
* @param b Buddy system.
* @param block Buddy system block.
* @param order Order to set.
*/
static void zone_buddy_set_order(buddy_system_t *b, link_t *block,
uint8_t order) {
uint8_t order)
{
frame_t *frame;
frame = list_get_instance(block, frame_t, buddy_link);
frame->buddy_order = order;
}
 
/** Buddy system get_order implementation
/** Buddy system get_order implementation.
*
* @param b Buddy system.
* @param block Buddy system block
* @param b Buddy system.
* @param block Buddy system block.
*
* @return Order of block
* @return Order of block.
*/
static uint8_t zone_buddy_get_order(buddy_system_t *b, link_t *block) {
static uint8_t zone_buddy_get_order(buddy_system_t *b, link_t *block)
{
frame_t *frame;
frame = list_get_instance(block, frame_t, buddy_link);
return frame->buddy_order;
}
 
/** Buddy system mark_busy implementation
/** Buddy system mark_busy implementation.
*
* @param b Buddy system
* @param block Buddy system block
*
* @param b Buddy system.
* @param block Buddy system block.
*/
static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block) {
static void zone_buddy_mark_busy(buddy_system_t *b, link_t * block)
{
frame_t * frame;
 
frame = list_get_instance(block, frame_t, buddy_link);
434,13 → 448,13
frame->refcount = 1;
}
 
/** Buddy system mark_available implementation
/** Buddy system mark_available implementation.
*
* @param b Buddy system
* @param block Buddy system block
*
* @param b Buddy system.
* @param block Buddy system block.
*/
static void zone_buddy_mark_available(buddy_system_t *b, link_t *block) {
static void zone_buddy_mark_available(buddy_system_t *b, link_t *block)
{
frame_t *frame;
frame = list_get_instance(block, frame_t, buddy_link);
frame->refcount = 0;
454,8 → 468,7
.get_order = zone_buddy_get_order,
.mark_busy = zone_buddy_mark_busy,
.mark_available = zone_buddy_mark_available,
.find_block = zone_buddy_find_block,
.print_id = zone_buddy_print_id
.find_block = zone_buddy_find_block
};
 
/******************/
462,15 → 475,15
/* Zone functions */
/******************/
 
/** Allocate frame in particular zone
/** Allocate frame in particular zone.
*
* Assume zone is locked
* Assume zone is locked.
* Panics if allocation is impossible.
*
* @param zone Zone to allocate from.
* @param order Allocate exactly 2^order frames.
* @param zone Zone to allocate from.
* @param order Allocate exactly 2^order frames.
*
* @return Frame index in zone
* @return Frame index in zone.
*
*/
static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order)
496,12 → 509,12
return v;
}
 
/** Free frame from zone
/** Free frame from zone.
*
* Assume zone is locked
* Assume zone is locked.
*
* @param zone Pointer to zone from which the frame is to be freed
* @param frame_idx Frame index relative to zone
* @param zone Pointer to zone from which the frame is to be freed.
* @param frame_idx Frame index relative to zone.
*/
static void zone_frame_free(zone_t *zone, index_t frame_idx)
{
524,14 → 537,14
}
}
 
/** Return frame from zone */
static frame_t * zone_get_frame(zone_t *zone, index_t frame_idx)
/** Return frame from zone. */
static frame_t *zone_get_frame(zone_t *zone, index_t frame_idx)
{
ASSERT(frame_idx < zone->count);
return &zone->frames[frame_idx];
}
 
/** Mark frame in zone unavailable to allocation */
/** Mark frame in zone unavailable to allocation. */
static void zone_mark_unavailable(zone_t *zone, index_t frame_idx)
{
frame_t *frame;
544,18 → 557,21
&frame->buddy_link);
ASSERT(link);
zone->free_count--;
 
mutex_lock(&mem_avail_mtx);
mem_avail_frames--;
mutex_unlock(&mem_avail_mtx);
}
 
/**
* Join 2 zones
/** Join two zones.
*
* Expect zone_t *z to point to space at least zone_conf_size large
* Expect zone_t *z to point to space at least zone_conf_size large.
*
* Assume z1 & z2 are locked
* Assume z1 & z2 are locked.
*
* @param z Target zone structure pointer
* @param z1 Zone to merge
* @param z2 Zone to merge
* @param z Target zone structure pointer.
* @param z1 Zone to merge.
* @param z2 Zone to merge.
*/
static void _zone_merge(zone_t *z, zone_t *z1, zone_t *z2)
{
629,7 → 645,7
}
}
 
/** Return old configuration frames into the zone
/** Return old configuration frames into the zone.
*
* We have several cases
* - the conf. data is outside of zone -> exit, shall we call frame_free??
636,9 → 652,9
* - the conf. data was created by zone_create or
* updated with reduce_region -> free every frame
*
* @param newzone The actual zone where freeing should occur
* @param oldzone Pointer to old zone configuration data that should
* be freed from new zone
* @param newzone The actual zone where freeing should occur.
* @param oldzone Pointer to old zone configuration data that should
* be freed from new zone.
*/
static void return_config_frames(zone_t *newzone, zone_t *oldzone)
{
662,7 → 678,7
}
}
 
/** Reduce allocated block to count of order 0 frames
/** Reduce allocated block to count of order 0 frames.
*
* The allocated block need 2^order frames of space. Reduce all frames
* in block to order 0 and free the unneeded frames. This means, that
670,8 → 686,8
* you have to free every frame.
*
* @param zone
* @param frame_idx Index to block
* @param count Allocated space in block
* @param frame_idx Index to block.
* @param count Allocated space in block.
*/
static void zone_reduce_region(zone_t *zone, pfn_t frame_idx, count_t count)
{
698,7 → 714,7
}
}
 
/** Merge zones z1 and z2
/** Merge zones z1 and z2.
*
* - the zones must be 2 zones with no zone existing in between,
* which means that z2 = z1+1
722,7 → 738,7
if ((z1 >= zones.count) || (z2 >= zones.count))
goto errout;
/* We can join only 2 zones with none existing inbetween */
if (z2-z1 != 1)
if (z2 - z1 != 1)
goto errout;
 
zone1 = zones.info[z1];
773,8 → 789,7
interrupts_restore(ipl);
}
 
/**
* Merge all zones into one big zone
/** Merge all zones into one big zone.
*
* It is reasonable to do this on systems whose bios reports parts in chunks,
* so that we could have 1 zone (it's faster).
784,21 → 799,19
int count = zones.count;
 
while (zones.count > 1 && --count) {
zone_merge(0,1);
zone_merge(0, 1);
break;
}
}
 
/** Create frame zone
/** Create new frame zone.
*
* Create new frame zone.
* @param start Physical address of the first frame within the zone.
* @param count Count of frames in zone.
* @param z Address of configuration information of zone.
* @param flags Zone flags.
*
* @param start Physical address of the first frame within the zone.
* @param count Count of frames in zone
* @param z Address of configuration information of zone
* @param flags Zone flags.
*
* @return Initialized zone.
* @return Initialized zone.
*/
static void zone_construct(pfn_t start, count_t count, zone_t *z, int flags)
{
808,7 → 821,15
spinlock_initialize(&z->lock, "zone_lock");
z->base = start;
z->count = count;
 
/* Mask off flags that are calculated automatically. */
flags &= ~FRAME_LOW_4_GiB;
/* Determine calculated flags. */
if (z->base + count < (1ULL << (32 - FRAME_WIDTH))) /* 4 GiB */
flags |= FRAME_LOW_4_GiB;
 
z->flags = flags;
 
z->free_count = count;
z->busy_count = 0;
 
819,8 → 840,7
z->buddy_system = (buddy_system_t *)&z[1];
buddy_system_create(z->buddy_system, max_order,
&zone_buddy_system_operations,
(void *) z);
&zone_buddy_system_operations, (void *) z);
/* Allocate frames _after_ the conframe */
/* Check sizes */
837,10 → 857,10
}
}
 
/** Compute configuration data size for zone
/** Compute configuration data size for zone.
*
* @param count Size of zone in frames
* @return Size of zone configuration info (in bytes)
* @param count Size of zone in frames.
* @return Size of zone configuration info (in bytes).
*/
uintptr_t zone_conf_size(count_t count)
{
852,20 → 872,20
return size;
}
 
/** Create and add zone to system
/** Create and add zone to system.
*
* @param start First frame number (absolute)
* @param count Size of zone in frames
* @param confframe Where configuration frames are supposed to be.
* Automatically checks, that we will not disturb the
* kernel and possibly init.
* If confframe is given _outside_ this zone, it is expected,
* that the area is already marked BUSY and big enough
* to contain zone_conf_size() amount of data.
* If the confframe is inside the area, the zone free frame
* information is modified not to include it.
* @param start First frame number (absolute).
* @param count Size of zone in frames.
* @param confframe Where configuration frames are supposed to be.
* Automatically checks, that we will not disturb the
* kernel and possibly init. If confframe is given
* _outside_ this zone, it is expected, that the area is
* already marked BUSY and big enough to contain
* zone_conf_size() amount of data. If the confframe is
* inside the area, the zone free frame information is
* modified not to include it.
*
* @return Zone number or -1 on error
* @return Zone number or -1 on error.
*/
int zone_create(pfn_t start, count_t count, pfn_t confframe, int flags)
{
884,8 → 904,8
* it does not span kernel & init
*/
confcount = SIZE2FRAMES(zone_conf_size(count));
if (confframe >= start && confframe < start+count) {
for (;confframe < start + count; confframe++) {
if (confframe >= start && confframe < start + count) {
for (; confframe < start + count; confframe++) {
addr = PFN2ADDR(confframe);
if (overlaps(addr, PFN2ADDR(confcount),
KA2PA(config.base), config.kernel_size))
919,11 → 939,16
if (znum == -1)
return -1;
 
mutex_lock(&mem_avail_mtx);
mem_avail_frames += count;
mutex_unlock(&mem_avail_mtx);
 
/* If confdata in zone, mark as unavailable */
if (confframe >= start && confframe < start + count)
for (i = confframe; i < confframe + confcount; i++) {
zone_mark_unavailable(z, i - z->base);
}
return znum;
}
 
930,7 → 955,7
/***************************************/
/* Frame functions */
 
/** Set parent of frame */
/** Set parent of frame. */
void frame_set_parent(pfn_t pfn, void *data, unsigned int hint)
{
zone_t *zone = find_zone_and_lock(pfn, &hint);
937,7 → 962,7
 
ASSERT(zone);
 
zone_get_frame(zone, pfn-zone->base)->parent = data;
zone_get_frame(zone, pfn - zone->base)->parent = data;
spinlock_unlock(&zone->lock);
}
 
955,19 → 980,20
 
/** Allocate power-of-two frames of physical memory.
*
* @param order Allocate exactly 2^order frames.
* @param flags Flags for host zone selection and address processing.
* @param pzone Preferred zone
* @param order Allocate exactly 2^order frames.
* @param flags Flags for host zone selection and address processing.
* @param pzone Preferred zone.
*
* @return Physical address of the allocated frame.
* @return Physical address of the allocated frame.
*
*/
void * frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone)
void *frame_alloc_generic(uint8_t order, int flags, unsigned int *pzone)
{
ipl_t ipl;
int freed;
pfn_t v;
zone_t *zone;
unsigned long gen = 0;
loop:
ipl = interrupts_disable();
975,7 → 1001,7
/*
* First, find suitable frame zone.
*/
zone = find_free_zone_and_lock(order, pzone);
zone = find_free_zone_and_lock(order, flags, pzone);
/* If no memory, reclaim some slab memory,
if it does not help, reclaim all */
982,23 → 1008,51
if (!zone && !(flags & FRAME_NO_RECLAIM)) {
freed = slab_reclaim(0);
if (freed)
zone = find_free_zone_and_lock(order, pzone);
zone = find_free_zone_and_lock(order, flags, pzone);
if (!zone) {
freed = slab_reclaim(SLAB_RECLAIM_ALL);
if (freed)
zone = find_free_zone_and_lock(order, pzone);
zone = find_free_zone_and_lock(order, flags,
pzone);
}
}
if (!zone) {
/*
* TODO: Sleep until frames are available again.
* Sleep until some frames are available again.
*/
interrupts_restore(ipl);
 
if (flags & FRAME_ATOMIC)
if (flags & FRAME_ATOMIC) {
interrupts_restore(ipl);
return 0;
}
panic("Sleep not implemented.\n");
#ifdef CONFIG_DEBUG
unsigned long avail;
 
mutex_lock(&mem_avail_mtx);
avail = mem_avail_frames;
mutex_unlock(&mem_avail_mtx);
 
printf("Thread %" PRIu64 " waiting for %u frames, "
"%u available.\n", THREAD->tid, 1ULL << order, avail);
#endif
 
mutex_lock(&mem_avail_mtx);
while ((mem_avail_frames < (1ULL << order)) ||
gen == mem_avail_gen)
condvar_wait(&mem_avail_cv, &mem_avail_mtx);
gen = mem_avail_gen;
mutex_unlock(&mem_avail_mtx);
 
#ifdef CONFIG_DEBUG
mutex_lock(&mem_avail_mtx);
avail = mem_avail_frames;
mutex_unlock(&mem_avail_mtx);
 
printf("Thread %" PRIu64 " woken up, %u frames available.\n",
THREAD->tid, avail);
#endif
 
interrupts_restore(ipl);
goto loop;
}
1006,6 → 1060,11
v += zone->base;
 
spinlock_unlock(&zone->lock);
mutex_lock(&mem_avail_mtx);
mem_avail_frames -= (1ULL << order);
mutex_unlock(&mem_avail_mtx);
 
interrupts_restore(ipl);
 
if (flags & FRAME_KA)
1019,7 → 1078,7
* Decrement frame reference count.
* If it drops to zero, move the frame structure to free list.
*
* @param Frame Physical Address of of the frame to be freed.
* @param frame Physical Address of of the frame to be freed.
*/
void frame_free(uintptr_t frame)
{
1028,16 → 1087,26
pfn_t pfn = ADDR2PFN(frame);
 
ipl = interrupts_disable();
 
/*
* First, find host frame zone for addr.
*/
zone = find_zone_and_lock(pfn,NULL);
zone = find_zone_and_lock(pfn, NULL);
ASSERT(zone);
zone_frame_free(zone, pfn-zone->base);
zone_frame_free(zone, pfn - zone->base);
spinlock_unlock(&zone->lock);
/*
* Signal that some memory has been freed.
*/
mutex_lock(&mem_avail_mtx);
mem_avail_frames++;
mem_avail_gen++;
condvar_broadcast(&mem_avail_cv);
mutex_unlock(&mem_avail_mtx);
 
interrupts_restore(ipl);
}
 
1046,7 → 1115,7
* Find respective frame structure for supplied PFN and
* increment frame reference count.
*
* @param pfn Frame number of the frame to be freed.
* @param pfn Frame number of the frame to be freed.
*/
void frame_reference_add(pfn_t pfn)
{
1059,10 → 1128,10
/*
* First, find host frame zone for addr.
*/
zone = find_zone_and_lock(pfn,NULL);
zone = find_zone_and_lock(pfn, NULL);
ASSERT(zone);
frame = &zone->frames[pfn-zone->base];
frame = &zone->frames[pfn - zone->base];
frame->refcount++;
spinlock_unlock(&zone->lock);
1069,7 → 1138,7
interrupts_restore(ipl);
}
 
/** Mark given range unavailable in frame zones */
/** Mark given range unavailable in frame zones. */
void frame_mark_unavailable(pfn_t start, count_t count)
{
unsigned int i;
1086,15 → 1155,14
}
}
 
/** Initialize physical memory management
*
* Initialize physical memory managemnt.
*/
/** Initialize physical memory management. */
void frame_init(void)
{
if (config.cpu_active == 1) {
zones.count = 0;
spinlock_initialize(&zones.lock, "zones.lock");
mutex_initialize(&mem_avail_mtx, MUTEX_ACTIVE);
condvar_initialize(&mem_avail_cv);
}
/* Tell the architecture to create some memory */
frame_arch_init();
1122,10 → 1190,9
}
 
 
/** Return total size of all zones
*
*/
uint64_t zone_total_size(void) {
/** Return total size of all zones. */
uint64_t zone_total_size(void)
{
zone_t *zone = NULL;
unsigned int i;
ipl_t ipl;
1147,19 → 1214,13
return total;
}
 
 
 
/** Prints list of zones
*
*/
void zone_print_list(void) {
/** Prints list of zones. */
void zone_print_list(void)
{
zone_t *zone = NULL;
unsigned int i;
ipl_t ipl;
 
ipl = interrupts_disable();
spinlock_lock(&zones.lock);
 
#ifdef __32_BITS__
printf("# base address free frames busy frames\n");
printf("-- ------------ ------------ ------------\n");
1170,35 → 1231,69
printf("-- -------------------- ------------ ------------\n");
#endif
for (i = 0; i < zones.count; i++) {
/*
* Because printing may require allocation of memory, we may not hold
* the frame allocator locks when printing zone statistics. Therefore,
* we simply gather the statistics under the protection of the locks and
* print the statistics when the locks have been released.
*
* When someone adds/removes zones while we are printing the statistics,
* we may end up with inaccurate output (e.g. a zone being skipped from
* the listing).
*/
 
for (i = 0; ; i++) {
uintptr_t base;
count_t free_count;
count_t busy_count;
 
ipl = interrupts_disable();
spinlock_lock(&zones.lock);
if (i >= zones.count) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
break;
}
 
zone = zones.info[i];
spinlock_lock(&zone->lock);
 
base = PFN2ADDR(zone->base);
free_count = zone->free_count;
busy_count = zone->busy_count;
 
spinlock_unlock(&zone->lock);
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
 
#ifdef __32_BITS__
printf("%-2u %10p %12" PRIc " %12" PRIc "\n", i, PFN2ADDR(zone->base),
zone->free_count, zone->busy_count);
printf("%-2u %10p %12" PRIc " %12" PRIc "\n", i, base,
free_count, busy_count);
#endif
 
#ifdef __64_BITS__
printf("%-2u %18p %12" PRIc " %12" PRIc "\n", i, PFN2ADDR(zone->base),
zone->free_count, zone->busy_count);
printf("%-2u %18p %12" PRIc " %12" PRIc "\n", i, base,
free_count, busy_count);
#endif
spinlock_unlock(&zone->lock);
}
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
}
 
/** Prints zone details.
*
* @param num Zone base address or zone number.
* @param num Zone base address or zone number.
*/
void zone_print_one(unsigned int num) {
void zone_print_one(unsigned int num)
{
zone_t *zone = NULL;
ipl_t ipl;
unsigned int i;
uintptr_t base;
count_t count;
count_t busy_count;
count_t free_count;
 
ipl = interrupts_disable();
spinlock_lock(&zones.lock);
1210,25 → 1305,28
}
}
if (!zone) {
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
printf("Zone not found.\n");
goto out;
return;
}
spinlock_lock(&zone->lock);
printf("Memory zone information\n");
printf("Zone base address: %p\n", PFN2ADDR(zone->base));
printf("Zone size: %" PRIc " frames (%" PRIs " KB)\n", zone->count,
SIZE2KB(FRAMES2SIZE(zone->count)));
printf("Allocated space: %" PRIc " frames (%" PRIs " KB)\n", zone->busy_count,
SIZE2KB(FRAMES2SIZE(zone->busy_count)));
printf("Available space: %" PRIc " frames (%" PRIs " KB)\n", zone->free_count,
SIZE2KB(FRAMES2SIZE(zone->free_count)));
buddy_system_structure_print(zone->buddy_system, FRAME_SIZE);
base = PFN2ADDR(zone->base);
count = zone->count;
busy_count = zone->busy_count;
free_count = zone->free_count;
spinlock_unlock(&zone->lock);
out:
spinlock_unlock(&zones.lock);
interrupts_restore(ipl);
 
printf("Zone base address: %p\n", base);
printf("Zone size: %" PRIc " frames (%" PRIs " KiB)\n", count,
SIZE2KB(FRAMES2SIZE(count)));
printf("Allocated space: %" PRIc " frames (%" PRIs " KiB)\n",
busy_count, SIZE2KB(FRAMES2SIZE(busy_count)));
printf("Available space: %" PRIc " frames (%" PRIs " KiB)\n",
free_count, SIZE2KB(FRAMES2SIZE(free_count)));
}
 
/** @}
/branches/tracing/kernel/generic/src/mm/backend_elf.c
118,7 → 118,7
*/
 
for (i = 0; i < leaf->keys; i++) {
if (leaf->key[i] == page) {
if (leaf->key[i] == page - area->base) {
found = true;
break;
}
/branches/tracing/kernel/generic/src/syscall/syscall.c
38,6 → 38,7
#include <syscall/syscall.h>
#include <proc/thread.h>
#include <proc/task.h>
#include <proc/program.h>
#include <mm/as.h>
#include <print.h>
#include <putchar.h>
46,6 → 47,7
#include <debug.h>
#include <ipc/sysipc.h>
#include <synch/futex.h>
#include <synch/smc.h>
#include <ddi/ddi.h>
#include <security/cap.h>
#include <syscall/copy.h>
133,15 → 135,17
(syshandler_t) sys_thread_get_id,
(syshandler_t) sys_task_get_id,
(syshandler_t) sys_task_spawn,
(syshandler_t) sys_program_spawn_loader,
/* Synchronization related syscalls. */
(syshandler_t) sys_futex_sleep_timeout,
(syshandler_t) sys_futex_wakeup,
(syshandler_t) sys_smc_coherence,
/* Address space related syscalls. */
(syshandler_t) sys_as_area_create,
(syshandler_t) sys_as_area_resize,
(syshandler_t) sys_as_area_change_flags,
(syshandler_t) sys_as_area_destroy,
/* IPC related syscalls. */
/branches/tracing/kernel/generic/src/ipc/ipcrsc.c
170,7 → 170,6
int i;
 
spinlock_lock(&TASK->lock);
for (i = 0; i < IPC_MAX_PHONES; i++) {
if (TASK->phones[i].state == IPC_PHONE_HUNGUP &&
atomic_get(&TASK->phones[i].active_calls) == 0)
183,8 → 182,9
}
spinlock_unlock(&TASK->lock);
 
if (i >= IPC_MAX_PHONES)
if (i == IPC_MAX_PHONES)
return -1;
 
return i;
}
 
/branches/tracing/kernel/generic/src/ipc/sysipc.c
271,12 → 271,12
/* The recipient agreed to receive data. */
int rc;
uintptr_t dst;
uintptr_t size;
uintptr_t max_size;
size_t size;
size_t max_size;
 
dst = IPC_GET_ARG1(answer->data);
size = IPC_GET_ARG2(answer->data);
max_size = IPC_GET_ARG2(*olddata);
dst = (uintptr_t)IPC_GET_ARG1(answer->data);
size = (size_t)IPC_GET_ARG2(answer->data);
max_size = (size_t)IPC_GET_ARG2(*olddata);
 
if (size <= max_size) {
rc = copy_to_uspace((void *) dst,
453,7 → 453,9
IPC_SET_ARG5(call.data, 0);
 
if (!(res = request_preprocess(&call, phone))) {
ipc_call_sync(phone, &call);
rc = ipc_call_sync(phone, &call);
if (rc != EOK)
return rc;
process_answer(&call);
} else {
IPC_SET_RETVAL(call.data, res);
491,7 → 493,9
GET_CHECK_PHONE(phone, phoneid, return ENOENT);
 
if (!(res = request_preprocess(&call, phone))) {
ipc_call_sync(phone, &call);
rc = ipc_call_sync(phone, &call);
if (rc != EOK)
return rc;
process_answer(&call);
} else
IPC_SET_RETVAL(call.data, res);
/branches/tracing/kernel/generic/src/ipc/ipc.c
88,7 → 88,8
call_t *call;
 
call = slab_alloc(ipc_call_slab, flags);
_ipc_call_init(call);
if (call)
_ipc_call_init(call);
 
return call;
}
161,7 → 162,7
*/
void ipc_phone_init(phone_t *phone)
{
mutex_initialize(&phone->lock);
mutex_initialize(&phone->lock, MUTEX_PASSIVE);
phone->callee = NULL;
phone->state = IPC_PHONE_FREE;
atomic_set(&phone->active_calls, 0);
171,8 → 172,10
*
* @param phone Destination kernel phone structure.
* @param request Call structure with request.
*
* @return EOK on success or EINTR if the sleep was interrupted.
*/
void ipc_call_sync(phone_t *phone, call_t *request)
int ipc_call_sync(phone_t *phone, call_t *request)
{
answerbox_t sync_box;
 
182,7 → 185,10
request->callerbox = &sync_box;
 
ipc_call(phone, request);
ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
if (!ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT,
SYNCH_FLAGS_INTERRUPTIBLE))
return EINTR;
return EOK;
}
 
/** Answer a message which was not dispatched and is not listed in any queue.
195,6 → 201,13
 
call->flags |= IPC_CALL_ANSWERED;
 
if (call->flags & IPC_CALL_FORWARDED) {
if (call->caller_phone) {
/* Demasquerade the caller phone. */
call->data.phone = call->caller_phone;
}
}
 
spinlock_lock(&callerbox->lock);
list_append(&call->link, &callerbox->answers);
spinlock_unlock(&callerbox->lock);
347,8 → 360,11
list_remove(&call->link);
spinlock_unlock(&oldbox->lock);
 
if (mode & IPC_FF_ROUTE_FROM_ME)
if (mode & IPC_FF_ROUTE_FROM_ME) {
if (!call->caller_phone)
call->caller_phone = call->data.phone;
call->data.phone = newphone;
}
 
return ipc_call(newphone, call);
}
666,8 → 682,9
tmp = tmp->next) {
call = list_get_instance(tmp, call_t, link);
printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, call->sender->taskid,
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call,
call->sender->taskid,
IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data),
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
680,8 → 697,9
tmp = tmp->next) {
call = list_get_instance(tmp, call_t, link);
printf("Callid: %p Srctask:%" PRIu64 " M:%" PRIun
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call, call->sender->taskid,
" A1:%" PRIun " A2:%" PRIun " A3:%" PRIun
" A4:%" PRIun " A5:%" PRIun " Flags:%x\n", call,
call->sender->taskid,
IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data),
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
689,11 → 707,12
}
/* Print answerbox - calls */
printf("ABOX - ANSWERS:\n");
for (tmp = task->answerbox.answers.next; tmp != &task->answerbox.answers;
for (tmp = task->answerbox.answers.next;
tmp != &task->answerbox.answers;
tmp = tmp->next) {
call = list_get_instance(tmp, call_t, link);
printf("Callid:%p M:%" PRIun " A1:%" PRIun " A2:%" PRIun
" A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n",
" A3:%" PRIun " A4:%" PRIun " A5:%" PRIun " Flags:%x\n",
call, IPC_GET_METHOD(call->data), IPC_GET_ARG1(call->data),
IPC_GET_ARG2(call->data), IPC_GET_ARG3(call->data),
IPC_GET_ARG4(call->data), IPC_GET_ARG5(call->data),
/branches/tracing/kernel/Makefile
232,6 → 232,7
generic/src/main/uinit.c \
generic/src/main/version.c \
generic/src/main/shutdown.c \
generic/src/proc/program.c \
generic/src/proc/scheduler.c \
generic/src/proc/thread.c \
generic/src/proc/task.c \
270,6 → 271,7
generic/src/synch/rwlock.c \
generic/src/synch/mutex.c \
generic/src/synch/semaphore.c \
generic/src/synch/smc.c \
generic/src/synch/waitq.c \
generic/src/synch/futex.c \
generic/src/smp/ipi.c \
318,16 → 320,6
test/sysinfo/sysinfo1.c
endif
 
## Experimental features
#
 
ifeq ($(CONFIG_EXPERIMENTAL),y)
GENERIC_SOURCES += generic/src/lib/objc_ext.c \
generic/src/lib/objc.c
EXTRA_OBJECTS = $(LIBDIR)/libobjc.a
EXTRA_FLAGS += -x objective-c
endif
 
GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES)))
ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES)))
GENARCH_OBJECTS := $(addsuffix .o,$(basename $(GENARCH_SOURCES)))
/branches/tracing/kernel/arch/sparc64/include/atomic.h
37,6 → 37,7
 
#include <arch/barrier.h>
#include <arch/types.h>
#include <preemption.h>
 
/** Atomic add operation.
*
56,7 → 57,8
 
a = *((uint64_t *) x);
b = a + i;
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *)x)), "+r" (b) : "r" (a));
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *)x)),
"+r" (b) : "r" (a));
} while (a != b);
 
return a;
97,7 → 99,8
uint64_t v = 1;
volatile uintptr_t x = (uint64_t) &val->count;
 
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *) x)), "+r" (v) : "r" (0));
asm volatile ("casx %0, %2, %1\n" : "+m" (*((uint64_t *) x)),
"+r" (v) : "r" (0));
 
return v;
}
109,6 → 112,8
 
volatile uintptr_t x = (uint64_t) &val->count;
 
preemption_disable();
 
asm volatile (
"0:\n"
"casx %0, %3, %1\n"
/branches/tracing/kernel/arch/sparc64/include/mm/page.h
53,11 → 53,6
 
#define MMU_PAGES_PER_PAGE (1 << (PAGE_WIDTH - MMU_PAGE_WIDTH))
 
/*
* With 16K pages, there is only one page color.
*/
#define PAGE_COLOR_BITS 0 /**< 14 - 14; 2^14 == 16K == alias boundary. */
 
#ifdef KERNEL
 
#ifndef __ASM__
/branches/tracing/kernel/arch/sparc64/Makefile.inc
29,11 → 29,15
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf64-sparc
BFD_ARCH = sparc
BFD = binary
TARGET = sparc64-linux-gnu
TOOLCHAIN_DIR = /usr/local/sparc64
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64
 
GCC_CFLAGS += -m64 -mcpu=ultrasparc
SUNCC_CFLAGS += -m64 -xarch=sparc -xregs=appl,no%float
/branches/tracing/kernel/arch/sparc64/src/asm.S
41,6 → 41,7
*/
.global memcpy
memcpy:
mov %o0, %o3 ! save dst
add %o1, 7, %g1
and %g1, -8, %g1
cmp %o1, %g1
59,7 → 60,7
mov %g2, %g3
2:
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
3:
and %g1, -8, %g1
cmp %o0, %g1
93,7 → 94,7
mov %g2, %g3
 
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
 
/*
* Almost the same as memcpy() except the loads are from userspace.
100,6 → 101,7
*/
.global memcpy_from_uspace
memcpy_from_uspace:
mov %o0, %o3 ! save dst
add %o1, 7, %g1
and %g1, -8, %g1
cmp %o1, %g1
118,7 → 120,7
mov %g2, %g3
2:
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
3:
and %g1, -8, %g1
cmp %o0, %g1
152,7 → 154,7
mov %g2, %g3
 
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
 
/*
* Almost the same as memcpy() except the stores are to userspace.
159,6 → 161,7
*/
.global memcpy_to_uspace
memcpy_to_uspace:
mov %o0, %o3 ! save dst
add %o1, 7, %g1
and %g1, -8, %g1
cmp %o1, %g1
177,7 → 180,7
mov %g2, %g3
2:
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
3:
and %g1, -8, %g1
cmp %o0, %g1
211,7 → 214,7
mov %g2, %g3
 
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
 
.global memcpy_from_uspace_failover_address
.global memcpy_to_uspace_failover_address
274,6 → 277,8
wrpr %g0, 0, %cleanwin ! avoid information leak
 
mov %i2, %o0 ! uarg
xor %o1, %o1, %o1 ! %o1 is defined to hold pcb_ptr
! set it to 0
 
clr %i2
clr %i3
/branches/tracing/kernel/arch/ia64/include/mm/page.h
41,8 → 41,6
#define PAGE_SIZE FRAME_SIZE
#define PAGE_WIDTH FRAME_WIDTH
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifdef KERNEL
 
/** Bit width of the TLB-locked portion of kernel address space. */
/branches/tracing/kernel/arch/ia64/Makefile.inc
29,14 → 29,15
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf64-little
BFD_ARCH = ia64-elf64
TARGET = ia64-pc-linux-gnu
TOOLCHAIN_DIR = /usr/local/ia64
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64
 
INIT0_ADDRESS = 0xe000000004404000
INIT0_SIZE = 0x100000
 
CMN1 = -mconstant-gp -fno-unwind-tables -mfixed-range=f32-f127
GCC_CFLAGS += $(CMN1)
ICC_CFLAGS += $(CMN1)
44,9 → 45,8
LFLAGS += -EL
AFLAGS += -mconstant-gp
 
DEFS += -D__64_BITS__ -DINIT0_ADDRESS=$(INIT0_ADDRESS) -DINIT0_SIZE=$(INIT0_SIZE) -D$(MACHINE)
DEFS += -D__64_BITS__ -D$(MACHINE)
 
 
## Compile with page hash table support.
#
 
96,6 → 96,5
CONFIG_I8042 = y
DEFS += -DI460GX -DCONFIG_I8042
BFD = binary
 
endif
 
/branches/tracing/kernel/arch/ia64/src/asm.S
51,7 → 51,7
 
adds r14 = 7, in1
mov r2 = ar.lc
mov r8 = in1 ;;
mov r8 = in0
and r14 = -8, r14 ;;
cmp.ne p6, p7 = r14, in1
(p7) br.cond.dpnt 3f ;;
63,7 → 63,7
(p6) mov r17 = r0 ;;
(p6) mov ar.lc = r14
1:
add r14 = r16, r8
add r14 = r16, in1
add r15 = r16, in0
adds r17 = 1, r17 ;;
ld1 r14 = [r14]
72,7 → 72,6
br.cloop.sptk.few 1b ;;
2:
mov ar.lc = r2
 
mov ar.pfs = loc0
br.ret.sptk.many rp
3:
90,7 → 89,7
4:
shladd r14 = r16, 3, r0
adds r16 = 1, r17 ;;
add r15 = r8, r14
add r15 = in1, r14
add r14 = in0, r14
mov r17 = r16 ;;
ld8 r15 = [r15] ;;
104,7 → 103,7
cmp.eq p6, p7 = 0, r15
add in0 = r14, in0
adds r15 = -1, r15
add r17 = r14, r8
add r17 = r14, in1
(p6) br.cond.dpnt 2b ;;
mov ar.lc = r15
6:
116,7 → 115,6
st1 [r15] = r14
br.cloop.sptk.few 6b ;;
mov ar.lc = r2
 
mov ar.pfs = loc0
br.ret.sptk.many rp
163,6 → 161,9
 
xor r1 = r1, r1
/* r2 is defined to hold pcb_ptr - set it to 0 */
xor r2 = r2, r2
mov loc1 = cr.ifs
movl loc2 = PFM_MASK ;;
and loc1 = loc2, loc1 ;;
/branches/tracing/kernel/arch/arm32/include/mm/page.h
43,8 → 43,6
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifndef __ASM__
# define KA2PA(x) (((uintptr_t) (x)) - 0x80000000)
# define PA2KA(x) (((uintptr_t) (x)) + 0x80000000)
/branches/tracing/kernel/arch/arm32/Makefile.inc
29,11 → 29,15
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf32-littlearm
BFD_ARCH = arm
BFD = binary
TARGET = arm-linux-gnu
TOOLCHAIN_DIR = /usr/local/arm
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm
 
KERNEL_LOAD_ADDRESS = 0x80200000
 
/branches/tracing/kernel/arch/arm32/src/asm.S
45,7 → 45,8
add r3, r1, #3
bic r3, r3, #3
cmp r1, r3
stmdb sp!, {r4, lr}
stmdb sp!, {r4, r5, lr}
mov r5, r0 /* save dst */
beq 4f
1:
cmp r2, #0
58,8 → 59,8
cmp ip, r2
bne 2b
3:
mov r0, r1
ldmia sp!, {r4, pc}
mov r0, r5
ldmia sp!, {r4, r5, pc}
4:
add r3, r0, #3
bic r3, r3, #3
94,5 → 95,5
 
memcpy_from_uspace_failover_address:
memcpy_to_uspace_failover_address:
mov r0, #0
ldmia sp!, {r4, pc}
mov r0, #0
ldmia sp!, {r4, r5, pc}
/branches/tracing/kernel/arch/arm32/src/userspace.c
70,8 → 70,11
/* set first parameter */
ustate.r0 = (uintptr_t) kernel_uarg->uspace_uarg;
 
/* %r1 is defined to hold pcb_ptr - set it to 0 */
ustate.r1 = 0;
 
/* clear other registers */
ustate.r1 = ustate.r2 = ustate.r3 = ustate.r4 = ustate.r5 =
ustate.r2 = ustate.r3 = ustate.r4 = ustate.r5 =
ustate.r6 = ustate.r7 = ustate.r8 = ustate.r9 = ustate.r10 =
ustate.r11 = ustate.r12 = ustate.lr = 0;
 
/branches/tracing/kernel/arch/ppc32/include/mm/page.h
40,8 → 40,6
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifdef KERNEL
 
#ifndef __ASM__
/branches/tracing/kernel/arch/ppc32/Makefile.inc
29,11 → 29,15
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf32-powerpc
BFD_ARCH = powerpc:common
BFD = binary
TARGET = ppc-linux-gnu
TOOLCHAIN_DIR = /usr/local/ppc
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc
 
GCC_CFLAGS += -mcpu=powerpc -msoft-float -m32
AFLAGS += -a32
/branches/tracing/kernel/arch/ppc32/src/asm.S
65,6 → 65,10
# set stack
mr sp, r4
 
# %r3 is defined to hold pcb_ptr - set it to 0
 
xor r3, r3, r3
# jump to userspace
199,47 → 203,7
rfi
memsetb:
rlwimi r5, r5, 8, 16, 23
rlwimi r5, r5, 16, 0, 15
addi r14, r3, -4
cmplwi 0, r4, 4
blt 7f
stwu r5, 4(r14)
beqlr
andi. r15, r14, 3
add r4, r15, r4
subf r14, r15, r14
srwi r15, r4, 2
mtctr r15
bdz 6f
1:
stwu r5, 4(r14)
bdnz 1b
6:
andi. r4, r4, 3
7:
cmpwi 0, r4, 0
beqlr
mtctr r4
addi r6, r6, 3
8:
stbu r5, 1(r14)
bdnz 8b
blr
b _memsetb
 
memcpy:
memcpy_from_uspace:
308,4 → 272,6
 
memcpy_from_uspace_failover_address:
memcpy_to_uspace_failover_address:
b memcpy_from_uspace_failover_address
# return zero, failure
xor r3, r3, r3
blr
/branches/tracing/kernel/arch/ppc32/src/mm/tlb.c
47,16 → 47,19
* The as->lock must be held on entry to this function
* if lock is true.
*
* @param as Address space.
* @param lock Lock/unlock the address space.
* @param badvaddr Faulting virtual address.
* @param access Access mode that caused the fault.
* @param istate Pointer to interrupted state.
* @param pfrc Pointer to variable where as_page_fault() return code will be stored.
* @return PTE on success, NULL otherwise.
* @param as Address space.
* @param lock Lock/unlock the address space.
* @param badvaddr Faulting virtual address.
* @param access Access mode that caused the fault.
* @param istate Pointer to interrupted state.
* @param pfrc Pointer to variable where as_page_fault() return code
* will be stored.
* @return PTE on success, NULL otherwise.
*
*/
static pte_t *find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access, istate_t *istate, int *pfrc)
static pte_t *
find_mapping_and_check(as_t *as, bool lock, uintptr_t badvaddr, int access,
istate_t *istate, int *pfrc)
{
/*
* Check if the mapping exists in page tables.
77,27 → 80,27
*/
page_table_unlock(as, lock);
switch (rc = as_page_fault(badvaddr, access, istate)) {
case AS_PF_OK:
/*
* The higher-level page fault handler succeeded,
* The mapping ought to be in place.
*/
page_table_lock(as, lock);
pte = page_mapping_find(as, badvaddr);
ASSERT((pte) && (pte->p));
*pfrc = 0;
return pte;
case AS_PF_DEFER:
page_table_lock(as, lock);
*pfrc = rc;
return NULL;
case AS_PF_FAULT:
page_table_lock(as, lock);
printf("Page fault.\n");
*pfrc = rc;
return NULL;
default:
panic("unexpected rc (%d)\n", rc);
case AS_PF_OK:
/*
* The higher-level page fault handler succeeded,
* The mapping ought to be in place.
*/
page_table_lock(as, lock);
pte = page_mapping_find(as, badvaddr);
ASSERT((pte) && (pte->p));
*pfrc = 0;
return pte;
case AS_PF_DEFER:
page_table_lock(as, lock);
*pfrc = rc;
return NULL;
case AS_PF_FAULT:
page_table_lock(as, lock);
printf("Page fault.\n");
*pfrc = rc;
return NULL;
default:
panic("unexpected rc (%d)\n", rc);
}
}
}
114,7 → 117,8
s = get_symtab_entry(istate->lr);
if (s)
sym2 = s;
panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2);
panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr,
istate->pc, symbol, sym2);
}
 
 
147,7 → 151,8
/* Find unused or colliding
PTE in PTEG */
for (i = 0; i < 8; i++) {
if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) && (phte[base + i].api == api))) {
if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) &&
(phte[base + i].api == api))) {
found = true;
break;
}
160,7 → 165,9
/* Find unused or colliding
PTE in PTEG */
for (i = 0; i < 8; i++) {
if ((!phte[base2 + i].v) || ((phte[base2 + i].vsid == vsid) && (phte[base2 + i].api == api))) {
if ((!phte[base2 + i].v) ||
((phte[base2 + i].vsid == vsid) &&
(phte[base2 + i].api == api))) {
found = true;
base = base2;
h = 1;
214,7 → 221,9
/* Find unused or colliding
PTE in PTEG */
for (i = 0; i < 8; i++) {
if ((!phte_physical[base + i].v) || ((phte_physical[base + i].vsid == vsid) && (phte_physical[base + i].api == api))) {
if ((!phte_physical[base + i].v) ||
((phte_physical[base + i].vsid == vsid) &&
(phte_physical[base + i].api == api))) {
found = true;
break;
}
227,7 → 236,9
/* Find unused or colliding
PTE in PTEG */
for (i = 0; i < 8; i++) {
if ((!phte_physical[base2 + i].v) || ((phte_physical[base2 + i].vsid == vsid) && (phte_physical[base2 + i].api == api))) {
if ((!phte_physical[base2 + i].v) ||
((phte_physical[base2 + i].vsid == vsid) &&
(phte_physical[base2 + i].api == api))) {
found = true;
base = base2;
h = 1;
254,8 → 265,8
 
/** Process Instruction/Data Storage Interrupt
*
* @param n Interrupt vector number.
* @param istate Interrupted register context.
* @param n Interrupt vector number.
* @param istate Interrupted register context.
*
*/
void pht_refill(int n, istate_t *istate)
284,21 → 295,22
page_table_lock(as, lock);
pte = find_mapping_and_check(as, lock, badvaddr, PF_ACCESS_READ /* FIXME */, istate, &pfrc);
pte = find_mapping_and_check(as, lock, badvaddr,
PF_ACCESS_READ /* FIXME */, istate, &pfrc);
if (!pte) {
switch (pfrc) {
case AS_PF_FAULT:
goto fail;
break;
case AS_PF_DEFER:
/*
* The page fault came during copy_from_uspace()
* or copy_to_uspace().
*/
page_table_unlock(as, lock);
return;
default:
panic("Unexpected pfrc (%d)\n", pfrc);
case AS_PF_FAULT:
goto fail;
break;
case AS_PF_DEFER:
/*
* The page fault came during copy_from_uspace()
* or copy_to_uspace().
*/
page_table_unlock(as, lock);
return;
default:
panic("Unexpected pfrc (%d)\n", pfrc);
}
}
316,8 → 328,8
 
/** Process Instruction/Data Storage Interrupt in Real Mode
*
* @param n Interrupt vector number.
* @param istate Interrupted register context.
* @param n Interrupt vector number.
* @param istate Interrupted register context.
*
*/
bool pht_real_refill(int n, istate_t *istate)
373,7 → 385,8
uint32_t i;
for (i = 0; i < 8192; i++) {
if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) && (phte[i].vsid < ((asid << 4) + 16)))
if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) &&
(phte[i].vsid < ((asid << 4) + 16)))
phte[i].v = 0;
}
tlb_invalidate_all();
407,7 → 420,11
} \
} else \
length = 0; \
printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, lower & 0xffff0000, length, mask, ((upper >> 1) & 1) ? " supervisor" : "", (upper & 1) ? " user" : "");
printf(name ": page=%.*p frame=%.*p length=%d KB (mask=%#x)%s%s\n", \
sizeof(upper) * 2, upper & 0xffff0000, sizeof(lower) * 2, \
lower & 0xffff0000, length, mask, \
((upper >> 1) & 1) ? " supervisor" : "", \
(upper & 1) ? " user" : "");
 
 
void tlb_print(void)
421,7 → 438,10
: "=r" (vsid)
: "r" (sr << 28)
);
printf("vsid[%d]: VSID=%.*p (ASID=%d)%s%s\n", sr, sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4, ((vsid >> 30) & 1) ? " supervisor" : "", ((vsid >> 29) & 1) ? " user" : "");
printf("vsid[%d]: VSID=%.*p (ASID=%d)%s%s\n", sr,
sizeof(vsid) * 2, vsid & 0xffffff, (vsid & 0xffffff) >> 4,
((vsid >> 30) & 1) ? " supervisor" : "",
((vsid >> 29) & 1) ? " user" : "");
}
uint32_t upper;
/branches/tracing/kernel/arch/ppc32/src/mm/page.c
47,13 → 47,16
 
uintptr_t hw_map(uintptr_t physaddr, size_t size)
{
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
panic("Unable to map physical memory %p (%" PRIs " bytes)", physaddr, size)
if (last_frame + ALIGN_UP(size, PAGE_SIZE) >
KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
panic("Unable to map physical memory %p (%" PRIs " bytes)",
physaddr, size)
uintptr_t virtaddr = PA2KA(last_frame);
pfn_t i;
for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++)
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE);
page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i),
physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE);
last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
/branches/tracing/kernel/arch/ia32xen/include/mm/page.h
40,8 → 40,6
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifdef KERNEL
 
#ifndef __ASM__
/branches/tracing/kernel/arch/ia32xen/Makefile.inc
29,11 → 29,15
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf32-i386
BFD_ARCH = i386
BFD = elf32-i386
TARGET = i686-pc-linux-gnu
TOOLCHAIN_DIR = /usr/local/i686
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686
 
DEFS += -DMACHINE=$(MACHINE) -D__32_BITS__
 
/branches/tracing/kernel/arch/ia32xen/src/asm.S
67,7 → 67,7
* @param MEMCPY_SRC(%esp) Source address.
* @param MEMCPY_SIZE(%esp) Size.
*
* @return MEMCPY_SRC(%esp) on success and 0 on failure.
* @return MEMCPY_DST(%esp) on success and 0 on failure.
*/
memcpy:
memcpy_from_uspace:
92,7 → 92,7
0:
movl %edx, %edi
movl %eax, %esi
movl MEMCPY_SRC(%esp), %eax /* MEMCPY_SRC(%esp), success */
movl MEMCPY_DST(%esp), %eax /* MEMCPY_DST(%esp), success */
ret
/*
/branches/tracing/kernel/arch/ia32xen/src/userspace.c
68,6 → 68,10
"pushl %3\n"
"pushl %4\n"
"movl %5, %%eax\n"
 
/* %ebx is defined to hold pcb_ptr - set it to 0 */
"xorl %%ebx, %%ebx\n"
 
"iret\n"
:
: "i" (selector(UDATA_DES) | PL_USER),
/branches/tracing/kernel/arch/amd64/include/atomic.h
108,13 → 108,13
#endif
"mov %0, %1\n"
"testq %1, %1\n"
"jnz 0b\n" /* Lightweight looping on locked spinlock */
"jnz 0b\n" /* lightweight looping on locked spinlock */
"incq %1\n" /* now use the atomic operation */
"xchgq %0, %1\n"
"testq %1, %1\n"
"jnz 0b\n"
: "+m" (val->count), "=r"(tmp)
: "+m" (val->count), "=&r" (tmp)
);
/*
* Prevent critical section code from bleeding out this way up.
/branches/tracing/kernel/arch/amd64/include/mm/page.h
52,8 → 52,6
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifdef KERNEL
 
#ifndef __ASM__
/branches/tracing/kernel/arch/amd64/Makefile.inc
29,11 → 29,15
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf64-x86-64
BFD_ARCH = i386:x86-64
BFD = binary
TARGET = amd64-linux-gnu
TOOLCHAIN_DIR = /usr/local/amd64
TOOLCHAIN_DIR = $(CROSS_PREFIX)/amd64
 
FPU_NO_CFLAGS = -mno-sse -mno-sse2
CMN1 = -m64 -mcmodel=kernel -mno-red-zone -fno-unwind-tables
/branches/tracing/kernel/arch/amd64/src/asm_utils.S
98,12 → 98,12
* @param MEMCPY_SRC Source address.
* @param MEMCPY_SIZE Number of bytes to copy.
*
* @retrun MEMCPY_SRC on success, 0 on failure.
* @retrun MEMCPY_DST on success, 0 on failure.
*/
memcpy:
memcpy_from_uspace:
memcpy_to_uspace:
movq MEMCPY_SRC, %rax
movq MEMCPY_DST, %rax
 
movq MEMCPY_SIZE, %rcx
shrq $3, %rcx /* size / 8 */
/branches/tracing/kernel/arch/amd64/src/userspace.c
61,6 → 61,8
"pushq %3\n"
"pushq %4\n"
"movq %5, %%rax\n"
/* %rdi is defined to hold pcb_ptr - set it to 0 */
"xorq %%rdi, %%rdi\n"
"iretq\n"
: :
"i" (gdtselector(UDATA_DES) | PL_USER),
/branches/tracing/kernel/arch/ppc64/include/mm/page.h
40,8 → 40,6
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifdef KERNEL
 
#ifndef __ASM__
/branches/tracing/kernel/arch/ppc64/Makefile.inc
29,11 → 29,15
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf64-powerpc
BFD_ARCH = powerpc:common64
BFD = binary
TARGET = ppc64-linux-gnu
TOOLCHAIN_DIR = /usr/local/ppc64
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc64
 
GCC_CFLAGS += -mcpu=powerpc64 -msoft-float -m64
AFLAGS += -a64
/branches/tracing/kernel/arch/ppc64/src/asm.S
66,6 → 66,10
mr sp, r4
# %r3 is defined to hold pcb_ptr - set it to 0
 
xor r3, r3, r3
 
# jump to userspace
rfi
/branches/tracing/kernel/arch/mips32/include/mm/page.h
40,8 → 40,6
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifndef __ASM__
# define KA2PA(x) (((uintptr_t) (x)) - 0x80000000)
# define PA2KA(x) (((uintptr_t) (x)) + 0x80000000)
/branches/tracing/kernel/arch/mips32/include/mm/tlb.h
35,6 → 35,9
#ifndef KERN_mips32_TLB_H_
#define KERN_mips32_TLB_H_
 
#include <arch/types.h>
#include <typedefs.h>
#include <arch/mm/asid.h>
#include <arch/exception.h>
 
#ifdef TLBCNT
46,7 → 49,13
#define TLB_WIRED 1
#define TLB_KSTACK_WIRED_INDEX 0
 
#define TLB_PAGE_MASK_16K (0x3<<13)
#define TLB_PAGE_MASK_4K (0x000 << 13)
#define TLB_PAGE_MASK_16K (0x003 << 13)
#define TLB_PAGE_MASK_64K (0x00f << 13)
#define TLB_PAGE_MASK_256K (0x03f << 13)
#define TLB_PAGE_MASK_1M (0x0ff << 13)
#define TLB_PAGE_MASK_4M (0x3ff << 13)
#define TLB_PAGE_MASK_16M (0xfff << 13)
 
#define PAGE_UNCACHED 2
#define PAGE_CACHEABLE_EXC_WRITE 5
159,6 → 168,8
extern void tlb_invalid(istate_t *istate);
extern void tlb_refill(istate_t *istate);
extern void tlb_modified(istate_t *istate);
extern void tlb_prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn);
extern void tlb_prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr);
 
#endif
 
/branches/tracing/kernel/arch/mips32/include/mm/as.h
38,7 → 38,7
#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH 0
 
#define KERNEL_ADDRESS_SPACE_START_ARCH (unsigned long) 0x80000000
#define KERNEL_ADDRESS_SPACE_END_ARCH (unsigned long) 0xffffffff
#define KERNEL_ADDRESS_SPACE_END_ARCH (unsigned long) 0x9fffffff
#define USER_ADDRESS_SPACE_START_ARCH (unsigned long) 0x00000000
#define USER_ADDRESS_SPACE_END_ARCH (unsigned long) 0x7fffffff
 
/branches/tracing/kernel/arch/mips32/include/drivers/arc.h
File deleted
/branches/tracing/kernel/arch/mips32/include/drivers/serial.h
37,6 → 37,8
 
#include <console/chardev.h>
 
#define SERIAL_ADDRESS 0x98000000
 
#define SERIAL_MAX 4
#define SERIAL_COM1 0x3f8
#define SERIAL_COM1_IRQ 4
43,16 → 45,19
#define SERIAL_COM2 0x2f8
#define SERIAL_COM2_IRQ 3
 
#define P_WRITEB(where,what) (*((volatile char *) (0xB8000000+where))=what)
#define P_READB(where) (*((volatile char *)(0xB8000000+where)))
#define P_WRITEB(where, what) (*((volatile char *) (SERIAL_ADDRESS + where)) = what)
#define P_READB(where) (*((volatile char *) (SERIAL_ADDRESS + where)))
 
#define SERIAL_READ(x) P_READB(x)
#define SERIAL_WRITE(x,c) P_WRITEB(x,c)
#define SERIAL_READ(x) P_READB(x)
#define SERIAL_WRITE(x, c) P_WRITEB(x, c)
 
/* Interrupt enable register */
#define SERIAL_READ_IER(x) (P_READB((x) + 1))
#define SERIAL_WRITE_IER(x,c) (P_WRITEB((x)+1,c))
#define SERIAL_WRITE_IER(x,c) (P_WRITEB((x) + 1, c))
 
/* Interrupt identification register */
#define SERIAL_READ_IIR(x) (P_READB((x) + 2))
 
/* Line status register */
#define SERIAL_READ_LSR(x) (P_READB((x) + 5))
#define TRANSMIT_EMPTY_BIT 5
/branches/tracing/kernel/arch/mips32/include/drivers/msim.h
35,6 → 35,11
#ifndef KERN_mips32_MSIM_H_
#define KERN_mips32_MSIM_H_
 
/** Address of devices. */
#define MSIM_VIDEORAM 0x90000000
#define MSIM_KBD_ADDRESS 0x90000000
#define MSIM_KBD_IRQ 2
 
#include <console/chardev.h>
 
void msim_console(devno_t devno);
/branches/tracing/kernel/arch/mips32/Makefile.inc
29,17 → 29,19
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_ARCH = mips
TARGET = mipsel-linux-gnu
TOOLCHAIN_DIR = /usr/local/mipsel
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel
 
KERNEL_LOAD_ADDRESS = 0x80100000
INIT_ADDRESS = 0x81000000
INIT_SIZE = 262144
 
GCC_CFLAGS += -mno-abicalls -G 0 -fno-zero-initialized-in-bss
 
DEFS += -D__32_BITS__ -DMACHINE=$(MACHINE) -DKERNEL_LOAD_ADDRESS=${KERNEL_LOAD_ADDRESS} -DINIT_ADDRESS=${INIT_ADDRESS} -DINIT_SIZE=${INIT_SIZE}
DEFS += -D__32_BITS__ -DMACHINE=$(MACHINE) -DKERNEL_LOAD_ADDRESS=${KERNEL_LOAD_ADDRESS}
 
## Compile with hierarchical page tables support.
#
56,20 → 58,6
## Accepted MACHINEs
#
 
ifeq ($(MACHINE),indy)
# GCC 4.0.1 compiled for mipsEL has problems compiling in
# BigEndian mode with the swl/swr/lwl/lwr instructions.
# We have to compile it with mips-sgi-irix5 to get it right.
BFD_NAME = elf32-bigmips
BFD = ecoff-bigmips --impure
TARGET = mips-sgi-irix5
TOOLCHAIN_DIR = /usr/local/mips/bin
KERNEL_LOAD_ADDRESS = 0x88002000
GCC_CFLAGS += -EB -DBIG_ENDIAN -DARCH_HAS_FPU -march=r4600
INIT_ADDRESS = 0
INIT_SIZE = 0
endif
ifeq ($(MACHINE),lgxemul)
BFD_NAME = elf32-tradlittlemips
BFD = binary
79,9 → 67,8
BFD_NAME = elf32-bigmips
BFD = ecoff-bigmips
TARGET = mips-sgi-irix5
TOOLCHAIN_DIR = /usr/local/mips/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin
GCC_CFLAGS += -EB -DBIG_ENDIAN -DARCH_HAS_FPU -mips3
INIT_ADDRESS = 0x81800000
endif
ifeq ($(MACHINE),simics)
# SIMICS 4kc emulation is broken, although for instructions
123,7 → 110,6
arch/$(ARCH)/src/mm/as.c \
arch/$(ARCH)/src/fpu_context.c \
arch/$(ARCH)/src/ddi/ddi.c \
arch/$(ARCH)/src/drivers/arc.c \
arch/$(ARCH)/src/drivers/msim.c \
arch/$(ARCH)/src/drivers/serial.c \
arch/$(ARCH)/src/smp/order.c
/branches/tracing/kernel/arch/mips32/src/asm.S
71,6 → 71,7
and $v0,$v0,$v1
beq $a1,$v0,3f
move $t0,$a0
move $t2,$a0 # save dst
 
0:
beq $a2,$zero,2f
86,7 → 87,7
 
2:
jr $ra
move $v0,$a1
move $v0,$t2
 
3:
addiu $v0,$a0,3
126,7 → 127,7
sb $a0,0($v1)
 
jr $ra
move $v0,$a1
move $v0,$t2
 
memcpy_from_uspace_failover_address:
memcpy_to_uspace_failover_address:
/branches/tracing/kernel/arch/mips32/src/console.c
34,18 → 34,15
 
#include <console/console.h>
#include <arch/console.h>
#include <arch/drivers/arc.h>
#include <arch/drivers/serial.h>
#include <arch/drivers/msim.h>
 
void console_init(devno_t devno)
{
if (!arc_console()) {
if (serial_init())
serial_console(devno);
else
msim_console(devno);
}
if (serial_init())
serial_console(devno);
else
msim_console(devno);
}
 
/** Acquire console back for kernel
/branches/tracing/kernel/arch/mips32/src/mips32.c
48,7 → 48,6
#include <sysinfo/sysinfo.h>
 
#include <arch/interrupt.h>
#include <arch/drivers/arc.h>
#include <console/chardev.h>
#include <arch/barrier.h>
#include <arch/debugger.h>
97,7 → 96,6
/* Initialize dispatch table */
exception_init();
arc_init();
 
/* Copy the exception vectors to the right places */
memcpy(TLB_EXC, (char *) tlb_refill_entry, EXCEPTION_JUMP_SIZE);
187,8 → 185,7
 
void arch_reboot(void)
{
if (!arc_reboot())
___halt();
___halt();
while (1)
;
/branches/tracing/kernel/arch/mips32/src/start.S
349,5 → 349,7
userspace_asm:
add $sp, $a0, 0
add $v0, $a1, 0
add $t9, $a2, 0 # Set up correct entry into PIC code
add $t9, $a2, 0 # Set up correct entry into PIC code
xor $a0, $a0, $a0 # $a0 is defined to hold pcb_ptr
# set it to 0
eret
/branches/tracing/kernel/arch/mips32/src/mm/tlb.c
47,18 → 47,14
#include <align.h>
#include <interrupt.h>
 
static void tlb_refill_fail(istate_t *istate);
static void tlb_invalid_fail(istate_t *istate);
static void tlb_modified_fail(istate_t *istate);
static void tlb_refill_fail(istate_t *);
static void tlb_invalid_fail(istate_t *);
static void tlb_modified_fail(istate_t *);
 
static pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, int *pfrc);
static pte_t *find_mapping_and_check(uintptr_t, int, istate_t *, int *);
 
static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn);
static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr);
 
/** Initialize TLB
/** Initialize TLB.
*
* Initialize TLB.
* Invalidate all entries and mark wired entries.
*/
void tlb_arch_init(void)
76,7 → 72,6
cp0_index_write(i);
tlbwi();
}
 
/*
* The kernel is going to make use of some wired
85,11 → 80,9
cp0_wired_write(TLB_WIRED);
}
 
/** Process TLB Refill Exception
/** Process TLB Refill Exception.
*
* Process TLB Refill Exception.
*
* @param istate Interrupted register context.
* @param istate Interrupted register context.
*/
void tlb_refill(istate_t *istate)
{
131,14 → 124,15
*/
pte->a = 1;
 
prepare_entry_hi(&hi, asid, badvaddr);
prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn);
tlb_prepare_entry_hi(&hi, asid, badvaddr);
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable,
pte->pfn);
 
/*
* New entry is to be inserted into TLB
*/
cp0_entry_hi_write(hi.value);
if ((badvaddr/PAGE_SIZE) % 2 == 0) {
if ((badvaddr / PAGE_SIZE) % 2 == 0) {
cp0_entry_lo0_write(lo.value);
cp0_entry_lo1_write(0);
}
157,11 → 151,9
tlb_refill_fail(istate);
}
 
/** Process TLB Invalid Exception
/** Process TLB Invalid Exception.
*
* Process TLB Invalid Exception.
*
* @param istate Interrupted register context.
* @param istate Interrupted register context.
*/
void tlb_invalid(istate_t *istate)
{
178,7 → 170,7
* Locate the faulting entry in TLB.
*/
hi.value = cp0_entry_hi_read();
prepare_entry_hi(&hi, hi.asid, badvaddr);
tlb_prepare_entry_hi(&hi, hi.asid, badvaddr);
cp0_entry_hi_write(hi.value);
tlbp();
index.value = cp0_index_read();
221,12 → 213,13
*/
pte->a = 1;
 
prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable, pte->pfn);
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->cacheable,
pte->pfn);
 
/*
* The entry is to be updated in TLB.
*/
if ((badvaddr/PAGE_SIZE) % 2 == 0)
if ((badvaddr / PAGE_SIZE) % 2 == 0)
cp0_entry_lo0_write(lo.value);
else
cp0_entry_lo1_write(lo.value);
241,11 → 234,9
tlb_invalid_fail(istate);
}
 
/** Process TLB Modified Exception
/** Process TLB Modified Exception.
*
* Process TLB Modified Exception.
*
* @param istate Interrupted register context.
* @param istate Interrupted register context.
*/
void tlb_modified(istate_t *istate)
{
262,7 → 253,7
* Locate the faulting entry in TLB.
*/
hi.value = cp0_entry_hi_read();
prepare_entry_hi(&hi, hi.asid, badvaddr);
tlb_prepare_entry_hi(&hi, hi.asid, badvaddr);
cp0_entry_hi_write(hi.value);
tlbp();
index.value = cp0_index_read();
296,12 → 287,6
}
 
/*
* Fail if the page is not writable.
*/
if (!pte->w)
goto fail;
 
/*
* Read the faulting TLB entry.
*/
tlbr();
312,12 → 297,13
pte->a = 1;
pte->d = 1;
 
prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable, pte->pfn);
tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->cacheable,
pte->pfn);
 
/*
* The entry is to be updated in TLB.
*/
if ((badvaddr/PAGE_SIZE) % 2 == 0)
if ((badvaddr / PAGE_SIZE) % 2 == 0)
cp0_entry_lo0_write(lo.value);
else
cp0_entry_lo1_write(lo.value);
344,8 → 330,10
if (s)
sym2 = s;
 
fault_if_from_uspace(istate, "TLB Refill Exception on %p", cp0_badvaddr_read());
panic("%x: TLB Refill Exception at %x(%s<-%s)\n", cp0_badvaddr_read(), istate->epc, symbol, sym2);
fault_if_from_uspace(istate, "TLB Refill Exception on %p",
cp0_badvaddr_read());
panic("%x: TLB Refill Exception at %x(%s<-%s)\n", cp0_badvaddr_read(),
istate->epc, symbol, sym2);
}
 
 
356,8 → 344,10
char *s = get_symtab_entry(istate->epc);
if (s)
symbol = s;
fault_if_from_uspace(istate, "TLB Invalid Exception on %p", cp0_badvaddr_read());
panic("%x: TLB Invalid Exception at %x(%s)\n", cp0_badvaddr_read(), istate->epc, symbol);
fault_if_from_uspace(istate, "TLB Invalid Exception on %p",
cp0_badvaddr_read());
panic("%x: TLB Invalid Exception at %x(%s)\n", cp0_badvaddr_read(),
istate->epc, symbol);
}
 
void tlb_modified_fail(istate_t *istate)
367,23 → 357,27
char *s = get_symtab_entry(istate->epc);
if (s)
symbol = s;
fault_if_from_uspace(istate, "TLB Modified Exception on %p", cp0_badvaddr_read());
panic("%x: TLB Modified Exception at %x(%s)\n", cp0_badvaddr_read(), istate->epc, symbol);
fault_if_from_uspace(istate, "TLB Modified Exception on %p",
cp0_badvaddr_read());
panic("%x: TLB Modified Exception at %x(%s)\n", cp0_badvaddr_read(),
istate->epc, symbol);
}
 
/** Try to find PTE for faulting address
/** Try to find PTE for faulting address.
*
* Try to find PTE for faulting address.
* The AS->lock must be held on entry to this function.
*
* @param badvaddr Faulting virtual address.
* @param access Access mode that caused the fault.
* @param istate Pointer to interrupted state.
* @param pfrc Pointer to variable where as_page_fault() return code will be stored.
* @param badvaddr Faulting virtual address.
* @param access Access mode that caused the fault.
* @param istate Pointer to interrupted state.
* @param pfrc Pointer to variable where as_page_fault() return code
* will be stored.
*
* @return PTE on success, NULL otherwise.
* @return PTE on success, NULL otherwise.
*/
pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate, int *pfrc)
pte_t *
find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate,
int *pfrc)
{
entry_hi_t hi;
pte_t *pte;
402,7 → 396,7
* Check if the mapping exists in page tables.
*/
pte = page_mapping_find(AS, badvaddr);
if (pte && pte->p) {
if (pte && pte->p && (pte->w || access != PF_ACCESS_WRITE)) {
/*
* Mapping found in page tables.
* Immediately succeed.
425,6 → 419,7
page_table_lock(AS, true);
pte = page_mapping_find(AS, badvaddr);
ASSERT(pte && pte->p);
ASSERT(pte->w || access != PF_ACCESS_WRITE);
return pte;
break;
case AS_PF_DEFER:
445,7 → 440,9
}
}
 
void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, uintptr_t pfn)
void
tlb_prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable,
uintptr_t pfn)
{
lo->value = 0;
lo->g = g;
455,7 → 452,7
lo->pfn = pfn;
}
 
void prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr)
void tlb_prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr)
{
hi->value = ALIGN_DOWN(addr, PAGE_SIZE * 2);
hi->asid = asid;
484,10 → 481,10
lo1.value = cp0_entry_lo1_read();
printf("%-2u %-4u %#6x %#4x %1u %1u %1u %1u %#6x\n",
i, hi.asid, hi.vpn2, mask.mask,
lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn);
i, hi.asid, hi.vpn2, mask.mask,
lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn);
printf(" %1u %1u %1u %1u %#6x\n",
lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn);
lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn);
}
cp0_entry_hi_write(hi_save.value);
564,11 → 561,12
cp0_entry_hi_write(hi_save.value);
}
 
/** Invalidate TLB entries for specified page range belonging to specified address space.
/** Invalidate TLB entries for specified page range belonging to specified
* address space.
*
* @param asid Address space identifier.
* @param page First page whose TLB entry is to be invalidated.
* @param cnt Number of entries to invalidate.
* @param asid Address space identifier.
* @param page First page whose TLB entry is to be invalidated.
* @param cnt Number of entries to invalidate.
*/
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
{
585,7 → 583,7
 
for (i = 0; i < cnt + 1; i += 2) {
hi.value = 0;
prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE);
tlb_prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE);
cp0_entry_hi_write(hi.value);
 
tlbp();
592,7 → 590,10
index.value = cp0_index_read();
 
if (!index.p) {
/* Entry was found, index register contains valid index. */
/*
* Entry was found, index register contains valid
* index.
*/
tlbr();
 
lo0.value = cp0_entry_lo0_read();
/branches/tracing/kernel/arch/mips32/src/mm/as.c
44,7 → 44,7
/** Architecture dependent address space init. */
void as_arch_init(void)
{
as_operations = &as_pt_operations;
as_operations = &as_pt_operations;
asid_fifo_init();
}
 
/branches/tracing/kernel/arch/mips32/src/mm/frame.c
32,27 → 32,238
/** @file
*/
 
#include <macros.h>
#include <arch/mm/frame.h>
#include <arch/mm/tlb.h>
#include <interrupt.h>
#include <mm/frame.h>
#include <mm/asid.h>
#include <config.h>
#include <arch/drivers/arc.h>
#include <arch/drivers/msim.h>
#include <arch/drivers/serial.h>
#include <print.h>
 
#define ZERO_PAGE_MASK TLB_PAGE_MASK_256K
#define ZERO_FRAMES 2048
#define ZERO_PAGE_WIDTH 18 /* 256K */
#define ZERO_PAGE_SIZE (1 << ZERO_PAGE_WIDTH)
#define ZERO_PAGE_ASID ASID_INVALID
#define ZERO_PAGE_TLBI 0
#define ZERO_PAGE_ADDR 0
#define ZERO_PAGE_OFFSET (ZERO_PAGE_SIZE / sizeof(uint32_t) - 1)
#define ZERO_PAGE_VALUE (((volatile uint32_t *) ZERO_PAGE_ADDR)[ZERO_PAGE_OFFSET])
 
#define ZERO_PAGE_VALUE_KSEG1(frame) (((volatile uint32_t *) (0xa0000000 + (frame << ZERO_PAGE_WIDTH)))[ZERO_PAGE_OFFSET])
 
#define MAX_REGIONS 32
 
typedef struct {
pfn_t start;
pfn_t count;
} phys_region_t;
 
static count_t phys_regions_count = 0;
static phys_region_t phys_regions[MAX_REGIONS];
 
 
/** Check whether frame is available
*
* Returns true if given frame is generally available for use.
* Returns false if given frame is used for physical memory
* mapped devices and cannot be used.
*
*/
static bool frame_available(pfn_t frame)
{
#if MACHINE == msim
/* MSIM device (dprinter) */
if (frame == (KA2PA(MSIM_VIDEORAM) >> ZERO_PAGE_WIDTH))
return false;
/* MSIM device (dkeyboard) */
if (frame == (KA2PA(MSIM_KBD_ADDRESS) >> ZERO_PAGE_WIDTH))
return false;
#endif
 
#if MACHINE == simics
/* Simics device (serial line) */
if (frame == (KA2PA(SERIAL_ADDRESS) >> ZERO_PAGE_WIDTH))
return false;
#endif
 
#if (MACHINE == lgxemul) || (MACHINE == bgxemul)
/* gxemul devices */
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
0x10000000, MB2SIZE(256)))
return false;
#endif
return true;
}
 
 
/** Check whether frame is safe to write
*
* Returns true if given frame is safe for read/write test.
* Returns false if given frame should not be touched.
*
*/
static bool frame_safe(pfn_t frame)
{
/* Kernel structures */
if ((frame << ZERO_PAGE_WIDTH) < KA2PA(config.base))
return false;
/* Kernel */
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
KA2PA(config.base), config.kernel_size))
return false;
/* Kernel stack */
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
KA2PA(config.stack_base), config.stack_size))
return false;
/* Init tasks */
bool safe = true;
count_t i;
for (i = 0; i < init.cnt; i++)
if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
KA2PA(init.tasks[i].addr), init.tasks[i].size)) {
safe = false;
break;
}
return safe;
}
 
static void frame_add_region(pfn_t start_frame, pfn_t end_frame)
{
if (end_frame > start_frame) {
/* Convert 1M frames to 16K frames */
pfn_t first = ADDR2PFN(start_frame << ZERO_PAGE_WIDTH);
pfn_t count = ADDR2PFN((end_frame - start_frame) << ZERO_PAGE_WIDTH);
/* Interrupt vector frame is blacklisted */
pfn_t conf_frame;
if (first == 0)
conf_frame = 1;
else
conf_frame = first;
zone_create(first, count, conf_frame, 0);
if (phys_regions_count < MAX_REGIONS) {
phys_regions[phys_regions_count].start = first;
phys_regions[phys_regions_count].count = count;
phys_regions_count++;
}
}
}
 
 
/** Create memory zones
*
* If ARC is known, read information from ARC, otherwise
* assume some defaults.
* - blacklist first FRAME because there is an exception vector
* Walk through available 256 KB chunks of physical
* memory and create zones.
*
* Note: It is assumed that the TLB is not yet being
* used in any way, thus there is no interference.
*
*/
void frame_arch_init(void)
{
if (!arc_frame_init()) {
zone_create(0, ADDR2PFN(CONFIG_MEMORY_SIZE), 1, 0);
/*
* Blacklist interrupt vector
*/
frame_mark_unavailable(0, 1);
ipl_t ipl = interrupts_disable();
/* Clear and initialize TLB */
cp0_pagemask_write(ZERO_PAGE_MASK);
cp0_entry_lo0_write(0);
cp0_entry_lo1_write(0);
cp0_entry_hi_write(0);
 
count_t i;
for (i = 0; i < TLB_ENTRY_COUNT; i++) {
cp0_index_write(i);
tlbwi();
}
pfn_t start_frame = 0;
pfn_t frame;
bool avail = true;
/* Walk through all 1 MB frames */
for (frame = 0; frame < ZERO_FRAMES; frame++) {
if (!frame_available(frame))
avail = false;
else {
if (frame_safe(frame)) {
entry_lo_t lo0;
entry_lo_t lo1;
entry_hi_t hi;
tlb_prepare_entry_lo(&lo0, false, true, true, false, frame << (ZERO_PAGE_WIDTH - 12));
tlb_prepare_entry_lo(&lo1, false, false, false, false, 0);
tlb_prepare_entry_hi(&hi, ZERO_PAGE_ASID, ZERO_PAGE_ADDR);
cp0_pagemask_write(ZERO_PAGE_MASK);
cp0_entry_lo0_write(lo0.value);
cp0_entry_lo1_write(lo1.value);
cp0_entry_hi_write(hi.value);
cp0_index_write(ZERO_PAGE_TLBI);
tlbwi();
ZERO_PAGE_VALUE = 0;
if (ZERO_PAGE_VALUE != 0)
avail = false;
else {
ZERO_PAGE_VALUE = 0xdeadbeef;
if (ZERO_PAGE_VALUE != 0xdeadbeef)
avail = false;
#if (MACHINE == lgxemul) || (MACHINE == bgxemul)
else {
ZERO_PAGE_VALUE_KSEG1(frame) = 0xaabbccdd;
if (ZERO_PAGE_VALUE_KSEG1(frame) != 0xaabbccdd)
avail = false;
}
#endif
}
}
}
if (!avail) {
frame_add_region(start_frame, frame);
start_frame = frame + 1;
avail = true;
}
}
frame_add_region(start_frame, frame);
/* Blacklist interrupt vector frame */
frame_mark_unavailable(0, 1);
/* Cleanup */
cp0_pagemask_write(ZERO_PAGE_MASK);
cp0_entry_lo0_write(0);
cp0_entry_lo1_write(0);
cp0_entry_hi_write(0);
cp0_index_write(ZERO_PAGE_TLBI);
tlbwi();
interrupts_restore(ipl);
}
 
 
void physmem_print(void)
{
printf("Base Size\n");
printf("---------- ----------\n");
count_t i;
for (i = 0; i < phys_regions_count; i++) {
printf("%#010x %10u\n",
PFN2ADDR(phys_regions[i].start), PFN2ADDR(phys_regions[i].count));
}
}
 
/** @}
*/
/branches/tracing/kernel/arch/mips32/src/interrupt.c
38,7 → 38,6
#include <arch.h>
#include <arch/cp0.h>
#include <time/clock.h>
#include <arch/drivers/arc.h>
#include <ipc/sysipc.h>
#include <ddi/device.h>
 
/branches/tracing/kernel/arch/mips32/src/drivers/arc.c
File deleted
/branches/tracing/kernel/arch/mips32/src/drivers/msim.c
39,12 → 39,9
#include <arch/cp0.h>
#include <console/console.h>
#include <sysinfo/sysinfo.h>
#include <ddi/ddi.h>
 
/** Address of devices. */
#define MSIM_VIDEORAM 0xB0000000
#define MSIM_KBD_ADDRESS 0xB0000000
#define MSIM_KBD_IRQ 2
 
static parea_t msim_parea;
static chardev_t console;
static irq_t msim_irq;
 
158,6 → 155,16
sysinfo_set_item_val("kbd.devno", NULL, devno);
sysinfo_set_item_val("kbd.inr", NULL, MSIM_KBD_IRQ);
sysinfo_set_item_val("kbd.address.virtual", NULL, MSIM_KBD_ADDRESS);
msim_parea.pbase = KA2PA(MSIM_VIDEORAM);
msim_parea.vbase = MSIM_VIDEORAM;
msim_parea.frames = 1;
msim_parea.cacheable = false;
ddi_parea_register(&msim_parea);
sysinfo_set_item_val("fb", NULL, true);
sysinfo_set_item_val("fb.kind", NULL, 3);
sysinfo_set_item_val("fb.address.physical", NULL, KA2PA(MSIM_VIDEORAM));
}
 
/** @}
/branches/tracing/kernel/arch/ia32/include/atomic.h
113,7 → 113,7
"xchgl %0, %1\n"
"testl %1, %1\n"
"jnz 0b\n"
: "+m" (val->count), "=r"(tmp)
: "+m" (val->count), "=&r"(tmp)
);
/*
* Prevent critical section code from bleeding out this way up.
/branches/tracing/kernel/arch/ia32/include/mm/page.h
40,8 → 40,6
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
 
#define PAGE_COLOR_BITS 0 /* dummy */
 
#ifdef KERNEL
 
#ifndef __ASM__
/branches/tracing/kernel/arch/ia32/Makefile.inc
29,11 → 29,15
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf32-i386
BFD_ARCH = i386
BFD = binary
TARGET = i686-pc-linux-gnu
TOOLCHAIN_DIR = /usr/local/i686
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686
 
DEFS += -DMACHINE=$(MACHINE) -D__32_BITS__
 
74,7 → 78,7
CONFIG_HT = n
endif
ifeq ($(MACHINE),core)
FPU_NO_CFLAGS = -mno-mmmx -mno-sse -mno-sse2 -mno-sse3
FPU_NO_CFLAGS = -mno-mmx -mno-sse -mno-sse2 -mno-sse3
CMN2 = -march=prescott
GCC_CFLAGS += $(CMN2)
ICC_CFLAGS += $(CMN2)
/branches/tracing/kernel/arch/ia32/src/asm.S
71,7 → 71,7
* @param MEMCPY_SRC(%esp) Source address.
* @param MEMCPY_SIZE(%esp) Size.
*
* @return MEMCPY_SRC(%esp) on success and 0 on failure.
* @return MEMCPY_DST(%esp) on success and 0 on failure.
*/
memcpy:
memcpy_from_uspace:
96,7 → 96,7
0:
movl %edx, %edi
movl %eax, %esi
movl MEMCPY_SRC(%esp), %eax /* MEMCPY_SRC(%esp), success */
movl MEMCPY_DST(%esp), %eax /* MEMCPY_DST(%esp), success */
ret
/*
/branches/tracing/kernel/arch/ia32/src/smp/smp.c
155,7 → 155,7
* Prepare new GDT for CPU in question.
*/
gdt_new = (struct descriptor *) malloc(GDT_ITEMS *
sizeof(struct descriptor), FRAME_ATOMIC);
sizeof(struct descriptor), FRAME_ATOMIC | FRAME_LOW_4_GiB);
if (!gdt_new)
panic("couldn't allocate memory for GDT\n");
 
/branches/tracing/kernel/arch/ia32/src/mm/as.c
39,9 → 39,7
/** Architecture dependent address space init. */
void as_arch_init(void)
{
#ifndef __OBJC__
as_operations = &as_pt_operations;
#endif
}
 
/** @}
/branches/tracing/kernel/arch/ia32/src/userspace.c
70,6 → 70,10
"pushl %3\n"
"pushl %4\n"
"movl %5, %%eax\n"
 
/* %ebx is defined to hold pcb_ptr - set it to 0 */
"xorl %%ebx, %%ebx\n"
 
"iret\n"
:
: "i" (selector(UDATA_DES) | PL_USER),
/branches/tracing/kernel/arch/ia32/src/drivers/ega.c
93,12 → 93,6
sysinfo_set_item_val("fb.width", NULL, ROW);
sysinfo_set_item_val("fb.height", NULL, ROWS);
sysinfo_set_item_val("fb.address.physical", NULL, VIDEORAM);
sysinfo_set_item_val("fb.address.color", NULL, PAGE_COLOR((uintptr_t)
videoram));
#ifndef CONFIG_FB
putchar('\n');
#endif
}
 
static void ega_display_char(char ch)
/branches/tracing/tools/xstruct.py
0,0 → 1,110
#
# Copyright (c) 2008 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""
Convert descriptive structure definitions to structure object
"""
 
import struct
 
class Struct:
def size(self):
return struct.calcsize(self._format_)
def pack(self):
args = []
for variable in self._args_:
if (isinstance(self.__dict__[variable], list)):
for item in self.__dict__[variable]:
args.append(item)
else:
args.append(self.__dict__[variable])
return struct.pack(self._format_, *args)
 
def create(definition):
"Create structure object"
tokens = definition.split(None)
# Initial byte order tag
format = {
"little:": lambda: "<",
"big:": lambda: ">",
"network:": lambda: "!"
}[tokens[0]]()
inst = Struct()
args = []
# Member tags
comment = False
variable = None
for token in tokens[1:]:
if (comment):
if (token == "*/"):
comment = False
continue
if (token == "/*"):
comment = True
continue
if (variable != None):
subtokens = token.split("[")
if (len(subtokens) > 1):
format += "%d" % int(subtokens[1].split("]")[0])
format += variable
inst.__dict__[subtokens[0]] = None
args.append(subtokens[0])
variable = None
continue
if (token[0:8] == "padding["):
size = token[8:].split("]")[0]
format += "%dx" % int(size)
continue
variable = {
"char": lambda: "s",
"uint8_t": lambda: "B",
"uint16_t": lambda: "H",
"uint32_t": lambda: "L",
"uint64_t": lambda: "Q",
"int8_t": lambda: "b",
"int16_t": lambda: "h",
"int32_t": lambda: "l",
"int64_t": lambda: "q"
}[token]()
inst.__dict__['_format_'] = format
inst.__dict__['_args_'] = args
return inst
/branches/tracing/tools/mktmpfs.py
32,84 → 32,105
 
import sys
import os
import struct
import xstruct
 
def align_up(size, alignment):
"Align upwards to a given alignment"
return (((size) + ((alignment) - 1)) & ~((alignment) - 1))
HEADER = """little:
char tag[5] /* 'TMPFS' */
"""
 
DENTRY_NONE = """little:
uint8_t kind /* NONE */
uint32_t fname_len /* 0 */
"""
 
DENTRY_FILE = """little:
uint8_t kind /* FILE */
uint32_t fname_len /* filename length */
char fname[%d] /* filename */
uint32_t flen /* file length */
"""
 
DENTRY_DIRECTORY = """little:
uint8_t kind /* DIRECTORY */
uint32_t fname_len /* filename length */
char fname[%d] /* filename */
"""
 
TMPFS_NONE = 0
TMPFS_FILE = 1
TMPFS_DIRECTORY = 2
 
def usage(prname):
"Print usage syntax"
print prname + " <ALIGNMENT> <PATH> <IMAGE>"
print prname + " <PATH> <IMAGE>"
 
def recursion(root, outf):
"Recursive directory walk"
payload_size = 0
for name in os.listdir(root):
canon = os.path.join(root, name)
if (os.path.isfile(canon)):
outf.write(struct.pack("<BL" + ("%d" % len(name)) + "s", 1, len(name), name))
payload_size += 5 + len(name)
size = os.path.getsize(canon)
rd = 0;
outf.write(struct.pack("<L", size))
payload_size += 4
dentry = xstruct.create(DENTRY_FILE % len(name))
dentry.kind = TMPFS_FILE
dentry.fname_len = len(name)
dentry.fname = name
dentry.flen = size
outf.write(dentry.pack())
inf = file(canon, "r")
rd = 0;
while (rd < size):
data = inf.read(4096);
outf.write(data)
payload_size += len(data)
rd += len(data)
inf.close()
if (os.path.isdir(canon)):
outf.write(struct.pack("<BL" + ("%d" % len(name)) + "s", 2, len(name), name))
payload_size += 5 + len(name)
payload_size += recursion(canon, outf)
outf.write(struct.pack("<BL", 0, 0))
payload_size += 5
return payload_size
dentry = xstruct.create(DENTRY_DIRECTORY % len(name))
dentry.kind = TMPFS_DIRECTORY
dentry.fname_len = len(name)
dentry.fname = name
outf.write(dentry.pack())
recursion(canon, outf)
dentry = xstruct.create(DENTRY_NONE)
dentry.kind = TMPFS_NONE
dentry.fname_len = 0
outf.write(dentry.pack())
 
def main():
if (len(sys.argv) < 4):
if (len(sys.argv) < 3):
usage(sys.argv[0])
return
if (not sys.argv[1].isdigit()):
print "<ALIGNMENT> must be a number"
return
align = int(sys.argv[1], 0)
path = os.path.abspath(sys.argv[2])
path = os.path.abspath(sys.argv[1])
if (not os.path.isdir(path)):
print "<PATH> must be a directory"
return
header_size = align_up(18, align)
outf = file(sys.argv[3], "w")
outf.write(struct.pack("<" + ("%d" % header_size) + "x"))
outf = file(sys.argv[2], "w")
outf.write(struct.pack("<5s", "TMPFS"))
payload_size = 5
header = xstruct.create(HEADER)
header.tag = "TMPFS"
payload_size += recursion(path, outf)
outf.write(struct.pack("<BL", 0, 0))
payload_size += 5
outf.write(header.pack())
aligned_size = align_up(payload_size, align)
recursion(path, outf)
if (aligned_size - payload_size > 0):
outf.write(struct.pack("<" + ("%d" % (aligned_size - payload_size)) + "x"))
outf.seek(0)
outf.write(struct.pack("<4sBBLQ", "HORD", 1, 1, header_size, aligned_size))
dentry = xstruct.create(DENTRY_NONE)
dentry.kind = TMPFS_NONE
dentry.fname_len = 0
outf.write(dentry.pack())
outf.close()
 
if __name__ == '__main__':
main()
/branches/tracing/tools/mkfat.py
0,0 → 1,109
#!/usr/bin/env python
#
# Copyright (c) 2008 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""
FAT creator
"""
 
import sys
import os
import random
import xstruct
 
BOOT_SECTOR = """little:
uint8_t jmp[3] /* jump instruction */
char oem[8] /* OEM string */
uint16_t sector /* bytes per sector */
uint8_t cluster /* sectors per cluster */
uint16_t reserved /* reserved sectors */
uint8_t fats /* number of FATs */
uint16_t rootdir /* root directory entries */
uint16_t sectors /* total number of sectors */
uint8_t descriptor /* media descriptor */
uint16_t fat_sectors /* sectors per single FAT */
uint16_t track_sectors /* sectors per track */
uint16_t heads /* number of heads */
uint32_t hidden /* hidden sectors */
uint32_t sectors_big /* total number of sectors (if sectors == 0) */
/* Extended BIOS Parameter Block */
uint8_t drive /* physical drive number */
padding[1] /* reserved (current head) */
uint8_t extboot_signature /* extended boot signature */
uint32_t serial /* serial number */
char label[11] /* volume label */
char fstype[8] /* filesystem type */
padding[448] /* boot code */
uint8_t boot_signature[2] /* boot signature */
"""
 
def usage(prname):
"Print usage syntax"
print prname + " <PATH> <IMAGE>"
 
def main():
if (len(sys.argv) < 3):
usage(sys.argv[0])
return
path = os.path.abspath(sys.argv[1])
if (not os.path.isdir(path)):
print "<PATH> must be a directory"
return
outf = file(sys.argv[2], "w")
boot_sector = xstruct.create(BOOT_SECTOR)
boot_sector.jmp = [0xEB, 0x3C, 0x90]
boot_sector.oem = "MSDOS5.0"
boot_sector.sector = 512
boot_sector.cluster = 8 # 4096 bytes per cluster
boot_sector.reserved = 1
boot_sector.fats = 2
boot_sector.rootdir = 224 # FIXME: root directory should be sector aligned
boot_sector.sectors = 0 # FIXME
boot_sector.descriptor = 0xF8
boot_sector.fat_sectors = 0 # FIXME
boot_sector.track_sectors = 0 # FIXME
boot_sector.heads = 0 # FIXME
boot_sector.hidden = 0
boot_sector.sectors_big = 0 # FIXME
boot_sector.drive = 0
boot_sector.extboot_signature = 0x29
boot_sector.serial = random.randint(0, 0xFFFFFFFF)
boot_sector.label = "HELENOS"
boot_sector.fstype = "FAT16 "
boot_sector.boot_signature = [0x55, 0xAA]
outf.write(boot_sector.pack())
outf.close()
if __name__ == '__main__':
main()
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/tracing/tools/mkfat.sh
0,0 → 1,73
#!/bin/bash
#
# Copyright (c) 2008 Jakub Jermar
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
MFORMAT=`which mformat`
MCOPY=`which mcopy`
 
if [ `which mformat` == "" ]; then
echo "Please install mtools."
exit 1
fi
 
if [ `which mcopy` == "" ]; then
echo "Please install mtools."
exit 1
fi
 
if [ $# -ne 2 ]; then
echo "Usage: $0 <PATH> <IMAGE>"
exit 1
fi
 
if [ ! -d $1 ]; then
echo "Usage: $0 <PATH> <IMAGE>"
exit 1
fi
 
BPS=512
SPC=4
FAT16_MIN_SEC=$((4085 * $SPC))
HEADS=2
TRACKS=16
BYTES=`du -sb $1 | cut -f 1`
SECTORS=$(($BYTES / $BPS))
SPTPH=$((($SECTORS + $FAT16_MIN_SEC) / ($HEADS * $TRACKS)))
 
# Format the image as FAT16
$MFORMAT -h $HEADS -t $TRACKS -s $SPTPH -M $BPS -c $SPC -v "FAT16HORD" -B /dev/zero -C -i $2 ::
 
if [ $? -ne 0 ]; then
echo "$MFORMAT failed: $?"
exit $?
fi
 
# Copy the subtree to the image
$MCOPY -vspQmi $2 $1/* ::
 
exit $?
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/tracing/tools/mkhord.py
0,0 → 1,104
#!/usr/bin/env python
#
# Copyright (c) 2008 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
"""
HORD encapsulator
"""
 
import sys
import os
import xstruct
 
HEADER = """little:
char tag[4] /* 'HORD' */
uint8_t version /* version */
uint8_t encoding /* encoding */
uint32_t header_size /* header size */
uint64_t payload_size /* payload size */
"""
 
HORD_LSB = 1
 
def align_up(size, alignment):
"Align upwards to a given alignment"
return (((size) + ((alignment) - 1)) & ~((alignment) - 1))
 
def usage(prname):
"Print usage syntax"
print prname + " <ALIGNMENT> <FS_IMAGE> <HORD_IMAGE>"
 
def main():
if (len(sys.argv) < 4):
usage(sys.argv[0])
return
if (not sys.argv[1].isdigit()):
print "<ALIGNMENT> must be a number"
return
align = int(sys.argv[1], 0)
if (align <= 0):
print "<ALIGNMENT> must be positive"
return
fs_image = os.path.abspath(sys.argv[2])
if (not os.path.isfile(fs_image)):
print "<FS_IMAGE> must be a file"
return
inf = file(fs_image, "rb")
outf = file(sys.argv[3], "wb")
header = xstruct.create(HEADER)
header_size = header.size()
payload_size = os.path.getsize(fs_image)
header_size_aligned = align_up(header_size, align)
payload_size_aligned = align_up(payload_size, align)
header.tag = "HORD"
header.version = 1
header.encoding = HORD_LSB
header.header_size = header_size_aligned
header.payload_size = payload_size_aligned
outf.write(header.pack())
outf.write(xstruct.create("little: padding[%d]" % (header_size_aligned - header_size)).pack())
outf.write(inf.read())
padding = payload_size_aligned - payload_size
if (padding > 0):
outf.write(xstruct.create("little: padding[%d]" % padding).pack())
inf.close()
outf.close()
 
if __name__ == '__main__':
main()
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/tracing/uspace/app/ash/lex.yy.c
File deleted
/branches/tracing/uspace/app/ash/arith_lex.l
File deleted
/branches/tracing/uspace/app/ash/sh.1
File deleted
/branches/tracing/uspace/app/ash/Makefile
File deleted
/branches/tracing/uspace/app/ash/funcs/suspend
File deleted
/branches/tracing/uspace/app/ash/funcs/dirs
File deleted
/branches/tracing/uspace/app/ash/funcs/popd
File deleted
/branches/tracing/uspace/app/ash/funcs/newgrp
File deleted
/branches/tracing/uspace/app/ash/funcs/pushd
File deleted
/branches/tracing/uspace/app/ash/funcs/cmv
File deleted
/branches/tracing/uspace/app/ash/funcs/login
File deleted
/branches/tracing/uspace/app/ash/funcs/kill
File deleted
/branches/tracing/uspace/app/ash/input.c
File deleted
/branches/tracing/uspace/app/ash/input.h
File deleted
/branches/tracing/uspace/app/ash/redir.c
File deleted
/branches/tracing/uspace/app/ash/arith.c
File deleted
/branches/tracing/uspace/app/ash/TOUR
File deleted
/branches/tracing/uspace/app/ash/redir.h
File deleted
/branches/tracing/uspace/app/ash/mktokens
File deleted
/branches/tracing/uspace/app/ash/arith.h
File deleted
/branches/tracing/uspace/app/ash/miscbltin.c
File deleted
/branches/tracing/uspace/app/ash/exec.c
File deleted
/branches/tracing/uspace/app/ash/cd.c
File deleted
/branches/tracing/uspace/app/ash/var.c
File deleted
/branches/tracing/uspace/app/ash/miscbltin.h
File deleted
/branches/tracing/uspace/app/ash/memalloc.c
File deleted
/branches/tracing/uspace/app/ash/exec.h
File deleted
/branches/tracing/uspace/app/ash/cd.h
File deleted
/branches/tracing/uspace/app/ash/options.c
File deleted
/branches/tracing/uspace/app/ash/parser.c
File deleted
/branches/tracing/uspace/app/ash/var.h
File deleted
/branches/tracing/uspace/app/ash/arith.y
File deleted
/branches/tracing/uspace/app/ash/jobs.c
File deleted
/branches/tracing/uspace/app/ash/memalloc.h
File deleted
/branches/tracing/uspace/app/ash/setmode.c
File deleted
/branches/tracing/uspace/app/ash/options.h
File deleted
/branches/tracing/uspace/app/ash/output.c
File deleted
/branches/tracing/uspace/app/ash/parser.h
File deleted
/branches/tracing/uspace/app/ash/jobs.h
File deleted
/branches/tracing/uspace/app/ash/output.h
File deleted
/branches/tracing/uspace/app/ash/builtins.def
File deleted
/branches/tracing/uspace/app/ash/mystring.c
File deleted
/branches/tracing/uspace/app/ash/histedit.c
File deleted
/branches/tracing/uspace/app/ash/tags
File deleted
/branches/tracing/uspace/app/ash/tools/mkinit.c
File deleted
/branches/tracing/uspace/app/ash/tools/Makefile
File deleted
/branches/tracing/uspace/app/ash/tools/mksyntax.c
File deleted
/branches/tracing/uspace/app/ash/tools/mksignames.c
File deleted
/branches/tracing/uspace/app/ash/tools/mknodes.c
File deleted
/branches/tracing/uspace/app/ash/show.c
File deleted
/branches/tracing/uspace/app/ash/mystring.h
File deleted
/branches/tracing/uspace/app/ash/show.h
File deleted
/branches/tracing/uspace/app/ash/myhistedit.h
File deleted
/branches/tracing/uspace/app/ash/nodetypes
File deleted
/branches/tracing/uspace/app/ash/error.c
File deleted
/branches/tracing/uspace/app/ash/error.h
File deleted
/branches/tracing/uspace/app/ash/trap.c
File deleted
/branches/tracing/uspace/app/ash/machdep.h
File deleted
/branches/tracing/uspace/app/ash/hetio.c
File deleted
/branches/tracing/uspace/app/ash/trap.h
File deleted
/branches/tracing/uspace/app/ash/shell.h
File deleted
/branches/tracing/uspace/app/ash/hetio.h
File deleted
/branches/tracing/uspace/app/ash/expand.c
File deleted
/branches/tracing/uspace/app/ash/mail.c
File deleted
/branches/tracing/uspace/app/ash/expand.h
File deleted
/branches/tracing/uspace/app/ash/main.c
File deleted
/branches/tracing/uspace/app/ash/mail.h
File deleted
/branches/tracing/uspace/app/ash/eval.c
File deleted
/branches/tracing/uspace/app/ash/bltin/echo.c
File deleted
/branches/tracing/uspace/app/ash/bltin/test.c
File deleted
/branches/tracing/uspace/app/ash/bltin/times.c
File deleted
/branches/tracing/uspace/app/ash/bltin/echo.1
File deleted
/branches/tracing/uspace/app/ash/bltin/bltin.h
File deleted
/branches/tracing/uspace/app/ash/alias.c
File deleted
/branches/tracing/uspace/app/ash/main.h
File deleted
/branches/tracing/uspace/app/ash/nodes.c.pat
File deleted
/branches/tracing/uspace/app/ash/eval.h
File deleted
/branches/tracing/uspace/app/ash/alias.h
File deleted
/branches/tracing/uspace/app/ash/mkbuiltins
File deleted
/branches/tracing/uspace/app/ash/fake.c
File deleted
/branches/tracing/uspace/app/ash/init.h
File deleted
/branches/tracing/uspace/app/ash/fake.h
File deleted
/branches/tracing/uspace/app/bdsh/cmds/modules/cp/cp.c
0,0 → 1,73
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include "util.h"
#include "errors.h"
#include "entry.h"
#include "cp.h"
#include "cmds.h"
 
static char *cmdname = "cp";
 
/* Dispays help for cp in various levels */
void help_cmd_cp(unsigned int level)
{
printf("This is the %s help for '%s'.\n",
level ? EXT_HELP : SHORT_HELP, cmdname);
return;
}
 
/* Main entry point for cp, accepts an array of arguments */
int cmd_cp(char **argv)
{
unsigned int argc;
unsigned int i;
 
/* Count the arguments */
for (argc = 0; argv[argc] != NULL; argc ++);
 
printf("%s %s\n", TEST_ANNOUNCE, cmdname);
printf("%d arguments passed to %s", argc - 1, cmdname);
 
if (argc < 2) {
printf("\n");
return CMD_SUCCESS;
}
 
printf(":\n");
for (i = 1; i < argc; i++)
printf("[%d] -> %s\n", i, argv[i]);
 
return CMD_SUCCESS;
}
 
/branches/tracing/uspace/app/bdsh/cmds/modules/cp/cp_def.h
0,0 → 1,8
{
"cp",
"Copy files and directories",
&cmd_cp,
&help_cmd_cp,
0
},
 
/branches/tracing/uspace/app/bdsh/cmds/modules/cp/entry.h
0,0 → 1,9
#ifndef CP_ENTRY_H
#define CP_ENTRY_H
 
/* Entry points for the cp command */
extern int cmd_cp(char **);
extern void help_cmd_cp(unsigned int);
 
#endif /* CP_ENTRY_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/cp/cp.h
0,0 → 1,8
#ifndef CP_H
#define CP_H
 
/* Prototypes for the cp command, excluding entry points */
 
 
#endif /* CP_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/sleep/entry.h
0,0 → 1,9
#ifndef SLEEP_ENTRY_H
#define SLEEP_ENTRY_H
 
/* Entry points for the sleep command */
extern int cmd_sleep(char **);
extern void help_cmd_sleep(unsigned int);
 
#endif /* SLEEP_ENTRY_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/sleep/sleep.c
0,0 → 1,73
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include "util.h"
#include "errors.h"
#include "entry.h"
#include "sleep.h"
#include "cmds.h"
 
static char *cmdname = "sleep";
 
/* Dispays help for sleep in various levels */
void help_cmd_sleep(unsigned int level)
{
printf("This is the %s help for '%s'.\n",
level ? EXT_HELP : SHORT_HELP, cmdname);
return;
}
 
/* Main entry point for sleep, accepts an array of arguments */
int cmd_sleep(char **argv)
{
unsigned int argc;
unsigned int i;
 
/* Count the arguments */
for (argc = 0; argv[argc] != NULL; argc ++);
 
printf("%s %s\n", TEST_ANNOUNCE, cmdname);
printf("%d arguments passed to %s", argc - 1, cmdname);
 
if (argc < 2) {
printf("\n");
return CMD_SUCCESS;
}
 
printf(":\n");
for (i = 1; i < argc; i++)
printf("[%d] -> %s\n", i, argv[i]);
 
return CMD_SUCCESS;
}
 
/branches/tracing/uspace/app/bdsh/cmds/modules/sleep/sleep_def.h
0,0 → 1,8
{
"sleep",
"Pause for given time interval (in seconds)",
&cmd_sleep,
&help_cmd_sleep,
0
},
 
/branches/tracing/uspace/app/bdsh/cmds/modules/sleep/sleep.h
0,0 → 1,8
#ifndef SLEEP_H
#define SLEEP_H
 
/* Prototypes for the sleep command, excluding entry points */
 
 
#endif /* SLEEP_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/modules.h
0,0 → 1,49
#ifndef MODULES_H
#define MODULES_H
 
/* Each built in function has two files, one being an entry.h file which
* prototypes the run/help entry functions, the other being a .def file
* which fills the modules[] array according to the cmd_t structure
* defined in cmds.h.
*
* To add or remove a module, just make a new directory in cmds/modules
* for it and copy the 'show' example for basics, then include it here.
* (or reverse the process to remove one)
*
* NOTE: See module_ aliases.h as well, this is where aliases (commands that
* share an entry point with others) are indexed */
 
#include "config.h"
 
/* Prototypes for each module's entry (help/exec) points */
 
#include "help/entry.h"
#include "quit/entry.h"
#include "mkdir/entry.h"
#include "rm/entry.h"
#include "cat/entry.h"
#include "touch/entry.h"
#include "ls/entry.h"
#include "pwd/entry.h"
#include "sleep/entry.h"
#include "cp/entry.h"
 
/* Each .def function fills the module_t struct with the individual name, entry
* point, help entry point, etc. You can use config.h to control what modules
* are loaded based on what libraries exist on the system. */
 
module_t modules[] = {
#include "help/help_def.h"
#include "quit/quit_def.h"
#include "mkdir/mkdir_def.h"
#include "rm/rm_def.h"
#include "cat/cat_def.h"
#include "touch/touch_def.h"
#include "ls/ls_def.h"
#include "pwd/pwd_def.h"
#include "sleep/sleep_def.h"
#include "cp/cp_def.h"
{NULL, NULL, NULL, NULL}
};
 
#endif
/branches/tracing/uspace/app/bdsh/cmds/modules/quit/quit.c
0,0 → 1,55
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include "entry.h"
#include "quit.h"
#include "cmds.h"
 
static char *cmdname = "quit";
 
extern volatile unsigned int cli_quit;
extern const char *progname;
 
void help_cmd_quit(unsigned int level)
{
printf("Type `%s' to exit %s\n", cmdname, progname);
return;
}
 
/* Quits the program and returns the status of whatever command
* came before invoking 'quit' */
int cmd_quit(char *argv[])
{
/* Inform that we're outta here */
cli_quit = 1;
return CMD_SUCCESS;
}
/branches/tracing/uspace/app/bdsh/cmds/modules/quit/entry.h
0,0 → 1,10
#ifndef QUIT_ENTRY_H_
#define QUIT_ENTRY_H_
 
/* Entry points for the quit command */
extern void help_cmd_quit(unsigned int);
extern int cmd_quit(char *[]);
 
#endif
 
 
/branches/tracing/uspace/app/bdsh/cmds/modules/quit/quit_def.h
0,0 → 1,14
{
"quit",
"Exit the console",
&cmd_quit,
&help_cmd_quit,
-1
},
{
"exit",
NULL,
&cmd_quit,
&help_cmd_quit,
-1
},
/branches/tracing/uspace/app/bdsh/cmds/modules/quit/quit.h
0,0 → 1,6
#ifndef QUIT_H
#define QUIT_H
 
/* Prototypes for the quit command (excluding entry points) */
 
#endif
/branches/tracing/uspace/app/bdsh/cmds/modules/touch/touch.c
0,0 → 1,107
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
/* TODO: Options that people would expect, such as not creating the file if
* it doesn't exist, specifying the access time, etc */
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/types.h>
 
#include "config.h"
#include "errors.h"
#include "util.h"
#include "entry.h"
#include "touch.h"
#include "cmds.h"
 
static char *cmdname = "touch";
 
/* Dispays help for touch in various levels */
void help_cmd_touch(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' updates access times for files\n", cmdname);
} else {
help_cmd_touch(HELP_SHORT);
printf(" `%s' <file>, if the file does not exist it will be "
"created\n", cmdname);
}
 
return;
}
 
/* Main entry point for touch, accepts an array of arguments */
int cmd_touch(char **argv)
{
unsigned int argc, i = 0, ret = 0;
int fd;
char *buff = NULL;
 
DIR *dirp;
 
argc = cli_count_args(argv);
 
if (argc == 1) {
printf("%s - incorrect number of arguments. Try `help %s extended'\n",
cmdname, cmdname);
return CMD_FAILURE;
}
 
for (i = 1; i < argc; i ++) {
buff = cli_strdup(argv[i]);
dirp = opendir(buff);
if (dirp) {
cli_error(CL_ENOTSUP, "%s is a directory", buff);
closedir(dirp);
ret ++;
continue;
}
 
fd = open(buff, O_RDWR | O_CREAT);
if (fd < 0) {
cli_error(CL_EFAIL, "Could not update / create %s ", buff);
ret ++;
continue;
} else
close(fd);
 
free(buff);
}
 
if (ret)
return CMD_FAILURE;
else
return CMD_SUCCESS;
}
 
/branches/tracing/uspace/app/bdsh/cmds/modules/touch/entry.h
0,0 → 1,9
#ifndef TOUCH_ENTRY_H
#define TOUCH_ENTRY_H
 
/* Entry points for the touch command */
extern int cmd_touch(char **);
extern void help_cmd_touch(unsigned int);
 
#endif /* TOUCH_ENTRY_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/touch/touch_def.h
0,0 → 1,8
{
"touch",
"Create files or update access times",
&cmd_touch,
&help_cmd_touch,
0
},
 
/branches/tracing/uspace/app/bdsh/cmds/modules/touch/touch.h
0,0 → 1,8
#ifndef TOUCH_H
#define TOUCH_H
 
/* Prototypes for the touch command, excluding entry points */
 
 
#endif /* TOUCH_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/mkdir/entry.h
0,0 → 1,9
#ifndef MKDIR_ENTRY_H
#define MKDIR_ENTRY_H
 
/* Entry points for the mkdir command */
extern int cmd_mkdir(char **);
extern void help_cmd_mkdir(unsigned int);
 
#endif /* MKDIR_ENTRY_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c
0,0 → 1,251
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <getopt.h>
#include <stdarg.h>
 
#include "config.h"
#include "errors.h"
#include "util.h"
#include "entry.h"
#include "mkdir.h"
#include "cmds.h"
 
#define MKDIR_VERSION "0.0.1"
 
static char *cmdname = "mkdir";
 
static struct option const long_options[] = {
{"parents", no_argument, 0, 'p'},
{"verbose", no_argument, 0, 'v'},
{"mode", required_argument, 0, 'm'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"follow", no_argument, 0, 'f'},
{0, 0, 0, 0}
};
 
 
void help_cmd_mkdir(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' creates a new directory\n", cmdname);
} else {
help_cmd_mkdir(HELP_SHORT);
printf(
"Usage: %s [options] <path>\n"
"Options:\n"
" -h, --help A short option summary\n"
" -V, --version Print version information and exit\n"
" -p, --parents Create needed parents for <path>\n"
" -m, --mode Set permissions to [mode] (UNUSED)\n"
" -v, --verbose Be extremely noisy about what is happening\n"
" -f, --follow Go to the new directory once created\n"
"Currently, %s is under development, some options don't work.\n",
cmdname, cmdname);
}
 
return;
}
 
/* This is kind of clunky, but effective for now */
static unsigned int
create_directory(const char *path, unsigned int p)
{
DIR *dirp;
char *tmp = NULL, *buff = NULL, *wdp = NULL;
char *dirs[255];
unsigned int absolute = 0, i = 0, ret = 0;
 
/* Its a good idea to allocate path, plus we (may) need a copy of
* path to tokenize if parents are specified */
if (NULL == (tmp = cli_strdup(path))) {
cli_error(CL_ENOMEM, "%s: path too big?", cmdname);
return 1;
}
 
if (NULL == (wdp = (char *) malloc(PATH_MAX))) {
cli_error(CL_ENOMEM, "%s: could not alloc cwd", cmdname);
free(tmp);
return 1;
}
 
/* The only reason for wdp is to be (optionally) verbose */
getcwd(wdp, PATH_MAX);
 
/* Typical use without specifying the creation of parents */
if (p == 0) {
dirp = opendir(tmp);
if (dirp) {
cli_error(CL_EEXISTS, "%s: can not create %s, try -p", cmdname, path);
closedir(dirp);
goto finit;
}
if (-1 == (mkdir(tmp, 0))) {
cli_error(CL_EFAIL, "%s: could not create %s", cmdname, path);
goto finit;
}
}
 
/* Parents need to be created, path has to be broken up */
 
/* See if path[0] is a slash, if so we have to remember to append it */
if (tmp[0] == '/')
absolute = 1;
 
/* TODO: Canonify the path prior to tokenizing it, see below */
dirs[i] = cli_strtok(tmp, "/");
while (dirs[i] && i < 255)
dirs[++i] = cli_strtok(NULL, "/");
 
if (NULL == dirs[0])
return 1;
 
if (absolute == 1) {
asprintf(&buff, "/%s", dirs[0]);
mkdir(buff, 0);
chdir(buff);
free(buff);
getcwd(wdp, PATH_MAX);
i = 1;
} else {
i = 0;
}
 
while (dirs[i] != NULL) {
/* Sometimes make or scripts conjoin odd paths. Account for something
* like this: ../../foo/bar/../foo/foofoo/./bar */
if (!strcmp(dirs[i], "..") || !strcmp(dirs[i], ".")) {
if (0 != (chdir(dirs[i]))) {
cli_error(CL_EFAIL, "%s: impossible path: %s",
cmdname, path);
ret ++;
goto finit;
}
getcwd(wdp, PATH_MAX);
} else {
if (-1 == (mkdir(dirs[i], 0))) {
cli_error(CL_EFAIL,
"%s: failed at %s/%s", wdp, dirs[i]);
ret ++;
goto finit;
}
if (0 != (chdir(dirs[i]))) {
cli_error(CL_EFAIL, "%s: failed creating %s\n",
cmdname, dirs[i]);
ret ++;
break;
}
}
i++;
}
goto finit;
 
finit:
free(wdp);
free(tmp);
return ret;
}
 
int cmd_mkdir(char **argv)
{
unsigned int argc, create_parents = 0, i, ret = 0, follow = 0;
unsigned int verbose = 0;
int c, opt_ind;
char *cwd;
 
argc = cli_count_args(argv);
 
for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind);
switch (c) {
case 'p':
create_parents = 1;
break;
case 'v':
verbose = 1;
break;
case 'h':
help_cmd_mkdir(HELP_LONG);
return CMD_SUCCESS;
case 'V':
printf("%s\n", MKDIR_VERSION);
return CMD_SUCCESS;
case 'f':
follow = 1;
break;
case 'm':
printf("%s: [W] Ignoring mode %s\n", cmdname, optarg);
break;
}
}
 
argc -= optind;
 
if (argc < 1) {
printf("%s - incorrect number of arguments. Try `%s --help'\n",
cmdname, cmdname);
return CMD_FAILURE;
}
 
if (NULL == (cwd = (char *) malloc(PATH_MAX))) {
cli_error(CL_ENOMEM, "%s: could not allocate cwd", cmdname);
return CMD_FAILURE;
}
 
memset(cwd, 0, sizeof(cwd));
getcwd(cwd, PATH_MAX);
 
for (i = optind; argv[i] != NULL; i++) {
if (verbose == 1)
printf("%s: creating %s%s\n",
cmdname, argv[i],
create_parents ? " (and all parents)" : "");
ret += create_directory(argv[i], create_parents);
}
 
if (follow == 0)
chdir(cwd);
 
free(cwd);
 
if (ret)
return CMD_FAILURE;
else
return CMD_SUCCESS;
}
 
/branches/tracing/uspace/app/bdsh/cmds/modules/mkdir/mkdir_def.h
0,0 → 1,16
{
"mkdir",
"Create new directories",
&cmd_mkdir,
&help_cmd_mkdir,
0
},
 
{
"md",
NULL,
&cmd_mkdir,
&help_cmd_mkdir,
0
},
 
/branches/tracing/uspace/app/bdsh/cmds/modules/mkdir/mkdir.h
0,0 → 1,8
#ifndef MKDIR_H
#define MKDIR_H
 
/* Prototypes for the mkdir command, excluding entry points */
 
static unsigned int create_directory(const char *, unsigned int);
#endif /* MKDIR_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/cat/entry.h
0,0 → 1,9
#ifndef CAT_ENTRY_H
#define CAT_ENTRY_H
 
/* Entry points for the cat command */
extern int cmd_cat(char **);
extern void help_cmd_cat(unsigned int);
 
#endif /* CAT_ENTRY_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/cat/cat.c
0,0 → 1,180
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <fcntl.h>
 
#include "config.h"
#include "util.h"
#include "errors.h"
#include "entry.h"
#include "cat.h"
#include "cmds.h"
 
static char *cmdname = "cat";
#define CAT_VERSION "0.0.1"
#define CAT_DEFAULT_BUFLEN 1024
 
static char *cat_oops = "That option is not yet supported\n";
 
static struct option const long_options[] = {
{ "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'v' },
{ "head", required_argument, 0, 'H' },
{ "tail", required_argument, 0, 't' },
{ "buffer", required_argument, 0, 'b' },
{ "more", no_argument, 0, 'm' },
{ 0, 0, 0, 0 }
};
 
/* Dispays help for cat in various levels */
void help_cmd_cat(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' shows the contents of files\n", cmdname);
} else {
help_cmd_cat(HELP_SHORT);
printf(
"Usage: %s [options] <file1> [file2] [...]\n"
"Options:\n"
" -h, --help A short option summary\n"
" -v, --version Print version information and exit\n"
" -H, --head ## Print only the first ## bytes\n"
" -t, --tail ## Print only the last ## bytes\n"
" -b, --buffer ## Set the read buffer size to ##\n"
" -m, --more Pause after each screen full\n"
"Currently, %s is under development, some options don't work.\n",
cmdname, cmdname);
}
 
return;
}
 
static unsigned int cat_file(const char *fname, size_t blen)
{
int fd, bytes = 0, count = 0, reads = 0;
off_t total = 0;
char *buff = NULL;
 
if (-1 == (fd = open(fname, O_RDONLY))) {
printf("Unable to open %s\n", fname);
return 1;
}
 
total = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
 
if (NULL == (buff = (char *) malloc(blen + 1))) {
close(fd);
printf("Unable to allocate enough memory to read %s\n",
fname);
return 1;
}
 
do {
memset(buff, 0, sizeof(buff));
bytes = read(fd, buff, blen);
if (bytes > 0) {
count += bytes;
if (bytes < blen)
buff[bytes] = '\0';
printf(buff);
reads++;
}
} while (bytes > 0);
 
close(fd);
if (bytes == -1) {
printf("Error reading %s\n", fname);
free(buff);
return 1;
}
 
free(buff);
 
return 0;
}
 
/* Main entry point for cat, accepts an array of arguments */
int cmd_cat(char **argv)
{
unsigned int argc, i, ret = 0, buffer = 0;
int c, opt_ind;
 
argc = cli_count_args(argv);
 
for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
c = getopt_long(argc, argv, "hvmH:t:b:", long_options, &opt_ind);
switch (c) {
case 'h':
help_cmd_cat(HELP_LONG);
return CMD_SUCCESS;
case 'v':
printf("%s\n", CAT_VERSION);
return CMD_SUCCESS;
case 'H':
printf(cat_oops);
return CMD_FAILURE;
case 't':
printf(cat_oops);
return CMD_FAILURE;
case 'b':
printf(cat_oops);
break;
case 'm':
printf(cat_oops);
return CMD_FAILURE;
}
}
 
argc -= optind;
 
if (argc < 1) {
printf("%s - incorrect number of arguments. Try `%s --help'\n",
cmdname, cmdname);
return CMD_FAILURE;
}
 
if (buffer <= 0)
buffer = CAT_DEFAULT_BUFLEN;
 
for (i = optind; argv[i] != NULL; i++)
ret += cat_file(argv[i], buffer);
 
if (ret)
return CMD_FAILURE;
else
return CMD_SUCCESS;
}
 
/branches/tracing/uspace/app/bdsh/cmds/modules/cat/cat_def.h
0,0 → 1,8
{
"cat",
"Show the contents of a file",
&cmd_cat,
&help_cmd_cat,
0
},
 
/branches/tracing/uspace/app/bdsh/cmds/modules/cat/cat.h
0,0 → 1,9
#ifndef CAT_H
#define CAT_H
 
/* Prototypes for the cat command, excluding entry points */
 
static unsigned int cat_file(const char *, size_t);
 
#endif /* CAT_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/help/entry.h
0,0 → 1,8
#ifndef HELP_ENTRY_H_
#define HELP_ENTRY_H_
 
/* Entry points for the help command */
extern void help_cmd_help(unsigned int);
extern int cmd_help(char *[]);
 
#endif
/branches/tracing/uspace/app/bdsh/cmds/modules/help/help.c
0,0 → 1,162
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include "config.h"
#include "entry.h"
#include "help.h"
#include "cmds.h"
#include "modules.h"
#include "builtins.h"
#include "errors.h"
#include "util.h"
 
static char *cmdname = "help";
extern const char *progname;
 
#define HELP_IS_MODULE 1
#define HELP_IS_BUILTIN 0
#define HELP_IS_RUBBISH -1
 
volatile int mod_switch = -1;
 
/* Just use a pointer here, no need for mod_switch */
static int is_mod_or_builtin(char *cmd)
{
int rc = HELP_IS_RUBBISH;
 
rc = is_builtin(cmd);
if (rc > -1) {
mod_switch = rc;
return HELP_IS_BUILTIN;
}
rc = is_module(cmd);
if (rc > -1) {
mod_switch = rc;
return HELP_IS_MODULE;
}
 
return HELP_IS_RUBBISH;
}
 
void help_cmd_help(unsigned int level)
{
if (level == HELP_SHORT) {
printf(
"\n %s [command] <extended>\n"
" Use help [command] extended for detailed help on [command] "
", even `help'\n\n", cmdname);
} else {
printf(
"\n `%s' - shows help for commands\n"
" Examples:\n"
" %s [command] Show help for [command]\n"
" %s [command] extended Show extended help for [command]\n"
"\n If no argument is given to %s, a list of commands are shown\n\n",
cmdname, cmdname, cmdname, cmdname);
}
 
return;
}
 
int cmd_help(char *argv[])
{
module_t *mod;
builtin_t *cmd;
unsigned int i = 0;
int rc = 0;
int argc;
int level = HELP_SHORT;
 
argc = cli_count_args(argv);
 
if (argc > 3) {
printf("\nToo many arguments to `%s', try:\n", cmdname);
help_cmd_help(HELP_SHORT);
return CMD_FAILURE;
}
 
if (argc == 3) {
if (!strcmp("extended", argv[2]))
level = HELP_LONG;
else
level = HELP_SHORT;
}
 
if (argc > 1) {
rc = is_mod_or_builtin(argv[1]);
switch (rc) {
case HELP_IS_RUBBISH:
printf("Invalid command %s\n", argv[1]);
return CMD_FAILURE;
case HELP_IS_MODULE:
help_module(mod_switch, level);
return CMD_SUCCESS;
case HELP_IS_BUILTIN:
help_builtin(mod_switch, level);
return CMD_SUCCESS;
}
}
 
printf("\n Available commands are:\n");
printf(" ------------------------------------------------------------\n");
 
/* First, show a list of built in commands that are available in this mode */
for (cmd = builtins; cmd->name != NULL; cmd++, i++) {
if (!builtin_is_restricted(i)) {
if (is_builtin_alias(cmd->name))
printf(" %-16s\tAlias for `%s'\n", cmd->name,
alias_for_builtin(cmd->name));
else
printf(" %-16s\t%s\n", cmd->name, cmd->desc);
}
}
 
i = 0;
 
/* Now, show a list of module commands that are available in this mode */
for (mod = modules; mod->name != NULL; mod++, i++) {
if (!module_is_restricted(i)) {
if (is_module_alias(mod->name))
printf(" %-16s\tAlias for `%s'\n", mod->name,
alias_for_module(mod->name));
else
printf(" %-16s\t%s\n", mod->name, mod->desc);
}
}
 
printf("\n Try %s %s for more information on how `%s' works.\n\n",
cmdname, cmdname, cmdname);
 
return CMD_SUCCESS;
}
/branches/tracing/uspace/app/bdsh/cmds/modules/help/help_def.h
0,0 → 1,7
{
"help",
"Show help for commands",
&cmd_help,
&help_cmd_help,
0
},
/branches/tracing/uspace/app/bdsh/cmds/modules/help/help.h
0,0 → 1,7
#ifndef HELP_H
#define HELP_H
 
/* Prototypes for the help command (excluding entry points) */
static int is_mod_or_builtin(char *);
 
#endif
/branches/tracing/uspace/app/bdsh/cmds/modules/pwd/entry.h
0,0 → 1,12
#ifndef PWD_ENTRY_H
#define PWD_ENTRY_H
 
#include "scli.h"
 
/* Entry points for the pwd command */
extern void help_cmd_pwd(unsigned int);
extern int cmd_pwd(char **);
 
#endif
 
 
/branches/tracing/uspace/app/bdsh/cmds/modules/pwd/pwd.c
0,0 → 1,71
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
 
#include "config.h"
#include "errors.h"
#include "entry.h"
#include "cmds.h"
#include "pwd.h"
 
static char * cmdname = "pwd";
 
void help_cmd_pwd(unsigned int level)
{
printf("`%s' prints your current working directory.\n", cmdname);
return;
}
 
int cmd_pwd(char *argv[])
{
char *buff;
 
buff = (char *) malloc(PATH_MAX);
if (NULL == buff) {
cli_error(CL_ENOMEM, "%s:", cmdname);
return CMD_FAILURE;
}
 
memset(buff, 0, sizeof(buff));
getcwd(buff, PATH_MAX);
 
if (! buff) {
cli_error(CL_EFAIL,
"Unable to determine the current working directory");
free(buff);
return CMD_FAILURE;
} else {
printf("%s\n", buff);
free(buff);
return CMD_SUCCESS;
}
}
/branches/tracing/uspace/app/bdsh/cmds/modules/pwd/pwd_def.h
0,0 → 1,7
{
"pwd",
"Prints the current working directory",
&cmd_pwd,
&help_cmd_pwd,
-1
},
/branches/tracing/uspace/app/bdsh/cmds/modules/pwd/pwd.h
0,0 → 1,6
#ifndef PWD_H_
#define PWD_H_
 
/* Prototypes for the pwd command (excluding entry points) */
 
#endif
/branches/tracing/uspace/app/bdsh/cmds/modules/ls/ls.c
0,0 → 1,196
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
/* NOTE:
* This is a bit of an ugly hack, working around the absence of fstat / etc.
* As more stuff is completed and exposed in libc, this will improve */
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
 
#include "errors.h"
#include "config.h"
#include "util.h"
#include "entry.h"
#include "ls.h"
#include "cmds.h"
 
static char *cmdname = "ls";
 
static unsigned int ls_scope(const char *path)
{
int fd;
DIR *dirp;
 
dirp = opendir(path);
if (dirp) {
closedir(dirp);
return LS_DIR;
}
 
fd = open(path, O_RDONLY);
if (fd > 0) {
close(fd);
return LS_FILE;
}
 
return LS_BOGUS;
}
 
static void ls_scan_dir(const char *d, DIR *dirp)
{
struct dirent *dp;
unsigned int scope;
char *buff;
 
if (! dirp)
return;
 
buff = (char *)malloc(PATH_MAX);
if (NULL == buff) {
cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
return;
}
 
while ((dp = readdir(dirp))) {
memset(buff, 0, sizeof(buff));
/* Don't worry if inserting a double slash, this will be fixed by
* absolutize() later with subsequent calls to open() or readdir() */
snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name);
scope = ls_scope(buff);
switch (scope) {
case LS_DIR:
ls_print_dir(dp->d_name);
break;
case LS_FILE:
ls_print_file(dp->d_name);
break;
case LS_BOGUS:
/* Odd chance it was deleted from the time readdir() found
* it and the time that it was scoped */
printf("ls: skipping bogus node %s\n", dp->d_name);
break;
}
}
 
free(buff);
 
return;
}
 
/* ls_print_* currently does nothing more than print the entry.
* in the future, we will likely pass the absolute path, and
* some sort of ls_options structure that controls how each
* entry is printed and what is printed about it.
*
* Now we just print basic DOS style lists */
 
static void ls_print_dir(const char *d)
{
printf("%-40s\t<DIR>\n", d);
 
return;
}
 
static void ls_print_file(const char *f)
{
printf("%-40s\n", f);
 
return;
}
 
void help_cmd_ls(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' lists files and directories.\n", cmdname);
} else {
help_cmd_ls(HELP_SHORT);
printf(" `%s' [path], if no path is given the current "
"working directory is used.\n", cmdname);
}
 
return;
}
 
int cmd_ls(char **argv)
{
unsigned int argc;
unsigned int scope;
char *buff;
DIR *dirp;
 
argc = cli_count_args(argv);
 
buff = (char *) malloc(PATH_MAX);
if (NULL == buff) {
cli_error(CL_ENOMEM, "%s: ", cmdname);
return CMD_FAILURE;
}
memset(buff, 0, sizeof(buff));
 
if (argc == 1)
getcwd(buff, PATH_MAX);
else
strncpy(buff, argv[1], PATH_MAX);
 
scope = ls_scope(buff);
 
switch (scope) {
case LS_BOGUS:
cli_error(CL_ENOENT, buff);
free(buff);
return CMD_FAILURE;
case LS_FILE:
ls_print_file(buff);
break;
case LS_DIR:
dirp = opendir(buff);
if (! dirp) {
/* May have been deleted between scoping it and opening it */
cli_error(CL_EFAIL, "Could not stat %s", buff);
free(buff);
return CMD_FAILURE;
}
ls_scan_dir(buff, dirp);
closedir(dirp);
break;
}
 
free(buff);
 
return CMD_SUCCESS;
}
 
/branches/tracing/uspace/app/bdsh/cmds/modules/ls/entry.h
0,0 → 1,9
#ifndef LS_ENTRY_H
#define LS_ENTRY_H
 
/* Entry points for the ls command */
extern int cmd_ls(char **);
extern void help_cmd_ls(unsigned int);
 
#endif /* LS_ENTRY_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/ls/ls_def.h
0,0 → 1,16
{
"ls",
"List files and directories",
&cmd_ls,
&help_cmd_ls,
0
},
 
{
"dir",
NULL,
&cmd_ls,
&help_cmd_ls,
0
},
 
/branches/tracing/uspace/app/bdsh/cmds/modules/ls/ls.h
0,0 → 1,16
#ifndef LS_H
#define LS_H
 
/* Various values that can be returned by ls_scope() */
#define LS_BOGUS 0
#define LS_FILE 1
#define LS_DIR 2
 
 
static unsigned int ls_scope(const char *);
static void ls_scan_dir(const char *, DIR *);
static void ls_print_dir(const char *);
static void ls_print_file(const char *);
 
#endif /* LS_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/rm/rm.c
0,0 → 1,254
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <assert.h>
#include <getopt.h>
 
#include "config.h"
#include "errors.h"
#include "util.h"
#include "entry.h"
#include "rm.h"
#include "cmds.h"
 
static char *cmdname = "rm";
#define RM_VERSION "0.0.1"
 
static rm_job_t rm;
 
static struct option const long_options[] = {
{ "help", no_argument, 0, 'h' },
{ "version", no_argument, 0, 'v' },
{ "recursive", no_argument, 0, 'r' },
{ "force", no_argument, 0, 'f' },
{ "safe", no_argument, 0, 's' },
{ 0, 0, 0, 0 }
};
 
static unsigned int rm_start(rm_job_t *rm)
{
rm->recursive = 0;
rm->force = 0;
rm->safe = 0;
 
/* Make sure we can allocate enough memory to store
* what is needed in the job structure */
if (NULL == (rm->nwd = (char *) malloc(PATH_MAX)))
return 0;
memset(rm->nwd, 0, sizeof(rm->nwd));
 
if (NULL == (rm->owd = (char *) malloc(PATH_MAX)))
return 0;
memset(rm->owd, 0, sizeof(rm->owd));
 
if (NULL == (rm->cwd = (char *) malloc(PATH_MAX)))
return 0;
memset(rm->cwd, 0, sizeof(rm->cwd));
 
chdir(".");
 
if (NULL == (getcwd(rm->owd, PATH_MAX)))
return 0;
 
return 1;
}
 
static void rm_end(rm_job_t *rm)
{
if (NULL != rm->nwd)
free(rm->nwd);
 
if (NULL != rm->owd)
free(rm->owd);
 
if (NULL != rm->cwd)
free(rm->cwd);
 
return;
}
 
static unsigned int rm_recursive(const char *path)
{
int rc;
 
/* First see if it will just go away */
rc = rmdir(path);
if (rc == 0)
return 0;
 
/* Its not empty, recursively scan it */
cli_error(CL_ENOTSUP,
"Can not remove %s, directory not empty", path);
return 1;
}
 
static unsigned int rm_single(const char *path)
{
if (unlink(path)) {
cli_error(CL_EFAIL, "rm: could not remove file %s", path);
return 1;
}
return 0;
}
 
static unsigned int rm_scope(const char *path)
{
int fd;
DIR *dirp;
 
dirp = opendir(path);
if (dirp) {
closedir(dirp);
return RM_DIR;
}
 
fd = open(path, O_RDONLY);
if (fd > 0) {
close(fd);
return RM_FILE;
}
 
return RM_BOGUS;
}
 
/* Dispays help for rm in various levels */
void help_cmd_rm(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' removes files and directories.\n", cmdname);
} else {
help_cmd_rm(HELP_SHORT);
printf(
"Usage: %s [options] <path>\n"
"Options:\n"
" -h, --help A short option summary\n"
" -v, --version Print version information and exit\n"
" -r, --recursive Recursively remove sub directories\n"
" -f, --force Do not prompt prior to removing files\n"
" -s, --safe Stop if directories change during removal\n\n"
"Currently, %s is under development, some options don't work.\n",
cmdname, cmdname);
}
return;
}
 
/* Main entry point for rm, accepts an array of arguments */
int cmd_rm(char **argv)
{
unsigned int argc;
unsigned int i, scope, ret = 0;
int c, opt_ind;
size_t len;
char *buff = NULL;
 
argc = cli_count_args(argv);
 
if (argc < 2) {
cli_error(CL_EFAIL,
"%s: insufficient arguments. Try %s --help", cmdname, cmdname);
return CMD_FAILURE;
}
 
if (!rm_start(&rm)) {
cli_error(CL_ENOMEM, "%s: could not initialize", cmdname);
rm_end(&rm);
return CMD_FAILURE;
}
 
for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
c = getopt_long(argc, argv, "hvrfs", long_options, &opt_ind);
switch (c) {
case 'h':
help_cmd_rm(HELP_LONG);
return CMD_SUCCESS;
case 'v':
printf("%s\n", RM_VERSION);
return CMD_SUCCESS;
case 'r':
rm.recursive = 1;
break;
case 'f':
rm.force = 1;
break;
case 's':
rm.safe = 1;
break;
}
}
 
if (optind == argc) {
cli_error(CL_EFAIL,
"%s: insufficient arguments. Try %s --help", cmdname, cmdname);
rm_end(&rm);
return CMD_FAILURE;
}
 
i = optind;
while (NULL != argv[i]) {
len = strlen(argv[i]) + 2;
buff = (char *) realloc(buff, len);
assert(buff != NULL);
memset(buff, 0, sizeof(buff));
snprintf(buff, len, argv[i]);
 
scope = rm_scope(buff);
switch (scope) {
case RM_BOGUS: /* FIXME */
case RM_FILE:
ret += rm_single(buff);
break;
case RM_DIR:
if (! rm.recursive) {
printf("%s is a directory, use -r to remove it.\n", buff);
ret ++;
} else {
ret += rm_recursive(buff);
}
break;
}
i++;
}
 
if (NULL != buff)
free(buff);
 
rm_end(&rm);
 
if (ret)
return CMD_FAILURE;
else
return CMD_SUCCESS;
}
 
/branches/tracing/uspace/app/bdsh/cmds/modules/rm/entry.h
0,0 → 1,9
#ifndef RM_ENTRY_H
#define RM_ENTRY_H
 
/* Entry points for the rm command */
extern int cmd_rm(char **);
extern void help_cmd_rm(unsigned int);
 
#endif /* RM_ENTRY_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/rm/rm_def.h
0,0 → 1,16
{
"rm",
"Remove files and directories",
&cmd_rm,
&help_cmd_rm,
0
},
 
{
"del",
NULL,
&cmd_rm,
&help_cmd_rm,
0
},
 
/branches/tracing/uspace/app/bdsh/cmds/modules/rm/rm.h
0,0 → 1,43
#ifndef RM_H
#define RM_H
 
/* Return values for rm_scope() */
#define RM_BOGUS 0
#define RM_FILE 1
#define RM_DIR 2
 
/* Flags for rm_update() */
#define _RM_ENTRY 0
#define _RM_ADVANCE 1
#define _RM_REWIND 2
#define _RM_EXIT 3
 
/* A simple job structure */
typedef struct {
/* Options set at run time */
unsigned int force; /* -f option */
unsigned int recursive; /* -r option */
unsigned int safe; /* -s option */
 
/* Keeps track of the job in progress */
int advance; /* How far deep we've gone since entering */
DIR *entry; /* Entry point to the tree being removed */
char *owd; /* Where we were when we invoked rm */
char *cwd; /* Current directory being transversed */
char *nwd; /* Next directory to be transversed */
 
/* Counters */
int f_removed; /* Number of files unlinked */
int d_removed; /* Number of directories unlinked */
} rm_job_t;
 
 
/* Prototypes for the rm command, excluding entry points */
static unsigned int rm_start(rm_job_t *);
static void rm_end(rm_job_t *rm);
static unsigned int rm_recursive(const char *);
static unsigned int rm_single(const char *);
static unsigned int rm_scope(const char *);
 
#endif /* RM_H */
 
/branches/tracing/uspace/app/bdsh/cmds/modules/README
0,0 → 1,15
Modules are commands or full programs (anything can be made into a module
that can return int type) should go here. Note, modules do not (can not)
update or read cliuser_t.
 
Stuff that needs to write to the user structures contained in scli.h should
be made as built-in commands, not modules, but there are very few times when
you would want to do that.
 
See the README file in the bdsh root directory for a quick overview of how to
write a new command, or convert an existig stand-alone program into a module
for BDSH.
 
 
 
 
/branches/tracing/uspace/app/bdsh/cmds/modules/module_aliases.h
0,0 → 1,22
#ifndef MODULE_ALIASES_H
#define MODULE_ALIASES_H
 
/* Modules that declare multiple names for themselves but use the
* same entry functions are aliases. This array helps to determine if
* a module is an alias, as such it can be invoked differently.
* format is alias , real_name */
 
/* So far, this is only used in the help display but could be used to
* handle a module differently even prior to reaching its entry code.
* For instance, 'exit' could behave differently than 'quit', prior to
* the entry point being reached. */
 
char *mod_aliases[] = {
"exit", "quit",
"md", "mkdir",
"del", "rm",
"dir", "ls",
NULL, NULL
};
 
#endif
/branches/tracing/uspace/app/bdsh/cmds/mknewcmd
0,0 → 1,347
#!/bin/sh
# Copyright (C) 2008 Tim Post - All Rights Reserved
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# Neither the name of the original program's authors nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
 
# Script to generate skeletal files for a new command
# Uses `getopt', not quite a bash-ism but might be
# lacking on some legacy systems.
 
# If your shell does not support eval, shift (x) or
# here-now documents, sorry :)
 
usage()
{
def="$DEFAULT_COMMAND"
cat << EOF
\`$PROGNAME' generates skeletal command files to simplify adding commands
Usage: $PROGNAME [options] <location>
Options:
-n, --name Name of the command (default: ${def})
-d, --desc Short (20 30 chars) description of the command
(def: "The $def command")
-e, --entry Entry function of the command (def: cmd_${def})
-h, --help-entry Entry function for command help (def: help_cmd_${def})
-a, --alias Alias (nickname) for this command (def: none)
-r, --restrict Restriction level (interactive, non-interactive, both)
(def: module is both, builtin is interactive only)
-t, --type Type of command (module or builtin) (def: module)
-H, --help This help summary
-V, --version Print $PROGNAME version and exit normally
 
Notes:
You must supply at least the name of the command.
 
If you do not specify a location (i.e. modules/foo), the command will be
created in modules/command_name or builtins/command_name depending on your
selection.
 
This script will only create skeletal files and inform you what headers
need to be modified to incorporate the command. You will also have to
manually update the main Makefile.
 
This script is intended only to be a convenience for developers. Example use:
$PROGNAME -n foo -d "Foo power" -a bar -r both -t module modules/foo
 
The example would generate a modular command named 'foo', which is also
reached by typing 'bar' and available in either interactive or noninteractive
mode.
 
Skeletal files do *not* depend on the autoconf generated "config.h" unless you
include it. This may or may not be desirable depending on your use.
 
Report bugs to $PROGMAINT
 
EOF
}
 
# Convert a string to all uppercase
toupper()
{
local str="$1"
 
echo "${str}" | tr 'a-z' 'A-Z'
}
 
# Template stored `here-now' style, this generates all files needed
# for a new command according to arguments passed.
generate_code()
{
echo "Creating ${OUTDIR}/${CMDNAME}_def.h ..."
cat << EOF > ${OUTDIR}/${CMDNAME}_def.h
{
"${CMDNAME}",
"${CMDDESC}",
&${CMDENTRY},
&${HELPENTRY},
${CMDRESTRICT}
},
 
EOF
[ -n "${CMDALIAS}" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}_def.h
{
"${CMDALIAS}",
NULL,
&${CMDENTRY},
&${HELPENTRY},
${CMDRESTRICT}
},
 
EOF
local defname=$(toupper "${CMDNAME}")
echo "Creating ${OUTDIR}/entry.h ..."
cat << EOF > ${OUTDIR}/entry.h
#ifndef ${defname}_ENTRY_H
#define ${defname}_ENTRY_H
 
EOF
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/entry.h
/* Entry points for the ${CMDNAME} command */
extern int ${CMDENTRY}(char **);
extern void ${HELPENTRY}(unsigned int);
 
#endif /* ${defname}_ENTRY_H */
 
EOF
[ "${CMDTYPE}" = "builtin" ] && cat << EOF >> ${OUTDIR}/entry.h
/* Pick up cliuser_t */
#include "scli.h"
 
/* Entry points for the ${CMDNAME} command */
extern int * ${CMDENTRY}(char **, cliuser_t *);
extern void * ${HELPENTRY}(unsigned int);
 
#endif /* ${defname}_ENTRY_H */
 
EOF
echo "Creating ${OUTDIR}/${CMDNAME}.h ..."
cat << EOF > ${OUTDIR}/${CMDNAME}.h
#ifndef ${defname}_H
#define ${defname}_H
 
/* Prototypes for the ${CMDNAME} command, excluding entry points */
 
 
#endif /* ${defname}_H */
 
EOF
echo "Creating ${OUTDIR}/${CMDNAME}.c ..."
cat << EOF > ${OUTDIR}/${CMDNAME}.c
/* Automatically generated by ${PROGNAME} on ${TIMESTAMP}
* This is machine generated output. The author of ${PROGNAME} claims no
* copyright over the contents of this file. Where legally permitted, the
* contents herein are donated to the public domain.
*
* You should apply any license and copyright that you wish to this file,
* replacing this header in its entirety. */
 
#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include "util.h"
#include "errors.h"
#include "entry.h"
#include "${CMDNAME}.h"
#include "cmds.h"
 
static char *cmdname = "${CMDNAME}";
 
/* Dispays help for ${CMDNAME} in various levels */
void ${HELPENTRY}(unsigned int level)
{
printf("This is the %s help for '%s'.\n",
level ? EXT_HELP : SHORT_HELP, cmdname);
return;
}
 
EOF
[ "${CMDTYPE}" = "module" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c
/* Main entry point for ${CMDNAME}, accepts an array of arguments */
int ${CMDENTRY}(char **argv)
EOF
[ "${CMDTYPE}" = "builtin" ] && cat << EOF >> ${OUTDIR}/${CMDNAME}.c
/* Main entry point for ${CMDNAME}, accepts an array of arguments and a
* pointer to the cliuser_t structure */
int ${CMDENTRY}(char **argv, cliuser_t *usr)
EOF
cat << EOF >> ${OUTDIR}/${CMDNAME}.c
{
unsigned int argc;
unsigned int i;
 
/* Count the arguments */
for (argc = 0; argv[argc] != NULL; argc ++);
 
printf("%s %s\n", TEST_ANNOUNCE, cmdname);
printf("%d arguments passed to %s", argc - 1, cmdname);
 
if (argc < 2) {
printf("\n");
return CMD_SUCCESS;
}
 
printf(":\n");
for (i = 1; i < argc; i++)
printf("[%d] -> %s\n", i, argv[i]);
 
return CMD_SUCCESS;
}
 
EOF
printf "Done.\n\nYou should now modify %ss/%ss.h and ../Makefile" \
"${CMDTYPE}" "${CMDTYPE}"
printf " to include your new command.\n"
[ -n "$CMDALIAS" ] && {
printf "\nYou should also modify %ss/%s_aliases.h and " \
"${CMDTYPE}" "${CMDTYPE}"
printf "add %s as an alias for %s\n" \
"${CMDALIAS}" "${CMDNAME}"
}
printf "\nOnce completed, re-run make\n\n"
}
 
# Main program
 
TIMESTAMP="$(date)"
PROGNAME=$(basename $0)
PROGVER="0.0.1"
PROGMAINT="Tim Post <echo@echoreply.us>"
DEFAULT_COMMAND="cmdname"
 
# We need at least one
[ $# = 0 ] && usage && exit 1;
 
TEMP=$(getopt -o n:d:e:h:a:r:t:HV \
--long name:,desc:,entry:,help-entry:,alias:,restrict:,type:,help,version \
-- "$@") || {
echo "Try $PROGNAME --help for help"
}
 
eval set -- "$TEMP"
 
while true; do
case "$1" in
-n | --name)
CMDNAME="$2"
shift 2
continue
;;
-d | --desc)
CMDDESC="$2"
shift 2
continue
;;
-e | --entry)
CMDENTRY="$2"
shift 2
continue
;;
-h | --help-entry)
HELPENTRY="$2"
shift 2
continue
;;
-a | --alias)
CMDALIAS="$2"
shift 2
continue
;;
-r | --restrict)
CMDRESTRICT="$2"
shift 2
continue
;;
-t | --type)
CMDTYPE="$2"
shift 2
continue
;;
-H | --help)
usage
exit 0
;;
-V | --version)
echo "$PROGVER"
exit 0
;;
--)
break
;;
esac
done
 
# Pick up a location if one was specified
eval set -- "$*"
[ -n "$2" ] && OUTDIR="$2"
 
# Fill in defaults for whatever was not specified
[ -n "$CMDNAME" ] || CMDNAME="$DEFAULT_COMMAND"
[ -n "$CMDDESC" ] || CMDDESC="The $CMDNAME command"
[ -n "$CMDENTRY" ] || CMDENTRY="cmd_${CMDNAME}"
[ -n "$HELPENTRY" ] || HELPENTRY="help_cmd_${CMDNAME}"
[ -n "$CMDTYPE" ] || CMDTYPE="module"
[ -n "$OUTDIR" ] || OUTDIR="${CMDTYPE}s/${CMDNAME}"
 
# Builtins typically only need to be available in interactive mode,
# set the default accordingly.
[ -n "$CMDRESTRICT" ] || {
[ "$CMDTYPE" = "module" ] && CMDRESTRICT="both"
[ "$CMDTYPE" = "builtin" ] && CMDRESTRICT="interactive"
}
 
# Set the restriction level as the structure expects to see it
case "$CMDRESTRICT" in
0 | both)
CMDRESTRICT="0"
;;
1 | non-interactive)
CMDRESTRICT="1"
;;
-1 | interactive)
CMDRESTRICT="-1"
;;
*)
usage
exit 1
;;
esac
 
# Do a little sanity
[ -d $OUTDIR ] && {
echo "$OUTDIR already exists, remove it to proceed."
exit 1
}
 
mkdir -p ${OUTDIR} >/dev/null 2>&1 || {
echo "Could not create ${OUTDIR}, aborting!"
exit 1
}
 
# Generate the files and inform on how to include them based on options
generate_code
 
exit 0
 
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/branches/tracing/uspace/app/bdsh/cmds/builtins/cd/cd.c
0,0 → 1,106
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
 
#include "util.h"
#include "errors.h"
#include "entry.h"
#include "cmds.h"
#include "cd.h"
 
static char * cmdname = "cd";
 
void help_cmd_cd(unsigned int level)
{
if (level == HELP_SHORT) {
printf("`%s' changes the current working directory.\n", cmdname);
} else {
printf(
" %s <directory>\n"
" Change directory to <directory>, e.g `%s /sbin'\n",
cmdname, cmdname);
}
 
return;
}
 
/* This is a very rudamentary 'cd' command. It is not 'link smart' (yet) */
 
int cmd_cd(char **argv, cliuser_t *usr)
{
int argc, rc = 0;
 
argc = cli_count_args(argv);
 
/* We don't yet play nice with whitespace, a getopt implementation should
* protect "quoted\ destination" as a single argument. Its not our job to
* look for && || or redirection as the tokenizer should have done that
* (currently, it does not) */
 
if (argc > 2) {
cli_error(CL_EFAIL, "Too many arguments to `%s'", cmdname);
return CMD_FAILURE;
}
 
if (argc < 2) {
printf("%s - no directory specified. Try `help %s extended'\n",
cmdname, cmdname);
return CMD_FAILURE;
}
 
/* We have the correct # of arguments
* TODO: handle tidle (~) expansion? */
 
rc = chdir(argv[1]);
 
if (rc == 0) {
cli_set_prompt(usr);
return CMD_SUCCESS;
} else {
switch (rc) {
case ENOMEM:
cli_error(CL_EFAIL, "Destination path too long");
break;
case ENOENT:
cli_error(CL_ENOENT, "Invalid directory `%s'", argv[1]);
break;
default:
cli_error(CL_EFAIL, "Unable to change to `%s'", argv[1]);
break;
}
}
 
return CMD_FAILURE;
}
/branches/tracing/uspace/app/bdsh/cmds/builtins/cd/entry.h
0,0 → 1,12
#ifndef CD_ENTRY_H_
#define CD_ENTRY_H_
 
#include "scli.h"
 
/* Entry points for the cd command */
extern void help_cmd_cd(unsigned int);
extern int cmd_cd(char **, cliuser_t *);
 
#endif
 
 
/branches/tracing/uspace/app/bdsh/cmds/builtins/cd/cd_def.h
0,0 → 1,14
{
"cd",
"Change the current working directory",
&cmd_cd,
&help_cmd_cd,
-1
},
{
"chdir",
NULL,
&cmd_cd,
&help_cmd_cd,
-1
},
/branches/tracing/uspace/app/bdsh/cmds/builtins/cd/cd.h
0,0 → 1,7
#ifndef CD_H
#define CD_H
 
/* Prototypes for the cd command (excluding entry points) */
 
 
#endif
/branches/tracing/uspace/app/bdsh/cmds/builtins/builtins.h
0,0 → 1,13
#ifndef BUILTINS_H
#define BUILTINS_H
 
#include "config.h"
 
#include "cd/entry.h"
 
builtin_t builtins[] = {
#include "cd/cd_def.h"
{NULL, NULL, NULL, NULL}
};
 
#endif
/branches/tracing/uspace/app/bdsh/cmds/builtins/README
0,0 → 1,21
Commands that need to modify the running user structure defined in scli.h
should reside here. They (will) have a slightly different prototype that
allows passing the user structure to them for ease of modifications.
 
Examples of what should be a built-in and not a module would be:
 
cd (cliuser_t->cwd needs to be updated)
 
In the future, more user preferences will be set via built-in commands,
such as the formatting of the prompt string (HelenOS doesn't yet have
an environment, much less PS*, even if it did we'd likely do it a little
differently).
 
.... etc.
 
Anything that does _not_ need to use this structure should be included
as a module, not a built in. If you want to include a new command, there
is a 99% chance that you want it to be a module.
 
 
 
/branches/tracing/uspace/app/bdsh/cmds/builtins/builtin_aliases.h
0,0 → 1,11
#ifndef BUILTIN_ALIASES_H
#define BUILTIN_ALIASES_H
 
/* See modules/module_aliases.h for an explanation of this file */
 
char *builtin_aliases[] = {
"chdir", "cd",
NULL, NULL
};
 
#endif
/branches/tracing/uspace/app/bdsh/cmds/cmds.h
0,0 → 1,72
#ifndef CMDS_H
#define CMDS_H
 
#include "config.h"
#include "scli.h"
 
/* Temporary to store strings */
#define EXT_HELP "extended"
#define SHORT_HELP "short"
#define TEST_ANNOUNCE "Hello, this is :"
 
/* Simple levels of help displays */
#define HELP_SHORT 0
#define HELP_LONG 1
 
/* Acceptable buffer sizes (for strn functions) */
/* TODO: Move me, other files duplicate these needlessly */
#define BUFF_LARGE 1024
#define BUFF_SMALL 255
 
/* Return macros for int type entry points */
#define CMD_FAILURE 1
#define CMD_SUCCESS 0
 
/* Types for module command entry and help */
typedef int (* mod_entry_t)(char **);
typedef void (* mod_help_t)(unsigned int);
 
/* Built-in commands need to be able to modify cliuser_t */
typedef int (* builtin_entry_t)(char **, cliuser_t *);
typedef void (* builtin_help_t)(unsigned int);
 
/* Module structure */
typedef struct {
char *name; /* Name of the command */
char *desc; /* Description of the command */
mod_entry_t entry; /* Command (exec) entry function */
mod_help_t help; /* Command (help) entry function */
int restricted; /* Restricts to interactive/non-interactive only */
} module_t;
 
/* Builtin structure, same as modules except different types of entry points */
typedef struct {
char *name;
char *desc;
builtin_entry_t entry;
builtin_help_t help;
int restricted;
} builtin_t;
 
/* Declared in cmds/modules/modules.h and cmds/builtins/builtins.h
* respectively */
extern module_t modules[];
extern builtin_t builtins[];
 
/* Prototypes for module launchers */
extern int module_is_restricted(int);
extern int is_module(const char *);
extern int is_module_alias(const char *);
extern char * alias_for_module(const char *);
extern int help_module(int, unsigned int);
extern int run_module(int, char *[]);
 
/* Prototypes for builtin launchers */
extern int builtin_is_restricted(int);
extern int is_builtin(const char *);
extern int is_builtin_alias(const char *);
extern char * alias_for_builtin(const char *);
extern int help_builtin(int, unsigned int);
extern int run_builtin(int, char *[], cliuser_t *);
 
#endif
/branches/tracing/uspace/app/bdsh/cmds/mod_cmds.c
0,0 → 1,156
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
/* NOTES:
* module_* functions are pretty much identical to builtin_* functions at this
* point. On the surface, it would appear that making each function dual purpose
* would be economical.
*
* These are kept separate because the structures (module_t and builtin_t) may
* grow apart and become rather different, even though they're identical at this
* point.
*
* To keep things easy to hack, everything is separated. In reality this only adds
* 6 - 8 extra functions, but keeps each function very easy to read and modify. */
 
/* TODO:
* Many of these could be unsigned, provided the modules and builtins themselves
* can follow suit. Long term goal. */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "errors.h"
#include "cmds.h"
#include "module_aliases.h"
 
extern volatile unsigned int cli_interactive;
 
int module_is_restricted(int pos)
{
/* Restriction Levels:
* -1 -> Available only in interactive mode
* 0 -> Available in any mode
* 1 -> Available only in non-interactive mode */
 
module_t *mod = modules;
mod += pos;
/* We're interactive, and the module is OK to run */
if (cli_interactive && mod->restricted <= 0)
return 0;
/* We're not interactive, and the module is OK to run */
if (!cli_interactive && mod->restricted >= 0)
return 0;
 
/* Anything else is just a big fat no :) */
return 1;
}
 
/* Checks if an entry function matching command exists in modules[], if so
* its position in the array is returned */
int is_module(const char *command)
{
module_t *mod;
unsigned int i = 0;
 
if (NULL == command)
return -2;
 
for (mod = modules; mod->name != NULL; mod++, i++) {
if (!strcmp(mod->name, command))
return i;
}
 
return -1;
}
 
/* Checks if a module is an alias (sharing an entry point with another
* module). Returns 1 if so */
int is_module_alias(const char *command)
{
unsigned int i = 0;
 
if (NULL == command)
return -1;
 
for(i=0; mod_aliases[i] != NULL; i+=2) {
if (!strcmp(mod_aliases[i], command))
return 1;
}
 
return 0;
}
 
/* Returns the name of the module that an alias points to */
char *alias_for_module(const char *command)
{
unsigned int i = 0;
 
if (NULL == command)
return (char *)NULL;
 
for(i=0; mod_aliases[i] != NULL; i++) {
if (!strcmp(mod_aliases[i], command))
return (char *)mod_aliases[++i];
i++;
}
 
return (char *)NULL;
}
 
 
/* Invokes the 'help' entry function for the module at position (int) module,
* which wants an unsigned int to determine brief or extended display. */
int help_module(int module, unsigned int extended)
{
module_t *mod = modules;
 
mod += module;
 
if (NULL != mod->help) {
mod->help(extended);
return CL_EOK;
} else
return CL_ENOENT;
}
 
/* Invokes the module entry point modules[module], passing argv[] as an argument
* stack. */
int run_module(int module, char *argv[])
{
module_t *mod = modules;
 
mod += module;
 
if (NULL != mod->entry)
return ((int)mod->entry(argv));
 
return CL_ENOENT;
}
/branches/tracing/uspace/app/bdsh/cmds/builtin_cmds.c
0,0 → 1,126
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
/* Almost identical (for now) to mod_cmds.c , however this will not be the case
* soon as builtin_t is going to grow way beyond module_t */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "errors.h"
#include "cmds.h"
#include "builtin_aliases.h"
 
extern volatile unsigned int cli_interactive;
 
int builtin_is_restricted(int pos)
{
builtin_t *cmd = builtins;
cmd += pos;
 
if (cli_interactive && cmd->restricted <= 0)
return 0;
if (!cli_interactive && cmd->restricted >= 0)
return 0;
 
return 1;
}
 
int is_builtin(const char *command)
{
builtin_t *cmd;
unsigned int i = 0;
 
if (NULL == command)
return -2;
 
for (cmd = builtins; cmd->name != NULL; cmd++, i++) {
if (!strcmp(cmd->name, command))
return i;
}
 
return -1;
}
 
int is_builtin_alias(const char *command)
{
unsigned int i = 0;
 
if (NULL == command)
return -1;
 
for(i=0; builtin_aliases[i] != NULL; i+=2) {
if (!strcmp(builtin_aliases[i], command))
return 1;
}
 
return 0;
}
 
char *alias_for_builtin(const char *command)
{
unsigned int i = 0;
 
if (NULL == command)
return (char *)NULL;
 
for(i=0; builtin_aliases[i] != NULL; i++) {
if (!strcmp(builtin_aliases[i], command))
return (char *)builtin_aliases[++i];
i++;
}
 
return (char *)NULL;
}
 
int help_builtin(int builtin, unsigned int extended)
{
builtin_t *cmd = builtins;
 
cmd += builtin;
 
if (NULL != cmd->help) {
cmd->help(extended);
return CL_EOK;
} else
return CL_ENOENT;
}
 
int run_builtin(int builtin, char *argv[], cliuser_t *usr)
{
builtin_t *cmd = builtins;
 
cmd += builtin;
 
if (NULL != cmd->entry)
return((int)cmd->entry(argv, usr));
 
return CL_ENOENT;
}
/branches/tracing/uspace/app/bdsh/util.c
0,0 → 1,284
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* Copyright (C) 1998 by Wes Peters <wes@softweyr.com>
* Copyright (c) 1988, 1993 The Regents of the University of California.
* All rights reserved by all copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
/* NOTES:
* 1 - Various functions were adapted from FreeBSD (copyright holders noted above)
* these functions are identified with comments.
*
* 2 - Some of these have since appeared in libc. They remain here for various
* reasons, such as the eventual integration of garbage collection for things
* that allocate memory and don't automatically free it.
*
* 3 - Things that expect a pointer to an allocated string do _no_ sanity checking
* if developing on a simulator with no debugger, take care :)
*/
 
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdarg.h>
 
#include "config.h"
#include "errors.h"
#include "util.h"
 
extern volatile int cli_errno;
 
/* some platforms do not have strdup, implement it here.
* Returns a pointer to an allocated string or NULL on failure */
char * cli_strdup(const char *s1)
{
size_t len = strlen(s1) + 1;
void *ret = malloc(len);
 
if (ret == NULL) {
cli_errno = CL_ENOMEM;
return (char *) NULL;
}
 
cli_errno = CL_EOK;
return (char *) memcpy(ret, s1, len);
}
 
/*
* Take a previously allocated string (s1), re-size it to accept s2 and copy
* the contents of s2 into s1.
* Return -1 on failure, or the length of the copied string on success.
*/
int cli_redup(char **s1, const char *s2)
{
size_t len = strlen(s2) + 1;
 
if (! len)
return -1;
 
*s1 = realloc(*s1, len);
 
if (*s1 == NULL) {
cli_errno = CL_ENOMEM;
return -1;
}
 
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, s2, len);
cli_errno = CL_EOK;
return (int) len;
}
 
/* An asprintf() for formatting paths, similar to asprintf() but ensures
* the returned allocated string is <= PATH_MAX. On failure, an attempt
* is made to return the original string (if not null) unmodified.
*
* Returns: Length of the new string on success, 0 if the string was handed
* back unmodified, -1 on failure. On failure, cli_errno is set.
*
* We do not use POSIX_PATH_MAX, as it is typically much smaller than the
* PATH_MAX defined by the kernel.
*
* Use this like:
* if (1 > cli_psprintf(&char, "%s/%s", foo, bar)) {
* cli_error(cli_errno, "Failed to format path");
* stop_what_your_doing_as_your_out_of_memory();
* }
*/
 
int cli_psprintf(char **s1, const char *fmt, ...)
{
va_list ap;
size_t needed, base = PATH_MAX + 1;
int skipped = 0;
char *orig = NULL;
char *tmp = (char *) malloc(base);
 
/* Don't even touch s1, not enough memory */
if (NULL == tmp) {
cli_errno = CL_ENOMEM;
return -1;
}
 
/* If re-allocating s1, save a copy in case we fail */
if (NULL != *s1)
orig = cli_strdup(*s1);
 
/* Print the string to tmp so we can determine the size that
* we actually need */
memset(tmp, 0, sizeof(tmp));
va_start(ap, fmt);
/* vsnprintf will return the # of bytes not written */
skipped = vsnprintf(tmp, base, fmt, ap);
va_end(ap);
 
/* realloc/alloc s1 to be just the size that we need */
needed = strlen(tmp) + 1;
*s1 = realloc(*s1, needed);
 
if (NULL == *s1) {
/* No string lived here previously, or we failed to
* make a copy of it, either way there's nothing we
* can do. */
if (NULL == *orig) {
cli_errno = CL_ENOMEM;
return -1;
}
/* We can't even allocate enough size to restore the
* saved copy, just give up */
*s1 = realloc(*s1, strlen(orig) + 1);
if (NULL == *s1) {
free(tmp);
free(orig);
cli_errno = CL_ENOMEM;
return -1;
}
/* Give the string back as we found it */
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, orig, strlen(orig) + 1);
free(tmp);
free(orig);
cli_errno = CL_ENOMEM;
return 0;
}
 
/* Ok, great, we have enough room */
memset(*s1, 0, sizeof(*s1));
memcpy(*s1, tmp, needed);
free(tmp);
 
/* Free tmp only if s1 was reallocated instead of allocated */
if (NULL != orig)
free(orig);
 
if (skipped) {
/* s1 was bigger than PATH_MAX when expanded, however part
* of the string was printed. Tell the caller not to use it */
cli_errno = CL_ETOOBIG;
return -1;
}
 
/* Success! */
cli_errno = CL_EOK;
return (int) needed;
}
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
char * cli_strtok_r(char *s, const char *delim, char **last)
{
char *spanp, *tok;
int c, sc;
 
if (s == NULL && (s = *last) == NULL) {
cli_errno = CL_EFAIL;
return (NULL);
}
 
cont:
c = *s++;
for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
if (c == sc)
goto cont;
}
 
if (c == 0) { /* no non-delimiter characters */
*last = NULL;
return (NULL);
}
 
tok = s - 1;
 
for (;;) {
c = *s++;
spanp = (char *)delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = '\0';
*last = s;
return (tok);
}
} while (sc != 0);
}
}
 
/* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */
char * cli_strtok(char *s, const char *delim)
{
static char *last;
 
return (cli_strtok_r(s, delim, &last));
}
 
/* Count and return the # of elements in an array */
unsigned int cli_count_args(char **args)
{
unsigned int i;
 
for (i=0; args[i] != NULL; i++);
return i;
}
 
/* (re)allocates memory to store the current working directory, gets
* and updates the current working directory, formats the prompt
* string */
unsigned int cli_set_prompt(cliuser_t *usr)
{
usr->prompt = (char *) realloc(usr->prompt, PATH_MAX);
if (NULL == usr->prompt) {
cli_error(CL_ENOMEM, "Can not allocate prompt");
cli_errno = CL_ENOMEM;
return 1;
}
memset(usr->prompt, 0, sizeof(usr->prompt));
 
usr->cwd = (char *) realloc(usr->cwd, PATH_MAX);
if (NULL == usr->cwd) {
cli_error(CL_ENOMEM, "Can not allocate cwd");
cli_errno = CL_ENOMEM;
return 1;
}
memset(usr->cwd, 0, sizeof(usr->cwd));
 
usr->cwd = getcwd(usr->cwd, PATH_MAX - 1);
 
if (NULL == usr->cwd)
snprintf(usr->cwd, PATH_MAX, "(unknown)");
 
if (1 < cli_psprintf(&usr->prompt, "%s ", usr->cwd)) {
cli_error(cli_errno, "Failed to set prompt");
return 1;
}
 
return 0;
}
 
 
/branches/tracing/uspace/app/bdsh/Makefile
0,0 → 1,138
# Copyright (c) 2005, Martin Decky
# All rights reserved.
# Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# Neither the name of the original program's authors nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
 
include ../../../version
include ../../Makefile.config
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -I../../srv/kbd/include
 
LIBS = $(LIBC_PREFIX)/libc.a
DEFS += -DRELEASE=\"$(RELEASE)\"
 
ifdef REVISION
DEFS += "-DREVISION=\"$(TIMESTAMP)\""
endif
 
ifdef TIMESTAMP
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\""
endif
 
PROGRAM = bdsh
 
# Any directory that cleaning targets should know about
SUBDIRS = \
./ \
cmds/ \
cmds/modules/ \
cmds/modules/help/ \
cmds/modules/quit/ \
cmds/modules/mkdir/ \
cmds/modules/rm/ \
cmds/modules/cat/ \
cmds/modules/touch/ \
cmds/modules/ls/ \
cmds/modules/pwd/ \
cmds/modules/sleep/ \
cmds/modules/cp/ \
cmds/builtins/ \
cmds/builtins/cd/
 
SOURCES = \
cmds/modules/help/help.c \
cmds/modules/quit/quit.c \
cmds/modules/mkdir/mkdir.c \
cmds/modules/rm/rm.c \
cmds/modules/cat/cat.c \
cmds/modules/touch/touch.c \
cmds/modules/ls/ls.c \
cmds/modules/pwd/pwd.c \
cmds/modules/sleep/sleep.c \
cmds/modules/cp/cp.c \
cmds/builtins/cd/cd.c \
cmds/mod_cmds.c \
cmds/builtin_cmds.c \
errors.c \
input.c \
util.c \
exec.c \
scli.c
 
CFLAGS += -I. -Icmds/ -Icmds/builtins -Icmds/modules
 
OBJECTS = $(SOURCES:.c=.o)
 
# For easy cleaning, *.o is already handled
CLEANDIRS := $(addsuffix *~,$(SUBDIRS))
CLEANDIRS += $(addsuffix *.bak,$(SUBDIRS))
CLEANDIRS += $(addsuffix *.tmp,$(SUBDIRS))
CLEANDIRS += $(addsuffix *.out,$(SUBDIRS))
CLEANDIRS += $(addsuffix *.d,$(SUBDIRS))
CLEANDIRS += $(addsuffix *.gch,$(SUBDIRS) )
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(CFLAGS) $(INC) -c $< -o $@
@$(CC) -M $(CFLAGS) $(INC) $*.c > $*.d
 
$(PROGRAM): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(PROGRAM).map
 
# Everything else is a phony target
.PHONY: all clean distclean depend disasm
 
all: $(PROGRAM) disasm
 
clean:
@-rm -f $(OBJECTS)
@-rm -f $(PROGRAM)
@-rm -f $(PROGRAM).map
@-rm -f $(PROGRAM).disasm
@-rm -f $(CLEANDIRS)
 
depend:
@echo ''
 
disasm:
$(OBJDUMP) -d $(PROGRAM) >$(PROGRAM).disasm
 
distclean: clean
 
# Do not delete - dependencies
-include $(OBJECTS:.o=.d)
/branches/tracing/uspace/app/bdsh/scli.c
0,0 → 1,106
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "config.h"
#include "scli.h"
#include "input.h"
#include "util.h"
#include "errors.h"
#include "cmds/cmds.h"
 
/* See scli.h */
static cliuser_t usr;
 
/* Globals that are modified during start-up that modules/builtins
* should be aware of. */
volatile unsigned int cli_quit = 0;
volatile unsigned int cli_interactive = 1;
volatile unsigned int cli_verbocity = 1;
 
/* The official name of this program
* (change to your liking in configure.ac and re-run autoconf) */
const char *progname = PACKAGE_NAME;
 
/* These are not exposed, even to builtins */
static int cli_init(cliuser_t *);
static void cli_finit(cliuser_t *);
 
/* Constructor */
static int cli_init(cliuser_t *usr)
{
usr->line = (char *) NULL;
usr->name = "root";
usr->home = "/";
usr->cwd = (char *) NULL;
usr->prompt = (char *) NULL;
chdir(usr->home);
usr->lasterr = 0;
return (int) cli_set_prompt(usr);
}
 
/* Destructor */
static void cli_finit(cliuser_t *usr)
{
if (NULL != usr->line)
free(usr->line);
if (NULL != usr->prompt)
free(usr->prompt);
if (NULL != usr->cwd)
free(usr->cwd);
}
 
int main(int argc, char *argv[])
{
int ret = 0;
 
if (cli_init(&usr))
exit(EXIT_FAILURE);
 
printf("Welcome to %s - %s\nType `help' at any time for usage information.\n",
progname, PACKAGE_STRING);
 
while (!cli_quit) {
get_input(&usr);
if (NULL != usr.line) {
ret = tok_input(&usr);
cli_set_prompt(&usr);
usr.lasterr = ret;
}
}
goto finit;
 
finit:
cli_finit(&usr);
return ret;
}
/branches/tracing/uspace/app/bdsh/config.h
0,0 → 1,38
/* Various things that are used in many files
* Various temporary port work-arounds are addressed in __HELENOS__ , this
* serves as a convenience and later as a guide to make "phony.h" for future
* ports */
 
/* Specific port work-arounds : */
#ifndef PATH_MAX
#define PATH_MAX 255
#endif
 
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#endif
 
/* Work around for getenv() */
#define PATH "/srv:/app"
#define PATH_DELIM ":"
 
/* Used in many places */
#define SMALL_BUFLEN 256
#define LARGE_BUFLEN 1024
 
/* How many words (arguments) are permitted, how big can a whole
* sentence be? Similar to ARG_MAX */
#define WORD_MAX 255
#define INPUT_MAX 1024
 
/* Leftovers from Autoconf */
#define PACKAGE_MAINTAINER "Tim Post"
#define PACKAGE_BUGREPORT "echo@echoreply.us"
#define PACKAGE_NAME "bdsh"
#define PACKAGE_STRING "The brain dead shell"
#define PACKAGE_TARNAME "bdsh"
#define PACKAGE_VERSION "0.0.1"
 
 
 
/branches/tracing/uspace/app/bdsh/README
0,0 → 1,252
BDSH - The Brain Dead Shell | Design Documentation
--------------------------------------------------
 
Overview:
=========
 
BDSH was written as a drop in command line interface for HelenOS to permit
interactive access to persistent file systems in development. BDSH was
written from scratch with a very limited userspace standard C library in
mind. Much like the popular Busybox program, BDSH provides a very limited
shell with limited common UNIX creature comforts built in.
 
Porting Busybox (and by extension ASH) would have taken much longer to
complete, much less make stable due to stark differences between Linux and
Spartan with regards to IPC, term I/O and process creation. BDSH was written
and made stable within the space of less than 30 days.
 
BDSH will eventually evolve and be refined into the HelenOS equivalent
of Busybox. While BDSH is now very intrinsic to HelenOS, its structure and
use of strictly lower level functions makes it extremely easy to port.
 
Design:
=======
 
BDSH is made up of three basic components:
 
1. Main i/o, error handling and task management
2. The builtin sub system
3. The module sub system
 
The main part handles user input, reports errors, spawns external tasks and
provides a convenient entry point for built-in and modular commands. A simple
structure, cliuser_t keeps track of the user's vitals, such as their current
working directory (and eventually uid, home directory, etc if they apply).
 
This part defines and exposes all functions that are not intrinsic to a
certain built in or modular command. For instance: string handlers,
module/builtin search and launch functions, error handlers and other things
can be found here.
 
Builtin commands are commands that must have access to cliuser_t, which is
not exposed to modular commands. For instance, the 'cd' command must update
the current working directory, which is stored in cliuser_t. As such, the
entry types for builtin commands are slightly different.
 
Modular commands do not need anything more than the basic functions that are
exposed by default. They do not need to modify cliuser_t, they are just self
contained. A modular command could very easily be made into a stand alone
program, likewise any stand alone program could easily become a modular
command.
 
Both modular and builtin commands share two things in common. Both must have
two entry points, one to invoke the command and one to invoke a help display
for the command. Exec (main()) entry points are int * and are expected to
return a value. Help entry points are void *, no return value is expected.
 
They are typed as such (from cmds.h):
 
/* Types for module command entry and help */
typedef int (* mod_entry_t)(char **);
typedef void (* mod_help_t)(unsigned int);
 
/* Built-in commands need to be able to modify cliuser_t */
typedef int (* builtin_entry_t)(char **, cliuser_t *);
typedef void (* builtin_help_t)(unsigned int);
 
As you can see, both modular and builtin commands expect an array of
arguments, however bulitins also expect to be pointed to cliuser_t.
 
Both are defined with the same simple structure:
 
/* Module structure */
typedef struct {
char *name; /* Name of the command */
char *desc; /* Description of the command */
mod_entry_t entry; /* Command (exec) entry function */
mod_help_t help; /* Command (help) entry function */
int restricted; /* Restricts to interactive/non-interactive only */
} module_t;
 
NOTE: Builtin commands may grow in this respect, that is why they are
defined separately.
 
Builtins, of course, would use the builtin_entry_t type. The name of the
command is used to associate user input to a possible entry point. The
description is a short (40 - 60 chars) summary of what the command does. Both
entry points are then defined, and the restrict value is used to determine a
commands availability.
 
Restriction levels are easy, a command is either available exclusively within
interactive mode, exclusively within non-interactive mode or both. If you are
looking at a prompt, you are in interactive mode. If you issue a command like
this:
 
/sbin/bdsh command [arg1] [arg2]
 
... you are in non interactive mode. This is done when you need to force the
parent shell to be the one who actually handles the command, or ensure that
/sbin/ls was used in lieu of the built in 'ls' when in non-interactive mode.
 
The values are:
0 : Unrestricted
-1 : Interactive only
1 : Non-interactive only
 
A script to generate skeletal files for a new command is included, it can be
found in cmds/mknewcmd. To generate a new modular command named 'foo', which
should also be reachable by typing 'f00', you would issue this command:
 
./mknewcmd -n foo -a f00 -t module
 
This generates all needed files and instructs you on how to include your new
command in the build and make it accessible. By default, the command will be
unrestricted. Builtin commands can be created by changing 'module' to
'builtin'
 
There are more options to mknewcmd, which allow you to specify the
description, entry point, help entry point, or restriction. By default, names
just follow the command such as cmd_foo(), help_cmd_foo(), 'The foo command',
etc. If you want to see the options and explanations in detail, use
./mknewcmd --help.
 
When working with commands, keep in mind that only the main and help entry
points need to be exposed. If commands share the same functions, put them
where they are exposed to all commands, without the potential oops of those
functions going away if the command is eliminated in favor of a stand alone
external program.
 
The util.c file is a great place to put those types of functions.
 
Also, be careful with globals, option structures, etc. The compiler will
generally tell you if you've made a mistake, however declaring:
 
volatile int foo
 
... in a command will allow for anything else to pick it up. Sometimes
this could be desirable .. other times not. When communicating between
builtins and the main system, try to use cliuser_t. The one exception
for this is the cli_quit global, since everything may at some point
need to check it. Modules should only communicate their return value.
 
Symbolic constants that everything needs should go in the config.h file,
however this is not the place to define shared macros.
 
Making a program into a module
==============================
 
If you have some neat program that would be useful as a modular command,
converting it is not very hard. The following steps should get you through
the process easily (assuming your program is named 'foo'):
 
1: Use mknewcmd to generate the skeletal files.
 
2: Change your "usage()" command as shown:
-- void usage(...)
++ void help_cmd_foo(unsigned int level)
 
'level' is either 0 or 1, indicating the level of help requested.
If the help / usage function currently exits based on how it is
called, you'll need to change it.
 
3: Change the programs "main()" as shown:
-- int main(int argc, char **argv)
++ int cmd_foo(char **argv)
-- return 1;
++ return CMD_FAILURE;
-- return 0;
++ return CMD_SUCCESS;
 
NOTE: If main is void, you'll need to change it and ensure that its
expecting an array of arguments, even if they'll never be read or
used. I.e.:
 
-- void main(void)
++ int cmd_foo(char **argv)
 
4: Don't expose more than the entry and help points:
-- void my_function(int n)
++ static void my_function(int n)
 
5: Copy/paste to the stub generated by mknewcmd then add your files to the
Makefile. Be sure to add any directories that you made to the SUBDIRS so
that a 'make clean' will clean them.
 
Provided that all functions that your calling are available in the
userspace C library, your program should compile just fine and appear
as a modular command.
 
Overcoming userspace libc obstacles
===================================
 
A quick glance through the util.c file will reveal functions like
cli_strdup(), cli_strtok(), cli_strtok_r() and more. Those are functions
that were missing from userspace libc when BDSH was born. Later, after
porting what was needed from FBSD/NBSD, the real functions appeared in
the userspace libc after being tested in their cli_* implementations.
 
Those functions remain because they guarantee that bdsh will work even
on systems that lack them. Additionally, more BDSH specific stuff can
go into them, such as error handling and reporting when malloc() fails.
 
You will also notice that FILE, fopen() (and all friends), ato*() and
other common things might be missing. The HelenOS userspace C library is
still very young, you are sure to run into something that you want/need
which is missing.
 
When that happens, you have three options:
 
1 - Implement it internally in util.c , when its tested and stable send a
patch to HelenOS asking for your function to be included in libc. This is
the best option, as you not only improve BDSH .. but HelenOS as a whole.
 
2 - Work around it. Not everyone can implement / port fopen() and all of
its friends. Make open(), read(), write() (etc) work if at all possible.
 
3 - Send an e-mail to the HelenOS development mailing list. Explain why you
need the function and what its absence is holding up.
 
If what you need is part of a library that is typically a shared object, try
to implement a 'mini' version of it. Currently, all userspace applications
are statically linked. Giving up creature comforts for size while avoiding
temporary 'band aids' is never frowned upon.
 
Most of all, don't get discouraged .. ask for some help prior to giving up
if you just can't accomplish something with the limited means provided.
 
Contributing
============
 
I will take any well written patch that sanely improves or expands BDSH. Send
me a patch against the trunk revision, or, if you like a Mercurial repository
is also maintained at http://echoreply.us/hg/bdsh.hg and kept in sync with
the trunk.
 
Please be sure to follow the simple coding standards outlined at
http://www.helenos.eu/cstyle (mostly just regarding formatting), test your
changes and make sure your patch applies cleanly against the latest revision.
 
All patches submitted must be your original code, or a derivative work of
something licensed under the same 3 clause BSD license as BDSH. See LICENSE
for more information.
 
When sending patches, you agree that your work will be published under the
same 3 clause BSD license as BDSH itself. Failure to ensure that anything
you used is not under the same or less restrictive license could cause major
issues for BDSH in the future .. please be sure. Also, please don't forget
to add yourself in the AUTHORS file, as I am horrible about keeping such
things up to date.
 
 
 
 
/branches/tracing/uspace/app/bdsh/scli.h
0,0 → 1,16
#ifndef SCLI_H
#define SCLI_H
 
#include "config.h"
#include <stdint.h>
 
typedef struct {
char *name;
char *home;
char *line;
char *cwd;
char *prompt;
int lasterr;
} cliuser_t;
 
#endif
/branches/tracing/uspace/app/bdsh/util.h
0,0 → 1,17
#ifndef UTIL_H
#define UTIL_H
 
#include "scli.h"
 
/* Internal string handlers */
extern char * cli_strdup(const char *);
extern int cli_redup(char **, const char *);
extern int cli_psprintf(char **, const char *, ...);
extern char * cli_strtok_r(char *, const char *, char **);
extern char * cli_strtok(char *, const char *);
 
/* Utility functions */
extern unsigned int cli_count_args(char **);
extern unsigned int cli_set_prompt(cliuser_t *usr);
 
#endif
/branches/tracing/uspace/app/bdsh/input.c
0,0 → 1,177
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
* Copyright (c) 2008, Jiri Svoboda - All Rights Reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io/stream.h>
 
#include "config.h"
#include "util.h"
#include "scli.h"
#include "input.h"
#include "errors.h"
#include "exec.h"
 
extern volatile unsigned int cli_interactive;
 
/* Not exposed in input.h */
static void cli_restricted(char *);
static void read_line(char *, int);
 
/* More than a macro than anything */
static void cli_restricted(char *cmd)
{
printf("%s is not available in %s mode\n", cmd,
cli_interactive ? "interactive" : "non-interactive");
 
return;
}
 
/* Tokenizes input from console, sees if the first word is a built-in, if so
* invokes the built-in entry point (a[0]) passing all arguments in a[] to
* the handler */
int tok_input(cliuser_t *usr)
{
char *cmd[WORD_MAX];
int n = 0, i = 0;
int rc = 0;
char *tmp;
 
if (NULL == usr->line)
return CL_EFAIL;
 
tmp = cli_strdup(usr->line);
 
/* Break up what the user typed, space delimited */
 
/* TODO: Protect things in quotes / ticks, expand wildcards */
cmd[n] = cli_strtok(tmp, " ");
while (cmd[n] && n < WORD_MAX) {
cmd[++n] = cli_strtok(NULL, " ");
}
 
/* We have rubbish */
if (NULL == cmd[0]) {
rc = CL_ENOENT;
goto finit;
}
 
/* Its a builtin command */
if ((i = (is_builtin(cmd[0]))) > -1) {
/* Its not available in this mode, see what try_exec() thinks */
if (builtin_is_restricted(i)) {
rc = try_exec(cmd[0], cmd);
if (rc)
/* No external matching it could be found, tell the
* user that the command does exist, but is not
* available in this mode. */
cli_restricted(cmd[0]);
goto finit;
}
/* Its a builtin, its available, run it */
rc = run_builtin(i, cmd, usr);
goto finit;
/* We repeat the same dance for modules */
} else if ((i = (is_module(cmd[0]))) > -1) {
if (module_is_restricted(i)) {
rc = try_exec(cmd[0], cmd);
if (rc)
cli_restricted(cmd[0]);
goto finit;
}
rc = run_module(i, cmd);
goto finit;
} else {
/* Its not a module or builtin, restricted or otherwise.
* See what try_exec() thinks of it and just pass its return
* value back to the caller */
rc = try_exec(cmd[0], cmd);
goto finit;
}
 
finit:
if (NULL != usr->line) {
free(usr->line);
usr->line = (char *) NULL;
}
if (NULL != tmp)
free(tmp);
 
return rc;
}
 
/* Borrowed from Jiri Svoboda's 'cli' uspace app */
static void read_line(char *buffer, int n)
{
char c;
int chars;
 
chars = 0;
while (chars < n - 1) {
c = getchar();
if (c < 0)
return;
if (c == '\n')
break;
if (c == '\b') {
if (chars > 0) {
putchar('\b');
--chars;
}
continue;
}
putchar(c);
buffer[chars++] = c;
}
putchar('\n');
buffer[chars] = '\0';
}
 
/* TODO:
* Implement something like editline() / readline(), if even
* just for command history and making arrows work. */
void get_input(cliuser_t *usr)
{
char line[INPUT_MAX];
size_t len = 0;
 
printf("%s", usr->prompt);
read_line(line, INPUT_MAX);
len = strlen(line);
/* Make sure we don't have rubbish or a C/R happy user */
if (len == 0 || line[0] == '\n')
return;
usr->line = cli_strdup(line);
 
return;
}
 
/branches/tracing/uspace/app/bdsh/input.h
0,0 → 1,11
#ifndef INPUT_H
#define INPUT_H
 
#include "cmds/cmds.h"
 
/* prototypes */
 
extern void get_input(cliuser_t *);
extern int tok_input(cliuser_t *);
 
#endif
/branches/tracing/uspace/app/bdsh/exec.c
0,0 → 1,129
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
/* The VERY basics of execute in place support. These are buggy, leaky
* and not nearly done. Only here for beta testing!! You were warned!!
* TODO:
* Hash command lookups to save time
* Create a running pointer to **path and advance/rewind it as we go */
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
 
#include "config.h"
#include "util.h"
#include "exec.h"
#include "errors.h"
 
/* FIXME: Just have find_command() return an allocated string */
char *found;
 
static char *find_command(char *);
static unsigned int try_access(const char *);
 
/* work-around for access() */
static unsigned int try_access(const char *f)
{
int fd;
 
fd = open(f, O_RDONLY);
if (fd > -1) {
close(fd);
return 0;
} else
return -1;
}
 
/* Returns the full path of "cmd" if cmd is found, else just hand back
* cmd as it was presented */
static char *find_command(char *cmd)
{
char *path_tok;
char *path[PATH_MAX];
int n = 0, i = 0;
size_t x = strlen(cmd) + 2;
 
found = (char *)malloc(PATH_MAX);
 
/* The user has specified a full or relative path, just give it back. */
if (-1 != try_access(cmd)) {
return (char *) cmd;
}
 
path_tok = cli_strdup(PATH);
 
/* Extract the PATH env to a path[] array */
path[n] = cli_strtok(path_tok, PATH_DELIM);
while (NULL != path[n]) {
if ((strlen(path[n]) + x ) > PATH_MAX) {
cli_error(CL_ENOTSUP,
"Segment %d of path is too large, search ends at segment %d",
n, n-1);
break;
}
path[++n] = cli_strtok(NULL, PATH_DELIM);
}
 
/* We now have n places to look for the command */
for (i=0; path[i]; i++) {
memset(found, 0, sizeof(found));
snprintf(found, PATH_MAX, "%s/%s", path[i], cmd);
if (-1 != try_access(found)) {
free(path_tok);
return (char *) found;
}
}
 
/* We didn't find it, just give it back as-is. */
free(path_tok);
return (char *) cmd;
}
 
unsigned int try_exec(char *cmd, char **argv)
{
task_id_t tid;
char *tmp;
 
tmp = cli_strdup(find_command(cmd));
free(found);
 
tid = task_spawn((const char *)tmp, (const char **)argv);
free(tmp);
 
if (tid == 0) {
cli_error(CL_EEXEC, "Can not spawn %s", cmd);
return 1;
} else {
return 0;
}
}
/branches/tracing/uspace/app/bdsh/exec.h
0,0 → 1,7
#ifndef EXEC_H
#define EXEC_H
 
#include <task.h>
 
extern unsigned int try_exec(char *, char **);
#endif
/branches/tracing/uspace/app/bdsh/errors.c
0,0 → 1,87
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the original program's authors nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
 
#include "config.h"
#include "errors.h"
#include "errstr.h"
 
volatile int cli_errno = CL_EOK;
extern volatile unsigned int cli_quit;
 
/* Error printing, translation and handling functions */
 
 
/* Look up errno in cl_errors and return the corresponding string.
* Return NULL if not found */
static char *err2str(int err)
{
 
if (NULL != cl_errors[err])
return cl_errors[err];
 
return (char *)NULL;
}
 
/* Print an error report signifying errno, which is translated to
* its corresponding human readable string. If errno > 0, raise the
* cli_quit int that tells the main program loop to exit immediately */
 
void cli_error(int err, const char *fmt, ...)
{
va_list vargs;
va_start(vargs, fmt);
vprintf(fmt, vargs);
va_end(vargs);
 
if (NULL != err2str(err))
printf(" (%s)\n", err2str(err));
else
printf(" (Unknown Error %d)\n", err);
 
/* If fatal, raise cli_quit so that we try to exit
* gracefully. This will break the main loop and
* invoke the destructor */
if (err == CL_EFATAL)
cli_quit = 1;
 
return;
 
}
 
 
 
 
 
/branches/tracing/uspace/app/bdsh/errors.h
0,0 → 1,22
#ifndef ERRORS_H
#define ERRORS_H
 
/* Various error levels */
#define CL_EFATAL -1
#define CL_EOK 0
#define CL_EFAIL 1
#define CL_EBUSY 2
#define CL_ENOENT 3
#define CL_ENOMEM 4
#define CL_EPERM 5
#define CL_ENOTSUP 6
#define CL_EEXEC 7
#define CL_EEXISTS 8
#define CL_ETOOBIG 9
 
/* Just like 'errno' */
extern volatile int cli_errno;
 
extern void cli_error(int, const char *, ...);
 
#endif
/branches/tracing/uspace/app/bdsh/errstr.h
0,0 → 1,23
#ifndef ERRSTR_H
#define ERRSTR_H
 
/* Simple array to translate error codes to meaningful strings */
 
static char *cl_errors[] = {
"Success",
"Failure",
"Busy",
"No Such Entry",
"Not Enough Memory",
"Permission Denied",
"Method Not Supported",
"Bad command or file name",
"Entry already exists",
"Object too large",
NULL
};
 
static char *err2str(int);
 
#endif
 
/branches/tracing/uspace/app/bdsh/TODO
0,0 → 1,57
This is a very brain dead shell. It needs some love, coffee or perhaps beer.
Currently, you can't even really call it a shell, its more of a CLI that
offers some shell like creature comforts.
 
This was written in a hurry to provide some means of testing persistent file
systems in HelenOS. It does its job, its nowhere near complete but it is
actively developed. If your reading this, its likely that you're looking for
some functionality that is not yet present. Prior to filing a bug report,
please make sure that what you want is not on the list below.
 
A list of things to do:
-----------------------
 
* rm: add support for recursively removing directories and files therein
 
* Port an editor (vim?)
 
* Finish cat / cp
 
* Support basic redirection (i.e ls > foo.txt)
 
* Expand wildcards (i.e. *.txt), don't worry about variables for now
 
* Basic scripting
 
* Hash previously found commands
 
* Improve input, add history / etc (port libedit?)
 
* Add wrappers for signal, sigaction to make ports to modules easier
 
* Add 'echo' and 'printf' modules.
 
Regarding POSIX:
----------------
POSIX is a standard for Unix-like operating systems. HelenOS is (mostly) just
a kernel at this point with a few userspace programs that facilitate testing
of the kernel and file systems.
 
HelenOS is not a Unix-like operating system. HelenOS is its own thing, a modern
microkernel OS and many directions are not yet set.
 
Please do not e-mail me to point out that modular implementations that resemble
typical core utilities do not conform to some POSIX standard, these are temporary
and serve the useful purpose of testing persistent file systems.
 
Contributing:
-------------
If you feel like doing any of the above to-do items, I am echo@echoreply.us. Please
e-mail me and let me know your working on something so that I do not unwittingly
duplicate your efforts. You can also e-mail the HelenOS list directly:
 
HelenOS development mailing list <helenos-devel@lists.modry.cz>
Subscribe here if you like: http://lists.modry.cz/cgi-bin/listinfo/helenos-devel
 
Cheers and happy hacking!
--Tim
/branches/tracing/uspace/app/bdsh/AUTHORS
0,0 → 1,17
 
Written by Tim Post <echo@echoreply.us> to serve as a primitive shell
for HelenOS, or as a template to make a command line interface that
offers shell like creature comforts.
 
This program was mostly written from scratch, some existing code was
used from other various free software projects:
 
* Based on the HelenOS testing sub-system written by Martin Decky
 
* cli_strtok() and cli_strtok_r() (util.c) were adapted from the FreeBSD
strtok() and strtok_r() functions written by Wes Peters.
 
* read_line() (input.c) was written by Jiri Svoboda
 
Individual author copyrights are listed in the headers of each file.
 
/branches/tracing/uspace/app/bdsh/LICENSE
0,0 → 1,28
Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
All rights reserved.
 
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
 
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
 
Neither the name of the original program's authors nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
/branches/tracing/uspace/app/init/init.c
45,10 → 45,6
#include "init.h"
#include "version.h"
 
#define BUF_SIZE 150000
 
static char *buf;
 
static void console_wait(void)
{
while (get_cons_phone() < 0)
55,13 → 51,13
usleep(50000); // FIXME
}
 
static bool mount_tmpfs(void)
static bool mount_fs(const char *fstype)
{
int rc = -1;
while (rc < 0) {
rc = mount("tmpfs", "/", "initrd");
rc = mount(fstype, "/", "initrd");
 
switch (rc) {
case EOK:
printf(NAME ": Root filesystem mounted\n");
72,6 → 68,9
case ELIMIT:
printf(NAME ": Unable to mount root filesystem\n");
return false;
case ENOENT:
printf(NAME ": Unknown filesystem type (%s)\n", fstype);
return false;
default:
sleep(5); // FIXME
}
82,28 → 81,16
 
static void spawn(char *fname)
{
char *argv[2];
 
printf(NAME ": Spawning %s\n", fname);
int fd = open(fname, O_RDONLY);
if (fd >= 0) {
ssize_t rd;
size_t len = 0;
// FIXME: cannot do long reads yet
do {
rd = read(fd, buf + len, 1024);
if (rd > 0)
len += rd;
} while (rd > 0);
if (len > 0) {
task_spawn(buf, len);
sleep(1); // FIXME
}
close(fd);
 
argv[0] = fname;
argv[1] = NULL;
 
if (task_spawn(fname, argv) != 0) {
/* Success */
sleep(1);
}
}
 
112,27 → 99,21
info_print();
sleep(5); // FIXME
if (!mount_tmpfs()) {
if (!mount_fs("tmpfs") && !mount_fs("fat")) {
printf(NAME ": Exiting\n");
return -1;
}
buf = malloc(BUF_SIZE);
// FIXME: spawn("/srv/pci");
spawn("/srv/fb");
spawn("/srv/kbd");
spawn("/srv/console");
// FIXME: spawn("/sbin/pci");
spawn("/sbin/fb");
spawn("/sbin/kbd");
spawn("/sbin/console");
console_wait();
version_print();
spawn("/sbin/fat");
spawn("/sbin/tetris");
// FIXME: spawn("/sbin/tester");
spawn("/sbin/klog");
spawn("/app/bdsh");
free(buf);
return 0;
}
 
/branches/tracing/uspace/app/init/Makefile
61,7 → 61,7
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
74,9 → 74,11
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/app/tester/tester.c
108,8 → 108,17
printf("*\t\t\tRun all safe tests\n");
}
 
int main(void)
int main(int argc, char **argv)
{
printf("Number of arguments: %d\n", argc);
if (argv) {
printf("Arguments:");
while (*argv) {
printf(" '%s'", *argv++);
}
printf("\n");
}
 
while (1) {
char c;
test_t *test;
125,7 → 134,7
if (c == 'a')
break;
if (c > 'a')
if (test->name == NULL)
printf("Unknown test\n\n");
else
run_test(test);
/branches/tracing/uspace/app/tester/Makefile
60,7 → 60,7
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
73,9 → 73,11
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d -S $(OUTPUT) >$(OUTPUT).disasm
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/app/cli/cli.c
0,0 → 1,125
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup cli cli
* @brief Trivial command-line interface for running programs.
* @{
*/
/**
* @file
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <task.h>
 
#define LINE_BUFFER_SIZE 128
static char line_buffer[LINE_BUFFER_SIZE];
 
#define MAX_ARGS 16
static char *argv_buf[MAX_ARGS + 1];
 
static void read_line(char *buffer, int n)
{
char c;
int chars;
 
printf("> ");
 
chars = 0;
while (chars < n - 1) {
c = getchar();
if (c < 0) exit(0);
if (c == '\n') break;
if (c == '\b') {
if (chars > 0) {
putchar('\b');
--chars;
}
continue;
}
putchar(c);
buffer[chars++] = c;
}
 
putchar('\n');
buffer[chars] = '\0';
}
 
static void program_run(void)
{
char *p;
int n;
 
p = line_buffer;
n = 0;
 
while (n < MAX_ARGS) {
argv_buf[n++] = p;
p = strchr(p, ' ');
if (p == NULL) break;
 
*p++ = '\0';
}
argv_buf[n] = NULL;
 
printf("spawn task '%s' with %d args\n", argv_buf[0], n);
printf("args:");
int i;
for (i = 0; i < n; ++i) {
printf(" '%s'", argv_buf[i]);
}
printf("\n");
 
task_spawn(argv_buf[0], argv_buf);
}
 
 
int main(int argc, char *argv[])
{
printf("This is CLI\n");
 
while (1) {
read_line(line_buffer, LINE_BUFFER_SIZE);
printf("'%s'\n", line_buffer);
if (strcmp(line_buffer, "exit") == 0)
break;
if (line_buffer[0] != '\0')
program_run();
}
 
printf("Bye\n");
return 0;
}
 
/** @}
*/
 
/branches/tracing/uspace/app/cli/Makefile
0,0 → 1,86
#
# Copyright (c) 2005 Martin Decky
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
include ../../../version
include ../../Makefile.config
 
## Setup toolchain
#
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
 
CFLAGS += -I../../srv/kbd/include
 
LIBS = $(LIBC_PREFIX)/libc.a
DEFS += -DRELEASE=\"$(RELEASE)\"
 
ifdef REVISION
DEFS += "-DREVISION=\"$(REVISION)\""
endif
 
ifdef TIMESTAMP
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\""
endif
 
## Sources
#
 
OUTPUT = cli
SOURCES = \
cli.c
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/tracing/uspace/app/tetris/input.c
96,6 → 96,7
struct timeval starttv, endtv, *s;
static ipc_call_t charcall;
ipcarg_t rc;
int cons_phone;
 
/*
* Someday, select() will do this for us.
110,8 → 111,11
s = NULL;
 
if (!lastchar) {
if (!getchar_inprog)
getchar_inprog = async_send_2(1,CONSOLE_GETCHAR,0,0,&charcall);
if (!getchar_inprog) {
cons_phone = get_cons_phone();
getchar_inprog = async_send_2(cons_phone,
CONSOLE_GETCHAR, 0, 0, &charcall);
}
if (!s)
async_wait_for(getchar_inprog, &rc);
else if (async_wait_timeout(getchar_inprog, &rc, s->tv_usec) == ETIMEOUT) {
/branches/tracing/uspace/app/tetris/Makefile
10,7 → 10,7
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
22,9 → 22,12
 
clean:
-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend *.o
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
 
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/app/klog/Makefile
47,7 → 47,7
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
60,9 → 60,11
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/lib/libfs/libfs.c
36,6 → 36,7
 
#include "libfs.h"
#include "../../srv/vfs/vfs.h"
#include "../../srv/rd/rd.h"
#include <errno.h>
#include <async.h>
#include <ipc/ipc.h>
330,5 → 331,62
ops->node_put(tmp);
}
 
/** Read data from a block device.
*
* @param phone Phone to be used to communicate with the device.
* @param buffer Communication buffer shared with the device.
* @param bufpos Pointer to the first unread valid offset within the
* communication buffer.
* @param buflen Pointer to the number of unread bytes that are ready in
* the communication buffer.
* @param pos Device position to be read.
* @param dst Destination buffer.
* @param size Size of the destination buffer.
* @param block_size Block size to be used for the transfer.
*
* @return True on success, false on failure.
*/
bool libfs_blockread(int phone, void *buffer, off_t *bufpos, size_t *buflen,
off_t *pos, void *dst, size_t size, size_t block_size)
{
off_t offset = 0;
size_t left = size;
while (left > 0) {
size_t rd;
if (*bufpos + left < *buflen)
rd = left;
else
rd = *buflen - *bufpos;
if (rd > 0) {
/*
* Copy the contents of the communication buffer to the
* destination buffer.
*/
memcpy(dst + offset, buffer + *bufpos, rd);
offset += rd;
*bufpos += rd;
*pos += rd;
left -= rd;
}
if (*bufpos == *buflen) {
/* Refill the communication buffer with a new block. */
ipcarg_t retval;
int rc = async_req_2_1(phone, RD_READ_BLOCK,
*pos / block_size, block_size, &retval);
if ((rc != EOK) || (retval != EOK))
return false;
*bufpos = 0;
*buflen = block_size;
}
}
return true;
}
 
/** @}
*/
/branches/tracing/uspace/lib/libfs/libfs.h
69,6 → 69,9
 
extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
 
extern bool libfs_blockread(int, void *, off_t *, size_t *, off_t *, void *,
size_t, size_t);
 
#endif
 
/** @}
/branches/tracing/uspace/lib/libc/include/getopt.h
0,0 → 1,71
/* $NetBSD: getopt.h,v 1.10.6.1 2008/05/18 12:30:09 yamt Exp $ */
 
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
/* Ported to HelenOS August 2008 by Tim Post <echo@echoreply.us> */
 
#ifndef _GETOPT_H_
#define _GETOPT_H_
 
#include <unistd.h>
 
/*
* Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions
*/
#define no_argument 0
#define required_argument 1
#define optional_argument 2
 
struct option {
/* name of long option */
const char *name;
/*
* one of no_argument, required_argument, and optional_argument:
* whether option takes an argument
*/
int has_arg;
/* if not NULL, set *flag to val when option found */
int *flag;
/* if flag not NULL, value to set *flag to; else return value */
int val;
};
 
/* HelenOS Port - These need to be exposed for legacy getopt() */
extern char *optarg;
extern int optind, opterr, optopt;
extern int optreset;
 
int getopt_long(int, char * const *, const char *,
const struct option *, int *);
 
/* HelenOS Port : Expose legacy getopt() */
int getopt(int, char * const [], const char *);
 
#endif /* !_GETOPT_H_ */
/branches/tracing/uspace/lib/libc/include/as.h
42,6 → 42,7
 
extern void *as_area_create(void *address, size_t size, int flags);
extern int as_area_resize(void *address, size_t size, int flags);
extern int as_area_change_flags(void *address, int flags);
extern int as_area_destroy(void *address);
extern void *set_maxheapsize(size_t mhs);
extern void * as_get_mappable_page(size_t sz);
/branches/tracing/uspace/lib/libc/include/string.h
47,6 → 47,7
 
extern int strcmp(const char *, const char *);
extern int strncmp(const char *, const char *, size_t);
extern int stricmp(const char *, const char *);
 
extern char *strcpy(char *, const char *);
extern char *strncpy(char *, const char *, size_t);
55,6 → 56,8
 
extern size_t strlen(const char *);
 
extern char *strdup(const char *);
 
extern char *strchr(const char *, int);
extern char *strrchr(const char *, int);
 
/branches/tracing/uspace/lib/libc/include/vfs/vfs.h
35,6 → 35,10
#ifndef LIBC_VFS_H_
#define LIBC_VFS_H_
 
#include <sys/types.h>
 
extern char *absolutize(const char *, size_t *);
 
extern int mount(const char *, const char *, const char *);
 
#endif
/branches/tracing/uspace/lib/libc/include/stdio.h
54,16 → 54,17
 
extern int getchar(void);
 
extern int puts(const char * str);
extern int putchar(int c);
extern int puts(const char *);
extern int putchar(int);
 
extern int printf(const char *fmt, ...);
extern int sprintf(char *str, const char *fmt, ...);
extern int snprintf(char *str, size_t size, const char *fmt, ...);
extern int printf(const char *, ...);
extern int asprintf(char **, const char *, ...);
extern int sprintf(char *, const char *fmt, ...);
extern int snprintf(char *, size_t , const char *, ...);
 
extern int vprintf(const char *fmt, va_list ap);
extern int vsprintf(char *str, const char *fmt, va_list ap);
extern int vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
extern int vprintf(const char *, va_list);
extern int vsprintf(char *, const char *, va_list);
extern int vsnprintf(char *, size_t, const char *, va_list);
 
#define fprintf(f, fmt, ...) printf(fmt, ##__VA_ARGS__)
 
/branches/tracing/uspace/lib/libc/include/task.h
40,7 → 40,7
typedef uint64_t task_id_t;
 
extern task_id_t task_get_id(void);
extern int task_spawn(void *image, size_t size);
extern task_id_t task_spawn(const char *path, const char *argv[]);
 
#endif
 
/branches/tracing/uspace/lib/libc/include/libc.h
48,7 → 48,7
#define __SYSCALL6(id, p1, p2, p3, p4, p5, p6) \
__syscall(p1, p2, p3, p4, p5, p6,id)
 
extern void __main(void);
extern void __main(void *pcb_ptr);
extern void __exit(void);
 
#endif
/branches/tracing/uspace/lib/libc/include/loader/pcb.h
0,0 → 1,74
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup fs
* @{
*/
/** @file
* @brief Program Control Block interface.
*/
 
#ifndef LIBC_PCB_H_
#define LIBC_PCB_H_
 
#include <sys/types.h>
 
typedef void (*entry_point_t)(void);
 
/**
* Holds pointers to data passed from the program loader to the program
* and/or to the dynamic linker. This includes the program entry point,
* arguments, environment variables etc.
*/
typedef struct {
/** Program entry point */
entry_point_t entry;
 
/** Number of command-line arguments */
int argc;
/** Command-line arguments */
char **argv;
 
/*
* ELF-specific data
*/
/** Pointer to ELF dynamic section of the program */
void *dynamic;
/** Pointer to dynamic section of the runtime linker */
void *rtld_dynamic;
/** Runtime-linker load bias */
uintptr_t rtld_bias;
} pcb_t;
 
extern pcb_t *__pcb;
 
#endif
 
/**
* @}
*/
/branches/tracing/uspace/lib/libc/include/io/stream.h
40,6 → 40,7
#define EMFILE -17
 
extern void open_console(void);
extern void close_console(void);
extern void klog_update(void);
 
extern ssize_t read_stdin(void *, size_t);
/branches/tracing/uspace/lib/libc/include/smc.h
0,0 → 1,45
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#ifndef LIBC_SMC_H_
#define LIBC_SMC_H_
 
#include <sys/types.h>
 
extern int smc_coherence(void *address, size_t size);
 
#endif
 
/** @}
*/
/branches/tracing/uspace/lib/libc/include/ctype.h
76,6 → 76,14
}
}
 
static inline int tolower(int c)
{
if (isupper(c))
return (c + ('a' - 'A' > 0 ? 'a' - 'A' : 'A' - 'a'));
else
return c;
}
 
#endif
 
/** @}
/branches/tracing/uspace/lib/libc/include/ipc/loader.h
0,0 → 1,50
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libcipc
* @{
*/
/** @file
*/
 
#ifndef LIBC_LOADER_H_
#define LIBC_LOADER_H_
 
#include <ipc/ipc.h>
 
typedef enum {
LOADER_HELLO = IPC_FIRST_USER_METHOD,
LOADER_SET_PATHNAME,
LOADER_SET_ARGS,
LOADER_RUN
} fb_request_t;
 
#endif
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/task.c
1,5 → 1,6
/*
* Copyright (c) 2006 Jakub Jermar
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
33,7 → 34,14
*/
 
#include <task.h>
#include <ipc/ipc.h>
#include <ipc/loader.h>
#include <libc.h>
#include <string.h>
#include <stdlib.h>
#include <async.h>
#include <errno.h>
#include <vfs/vfs.h>
 
task_id_t task_get_id(void)
{
44,10 → 52,136
return task_id;
}
 
int task_spawn(void *image, size_t size)
static int task_spawn_loader(void)
{
return __SYSCALL2(SYS_TASK_SPAWN, (sysarg_t) image, (sysarg_t) size);
int phone_id, rc;
 
rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id);
if (rc != 0)
return rc;
 
return phone_id;
}
 
static int loader_set_args(int phone_id, const char *argv[])
{
aid_t req;
ipc_call_t answer;
ipcarg_t rc;
 
const char **ap;
char *dp;
char *arg_buf;
size_t buffer_size;
size_t len;
 
/*
* Serialize the arguments into a single array. First
* compute size of the buffer needed.
*/
ap = argv;
buffer_size = 0;
while (*ap != NULL) {
buffer_size += strlen(*ap) + 1;
++ap;
}
 
arg_buf = malloc(buffer_size);
if (arg_buf == NULL) return ENOMEM;
 
/* Now fill the buffer with null-terminated argument strings */
ap = argv;
dp = arg_buf;
while (*ap != NULL) {
strcpy(dp, *ap);
dp += strlen(*ap) + 1;
 
++ap;
}
 
/* Send serialized arguments to the loader */
 
req = async_send_0(phone_id, LOADER_SET_ARGS, &answer);
rc = ipc_data_write_start(phone_id, (void *)arg_buf, buffer_size);
if (rc != EOK) {
async_wait_for(req, NULL);
return rc;
}
 
async_wait_for(req, &rc);
if (rc != EOK) return rc;
 
/* Free temporary buffer */
free(arg_buf);
 
return EOK;
}
 
/** Create a new task by running an executable from VFS.
*
* @param path pathname of the binary to execute
* @param argv command-line arguments
* @return ID of the newly created task or zero on error.
*/
task_id_t task_spawn(const char *path, const char *argv[])
{
int phone_id;
ipc_call_t answer;
aid_t req;
int rc;
ipcarg_t retval;
 
char *pa;
size_t pa_len;
 
pa = absolutize(path, &pa_len);
if (!pa)
return 0;
 
/* Spawn a program loader */
phone_id = task_spawn_loader();
if (phone_id < 0)
return 0;
 
/*
* Say hello so that the loader knows the incoming connection's
* phone hash.
*/
rc = async_req_0_0(phone_id, LOADER_HELLO);
if (rc != EOK)
return 0;
 
/* Send program pathname */
req = async_send_0(phone_id, LOADER_SET_PATHNAME, &answer);
rc = ipc_data_write_start(phone_id, (void *)pa, pa_len);
if (rc != EOK) {
async_wait_for(req, NULL);
return 1;
}
 
async_wait_for(req, &retval);
if (retval != EOK)
goto error;
 
/* Send arguments */
rc = loader_set_args(phone_id, argv);
if (rc != EOK)
goto error;
 
/* Request loader to start the program */
rc = async_req_0_0(phone_id, LOADER_RUN);
if (rc != EOK)
goto error;
 
/* Success */
ipc_hangup(phone_id);
return 1;
 
/* Error exit */
error:
ipc_hangup(phone_id);
return 0;
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/getopt.c
0,0 → 1,478
/* $NetBSD: getopt_long.c,v 1.21.4.1 2008/01/09 01:34:14 matt Exp $ */
 
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
 
/* Ported to HelenOS August 2008 by Tim Post <echo@echoreply.us> */
 
#include <assert.h>
#include <stdarg.h>
#include <err.h>
#include <errno.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
 
/* HelenOS Port : We're incorporating only the modern getopt_long with wrappers
* to keep legacy getopt() usage from breaking. All references to REPLACE_GETOPT
* are dropped, we just include the code */
 
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
 
 
#define IGNORE_FIRST (*options == '-' || *options == '+')
#define PRINT_ERROR ((opterr) && ((*options != ':') \
|| (IGNORE_FIRST && options[1] != ':')))
/*HelenOS Port - POSIXLY_CORRECT is always false */
#define IS_POSIXLY_CORRECT 0
#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
/* XXX: GNU ignores PC if *options == '-' */
#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
 
/* return values */
#define BADCH (int)'?'
#define BADARG ((IGNORE_FIRST && options[1] == ':') \
|| (*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
 
#define EMSG ""
 
static int getopt_internal(int, char **, const char *);
static int gcd(int, int);
static void permute_args(int, int, int, char **);
 
static const char *place = EMSG; /* option letter processing */
 
/* XXX: set optreset to 1 rather than these two */
static int nonopt_start = -1; /* first non option argument (for permute) */
static int nonopt_end = -1; /* first option after non options (for permute) */
 
/* Error messages */
 
/* HelenOS Port: Calls to warnx() were eliminated (as we have no stderr that
* may be redirected) and replaced with printf. As such, error messages now
* end in a newline */
 
static const char recargchar[] = "option requires an argument -- %c\n";
static const char recargstring[] = "option requires an argument -- %s\n";
static const char ambig[] = "ambiguous option -- %.*s\n";
static const char noarg[] = "option doesn't take an argument -- %.*s\n";
static const char illoptchar[] = "unknown option -- %c\n";
static const char illoptstring[] = "unknown option -- %s\n";
 
 
/*
* Compute the greatest common divisor of a and b.
*/
static int
gcd(a, b)
int a;
int b;
{
int c;
 
c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}
return b;
}
 
/*
* Exchange the block from nonopt_start to nonopt_end with the block
* from nonopt_end to opt_end (keeping the same order of arguments
* in each block).
*/
static void
permute_args(panonopt_start, panonopt_end, opt_end, nargv)
int panonopt_start;
int panonopt_end;
int opt_end;
char **nargv;
{
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
 
assert(nargv != NULL);
 
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
 
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
pos -= nnonopts;
else
pos += nopts;
swap = nargv[pos];
nargv[pos] = nargv[cstart];
nargv[cstart] = swap;
}
}
}
 
/*
* getopt_internal --
* Parse argc/argv argument vector. Called by user level routines.
* Returns -2 if -- is found (can be long option or end of options marker).
*/
static int
getopt_internal(nargc, nargv, options)
int nargc;
char **nargv;
const char *options;
{
char *oli; /* option letter list index */
int optchar;
 
assert(nargv != NULL);
assert(options != NULL);
 
optarg = NULL;
 
/*
* XXX Some programs (like rsyncd) expect to be able to
* XXX re-initialize optind to 0 and have getopt_long(3)
* XXX properly function again. Work around this braindamage.
*/
if (optind == 0)
optind = 1;
 
if (optreset)
nonopt_start = nonopt_end = -1;
start:
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc) { /* end of argument vector */
place = EMSG;
if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start;
}
nonopt_start = nonopt_end = -1;
return -1;
}
if ((*(place = nargv[optind]) != '-')
|| (place[1] == '\0')) { /* found non-option */
place = EMSG;
if (IN_ORDER) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++];
return INORDER;
}
if (!PERMUTE) {
/*
* if no permutation wanted, stop parsing
* at first non-option
*/
return -1;
}
/* do permutation */
if (nonopt_start == -1)
nonopt_start = optind;
else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
nonopt_start = optind -
(nonopt_end - nonopt_start);
nonopt_end = -1;
}
optind++;
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
if (place[1] && *++place == '-') { /* found "--" */
place++;
return -2;
}
}
if ((optchar = (int)*place++) == (int)':' ||
(oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
/* option letter unknown or ':' */
if (!*place)
++optind;
if (PRINT_ERROR)
printf(illoptchar, optchar);
optopt = optchar;
return BADCH;
}
if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
/* XXX: what if no long options provided (called by getopt)? */
if (*place)
return -2;
 
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
printf(recargchar, optchar);
optopt = optchar;
return BADARG;
} else /* white space */
place = nargv[optind];
/*
* Handle -W arg the same as --arg (which causes getopt to
* stop parsing).
*/
return -2;
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
++optind;
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) /* no white space */
optarg = *place;
/* XXX: disable test for :: if PC? (GNU doesn't) */
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
printf(recargchar, optchar);
optopt = optchar;
return BADARG;
} else
optarg = nargv[optind];
}
place = EMSG;
++optind;
}
/* dump back option letter */
return optchar;
}
 
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt(nargc, nargv, options)
int nargc;
char * const *nargv;
const char *options;
{
int retval;
 
assert(nargv != NULL);
assert(options != NULL);
 
retval = getopt_internal(nargc, (char **)nargv, options);
if (retval == -2) {
++optind;
/*
* We found an option (--), so if we skipped non-options,
* we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end, optind,
(char **)nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
retval = -1;
}
return retval;
}
 
/*
* getopt_long --
* Parse argc/argv argument vector.
*/
int
getopt_long(nargc, nargv, options, long_options, idx)
int nargc;
char * const *nargv;
const char *options;
const struct option *long_options;
int *idx;
{
int retval;
 
#define IDENTICAL_INTERPRETATION(_x, _y) \
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
long_options[(_x)].flag == long_options[(_y)].flag && \
long_options[(_x)].val == long_options[(_y)].val)
 
assert(nargv != NULL);
assert(options != NULL);
assert(long_options != NULL);
/* idx may be NULL */
 
retval = getopt_internal(nargc, (char **)nargv, options);
if (retval == -2) {
char *current_argv, *has_equal;
size_t current_argv_len;
int i, ambiguous, match;
 
current_argv = (char *)place;
match = -1;
ambiguous = 0;
 
optind++;
place = EMSG;
 
if (*current_argv == '\0') { /* found "--" */
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, (char **)nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
return -1;
}
if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
current_argv_len))
continue;
 
if (strlen(long_options[i].name) ==
(unsigned)current_argv_len) {
/* exact match */
match = i;
ambiguous = 0;
break;
}
if (match == -1) /* partial match */
match = i;
else if (!IDENTICAL_INTERPRETATION(i, match))
ambiguous = 1;
}
if (ambiguous) {
/* ambiguous abbreviation */
if (PRINT_ERROR)
printf(ambig, (int)current_argv_len,
current_argv);
optopt = 0;
return BADCH;
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
printf(noarg, (int)current_argv_len,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of
* flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
return BADARG;
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
if (has_equal)
optarg = has_equal;
else if (long_options[match].has_arg ==
required_argument) {
/*
* optional argument doesn't use
* next nargv
*/
optarg = nargv[optind++];
}
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
/*
* Missing argument; leading ':'
* indicates no error should be generated
*/
if (PRINT_ERROR)
printf(recargstring, current_argv);
/*
* XXX: GNU sets optopt to val regardless
* of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
--optind;
return BADARG;
}
} else { /* unknown option */
if (PRINT_ERROR)
printf(illoptstring, current_argv);
optopt = 0;
return BADCH;
}
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
retval = 0;
} else
retval = long_options[match].val;
if (idx)
*idx = match;
}
return retval;
#undef IDENTICAL_INTERPRETATION
}
 
/branches/tracing/uspace/lib/libc/generic/as.c
85,6 → 85,20
return __SYSCALL1(SYS_AS_AREA_DESTROY, (sysarg_t ) address);
}
 
/** Change address-space area flags.
*
* @param address Virtual address pointing into the address space area being
* modified.
* @param flags New flags describing type of the area.
*
* @return Zero on success or a code from @ref errno.h on failure.
*/
int as_area_change_flags(void *address, int flags)
{
return __SYSCALL2(SYS_AS_AREA_CHANGE_FLAGS, (sysarg_t) address,
(sysarg_t) flags);
}
 
static size_t heapsize = 0;
static size_t maxheapsize = (size_t) (-1);
 
/branches/tracing/uspace/lib/libc/generic/pcb.c
0,0 → 1,40
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <loader/pcb.h>
 
pcb_t *__pcb;
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/string.c
38,8 → 38,8
#include <limits.h>
#include <align.h>
#include <sys/types.h>
#include <malloc.h>
 
 
/* Dummy implementation of mem/ functions */
 
void *memset(void *s, int c, size_t n)
66,9 → 66,10
adst[i].n = asrc[i].n;
for (j = 0; j < n % sizeof(unsigned long); j++)
((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j];
((unsigned char *) (((unsigned long *) dst) + i))[j] =
((unsigned char *) (((unsigned long *) src) + i))[j];
return (char *) src;
return (char *) dst;
}
 
void *memcpy(void *dst, const void *src, size_t n)
75,7 → 76,8
{
int i, j;
 
if (((long) dst & (sizeof(long) - 1)) || ((long) src & (sizeof(long) - 1)))
if (((long) dst & (sizeof(long) - 1)) ||
((long) src & (sizeof(long) - 1)))
return unaligned_memcpy(dst, src, n);
 
for (i = 0; i < n / sizeof(unsigned long); i++)
82,9 → 84,10
((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
for (j = 0; j < n % sizeof(unsigned long); j++)
((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j];
((unsigned char *) (((unsigned long *) dst) + i))[j] =
((unsigned char *) (((unsigned long *) src) + i))[j];
return (char *) src;
return (char *) dst;
}
 
void *memmove(void *dst, const void *src, size_t n)
95,22 → 98,23
return memcpy(dst, src, n);
 
for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--)
((unsigned char *) ((unsigned long *) dst))[j] = ((unsigned char *) ((unsigned long *) src))[j];
((unsigned char *) ((unsigned long *) dst))[j] =
((unsigned char *) ((unsigned long *) src))[j];
 
for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--)
((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
return (char *) src;
return (char *) dst;
}
 
/** Compare two memory areas.
*
* @param s1 Pointer to the first area to compare.
* @param s2 Pointer to the second area to compare.
* @param len Size of the first area in bytes. Both areas must have the same
* length.
* @return If len is 0, return zero. If the areas match, return zero.
* Otherwise return non-zero.
* @param s1 Pointer to the first area to compare.
* @param s2 Pointer to the second area to compare.
* @param len Size of the first area in bytes. Both areas must have
* the same length.
* @return If len is 0, return zero. If the areas match, return
* zero. Otherwise return non-zero.
*/
int bcmp(const char *s1, const char *s2, size_t len)
{
120,8 → 124,9
}
 
/** Count the number of characters in the string, not including terminating 0.
* @param str string
* @return number of characters in string.
*
* @param str String.
* @return Number of characters in string.
*/
size_t strlen(const char *str)
{
141,7 → 146,6
c++;
return (a[c] - b[c]);
}
 
int strncmp(const char *a, const char *b, size_t n)
155,10 → 159,22
}
 
/** Return pointer to the first occurence of character c in string
* @param str scanned string
* @param c searched character (taken as one byte)
* @return pointer to the matched character or NULL if it is not found in given string.
int stricmp(const char *a, const char *b)
{
int c = 0;
while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
c++;
return (tolower(a[c]) - tolower(b[c]));
}
 
/** Return pointer to the first occurence of character c in string.
*
* @param str Scanned string.
* @param c Searched character (taken as one byte).
* @return Pointer to the matched character or NULL if it is not
* found in given string.
*/
char *strchr(const char *str, int c)
{
171,10 → 187,12
return NULL;
}
 
/** Return pointer to the last occurence of character c in string
* @param str scanned string
* @param c searched character (taken as one byte)
* @return pointer to the matched character or NULL if it is not found in given string.
/** Return pointer to the last occurence of character c in string.
*
* @param str Scanned string.
* @param c Searched character (taken as one byte).
* @return Pointer to the matched character or NULL if it is not
* found in given string.
*/
char *strrchr(const char *str, int c)
{
191,13 → 209,16
 
/** Convert string to a number.
* Core of strtol and strtoul functions.
* @param nptr pointer to string
* @param endptr if not NULL, function stores here pointer to the first invalid character
* @param base zero or number between 2 and 36 inclusive
* @param sgn its set to 1 if minus found
* @return result of conversion.
*
* @param nptr Pointer to string.
* @param endptr If not NULL, function stores here pointer to the first
* invalid character.
* @param base Zero or number between 2 and 36 inclusive.
* @param sgn It's set to 1 if minus found.
* @return Result of conversion.
*/
static unsigned long _strtoul(const char *nptr, char **endptr, int base, char *sgn)
static unsigned long
_strtoul(const char *nptr, char **endptr, int base, char *sgn)
{
unsigned char c;
unsigned long result = 0;
219,7 → 240,8
/* FIXME: set errno to EINVAL */
return 0;
}
if ((base == 16) && (*str == '0') && ((str[1] == 'x') || (str[1] == 'X'))) {
if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
(str[1] == 'X'))) {
str += 2;
}
} else {
238,7 → 260,8
 
while (*str) {
c = *str;
c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 : (c <= '9' ? c - '0' : 0xff)));
c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
(c <= '9' ? c - '0' : 0xff)));
if (c > base) {
break;
}
257,7 → 280,10
}
if (str == tmpptr) {
/* no number was found => first invalid character is the first character of the string */
/*
* No number was found => first invalid character is the first
* character of the string.
*/
/* FIXME: set errno to EINVAL */
str = nptr;
result = 0;
275,14 → 301,17
}
 
/** Convert initial part of string to long int according to given base.
* The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-').
* If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one.
* If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8).
* Otherwise the base 0 is taken as decimal.
* @param nptr pointer to string
* @param endptr if not NULL, function stores here pointer to the first invalid character
* @param base zero or number between 2 and 36 inclusive
* @return result of conversion.
* The number may begin with an arbitrary number of whitespaces followed by
* optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
* inserted and the number will be taken as hexadecimal one. If the base is 0
* and the number begin with a zero, number will be taken as octal one (as with
* base 8). Otherwise the base 0 is taken as decimal.
*
* @param nptr Pointer to string.
* @param endptr If not NULL, function stores here pointer to the first
* invalid character.
* @param base Zero or number between 2 and 36 inclusive.
* @return Result of conversion.
*/
long int strtol(const char *nptr, char **endptr, int base)
{
305,14 → 334,17
 
 
/** Convert initial part of string to unsigned long according to given base.
* The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-').
* If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one.
* If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8).
* Otherwise the base 0 is taken as decimal.
* @param nptr pointer to string
* @param endptr if not NULL, function stores here pointer to the first invalid character
* @param base zero or number between 2 and 36 inclusive
* @return result of conversion.
* The number may begin with an arbitrary number of whitespaces followed by
* optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
* inserted and the number will be taken as hexadecimal one. If the base is 0
* and the number begin with a zero, number will be taken as octal one (as with
* base 8). Otherwise the base 0 is taken as decimal.
*
* @param nptr Pointer to string.
* @param endptr If not NULL, function stores here pointer to the first
* invalid character
* @param base Zero or number between 2 and 36 inclusive.
* @return Result of conversion.
*/
unsigned long strtoul(const char *nptr, char **endptr, int base)
{
353,5 → 385,16
return orig;
}
 
char * strdup(const char *s1)
{
size_t len = strlen(s1) + 1;
void *ret = malloc(len);
 
if (ret == NULL)
return (char *) NULL;
 
return (char *) memcpy(ret, s1, len);
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/libc.c
48,8 → 48,10
#include <ipc/ipc.h>
#include <async.h>
#include <as.h>
#include <loader/pcb.h>
 
extern char _heap;
extern int main(int argc, char *argv[]);
 
void _exit(int status)
{
56,9 → 58,11
thread_exit(status);
}
 
void __main(void)
void __main(void *pcb_ptr)
{
fibril_t *f;
int argc;
char **argv;
 
(void) as_area_create(&_heap, 1, AS_AREA_WRITE | AS_AREA_READ);
_async_init();
66,6 → 70,19
__tcb_set(f->tcb);
open_console();
 
/* Save the PCB pointer */
__pcb = (pcb_t *)pcb_ptr;
 
if (__pcb == NULL) {
argc = 0;
argv = NULL;
} else {
argc = __pcb->argc;
argv = __pcb->argv;
}
 
main(argc, argv);
}
 
void __exit(void)
/branches/tracing/uspace/lib/libc/generic/ipc.c
682,7 → 682,7
{
int res;
sysarg_t tmp_flags;
res = ipc_call_sync_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst,
res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst,
(ipcarg_t) size, arg, NULL, &tmp_flags);
if (flags)
*flags = tmp_flags;
742,7 → 742,7
*/
int ipc_share_out_start(int phoneid, void *src, int flags)
{
return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0,
return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0,
(ipcarg_t) flags);
}
 
803,7 → 803,7
*/
int ipc_data_read_start(int phoneid, void *dst, size_t size)
{
return ipc_call_sync_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst,
return async_req_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst,
(ipcarg_t) size);
}
 
862,7 → 862,7
*/
int ipc_data_write_start(int phoneid, void *src, size_t size)
{
return ipc_call_sync_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src,
return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src,
(ipcarg_t) size);
}
 
/branches/tracing/uspace/lib/libc/generic/vfs/vfs.c
59,9 → 59,10
char *cwd_path = NULL;
size_t cwd_len = 0;
 
static char *absolutize(const char *path, size_t *retlen)
char *absolutize(const char *path, size_t *retlen)
{
char *ncwd_path;
char *ncwd_path_nc;
 
futex_down(&cwd_futex);
size_t len = strlen(path);
70,28 → 71,40
futex_up(&cwd_futex);
return NULL;
}
ncwd_path = malloc(len + cwd_len + 1);
if (!ncwd_path) {
ncwd_path_nc = malloc(cwd_len + 1 + len + 1);
if (!ncwd_path_nc) {
futex_up(&cwd_futex);
return NULL;
}
strcpy(ncwd_path, cwd_path);
ncwd_path[cwd_len] = '/';
ncwd_path[cwd_len + 1] = '\0';
strcpy(ncwd_path_nc, cwd_path);
ncwd_path_nc[cwd_len] = '/';
ncwd_path_nc[cwd_len + 1] = '\0';
} else {
ncwd_path = malloc(len + 1);
if (!ncwd_path) {
ncwd_path_nc = malloc(len + 1);
if (!ncwd_path_nc) {
futex_up(&cwd_futex);
return NULL;
}
ncwd_path[0] = '\0';
ncwd_path_nc[0] = '\0';
}
strcat(ncwd_path, path);
if (!canonify(ncwd_path, retlen)) {
strcat(ncwd_path_nc, path);
ncwd_path = canonify(ncwd_path_nc, retlen);
if (!ncwd_path) {
futex_up(&cwd_futex);
free(ncwd_path);
free(ncwd_path_nc);
return NULL;
}
/*
* We need to clone ncwd_path because canonify() works in-place and thus
* the address in ncwd_path need not be the same as ncwd_path_nc, even
* though they both point into the same dynamically allocated buffer.
*/
ncwd_path = strdup(ncwd_path);
free(ncwd_path_nc);
if (!ncwd_path) {
futex_up(&cwd_futex);
return NULL;
}
futex_up(&cwd_futex);
return ncwd_path;
}
105,7 → 118,8
 
static int device_get_handle(char *name, dev_handle_t *handle)
{
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT,
0);
if (phone < 0)
return phone;
171,6 → 185,15
free(mpa);
return (int) rc;
}
/* Ask VFS whether it likes fs_name. */
rc = async_req_0_0(vfs_phone, IPC_M_PING);
if (rc != EOK) {
async_wait_for(req, NULL);
async_serialize_end();
futex_up(&vfs_phone_futex);
free(mpa);
return (int) rc;
}
rc = ipc_data_write_start(vfs_phone, (void *)mpa, mpa_len);
if (rc != EOK) {
async_wait_for(req, NULL);
222,6 → 245,9
async_serialize_end();
futex_up(&vfs_phone_futex);
free(pa);
 
if (rc != EOK)
return (int) rc;
return (int) IPC_GET_ARG1(answer);
}
 
285,7 → 311,7
if (rc == EOK)
return (ssize_t) IPC_GET_ARG1(answer);
else
return -1;
return rc;
}
 
ssize_t write(int fildes, const void *buf, size_t nbyte)
/branches/tracing/uspace/lib/libc/generic/vfs/canonify.c
125,6 → 125,7
static void set_first_slash(token_t *t, token_t *tfsl, token_t *tlcomp)
{
*tfsl = *t;
*tlcomp = *t;
}
static void save_component(token_t *t, token_t *tfsl, token_t *tlcomp)
{
/branches/tracing/uspace/lib/libc/generic/smc.c
0,0 → 1,45
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <libc.h>
#include <sys/types.h>
 
int smc_coherence(void *address, size_t size)
{
return __SYSCALL2(SYS_SMC_COHERENCE, (sysarg_t) address,
(sysarg_t) size);
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/io/sprintf.c
48,7 → 48,6
va_start(args, fmt);
ret = vsprintf(str, fmt, args);
 
va_end(args);
 
return ret;
/branches/tracing/uspace/lib/libc/generic/io/asprintf.c
0,0 → 1,79
/*
* Copyright (c) 2006 Josef Cejka
* Copyright (c) 2008 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup libc
* @{
*/
/** @file
*/
 
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <io/printf_core.h>
 
static int asprintf_prewrite(const char *str, size_t count, void *unused)
{
return count;
}
 
/** Allocate and print to string.
*
* @param strp Address of the pointer where to store the address of
* the newly allocated string.
* @fmt Format strin.
*
* @return Number of characters printed or a negative error code.
*/
int asprintf(char **strp, const char *fmt, ...)
{
struct printf_spec ps = {
asprintf_prewrite,
NULL
};
int ret;
va_list args;
 
va_start(args, fmt);
ret = printf_core(fmt, &ps, args);
va_end(args);
if (ret > 0) {
*strp = malloc(ret + 20);
if (!*strp)
return -1;
va_start(args, fmt);
vsprintf(*strp, fmt, args);
va_end(args);
}
 
return ret;
}
 
/** @}
*/
/branches/tracing/uspace/lib/libc/generic/io/vsnprintf.c
38,22 → 38,27
#include <io/printf_core.h>
 
struct vsnprintf_data {
size_t size; /* total space for string */
size_t len; /* count of currently used characters */
char *string; /* destination string */
size_t size; /* total space for string */
size_t len; /* count of currently used characters */
char *string; /* destination string */
};
 
/** Write string to given buffer.
* Write at most data->size characters including trailing zero. According to C99 has snprintf to return number
* of characters that would have been written if enough space had been available. Hence the return value is not
* number of really printed characters but size of input string. Number of really used characters
* is stored in data->len.
* @param str source string to print
* @param count size of source string
* @param data structure with destination string, counter of used space and total string size.
* @return number of characters to print (not characters really printed!)
* Write at most data->size characters including trailing zero. According to C99
* has snprintf to return number of characters that would have been written if
* enough space had been available. Hence the return value is not number of
* really printed characters but size of input string. Number of really used
* characters is stored in data->len.
*
* @param str Source string to print.
* @param count Size of the source string.
* @param data Structure with destination string, counter of used space
* and total string size.
* @return Number of characters to print (not characters really
* printed!)
*/
static int vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data)
static int
vsnprintf_write(const char *str, size_t count, struct vsnprintf_data *data)
{
size_t i;
i = data->size - data->len;
63,7 → 68,10
}
if (i == 1) {
/* We have only one free byte left in buffer => write there trailing zero */
/*
* We have only one free byte left in buffer => write there
* trailing zero.
*/
data->string[data->size - 1] = 0;
data->len = data->size;
return count;
70,17 → 78,23
}
if (i <= count) {
/* We have not enought space for whole string with the trailing zero => print only a part of string */
memcpy((void *)(data->string + data->len), (void *)str, i - 1);
data->string[data->size - 1] = 0;
data->len = data->size;
return count;
/*
* We have not enought space for whole string with the trailing
* zero => print only a part of string.
*/
memcpy((void *)(data->string + data->len), (void *)str, i - 1);
data->string[data->size - 1] = 0;
data->len = data->size;
return count;
}
/* Buffer is big enought to print whole string */
memcpy((void *)(data->string + data->len), (void *)str, count);
data->len += count;
/* Put trailing zero at end, but not count it into data->len so it could be rewritten next time */
/*
* Put trailing zero at end, but not count it into data->len so it could
* be rewritten next time.
*/
data->string[data->len] = 0;
 
return count;
87,17 → 101,22
}
 
/** Print formatted to the given buffer with limited size.
* @param str buffer
* @param size buffer size
* @param fmt format string
* @param str Buffer.
* @param size Bffer size.
* @param fmt Format string.
* \see For more details about format string see printf_core.
*/
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
{
struct vsnprintf_data data = {size, 0, str};
struct printf_spec ps = {(int(*)(void *, size_t, void *)) vsnprintf_write, &data};
struct printf_spec ps = {
(int(*)(void *, size_t, void *)) vsnprintf_write,
&data
};
 
/* Print 0 at end of string - fix the case that nothing will be printed */
/*
* Print 0 at end of string - fix the case that nothing will be printed.
*/
if (size > 0)
str[0] = 0;
/branches/tracing/uspace/lib/libc/generic/io/printf_core.c
94,12 → 94,9
if (str == NULL)
return printf_putnchars("(NULL)", 6, ps);
 
for (count = 0; str[count] != 0; count++);
count = strlen(str);
 
if (ps->write((void *) str, count, ps->data) == count)
return 0;
return EOF;
return ps->write((void *) str, count, ps->data);
}
 
/** Print one character to output
/branches/tracing/uspace/lib/libc/generic/io/stream.c
96,6 → 96,15
}
}
 
void close_console(void)
{
if (console_phone >= 0) {
if (ipc_hangup(console_phone) == 0) {
console_phone = -1;
}
}
}
 
void klog_update(void)
{
(void) __SYSCALL3(SYS_KLOG, 1, NULL, 0);
/branches/tracing/uspace/lib/libc/Makefile
51,10 → 51,13
generic/cap.c \
generic/string.c \
generic/fibril.c \
generic/pcb.c \
generic/smc.c \
generic/thread.c \
generic/tls.c \
generic/task.c \
generic/futex.c \
generic/io/asprintf.c \
generic/io/io.c \
generic/io/printf.c \
generic/io/stream.c \
68,6 → 71,7
generic/sysinfo.c \
generic/ipc.c \
generic/async.c \
generic/getopt.c \
generic/libadt/list.o \
generic/libadt/hash_table.o \
generic/time.c \
/branches/tracing/uspace/lib/libc/arch/sparc64/include/config.h
37,7 → 37,6
 
#define PAGE_WIDTH 14
#define PAGE_SIZE (1 << PAGE_WIDTH)
#define PAGE_COLOR_BITS 0 /**< Only one page color. */
 
#endif
 
/branches/tracing/uspace/lib/libc/arch/sparc64/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = sparc64-linux-gnu
TOOLCHAIN_DIR = /usr/local/sparc64/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/fibril.S \
arch/$(ARCH)/src/tls.c
/branches/tracing/uspace/lib/libc/arch/sparc64/src/entry.s
34,12 → 34,15
 
## User-space task entry point
#
# %o0 contains uarg
# %o1 contains pcb_ptr
#
__entry:
# Pass pcb_ptr as the first argument to __main()
mov %o1, %o0
sethi %hi(_gp), %l7
call __main
or %l7, %lo(_gp), %l7
call main
nop
 
call __exit
nop
/branches/tracing/uspace/lib/libc/arch/ia64/include/config.h
36,8 → 36,7
#define LIBC_ia64_CONFIG_H_
 
#define PAGE_WIDTH 14
#define PAGE_SIZE (1<<PAGE_WIDTH)
#define PAGE_COLOR_BITS 0 /* dummy */
#define PAGE_SIZE (1 << PAGE_WIDTH)
 
#endif
 
/branches/tracing/uspace/lib/libc/arch/ia64/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = ia64-pc-linux-gnu
TOOLCHAIN_DIR = /usr/local/ia64/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin
CFLAGS += -fno-unwind-tables -DMALLOC_ALIGNMENT_16
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS +=
/branches/tracing/uspace/lib/libc/arch/ia64/src/entry.s
34,12 → 34,14
 
## User-space task entry point
#
# r2 contains the PCB pointer
#
__entry:
alloc loc0 = ar.pfs, 0, 1, 2, 0
mov r1 = _gp
mov r1 = _gp
 
# Pass PCB pointer as the first argument to __main
mov out0 = r2
br.call.sptk.many b0 = __main
0:
br.call.sptk.many b0 = main
1:
br.call.sptk.many b0 = __exit
/branches/tracing/uspace/lib/libc/arch/arm32/include/byteorder.h
36,7 → 36,7
#ifndef LIBC_arm32_BYTEORDER_H_
#define LIBC_arm32_BYTEORDER_H_
 
#define ARCH_IS_BIG_ENDIAN
#define ARCH_IS_LITTLE_ENDIAN
 
#endif
 
/branches/tracing/uspace/lib/libc/arch/arm32/include/config.h
38,7 → 38,6
 
#define PAGE_WIDTH 12
#define PAGE_SIZE (1 << PAGE_WIDTH)
#define PAGE_COLOR_BITS 0 /* dummy */
 
#endif
 
/branches/tracing/uspace/lib/libc/arch/arm32/Makefile.inc
30,8 → 30,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = arm-linux-gnu
TOOLCHAIN_DIR = /usr/local/arm/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin
CFLAGS += -ffixed-r9 -mtp=soft
LFLAGS += -N $(SOFTINT_PREFIX)/libsoftint.a
AFLAGS +=
/branches/tracing/uspace/lib/libc/arch/arm32/src/entry.s
34,8 → 34,11
 
## User-space task entry point
#
# r1 contains the PCB pointer
#
__entry:
# Pass pcb_ptr to __main as the first argument (in r0)
mov r0, r1
bl __main
bl main
 
bl __exit
/branches/tracing/uspace/lib/libc/arch/mips32eb/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = mips-sgi-irix5
TOOLCHAIN_DIR = /usr/local/mips/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mips/bin
CFLAGS += -mips3
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \
/branches/tracing/uspace/lib/libc/arch/ppc32/include/config.h
36,8 → 36,7
#define LIBC_ppc32_CONFIG_H_
 
#define PAGE_WIDTH 12
#define PAGE_SIZE (1<<PAGE_WIDTH)
#define PAGE_COLOR_BITS 0 /* dummy */
#define PAGE_SIZE (1 << PAGE_WIDTH)
 
#endif
 
/branches/tracing/uspace/lib/libc/arch/ppc32/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = ppc-linux-gnu
TOOLCHAIN_DIR = /usr/local/ppc/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \
arch/$(ARCH)/src/fibril.S \
/branches/tracing/uspace/lib/libc/arch/ppc32/src/entry.s
34,8 → 34,11
 
## User-space task entry point
#
# r3 contains the PCB pointer
#
__entry:
# Pass the PCB pointer to __main() as the first argument.
# Since the first argument is passed in r3, no operation is needed.
bl __main
bl main
 
bl __exit
/branches/tracing/uspace/lib/libc/arch/amd64/include/config.h
36,8 → 36,7
#define LIBC_amd64_CONFIG_H_
 
#define PAGE_WIDTH 12
#define PAGE_SIZE (1<<PAGE_WIDTH)
#define PAGE_COLOR_BITS 0 /* dummy */
#define PAGE_SIZE (1 << PAGE_WIDTH)
 
#endif
 
/branches/tracing/uspace/lib/libc/arch/amd64/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = amd64-linux-gnu
TOOLCHAIN_DIR = /usr/local/amd64/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/amd64/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \
arch/$(ARCH)/src/fibril.S \
/branches/tracing/uspace/lib/libc/arch/amd64/src/entry.s
34,8 → 34,11
 
## User-space task entry point
#
# %rdi contains the PCB pointer
#
__entry:
# %rdi was deliberately chosen as the first argument is also in %rdi
# Pass PCB pointer to __main (no operation)
call __main
call main
 
call __exit
/branches/tracing/uspace/lib/libc/arch/ppc64/include/config.h
36,8 → 36,7
#define LIBC_ppc64_CONFIG_H_
 
#define PAGE_WIDTH 12
#define PAGE_SIZE (1<<PAGE_WIDTH)
#define PAGE_COLOR_BITS 0 /* dummy */
#define PAGE_SIZE (1 << PAGE_WIDTH)
 
#endif
 
/branches/tracing/uspace/lib/libc/arch/ppc64/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = ppc64-linux-gnu
TOOLCHAIN_DIR = /usr/local/ppc64/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc64/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \
arch/$(ARCH)/src/fibril.S \
/branches/tracing/uspace/lib/libc/arch/ppc64/src/entry.s
31,7 → 31,6
.org 0
 
.globl __entry
.globl __entry_driver
 
## User-space task entry point
#
38,11 → 37,4
#
__entry:
bl __main
bl __io_init
bl main
bl __exit
 
__entry_driver:
bl __main
bl main
bl __exit
/branches/tracing/uspace/lib/libc/arch/mips32/include/config.h
36,8 → 36,7
#define LIBC_mips32_CONFIG_H_
 
#define PAGE_WIDTH 14
#define PAGE_SIZE (1<<PAGE_WIDTH)
#define PAGE_COLOR_BITS 0 /* dummy */
#define PAGE_SIZE (1 << PAGE_WIDTH)
 
#endif
 
/branches/tracing/uspace/lib/libc/arch/mips32/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = mipsel-linux-gnu
TOOLCHAIN_DIR = /usr/local/mipsel/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin
CFLAGS += -mips3
 
-include ../../Makefile.config
/branches/tracing/uspace/lib/libc/arch/mips32/src/entry.s
35,13 → 35,13
 
## User-space task entry point
#
# $a0 ($4) contains the PCB pointer
#
.ent __entry
__entry:
.frame $sp, 32, $31
.cpload $25
 
# Mips o32 may store its arguments on stack, make space (16 bytes),
# so that it could work with -O0
# Make space additional 16 bytes for the stack frame
48,13 → 48,14
 
addiu $sp, -32
.cprestore 16 # Allow PIC code
 
# Pass pcb_ptr to __main() as the first argument. pcb_ptr is already
# in $a0. As the first argument is passed in $a0, no operation
# is needed.
 
jal __main
nop
jal main
nop
jal __exit
nop
.end
/branches/tracing/uspace/lib/libc/arch/ia32/include/config.h
37,7 → 37,6
 
#define PAGE_WIDTH 12
#define PAGE_SIZE (1 << PAGE_WIDTH)
#define PAGE_COLOR_BITS 0 /* dummy */
 
#endif
 
/branches/tracing/uspace/lib/libc/arch/ia32/Makefile.inc
29,8 → 29,12
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
TARGET = i686-pc-linux-gnu
TOOLCHAIN_DIR = /usr/local/i686/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/i686/bin
 
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \
arch/$(ARCH)/src/fibril.S \
/branches/tracing/uspace/lib/libc/arch/ia32/src/entry.s
34,6 → 34,7
 
## User-space task entry point
#
# %ebx contains the PCB pointer
#
__entry:
mov %ss, %ax
41,7 → 42,9
mov %ax, %es
mov %ax, %fs
# Do not set %gs, it contains descriptor that can see TLS
 
# Pass the PCB pointer to __main as the first argument
pushl %ebx
call __main
call main
 
call __exit
/branches/tracing/uspace/srv/kbd/Makefile
83,7 → 83,7
 
.PHONY: all clean depend disasm links
 
all: links $(OUTPUT) disasm
all: links $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
100,9 → 100,11
$(OUTPUT): $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(GENARCH_OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(GENERIC_OBJECTS) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/srv/ns/Makefile
46,7 → 46,7
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
59,9 → 59,11
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/srv/console/Makefile
59,7 → 59,7
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
72,9 → 72,11
$(OUTPUT): $(ARCH_OBJECTS) $(GENERIC_OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(GENERIC_OBJECTS) $(ARCH_OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/srv/rd/rd.c
81,46 → 81,24
ipc_call_t call;
int retval;
void *fs_va = NULL;
ipcarg_t offset;
off_t offset;
size_t block_size;
size_t maxblock_size;
 
/*
* We allocate VA for communication per connection.
* This allows us to potentionally have more clients and work
* concurrently.
* Answer the first IPC_M_CONNECT_ME_TO call.
*/
fs_va = as_get_mappable_page(ALIGN_UP(BLOCK_SIZE, PAGE_SIZE));
if (!fs_va) {
/*
* Hang up the phone if we cannot proceed any further.
* This is the answer to the call that opened the connection.
*/
ipc_answer_0(iid, EHANGUP);
return;
} else {
/*
* Answer the first IPC_M_CONNECT_ME_TO call.
* Return supported block size as ARG1.
*/
ipc_answer_1(iid, EOK, BLOCK_SIZE);
}
ipc_answer_0(iid, EOK);
 
/*
* Now we wait for the client to send us its communication as_area.
*/
size_t size;
int flags;
if (ipc_share_out_receive(&callid, &size, &flags)) {
if (size >= BLOCK_SIZE) {
/*
* The client sends an as_area that can absorb the whole
* block.
*/
if (ipc_share_out_receive(&callid, &maxblock_size, &flags)) {
fs_va = as_get_mappable_page(maxblock_size);
if (fs_va) {
(void) ipc_share_out_finalize(callid, fs_va);
} else {
/*
* The client offered as_area too small.
* Close the connection.
*/
ipc_answer_0(callid, EHANGUP);
return;
}
146,8 → 124,16
return;
case RD_READ_BLOCK:
offset = IPC_GET_ARG1(call);
if (offset * BLOCK_SIZE > rd_size - BLOCK_SIZE) {
block_size = IPC_GET_ARG2(call);
if (block_size > maxblock_size) {
/*
* Maximum block size exceeded.
*/
retval = ELIMIT;
break;
}
if (offset * block_size > rd_size - block_size) {
/*
* Reading past the end of the device.
*/
retval = ELIMIT;
154,14 → 140,22
break;
}
futex_down(&rd_futex);
memcpy(fs_va, rd_addr + offset * BLOCK_SIZE, BLOCK_SIZE);
memcpy(fs_va, rd_addr + offset * block_size, block_size);
futex_up(&rd_futex);
retval = EOK;
break;
case RD_WRITE_BLOCK:
offset = IPC_GET_ARG1(call);
if (offset * BLOCK_SIZE > rd_size - BLOCK_SIZE) {
block_size = IPC_GET_ARG2(call);
if (block_size > maxblock_size) {
/*
* Maximum block size exceeded.
*/
retval = ELIMIT;
break;
}
if (offset * block_size > rd_size - block_size) {
/*
* Writing past the end of the device.
*/
retval = ELIMIT;
168,7 → 162,7
break;
}
futex_up(&rd_futex);
memcpy(rd_addr + offset * BLOCK_SIZE, fs_va, BLOCK_SIZE);
memcpy(rd_addr + offset * block_size, fs_va, block_size);
futex_down(&rd_futex);
retval = EOK;
break;
/branches/tracing/uspace/srv/rd/rd.h
43,8 → 43,6
#ifndef RD_RD_H_
#define RD_RD_H_
 
#define BLOCK_SIZE 1024 /**< Working block size */
 
#define RD_BASE 1024
#define RD_READ_BLOCK (RD_BASE + 1) /**< Method for reading block. */
#define RD_WRITE_BLOCK (RD_BASE + 2) /**< Method for writing block. */
/branches/tracing/uspace/srv/rd/Makefile
46,7 → 46,7
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
59,9 → 59,11
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/srv/loader/elf_load.c
0,0 → 1,479
/*
* Copyright (c) 2006 Sergey Bondari
* Copyright (c) 2006 Jakub Jermar
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
* @{
*/
 
/**
* @file
* @brief Userspace ELF loader.
*
* This module allows loading ELF binaries (both executables and
* shared objects) from VFS. The current implementation allocates
* anonymous memory, fills it with segment data and then adjusts
* the memory areas' flags to the final value. In the future,
* the segments will be mapped directly from the file.
*/
 
#include <stdio.h>
#include <sys/types.h>
#include <align.h>
#include <assert.h>
#include <as.h>
#include <unistd.h>
#include <fcntl.h>
#include <smc.h>
#include <loader/pcb.h>
 
#include "elf.h"
#include "elf_load.h"
#include "arch.h"
 
static char *error_codes[] = {
"no error",
"invalid image",
"address space error",
"incompatible image",
"unsupported image type",
"irrecoverable error"
};
 
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
 
/** Read until the buffer is read in its entirety. */
static int my_read(int fd, char *buf, size_t len)
{
int cnt = 0;
do {
buf += cnt;
len -= cnt;
cnt = read(fd, buf, len);
} while ((cnt > 0) && ((len - cnt) > 0));
 
return cnt;
}
 
/** Load ELF binary from a file.
*
* Load an ELF binary from the specified file. If the file is
* an executable program, it is loaded unbiased. If it is a shared
* object, it is loaded with the bias @a so_bias. Some information
* extracted from the binary is stored in a elf_info_t structure
* pointed to by @a info.
*
* @param file_name Path to the ELF file.
* @param so_bias Bias to use if the file is a shared object.
* @param info Pointer to a structure for storing information
* extracted from the binary.
*
* @return EOK on success or negative error code.
*/
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info)
{
elf_ld_t elf;
 
int fd;
int rc;
 
// printf("open and read '%s'...\n", file_name);
 
fd = open(file_name, O_RDONLY);
if (fd < 0) {
printf("failed opening file\n");
return -1;
}
 
elf.fd = fd;
elf.info = info;
 
rc = elf_load(&elf, so_bias);
 
close(fd);
 
return rc;
}
 
/** Run an ELF executable.
*
* Transfers control to the entry point of an ELF executable loaded
* earlier with elf_load_file(). This function does not return.
*
* @param info Info structure filled earlier by elf_load_file()
*/
void elf_run(elf_info_t *info, pcb_t *pcb)
{
program_run(info->entry, pcb);
 
/* not reached */
}
 
/** Create the program control block (PCB).
*
* Fills the program control block @a pcb with information from
* @a info.
*
* @param info Program info structure
* @return EOK on success or negative error code
*/
void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
{
pcb->entry = info->entry;
pcb->dynamic = info->dynamic;
}
 
 
/** Load an ELF binary.
*
* The @a elf structure contains the loader state, including
* an open file, from which the binary will be loaded,
* a pointer to the @c info structure etc.
*
* @param elf Pointer to loader state buffer.
* @param so_bias Bias to use if the file is a shared object.
* @return EE_OK on success or EE_xx error code.
*/
static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
{
elf_header_t header_buf;
elf_header_t *header = &header_buf;
int i, rc;
 
rc = my_read(elf->fd, header, sizeof(elf_header_t));
if (rc < 0) {
printf("read error\n");
return EE_INVALID;
}
 
elf->header = header;
 
// printf("ELF-load:");
/* Identify ELF */
if (header->e_ident[EI_MAG0] != ELFMAG0 ||
header->e_ident[EI_MAG1] != ELFMAG1 ||
header->e_ident[EI_MAG2] != ELFMAG2 ||
header->e_ident[EI_MAG3] != ELFMAG3) {
printf("invalid header\n");
return EE_INVALID;
}
/* Identify ELF compatibility */
if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
header->e_machine != ELF_MACHINE ||
header->e_ident[EI_VERSION] != EV_CURRENT ||
header->e_version != EV_CURRENT ||
header->e_ident[EI_CLASS] != ELF_CLASS) {
printf("incompatible data/version/class\n");
return EE_INCOMPATIBLE;
}
 
if (header->e_phentsize != sizeof(elf_segment_header_t)) {
printf("e_phentsize:%d != %d\n", header->e_phentsize,
sizeof(elf_segment_header_t));
return EE_INCOMPATIBLE;
}
 
if (header->e_shentsize != sizeof(elf_section_header_t)) {
printf("e_shentsize:%d != %d\n", header->e_shentsize,
sizeof(elf_section_header_t));
return EE_INCOMPATIBLE;
}
 
/* Check if the object type is supported. */
if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
printf("Object type %d is not supported\n", header->e_type);
return EE_UNSUPPORTED;
}
 
/* Shared objects can be loaded with a bias */
// printf("Object type: %d\n", header->e_type);
if (header->e_type == ET_DYN)
elf->bias = so_bias;
else
elf->bias = 0;
 
// printf("Bias set to 0x%x\n", elf->bias);
elf->info->interp = NULL;
elf->info->dynamic = NULL;
 
// printf("parse segments\n");
 
/* Walk through all segment headers and process them. */
for (i = 0; i < header->e_phnum; i++) {
elf_segment_header_t segment_hdr;
 
/* Seek to start of segment header */
lseek(elf->fd, header->e_phoff
+ i * sizeof(elf_segment_header_t), SEEK_SET);
 
rc = my_read(elf->fd, &segment_hdr,
sizeof(elf_segment_header_t));
if (rc < 0) {
printf("read error\n");
return EE_INVALID;
}
 
rc = segment_header(elf, &segment_hdr);
if (rc != EE_OK)
return rc;
}
 
// printf("parse sections\n");
 
/* Inspect all section headers and proccess them. */
for (i = 0; i < header->e_shnum; i++) {
elf_section_header_t section_hdr;
 
/* Seek to start of section header */
lseek(elf->fd, header->e_shoff
+ i * sizeof(elf_section_header_t), SEEK_SET);
 
rc = my_read(elf->fd, &section_hdr,
sizeof(elf_section_header_t));
if (rc < 0) {
printf("read error\n");
return EE_INVALID;
}
 
rc = section_header(elf, &section_hdr);
if (rc != EE_OK)
return rc;
}
 
elf->info->entry =
(entry_point_t)((uint8_t *)header->e_entry + elf->bias);
 
// printf("done\n");
 
return EE_OK;
}
 
/** Print error message according to error code.
*
* @param rc Return code returned by elf_load().
*
* @return NULL terminated description of error.
*/
char *elf_error(unsigned int rc)
{
assert(rc < sizeof(error_codes) / sizeof(char *));
 
return error_codes[rc];
}
 
/** Process segment header.
*
* @param entry Segment header.
*
* @return EE_OK on success, error code otherwise.
*/
static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
{
switch (entry->p_type) {
case PT_NULL:
case PT_PHDR:
break;
case PT_LOAD:
return load_segment(elf, entry);
break;
case PT_INTERP:
/* Assume silently interp == "/rtld.so" */
elf->info->interp = "/rtld.so";
break;
case PT_DYNAMIC:
case PT_SHLIB:
case PT_NOTE:
case PT_LOPROC:
case PT_HIPROC:
default:
printf("segment p_type %d unknown\n", entry->p_type);
return EE_UNSUPPORTED;
break;
}
return EE_OK;
}
 
/** Load segment described by program header entry.
*
* @param elf Loader state.
* @param entry Program header entry describing segment to be loaded.
*
* @return EE_OK on success, error code otherwise.
*/
int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
{
void *a;
int flags = 0;
uintptr_t bias;
uintptr_t base;
size_t mem_sz;
int rc;
 
// printf("load segment at addr 0x%x, size 0x%x\n", entry->p_vaddr,
// entry->p_memsz);
bias = elf->bias;
 
if (entry->p_align > 1) {
if ((entry->p_offset % entry->p_align) !=
(entry->p_vaddr % entry->p_align)) {
printf("align check 1 failed offset%%align=%d, "
"vaddr%%align=%d\n",
entry->p_offset % entry->p_align,
entry->p_vaddr % entry->p_align
);
return EE_INVALID;
}
}
 
/* Final flags that will be set for the memory area */
 
if (entry->p_flags & PF_X)
flags |= AS_AREA_EXEC;
if (entry->p_flags & PF_W)
flags |= AS_AREA_WRITE;
if (entry->p_flags & PF_R)
flags |= AS_AREA_READ;
flags |= AS_AREA_CACHEABLE;
base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
mem_sz = entry->p_memsz + (entry->p_vaddr - base);
 
// printf("map to p_vaddr=0x%x-0x%x...\n", entry->p_vaddr + bias,
// entry->p_vaddr + bias + ALIGN_UP(entry->p_memsz, PAGE_SIZE));
 
/*
* For the course of loading, the area needs to be readable
* and writeable.
*/
a = as_area_create((uint8_t *)base + bias, mem_sz,
AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
if (a == (void *)(-1)) {
printf("memory mapping failed\n");
return EE_MEMORY;
}
 
// printf("as_area_create(0x%lx, 0x%x, %d) -> 0x%lx\n",
// entry->p_vaddr+bias, entry->p_memsz, flags, (uintptr_t)a);
 
/*
* Load segment data
*/
// printf("seek to %d\n", entry->p_offset);
rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
if (rc < 0) {
printf("seek error\n");
return EE_INVALID;
}
 
// printf("read 0x%x bytes to address 0x%x\n", entry->p_filesz, entry->p_vaddr+bias);
/* rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
 
/* Long reads are not possible yet. Load segment picewise */
 
unsigned left, now;
uint8_t *dp;
 
left = entry->p_filesz;
dp = (uint8_t *)(entry->p_vaddr + bias);
 
while (left > 0) {
now = 16384;
if (now > left) now = left;
 
// printf("read %d...", now);
rc = my_read(elf->fd, dp, now);
// printf("->%d\n", rc);
 
if (rc < 0) {
printf("read error\n");
return EE_INVALID;
}
 
left -= now;
dp += now;
}
 
// printf("set area flags to %d\n", flags);
rc = as_area_change_flags((uint8_t *)entry->p_vaddr + bias, flags);
if (rc != 0) {
printf("failed to set memory area flags\n");
return EE_MEMORY;
}
 
if (flags & AS_AREA_EXEC) {
/* Enforce SMC coherence for the segment */
if (smc_coherence(entry->p_vaddr + bias, entry->p_filesz))
return EE_MEMORY;
}
 
return EE_OK;
}
 
/** Process section header.
*
* @param elf Loader state.
* @param entry Segment header.
*
* @return EE_OK on success, error code otherwise.
*/
static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
{
switch (entry->sh_type) {
case SHT_PROGBITS:
if (entry->sh_flags & SHF_TLS) {
/* .tdata */
}
break;
case SHT_NOBITS:
if (entry->sh_flags & SHF_TLS) {
/* .tbss */
}
break;
case SHT_DYNAMIC:
/* Record pointer to dynamic section into info structure */
elf->info->dynamic =
(void *)((uint8_t *)entry->sh_addr + elf->bias);
printf("dynamic section found at 0x%x\n",
(uintptr_t)elf->info->dynamic);
break;
default:
break;
}
return EE_OK;
}
 
/** @}
*/
/branches/tracing/uspace/srv/loader/interp.s
0,0 → 1,7
#
# Provide a string to be included in a special DT_INTERP header, even though
# this is a statically-linked executable. This will mark the binary as
# the program loader.
#
.section .interp , ""
.string "kernel"
/branches/tracing/uspace/srv/loader/include/arch.h
0,0 → 1,45
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup fs
* @{
*/
/** @file
* @brief
*/
 
#ifndef LOADER_ARCH_H_
#define LOADER_ARCH_H_
 
void program_run(void *entry_point, void *pcb);
 
#endif
 
/**
* @}
*/
/branches/tracing/uspace/srv/loader/include/elf_load.h
0,0 → 1,83
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
* @{
*/
/** @file
* @brief ELF loader structures and public functions.
*/
 
#ifndef ELF_LOAD_H_
#define ELF_LOAD_H_
 
#include <arch/elf.h>
#include <sys/types.h>
#include <loader/pcb.h>
 
#include "elf.h"
 
/**
* Some data extracted from the headers are stored here
*/
typedef struct {
/** Entry point */
entry_point_t entry;
 
/** ELF interpreter name or NULL if statically-linked */
char *interp;
 
/** Pointer to the dynamic section */
void *dynamic;
} elf_info_t;
 
/**
* Holds information about an ELF binary being loaded.
*/
typedef struct {
/** Filedescriptor of the file from which we are loading */
int fd;
 
/** Difference between run-time addresses and link-time addresses */
uintptr_t bias;
 
/** A copy of the ELF file header */
elf_header_t *header;
 
/** Store extracted info here */
elf_info_t *info;
} elf_ld_t;
 
int elf_load_file(char *file_name, size_t so_bias, elf_info_t *info);
void elf_run(elf_info_t *info, pcb_t *pcb);
void elf_create_pcb(elf_info_t *info, pcb_t *pcb);
 
#endif
 
/** @}
*/
/branches/tracing/uspace/srv/loader/include/elf.h
0,0 → 1,344
/*
* Copyright (c) 2006 Sergey Bondari
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup generic
* @{
*/
/** @file
*/
 
#ifndef ELF_H_
#define ELF_H_
 
#include <arch/elf.h>
#include <sys/types.h>
 
/**
* current ELF version
*/
#define EV_CURRENT 1
 
/**
* ELF types
*/
#define ET_NONE 0 /* No type */
#define ET_REL 1 /* Relocatable file */
#define ET_EXEC 2 /* Executable */
#define ET_DYN 3 /* Shared object */
#define ET_CORE 4 /* Core */
#define ET_LOPROC 0xff00 /* Processor specific */
#define ET_HIPROC 0xffff /* Processor specific */
 
/**
* ELF machine types
*/
#define EM_NO 0 /* No machine */
#define EM_SPARC 2 /* SPARC */
#define EM_386 3 /* i386 */
#define EM_MIPS 8 /* MIPS RS3000 */
#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 LE */
#define EM_PPC 20 /* PPC32 */
#define EM_PPC64 21 /* PPC64 */
#define EM_ARM 40 /* ARM */
#define EM_SPARCV9 43 /* SPARC64 */
#define EM_IA_64 50 /* IA-64 */
#define EM_X86_64 62 /* AMD64/EMT64 */
 
/**
* ELF identification indexes
*/
#define EI_MAG0 0
#define EI_MAG1 1
#define EI_MAG2 2
#define EI_MAG3 3
#define EI_CLASS 4 /* File class */
#define EI_DATA 5 /* Data encoding */
#define EI_VERSION 6 /* File version */
#define EI_OSABI 7
#define EI_ABIVERSION 8
#define EI_PAD 9 /* Start of padding bytes */
#define EI_NIDENT 16 /* ELF identification table size */
 
/**
* ELF magic number
*/
#define ELFMAG0 0x7f
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
 
/**
* ELF file classes
*/
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
 
/**
* ELF data encoding types
*/
#define ELFDATANONE 0
#define ELFDATA2LSB 1 /* Least significant byte first (little endian) */
#define ELFDATA2MSB 2 /* Most signigicant byte first (big endian) */
 
/**
* ELF error return codes
*/
#define EE_OK 0 /* No error */
#define EE_INVALID 1 /* Invalid ELF image */
#define EE_MEMORY 2 /* Cannot allocate address space */
#define EE_INCOMPATIBLE 3 /* ELF image is not compatible with current architecture */
#define EE_UNSUPPORTED 4 /* Non-supported ELF (e.g. dynamic ELFs) */
#define EE_IRRECOVERABLE 5
 
/**
* ELF section types
*/
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_LOOS 0x60000000
#define SHT_HIOS 0x6fffffff
#define SHT_LOPROC 0x70000000
#define SHT_HIPROC 0x7fffffff
#define SHT_LOUSER 0x80000000
#define SHT_HIUSER 0xffffffff
 
/**
* ELF section flags
*/
#define SHF_WRITE 0x1
#define SHF_ALLOC 0x2
#define SHF_EXECINSTR 0x4
#define SHF_TLS 0x400
#define SHF_MASKPROC 0xf0000000
 
/**
* Symbol binding
*/
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
#define STB_LOPROC 13
#define STB_HIPROC 15
 
/**
* Symbol types
*/
#define STT_NOTYPE 0
#define STT_OBJECT 1
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
#define STT_LOPROC 13
#define STT_HIPROC 15
 
/**
* Program segment types
*/
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
#define PT_LOPROC 0x70000000
#define PT_HIPROC 0x7fffffff
 
/**
* Program segment attributes.
*/
#define PF_X 1
#define PF_W 2
#define PF_R 4
 
/**
* ELF data types
*
* These types are found to be identical in both 32-bit and 64-bit
* ELF object file specifications. They are the only types used
* in ELF header.
*/
typedef uint64_t elf_xword;
typedef int64_t elf_sxword;
typedef uint32_t elf_word;
typedef int32_t elf_sword;
typedef uint16_t elf_half;
 
/**
* 32-bit ELF data types.
*
* These types are specific for 32-bit format.
*/
typedef uint32_t elf32_addr;
typedef uint32_t elf32_off;
 
/**
* 64-bit ELF data types.
*
* These types are specific for 64-bit format.
*/
typedef uint64_t elf64_addr;
typedef uint64_t elf64_off;
 
/** ELF header */
struct elf32_header {
uint8_t e_ident[EI_NIDENT];
elf_half e_type;
elf_half e_machine;
elf_word e_version;
elf32_addr e_entry;
elf32_off e_phoff;
elf32_off e_shoff;
elf_word e_flags;
elf_half e_ehsize;
elf_half e_phentsize;
elf_half e_phnum;
elf_half e_shentsize;
elf_half e_shnum;
elf_half e_shstrndx;
};
struct elf64_header {
uint8_t e_ident[EI_NIDENT];
elf_half e_type;
elf_half e_machine;
elf_word e_version;
elf64_addr e_entry;
elf64_off e_phoff;
elf64_off e_shoff;
elf_word e_flags;
elf_half e_ehsize;
elf_half e_phentsize;
elf_half e_phnum;
elf_half e_shentsize;
elf_half e_shnum;
elf_half e_shstrndx;
};
 
/*
* ELF segment header.
* Segments headers are also known as program headers.
*/
struct elf32_segment_header {
elf_word p_type;
elf32_off p_offset;
elf32_addr p_vaddr;
elf32_addr p_paddr;
elf_word p_filesz;
elf_word p_memsz;
elf_word p_flags;
elf_word p_align;
};
struct elf64_segment_header {
elf_word p_type;
elf_word p_flags;
elf64_off p_offset;
elf64_addr p_vaddr;
elf64_addr p_paddr;
elf_xword p_filesz;
elf_xword p_memsz;
elf_xword p_align;
};
 
/*
* ELF section header
*/
struct elf32_section_header {
elf_word sh_name;
elf_word sh_type;
elf_word sh_flags;
elf32_addr sh_addr;
elf32_off sh_offset;
elf_word sh_size;
elf_word sh_link;
elf_word sh_info;
elf_word sh_addralign;
elf_word sh_entsize;
};
struct elf64_section_header {
elf_word sh_name;
elf_word sh_type;
elf_xword sh_flags;
elf64_addr sh_addr;
elf64_off sh_offset;
elf_xword sh_size;
elf_word sh_link;
elf_word sh_info;
elf_xword sh_addralign;
elf_xword sh_entsize;
};
 
/*
* ELF symbol table entry
*/
struct elf32_symbol {
elf_word st_name;
elf32_addr st_value;
elf_word st_size;
uint8_t st_info;
uint8_t st_other;
elf_half st_shndx;
};
struct elf64_symbol {
elf_word st_name;
uint8_t st_info;
uint8_t st_other;
elf_half st_shndx;
elf64_addr st_value;
elf_xword st_size;
};
 
#ifdef __32_BITS__
typedef struct elf32_header elf_header_t;
typedef struct elf32_segment_header elf_segment_header_t;
typedef struct elf32_section_header elf_section_header_t;
typedef struct elf32_symbol elf_symbol_t;
#endif
#ifdef __64_BITS__
typedef struct elf64_header elf_header_t;
typedef struct elf64_segment_header elf_segment_header_t;
typedef struct elf64_section_header elf_section_header_t;
typedef struct elf64_symbol elf_symbol_t;
#endif
 
extern char *elf_error(unsigned int rc);
 
#endif
 
/** @}
*/
/branches/tracing/uspace/srv/loader/main.c
0,0 → 1,332
/*
* Copyright (c) 2008 Jiri Svoboda
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup loader
* @brief Loads and runs programs from VFS.
* @{
*/
/**
* @file
* @brief Loads and runs programs from VFS.
*
* The program loader is a special init binary. Its image is used
* to create a new task upon a @c task_spawn syscall. The syscall
* returns the id of a phone connected to the newly created task.
*
* The caller uses this phone to send the pathname and various other
* information to the loader. This is normally done by the C library
* and completely hidden from applications.
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <ipc/ipc.h>
#include <ipc/loader.h>
#include <loader/pcb.h>
#include <errno.h>
#include <async.h>
#include <as.h>
 
#include <elf.h>
#include <elf_load.h>
 
/**
* Bias used for loading the dynamic linker. This will be soon replaced
* by automatic placement.
*/
#define RTLD_BIAS 0x80000
 
/** Pathname of the file that will be loaded */
static char *pathname = NULL;
 
/** The Program control block */
static pcb_t pcb;
 
/** Number of arguments */
static int argc = 0;
/** Argument vector */
static char **argv = NULL;
/** Buffer holding all arguments */
static char *arg_buf = NULL;
 
/** Receive a call setting pathname of the program to execute.
*
* @param rid
* @param request
*/
static void loader_set_pathname(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t len;
char *name_buf;
 
if (!ipc_data_write_receive(&callid, &len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
name_buf = malloc(len + 1);
if (!name_buf) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
 
ipc_data_write_finalize(callid, name_buf, len);
ipc_answer_0(rid, EOK);
 
if (pathname != NULL) {
free(pathname);
pathname = NULL;
}
 
name_buf[len] = '\0';
pathname = name_buf;
}
 
/** Receive a call setting arguments of the program to execute.
*
* @param rid
* @param request
*/
static void loader_set_args(ipc_callid_t rid, ipc_call_t *request)
{
ipc_callid_t callid;
size_t buf_len, arg_len;
char *p;
int n;
 
if (!ipc_data_write_receive(&callid, &buf_len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
if (arg_buf != NULL) {
free(arg_buf);
arg_buf = NULL;
}
 
if (argv != NULL) {
free(argv);
argv = NULL;
}
 
arg_buf = malloc(buf_len + 1);
if (!arg_buf) {
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
 
ipc_data_write_finalize(callid, arg_buf, buf_len);
ipc_answer_0(rid, EOK);
 
arg_buf[buf_len] = '\0';
 
/*
* Count number of arguments
*/
p = arg_buf;
n = 0;
while (p < arg_buf + buf_len) {
arg_len = strlen(p);
p = p + arg_len + 1;
++n;
}
 
/* Allocate argv */
argv = malloc((n + 1) * sizeof(char *));
 
if (argv == NULL) {
free(arg_buf);
ipc_answer_0(callid, ENOMEM);
ipc_answer_0(rid, ENOMEM);
return;
}
 
/*
* Fill argv with argument pointers
*/
p = arg_buf;
n = 0;
while (p < arg_buf + buf_len) {
argv[n] = p;
 
arg_len = strlen(p);
p = p + arg_len + 1;
++n;
}
 
argc = n;
argv[n] = NULL;
}
 
 
/** Load and run the previously selected program.
*
* @param rid
* @param request
* @return 0 on success, !0 on error.
*/
static int loader_run(ipc_callid_t rid, ipc_call_t *request)
{
int rc;
 
elf_info_t prog_info;
elf_info_t interp_info;
 
// printf("Load program '%s'\n", pathname);
 
rc = elf_load_file(pathname, 0, &prog_info);
if (rc < 0) {
printf("failed to load program\n");
ipc_answer_0(rid, EINVAL);
return 1;
}
 
// printf("Create PCB\n");
elf_create_pcb(&prog_info, &pcb);
 
pcb.argc = argc;
pcb.argv = argv;
 
if (prog_info.interp == NULL) {
/* Statically linked program */
// printf("Run statically linked program\n");
// printf("entry point: 0x%llx\n", prog_info.entry);
ipc_answer_0(rid, EOK);
close_console();
elf_run(&prog_info, &pcb);
return 0;
}
 
printf("Load dynamic linker '%s'\n", prog_info.interp);
rc = elf_load_file("/rtld.so", RTLD_BIAS, &interp_info);
if (rc < 0) {
printf("failed to load dynamic linker\n");
ipc_answer_0(rid, EINVAL);
return 1;
}
 
/*
* Provide dynamic linker with some useful data
*/
pcb.rtld_dynamic = interp_info.dynamic;
pcb.rtld_bias = RTLD_BIAS;
 
printf("run dynamic linker\n");
printf("entry point: 0x%llx\n", interp_info.entry);
close_console();
 
ipc_answer_0(rid, EOK);
elf_run(&interp_info, &pcb);
 
/* Not reached */
return 0;
}
 
/** Handle loader connection.
*
* Receive and carry out commands (of which the last one should be
* to execute the loaded program).
*/
static void loader_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
int retval;
 
/* Ignore parameters, the connection is already open */
(void)iid; (void)icall;
 
while (1) {
callid = async_get_call(&call);
// printf("received call from phone %d, method=%d\n",
// call.in_phone_hash, IPC_GET_METHOD(call));
switch (IPC_GET_METHOD(call)) {
case LOADER_SET_PATHNAME:
loader_set_pathname(callid, &call);
continue;
case LOADER_SET_ARGS:
loader_set_args(callid, &call);
case LOADER_RUN:
loader_run(callid, &call);
exit(0);
continue;
default:
retval = ENOENT;
break;
}
if ((callid & IPC_CALLID_NOTIFICATION) == 0 &&
IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) {
printf("responding EINVAL to method %d\n",
IPC_GET_METHOD(call));
ipc_answer_0(callid, EINVAL);
}
}
}
 
/** Program loader main function.
*/
int main(int argc, char *argv[])
{
ipc_callid_t callid;
ipc_call_t call;
ipcarg_t phone_hash;
 
/* The first call only communicates the incoming phone hash */
callid = ipc_wait_for_call(&call);
 
if (IPC_GET_METHOD(call) != LOADER_HELLO) {
if (IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP)
ipc_answer_0(callid, EINVAL);
return 1;
}
 
ipc_answer_0(callid, EOK);
phone_hash = call.in_phone_hash;
 
/*
* Up until now async must not be used as it couldn't
* handle incoming requests. (Which means e.g. printf()
* cannot be used)
*/
async_new_connection(phone_hash, 0, NULL, loader_connection);
async_manager();
 
/* not reached */
return 0;
}
 
/** @}
*/
/branches/tracing/uspace/srv/loader/Makefile
0,0 → 1,94
#
# Copyright (c) 2005 Martin Decky
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
include ../../../version
include ../../Makefile.config
 
## Setup toolchain
#
 
LIBC_PREFIX = ../../lib/libc
SOFTINT_PREFIX = ../../lib/softint
include $(LIBC_PREFIX)/Makefile.toolchain
include arch/$(ARCH)/Makefile.inc
 
CFLAGS += -Iinclude
 
LIBS = $(LIBC_PREFIX)/libc.a $(SOFTINT_PREFIX)/libsoftint.a
DEFS += -DRELEASE=\"$(RELEASE)\"
 
ifdef REVISION
DEFS += "-DREVISION=\"$(REVISION)\""
endif
 
ifdef TIMESTAMP
DEFS += "-DTIMESTAMP=\"$(TIMESTAMP)\""
endif
 
## Sources
#
 
OUTPUT = loader
GENERIC_SOURCES = \
main.c \
elf_load.c \
interp.s
 
SOURCES := $(GENERIC_SOURCES) $(ARCH_SOURCES)
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
 
-include Makefile.depend
 
clean:
-rm -f $(OUTPUT) $(OBJECTS) $(OUTPUT).map $(OUTPUT).disasm arch/$(ARCH)/_link.ld Makefile.depend
 
depend:
$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
 
$(OUTPUT): $(OBJECTS) $(LIBS) arch/$(ARCH)/_link.ld
$(LD) -T arch/$(ARCH)/_link.ld $(LFLAGS) $(OBJECTS) $(LIBS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
 
arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in
$(CC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
%.o: %.s
$(AS) $(AFLAGS) $< -o $@
 
%.o: %.c
$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
/branches/tracing/uspace/srv/loader/arch/sparc64/_link.ld.in
0,0 → 1,59
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
interp PT_INTERP;
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
 
SECTIONS {
.interp : {
*(.interp);
} :interp
 
. = 0x70004000 + SIZEOF_HEADERS;
 
.init : {
*(.init);
} :text
.text : {
*(.text);
*(.rodata*);
} :text
 
. = . + 0x4000;
 
.got : {
_gp = .;
*(.got*);
} :data
.data : {
*(.data);
*(.sdata);
} :data
.tdata : {
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
.bss : {
*(.sbss);
*(COMMON);
*(.bss);
} :data
 
. = ALIGN(0x4000);
_heap = .;
/DISCARD/ : {
*(*);
}
 
}
/branches/tracing/uspace/srv/loader/arch/sparc64/sparc64.s
0,0 → 1,42
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
.globl program_run
 
## void program_run(void *entry_point, void *pcb);
#
# %o0 contains entry_point
# %o1 contains pcb
#
# Jump to a program entry point
program_run:
# Pass pcb pointer to entry point in %o1. As it is already
# there, no action is needed.
call %o0
nop
# fixme: use branch instead of call
/branches/tracing/uspace/srv/loader/arch/sparc64/Makefile.inc
0,0 → 1,30
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
CFLAGS += -D__64_BITS__
ARCH_SOURCES := arch/$(ARCH)/sparc64.s
/branches/tracing/uspace/srv/loader/arch/ia64/_link.ld.in
0,0 → 1,66
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
interp PT_INTERP;
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
 
SECTIONS {
.interp : {
*(.interp);
} :interp
 
. = 0x00084000 + SIZEOF_HEADERS;
 
.init : {
LONG(0);
LONG(0);
LONG(0);
LONG(0);
LONG(0);
LONG(0);
*(.init);
} : text
.text : {
*(.text);
*(.rodata*);
} :text
 
. = . + 0x4000;
 
.got : {
_gp = .;
*(.got*);
} :data
.data : {
*(.opd);
*(.data .data.*);
*(.sdata);
} :data
.tdata : {
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
.bss : {
*(.sbss);
*(.scommon);
*(COMMON);
*(.bss);
} :data
 
. = ALIGN(0x4000);
_heap = .;
/DISCARD/ : {
*(*);
}
}
/branches/tracing/uspace/srv/loader/arch/ia64/ia64.s
0,0 → 1,43
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
.text
.globl program_run
 
## void program_run(void *entry_point, void *pcb);
#
# in0 (r32) contains entry_point
# in1 (r33) contains pcb
#
# Jump to a program entry point
program_run:
# Pass pcb to the entry point in r2
 
mov b6 = r32
mov r2 = r33 ;;
br b6 ;;
/branches/tracing/uspace/srv/loader/arch/ia64/Makefile.inc
0,0 → 1,31
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
CFLAGS += -D__64_BITS__
ARCH_SOURCES := arch/$(ARCH)/ia64.s
AFLAGS += -xexplicit
/branches/tracing/uspace/srv/loader/arch/arm32/_link.ld.in
0,0 → 1,59
/*
* The only difference from _link.ld.in for regular statically-linked apps
* is the base address.
*/
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
interp PT_INTERP;
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
 
SECTIONS {
.interp : {
*(.interp);
} : interp
 
. = 0x70001000;
 
.init ALIGN(0x1000): SUBALIGN(0x1000) {
*(.init);
} : text
.text : {
*(.text);
*(.rodata*);
} :text
.data ALIGN(0x1000) : SUBALIGN(0x1000) {
*(.opd);
*(.data .data.*);
*(.sdata);
} :data
.tdata : {
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
.bss : {
*(.sbss);
*(.scommon);
*(COMMON);
*(.bss);
} :data
. = ALIGN(0x1000);
_heap = .;
/DISCARD/ : {
*(*);
}
 
}
/branches/tracing/uspace/srv/loader/arch/arm32/Makefile.inc
0,0 → 1,30
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
CFLAGS += -D__32_BITS__
ARCH_SOURCES := arch/$(ARCH)/arm32.s
/branches/tracing/uspace/srv/loader/arch/arm32/arm32.s
0,0 → 1,39
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
.globl program_run
 
## void program_run(void *entry_point, void *pcb);
#
# r0 contains entry_point
# r1 contains pcb
#
# Jump to a program entry point
program_run:
# pcb is passed to the entry point in r1 (where it already is)
mov r15, r0
/branches/tracing/uspace/srv/loader/arch/ppc32/_link.ld.in
0,0 → 1,57
/*
* The only difference from _link.ld.in for regular statically-linked apps
* is the base address.
*/
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
interp PT_INTERP;
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
 
SECTIONS {
.interp : {
*(.interp);
} :interp
 
. = 0x70001000;
 
.init ALIGN(0x1000) : SUBALIGN(0x1000) {
*(.init);
} :text
.text : {
*(.text);
*(.rodata*);
} :text
.data ALIGN(0x1000) : SUBALIGN(0x1000) {
*(.data);
*(.sdata);
} :data
.tdata : {
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
.bss : {
*(.sbss);
*(COMMON);
*(.bss);
} :data
 
. = ALIGN(0x1000);
_heap = .;
/DISCARD/ : {
*(*);
}
 
}
/branches/tracing/uspace/srv/loader/arch/ppc32/Makefile.inc
0,0 → 1,30
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
CFLAGS += -D__32_BITS__
ARCH_SOURCES := arch/$(ARCH)/ppc32.s
/branches/tracing/uspace/srv/loader/arch/ppc32/ppc32.s
0,0 → 1,40
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
.globl program_run
 
## void program_run(void *entry_point, void *pcb);
#
# %r3 contains entry_point
# %r4 contains pcb
#
# Jump to a program entry point
program_run:
mtctr %r3
mr %r3, %r4 # Pass pcb to the entry point in %r3
bctr
/branches/tracing/uspace/srv/loader/arch/amd64/_link.ld.in
0,0 → 1,52
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
interp PT_INTERP;
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
 
SECTIONS {
.interp : {
*(.interp);
} : interp
 
/* . = 0x0000700000001000;*/
. = 0x70001000;
.init ALIGN(0x1000) : SUBALIGN(0x1000) {
*(.init);
} :text
.text : {
*(.text);
*(.rodata*);
} :text
.data ALIGN(0x1000) : SUBALIGN(0x1000) {
*(.data);
} :data
.tdata : {
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
.bss : {
*(COMMON);
*(.bss);
} :data
 
. = ALIGN(0x1000);
_heap = .;
/DISCARD/ : {
*(*);
}
 
}
/branches/tracing/uspace/srv/loader/arch/amd64/Makefile.inc
0,0 → 1,30
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
CFLAGS += -D__64_BITS__
ARCH_SOURCES := arch/$(ARCH)/amd64.s
/branches/tracing/uspace/srv/loader/arch/amd64/amd64.s
0,0 → 1,43
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
.globl program_run
 
## void program_run(void *entry_point, void *pcb);
#
# %rdi contains entry_point
# %rsi contains pcb
#
# Jump to a program entry point
program_run:
# pcb must be passed in %rdi, use %rdx as a scratch register
mov %rdi, %rdx
mov %rsi, %rdi
 
# jump to entry point
jmp %rdx
/branches/tracing/uspace/srv/loader/arch/mips32/_link.ld.in
0,0 → 1,66
/*
* The only difference from _link.ld.in for regular statically-linked apps
* is the base address.
*/
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
interp PT_INTERP;
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
 
SECTIONS {
.interp : {
*(.interp);
} :interp
 
. = 0x70004000;
.init ALIGN(0x4000) : SUBALIGN(0x4000) {
*(.init);
} :text
.text : {
*(.text);
*(.rodata*);
} :text
 
.data : {
*(.data);
*(.data.rel*);
} :data
 
.got : {
_gp = .;
*(.got);
} :data
 
.tdata : {
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
 
.sbss : {
*(.scommon);
*(.sbss);
}
.bss : {
*(.bss);
*(COMMON);
} :data
 
. = ALIGN(0x4000);
_heap = .;
 
/DISCARD/ : {
*(*);
}
}
/branches/tracing/uspace/srv/loader/arch/mips32/Makefile.inc
0,0 → 1,30
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
CFLAGS += -D__32_BITS__
ARCH_SOURCES := arch/$(ARCH)/mips32.s
/branches/tracing/uspace/srv/loader/arch/mips32/mips32.s
0,0 → 1,49
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
.text
.section .text
.global program_run
.set noreorder
 
## void program_run(void *entry_point, void *pcb);
#
# $a0 (=$4) contains entry_point
# $a1 (=$5) contains pcb
#
# Jump to a program entry point
.ent program_run
program_run:
# tmp := entry_point
move $25, $a0
 
# Pass pcb to the entry point in $a0
move $a0, $a1
jr $25
nop
.end
/branches/tracing/uspace/srv/loader/arch/ia32/_link.ld.in
0,0 → 1,55
/*
* The difference from _link.ld.in for regular statically-linked apps
* is the base address and the special interp section.
*/
STARTUP(LIBC_PREFIX/arch/ARCH/src/entry.o)
ENTRY(__entry)
 
PHDRS {
interp PT_INTERP;
text PT_LOAD FILEHDR PHDRS FLAGS(5);
data PT_LOAD FLAGS(6);
}
 
SECTIONS {
.interp : {
*(.interp);
} :interp
 
. = 0x70001000;
 
.init ALIGN(0x1000) : SUBALIGN(0x1000) {
*(.init);
} :text
.text : {
*(.text);
*(.rodata*);
} :text
.data ALIGN(0x1000) : SUBALIGN(0x1000) {
*(.data);
} :data
.tdata : {
_tdata_start = .;
*(.tdata);
_tdata_end = .;
} :data
.tbss : {
_tbss_start = .;
*(.tbss);
_tbss_end = .;
} :data
_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
.bss : {
*(COMMON);
*(.bss);
} :data
. = ALIGN(0x1000);
_heap = .;
/DISCARD/ : {
*(*);
}
 
}
/branches/tracing/uspace/srv/loader/arch/ia32/ia32.s
0,0 → 1,49
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
.globl program_run
 
## void program_run(void *entry_point, void *pcb);
#
# Jump to a program entry point
program_run:
# Use standard ia32 prologue not to confuse anybody
push %ebp
movl %esp, %ebp
 
# %eax := entry_point
movl 0x8(%ebp), %eax
 
# %ebx := pcb
# pcb is passed to the entry point int %ebx
mov 0xc(%ebp), %ebx
 
# Save a tiny bit of stack space
pop %ebp
 
jmp %eax
/branches/tracing/uspace/srv/loader/arch/ia32/Makefile.inc
0,0 → 1,30
#
# Copyright (c) 2008 Jiri Svoboda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
 
CFLAGS += -D__32_BITS__
ARCH_SOURCES := arch/$(ARCH)/ia32.s
/branches/tracing/uspace/srv/fb/main.c
37,6 → 37,7
 
#include "fb.h"
#include "ega.h"
#include "msim.h"
#include "main.h"
 
#define NAME "fb"
58,20 → 59,26
printf(NAME ": HelenOS Framebuffer service\n");
ipcarg_t phonead;
int initialized = 0;
bool initialized = false;
 
#ifdef FB_ENABLED
if (sysinfo_value("fb.kind") == 1) {
if (fb_init() == 0)
initialized = 1;
initialized = true;
}
#endif
#ifdef EGA_ENABLED
if (!initialized && sysinfo_value("fb.kind") == 2) {
if ((!initialized) && (sysinfo_value("fb.kind") == 2)) {
if (ega_init() == 0)
initialized = 1;
initialized = true;
}
#endif
#ifdef MSIM_ENABLED
if ((!initialized) && (sysinfo_value("fb.kind") == 3)) {
if (msim_init() == 0)
initialized = true;
}
#endif
 
if (!initialized)
return -1;
/branches/tracing/uspace/srv/fb/msim.c
0,0 → 1,227
/*
* Copyright (c) 2006 Ondrej Palkovsky
* Copyright (c) 2008 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @defgroup msimfb MSIM text console
* @brief HelenOS MSIM text console.
* @ingroup fbs
* @{
*/
/** @file
*/
 
#include <async.h>
#include <ipc/fb.h>
#include <ipc/ipc.h>
#include <libc.h>
#include <errno.h>
#include <string.h>
#include <libc.h>
#include <stdio.h>
#include <ipc/fb.h>
#include <sysinfo.h>
#include <as.h>
#include <align.h>
#include <ddi.h>
 
#include "msim.h"
 
#define WIDTH 80
#define HEIGHT 25
 
#define MAX_CONTROL 20
 
/* Allow only 1 connection */
static int client_connected = 0;
 
static char *virt_addr;
 
static void msim_putc(const char c)
{
*virt_addr = c;
}
 
static void msim_puts(char *str)
{
while (*str)
*virt_addr = *(str++);
}
 
static void msim_clrscr(void)
{
msim_puts("\033[2J");
}
 
static void msim_goto(const unsigned int row, const unsigned int col)
{
if ((row > HEIGHT) || (col > WIDTH))
return;
char control[MAX_CONTROL];
snprintf(control, MAX_CONTROL, "\033[%u;%uf", row + 1, col + 1);
msim_puts(control);
}
 
static void msim_set_style(const unsigned int mode)
{
char control[MAX_CONTROL];
snprintf(control, MAX_CONTROL, "\033[%um", mode);
msim_puts(control);
}
 
static void msim_cursor_disable(void)
{
msim_puts("\033[?25l");
}
 
static void msim_cursor_enable(void)
{
msim_puts("\033[?25h");
}
 
static void msim_scroll(int i)
{
if (i > 0) {
msim_goto(HEIGHT - 1, 0);
while (i--)
msim_puts("\033D");
} else if (i < 0) {
msim_goto(0, 0);
while (i++)
msim_puts("\033M");
}
}
 
static void msim_client_connection(ipc_callid_t iid, ipc_call_t *icall)
{
int retval;
ipc_callid_t callid;
ipc_call_t call;
char c;
int lastcol = 0;
int lastrow = 0;
int newcol;
int newrow;
int fgcolor;
int bgcolor;
int i;
 
if (client_connected) {
ipc_answer_0(iid, ELIMIT);
return;
}
client_connected = 1;
ipc_answer_0(iid, EOK);
/* Clear the terminal, set scrolling region
to 0 - 25 lines */
msim_clrscr();
msim_goto(0, 0);
msim_puts("\033[0;25r");
while (true) {
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
client_connected = 0;
ipc_answer_0(callid, EOK);
return;
case FB_PUTCHAR:
c = IPC_GET_ARG1(call);
newrow = IPC_GET_ARG2(call);
newcol = IPC_GET_ARG3(call);
if ((lastcol != newcol) || (lastrow != newrow))
msim_goto(newrow, newcol);
lastcol = newcol + 1;
lastrow = newrow;
msim_putc(c);
retval = 0;
break;
case FB_CURSOR_GOTO:
newrow = IPC_GET_ARG1(call);
newcol = IPC_GET_ARG2(call);
msim_goto(newrow, newcol);
lastrow = newrow;
lastcol = newcol;
retval = 0;
break;
case FB_GET_CSIZE:
ipc_answer_2(callid, EOK, HEIGHT, WIDTH);
continue;
case FB_CLEAR:
msim_clrscr();
retval = 0;
break;
case FB_SET_STYLE:
fgcolor = IPC_GET_ARG1(call);
bgcolor = IPC_GET_ARG2(call);
if (fgcolor < bgcolor)
msim_set_style(0);
else
msim_set_style(7);
retval = 0;
break;
case FB_SCROLL:
i = IPC_GET_ARG1(call);
if ((i > HEIGHT) || (i < -HEIGHT)) {
retval = EINVAL;
break;
}
msim_scroll(i);
msim_goto(lastrow, lastcol);
retval = 0;
break;
case FB_CURSOR_VISIBILITY:
if(IPC_GET_ARG1(call))
msim_cursor_enable();
else
msim_cursor_disable();
retval = 0;
break;
default:
retval = ENOENT;
}
ipc_answer_0(callid, retval);
}
}
 
int msim_init(void)
{
void *phys_addr = (void *) sysinfo_value("fb.address.physical");
virt_addr = (char *) as_get_mappable_page(1);
physmem_map(phys_addr, virt_addr, 1, AS_AREA_READ | AS_AREA_WRITE);
async_set_client_connection(msim_client_connection);
return 0;
}
 
/**
* @}
*/
/branches/tracing/uspace/srv/fb/msim.h
0,0 → 1,47
/*
* Copyright (c) 2006 Ondrej Palkovsky
* Copyright (c) 2008 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup msimfb
* @brief HelenOS MSIM text console.
* @ingroup fbs
* @{
*/
/** @file
*/
 
#ifndef FB_MSIM_H_
#define FB_MSIM_H_
 
extern int msim_init(void);
 
#endif
 
/** @}
*/
 
/branches/tracing/uspace/srv/fb/Makefile
50,7 → 50,6
font-8x16.c
CFLAGS += -DFB_ENABLED
endif
 
ifeq ($(ARCH), ia32)
SOURCES += ega.c
CFLAGS += -DEGA_ENABLED
60,7 → 59,8
CFLAGS += -DEGA_ENABLED
endif
ifeq ($(ARCH), mips32)
CFLAGS += -DFB_INVERT_ENDIAN
SOURCES += msim.c
CFLAGS += -DMSIM_ENABLED -DFB_INVERT_ENDIAN
endif
 
CFLAGS += -D$(ARCH)
70,7 → 70,7
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
83,9 → 83,11
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs.h
44,6 → 44,12
#define dprintf(...) printf(__VA_ARGS__)
#endif
 
typedef enum {
TMPFS_NONE,
TMPFS_FILE,
TMPFS_DIRECTORY
} tmpfs_dentry_type_t;
 
typedef struct tmpfs_dentry {
fs_index_t index; /**< TMPFS node index. */
link_t dh_link; /**< Dentries hash table link. */
50,11 → 56,7
struct tmpfs_dentry *sibling;
struct tmpfs_dentry *child;
hash_table_t names; /**< All names linking to this TMPFS node. */
enum {
TMPFS_NONE,
TMPFS_FILE,
TMPFS_DIRECTORY
} type;
tmpfs_dentry_type_t type;
unsigned lnkcnt; /**< Link count. */
size_t size; /**< File size if type is TMPFS_FILE. */
void *data; /**< File content's if type is TMPFS_FILE. */
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs_dump.c
39,6 → 39,7
#include "tmpfs.h"
#include "../../vfs/vfs.h"
#include <ipc/ipc.h>
#include <async.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
50,9 → 51,7
#include <sys/mman.h>
#include <byteorder.h>
 
#define BLOCK_SIZE 1024 // FIXME
#define RD_BASE 1024 // FIXME
#define RD_READ_BLOCK (RD_BASE + 1)
#define TMPFS_BLOCK_SIZE 1024
 
struct rdentry {
uint8_t type;
59,48 → 58,9
uint32_t len;
} __attribute__((packed));
 
static bool
tmpfs_blockread(int phone, void *buffer, size_t *bufpos, size_t *buflen,
size_t *pos, void *dst, size_t size)
{
size_t offset = 0;
size_t left = size;
while (left > 0) {
size_t rd;
if (*bufpos + left < *buflen)
rd = left;
else
rd = *buflen - *bufpos;
if (rd > 0) {
memcpy(dst + offset, buffer + *bufpos, rd);
offset += rd;
*bufpos += rd;
*pos += rd;
left -= rd;
}
if (*bufpos == *buflen) {
ipcarg_t retval;
int rc = ipc_call_sync_2_1(phone, RD_READ_BLOCK,
*pos / BLOCK_SIZE, BLOCK_SIZE,
&retval);
if ((rc != EOK) || (retval != EOK))
return false;
*bufpos = 0;
*buflen = BLOCK_SIZE;
}
}
return true;
}
 
static bool
tmpfs_restore_recursion(int phone, void *block, size_t *bufpos, size_t *buflen,
size_t *pos, tmpfs_dentry_t *parent)
tmpfs_restore_recursion(int phone, void *block, off_t *bufpos, size_t *buflen,
off_t *pos, tmpfs_dentry_t *parent)
{
struct rdentry entry;
libfs_ops_t *ops = &tmpfs_libfs_ops;
110,16 → 70,16
tmpfs_dentry_t *node;
uint32_t size;
if (!tmpfs_blockread(phone, block, bufpos, buflen, pos, &entry,
sizeof(entry)))
if (!libfs_blockread(phone, block, bufpos, buflen, pos, &entry,
sizeof(entry), TMPFS_BLOCK_SIZE))
return false;
entry.len = uint32_t_le2host(entry.len);
switch (entry.type) {
case 0:
case TMPFS_NONE:
break;
case 1:
case TMPFS_FILE:
fname = malloc(entry.len + 1);
if (fname == NULL)
return false;
130,8 → 90,8
return false;
}
if (!tmpfs_blockread(phone, block, bufpos, buflen, pos,
fname, entry.len)) {
if (!libfs_blockread(phone, block, bufpos, buflen, pos,
fname, entry.len, TMPFS_BLOCK_SIZE)) {
ops->destroy((void *) node);
free(fname);
return false;
145,8 → 105,8
}
free(fname);
if (!tmpfs_blockread(phone, block, bufpos, buflen, pos,
&size, sizeof(size)))
if (!libfs_blockread(phone, block, bufpos, buflen, pos,
&size, sizeof(size), TMPFS_BLOCK_SIZE))
return false;
size = uint32_t_le2host(size);
156,12 → 116,12
return false;
node->size = size;
if (!tmpfs_blockread(phone, block, bufpos, buflen, pos,
node->data, size))
if (!libfs_blockread(phone, block, bufpos, buflen, pos,
node->data, size, TMPFS_BLOCK_SIZE))
return false;
break;
case 2:
case TMPFS_DIRECTORY:
fname = malloc(entry.len + 1);
if (fname == NULL)
return false;
172,8 → 132,8
return false;
}
if (!tmpfs_blockread(phone, block, bufpos, buflen, pos,
fname, entry.len)) {
if (!libfs_blockread(phone, block, bufpos, buflen, pos,
fname, entry.len, TMPFS_BLOCK_SIZE)) {
ops->destroy((void *) node);
free(fname);
return false;
195,7 → 155,7
default:
return false;
}
} while (entry.type != 0);
} while (entry.type != TMPFS_NONE);
return true;
}
204,7 → 164,7
{
libfs_ops_t *ops = &tmpfs_libfs_ops;
 
void *block = mmap(NULL, BLOCK_SIZE,
void *block = mmap(NULL, TMPFS_BLOCK_SIZE,
PROTO_READ | PROTO_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
if (block == NULL)
214,7 → 174,7
DEVMAP_CONNECT_TO_DEVICE, dev);
 
if (phone < 0) {
munmap(block, BLOCK_SIZE);
munmap(block, TMPFS_BLOCK_SIZE);
return false;
}
222,12 → 182,13
EOK)
goto error;
size_t bufpos = 0;
off_t bufpos = 0;
size_t buflen = 0;
size_t pos = 0;
off_t pos = 0;
char tag[6];
if (!tmpfs_blockread(phone, block, &bufpos, &buflen, &pos, tag, 5))
if (!libfs_blockread(phone, block, &bufpos, &buflen, &pos, tag, 5,
TMPFS_BLOCK_SIZE))
goto error;
tag[5] = 0;
239,12 → 200,12
goto error;
ipc_hangup(phone);
munmap(block, BLOCK_SIZE);
munmap(block, TMPFS_BLOCK_SIZE);
return true;
error:
ipc_hangup(phone);
munmap(block, BLOCK_SIZE);
munmap(block, TMPFS_BLOCK_SIZE);
return false;
}
 
/branches/tracing/uspace/srv/fs/tmpfs/tmpfs_ops.c
233,7 → 233,7
hash_table_destroy(&dentries);
return false;
}
root->lnkcnt = 1;
root->lnkcnt = 0; /* FS root is not linked */
return true;
}
 
405,11 → 405,12
 
if (dev_handle >= 0) {
if (tmpfs_restore(dev_handle))
ipc_answer_0(rid, EOK);
ipc_answer_3(rid, EOK, root->index, root->size,
root->lnkcnt);
else
ipc_answer_0(rid, ELIMIT);
} else {
ipc_answer_0(rid, EOK);
ipc_answer_3(rid, EOK, root->index, root->size, root->lnkcnt);
}
}
 
/branches/tracing/uspace/srv/fs/tmpfs/Makefile
51,7 → 51,7
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
64,9 → 64,11
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/srv/fs/fat/fat.h
222,6 → 222,7
extern void fat_mounted(ipc_callid_t, ipc_call_t *);
extern void fat_mount(ipc_callid_t, ipc_call_t *);
extern void fat_lookup(ipc_callid_t, ipc_call_t *);
extern void fat_read(ipc_callid_t, ipc_call_t *);
 
extern fat_idx_t *fat_idx_get_by_pos(dev_handle_t, fat_cluster_t, unsigned);
extern fat_idx_t *fat_idx_get_by_index(dev_handle_t, fs_index_t);
/branches/tracing/uspace/srv/fs/fat/fat.c
107,6 → 107,9
case VFS_LOOKUP:
fat_lookup(callid, &call);
break;
case VFS_READ:
fat_read(callid, &call);
break;
default:
ipc_answer_0(callid, ENOTSUP);
break;
/branches/tracing/uspace/srv/fs/fat/fat_ops.c
39,6 → 39,8
#include "../../vfs/vfs.h"
#include <libfs.h>
#include <ipc/ipc.h>
#include <ipc/services.h>
#include <ipc/devmap.h>
#include <async.h>
#include <errno.h>
#include <string.h>
47,8 → 49,10
#include <libadt/list.h>
#include <assert.h>
#include <futex.h>
#include <sys/mman.h>
 
#define BS_BLOCK 0
#define BS_SIZE 512
 
/** Futex protecting the list of cached free FAT nodes. */
static futex_t ffn_futex = FUTEX_INITIALIZER;
66,15 → 70,15
#define FAT_DENTRY_DOT 0x2e
#define FAT_DENTRY_ERASED 0xe5
 
#define min(a, b) ((a) < (b) ? (a) : (b))
 
static void dentry_name_canonify(fat_dentry_t *d, char *buf)
{
int i;
 
for (i = 0; i < FAT_NAME_LEN; i++) {
if (d->name[i] == FAT_PAD) {
buf++;
if (d->name[i] == FAT_PAD)
break;
}
if (d->name[i] == FAT_DENTRY_E5_ESC)
*buf++ = 0xe5;
else
92,21 → 96,55
else
*buf++ = d->ext[i];
}
*buf = '\0';
}
 
static int dev_phone = -1; /* FIXME */
static void *dev_buffer = NULL; /* FIXME */
 
/* TODO move somewhere else */
typedef struct {
void *data;
size_t size;
} block_t;
 
static block_t *block_get(dev_handle_t dev_handle, off_t offset)
static block_t *block_get(dev_handle_t dev_handle, off_t offset, size_t bs)
{
return NULL; /* TODO */
/* FIXME */
block_t *b;
off_t bufpos = 0;
size_t buflen = 0;
off_t pos = offset * bs;
 
assert(dev_phone != -1);
assert(dev_buffer);
 
b = malloc(sizeof(block_t));
if (!b)
return NULL;
b->data = malloc(bs);
if (!b->data) {
free(b);
return NULL;
}
b->size = bs;
 
if (!libfs_blockread(dev_phone, dev_buffer, &bufpos, &buflen, &pos,
b->data, bs, bs)) {
free(b->data);
free(b);
return NULL;
}
 
return b;
}
 
static void block_put(block_t *block)
{
/* TODO */
/* FIXME */
free(block->data);
free(block);
}
 
#define FAT_BS(b) ((fat_bs_t *)((b)->data))
143,7 → 181,7
fat_cluster_t clst = firstc;
unsigned i;
 
bb = block_get(dev_handle, BS_BLOCK);
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
spc = FAT_BS(bb)->spc;
rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);
159,7 → 197,7
if (firstc == FAT_CLST_ROOT) {
/* root directory special case */
assert(offset < rds);
b = block_get(dev_handle, rscnt + fatcnt * sf + offset);
b = block_get(dev_handle, rscnt + fatcnt * sf + offset, bps);
return b;
}
 
172,7 → 210,7
fsec = (clst * sizeof(fat_cluster_t)) / bps;
fidx = clst % (bps / sizeof(fat_cluster_t));
/* read FAT1 */
b = block_get(dev_handle, rscnt + fsec);
b = block_get(dev_handle, rscnt + fsec, bps);
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
assert(clst != FAT_CLST_BAD);
assert(clst < FAT_CLST_LAST1);
180,11 → 218,58
}
 
b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc +
offset % spc);
offset % spc, bps);
 
return b;
}
 
/** Return number of blocks allocated to a file.
*
* @param dev_handle Device handle of the device with the file.
* @param firstc First cluster of the file.
*
* @return Number of blocks allocated to the file.
*/
static uint16_t
_fat_blcks_get(dev_handle_t dev_handle, fat_cluster_t firstc)
{
block_t *bb;
block_t *b;
unsigned bps;
unsigned spc;
unsigned rscnt; /* block address of the first FAT */
unsigned clusters = 0;
fat_cluster_t clst = firstc;
 
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
spc = FAT_BS(bb)->spc;
rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt);
block_put(bb);
 
if (firstc == FAT_CLST_RES0) {
/* No space allocated to the file. */
return 0;
}
 
while (clst < FAT_CLST_LAST1) {
unsigned fsec; /* sector offset relative to FAT1 */
unsigned fidx; /* FAT1 entry index */
 
assert(clst >= FAT_CLST_FIRST);
fsec = (clst * sizeof(fat_cluster_t)) / bps;
fidx = clst % (bps / sizeof(fat_cluster_t));
/* read FAT1 */
b = block_get(dev_handle, rscnt + fsec, bps);
clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
assert(clst != FAT_CLST_BAD);
block_put(b);
clusters++;
}
 
return clusters * spc;
}
 
static void fat_node_initialize(fat_node_t *node)
{
futex_initialize(&node->lock, 1);
202,7 → 287,7
block_t *bb;
uint16_t bps;
bb = block_get(dev_handle, BS_BLOCK);
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
assert(bb != NULL);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
block_put(bb);
253,7 → 338,7
{
block_t *b;
fat_dentry_t *d;
fat_node_t *nodep;
fat_node_t *nodep = NULL;
unsigned bps;
unsigned dps;
 
264,7 → 349,7
*/
futex_down(&idxp->nodep->lock);
if (!idxp->nodep->refcnt++)
list_remove(&nodep->ffn_link);
list_remove(&idxp->nodep->ffn_link);
futex_up(&idxp->nodep->lock);
return idxp->nodep;
}
320,11 → 405,18
* and initialized elsewhere.
*/
nodep->type = FAT_DIRECTORY;
/*
* Unfortunately, the 'size' field of the FAT dentry is not
* defined for the directory entry type. We must determine the
* size of the directory by walking the FAT.
*/
nodep->size = bps * _fat_blcks_get(idxp->dev_handle,
uint16_t_le2host(d->firstc));
} else {
nodep->type = FAT_FILE;
nodep->size = uint32_t_le2host(d->size);
}
nodep->firstc = uint16_t_le2host(d->firstc);
nodep->size = uint32_t_le2host(d->size);
nodep->lnkcnt = 1;
nodep->refcnt = 1;
 
421,7 → 513,7
dentry_name_canonify(d, name);
break;
}
if (strcmp(name, component) == 0) {
if (stricmp(name, component) == 0) {
/* hit */
void *node;
/*
567,16 → 659,56
{
dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
block_t *bb;
uint16_t bps;
uint16_t rde;
int rc;
 
/*
* For now, we don't bother to remember dev_handle, dev_phone or
* dev_buffer in some data structure. We use global variables because we
* know there will be at most one mount on this file system.
* Of course, this is a huge TODO item.
*/
dev_buffer = mmap(NULL, BS_SIZE, PROTO_READ | PROTO_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
if (!dev_buffer) {
ipc_answer_0(rid, ENOMEM);
return;
}
 
dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
DEVMAP_CONNECT_TO_DEVICE, dev_handle);
 
if (dev_phone < 0) {
munmap(dev_buffer, BS_SIZE);
ipc_answer_0(rid, dev_phone);
return;
}
 
rc = ipc_share_out_start(dev_phone, dev_buffer,
AS_AREA_READ | AS_AREA_WRITE);
if (rc != EOK) {
munmap(dev_buffer, BS_SIZE);
ipc_answer_0(rid, rc);
return;
}
 
/* Read the number of root directory entries. */
bb = block_get(dev_handle, BS_BLOCK);
bb = block_get(dev_handle, BS_BLOCK, BS_SIZE);
bps = uint16_t_le2host(FAT_BS(bb)->bps);
rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max);
block_put(bb);
 
if (bps != BS_SIZE) {
munmap(dev_buffer, BS_SIZE);
ipc_answer_0(rid, ENOTSUP);
return;
}
 
rc = fat_idx_init_by_dev_handle(dev_handle);
if (rc != EOK) {
munmap(dev_buffer, BS_SIZE);
ipc_answer_0(rid, rc);
return;
}
584,6 → 716,7
/* Initialize the root node. */
fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
if (!rootp) {
munmap(dev_buffer, BS_SIZE);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
return;
592,6 → 725,7
 
fat_idx_t *ridxp = fat_idx_get_by_pos(dev_handle, FAT_CLST_ROOTPAR, 0);
if (!ridxp) {
munmap(dev_buffer, BS_SIZE);
free(rootp);
fat_idx_fini_by_dev_handle(dev_handle);
ipc_answer_0(rid, ENOMEM);
603,6 → 737,7
rootp->type = FAT_DIRECTORY;
rootp->firstc = FAT_CLST_ROOT;
rootp->refcnt = 1;
rootp->lnkcnt = 0; /* FS root is not linked */
rootp->size = rde * sizeof(fat_dentry_t);
rootp->idx = ridxp;
ridxp->nodep = rootp;
609,7 → 744,7
futex_up(&ridxp->lock);
 
ipc_answer_0(rid, EOK);
ipc_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
}
 
void fat_mount(ipc_callid_t rid, ipc_call_t *request)
622,6 → 757,96
libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
}
 
void fat_read(ipc_callid_t rid, ipc_call_t *request)
{
dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
off_t pos = (off_t)IPC_GET_ARG3(*request);
fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index);
uint16_t bps = fat_bps_get(dev_handle);
size_t bytes;
block_t *b;
 
if (!nodep) {
ipc_answer_0(rid, ENOENT);
return;
}
 
ipc_callid_t callid;
size_t len;
if (!ipc_data_read_receive(&callid, &len)) {
fat_node_put(nodep);
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
if (nodep->type == FAT_FILE) {
/*
* Our strategy for regular file reads is to read one block at
* most and make use of the possibility to return less data than
* requested. This keeps the code very simple.
*/
bytes = min(len, bps - pos % bps);
b = fat_block_get(nodep, pos / bps);
(void) ipc_data_read_finalize(callid, b->data + pos % bps,
bytes);
block_put(b);
} else {
unsigned bnum;
off_t spos = pos;
char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
fat_dentry_t *d;
 
assert(nodep->type == FAT_DIRECTORY);
assert(nodep->size % bps == 0);
assert(bps % sizeof(fat_dentry_t) == 0);
 
/*
* Our strategy for readdir() is to use the position pointer as
* an index into the array of all dentries. On entry, it points
* to the first unread dentry. If we skip any dentries, we bump
* the position pointer accordingly.
*/
bnum = (pos * sizeof(fat_dentry_t)) / bps;
while (bnum < nodep->size / bps) {
off_t o;
 
b = fat_block_get(nodep, bnum);
for (o = pos % (bps / sizeof(fat_dentry_t));
o < bps / sizeof(fat_dentry_t);
o++, pos++) {
d = ((fat_dentry_t *)b->data) + o;
switch (fat_classify_dentry(d)) {
case FAT_DENTRY_SKIP:
continue;
case FAT_DENTRY_LAST:
block_put(b);
goto miss;
default:
case FAT_DENTRY_VALID:
dentry_name_canonify(d, name);
block_put(b);
goto hit;
}
}
block_put(b);
bnum++;
}
miss:
fat_node_put(nodep);
ipc_answer_0(callid, ENOENT);
ipc_answer_1(rid, ENOENT, 0);
return;
hit:
(void) ipc_data_read_finalize(callid, name, strlen(name) + 1);
bytes = (pos - spos) + 1;
}
 
fat_node_put(nodep);
ipc_answer_1(rid, EOK, (ipcarg_t)bytes);
}
 
/**
* @}
*/
/branches/tracing/uspace/srv/fs/fat/Makefile
51,7 → 51,7
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
64,9 → 64,11
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/srv/devmap/Makefile
50,7 → 50,7
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
63,9 → 63,11
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/srv/vfs/vfs_ops.c
71,8 → 71,11
{
dev_handle_t dev_handle;
vfs_node_t *mp_node = NULL;
ipc_callid_t callid;
ipc_call_t data;
int rc;
int phone;
size_t size;
 
/*
* We expect the library to do the device-name to device-handle
86,9 → 89,6
* carry mount options in the future.
*/
 
ipc_callid_t callid;
size_t size;
 
/*
* Now, we expect the client to send us data with the name of the file
* system.
115,15 → 115,30
fs_name[size] = '\0';
/*
* Wait for IPC_M_PING so that we can return an error if we don't know
* fs_name.
*/
callid = async_get_call(&data);
if (IPC_GET_METHOD(data) != IPC_M_PING) {
ipc_answer_0(callid, ENOTSUP);
ipc_answer_0(rid, ENOTSUP);
return;
}
 
/*
* Check if we know a file system with the same name as is in fs_name.
* This will also give us its file system handle.
*/
fs_handle_t fs_handle = fs_name_to_handle(fs_name, true);
if (!fs_handle) {
ipc_answer_0(callid, ENOENT);
ipc_answer_0(rid, ENOENT);
return;
}
 
/* Acknowledge that we know fs_name. */
ipc_answer_0(callid, EOK);
 
/* Now, we want the client to send us the mount point. */
if (!ipc_data_write_receive(&callid, &size)) {
ipc_answer_0(callid, EINVAL);
190,6 → 205,12
} else {
/* We still don't have the root file system mounted. */
if ((size == 1) && (buf[0] == '/')) {
vfs_lookup_res_t mr_res;
vfs_node_t *mr_node;
ipcarg_t rindex;
ipcarg_t rsize;
ipcarg_t rlnkcnt;
/*
* For this simple, but important case,
* we are almost done.
198,16 → 219,30
/* Tell the mountee that it is being mounted. */
phone = vfs_grab_phone(fs_handle);
rc = async_req_1_0(phone, VFS_MOUNTED,
(ipcarg_t) dev_handle);
rc = async_req_1_3(phone, VFS_MOUNTED,
(ipcarg_t) dev_handle, &rindex, &rsize, &rlnkcnt);
vfs_release_phone(phone);
 
if (rc == EOK) {
rootfs.fs_handle = fs_handle;
rootfs.dev_handle = dev_handle;
if (rc != EOK) {
futex_up(&rootfs_futex);
ipc_answer_0(rid, rc);
return;
}
 
mr_res.triplet.fs_handle = fs_handle;
mr_res.triplet.dev_handle = dev_handle;
mr_res.triplet.index = (fs_index_t) rindex;
mr_res.size = (size_t) rsize;
mr_res.lnkcnt = (unsigned) rlnkcnt;
 
rootfs.fs_handle = fs_handle;
rootfs.dev_handle = dev_handle;
futex_up(&rootfs_futex);
 
/* Add reference to the mounted root. */
mr_node = vfs_node_get(&mr_res);
assert(mr_node);
 
ipc_answer_0(rid, rc);
return;
} else {
374,12 → 409,8
void vfs_close(ipc_callid_t rid, ipc_call_t *request)
{
int fd = IPC_GET_ARG1(*request);
if (fd >= MAX_OPEN_FILES) {
ipc_answer_0(rid, EBADF);
return;
}
vfs_fd_free(fd);
ipc_answer_0(rid, EOK);
int rc = vfs_fd_free(fd);
ipc_answer_0(rid, rc);
}
 
static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read)
/branches/tracing/uspace/srv/vfs/vfs.h
282,7 → 282,7
extern bool vfs_files_init(void);
extern vfs_file_t *vfs_file_get(int);
extern int vfs_fd_alloc(void);
extern void vfs_fd_free(int);
extern int vfs_fd_free(int);
 
extern void vfs_file_addref(vfs_file_t *);
extern void vfs_file_delref(vfs_file_t *);
/branches/tracing/uspace/srv/vfs/Makefile
52,7 → 52,7
 
.PHONY: all clean depend disasm
 
all: $(OUTPUT) disasm
all: $(OUTPUT) $(OUTPUT).disasm
 
-include Makefile.depend
 
65,9 → 65,11
$(OUTPUT): $(OBJECTS) $(LIBS)
$(LD) -T $(LIBC_PREFIX)/arch/$(ARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
 
disasm:
$(OBJDUMP) -d $(OUTPUT) >$(OUTPUT).disasm
disasm: $(OUTPUT).disasm
 
$(OUTPUT).disasm: $(OUTPUT)
$(OBJDUMP) -d $< >$@
 
%.o: %.S
$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
 
/branches/tracing/uspace/srv/vfs/vfs_file.c
97,13 → 97,17
/** Release file descriptor.
*
* @param fd File descriptor being released.
*
* @return EOK on success or EBADF if fd is an invalid file
* descriptor.
*/
void vfs_fd_free(int fd)
int vfs_fd_free(int fd)
{
assert(fd < MAX_OPEN_FILES);
assert(files[fd] != NULL);
if ((fd >= MAX_OPEN_FILES) || (files[fd] == NULL))
return EBADF;
vfs_file_delref(files[fd]);
files[fd] = NULL;
return EOK;
}
 
/** Increment reference count of VFS file structure.
/branches/tracing/uspace/Makefile
37,6 → 37,7
lib/softint \
lib/softfloat \
srv/ns \
srv/loader \
srv/fb \
srv/kbd \
srv/console \
50,7 → 51,8
app/tetris \
app/tester \
app/klog \
app/init
app/init \
app/bdsh
 
ifeq ($(ARCH), amd64)
DIRS += srv/pci
/branches/tracing/HelenOS.config
45,7 → 45,6
@ "simics" Simics
@ "bgxemul" GXEmul big endian
@ "lgxemul" GXEmul little endian
@ "indy" Sgi Indy
! [PLATFORM=mips32] MACHINE (choice)
 
# Machine type
/branches/tracing/boot/tools/ia64/vmaxlma.c
File deleted
/branches/tracing/boot/boot.config
78,3 → 78,7
@ "ecoff" Ecoff image (GXEmul)
! [ARCH=mips32] IMAGE (choice)
 
# Ramdisk format
@ "tmpfs" TMPFS image
@ "fat" FAT16 image
! RDFMT (choice)
/branches/tracing/boot/generic/string.c
39,9 → 39,9
 
/** Return number of characters in a string.
*
* @param str NULL terminated string.
* @param str NULL terminated string.
*
* @return Number of characters in str.
* @return Number of characters in str.
*/
size_t strlen(const char *str)
{
53,16 → 53,17
return i;
}
 
/** Compare two NULL terminated strings
/** Compare two NULL terminated strings.
*
* Do a char-by-char comparison of two NULL terminated strings.
* The strings are considered equal iff they consist of the same
* characters on the minimum of their lengths.
*
* @param src First string to compare.
* @param dst Second string to compare.
* @param src First string to compare.
* @param dst Second string to compare.
*
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller.
* @return 0 if the strings are equal, -1 if first is smaller,
* 1 if second smaller.
*
*/
int strcmp(const char *src, const char *dst)
81,7 → 82,7
}
 
 
/** Compare two NULL terminated strings
/** Compare two NULL terminated strings.
*
* Do a char-by-char comparison of two NULL terminated strings.
* The strings are considered equal iff they consist of the same
88,11 → 89,12
* characters on the minimum of their lengths and specified maximal
* length.
*
* @param src First string to compare.
* @param dst Second string to compare.
* @param len Maximal length for comparison.
* @param src First string to compare.
* @param dst Second string to compare.
* @param len Maximal length for comparison.
*
* @return 0 if the strings are equal, -1 if first is smaller, 1 if second smaller.
* @return 0 if the strings are equal, -1 if first is smaller,
* 1 if second smaller.
*
*/
int strncmp(const char *src, const char *dst, size_t len)
118,9 → 120,9
* If 'src' is shorter than 'len', '\0' is inserted behind the
* last copied character.
*
* @param src Source string.
* @param dest Destination buffer.
* @param len Size of destination buffer.
* @param src Source string.
* @param dest Destination buffer.
* @param len Size of destination buffer.
*/
void strncpy(char *dest, const char *src, size_t len)
{
132,13 → 134,13
dest[i-1] = '\0';
}
 
/** Convert ascii representation to unative_t
/** Convert ascii representation to unative_t.
*
* Supports 0x for hexa & 0 for octal notation.
* Does not check for overflows, does not support negative numbers
*
* @param text Textual representation of number
* @return Converted number or 0 if no valid number ofund
* @param text Textual representation of number.
* @return Converted number or 0 if no valid number found.
*/
unative_t atoi(const char *text)
{
152,9 → 154,9
base = 8;
 
while (*text) {
if (base != 16 && \
((*text >= 'A' && *text <= 'F' )
|| (*text >='a' && *text <='f')))
if (base != 16 &&
((*text >= 'A' && *text <= 'F') ||
(*text >='a' && *text <='f')))
break;
if (base == 8 && *text >='8')
break;
176,5 → 178,28
return result;
}
 
/** Move piece of memory to another, possibly overlapping, location.
*
* @param dst Destination address.
* @param src Source address.
* @param len Number of bytes to move.
*
* @return Destination address.
*/
void *memmove(void *dst, const void *src, size_t len)
{
char *d = dst;
const char *s = src;
if (s < d) {
while (len--)
*(d + len) = *(s + len);
} else {
while (len--)
*d++ = *s++;
}
return dst;
}
 
/** @}
*/
/branches/tracing/boot/generic/string.h
42,6 → 42,7
extern int strncmp(const char *src, const char *dst, size_t len);
extern void strncpy(char *dest, const char *src, size_t len);
extern unative_t atoi(const char *text);
extern void *memmove(void *dst, const void *src, size_t len);
 
#endif
 
/branches/tracing/boot/arch/sparc64/Makefile.inc
36,6 → 36,8
cat arch/$(ARCH)/silo/silo.tar.gz | (cd $(TMP)/boot; tar xvfz -)
cp arch/$(ARCH)/silo/README arch/$(ARCH)/silo/COPYING arch/$(ARCH)/silo/silo.conf $(TMP)/boot
cp arch/$(ARCH)/loader/image.boot $(TMP)/HelenOS/image.boot
gzip -f $(TMP)/HelenOS/image.boot
cp arch/$(ARCH)/loader/initrd.img $(TMP)/HelenOS/initrd.img
mkisofs -f -G $(TMP)/boot/isofs.b -B ... -r -o $(BASE)/image.iso $(TMP)/
 
depend:
/branches/tracing/boot/arch/sparc64/loader/asm.S
30,6 → 30,9
#include <stack.h>
#include <register.h>
 
.register %g2, #scratch
.register %g3, #scratch
 
.text
 
.global halt
41,8 → 44,7
nop
memcpy:
.register %g2, #scratch
.register %g3, #scratch
mov %o0, %o3 ! save dst
add %o1, 7, %g1
and %g1, -8, %g1
cmp %o1, %g1
61,7 → 63,7
mov %g2, %g3
2:
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
3:
and %g1, -8, %g1
cmp %o0, %g1
95,7 → 97,7
mov %g2, %g3
 
jmp %o7 + 8 ! exit point
mov %o1, %o0
mov %o3, %o0
 
jump_to_kernel:
/*
/branches/tracing/boot/arch/sparc64/loader/boot.S
53,6 → 53,15
.ascii "HdrS"
.word 0
.half 0
.half 0
.half 0
.half 0
.global silo_ramdisk_image
silo_ramdisk_image:
.word 0
.global silo_ramdisk_size
silo_ramdisk_size:
.word 0
 
.align 8
1:
/branches/tracing/boot/arch/sparc64/loader/main.c
36,6 → 36,7
#include <ofw_tree.h>
#include "ofwarch.h"
#include <align.h>
#include <string.h>
 
bootinfo_t bootinfo;
component_t components[COMPONENTS];
57,11 → 58,18
/** Print version information. */
static void version_print(void)
{
printf("HelenOS SPARC64 Bootloader\nRelease %s%s%s\nCopyright (c) 2006 HelenOS project\n", release, revision, timestamp);
printf("HelenOS SPARC64 Bootloader\nRelease %s%s%s\n"
"Copyright (c) 2006 HelenOS project\n",
release, revision, timestamp);
}
 
void bootstrap(void)
{
void *base = (void *) KERNEL_VIRTUAL_ADDRESS;
void *balloc_base;
unsigned int top = 0;
int i, j;
 
version_print();
init_components(components);
80,29 → 88,94
printf("Error: no memory detected, halting.\n");
halt();
}
 
/*
* SILO for some reason adds 0x400000 and subtracts
* bootinfo.physmem_start to/from silo_ramdisk_image.
* We just need plain physical address so we fix it up.
*/
if (silo_ramdisk_image) {
silo_ramdisk_image += bootinfo.physmem_start;
silo_ramdisk_image -= 0x400000;
/* Install 1:1 mapping for the ramdisk. */
if (ofw_map((void *)((uintptr_t)silo_ramdisk_image),
(void *)((uintptr_t)silo_ramdisk_image),
silo_ramdisk_size, -1) != 0) {
printf("Failed to map ramdisk.\n");
halt();
}
}
printf("\nSystem info\n");
printf(" memory: %dM starting at %P\n",
bootinfo.memmap.total >> 20, bootinfo.physmem_start);
bootinfo.memmap.total >> 20, bootinfo.physmem_start);
 
printf("\nMemory statistics\n");
printf(" kernel entry point at %P\n", KERNEL_VIRTUAL_ADDRESS);
printf(" %P: boot info structure\n", &bootinfo);
unsigned int i;
for (i = 0; i < COMPONENTS; i++)
/*
* Figure out destination address for each component.
* In this phase, we don't copy the components yet because we want to
* to be careful not to overwrite anything, especially the components
* which haven't been copied yet.
*/
bootinfo.taskmap.count = 0;
for (i = 0; i < COMPONENTS; i++) {
printf(" %P: %s image (size %d bytes)\n", components[i].start,
components[i].name, components[i].size);
top = ALIGN_UP(top, PAGE_SIZE);
if (i > 0) {
if (bootinfo.taskmap.count == TASKMAP_MAX_RECORDS) {
printf("Skipping superfluous components.\n");
break;
}
bootinfo.taskmap.tasks[bootinfo.taskmap.count].addr =
base + top;
bootinfo.taskmap.tasks[bootinfo.taskmap.count].size =
components[i].size;
bootinfo.taskmap.count++;
}
top += components[i].size;
}
 
void * base = (void *) KERNEL_VIRTUAL_ADDRESS;
unsigned int top = 0;
j = bootinfo.taskmap.count - 1; /* do not consider ramdisk */
 
printf("\nCopying components\n");
bootinfo.taskmap.count = 0;
for (i = 0; i < COMPONENTS; i++) {
printf(" %s...", components[i].name);
if (silo_ramdisk_image) {
/* Treat the ramdisk as the last bootinfo task. */
if (bootinfo.taskmap.count == TASKMAP_MAX_RECORDS) {
printf("Skipping ramdisk.\n");
goto skip_ramdisk;
}
top = ALIGN_UP(top, PAGE_SIZE);
bootinfo.taskmap.tasks[bootinfo.taskmap.count].addr =
base + top;
bootinfo.taskmap.tasks[bootinfo.taskmap.count].size =
silo_ramdisk_size;
bootinfo.taskmap.count++;
printf("\nCopying ramdisk...");
/*
* Claim and map the whole ramdisk as it may exceed the area
* given to us by SILO.
*/
(void) ofw_claim_phys(base + top, silo_ramdisk_size);
(void) ofw_map(base + top, base + top, silo_ramdisk_size, -1);
memmove(base + top, (void *)((uintptr_t)silo_ramdisk_image),
silo_ramdisk_size);
printf("done.\n");
top += silo_ramdisk_size;
}
skip_ramdisk:
 
/*
* Now we can proceed to copy the components. We do it in reverse order
* so that we don't overwrite anything even if the components overlap
* with base.
*/
printf("\nCopying bootinfo tasks\n");
for (i = COMPONENTS - 1; i > 0; i--, j--) {
printf(" %s...", components[i].name);
 
/*
* At this point, we claim the physical memory that we are
* going to use. We should be safe in case of the virtual
110,30 → 183,34
* SPARC binding, should restrict its use of virtual memory
* to addresses from [0xffd00000; 0xffefffff] and
* [0xfe000000; 0xfeffffff].
*
* XXX We don't map this piece of memory. We simply rely on
* SILO to have it done for us already in this case.
*/
(void) ofw_claim_phys(bootinfo.physmem_start + base + top,
(void) ofw_claim_phys(bootinfo.physmem_start +
bootinfo.taskmap.tasks[j].addr,
ALIGN_UP(components[i].size, PAGE_SIZE));
memcpy(base + top, components[i].start, components[i].size);
if (i > 0) {
bootinfo.taskmap.tasks[bootinfo.taskmap.count].addr =
base + top;
bootinfo.taskmap.tasks[bootinfo.taskmap.count].size =
components[i].size;
bootinfo.taskmap.count++;
}
top += components[i].size;
memcpy((void *)bootinfo.taskmap.tasks[j].addr,
components[i].start, components[i].size);
printf("done.\n");
}
 
printf("\nCopying kernel...");
(void) ofw_claim_phys(bootinfo.physmem_start + base,
ALIGN_UP(components[0].size, PAGE_SIZE));
memcpy(base, components[0].start, components[0].size);
printf("done.\n");
 
/*
* Claim the physical memory for the boot allocator.
* Claim and map the physical memory for the boot allocator.
* Initialize the boot allocator.
*/
(void) ofw_claim_phys(bootinfo.physmem_start +
base + ALIGN_UP(top, PAGE_SIZE), BALLOC_MAX_SIZE);
balloc_init(&bootinfo.ballocs, ALIGN_UP(((uintptr_t) base) + top,
PAGE_SIZE));
balloc_base = base + ALIGN_UP(top, PAGE_SIZE);
(void) ofw_claim_phys(bootinfo.physmem_start + balloc_base,
BALLOC_MAX_SIZE);
(void) ofw_map(balloc_base, balloc_base, BALLOC_MAX_SIZE, -1);
balloc_init(&bootinfo.ballocs, (uintptr_t)balloc_base);
 
printf("\nCanonizing OpenFirmware device tree...");
bootinfo.ofw_root = ofw_tree_build();
/branches/tracing/boot/arch/sparc64/loader/main.h
59,6 → 59,9
ofw_tree_node_t *ofw_root;
} bootinfo_t;
 
extern uint32_t silo_ramdisk_image;
extern uint32_t silo_ramdisk_size;
 
extern bootinfo_t bootinfo;
 
extern void start(void);
/branches/tracing/boot/arch/sparc64/loader/Makefile
32,10 → 32,14
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf64-sparc
BFD_ARCH = sparc
TARGET = sparc64-linux-gnu
TOOLCHAIN_DIR = /usr/local/sparc64/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/sparc64/bin
 
ifeq ($(COMPILER),gcc_native)
CC = gcc
53,7 → 57,7
OBJDUMP = $(TOOLCHAIN_DIR)/$(TARGET)-objdump
endif
 
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mcpu=ultrasparc -m64
CFLAGS = -DRELEASE=\"$(RELEASE)\" -I. -I../../../generic -I../../../genarch -nostdinc -nostdlib -fno-builtin -Werror-implicit-function-declaration -Wmissing-prototypes -Werror -O3 -mcpu=ultrasparc -m64 -mno-fpu
 
ifdef REVISION
CFLAGS += "-DREVISION=\"$(REVISION)\""
79,19 → 83,29
$(KERNELDIR)/kernel.bin \
$(USPACEDIR)/srv/ns/ns \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
endif
ifeq ($(RDFMT),fat)
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
RD_TASKS = \
RD_SRVS = \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat
 
RD_APPS = \
$(USPACEDIR)/app/sctrace/sctrace \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/bdsh/bdsh \
$(USPACEDIR)/app/klog/klog
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
103,24 → 117,37
 
-include Makefile.depend
 
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS)
$(LD) -Map image.map -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) -o $@
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS)
$(LD) -Map image.map -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
 
clean:
-for task in $(RD_TASKS) ; do \
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \
-for file in $(RD_SRVS) ; do \
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
done
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) initrd.img image.boot image.map image.disasm Makefile.depend
-for file in $(RD_APPS) ; do \
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
done
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) initrd.img image.boot image.map image.disasm Makefile.depend
 
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_TASKS) _link.ld.in
for task in $(RD_TASKS) ; do \
cp $$task $(USPACEDIR)/dist/sbin/ ; \
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_SRVS) $(RD_APPS) _link.ld.in
for file in $(RD_SRVS) ; do \
cp $$file $(USPACEDIR)/dist/srv/ ; \
done
../../../../tools/mktmpfs.py 16384 $(USPACEDIR)/dist/ initrd.img
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 1 "unsigned long" $(COMPONENTS) ./initrd.img
for file in $(RD_APPS) ; do \
cp $$file $(USPACEDIR)/dist/app/ ; \
done
ifeq ($(RDFMT),tmpfs)
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs
endif
ifeq ($(RDFMT),fat)
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs
endif
../../../../tools/mkhord.py 16384 initrd.fs initrd.img
rm initrd.fs
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 1 "unsigned long" $(COMPONENTS)
 
%.o: %.S
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/tracing/boot/arch/sparc64/silo/silo.conf
1,3 → 1,4
timeout = 0
image = /HelenOS/image.boot
image = /HelenOS/image.boot.gz
label = HelenOS
initrd = /HelenOS/initrd.img
/branches/tracing/boot/arch/ia64/Makefile.inc
28,23 → 28,6
 
#ifeq ($(MACHINE),ski)
 
 
 
#VMAXLMA_SRC = tools/ia64/vmaxlma.c
#build: $(BASE)/kernel.bin
#echo Building SKI
#$(BASE)/kernel.bin: $(KERNELDIR)/kernel.bin vmaxlma
# cp $(KERNELDIR)/kernel.bin $(BASE)/kernel.bin
# ./vmaxlma $(BASE)/kernel.bin
#vmaxlma: $(VMAXLMA_SRC)
# $(CC) $(VMAXLMA_SRC) -o $@
#clean:
# -rm -f $(BASE)/kernel.bin vmaxlma
 
 
#else
 
 
build: $(BASE)/image.boot
 
$(BASE)/image.boot: depend arch/$(ARCH)/loader/image.boot
60,5 → 43,5
make -C arch/$(ARCH)/loader clean COMPILER=$(COMPILER) KERNELDIR=../../../$(KERNELDIR) USPACEDIR=../../../$(USPACEDIR) "DEFS=$(DEFS)"
-rm -f $(BASE)/image.boot
 
#endif
 
#endif
/branches/tracing/boot/arch/ia64/loader/Makefile
32,10 → 32,14
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf64-ia64-little
BFD_ARCH = ia64
TARGET = ia64-pc-linux-gnu
TOOLCHAIN_DIR = /usr/local/ia64/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ia64/bin
 
ifeq ($(COMPILER),gcc_native)
CC = gcc
86,6 → 90,7
COMPONENTS = \
$(KERNELDIR)/kernel.bin \
$(USPACEDIR)/srv/ns/ns \
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
/branches/tracing/boot/arch/arm32/loader/asm.S
35,7 → 35,8
add r3, r1, #3
bic r3, r3, #3
cmp r1, r3
stmdb sp!, {r4, lr}
stmdb sp!, {r4, r5, lr}
mov r5, r0
beq 4f
1:
cmp r2, #0
48,8 → 49,8
cmp ip, r2
bne 2b
3:
mov r0, r1
ldmia sp!, {r4, pc}
mov r0, r5
ldmia sp!, {r4, r5, pc}
4:
add r3, r0, #3
bic r3, r3, #3
/branches/tracing/boot/arch/arm32/loader/Makefile
32,10 → 32,14
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf32-littlearm
BFD_ARCH = arm
TARGET = arm-linux-gnu
TOOLCHAIN_DIR = /usr/local/arm/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/arm/bin
 
ifeq ($(COMPILER),gcc_native)
CC = gcc
80,19 → 84,31
COMPONENTS = \
$(KERNELDIR)/kernel.bin \
$(USPACEDIR)/srv/ns/ns \
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
endif
ifeq ($(RDFMT),fat)
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
RD_SRVS = \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/vfs/vfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/fs/fat/fat
 
RD_APPS = \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/sctrace/sctrace \
$(USPACEDIR)/app/klog/klog
$(USPACEDIR)/app/klog/klog \
$(USPACEDIR)/app/bdsh/bdsh
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS))))
103,17 → 119,37
 
-include Makefile.depend
 
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS)
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS)
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) -o $@
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
 
clean:
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) image.boot Makefile.depend
-for file in $(RD_SRVS) ; do \
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
done
-for file in $(RD_APPS) ; do \
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
done
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) initrd.img image.boot Makefile.depend
 
_components.h _components.c _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) _link.ld.in
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 4096 "unsigned int" $(COMPONENTS)
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_SRVS) $(RD_APPS) _link.ld.in
for file in $(RD_SRVS) ; do \
cp $$file $(USPACEDIR)/dist/srv/ ; \
done
for file in $(RD_APPS) ; do \
cp $$file $(USPACEDIR)/dist/app/ ; \
done
ifeq ($(RDFMT),tmpfs)
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs
endif
ifeq ($(RDFMT),fat)
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs
endif
../../../../tools/mkhord.py 4096 initrd.fs initrd.img
rm initrd.fs
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 4096 "unsigned int" $(COMPONENTS) ./initrd.img
 
%.o: %.S
$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@
/branches/tracing/boot/arch/ppc32/loader/main.c
116,15 → 116,11
halt();
}
if (!ofw_screen(&bootinfo.screen)) {
printf("Error: unable to get screen properties, halting.\n");
halt();
}
if (!ofw_screen(&bootinfo.screen))
printf("Warning: unable to get screen properties.\n");
if (!ofw_keyboard(&bootinfo.keyboard)) {
printf("Error: unable to get keyboard properties, halting.\n");
halt();
}
if (!ofw_keyboard(&bootinfo.keyboard))
printf("Warning: unable to get keyboard properties.\n");
printf("\nDevice statistics\n");
printf(" screen at %L, resolution %dx%d, %d bpp (scanline %d bytes)\n", bootinfo.screen.addr, bootinfo.screen.width, bootinfo.screen.height, bootinfo.screen.bpp, bootinfo.screen.scanline);
/branches/tracing/boot/arch/ppc32/loader/ofwarch.c
39,7 → 39,13
 
void write(const char *str, const int len)
{
ofw_write(str, len);
int i;
for (i = 0; i < len; i++) {
if (str[i] == '\n')
ofw_write("\r", 1);
ofw_write(&str[i], 1);
}
}
 
int ofw_keyboard(keyboard_t *keyboard)
/branches/tracing/boot/arch/ppc32/loader/Makefile
32,10 → 32,14
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf32-powerpc
BFD_ARCH = powerpc:common
TARGET = ppc-linux-gnu
TOOLCHAIN_DIR = /usr/local/ppc/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc/bin
 
ifeq ($(COMPILER),gcc_native)
CC = gcc
75,21 → 79,31
COMPONENTS = \
$(KERNELDIR)/kernel.bin \
$(USPACEDIR)/srv/ns/ns \
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
endif
ifeq ($(RDFMT),fat)
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
RD_TASKS = \
RD_SRVS = \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat
 
RD_APPS = \
$(USPACEDIR)/app/sctrace/sctrace \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/klog/klog
$(USPACEDIR)/app/klog/klog \
$(USPACEDIR)/app/bdsh/bdsh
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS))))
107,16 → 121,29
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
 
clean:
-for task in $(RD_TASKS) ; do \
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \
-for file in $(RD_SRVS) ; do \
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
done
-for file in $(RD_APPS) ; do \
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
done
-rm -f _components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) initrd.img image.boot Makefile.depend
 
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_TASKS) _link.ld.in
for task in $(RD_TASKS) ; do \
cp $$task $(USPACEDIR)/dist/sbin/ ; \
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_SRVS) $(RD_APPS) _link.ld.in
for file in $(RD_SRVS) ; do \
cp $$file $(USPACEDIR)/dist/srv/ ; \
done
../../../../tools/mktmpfs.py 4096 $(USPACEDIR)/dist/ initrd.img
for file in $(RD_APPS) ; do \
cp $$file $(USPACEDIR)/dist/app/ ; \
done
ifeq ($(RDFMT),tmpfs)
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs
endif
ifeq ($(RDFMT),fat)
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs
endif
../../../../tools/mkhord.py 4096 initrd.fs initrd.img
rm initrd.fs
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 4096 "unsigned int" $(COMPONENTS) ./initrd.img
 
%.o: %.S
/branches/tracing/boot/arch/amd64/grub/menu.lst
10,4 → 10,6
module /boot/rd
module /boot/vfs
module /boot/tmpfs
module /boot/fat
module /boot/loader
module /boot/initrd.img
/branches/tracing/boot/arch/amd64/Makefile.inc
28,42 → 28,70
 
INIT_TASKS = \
$(USPACEDIR)/srv/ns/ns \
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
INIT_TASKS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
endif
ifeq ($(RDFMT),fat)
INIT_TASKS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
RD_TASKS = \
RD_SRVS = \
$(USPACEDIR)/srv/pci/pci \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat
 
RD_APPS = \
$(USPACEDIR)/app/sctrace/sctrace \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/klog/klog
$(USPACEDIR)/app/klog/klog \
$(USPACEDIR)/app/bdsh/bdsh
 
build: $(BASE)/image.iso
 
$(BASE)/image.iso: arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(INIT_TASKS) $(RD_TASKS)
$(BASE)/image.iso: arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(INIT_TASKS) $(RD_SRVS) $(RD_APPS)
mkdir -p arch/$(ARCH)/iso/boot/grub
cp arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/iso/boot/grub/
cp arch/$(ARCH)/grub/menu.lst arch/$(ARCH)/iso/boot/grub/
ifneq ($(RDFMT),tmpfs)
cat arch/$(ARCH)/grub/menu.lst | grep -v "tmpfs" >arch/$(ARCH)/iso/boot/grub/menu.lst
endif
ifneq ($(RDFMT),fat)
cat arch/$(ARCH)/grub/menu.lst | grep -v "fat" >arch/$(ARCH)/iso/boot/grub/menu.lst
endif
cp $(KERNELDIR)/kernel.bin arch/$(ARCH)/iso/boot/
for task in $(INIT_TASKS) ; do \
cp $$task arch/$(ARCH)/iso/boot/ ; \
done
for task in $(RD_TASKS) ; do \
cp $$task $(USPACEDIR)/dist/sbin/ ; \
for file in $(RD_SRVS) ; do \
cp $$file $(USPACEDIR)/dist/srv/ ; \
done
$(BASE)/tools/mktmpfs.py 4096 $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.img
for file in $(RD_APPS) ; do \
cp $$file $(USPACEDIR)/dist/app/ ; \
done
ifeq ($(RDFMT),tmpfs)
$(BASE)/tools/mktmpfs.py $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs
endif
ifeq ($(RDFMT),fat)
$(BASE)/tools/mkfat.sh $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs
endif
$(BASE)/tools/mkhord.py 4096 arch/$(ARCH)/iso/boot/initrd.fs arch/$(ARCH)/iso/boot/initrd.img
rm arch/$(ARCH)/iso/boot/initrd.fs
mkisofs -J -r -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o $(BASE)/image.iso arch/$(ARCH)/iso/
 
clean:
-for task in $(RD_TASKS) ; do \
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \
-for file in $(RD_SRVS) ; do \
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
done
-for file in $(RD_APPS) ; do \
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
done
-rm -fr arch/$(ARCH)/iso
-rm -f $(BASE)/image.iso
/branches/tracing/boot/arch/ppc64/loader/Makefile
32,10 → 32,14
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
BFD_NAME = elf64-powerpc
BFD_ARCH = powerpc:common64
TARGET = ppc64-linux-gnu
TOOLCHAIN_DIR = /usr/local/ppc64/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/ppc64/bin
 
ifeq ($(COMPILER),gcc_native)
CC = gcc
/branches/tracing/boot/arch/mips32/loader/asm.S
48,6 → 48,7
and $v0,$v0,$v1
beq $a1,$v0,3f
move $t0,$a0
move $t2,$a0 # save dst
 
0:
beq $a2,$zero,2f
63,7 → 64,7
 
2:
jr $ra
move $v0,$a1
move $v0,$t2
 
3:
addiu $v0,$a0,3
103,7 → 104,7
sb $a0,0($v1)
 
jr $ra
move $v0,$a1
move $v0,$t2
 
jump_to_kernel:
#
/branches/tracing/boot/arch/mips32/loader/Makefile
32,6 → 32,10
## Toolchain configuration
#
 
ifndef CROSS_PREFIX
CROSS_PREFIX = /usr/local
endif
 
ifeq ($(IMAGE),binary)
LD_IN = binary
endif
41,7 → 45,7
BFD_NAME = elf32-tradlittlemips
BFD_ARCH = mips
TARGET = mipsel-linux-gnu
TOOLCHAIN_DIR = /usr/local/mipsel/bin
TOOLCHAIN_DIR = $(CROSS_PREFIX)/mipsel/bin
 
ifeq ($(COMPILER),gcc_native)
CC = gcc
80,19 → 84,32
COMPONENTS = \
$(KERNELDIR)/kernel.bin \
$(USPACEDIR)/srv/ns/ns \
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
COMPONENTS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
endif
ifeq ($(RDFMT),fat)
COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
RD_SRVS = \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/vfs/vfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/fs/fat/fat
 
RD_APPS = \
$(USPACEDIR)/app/sctrace/sctrace \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/klog/klog \
$(USPACEDIR)/app/debug/debug
$(USPACEDIR)/app/debug/debug \
$(USPACEDIR)/app/bdsh/bdsh \
$(USPACEDIR)/app/klog/klog
 
OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
COMPONENT_OBJECTS := $(addsuffix .o,$(basename $(notdir $(COMPONENTS))))
103,17 → 120,37
 
-include Makefile.depend
 
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) $(OBJECTS)
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) $(OBJECTS) -o $@
image.boot: depend _components.h _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS)
$(LD) -no-check-sections -N -T _link.ld $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) -o $@
 
depend:
-makedepend $(DEFS) $(CFLAGS) -f - $(SOURCES) > Makefile.depend 2> /dev/null
 
clean:
-rm -f _components.h _components.c _link.ld _link.ld.in $(COMPONENT_OBJECTS) $(OBJECTS) image.boot Makefile.depend
-for file in $(RD_SRVS) ; do \
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
done
-for file in $(RD_APPS) ; do \
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
done
-rm -f _components.h _components.c _link.ld _link.ld.in $(COMPONENT_OBJECTS) initrd.o $(OBJECTS) initrd.img image.boot Makefile.depend
 
_components.h _components.c _link.ld $(COMPONENT_OBJECTS): $(COMPONENTS) _link.ld.in
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 4096 "unsigned int" $(COMPONENTS)
_components.h _components.c _link.ld $(COMPONENT_OBJECTS) initrd.o: $(COMPONENTS) $(RD_SRVS) $(RD_APPS) _link.ld.in
for file in $(RD_SRVS) ; do \
cp $$file $(USPACEDIR)/dist/srv/ ; \
done
for file in $(RD_APPS) ; do \
cp $$file $(USPACEDIR)/dist/app/ ; \
done
ifeq ($(RDFMT),tmpfs)
../../../../tools/mktmpfs.py $(USPACEDIR)/dist/ initrd.fs
endif
ifeq ($(RDFMT),fat)
../../../../tools/mkfat.sh $(USPACEDIR)/dist/ initrd.fs
endif
../../../../tools/mkhord.py 16384 initrd.fs initrd.img
rm initrd.fs
../../../tools/pack.py $(OBJCOPY) $(BFD_NAME) $(BFD_ARCH) 16384 "unsigned int" $(COMPONENTS) ./initrd.img
 
_link.ld.in: _link.ld.in.$(LD_IN)
cp $< $@
/branches/tracing/boot/arch/ia32/grub/menu.lst
10,4 → 10,6
module /boot/rd
module /boot/vfs
module /boot/tmpfs
module /boot/fat
module /boot/loader
module /boot/initrd.img
/branches/tracing/boot/arch/ia32/Makefile.inc
28,43 → 28,70
 
INIT_TASKS = \
$(USPACEDIR)/srv/ns/ns \
$(USPACEDIR)/srv/loader/loader \
$(USPACEDIR)/app/init/init \
$(USPACEDIR)/srv/devmap/devmap \
$(USPACEDIR)/srv/rd/rd \
$(USPACEDIR)/srv/vfs/vfs \
$(USPACEDIR)/srv/fs/tmpfs/tmpfs
$(USPACEDIR)/srv/vfs/vfs
ifeq ($(RDFMT),tmpfs)
INIT_TASKS += $(USPACEDIR)/srv/fs/tmpfs/tmpfs
endif
ifeq ($(RDFMT),fat)
INIT_TASKS += $(USPACEDIR)/srv/fs/fat/fat
endif
 
RD_TASKS = \
RD_SRVS = \
$(USPACEDIR)/srv/pci/pci \
$(USPACEDIR)/srv/fb/fb \
$(USPACEDIR)/srv/kbd/kbd \
$(USPACEDIR)/srv/console/console \
$(USPACEDIR)/srv/fs/fat/fat \
$(USPACEDIR)/srv/fs/fat/fat
 
RD_APPS = \
$(USPACEDIR)/app/sctrace/sctrace \
$(USPACEDIR)/app/tetris/tetris \
$(USPACEDIR)/app/tester/tester \
$(USPACEDIR)/app/debug/debug \
$(USPACEDIR)/app/klog/klog \
$(USPACEDIR)/app/debug/debug
$(USPACEDIR)/app/bdsh/bdsh
 
build: $(BASE)/image.iso
 
$(BASE)/image.iso: arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(INIT_TASKS) $(RD_TASKS)
$(BASE)/image.iso: arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/grub/menu.lst $(KERNELDIR)/kernel.bin $(INIT_TASKS) $(RD_SRVS) $(RD_APPS)
mkdir -p arch/$(ARCH)/iso/boot/grub
cp arch/$(ARCH)/grub/stage2_eltorito arch/$(ARCH)/iso/boot/grub/
cp arch/$(ARCH)/grub/menu.lst arch/$(ARCH)/iso/boot/grub/
ifneq ($(RDFMT),tmpfs)
cat arch/$(ARCH)/grub/menu.lst | grep -v "tmpfs" >arch/$(ARCH)/iso/boot/grub/menu.lst
endif
ifneq ($(RDFMT),fat)
cat arch/$(ARCH)/grub/menu.lst | grep -v "fat" >arch/$(ARCH)/iso/boot/grub/menu.lst
endif
cp $(KERNELDIR)/kernel.bin arch/$(ARCH)/iso/boot/
for task in $(INIT_TASKS) ; do \
cp $$task arch/$(ARCH)/iso/boot/ ; \
done
for task in $(RD_TASKS) ; do \
cp $$task $(USPACEDIR)/dist/sbin/ ; \
for file in $(RD_SRVS) ; do \
cp $$file $(USPACEDIR)/dist/srv/ ; \
done
$(BASE)/tools/mktmpfs.py 4096 $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.img
for file in $(RD_APPS) ; do \
cp $$file $(USPACEDIR)/dist/app/ ; \
done
ifeq ($(RDFMT),tmpfs)
$(BASE)/tools/mktmpfs.py $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs
endif
ifeq ($(RDFMT),fat)
$(BASE)/tools/mkfat.sh $(USPACEDIR)/dist/ arch/$(ARCH)/iso/boot/initrd.fs
endif
$(BASE)/tools/mkhord.py 4096 arch/$(ARCH)/iso/boot/initrd.fs arch/$(ARCH)/iso/boot/initrd.img
rm arch/$(ARCH)/iso/boot/initrd.fs
mkisofs -J -r -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o $(BASE)/image.iso arch/$(ARCH)/iso/
 
clean:
-for task in $(RD_TASKS) ; do \
rm -f $(USPACEDIR)/dist/sbin/`basename $$task` ; \
-for file in $(RD_SRVS) ; do \
rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
done
-for file in $(RD_APPS) ; do \
rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
done
-rm -fr arch/$(ARCH)/iso
-rm -f $(BASE)/image.iso
/branches/tracing/Makefile
82,11 → 82,6
UARCH = mips32
IMAGE = ecoff
endif
ifeq ($(MACHINE),indy)
UARCH = mips32eb
IMAGE = ecoff
endif
endif
 
ifeq ($(PLATFORM),ppc32)
139,7 → 134,7
-$(MAKE) -C kernel distclean
-$(MAKE) -C uspace distclean
-$(MAKE) -C boot distclean
-rm Makefile.config
rm -f Makefile.config tools/*.pyc
 
clean:
-$(MAKE) -C kernel clean
147,6 → 142,6
-$(MAKE) -C boot clean
 
cscope:
-rm cscope.out
-find kernel boot uspace -regex '^.*\.[chsS]$$' -print >srclist
-cscope -bi srclist
find kernel boot uspace -regex '^.*\.[chsS]$$' -print > srclist
rm -f cscope.out
cscope -bi srclist