From 253bcee5d050ca2e0ba3c884c722edfb89ed03ce Mon Sep 17 00:00:00 2001
From: Armin Luntzer <armin.luntzer@univie.ac.at>
Date: Tue, 14 Mar 2017 13:44:43 +0100
Subject: [PATCH] * import Xentium kernel loader * split ELF stuff from modules
 * add swab.h * add more generic string functions

---
 arch/sparc/kernel/irq.c    |   1 +
 include/asm-generic/swab.h |  45 ++
 include/elf.h              | 567 +++++++++++++++++++++++++
 include/kernel/elf.h       |  42 ++
 include/kernel/module.h    |  13 +-
 include/kernel/string.h    |   5 +
 include/kernel/xentium.h   |  35 ++
 init/main.c                |  13 +
 kernel/Makefile            |   1 +
 kernel/module.c            | 678 ++++--------------------------
 kernel/xentium.c           | 304 ++++++++++++++
 lib/Makefile               |   1 +
 lib/elf.c                  | 831 +++++++++++++++++++++++++++++++++++++
 lib/string.c               |  51 +++
 14 files changed, 1972 insertions(+), 615 deletions(-)
 create mode 100644 include/asm-generic/swab.h
 create mode 100644 include/elf.h
 create mode 100644 include/kernel/xentium.h
 create mode 100644 kernel/xentium.c
 create mode 100644 lib/elf.c

diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index 8a2aadb..a372b8a 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -44,6 +44,7 @@
 #include <kernel/irq.h>
 #include <kernel/kmem.h>
 #include <kernel/printk.h>
+#include <kernel/kernel.h>
 
 #include <errno.h>
 #include <list.h>
diff --git a/include/asm-generic/swab.h b/include/asm-generic/swab.h
new file mode 100644
index 0000000..2d0f816
--- /dev/null
+++ b/include/asm-generic/swab.h
@@ -0,0 +1,45 @@
+/**
+ * @file    include/asm-generic/swab.h
+ *
+ * @copyright GPLv2
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _ASM_GENERIC_SWAB_H_
+#define _ASM_GENERIC_SWAB_H_
+
+#include <kernel/types.h>
+
+#define swab16(x) ((uint16_t)(					\
+	(((uint16_t)(x) & (uint16_t)0x00ffU) << 8) |		\
+	(((uint16_t)(x) & (uint16_t)0xff00U) >> 8)))
+
+#define swab32(x) ((uint32_t)(					\
+	(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) |	\
+	(((uint32_t)(x) & (uint32_t)0x0000ff00UL) <<  8) |	\
+	(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >>  8) |	\
+	(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
+
+
+#define swahw32(x) ((uint32_t)(					\
+	(((uint32_t)(x) & (uint32_t)0x0000ffffUL) << 16) |	\
+	(((uint32_t)(x) & (uint32_t)0xffff0000UL) >> 16)))
+
+#define swahb32(x) ((uint32_t)(					\
+	(((uint32_t)(x) & (uint32_t)0x00ff00ffUL) << 8) |	\
+	(((uint32_t)(x) & (uint32_t)0xff00ff00UL) >> 8)))
+
+#define swabb32(x) ((uint32_t)(					\
+	(((uint32_t)(x) & (uint32_t)0x0f0f0f0fUL) << 4) |	\
+	(((uint32_t)(x) & (uint32_t)0xf0f0f0f0UL) >> 4)))
+
+#endif /* _ASM_GENERIC_SWAB_H_ */
diff --git a/include/elf.h b/include/elf.h
new file mode 100644
index 0000000..883eeae
--- /dev/null
+++ b/include/elf.h
@@ -0,0 +1,567 @@
+#ifndef _KERNEL_ELF_H_
+#define _KERNEL_ELF_H_
+
+
+#include <kernel/types.h>
+
+/* some ELF constants&stuff ripped from include/uapi/linux/elf.h */
+
+
+/* 32-bit base types */
+typedef uint32_t Elf32_Addr;
+typedef uint16_t Elf32_Half;
+typedef uint32_t Elf32_Off;
+typedef  int32_t Elf32_Sword;
+typedef uint32_t Elf32_Word;
+
+/* 64-bit base types */
+typedef uint64_t Elf64_Addr;
+typedef uint16_t Elf64_Half;
+typedef  int16_t Elf64_SHalf;
+typedef uint64_t Elf64_Off;
+typedef  int32_t Elf64_Sword;
+typedef uint32_t Elf64_Word;
+typedef uint64_t Elf64_Xword;
+typedef  int64_t Elf64_Sxword;
+
+
+__extension__
+typedef struct elf32_dyn {
+	Elf32_Sword d_tag;		/* dynamic array tag */
+	union{
+		Elf32_Sword	d_val;
+		Elf32_Addr	d_ptr;	/* program virtual address */
+	};
+} Elf32_Dyn;
+
+__extension__
+typedef struct elf64_dyn {
+	Elf64_Sxword d_tag;		/* entry tag value */
+	union {
+		Elf64_Xword d_val;
+		Elf64_Addr d_ptr;
+	};
+} Elf64_Dyn;
+
+/* The following are used with relocations */
+#define ELF32_R_SYM(x)		((x) >> 8)
+#define ELF32_R_TYPE(x)		((x) & 0xff)
+
+#define ELF64_R_SYM(x)		((x) >> 32)
+#define ELF64_R_TYPE(x)		((x) & 0xffffffff)
+
+/* Dynamic Array Tags */
+#define DT_NULL		0		/* end of _DYNAMIC array */
+#define DT_NEEDED	1		/* str tbl offset of needed librart */
+#define DT_PLTRELSZ	2               /* size of relocation entries in PLT */
+#define DT_PLTGOT	3               /* address PLT/GOT */
+#define DT_HASH		4               /* address of symbol hash table */
+#define DT_STRTAB	5               /* address of string table */
+#define DT_SYMTAB	6               /* address of symbol table */
+#define DT_RELA		7               /* address of relocation table */
+#define DT_RELASZ	8               /* size of relocation table */
+#define DT_RELAENT	9               /* size of relocation entry */
+#define DT_STRSZ	10              /* size of string table */
+#define DT_SYMENT	11              /* size of symbol table entry */
+#define DT_INIT		12              /* address of initialization func. */
+#define DT_FINI		13              /* address of termination function */
+#define DT_SONAME	14              /* string tbl offset of shared obj */
+#define DT_RPATH 	15              /* str tbl offset of lib search path */
+#define DT_SYMBOLIC	16              /* start symbol search in shared obj */
+#define DT_REL	        17              /* address of reloc tbl with addends */
+#define DT_RELSZ	18              /* size of DT_REL relocation table */
+#define DT_RELENT	19              /* size of DT_REL relocation entry */
+#define DT_PLTREL	20              /* PLT referenced relocation entry */
+#define DT_DEBUG	21              /* used for debugging */
+#define DT_TEXTREL	22              /* allow reloc mod to unwritable seg */
+#define DT_JMPREL	23              /* addr of PLT's relocation entries */
+#define DT_ENCODING	32
+#define OLD_DT_LOOS	0x60000000
+#define DT_LOOS		0x6000000d
+#define DT_HIOS		0x6ffff000
+#define DT_VALRNGLO	0x6ffffd00
+#define DT_VALRNGHI	0x6ffffdff
+#define DT_ADDRRNGLO	0x6ffffe00
+#define DT_ADDRRNGHI	0x6ffffeff
+#define DT_VERSYM	0x6ffffff0
+#define DT_RELACOUNT	0x6ffffff9
+#define DT_RELCOUNT	0x6ffffffa
+#define DT_FLAGS_1	0x6ffffffb
+#define DT_VERDEF	0x6ffffffc
+#define	DT_VERDEFNUM	0x6ffffffd
+#define DT_VERNEED	0x6ffffffe
+#define	DT_VERNEEDNUM	0x6fffffff
+#define OLD_DT_HIOS     0x6fffffff
+#define DT_LOPROC	0x70000000
+#define DT_HIPROC	0x7fffffff
+
+
+/* Dynamic Flags - DT_FLAGS_1 .dynamic entry */
+#define DF_1_NOW       0x00000001
+#define DF_1_GLOBAL    0x00000002
+#define DF_1_GROUP     0x00000004
+#define DF_1_NODELETE  0x00000008
+#define DF_1_LOADFLTR  0x00000010
+#define DF_1_INITFIRST 0x00000020
+#define DF_1_NOOPEN    0x00000040
+#define DF_1_ORIGIN    0x00000080
+#define DF_1_DIRECT    0x00000100
+#define DF_1_TRANS     0x00000200
+#define DF_1_INTERPOSE 0x00000400
+#define DF_1_NODEFLIB  0x00000800
+#define DF_1_NODUMP    0x00001000
+#define DF_1_CONLFAT   0x00002000
+
+/* ld.so: number of low tags that are used saved internally (0 .. DT_NUM-1) */
+#define DT_NUM        (DT_JMPREL+1)
+
+/* This info is needed when parsing the symbol table */
+#define STB_LOCAL  0
+#define STB_GLOBAL 1
+#define STB_WEAK   2
+
+#define STT_NOTYPE  0
+#define STT_OBJECT  1
+#define STT_FUNC    2
+#define STT_SECTION 3
+#define STT_FILE    4
+#define STT_COMMON  5
+#define STT_TLS     6
+
+#define ELF_ST_BIND(x)		((x) >> 4)
+#define ELF_ST_TYPE(x)		(((unsigned int) x) & 0xf)
+#define ELF32_ST_BIND(x)	ELF_ST_BIND(x)
+#define ELF32_ST_TYPE(x)	ELF_ST_TYPE(x)
+#define ELF64_ST_BIND(x)	ELF_ST_BIND(x)
+#define ELF64_ST_TYPE(x)	ELF_ST_TYPE(x)
+
+
+
+typedef struct elf32_rel {
+	Elf32_Addr	r_offset;
+	Elf32_Word	r_info;
+} Elf32_Rel;
+
+typedef struct elf64_rel {
+	Elf64_Addr r_offset;	/* Location at which to apply the action */
+	Elf64_Xword r_info;	/* index and type of relocation */
+} Elf64_Rel;
+
+typedef struct elf32_rela{
+	Elf32_Addr	r_offset;
+	Elf32_Word	r_info;
+	Elf32_Sword	r_addend;
+} Elf32_Rela;
+
+typedef struct elf64_rela {
+	Elf64_Addr r_offset;	/* Location at which to apply the action */
+	Elf64_Xword r_info;	/* index and type of relocation */
+	Elf64_Sxword r_addend;	/* Constant addend used to compute value */
+} Elf64_Rela;
+
+
+/* relocs as needed */
+#define R_AMD64_NONE     0
+#define R_AMD64_RELATIVE 8
+
+
+
+
+typedef struct elf32_sym{
+	Elf32_Word	st_name;
+	Elf32_Addr	st_value;
+	Elf32_Word	st_size;
+	unsigned char	st_info;
+	unsigned char	st_other;
+	Elf32_Half	st_shndx;
+} Elf32_Sym;
+
+typedef struct elf64_sym {
+	Elf64_Word	st_name;	/* Symbol name, index in string tbl */
+	unsigned char	st_info;	/* Type and binding attributes */
+	unsigned char	st_other;	/* No defined meaning, 0 */
+	Elf64_Half	st_shndx;	/* Associated section index */
+	Elf64_Addr	st_value;	/* Value of the symbol */
+	Elf64_Xword	st_size;	/* Associated symbol size */
+} Elf64_Sym;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * Note Definitions
+ */
+typedef struct {
+    Elf32_Word namesz;
+    Elf32_Word descsz;
+    Elf32_Word type;
+} Elf32_Note;
+
+typedef struct {
+    Elf64_Half namesz;
+    Elf64_Half descsz;
+    Elf64_Half type;
+} Elf64_Note;
+
+
+
+
+
+/**
+ * e_ident[] identification indexes
+ */
+
+#define EI_MAG0		0	/* file ID */
+#define EI_MAG1		1	/* file ID */
+#define EI_MAG2		2	/* file ID */
+#define EI_MAG3		3	/* file ID */
+#define EI_CLASS	4	/* file class */
+#define EI_DATA		5	/* data encoding */
+#define EI_VERSION	6	/* ELF header version */
+#define EI_OSABI	7	/* OS/ABI ID */
+#define EI_ABIVERSION	8	/* ABI version */
+#define EI_PAD		9	/* start of pad bytes */
+#define EI_NIDENT	16	/* size of e_ident[] */
+
+/* e_ident[] magic numbers */
+#define ELFMAG0		0x7f		/* e_ident[EI_MAG0] */
+#define ELFMAG1		'E'		/* e_ident[EI_MAG1] */
+#define ELFMAG2		'L'		/* e_ident[EI_MAG2] */
+#define ELFMAG3		'F'		/* e_ident[EI_MAG3] */
+#define ELFMAG		"\177ELF"	/* magic */
+#define SELFMAG		4		/* size of magic */
+
+/* e_ident[] file classes */
+#define ELFCLASSNONE	0	/* invalid */
+#define ELFCLASS32	1	/* 32-bit objs */
+#define ELFCLASS64	2	/* 64-bit objs */
+#define ELFCLASSNUM	3	/* number of classes */
+
+/* e_ident[] data encoding */
+#define ELFDATANONE	0	/* invalid */
+#define ELFDATA2LSB	1	/* Little-Endian */
+#define ELFDATA2MSB	2	/* Big-Endian */
+#define ELFDATANUM	3	/* number of data encode defines */
+
+/* e_ident[] Operating System/ABI */
+#define ELFOSABI_SYSV		0	/* UNIX System V ABI */
+#define ELFOSABI_HPUX		1	/* HP-UX operating system */
+#define ELFOSABI_NETBSD		2	/* NetBSD */
+#define ELFOSABI_LINUX		3	/* GNU/Linux */
+#define ELFOSABI_HURD		4	/* GNU/Hurd */
+#define ELFOSABI_86OPEN		5	/* 86Open common IA32 ABI */
+#define ELFOSABI_SOLARIS	6	/* Solaris */
+#define ELFOSABI_MONTEREY	7	/* Monterey */
+#define ELFOSABI_IRIX		8	/* IRIX */
+#define ELFOSABI_FREEBSD	9	/* FreeBSD */
+#define ELFOSABI_TRU64		10	/* TRU64 UNIX */
+#define ELFOSABI_MODESTO	11	/* Novell Modesto */
+#define ELFOSABI_OPENBSD	12	/* OpenBSD */
+#define ELFOSABI_ARM		97	/* ARM */
+#define ELFOSABI_STANDALONE	255	/* Standalone (embedded) application */
+
+
+/* e_version */
+#define EV_NONE		0
+#define EV_CURRENT	1
+#define EV_NUM		2	/* number of versions */
+
+/* e_type */
+#define ET_NONE		0
+#define ET_REL		1	/* relocatable */
+#define ET_EXEC		2	/* executable */
+#define ET_DYN		3	/* shared object*/
+#define ET_CORE		4	/* core file */
+#define ET_NUM		5	/* number of types */
+#define ET_LOPROC	0xff00	/* reserved range for processor */
+#define ET_HIPROC	0xffff	/*  specific e_type */
+
+/* e_machine */
+#define EM_NONE		0
+#define EM_M32		1	/* AT&T WE 32100 */
+#define EM_SPARC	2	/* SPARC */
+#define EM_386		3	/* Intel 80386 */
+#define EM_68K		4	/* Motorola 68000 */
+#define EM_88K		5	/* Motorola 88000 */
+#define EM_486		6	/* Intel 80486 - unused? */
+#define EM_860		7	/* Intel 80860 */
+#define EM_MIPS		8	/* MIPS R3000 Big-Endian only */
+#define EM_MIPS_RS4_BE	10	/* MIPS R4000 Big-Endian */
+#define EM_SPARC64	11	/* SPARC v9 64-bit unofficial */
+#define EM_PARISC	15	/* HPPA */
+#define EM_SPARC32PLUS	18	/* Enhanced instruction set SPARC */
+#define EM_PPC		20	/* PowerPC */
+#define EM_ARM		40	/* ARM AArch32 */
+#define EM_ALPHA	41	/* DEC ALPHA */
+#define EM_SH		42	/* Hitachi/Renesas Super-H */
+#define EM_SPARCV9	43	/* SPARC version 9 */
+#define EM_IA_64	50	/* Intel IA-64 Processor */
+#define EM_AMD64	62	/* AMD64 architecture */
+#define EM_VAX		75	/* DEC VAX */
+#define EM_AARCH64	183	/* ARM AArch64 */
+
+
+/* ELF32 Header */
+typedef struct elf32_hdr{
+	unsigned char	e_ident[EI_NIDENT];	/* ELF identifier */
+	Elf32_Half	e_type;			/* object file type */
+	Elf32_Half	e_machine;		/* machine type */
+	Elf32_Word	e_version;		/* object file version */
+	Elf32_Addr	e_entry;		/* entry point */
+	Elf32_Off	e_phoff;		/* program header offset */
+	Elf32_Off	e_shoff;		/* section header offset */
+	Elf32_Word	e_flags;		/* processor-specific flags */
+	Elf32_Half	e_ehsize;		/* ELF header size */
+	Elf32_Half	e_phentsize;		/* program header entry size */
+	Elf32_Half	e_phnum;		/* number of program headers */
+	Elf32_Half	e_shentsize;		/* section header entry size */
+	Elf32_Half	e_shnum;		/* number of section headers */
+	Elf32_Half	e_shstrndx;		/* string table index */
+} Elf32_Ehdr;
+
+/* ELF64 Header */
+typedef struct elf64_hdr{
+	unsigned char	e_ident[EI_NIDENT];	/* ELF identifier */
+	Elf64_Half	e_type;			/* object file type */
+	Elf64_Half	e_machine;		/* machine type */
+	Elf64_Word	e_version;		/* object file version */
+	Elf64_Addr	e_entry;		/* entry point */
+	Elf64_Off	e_phoff;		/* program header offset */
+	Elf64_Off	e_shoff;		/* section header offset */
+	Elf64_Word	e_flags;		/* processor-specific flags */
+	Elf64_Half	e_ehsize;		/* ELF header size */
+	Elf64_Half	e_phentsize;		/* program header entry size */
+	Elf64_Half	e_phnum;		/* number of program headers */
+	Elf64_Half	e_shentsize;		/* section header entry size */
+	Elf64_Half	e_shnum;		/* number of section headers */
+	Elf64_Half	e_shstrndx;		/* string table index */
+} Elf64_Ehdr;
+
+
+/* ELF32 Program Header */
+typedef struct elf32_phdr{
+	Elf32_Word	p_type;			/* entry type */
+	Elf32_Off	p_flags;		/* flags */
+	Elf32_Addr	p_offset;		/* file offset */
+	Elf32_Addr	p_vaddr;		/* virtual address */
+	Elf32_Word	p_paddr;		/* physical address */
+	Elf32_Word	p_filesz;		/* size in file */
+	Elf32_Word	p_memsz;		/* size in memory */
+	Elf32_Word	p_align;		/* alignment, file & memory */
+} Elf32_Phdr;
+
+/* ELF64 Program Header */
+typedef struct elf64_phdr {
+	Elf64_Word	p_type;			/* entry type */
+	Elf64_Word	p_flags;		/* flags */
+	Elf64_Off	p_offset;		/* file offset */
+	Elf64_Addr	p_vaddr;		/* virtual address */
+	Elf64_Addr	p_paddr;		/* physical address */
+	Elf64_Xword	p_filesz;		/* size in file */
+	Elf64_Xword	p_memsz;		/* size in memory */
+	Elf64_Xword	p_align;		/* alignment, file & memory */
+} Elf64_Phdr;
+
+
+/* Program entry types */
+#define PT_NULL		0		/* unused */
+#define PT_LOAD		1		/* loadable segment */
+#define PT_DYNAMIC	2		/* dynamic linking section */
+#define PT_INTERP	3		/* the RTLD */
+#define PT_NOTE		4		/* auxiliary information */
+#define PT_SHLIB	5		/* reserved - purpose undefined */
+#define PT_PHDR		6		/* program header */
+#define PT_TLS		7		/* thread local storage */
+#define PT_LOOS		0x60000000	/* reserved range for OS */
+#define PT_HIOS		0x6fffffff	/*  specific segment types */
+#define PT_LOPROC	0x70000000	/* reserved range for processor */
+#define PT_HIPROC	0x7fffffff	/*  specific segment types */
+
+
+/* ELF32 Section Header */
+typedef struct elf32_shdr {
+	Elf32_Word	sh_name;		/* section name index */
+	Elf32_Word	sh_type;		/* section type */
+	Elf32_Word	sh_flags;		/* section flags */
+	Elf32_Addr	sh_addr;		/* (virtual) address */
+	Elf32_Off	sh_offset;		/* file offset */
+	Elf32_Word	sh_size;		/* section size */
+	Elf32_Word	sh_link;		/* link to other section header */
+	Elf32_Word	sh_info;		/* misc info */
+	Elf32_Word	sh_addralign;		/* memory address alignment */
+	Elf32_Word	sh_entsize;		/* section entry size */
+} Elf32_Shdr;
+
+/* ELF64 Section Header */
+typedef struct elf64_shdr {
+	Elf64_Word	sh_name;		/* section name */
+	Elf64_Word	sh_type;		/* section type */
+	Elf64_Xword	sh_flags;		/* section flags */
+	Elf64_Addr	sh_addr;		/* (virtual) address */
+	Elf64_Off	sh_offset;		/* file offset */
+	Elf64_Xword	sh_size;		/* section size */
+	Elf64_Word	sh_link;		/* link to other section header */
+	Elf64_Word	sh_info;		/* misc info */
+	Elf64_Xword	sh_addralign;		/* memory address alignment */
+	Elf64_Xword	sh_entsize;		/* section entry size */
+} Elf64_Shdr;
+
+
+/* Special Section Indexes */
+#define SHN_UNDEF     0             /* undefined */
+#define SHN_LORESERVE 0xff00        /* lower bounds of reserved indexes */
+#define SHN_LOPROC    0xff00        /* reserved range for processor */
+#define SHN_HIPROC    0xff1f        /*   specific section indexes */
+#define SHN_ABS       0xfff1        /* absolute value */
+#define SHN_COMMON    0xfff2        /* common symbol */
+#define SHN_HIRESERVE 0xffff        /* upper bounds of reserved indexes */
+
+/* sh_type */
+#define SHT_NULL	0		/* inactive */
+#define SHT_PROGBITS	1		/* program defined information */
+#define SHT_SYMTAB	2		/* symbol table section */
+#define SHT_STRTAB	3		/* string table section */
+#define SHT_RELA	4		/* relocation section with addends*/
+#define SHT_HASH	5		/* symbol hash table section */
+#define SHT_DYNAMIC	6		/* dynamic section */
+#define SHT_NOTE	7		/* note section */
+#define SHT_NOBITS	8		/* no space section */
+#define SHT_REL		9		/* relation section without addends */
+#define SHT_SHLIB	10		/* reserved */
+#define SHT_DYNSYM	11		/* dynamic symbol table section */
+#define SHT_NUM		12		/* number of section types */
+#define SHT_LOPROC	0x70000000	/* reserved range for processor */
+#define SHT_HIPROC	0x7fffffff	/*  specific section header types */
+#define SHT_LOUSER	0x80000000	/* reserved range for application */
+#define SHT_HIUSER	0xffffffff	/*  specific indexes */
+
+/* Section names */
+#define ELF_BSS         ".bss"        /* uninitialized data */
+#define ELF_DATA        ".data"       /* initialized data */
+#define ELF_DEBUG       ".debug"      /* debug */
+#define ELF_DYNAMIC     ".dynamic"    /* dynamic linking information */
+#define ELF_DYNSTR      ".dynstr"     /* dynamic string table */
+#define ELF_DYNSYM      ".dynsym"     /* dynamic symbol table */
+#define ELF_FINI        ".fini"       /* termination code */
+#define ELF_GOT         ".got"        /* global offset table */
+#define ELF_HASH        ".hash"       /* symbol hash table */
+#define ELF_INIT        ".init"       /* initialization code */
+#define ELF_REL_DATA    ".rel.data"   /* relocation data */
+#define ELF_REL_FINI    ".rel.fini"   /* relocation termination code */
+#define ELF_REL_INIT    ".rel.init"   /* relocation initialization code */
+#define ELF_REL_DYN     ".rel.dyn"    /* relocation dynamic link info */
+#define ELF_REL_RODATA  ".rel.rodata" /* relocation read-only data */
+#define ELF_REL_TEXT    ".rel.text"   /* relocation code */
+#define ELF_RODATA      ".rodata"     /* read-only data */
+#define ELF_SHSTRTAB    ".shstrtab"   /* section header string table */
+#define ELF_STRTAB      ".strtab"     /* string table */
+#define ELF_SYMTAB      ".symtab"     /* symbol table */
+#define ELF_TEXT        ".text"       /* code */
+
+
+/* Section Attribute Flags - sh_flags */
+#define SHF_WRITE        0x1           /* Writable */
+#define SHF_ALLOC        0x2           /* occupies memory */
+#define SHF_EXECINSTR    0x4           /* executable */
+#define SHF_TLS          0x400         /* thread local storage */
+#define SHF_MASKPROC     0xf0000000    /* reserved bits for processor
+                                        *  specific section attributes */
+
+
+/* Sparc ELF relocation types */
+#define	R_SPARC_NONE		0
+#define	R_SPARC_8		1
+#define	R_SPARC_16		2
+#define	R_SPARC_32		3
+#define	R_SPARC_DISP8		4
+#define	R_SPARC_DISP16		5
+#define	R_SPARC_DISP32		6
+#define	R_SPARC_WDISP30		7
+#define	R_SPARC_WDISP22		8
+#define	R_SPARC_HI22		9
+#define	R_SPARC_22		10
+#define	R_SPARC_13		11
+#define	R_SPARC_LO10		12
+#define	R_SPARC_GOT10		13
+#define	R_SPARC_GOT13		14
+#define	R_SPARC_GOT22		15
+#define	R_SPARC_PC10		16
+#define	R_SPARC_PC22		17
+#define	R_SPARC_WPLT30		18
+#define	R_SPARC_COPY		19
+#define	R_SPARC_GLOB_DAT	20
+#define	R_SPARC_JMP_SLOT	21
+#define	R_SPARC_RELATIVE	22
+#define	R_SPARC_UA32		23
+#define R_SPARC_PLT32		24
+#define R_SPARC_HIPLT22		25
+#define R_SPARC_LOPLT10		26
+#define R_SPARC_PCPLT32		27
+#define R_SPARC_PCPLT22		28
+#define R_SPARC_PCPLT10		29
+#define R_SPARC_10		30
+#define R_SPARC_11		31
+#define R_SPARC_64		32
+#define R_SPARC_OLO10		33
+#define R_SPARC_WDISP16		40
+#define R_SPARC_WDISP19		41
+#define R_SPARC_7		43
+#define R_SPARC_5		44
+#define R_SPARC_6		45
+
+
+
+
+/* end of ELF stuff */
+
+
+
+/* begin configurable section */
+
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Phdr Elf_Phdr;
+typedef Elf32_Dyn  Elf_Dyn;
+typedef Elf32_Rel  Elf_Rel;
+typedef Elf32_Rela Elf_Rela;
+typedef Elf32_Off  Elf_Off;
+typedef Elf32_Addr Elf_Addr;
+typedef Elf32_Sym  Elf_Sym;
+
+#define ELF_R_SYM(x)    ELF32_R_SYM(x)
+#define ELF_R_TYPE(x)   ELF32_R_TYPE(x)
+
+
+
+/**
+ * NOTE: no free configuration, limited to 32bit ELF, SPARCv8, big endian,
+ * because I am lazy :)
+ */
+#if 1
+#define ELF_ENDIAN	ELFDATA2MSB
+#define EM_MACHINE	EM_SPARC
+#else
+#define ELF_ENDIAN	ELFDATA2LSB
+#define EM_MACHINE	EM_AMD64
+#endif
+
+
+#define elf_check_arch(x) ((x)->e_machine == EM_MACHINE)
+#define elf_check_endian(x) ((x)->e_ident[EI_DATA] == ELF_ENDIAN)
+
+
+/* implemented in arch code */
+int elf_header_check(Elf_Ehdr *ehdr);
+
+
+#endif /* _KERNEL_ELF_H_ */
diff --git a/include/kernel/elf.h b/include/kernel/elf.h
index 883eeae..4797c13 100644
--- a/include/kernel/elf.h
+++ b/include/kernel/elf.h
@@ -564,4 +564,46 @@ typedef Elf32_Sym  Elf_Sym;
 int elf_header_check(Elf_Ehdr *ehdr);
 
 
+
+Elf_Shdr *elf_get_shdr(const Elf_Ehdr *ehdr);
+size_t elf_find_shdr_alloc_idx(const Elf_Ehdr *ehdr, const size_t offset);
+
+Elf_Shdr *elf_get_sec_by_idx(const Elf_Ehdr *ehdr, const size_t idx);
+Elf_Shdr *elf_get_sec_shstrtab(const Elf_Ehdr *ehdr);
+char *elf_get_shstrtab_str(const Elf_Ehdr *ehdr, size_t idx);
+
+Elf_Shdr *elf_find_sec(const Elf_Ehdr *ehdr, const char *name);
+
+char *elf_get_strtab(const Elf_Ehdr *ehdr);
+char *elf_get_strtab_str(const Elf_Ehdr *ehdr, size_t idx);
+
+char *elf_get_dynstr(const Elf_Ehdr *ehdr);
+char *elf_get_dynstr_str(const Elf_Ehdr *ehdr, size_t idx);
+
+char *elf_get_symbol_str(const Elf_Ehdr *ehdr, size_t idx);
+
+unsigned long elf_get_symbol_value(const Elf_Ehdr *ehdr,
+				   const char *name, unsigned long *value);
+
+unsigned long elf_get_symbol_type(const Elf_Ehdr *ehdr, const char *name);
+
+size_t elf_find_sec_idx_by_type(const Elf_Ehdr *ehdr,
+				const uint32_t sh_type,
+				const size_t offset);
+
+size_t elf_get_num_alloc_sections(const Elf_Ehdr *ehdr);
+
+size_t elf_get_num_dyn_entries(const Elf_Ehdr *ehdr);
+
+Elf_Dyn *elf_find_dyn(const Elf_Ehdr *ehdr,
+			 const unsigned long d_tag,
+			 const unsigned int offset);
+
+void elf_hdr_endianess_swap(Elf_Ehdr *ehdr);
+
+void elf_dump_strtab(const Elf_Ehdr *ehdr);
+void elf_dump_symtab(const Elf_Ehdr *ehdr);
+void elf_dump_sections(const Elf_Ehdr *ehdr);
+
+
 #endif /* _KERNEL_ELF_H_ */
diff --git a/include/kernel/module.h b/include/kernel/module.h
index 281745f..f651c3d 100644
--- a/include/kernel/module.h
+++ b/include/kernel/module.h
@@ -36,17 +36,8 @@ struct elf_module {
 	unsigned int align;
 
 	Elf_Ehdr *ehdr;		/* coincides with start of module image */
-	Elf_Shdr *shdr;
-	Elf_Dyn  *dyn;
-
+	
 	size_t size;
-	size_t dyn_size;
-	size_t sh_size;
-	size_t str_size;
-
-	char  *dyn_str;		/* dynamic symbols string tab */
-	char  *sh_str;		/* section header string tab */
-	char  *str;		/* stringtab */
 
 	struct module_section *sec;
 	size_t num_sec;
@@ -58,11 +49,11 @@ struct elf_module {
 int apply_relocate_add(struct elf_module *m, Elf_Rela *rel, Elf_Addr sym);
 
 
-
 struct module_section *find_mod_sec(const struct elf_module *m,
 				    const char *name);
 
 int module_load(struct elf_module *m, void *p);
+
 void modules_list_loaded(void);
 
 #endif /* _KERNEL_MODULE_H_ */
diff --git a/include/kernel/string.h b/include/kernel/string.h
index 37e7490..c006b78 100644
--- a/include/kernel/string.h
+++ b/include/kernel/string.h
@@ -5,6 +5,9 @@
 #ifndef _KERNEL_STRING_H_
 #define _KERNEL_STRING_H_
 
+#include <kernel/types.h>
+
+
 int sprintf(char *str, const char *format, ...);
 int strcmp(const char *s1, const char *s2);
 char *strpbrk(const char *s, const char *accept);
@@ -12,6 +15,8 @@ char *strsep(char **stringp, const char *delim);
 size_t strlen(const char *s);
 
 void *memcpy(void *dest, const void *src, size_t n);
+char *strcpy(char *dest, const char *src);
+void bzero(void *s, size_t n);
 
 int isspace(int c);
 int atoi(const char *nptr);
diff --git a/include/kernel/xentium.h b/include/kernel/xentium.h
new file mode 100644
index 0000000..b28eee9
--- /dev/null
+++ b/include/kernel/xentium.h
@@ -0,0 +1,35 @@
+#ifndef _KERNEL_XENTIUM_H_
+#define _KERNEL_XENTIUM_H_
+
+#include <kernel/init.h>
+#include <kernel/elf.h>
+
+struct xen_module_section {
+	char *name;
+	unsigned long addr;
+	size_t size;
+};
+
+struct xen_kernel {
+
+	unsigned long ep;
+
+
+	int refcnt;
+
+	unsigned int align;
+
+	Elf_Ehdr *ehdr;		/* coincides with start of module image */
+
+	size_t size;
+
+
+	struct xen_module_section *sec;
+	size_t num_sec;
+};
+
+
+
+int xentium_kernel_load(struct xen_kernel *x, void *p);
+
+#endif /* _KERNEL_XENTIUM_H_ */
diff --git a/init/main.c b/init/main.c
index d4914a3..5a31e98 100644
--- a/init/main.c
+++ b/init/main.c
@@ -16,6 +16,8 @@
 #include <kernel/sbrk.h>
 #include <kernel/sysctl.h>
 
+#include <kernel/xentium.h>
+
 #define MSG "MAIN: "
 
 void module_image_load_embedded(void);
@@ -38,6 +40,7 @@ int main(void)
 {
 	void *addr;
 	struct elf_module m;
+	struct xen_kernel x;
 
 	kernel_init();
 
@@ -62,14 +65,24 @@ int main(void)
 	/* addr = module_lookup_symbol_embedded("somefunction"); */
 	/* XXX the image is not necessary aligned properly, so we can't access
 	 * it directly, until we have a MNA trap */
+#if 1
+	addr = module_read_embedded("testkernel.ko");
+
+	printk(MSG "testkernel module address is %p\n", addr);
 
+	if (addr)
+		xentium_kernel_load(&x, addr);
+#endif
 
+#if 0
 	addr = module_read_embedded("noc_dma.ko");
 
 	pr_debug(MSG "noc_dma module address is %p\n", addr);
 
 	if (addr)
 		module_load(&m, addr);
+
+#endif
 #if 0
 	modules_list_loaded();
 #endif
diff --git a/kernel/Makefile b/kernel/Makefile
index b163e87..ff7d2e7 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -5,3 +5,4 @@ obj-y += bitmap.o
 obj-y += module.o
 obj-$(CONFIG_NOC_DMA) += noc_dma.o
 obj-y += irq.o
+obj-y += xentium.o
diff --git a/kernel/module.c b/kernel/module.c
index bdab605..d205671 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -9,11 +9,8 @@
  *	4. profit
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
 #include <kernel/printk.h>
+#include <kernel/string.h>
 #include <kernel/err.h>
 #include <kernel/module.h>
 #include <kernel/ksym.h>
@@ -35,207 +32,12 @@ static struct {
 } _kmod;
 
 
-
 /**
- * @brief find section headers marked ALLOC by index
- *
- * @param offset a offset into the table (to locate multiple identical types)
- *
- * @return section index or 0 if not found
- */
-
-static unsigned int find_shdr_alloc(const struct elf_module *m,
-				    const unsigned int offset)
-{
-	size_t i;
-
-
-	for (i = offset; i < m->ehdr->e_shnum; i++) {
-		if ((m->shdr[i].sh_flags & SHF_ALLOC))
-			return i;
-	}
-
-	return 0;
-}
-
-
-
-/**
- * @brief get number of sections marked ALLOC with size > 0
- *
- * @return number of ALLOC sections
- */
-
-static unsigned int get_num_alloc_sections(const struct elf_module *m)
-{
-	size_t i;
-	size_t cnt = 0;
-
-
-	for (i = 0; i < m->ehdr->e_shnum; i++) {
-		if ((m->shdr[i].sh_flags & SHF_ALLOC))
-			if (m->shdr[i].sh_size)
-				cnt++;
-	}
-
-	return cnt;
-}
-
-
-/**
- * @brief get the number of entries in a dynamic section
- *
- * @return the number of entries in a dynamic section
- */
-
-static unsigned int get_num_dyn_entries(const struct elf_module *m)
-{
-	return m->dyn_size / sizeof(Elf_Dyn);
-}
-
-
-/**
- * @brief find a dynamic entry by tag
- *
- * @param offset a offset into the table (to locate multiple identical types)
- *
- * @return NULL if entry not found, pointer to entry otherwise
- *
- */
-__attribute__((unused))
-static Elf_Dyn *find_dyn(const struct elf_module *m,
-			 const typeof(m->dyn->d_tag) d_tag,
-			 const unsigned int offset)
-{
-	size_t i;
-
-
-	for (i = offset; i < get_num_dyn_entries(m); i++)
-		if (d_tag == m->dyn[i].d_tag)
-			return &m->dyn[i];
-
-	return NULL;
-}
-
-
-/**
- * @brief return a section header by index
- *
- * @return NULL if entry not found, pointer to entry otherwise
- *
- */
-
-static Elf_Shdr *get_sec(const struct elf_module *m, unsigned int idx)
-{
-	if (idx < m->ehdr->e_shnum)
-		return &m->shdr[idx];
-
-	return NULL;
-}
-
-
-/**
- * @brief find find an elf section by type
- *
- * @param offset a offset into the table (to locate multiple identical types)
- *
- * @return section index or 0 if not found
- *
- */
-
-static unsigned int find_sec_type(const struct elf_module *m,
-				  const typeof(m->shdr->sh_type) sh_type,
-				  const unsigned int offset)
-{
-	size_t i;
-
-
-	for (i = offset; i < m->ehdr->e_shnum; i++) {
-		if (sh_type == m->shdr[i].sh_type)
-			return i;
-	}
-
-	return 0;
-}
-
-
-/**
- * @brief find an elf section by name
- *
- * @return section index or 0 if not found
- */
-
-static unsigned int find_sec(const struct elf_module *m, const char *name)
-{
-	size_t i;
-
-
-	for (i = 1; i < m->ehdr->e_shnum; i++) {
-		if (!strcmp(m->sh_str + m->shdr[i].sh_name, name))
-			return i;
-	}
-
-	return 0;
-}
-
-
-/**
- * @brief get an entry in the .shstrtab
- *
- * @return pointer to the start of the string or NULL if not found
- */
-
-static char *get_shstrtab_str(const struct elf_module *m, unsigned int idx)
-{
-	if (idx < m->sh_size)
-		return (m->sh_str + m->shdr[idx].sh_name);
-
-	return NULL;
-}
-
-
-/**
- * @brief get an entry in the .strtab
+ * @brief find module section by name
  *
- * @return pointer to the start of the string or NULL if not found
- */
-
-__attribute__((unused))
-static char *get_strtab_str(const struct elf_module *m, unsigned int idx)
-{
-	if (idx < m->str_size)
-		return (m->str + idx);
-
-	return NULL;
-}
-
-
-/**
- * @brief get the name of a symbol in .symtab with a given index
+ * @param m a struct elf_module
  *
- * @return pointer to the start of the string or NULL if not found
- */
-
-static char *get_symbol_str(const struct elf_module *m, unsigned int idx)
-{
-	Elf_Shdr *symtab;
-	Elf_Sym *symbols;
-
-
-	symtab = &m->shdr[find_sec(m, ".symtab")];
-
-	//symbols = (Elf_Sym *) (m->pa + symtab->sh_offset);
-	symbols = (Elf_Sym *) ((unsigned long) m->ehdr + symtab->sh_offset);
-
-	if (idx < symtab->sh_size / symtab->sh_entsize)
-		return m->str + symbols[idx].st_name;
-
-	return NULL;
-}
-
-
-/**
- * @brief find module section by name
+ * @param name the name of the module section
  *
  * @return module section structure pointer or NULL if not found
  */
@@ -247,6 +49,9 @@ struct module_section *find_mod_sec(const struct elf_module *m,
 	size_t i;
 
 
+	if (!name)
+		return NULL;
+
 	for (i = 0; i < m->num_sec; i++) {
 		if (!strcmp(m->sec[i].name, name))
 			return &m->sec[i];
@@ -257,364 +62,11 @@ struct module_section *find_mod_sec(const struct elf_module *m,
 }
 
 
-/**
- * @brief dump the name of all elf sections
- */
-
-void dump_sections(const struct elf_module *m)
-{
-	size_t i;
-
-
-	printk(MOD "SECTIONS:\n"
-	        MOD "============================\n"
-	        MOD "\t[NUM]\t[NAME]\t\t\t[TYPE]\t\t[SIZE]\t[ENTSZ]\t[FLAGS]\n"
-		);
-
-
-	for (i = 0; i < m->ehdr->e_shnum; i++) {
-
-		printk(MOD "\t%d\t%-20s", i, m->sh_str + m->shdr[i].sh_name);
-
-		switch (m->shdr[i].sh_type) {
-		case SHT_NULL:
-			printk("%-10s", "\tNULL"); break;
-		case SHT_PROGBITS:
-			printk("%-10s", "\tPROGBITS");
-			break;
-		case SHT_SYMTAB:
-			printk("%-10s", "\tSYMTAB"); break;
-		case SHT_STRTAB:
-			printk("%-10s", "\tSTRTAB"); break;
-		case SHT_RELA  :
-			printk("%-10s", "\tRELA"); break;
-		case SHT_HASH  :
-			printk("%-10s", "\tHASH"); break;
-		case SHT_DYNAMIC:
-			printk("%-10s", "\tDYNAMIC"); break;
-		case SHT_NOTE  :
-			printk("%-10s", "\tNOTE"); break;
-		case SHT_NOBITS:
-			printk("%-10s", "\tNOBITS"); break;
-		case SHT_REL   :
-			printk("%-10s", "\tREL"); break;
-		case SHT_SHLIB :
-			printk("%-10s", "\tSHLIB"); break;
-		case SHT_DYNSYM:
-			printk("%-10s", "\tDYNSYM"); break;
-		case SHT_NUM   :
-			printk("%-10s", "\tNUM"); break;
-		default:
-			printk("%-10s", "\tOTHER"); break;
-		}
-
-		printk("\t%ld\t%ld\t", m->shdr[i].sh_size, m->shdr[i].sh_entsize);
-
-		if (m->shdr[i].sh_flags & SHF_WRITE)
-			printk("WRITE ");
-		if (m->shdr[i].sh_flags & SHF_ALLOC)
-			printk("ALLOC ");
-		if (m->shdr[i].sh_flags & SHF_EXECINSTR)
-			printk("EXECINSTR ");
-		if (m->shdr[i].sh_flags & SHF_TLS)
-			printk("TLS ");
-		if (m->shdr[i].sh_flags & SHF_MASKPROC)
-			printk("MASKPROC ");
-
-		printk(MOD "\n");
-
-	}
-
-}
-
-
-/**
- * @brief get the type of a symbol
- *
- * @return 1 if symbol has been found, 0 otherwise
- */
-
-static unsigned long get_symbol_type(const struct elf_module *m,
-				     const char *name)
-
-{
-	unsigned int i;
-	unsigned int idx;
-	size_t sym_cnt;
-
-	Elf_Shdr *symtab;
-	Elf_Sym *symbols;
-
-
-	idx = find_sec(m, ".symtab");
-
-	if (!idx) {
-		pr_debug(MOD "WARN: no .symtab section found\n");
-		return -1;
-	}
-
-	symtab = &m->shdr[idx];
-
-	if (symtab->sh_entsize != sizeof(Elf_Sym)) {
-		pr_debug("Error %d != %ld\n", sizeof(Elf_Sym), symtab->sh_entsize);
-		return -1;
-	}
-
-	symbols = (Elf_Sym *) ((unsigned long) m->ehdr + symtab->sh_offset);
-
-	sym_cnt = symtab->sh_size / symtab->sh_entsize;
-
-	for (i = 0; i < sym_cnt; i++) {
-		if(!strcmp(get_symbol_str(m, i), name)) {
-			return ELF_ST_TYPE(symbols[i].st_info);
-		}
-	}
-
-	return 0;
-}
-
-
-
-/**
- * @brief get the value of a symbol
- *
- * @return 1 if symbol has been found, 0 otherwise
- */
-
-static unsigned long get_symbol_value(const struct elf_module *m,
-				      const char *name, unsigned long *value)
-
-{
-	unsigned int i;
-	unsigned int idx;
-	size_t sym_cnt;
-
-	Elf_Shdr *symtab;
-	Elf_Sym *symbols;
-
-
-	idx = find_sec(m, ".symtab");
-
-	if (!idx) {
-		pr_debug(MOD "WARN: no .symtab section found\n");
-		return -1;
-	}
-
-	symtab = &m->shdr[idx];
-
-	if (symtab->sh_entsize != sizeof(Elf_Sym)) {
-		pr_debug(MOD "Error %d != %ld\n", sizeof(Elf_Sym), symtab->sh_entsize);
-		return -1;
-	}
-
-	symbols = (Elf_Sym *) ((unsigned long) m->ehdr + symtab->sh_offset);
-
-	sym_cnt = symtab->sh_size / symtab->sh_entsize;
-
-	for (i = 0; i < sym_cnt; i++) {
-		if(!strcmp(get_symbol_str(m, i), name)) {
-			(*value) =  symbols[i].st_value;
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-/**
- * @brief dump the contents of .symtab
- */
-
-static int dump_symtab(struct elf_module *m)
-{
-	Elf_Shdr *symtab;
-	Elf_Sym *symbols;
-
-	size_t sym_cnt;
-	unsigned int idx;
-	unsigned int i;
-
-
-
-	idx = find_sec(m, ".symtab");
-
-	if (!idx) {
-		printk(MOD "WARN: no .symtab section found\n");
-		return -1;
-	}
-
-	symtab = &m->shdr[idx];
-
-	if (symtab->sh_entsize != sizeof(Elf_Sym)) {
-		printk(MOD "Error %d != %ld\n", sizeof(Elf_Sym), symtab->sh_entsize);
-		return -1;
-	}
-
-	symbols = (Elf_Sym *) ((unsigned long) m->ehdr + symtab->sh_offset);
-
-	sym_cnt = symtab->sh_size / symtab->sh_entsize;
-
-
-	printk(MOD "\n"
-		MOD ".symtab contains %d entries\n"
-	        MOD "============================\n"
-	        MOD "\t[NUM]\t[VALUE]\t\t\t[SIZE]\t[TYPE]\t[NAME]\n", sym_cnt);
-
-
-	for (i = 0; i < sym_cnt; i++) {
-
-		printk(MOD "\t%d\t%016lx\t%4ld",
-		       i,
-		       symbols[i].st_value,
-		       symbols[i].st_size);
-
-		switch (ELF_ST_TYPE(symbols[i].st_info)) {
-		case STT_NOTYPE  :
-			printk("\tNOTYPE "); break;
-		case STT_OBJECT  :
-			printk("\tOBJECT "); break;
-		case STT_FUNC    :
-			printk("\tFUNC   "); break;
-		case STT_SECTION :
-			printk("\tSECTION"); break;
-		case STT_FILE    :
-			printk("\tFILE   "); break;
-		case STT_COMMON  :
-			printk("\tCOMMON "); break;
-		case STT_TLS     :
-			printk("\tTLS    "); break;
-		default:
-			printk("\tUNKNOWN"); break;
-		}
-
-		printk("\t%-10s\n", get_symbol_str(m, i));
-
-	}
-
-	return 0;
-}
-
-
-
-/**
- * @brief dump the contents of strtab
- */
-
-__attribute__((unused))
-static void dump_strtab(const struct elf_module *m)
-{
-	size_t i = 0;
-
-
-	if (!m->str)
-		return;
-
-
-	printk(MOD "\n.strtab:\n"
-	       "============================\n"
-	       "\t[OFF]\t[STR]\n");
-
-	while(i < m->sh_size) {
-		printk(MOD "\t[%d]\t%s\n", i, m->str + i);
-		i += strlen(m->str + i) + 1;
-	}
-
-	printk(MOD "\n\n");
-}
-
-
-/**
- * @brief locate and set the ".shstrtab" section
- *
- * @return 0 if section header string table was not found, 1 otherwise
- *
- */
-
-static int set_shstrtab(struct elf_module *m)
-{
-	size_t i;
-
-	for (i = 0; i < m->ehdr->e_shnum; i++) {
-
-		if (m->shdr[i].sh_type != SHT_STRTAB)
-			continue;
-
-		/* section name index is not within table boundary, skip */
-		if (m->shdr[i].sh_size < m->shdr[i].sh_name)
-			continue;
-
-		m->sh_str  = (((char *) m->ehdr) + m->shdr[i].sh_offset);
-		m->sh_size = m->shdr[i].sh_size;
-
-		/* it's a string section and the size is ok,
-		 * now make sure it is the right one */
-		if (!strcmp(m->sh_str + m->shdr[i].sh_name, ".shstrtab"))
-			return 1;
-	}
-
-	m->sh_str = NULL;
-	m->sh_size = 0;
-
-	return 0;
-}
-
-/**
- * @brief locate and set the ".dynstr" section
- *
- * @return 0 if section header string table was not found, 1 otherwise
- *
- */
-
-static int set_dynstr(struct elf_module *m)
-{
-	unsigned int idx;
-
-
-	idx = find_sec(m, ".dynstr");
-
-	if (idx) {
-		m->dyn_str  = (((char *) m->ehdr) + m->shdr[idx].sh_offset);
-		m->dyn_size = m->shdr[idx].sh_size;
-		return 1;
-	}
-
-	m->dyn_str = NULL;
-	m->dyn_size = 0;
-
-	return 0;
-}
-
-
-/**
- * @brief locate and set the ".strtab" section
- *
- * @return 0 if string table was not found, 1 otherwise
- *
- */
-
-static int set_strtab(struct elf_module *m)
-{
-	unsigned int idx;
-
-
-	idx = find_sec(m, ".strtab");
-
-	if (idx) {
-		m->str      = (((char *) m->ehdr) + m->shdr[idx].sh_offset);
-		m->str_size = m->shdr[idx].sh_size;
-		return 1;
-	}
-
-	m->str = NULL;
-	m->str_size = 0;
-
-	return 0;
-}
-
-
 /**
  * @brief setup the module structure
  *
+ * @param m a struct elf_module
+ *
  * @return -1 on error
  */
 
@@ -622,6 +74,8 @@ static int setup_module(struct elf_module *m)
 {
 	int i;
 
+	Elf_Shdr *shdr;
+
 
 	/* initialise module configuration */
 	m->pa       = 0;
@@ -629,47 +83,28 @@ static int setup_module(struct elf_module *m)
 	m->size     = 0;
 	m->refcnt   = 0;
 	m->align    = sizeof(void *);
-	m->dyn      = NULL;
-	m->dyn_size = 0;
 	m->sec      = NULL;
 	m->base     = NULL;
 	m->init     = NULL;
 	m->exit     = NULL;
 
-	/* set section headers */
-	if (m->ehdr->e_shoff) {
-		m->shdr = (Elf_Shdr *) (((char *) m->ehdr) + m->ehdr->e_shoff);
-	} else {
-		m->shdr = NULL;
-		pr_debug(MOD "ERR: no section header found\n");
-		return -1;
-	}
-
-	/* locate and set section header string table */
-	if (!set_shstrtab(m))
-		return -1;
-
-	/* locate and set dynamic string table */
-	if (!set_dynstr(m)) {
-		pr_debug(MOD "WARN: no dynamic string table found\n");
-	}
-
-	/* locate and set string table */
-	if (!set_strtab(m))
-		return -1;
-
+	
 	/* set up for relocatable object */
 	if (m->ehdr->e_type == ET_REL) {
 		for (i = 0; i < m->ehdr->e_shnum; i++) {
-			if ((m->shdr[i].sh_flags & SHF_ALLOC)) {
+			shdr = elf_get_sec_by_idx(m->ehdr, i);
+			if (!shdr)
+				return -1;	
+
+			if (shdr->sh_flags & SHF_ALLOC) {
 				pr_debug(MOD "Alloc section: %s, size %ld\n",
-					m->sh_str + m->shdr[i].sh_name,
-					m->shdr[i].sh_size);
+					 elf_get_shstrtab_str(m->ehdr, i),
+					 shdr->sh_size);
 
-				m->size += m->shdr[i].sh_size;
+				m->size += shdr->sh_size;
 
-				if (m->shdr[i].sh_addralign > m->align) {
-					m->align = m->shdr[i].sh_addralign;
+				if (shdr->sh_addralign > m->align) {
+					m->align = shdr->sh_addralign;
 					pr_debug(MOD "align: %d\n", m->align);
 				}
 
@@ -677,11 +112,17 @@ static int setup_module(struct elf_module *m)
 		}
 	}
 
-
 	return 0;
 }
 
 
+/**
+ * @brief load the run time sections of a module into memory
+ *
+ * @param m a struct elf_module
+ *
+ * @return 0 on success, -ENOMEM on error
+ */
 
 static int module_load_mem(struct elf_module *m)
 {
@@ -711,7 +152,7 @@ static int module_load_mem(struct elf_module *m)
 	va_load = m->va;
 	pa_load = m->pa;
 
-	m->num_sec = get_num_alloc_sections(m);
+	m->num_sec = elf_get_num_alloc_sections(m->ehdr);
 	m->sec = (struct module_section *)
 		 kcalloc(sizeof(struct module_section), m->num_sec);
 
@@ -723,11 +164,11 @@ static int module_load_mem(struct elf_module *m)
 
 	while (1) {
 
-		idx = find_shdr_alloc(m, idx + 1);
+		idx = elf_find_shdr_alloc_idx(m->ehdr, idx + 1);
 		if (!idx)
 			break;
 
-		sec = get_sec(m, idx);
+		sec = elf_get_sec_by_idx(m->ehdr, idx);
 
 
 		if (!sec->sh_size)	/* don't need those */
@@ -735,7 +176,10 @@ static int module_load_mem(struct elf_module *m)
 
 		s->size = sec->sh_size;
 
-		src = get_shstrtab_str(m, idx);
+		src = elf_get_shstrtab_str(m->ehdr, idx);
+		if (!src)
+			goto error;
+
 		s->name = kmalloc(strlen(src));
 
 		if (!s->name)
@@ -787,6 +231,14 @@ error:
 }
 
 
+/**
+ * @brief apply relocations to a module
+ *
+ * @param m a struct elf_module
+ *
+ * @return 0 on success, otherwise error
+ */
+
 static int module_relocate(struct elf_module *m)
 {
 	unsigned int idx = 0;
@@ -810,12 +262,12 @@ static int module_relocate(struct elf_module *m)
 
 	while (1) {
 
-		idx = find_sec_type(m, SHT_RELA, idx + 1);
+		idx = elf_find_sec_idx_by_type(m->ehdr, SHT_RELA, idx + 1);
 
 		if (!idx)
 			break;
 
-		sec = get_sec(m, idx);
+		sec = elf_get_sec_by_idx(m->ehdr, idx);
 
 		pr_debug(MOD "\n"
 			MOD "Section Header info: %ld\n", sec->sh_info);
@@ -834,10 +286,10 @@ static int module_relocate(struct elf_module *m)
 
 				int reladdr;
 				unsigned int symsec = ELF_R_SYM(relatab[i].r_info);
-				char *symstr = get_symbol_str(m, symsec);
+				char *symstr = elf_get_symbol_str(m->ehdr, symsec);
 				struct module_section *s;
 				struct module_section *text  = find_mod_sec(m, ".text");
-
+				
 				pr_debug(MOD "OFF: %08lx INF: %8lx ADD: %3ld LNK: %ld SEC: %d NAME: %s\n",
 				       relatab[i].r_offset,
 				       relatab[i].r_info,
@@ -858,15 +310,15 @@ static int module_relocate(struct elf_module *m)
 							 symstr);
 
 
-						if (!(get_symbol_type(m, symstr) & STT_OBJECT)) {
+						if (!(elf_get_symbol_type(m->ehdr, symstr) & STT_OBJECT)) {
 							pr_debug(MOD "\tERROR, object data resolution not yet implemented, symbol %s may not function as intended. If it is a variable, declare it static as a workaround\n", symstr);
 						}
 
-						if (!(get_symbol_type(m, symstr) & (STT_FUNC | STT_OBJECT))) {
+						if (!(elf_get_symbol_type(m->ehdr, symstr) & (STT_FUNC | STT_OBJECT))) {
 							pr_err(MOD "\tERROR, unresolved symbol %s\n", symstr);
 							return -1;
 						}
-						if (!get_symbol_value(m, symstr, &symval)) {
+						if (!elf_get_symbol_value(m->ehdr, symstr, &symval)) {
 							pr_err(MOD "\tERROR, unresolved symbol %s\n", symstr);
 							return -1;
 						}
@@ -881,7 +333,7 @@ static int module_relocate(struct elf_module *m)
 
 				} else  { /* no string, symtab entry is probably a section, try to identify it */
 
-					char *secstr = get_shstrtab_str(m, symsec);
+					char *secstr = elf_get_shstrtab_str(m->ehdr, symsec);
 
 					s = find_mod_sec(m, secstr);
 
@@ -909,6 +361,13 @@ static int module_relocate(struct elf_module *m)
 }
 
 
+/**
+ * @brief unload a module
+ *
+ * @param m a struct elf_module
+ *
+ */
+
 void module_unload(struct elf_module *m)
 {
 	int i;
@@ -929,6 +388,14 @@ void module_unload(struct elf_module *m)
 }
 
 
+/**
+ * @brief load a module
+ *
+ * @param m a struct elf_module
+ * @param p the address where the module ELF file is located
+ *
+ * @return 0 on success, -1 on error
+ */
 
 int module_load(struct elf_module *m, void *p)
 {
@@ -965,13 +432,13 @@ int module_load(struct elf_module *m, void *p)
 
 	_kmod.m[_kmod.cnt++] = m;
 
-	if (get_symbol_value(m, "_module_init", &symval))
+	if (elf_get_symbol_value(m->ehdr, "_module_init", &symval))
 		m->init = (void *) (m->va + symval);
 	else
 		pr_warn(MOD "_module_init() not found\n");
 
 
-	if (get_symbol_value(m, "_module_exit", &symval))
+	if (elf_get_symbol_value(m->ehdr, "_module_exit", &symval))
 		m->exit = (void *) (m->va + symval);
 	else
 		pr_warn(MOD "_module_exit() not found\n");
@@ -997,6 +464,9 @@ error:
 }
 
 
+/**
+ * @brief list all loaded modules
+ */
 
 void modules_list_loaded(void)
 {
@@ -1010,8 +480,8 @@ void modules_list_loaded(void)
 		       MOD "\n",
 		       (*m), (*m)->base);
 
-		dump_sections((*m));
-		dump_symtab((*m));
+		elf_dump_sections((*m)->ehdr);
+		elf_dump_symtab((*m)->ehdr);
 
 		m++;
 	}
diff --git a/kernel/xentium.c b/kernel/xentium.c
new file mode 100644
index 0000000..e1b09ba
--- /dev/null
+++ b/kernel/xentium.c
@@ -0,0 +1,304 @@
+/**
+ * @file kernel/xentium.c
+ *
+ */
+
+
+#include <kernel/printk.h>
+#include <kernel/err.h>
+#include <kernel/xentium.h>
+#include <kernel/kmem.h>
+#include <kernel/kernel.h>
+#include <asm-generic/swab.h>
+#include <kernel/string.h>
+#include <elf.h>
+
+
+
+
+
+
+
+
+
+
+#define MSG "XEN: "
+
+
+
+/* if we need more space, this is how many entries we will add */
+#define KERNEL_REALLOC 10
+/* this is where we keep track of loaded modules */
+static struct {
+	struct xen_kernel **x;
+	int    sz;
+	int    cnt;
+} _xen;
+
+
+
+
+/**
+ * @brief setup the module structure
+ *
+ * @return -1 on error
+ */
+
+static int xentium_setup_kernel(struct xen_kernel *m)
+{
+	int i;
+
+	Elf_Shdr *shdr;
+
+
+	/* initialise module configuration */
+	m->size     = 0;
+	m->refcnt   = 0;
+	m->align    = sizeof(void *);
+	m->sec      = NULL;
+	m->ep       = m->ehdr->e_entry;
+
+
+
+	for (i = 0; i < m->ehdr->e_shnum; i++) {
+		shdr = elf_get_sec_by_idx(m->ehdr, i);
+		if (!shdr)
+			return -1;	
+
+		if (shdr->sh_flags & SHF_ALLOC) {
+			printk(MSG "found alloc section: %s, size %ld\n",
+			       elf_get_shstrtab_str(m->ehdr, i),
+			       shdr->sh_size);
+
+			m->size += shdr->sh_size;
+
+			if (shdr->sh_addralign > m->align) {
+				m->align = shdr->sh_addralign;
+				printk(MSG "align: %d\n", m->align);
+			}
+
+		}
+	}
+
+	return 0;
+}
+
+
+
+/**
+ * @brief check if this is a valid Xentium ELF binary
+ * @note this requires elf32-big instead of elf32-xentium in linker script
+ *	 target
+ */
+
+int xentium_elf_header_check(Elf_Ehdr *ehdr)
+{
+	if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
+		pr_debug(MSG "swapping kernel ELF header endianess");
+		elf_hdr_endianess_swap(ehdr);
+	}
+
+	if (ehdr->e_shentsize != sizeof(Elf_Shdr))
+		return -1;
+
+	if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0))
+		return -1;
+
+	if (!(ehdr->e_ident[EI_MAG1] == ELFMAG1))
+		return -1;
+
+	if (!(ehdr->e_ident[EI_MAG2] == ELFMAG2))
+		return -1;
+
+	if (!(ehdr->e_ident[EI_MAG3] == ELFMAG3))
+		return -1;
+
+	if (!(ehdr->e_ident[EI_CLASS] == ELFCLASS32))
+		if (!(ehdr->e_ident[EI_CLASS] == ELFCLASS64))
+			return -1;
+
+
+	if (!(ehdr->e_ident[EI_VERSION] == EV_CURRENT))
+		return -1;
+
+#if 0
+	/* the Xentium toolchain cannot produce files with relocations,
+	 * which is very sad...
+	 */
+	if (!(ehdr->e_type == ET_REL)) {
+		return -1;
+	}
+	
+	if(!ehdr->e_machine != XXX)
+		return -1;
+#endif
+
+	if (!(ehdr->e_version == EV_CURRENT))
+		return -1;
+
+	return 0;
+}
+
+
+/**
+ * @brief load a xentium kernel
+ *
+ * @note since xentium programs are not relocatable, this just dumps
+ * them wherever they say they want to be. The user is responsible for the
+ * proper memory configuration and offsets, I really can't do much about that at
+ * the moment, because I simply do not have the time to just work with the
+ * object files and do all relocations by hand, because that would also require
+ * me to take care of the Xentium's runtime wrapper code, which again would take
+ * more time that I can currently spare, but this would be the preferred
+ * solution.
+ */
+
+static int xentium_load_kernel(struct xen_kernel *x)
+{
+	unsigned int idx = 0;
+
+	char *src;
+
+	Elf_Shdr *sec;
+
+	struct xen_module_section *s;
+
+	uint32_t *p;
+
+	int i;
+
+
+	printk(MSG "\n" MSG "\n"
+	       MSG "Loading kernel run-time sections\n");
+
+	x->num_sec = elf_get_num_alloc_sections(x->ehdr);
+	x->sec = (struct xen_module_section *)
+		kcalloc(sizeof(struct xen_module_section), x->num_sec);
+
+	if (!x->sec)
+		goto error;
+
+	s = x->sec;
+
+	while (1) {
+
+		idx = elf_find_shdr_alloc_idx(x->ehdr, idx + 1);
+
+
+		if (!idx)
+			break;
+
+		sec = elf_get_sec_by_idx(x->ehdr, idx);
+
+		if (!sec->sh_size)	/* don't need those */
+			continue;
+
+		s->size = sec->sh_size;
+
+		src = elf_get_shstrtab_str(x->ehdr, idx);
+		s->name = kmalloc(strlen(src));
+
+		if (!s->name)
+			goto error;
+
+		strcpy(s->name, src);
+
+		if (sec->sh_type & SHT_NOBITS) {
+			printk(MSG "\tZero segment %10s at %p size %ld\n",
+			       s->name, (char *) sec->sh_addr,
+			       sec->sh_size);
+
+			bzero((void *) sec->sh_addr, s->size);
+		} else {
+			printk(MSG "\tcopy segment %10s from %p to %p size %ld\n",
+			       s->name,
+			       (char *) x->ehdr + sec->sh_offset,
+			       (char *) sec->sh_addr,
+			       sec->sh_size);
+
+			memcpy((void *) sec->sh_addr,
+			       (char *) x->ehdr + sec->sh_offset,
+			       sec->sh_size);
+
+			printk(MSG "\tadjust byte ordering\n");
+
+			p = (uint32_t *) sec->sh_addr;
+			for (i = 0; i < sec->sh_size / sizeof(uint32_t); i++)
+				p[i] = swab32(p[i]);
+
+
+
+		}
+
+		s->addr = sec->sh_addr;
+
+		s++;
+
+		if (s > &x->sec[x->num_sec]) {
+			printk(MSG "Error out of section memory\n");
+			goto error;
+		}
+	}
+
+	return 0;
+
+error:
+	if (x->sec)
+		for (idx = 0; idx < x->num_sec; idx++)
+			kfree(x->sec[idx].name);
+
+	kfree(x->sec);
+
+	return -ENOMEM;
+}
+
+
+
+#include <asm-generic/swab.h>
+int xentium_kernel_load(struct xen_kernel *x, void *p)
+{
+	unsigned long symval;
+
+
+	/* the ELF binary starts with the ELF header */
+	x->ehdr = (Elf_Ehdr *) p;
+
+	printk(MSG "Checking ELF header\n");
+
+
+
+	if (xentium_elf_header_check(x->ehdr))
+		goto error;
+
+	printk(MSG "Setting up module configuration\n");
+
+	if (xentium_setup_kernel(x))
+		goto error;
+
+	if (xentium_load_kernel(x))
+		goto cleanup;
+
+
+
+	if (_xen.cnt == _xen.sz) {
+		_xen.x = krealloc(_xen.x, (_xen.sz + KERNEL_REALLOC) *
+				   sizeof(struct xen_kernel **));
+
+		bzero(&_xen.x[_xen.sz], sizeof(struct xen_kernel **) *
+		      KERNEL_REALLOC);
+		_xen.sz += KERNEL_REALLOC;
+	}
+
+	_xen.x[_xen.cnt++] = x;
+
+	return 0;
+cleanup:
+	printk("cleanup\n");
+#if 0
+	xentium_kernel_unload(m);
+#endif
+error:
+	printk("error\n");
+	return -1;
+}
+
diff --git a/lib/Makefile b/lib/Makefile
index a0d140f..9f50e2e 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -4,3 +4,4 @@ lib-$(CONFIG_PAGE_MAP)	+= page.o
 lib-$(CONFIG_AR)	+= ar.o
 lib-$(CONFIG_CHUNK)	+= chunk.o
 lib-y			+= string.o
+lib-y			+= elf.o
diff --git a/lib/elf.c b/lib/elf.c
new file mode 100644
index 0000000..a63e372
--- /dev/null
+++ b/lib/elf.c
@@ -0,0 +1,831 @@
+/**
+ * @file lib/elf.c
+ */
+
+
+#include <kernel/elf.h>
+#include <kernel/string.h>
+#include <kernel/printk.h>
+
+#include <asm-generic/swab.h>
+
+#define MSG "ELF: "
+
+
+/**
+ * @brief get the base of the ELF section header(s)
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * return a Elf_Shdr or NULL if not found
+ */
+
+Elf_Shdr *elf_get_shdr(const Elf_Ehdr *ehdr)
+{
+	Elf_Shdr *shdr = NULL;
+
+	if (ehdr->e_shoff)
+		shdr = (Elf_Shdr *) (((char *) ehdr) + ehdr->e_shoff);
+
+
+	return shdr;
+}
+
+
+/**
+ * @brief find section headers marked ALLOC by index
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ *
+ * @param offset a offset into the table (to locate multiple identical types)
+ *
+ * @return section index or 0 if not found
+ */
+
+size_t elf_find_shdr_alloc_idx(const Elf_Ehdr *ehdr, const size_t offset)
+{
+	size_t i;
+
+	Elf_Shdr *shdr;
+
+
+	shdr = elf_get_shdr(ehdr);
+	if (!shdr)
+		return 0;
+
+
+	for (i = offset; i < ehdr->e_shnum; i++) {
+		if ((shdr[i].sh_flags & SHF_ALLOC))
+			return i;
+	}
+
+	return 0;
+}
+
+
+/**
+ * @brief return a section header by index
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @param idx the section index
+ *
+ * @return NULL if entry not found, pointer to entry otherwise
+ */
+
+Elf_Shdr *elf_get_sec_by_idx(const Elf_Ehdr *ehdr, const size_t idx)
+{
+	Elf_Shdr *shdr;
+
+
+	if (idx >= ehdr->e_shnum)
+		return NULL;
+
+	shdr = elf_get_shdr(ehdr);
+	if (!shdr)
+		return NULL;
+
+	return &shdr[idx];
+}
+
+
+/**
+ * @brief locate the ".shstrtab" section
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @return the section header or NULL if not found
+ *
+ */
+
+Elf_Shdr *elf_get_sec_shstrtab(const Elf_Ehdr *ehdr)
+{
+	size_t i;
+
+	char *sh_str;
+
+	Elf_Shdr *shdr;
+
+
+	shdr = elf_get_shdr(ehdr);
+	if (!shdr)
+		return NULL;
+
+
+	for (i = 0; i < ehdr->e_shnum; i++) {
+
+		if (shdr[i].sh_type != SHT_STRTAB)
+			continue;
+
+		/* section name index is not within table boundary, skip */
+		if (shdr[i].sh_size < shdr[i].sh_name)
+			continue;
+
+		sh_str  = (((char *) ehdr) + shdr[i].sh_offset);
+
+		/* it's a string section and the size is ok,
+		 * now make sure it is the right one */
+		if (!strcmp(sh_str + shdr[i].sh_name, ".shstrtab"))
+			return &shdr[i];
+	}
+
+	return NULL;
+}
+
+
+/**
+ * @brief in-place swap the endianess of an ELF header
+ *
+ * @param ehdr an Elf_Ehdr
+ */
+
+void elf_hdr_endianess_swap(Elf_Ehdr *ehdr)
+{
+	uint32_t i;
+	uint32_t len;
+
+	uint32_t *p;
+
+	Elf_Shdr *shdr;
+	Elf_Phdr *phdr;
+
+
+
+	/* endianess is a factor from e_type onwards */
+
+	ehdr->e_type	  = swab16(ehdr->e_type);
+	ehdr->e_machine	  = swab16(ehdr->e_machine);
+	ehdr->e_version	  = swab32(ehdr->e_version);
+	ehdr->e_entry	  = swab32(ehdr->e_entry);
+	ehdr->e_phoff	  = swab32(ehdr->e_phoff);
+	ehdr->e_shoff	  = swab32(ehdr->e_shoff);
+	ehdr->e_flags	  = swab32(ehdr->e_flags);
+	ehdr->e_ehsize	  = swab16(ehdr->e_ehsize);
+	ehdr->e_phentsize = swab16(ehdr->e_phentsize);
+	ehdr->e_phnum	  = swab16(ehdr->e_phnum);
+	ehdr->e_shentsize = swab16(ehdr->e_shentsize);
+	ehdr->e_shnum	  = swab16(ehdr->e_shnum);
+	ehdr->e_shstrndx  = swab16(ehdr->e_shstrndx);
+
+	/* everything after is in 32 bit words */
+
+	phdr = (Elf_Phdr *) ((char *) ehdr + ehdr->e_phoff);
+
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		phdr[i].p_type   = swab32(phdr[i].p_type);
+		phdr[i].p_flags  = swab32(phdr[i].p_flags);
+		phdr[i].p_offset = swab32(phdr[i].p_offset);
+		phdr[i].p_vaddr  = swab32(phdr[i].p_vaddr);
+		phdr[i].p_paddr  = swab32(phdr[i].p_paddr);
+		phdr[i].p_filesz = swab32(phdr[i].p_filesz);
+		phdr[i].p_memsz  = swab32(phdr[i].p_memsz);
+		phdr[i].p_align  = swab32(phdr[i].p_align);
+	}
+
+	shdr = (Elf_Shdr *) ((char *) ehdr + ehdr->e_shoff);
+
+	for (i = 0; i < ehdr->e_shnum; i++) {
+		shdr[i].sh_name      = swab32(shdr[i].sh_name);
+		shdr[i].sh_type      = swab32(shdr[i].sh_type);
+		shdr[i].sh_flags     = swab32(shdr[i].sh_flags);
+		shdr[i].sh_addr      = swab32(shdr[i].sh_addr);
+		shdr[i].sh_offset    = swab32(shdr[i].sh_offset);
+		shdr[i].sh_size      = swab32(shdr[i].sh_size);
+		shdr[i].sh_link      = swab32(shdr[i].sh_link);
+		shdr[i].sh_info      = swab32(shdr[i].sh_info);
+		shdr[i].sh_addralign = swab32(shdr[i].sh_addralign);
+		shdr[i].sh_entsize   = swab32(shdr[i].sh_entsize);
+	}
+}
+
+/**
+ * @brief get the address of the section header string table
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @return the address of the section header string table or NULL if not found
+ */
+
+char *elf_get_shstrtab(const Elf_Ehdr *ehdr)
+{
+	char *sh_str;
+
+	Elf_Shdr *shdr;
+
+
+	shdr = elf_get_sec_shstrtab(ehdr);
+	if (!shdr)
+		return NULL;
+
+
+	sh_str = (((char *) ehdr) + shdr->sh_offset);
+
+	return sh_str;
+}
+
+
+/**
+ * @brief get an entry in the .shstrtab
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @param idx the section index
+ *
+ * @return pointer to the start of the string or NULL if not found
+ */
+
+char *elf_get_shstrtab_str(const Elf_Ehdr *ehdr, size_t idx)
+{
+	char *sh_str;
+
+	Elf_Shdr *shdr;
+
+
+
+	if (idx >= ehdr->e_shnum)
+		return NULL;
+
+	shdr = elf_get_shdr(ehdr);
+	if (!shdr)
+		return NULL;
+
+	sh_str = elf_get_shstrtab(ehdr);
+	if (!sh_str)
+		return NULL;
+
+
+	return sh_str + shdr[idx].sh_name;
+}
+
+
+
+/**
+ * @brief find an elf section by name
+ *
+ * @return section index or 0 if not found
+ */
+
+Elf_Shdr *elf_find_sec(const Elf_Ehdr *ehdr, const char *name)
+{
+	size_t i;
+
+	char *sh_str;
+
+	Elf_Shdr *shdr;
+
+
+	shdr = elf_get_sec_shstrtab(ehdr);
+	if (!shdr)
+		return NULL;
+
+	sh_str  = ((char *) ehdr + shdr->sh_offset);
+
+	for (i = 1; i < ehdr->e_shnum; i++) {
+		if (!strcmp(sh_str + shdr[i].sh_name, name))
+			return &shdr[i];
+	}
+
+	return NULL;
+}
+
+
+/**
+ * @brief get the address of the string table
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @return the address of the string table or NULL if not found
+ */
+
+char *elf_get_strtab(const Elf_Ehdr *ehdr)
+{
+	char *sh_str;
+
+	Elf_Shdr *shdr;
+
+
+	shdr = elf_find_sec(ehdr, ".strtab");
+	if (!shdr)
+		return NULL;
+
+
+	sh_str = (((char *) ehdr) + shdr->sh_offset);
+
+	return sh_str;
+}
+
+
+/**
+ * @brief get an entry in the .strtab
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @param idx the entry index
+ *
+ * @return pointer to the start of the string or NULL if not found
+ */
+
+char *elf_get_strtab_str(const Elf_Ehdr *ehdr, size_t idx)
+{
+	char *str;
+
+	Elf_Shdr *shdr;
+
+
+
+	if (idx >= ehdr->e_shnum)
+		return NULL;
+
+	shdr = elf_get_shdr(ehdr);
+	if (!shdr)
+		return NULL;
+
+	str = elf_get_strtab(ehdr);
+	if (!str)
+		return NULL;
+
+
+	return str + shdr[idx].sh_name;
+}
+
+
+/**
+ * @brief get the address of the dynamic string table
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @return the address of the string table or NULL if not found
+ */
+
+char *elf_get_dynstr(const Elf_Ehdr *ehdr)
+{
+	char *dyn_str;
+
+	Elf_Shdr *shdr;
+
+
+	shdr = elf_find_sec(ehdr, ".dynstr");
+	if (!shdr)
+		return NULL;
+
+
+	dyn_str = (((char *) ehdr) + shdr->sh_offset);
+
+	return dyn_str;
+}
+
+
+/**
+ * @brief get an entry in the .strtab
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @param idx the entry index
+ *
+ * @return pointer to the start of the string or NULL if not found
+ */
+
+char *elf_get_dynstr_str(const Elf_Ehdr *ehdr, size_t idx)
+{
+	char *sh_str;
+
+	Elf_Shdr *shdr;
+
+
+
+	if (idx >= ehdr->e_shnum)
+		return NULL;
+
+	shdr = elf_get_shdr(ehdr);
+	if (!shdr)
+		return NULL;
+
+	sh_str = elf_get_dynstr(ehdr);
+	if (!sh_str)
+		return NULL;
+
+
+	return sh_str + shdr[idx].sh_name;
+}
+
+
+/**
+ * @brief get the name of a symbol in .symtab with a given index
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @param idx the symbol index
+ *
+ * @return pointer to the start of the string or NULL if not found
+ */
+
+char *elf_get_symbol_str(const Elf_Ehdr *ehdr, size_t idx)
+{
+	Elf_Shdr *symtab;
+	Elf_Sym *symbols;
+
+
+	symtab = elf_find_sec(ehdr, ".symtab");
+	if (!symtab)
+		return NULL;
+
+	symbols = (Elf_Sym *) (((char *) ehdr) + symtab->sh_offset);
+
+	if (idx < symtab->sh_size / symtab->sh_entsize)
+		return elf_get_strtab(ehdr) + symbols[idx].st_name;
+
+	return NULL;
+}
+
+
+/**
+ * @brief get the value of a symbol
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @param name the name of the symbol
+ *
+ * @param[out] value the value of the symbol
+ *
+ * @return 1 if symbol has been found, 0 otherwise
+ */
+
+unsigned long elf_get_symbol_value(const Elf_Ehdr *ehdr,
+				   const char *name, unsigned long *value)
+
+{
+	unsigned int i;
+	unsigned int idx;
+	size_t sym_cnt;
+
+	Elf_Shdr *symtab;
+	Elf_Sym *symbols;
+
+
+	symtab = elf_find_sec(ehdr, ".symtab");
+
+	if (!symtab) {
+		pr_debug(MSG "WARN: no .symtab section found\n");
+		return -1;
+	}
+
+	if (symtab->sh_entsize != sizeof(Elf_Sym)) {
+		pr_debug(MSG "Error %d != %ld\n",
+			 sizeof(Elf_Sym), symtab->sh_entsize);
+		return -1;
+	}
+
+	symbols = (Elf_Sym *) (((char *) ehdr) + symtab->sh_offset);
+
+	sym_cnt = symtab->sh_size / symtab->sh_entsize;
+
+	for (i = 0; i < sym_cnt; i++) {
+		if(!strcmp(elf_get_symbol_str(ehdr, i), name)) {
+			(*value) =  symbols[i].st_value;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+
+/**
+ * @brief get the ELF type of a symbol
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @param name the name of the symbol
+ *
+ * @return the symbol type or 0 on error or if not found
+ */
+
+unsigned long elf_get_symbol_type(const Elf_Ehdr *ehdr, const char *name)
+{
+	unsigned int i;
+	size_t sym_cnt;
+
+	Elf_Shdr *symtab;
+	Elf_Sym *symbols;
+
+
+	symtab = elf_find_sec(ehdr, ".symtab");
+
+	if (!symtab) {
+		pr_debug(MSG "WARN: no .symtab section found\n");
+		return 0;
+	}
+
+	if (symtab->sh_entsize != sizeof(Elf_Sym)) {
+		pr_debug("Error %d != %ld\n", sizeof(Elf_Sym), symtab->sh_entsize);
+		return 0;
+	}
+
+	symbols = (Elf_Sym *) (((char *) ehdr) + symtab->sh_offset);
+
+	sym_cnt = symtab->sh_size / symtab->sh_entsize;
+
+	for (i = 0; i < sym_cnt; i++) {
+		if(!strcmp(elf_get_symbol_str(ehdr, i), name))
+			return ELF_ST_TYPE(symbols[i].st_info);
+	}
+
+	return 0;
+}
+
+
+/**
+ * @brief find an elf section index by type
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @param sh_type the section type to look for
+ *
+ * @param offset a offset into the table (to locate multiple identical types)
+ *
+ * @return section index or 0 if not found
+ *
+ */
+
+size_t elf_find_sec_idx_by_type(const Elf_Ehdr *ehdr,
+				const uint32_t sh_type,
+				const size_t offset)
+{
+	size_t i;
+
+	Elf_Shdr *shdr;
+
+
+	for (i = offset; i < ehdr->e_shnum; i++) {
+		shdr = elf_get_sec_by_idx(ehdr, i);
+		if (!shdr)
+			return 0;
+		if (sh_type == shdr->sh_type)
+			return i;
+	}
+
+	return 0;
+}
+
+
+/**
+ * @brief get number of sections marked ALLOC with size > 0
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @return number of ALLOC sections
+ */
+
+size_t elf_get_num_alloc_sections(const Elf_Ehdr *ehdr)
+{
+	size_t i;
+	size_t cnt = 0;
+
+	Elf_Shdr *shdr;
+
+
+	for (i = 0; i <ehdr->e_shnum; i++) {
+		shdr = elf_get_sec_by_idx(ehdr, i);
+		if ((shdr->sh_flags & SHF_ALLOC))
+			if (shdr->sh_size)
+				cnt++;
+	}
+
+	return cnt;
+}
+
+
+/**
+ * @brief get the number of entries in a dynamic section
+ *
+ * @param ehdr an Elf_Ehdr
+ *
+ * @return the number of entries in a dynamic section
+ */
+
+size_t elf_get_num_dyn_entries(const Elf_Ehdr *ehdr)
+{
+	Elf_Shdr *shdr;
+
+
+	shdr = elf_find_sec(ehdr, ".dyn");
+	if (!shdr)
+		return 0;
+
+
+	return shdr->sh_size / sizeof(Elf_Dyn);
+}
+
+
+/**
+ * @brief find a dynamic entry by tag
+ *
+ * @param offset a offset into the table (to locate multiple identical types)
+ *
+ * @return NULL if entry not found, pointer to entry otherwise
+ *
+ */
+Elf_Dyn *elf_find_dyn(const Elf_Ehdr *ehdr,
+		      const unsigned long d_tag,
+		      const unsigned int offset)
+{
+	size_t i;
+
+	Elf_Shdr *shdr;
+
+	Elf_Dyn *dyn;
+
+
+	shdr = elf_find_sec(ehdr, ".dyn");
+
+	dyn = (Elf_Dyn *) (((char *) ehdr) + shdr->sh_offset);
+
+	for (i = offset; i < elf_get_num_dyn_entries(ehdr); i++)
+		if (d_tag == dyn[i].d_tag)
+			return &dyn[i];
+
+	return NULL;
+}
+
+
+
+
+/**
+ * @brief dump the contents of .strtab
+ */
+
+void elf_dump_strtab(const Elf_Ehdr *ehdr)
+{
+	size_t i = 0;
+
+	char *s;
+
+
+	printk(MSG "\n.strtab:\n"
+	       "============================\n"
+	       "\t[OFF]\t[STR]\n");
+
+	while((s = elf_get_strtab_str(ehdr, i++)))
+		printk(MSG "\t[%d]\t%s\n", i, s);
+
+	printk(MSG "\n\n");
+}
+
+
+/**
+ * @brief dump the contents of .symtab
+ */
+
+void elf_dump_symtab(const Elf_Ehdr *ehdr)
+{
+	Elf_Shdr *symtab;
+	Elf_Sym *symbols;
+
+	size_t sym_cnt;
+	unsigned int idx;
+	unsigned int i;
+
+
+
+	symtab = elf_find_sec(ehdr, ".symtab");
+
+	if (!symtab) {
+		printk(MSG "WARN: no .symtab section found\n");
+		return;
+	}
+
+
+	if (symtab->sh_entsize != sizeof(Elf_Sym)) {
+		printk(MSG "Error %d != %ld\n", sizeof(Elf_Sym), symtab->sh_entsize);
+		return;
+	}
+
+	symbols = (Elf_Sym *) (((char *) ehdr) + symtab->sh_offset);
+
+	sym_cnt = symtab->sh_size / symtab->sh_entsize;
+
+
+	printk(MSG "\n"
+	       MSG ".symtab contains %d entries\n"
+	       MSG "============================\n"
+	       MSG "\t[NUM]\t[VALUE]\t\t\t[SIZE]\t[TYPE]\t[NAME]\n", sym_cnt);
+
+
+	for (i = 0; i < sym_cnt; i++) {
+
+		printk(MSG "\t%d\t%016lx\t%4ld",
+		       i,
+		       symbols[i].st_value,
+		       symbols[i].st_size);
+
+		switch (ELF_ST_TYPE(symbols[i].st_info)) {
+		case STT_NOTYPE  :
+			printk("\tNOTYPE "); break;
+		case STT_OBJECT  :
+			printk("\tOBJECT "); break;
+		case STT_FUNC    :
+			printk("\tFUNC   "); break;
+		case STT_SECTION :
+			printk("\tSECTION"); break;
+		case STT_FILE    :
+			printk("\tFILE   "); break;
+		case STT_COMMON  :
+			printk("\tCOMMON "); break;
+		case STT_TLS     :
+			printk("\tTLS    "); break;
+		default:
+			printk("\tUNKNOWN"); break;
+		}
+
+		printk("\t%-10s\n", elf_get_symbol_str(ehdr, i));
+
+	}
+}
+
+/**
+ * @brief dump the name of all elf sections
+ */
+
+void elf_dump_sections(const Elf_Ehdr *ehdr)
+{
+	size_t i;
+
+	Elf_Shdr *shdr;
+
+
+	printk(MSG "SECTIONS:\n"
+	       MSG "============================\n"
+	       MSG "\t[NUM]\t[NAME]\t\t\t[TYPE]\t\t[SIZE]\t[ENTSZ]\t[FLAGS]\n"
+	      );
+
+
+	for (i = 0; i < ehdr->e_shnum; i++) {
+
+		shdr = elf_get_sec_by_idx(ehdr, i);
+		printk(MSG "\t%d\t%-20s", i, elf_get_shstrtab_str(ehdr, i));
+
+		switch (shdr->sh_type) {
+		case SHT_NULL:
+			printk("%-10s", "\tNULL");
+			break;
+		case SHT_PROGBITS:
+			printk("%-10s", "\tPROGBITS");
+			break;
+		case SHT_SYMTAB:
+			printk("%-10s", "\tSYMTAB");
+			break;
+		case SHT_STRTAB:
+			printk("%-10s", "\tSTRTAB");
+			break;
+		case SHT_RELA  :
+			printk("%-10s", "\tRELA");
+			break;
+		case SHT_HASH  :
+			printk("%-10s", "\tHASH");
+			break;
+		case SHT_DYNAMIC:
+			printk("%-10s", "\tDYNAMIC");
+			break;
+		case SHT_NOTE  :
+			printk("%-10s", "\tNOTE");
+			break;
+		case SHT_NOBITS:
+			printk("%-10s", "\tNOBITS");
+			break;
+		case SHT_REL   :
+			printk("%-10s", "\tREL");
+			break;
+		case SHT_SHLIB :
+			printk("%-10s", "\tSHLIB");
+			break;
+		case SHT_DYNSYM:
+			printk("%-10s", "\tDYNSYM");
+			break;
+		case SHT_NUM   :
+			printk("%-10s", "\tNUM");
+			break;
+		default:
+			printk("%-10s", "\tOTHER");
+			break;
+		}
+
+		printk("\t%ld\t%ld\t", shdr->sh_size, shdr->sh_entsize);
+
+		if (shdr->sh_flags & SHF_WRITE)
+			printk("WRITE ");
+		if (shdr->sh_flags & SHF_ALLOC)
+			printk("ALLOC ");
+		if (shdr->sh_flags & SHF_EXECINSTR)
+			printk("EXECINSTR ");
+		if (shdr->sh_flags & SHF_TLS)
+			printk("TLS ");
+		if (shdr->sh_flags & SHF_MASKPROC)
+			printk("MASKPROC ");
+
+		printk(MSG "\n");
+
+	}
+
+}
+
diff --git a/lib/string.c b/lib/string.c
index c1d537e..3f08b9d 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -153,6 +153,57 @@ void *memcpy(void *dest, const void *src, size_t n)
 EXPORT_SYMBOL(memcpy);
 
 
+/**
+ * @brief copy a '\0' terminated string
+ *
+ * @param dest the destination of the string
+ * @param src the source of string
+ *
+ * @return a pointer to dest
+ *
+ * @note strings may not overlap
+ *
+ */
+
+char *strcpy(char *dest, const char *src)
+{
+	char *tmp;
+	
+	
+	tmp = dest;
+
+	while ((*dest++ = *src++) != '\0');
+	
+	return tmp;
+}
+EXPORT_SYMBOL(strcpy);
+
+
+
+/**
+ * @brief set the first n bytes of the area starting at s to zero (bytes
+ *        containing '\0')
+ *
+ * @param s the start of the area
+ *
+ * @param n the number of bytes to set to zero
+ *
+ */
+
+void bzero(void *s, size_t n)
+{
+	char *c;
+
+
+	c = (char *) s;
+
+	while (n--) {
+		(*c) = '\0';
+		c++;
+	}
+}
+EXPORT_SYMBOL(bzero);
+
 
 
 #include <stdarg.h>
-- 
GitLab