Index: uspace/srv/loader/Makefile
===================================================================
--- uspace/srv/loader/Makefile	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/Makefile	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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 $@
Index: uspace/srv/loader/arch/amd64/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/amd64/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/amd64/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/arch/amd64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/amd64/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/amd64/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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/ : {
+		*(*);
+	}
+
+}
Index: uspace/srv/loader/arch/amd64/amd64.s
===================================================================
--- uspace/srv/loader/arch/amd64/amd64.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/amd64/amd64.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/arch/arm32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/arm32/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/arm32/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/arch/arm32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/arm32/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/arm32/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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/ : {
+		*(*);
+	}
+
+}
Index: uspace/srv/loader/arch/arm32/arm32.s
===================================================================
--- uspace/srv/loader/arch/arm32/arm32.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/arm32/arm32.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/arch/ia32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/ia32/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/ia32/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/arch/ia32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia32/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/ia32/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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/ : {
+		*(*);
+	}
+
+}
Index: uspace/srv/loader/arch/ia32/ia32.s
===================================================================
--- uspace/srv/loader/arch/ia32/ia32.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/ia32/ia32.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/arch/ia64/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/ia64/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/ia64/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/arch/ia64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia64/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/ia64/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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/ : {
+		*(*);
+        }
+}
Index: uspace/srv/loader/arch/ia64/ia64.s
===================================================================
--- uspace/srv/loader/arch/ia64/ia64.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/ia64/ia64.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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 ;;
Index: uspace/srv/loader/arch/mips32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/mips32/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/mips32/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/arch/mips32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/mips32/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/mips32/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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/ : {
+		*(*);
+	}
+}
Index: uspace/srv/loader/arch/mips32/mips32.s
===================================================================
--- uspace/srv/loader/arch/mips32/mips32.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/mips32/mips32.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/arch/ppc32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/ppc32/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/ppc32/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/arch/ppc32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ppc32/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/ppc32/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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/ : {
+		*(*);
+	}
+
+}
Index: uspace/srv/loader/arch/ppc32/ppc32.s
===================================================================
--- uspace/srv/loader/arch/ppc32/ppc32.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/ppc32/ppc32.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/arch/sparc64/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/sparc64/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/sparc64/Makefile.inc	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/arch/sparc64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/sparc64/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/sparc64/_link.ld.in	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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/ : {
+		*(*);
+	}
+
+}
Index: uspace/srv/loader/arch/sparc64/sparc64.s
===================================================================
--- uspace/srv/loader/arch/sparc64/sparc64.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/arch/sparc64/sparc64.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
Index: uspace/srv/loader/elf_load.c
===================================================================
--- uspace/srv/loader/elf_load.c	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/elf_load.c	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -0,0 +1,451 @@
+/*
+ * 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);
+
+/** 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 = 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 = 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 = 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 = 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;
+}
+
+/** @}
+ */
Index: uspace/srv/loader/include/arch.h
===================================================================
--- uspace/srv/loader/include/arch.h	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/include/arch.h	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
+
+/**
+ * @}
+ */
Index: uspace/srv/loader/include/elf.h
===================================================================
--- uspace/srv/loader/include/elf.h	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/include/elf.h	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
+
+/** @}
+ */
Index: uspace/srv/loader/include/elf_load.h
===================================================================
--- uspace/srv/loader/include/elf_load.h	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/include/elf_load.h	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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
+
+/** @}
+ */
Index: uspace/srv/loader/interp.s
===================================================================
--- uspace/srv/loader/interp.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/interp.s	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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"
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
+++ uspace/srv/loader/main.c	(revision c98e6ee244a8e271a395a052069c23bca4f8b538)
@@ -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;
+}
+
+/** @}
+ */
