[coreboot] New patch to review for filo: 16d77de Rename i386 to x86, in accordance with libpayload

Patrick Georgi (patrick@georgi-clan.de) gerrit at coreboot.org
Wed Dec 19 13:56:16 CET 2012


Patrick Georgi (patrick at georgi-clan.de) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2057

-gerrit

commit 16d77debbf4a46d10e1e8abd105c8d5e6de9ebd9
Author: Patrick Georgi <patrick at georgi-clan.de>
Date:   Wed Dec 19 13:55:00 2012 +0100

    Rename i386 to x86, in accordance with libpayload
    
    Change-Id: Idd2239832f35d74d2034dd8b271ab36a7f82e096
    Signed-off-by: Patrick Georgi <patrick at georgi-clan.de>
---
 Makefile                      |   2 +-
 i386/Makefile.inc             |  23 --
 i386/artecboot.c              | 159 ---------
 i386/context.c                | 135 -------
 i386/context.h                |  65 ----
 i386/include/arch/byteorder.h |  64 ----
 i386/include/arch/elf.h       |   5 -
 i386/include/arch/eltorito.h  |   3 -
 i386/include/arch/timer.h     |  32 --
 i386/ldscript                 |  93 -----
 i386/linux_load.c             | 803 ------------------------------------------
 i386/segment.c                | 135 -------
 i386/segment.h                |  47 ---
 i386/switch.S                 | 116 ------
 i386/sys_info.c               |  34 --
 i386/timer.c                  |  38 --
 i386/wince_load.c             | 385 --------------------
 x86/Makefile.inc              |  23 ++
 x86/artecboot.c               | 159 +++++++++
 x86/context.c                 | 135 +++++++
 x86/context.h                 |  65 ++++
 x86/include/arch/byteorder.h  |  64 ++++
 x86/include/arch/elf.h        |   5 +
 x86/include/arch/eltorito.h   |   3 +
 x86/include/arch/timer.h      |  32 ++
 x86/ldscript                  |  93 +++++
 x86/linux_load.c              | 803 ++++++++++++++++++++++++++++++++++++++++++
 x86/segment.c                 | 135 +++++++
 x86/segment.h                 |  47 +++
 x86/switch.S                  | 116 ++++++
 x86/sys_info.c                |  34 ++
 x86/timer.c                   |  38 ++
 x86/wince_load.c              | 385 ++++++++++++++++++++
 33 files changed, 2138 insertions(+), 2138 deletions(-)

diff --git a/Makefile b/Makefile
index 20b21bf..46010b3 100644
--- a/Makefile
+++ b/Makefile
@@ -88,7 +88,7 @@ INCPAYLOAD = $(LIBPAYLOAD_PREFIX)/include
 LIBGCC = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
 GCCINCDIR = $(shell $(CC) -print-search-dirs | head -n 1 | cut -d' ' -f2)include
 
-ARCHDIR-$(CONFIG_TARGET_I386) := i386
+ARCHDIR-$(CONFIG_TARGET_I386) := x86
 
 CPPFLAGS := -nostdinc -imacros $(obj)/config.h
 CPPFLAGS += -I$(INCPAYLOAD) -I$(INCPAYLOAD)/$(ARCHDIR-y)
diff --git a/i386/Makefile.inc b/i386/Makefile.inc
deleted file mode 100644
index ce3e5c8..0000000
--- a/i386/Makefile.inc
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Copyright (C) 2008 by coresystems GmbH 
-# 
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that 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.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-TARGETS-$(CONFIG_TARGET_I386) += i386/context.o i386/switch.S.o i386/segment.o
-TARGETS-$(CONFIG_TARGET_I386) += i386/timer.o i386/sys_info.o
-TARGETS-$(CONFIG_LINUX_LOADER) += i386/linux_load.o
-TARGETS-$(CONFIG_WINCE_LOADER) += i386/wince_load.o
-TARGETS-$(CONFIG_ARTEC_BOOT) += i386/artecboot.o
diff --git a/i386/artecboot.c b/i386/artecboot.c
deleted file mode 100644
index 697a05b..0000000
--- a/i386/artecboot.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*******************************************************************************
- *
- *	FILO Artecboot loader, enables multiboot through custom header 
- *
- *	Copyright 2006 Andrei Birjukov <andrei.birjukov at artecdesign.ee> and
- *	Artec Design LLC http://www.artecdesign.ee
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	This program is distributed in the hope that 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.
- *
- *	You should have received a copy of the GNU General Public License
- *	along with this program; if not, write to the Free Software
- *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ******************************************************************************/
-
-#include <libpayload.h>
-#include <config.h>
-#include <fs.h>
-#include "artecboot.h"
-#include "../fs/filesys.h"
-
-#define DEBUG_THIS CONFIG_DEBUG_ARTECBOOT
-#include <debug.h>
-
-static ARTECBOOT_HEADER bootHdr;
-
-int artecboot_load(const char *file, const char *cmdline)
-{
-	int i;
-
-	printf("Starting the Artecboot loader...\n");
-	// clear the boot header
-	memset(&bootHdr, 0, sizeof(bootHdr));
-	
-	// try opening the boot parameter file
-	if (!file_open(file))
-	{
-		printf("Boot error: failed to open image file: %s\n", file);
-		return LOADER_NOT_SUPPORT;
-	}
-
-	file_seek(0);	// seek to the beginning of the parameter file
-	
-	// now read out the boot header
-	if(file_read(&bootHdr, sizeof(ARTECBOOT_HEADER)) != sizeof(ARTECBOOT_HEADER))
-	{
-		printf("Boot error: failed reading the boot image header\n");
-		file_close();
-		return LOADER_NOT_SUPPORT;
-	}
-	
-	// check whether the parameter data is valid at all
-	if(bootHdr.magicHeader != ARTECBOOT_HEADER_MAGIC)
-	{
-		debug("No Artecboot signature found, aborting\n");
-		file_close();
-		return LOADER_NOT_SUPPORT;
-	}
-
-	// check the version number
-	if(bootHdr.bootVersion > CURRENT_VERSION)
-	{
-		printf("Boot error: incompatible version number: %x\n", bootHdr.bootVersion);
-		file_close();
-		return LOADER_NOT_SUPPORT;
-	}
-	
-	// shall we replace the command line?
-	if(bootHdr.bitFlags & FLAG_CMDLINE)
-	{
-		// check the command line and wipe out all junk
-		for(i=0; bootHdr.cmdLine[i] != 0; i++)
-			switch(bootHdr.cmdLine[i])
-			{
-			case '\n':
-			case '\r':
-				bootHdr.cmdLine[i] = ' ';
-				break;
-			default:
-				// do nothing
-				break;
-			}
-	}
-	else if(cmdline) 
-		strncpy(bootHdr.cmdLine, cmdline, sizeof(bootHdr.cmdLine));
-	
-	// proceed basing on the specified OS type
-	switch(bootHdr.osType)
-	{
-	case OS_LINUX:
-		if(bootHdr.bitFlags & FLAG_INITRD)
-		{
-			char initrdParam[100];
-			if(bootHdr.bitFlags & FLAG_FILESYSTEM)
-			{
-				// we are using a real filesystem, so format the initrd file as usually
-				sprintf(initrdParam, " initrd=%s", bootHdr.initrdFile); 
-			}
-			else
-			{
-				// we are using a 'fake' filesystem, so use the image offset
-				sprintf(initrdParam, " initrd=%s at 0x%x,0x%x",
-						dev_name, bootHdr.initrdStart, bootHdr.initrdSize);
-			}			
-
-			debug("adding initrd parameter: %s\n", initrdParam); 
-			strncat(bootHdr.cmdLine, initrdParam, sizeof(bootHdr.cmdLine));
-		}
-	
-		printf("Starting Linux loader...\n");
-
-		// if using a real filesystem, load the kernel image from a specified file		
-		if(bootHdr.bitFlags & FLAG_FILESYSTEM)
-			linux_load(bootHdr.kernelFile, bootHdr.cmdLine);
-		// if using a 'fake' filesystem, consider reading from the same image
-		else
-		{
-			part_start = bootHdr.kernelStart >> DEV_SECTOR_BITS;	
-			part_length = ((bootHdr.kernelSize-1) >> DEV_SECTOR_BITS) + 1;
-			filemax = bootHdr.kernelSize;
-			using_devsize = 0;
-			linux_load(file, bootHdr.cmdLine);
-		}
-	
-		break;
-		
-	case OS_WINCE:
-
-		printf("Starting Windows CE loader...\n");
-		// if using a real filesystem, load the kernel image from a specified file		
-		if(bootHdr.bitFlags & FLAG_FILESYSTEM)
-			wince_load(bootHdr.kernelFile, bootHdr.cmdLine);
-		// if using a 'fake' filesystem, consider reading from the same image
-		else
-		{
-			part_start = bootHdr.kernelStart >> DEV_SECTOR_BITS;	
-			part_length = ((bootHdr.kernelSize-1) >> DEV_SECTOR_BITS) + 1;
-			filemax = bootHdr.kernelSize;	
-			wince_load(file, bootHdr.cmdLine);
-		}
-
-		break;	
-		
-	default:
-		printf("Boot error: unknown OS type, aborting: %d\n", bootHdr.osType);
-		return LOADER_NOT_SUPPORT;
-	}
-	
-	file_close();
-	return 0;
-}
diff --git a/i386/context.c b/i386/context.c
deleted file mode 100644
index a06b97d..0000000
--- a/i386/context.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * This file is part of FILO.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-
-/*
- * context switching
- * 2003-10 by SONE Takeshi
- */
-
-#include <libpayload.h>
-#include <lib.h>
-#include "segment.h"
-#include "context.h"
-
-#define MAIN_STACK_SIZE 16384
-#define IMAGE_STACK_SIZE 4096
-
-static void start_main(void);	/* forward decl. */
-void __exit_context(void);	/* assembly routine */
-
-/*
- * Main context structure 
- * It is placed at the bottom of our stack, and loaded by assembly routine
- * to start us up.
- */
-struct context main_ctx __attribute__ ((section(".initctx"))) = {
-	.gdt_base = (u32) gdt,
-	.gdt_limit = GDT_LIMIT,
-	.cs = FLAT_CS, .ds = FLAT_DS,
-	.es = FLAT_DS, .fs = FLAT_DS,
-	.gs = FLAT_DS, .ss = FLAT_DS,
-	.esp = (u32)ESP_LOC(&main_ctx),
-	.eip = (u32) start_main,
-	.return_addr = (u32) __exit_context
-};
-
-/* This is used by assembly routine to load/store the context which
- * it is to switch/switched.  */
-struct context *__context = &main_ctx;
-
-/* Stack for loaded ELF image */
-static u8 image_stack[IMAGE_STACK_SIZE];
-
-/* Pointer to startup context (physical address) */
-unsigned long __boot_ctx;
-
-/*
- * Main starter
- * This is the C function that runs first.
- */
-static void start_main(void)
-{
-	int retval;
-	extern int main(void);
-
-	/* Save startup context, so we can refer to it later.
-	 * We have to keep it in physical address since we will relocate. */
-	__boot_ctx = virt_to_phys(__context);
-
-	/* Start the real fun */
-	retval = main();
-
-	/* Pass return value to startup context. Bootloader may see it. */
-	boot_ctx->eax = retval;
-
-	/* Returning from here should jump to __exit_context */
-	__context = boot_ctx;
-}
-
-/* Setup a new context using the given stack.
- */
-struct context *init_context(u8 * stack, u32 stack_size, int num_params)
-{
-	struct context *ctx;
-
-	ctx = (struct context *) (stack + stack_size - 
-			(sizeof(*ctx) + num_params * sizeof(u32)));
-	memset(ctx, 0, sizeof(*ctx));
-
-	/* Fill in reasonable default for flat memory model */
-	ctx->gdt_base = virt_to_phys(gdt);
-	ctx->gdt_limit = GDT_LIMIT;
-	ctx->cs = FLAT_CS;
-	ctx->ds = FLAT_DS;
-	ctx->es = FLAT_DS;
-	ctx->fs = FLAT_DS;
-	ctx->gs = FLAT_DS;
-	ctx->ss = FLAT_DS;
-	ctx->esp = virt_to_phys(ESP_LOC(ctx));
-	ctx->return_addr = virt_to_phys(__exit_context);
-
-	return ctx;
-}
-
-/* Switch to another context. */
-struct context *switch_to(struct context *ctx)
-{
-	struct context *save, *ret;
-
-	save = __context;
-	__context = ctx;
-	asm volatile ("push %%cs; call __switch_context" ::: "memory");
-	ret = __context;
-	__context = save;
-	return ret;
-}
-
-/* Start ELF Boot image */
-u32 start_elf(u32 entry_point, u32 param)
-{
-	struct context *ctx;
-
-	ctx = init_context(image_stack, sizeof image_stack, 1);
-	ctx->eip = entry_point;
-	ctx->param[0] = param;
-	ctx->eax = 0xe1fb007;
-	ctx->ebx = param;
-
-	ctx = switch_to(ctx);
-	return ctx->eax;
-}
diff --git a/i386/context.h b/i386/context.h
deleted file mode 100644
index 44e9665..0000000
--- a/i386/context.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * This file is part of FILO.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-
-#ifndef i386_CONTEXT_H
-#define i386_CONTEXT_H
-
-struct context {
-	/* Stack Segment, placed here because of the alignment issue... */
-	u16 ss;
-	/* Used with sgdt/lgdt */
-	u16 gdt_limit;
-	u32 gdt_base;
-	/* General registers, accessed with pushal/popal */
-	u32 edi;
-	u32 esi;
-	u32 ebp;
-	u32 esp;		/* points just below eax */
-	u32 ebx;
-	u32 edx;
-	u32 ecx;
-	u32 eax;
-#define ESP_LOC(ctx) (&(ctx)->gs)
-	/* Segment registers */
-	u32 gs;
-	u32 fs;
-	u32 es;
-	u32 ds;
-	/* Flags */
-	u32 eflags;
-	/* Code segment:offset */
-	u32 eip;
-	u32 cs;
-	/* Optional stack contents */
-	u32 return_addr;
-	u32 param[0];
-};
-
-/* Create a new context in the given stack */
-struct context *init_context(u8 * stack, u32 stack_size, int num_param);
-
-/* Switch context */
-struct context *switch_to(struct context *);
-
-/* Holds physical address of boot context */
-extern unsigned long __boot_ctx;
-
-/* This can always be safely used to refer to the boot context */
-#define boot_ctx ((struct context *) phys_to_virt(__boot_ctx))
-
-#endif				/* i386_CONTEXT_H */
diff --git a/i386/include/arch/byteorder.h b/i386/include/arch/byteorder.h
deleted file mode 100644
index afaebfa..0000000
--- a/i386/include/arch/byteorder.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef ARCH_ENDIAN_H
-#define ARCH_ENDIAN_H
-
-static inline u16 __i386_bswap_16(u16 x)
-{
-	__asm__("xchgb %b0,%h0\n\t"
-		: "=q" (x)
-		: "0" (x));
-	return x;
-}
-
-static inline u32 __i386_bswap_32(u32 x)
-{
-	__asm__("xchgb %b0,%h0\n\t"
-		"rorl $16,%0\n\t"
-		"xchgb %b0,%h0"
-		: "=q" (x)
-		: "0" (x));
-	return x;
-}
-
-
-#define __bswap_constant_16(x) \
-	((u16)((((u16)(x) & 0x00ff) << 8) | \
-		(((u16)(x) & 0xff00) >> 8)))
-
-#define __bswap_constant_32(x) \
-	((u32)((((u32)(x) & 0x000000ffU) << 24) | \
-		(((u32)(x) & 0x0000ff00U) <<  8) | \
-		(((u32)(x) & 0x00ff0000U) >>  8) | \
-		(((u32)(x) & 0xff000000U) >> 24)))
-
-#define __bswap_16(x) \
-	((u16)(__builtin_constant_p(x) ? \
-	__bswap_constant_16(x) : \
-	__i386_bswap_16(x)))
-
-
-#define __bswap_32(x) \
-	((u32)(__builtin_constant_p(x) ? \
-	__bswap_constant_32(x) : \
-	__i386_bswap_32(x)))
-
-
-#define __BYTE_ORDER __LITTLE_ENDIAN
-
-#define le32_to_cpup(x) (*(u32 *)(x))
-#define cpu_to_le16p(x) (*(u16*)(x))
-
-#define ntohl(x)        __bswap_32(x)
-#define htonl(x)        __bswap_32(x)
-#define ntohs(x)        __bswap_16(x)
-#define htons(x)        __bswap_16(x)
-#define cpu_to_le32(x)  (x)
-#define cpu_to_le16(x)  (x)
-#define cpu_to_be32(x)  __bswap_32(x)
-#define cpu_to_be16(x)  __bswap_16(x)
-#define le32_to_cpu(x)  (x)
-#define le16_to_cpu(x)  (x)
-#define be32_to_cpu(x)  __bswap_32(x)
-#define be16_to_cpu(x)  __bswap_16(x)
-
-#endif /* ARCH_ENDIAN_H */
-
diff --git a/i386/include/arch/elf.h b/i386/include/arch/elf.h
deleted file mode 100644
index 86c6725..0000000
--- a/i386/include/arch/elf.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#define ARCH_ELF_CLASS ELFCLASS32
-#define ARCH_ELF_DATA ELFDATA2LSB
-#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_386 || (x)==EM_486)
-typedef Elf32_Ehdr Elf_ehdr;
-typedef Elf32_Phdr Elf_phdr;
diff --git a/i386/include/arch/eltorito.h b/i386/include/arch/eltorito.h
deleted file mode 100644
index d43e9aa..0000000
--- a/i386/include/arch/eltorito.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#ifndef ELTORITO_PLATFORM
-#define ELTORITO_PLATFORM ELTORITO_PLATFORM_X86
-#endif /* ELTORITO_PLATFORM */
diff --git a/i386/include/arch/timer.h b/i386/include/arch/timer.h
deleted file mode 100644
index 3cdd9b4..0000000
--- a/i386/include/arch/timer.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * This file is part of FILO.
- *
- * (C) 2004-2008 coresystems GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-#ifndef	TIMER_H
-#define TIMER_H
-
-extern u32 cpu_khz;
-
-u64 currticks(void);
-int getrtsecs (void);
-
-#define TICKS_PER_SEC (cpu_khz * 1000)
-#define TICKS_PER_USEC (cpu_khz / 1000)
-
-
-#endif	/* TIMER_H */
diff --git a/i386/ldscript b/i386/ldscript
deleted file mode 100644
index b260c51..0000000
--- a/i386/ldscript
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * This file is part of FILO.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-/* When started from General Software BIOS */
-/* BASE_ADDR = 0x40000; */
-/* When started from coreboot */
-BASE_ADDR = 0x100000;          
-
-
-OUTPUT_FORMAT(elf32-i386)
-OUTPUT_ARCH(i386)
-
-ENTRY(entry)
-
-/* 1024KB heap and 64KB stack */
-HEAP_SIZE = 1 * 1024 * 1024;
-STACK_SIZE = 64 * 1024;
-
-SECTIONS
-{
-    . = BASE_ADDR;
-
-    /* Put Multiboot header near beginning of file, if any. */
-    .hdr : { *(.hdr) *(.hdr.*) }
-
-    /* Start of the program. 
-     * Now the version string is in the note, we must include it
-     * in the program. Otherwise we lose the string after relocation. */
-    . = ALIGN(4096);
-    _start = .;
-
-    /* Putting ELF notes near beginning of file might help bootloaders.
-     * We discard .note sections other than .note.ELFBoot and .note.pinfo,
-     * because some versions of GCC generates useless ones. */
-    .note : { *(.note.ELFBoot) *(note.pinfo) }
-
-    /* Normal sections */
-    .boot : { *(.boot) *(.boot.*) }
-    .text : { *(.text) *(.text.*) }
-    .rodata : {
-	. = ALIGN(4);
-	drivers_start = .;
-	*(.rodata.drivers)
-	drivers_end = .;
-	*(.rodata)
-	*(.rodata.*)
-    }
-    .data : { *(.data) *(.data.*) }
-
-    .bss : {
-	*(.sbss)
-	*(.sbss.*)
-	*(.bss)
-	*(.bss.*)
-	*(COMMON)
-
-	/* heap and stack */
-
-	. = ALIGN(16);
-	_heap = .;
-	. += HEAP_SIZE;
-	. = ALIGN(16);
-	_eheap = .;
-
-	_stack = .;
-	. += STACK_SIZE;
-	. = ALIGN(16);
-	_estack = .;
-    }
-
-    .initctx : {
-	/* Initial contents of stack. This MUST BE just after the stack. */
-	*(.initctx)
-    }
-
-    _end = .;
-
-    /DISCARD/ : { *(.comment) *(.note) }
-}
diff --git a/i386/linux_load.c b/i386/linux_load.c
deleted file mode 100644
index aa2f27e..0000000
--- a/i386/linux_load.c
+++ /dev/null
@@ -1,803 +0,0 @@
-/*
- * This file is part of FILO.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-/*
- * Linux/i386 loader
- * Supports bzImage, zImage and Image format.
- *
- * Based on work by Steve Gehlbach.
- * Portions are taken from mkelfImage.
- *
- * 2003-09 by SONE Takeshi
- */
-
-#include <libpayload.h>
-#include <libpayload-config.h>
-#include <coreboot_tables.h>
-#include <config.h>
-#include <fs.h>
-#include "context.h"
-#include "segment.h"
-
-#define DEBUG_THIS CONFIG_DEBUG_LINUXLOAD
-#include <debug.h>
-
-#define LINUX_PARAM_LOC 0x90000
-#define COMMAND_LINE_LOC 0x91000
-#define GDT_LOC 0x92000
-#define STACK_LOC 0x93000
-
-#define E820MAX	32		/* number of entries in E820MAP */
-struct e820entry {
-	unsigned long long addr;	/* start of memory segment */
-	unsigned long long size;	/* size of memory segment */
-	unsigned long type;	/* type of memory segment */
-#define E820_RAM	1
-#define E820_RESERVED	2
-#define E820_ACPI	3	/* usable as RAM once ACPI tables have been read */
-#define E820_NVS	4
-};
-
-/* The header of Linux/i386 kernel */
-struct linux_header {
-	u8 reserved1[0x1f1];	/* 0x000 */
-	u8 setup_sects;		/* 0x1f1 */
-	u16 root_flags;		/* 0x1f2 */
-	u32 syssize;		/* 0x1f4 (2.04+) */
-	u8 reserved2[2];	/* 0x1f8 */
-	u16 vid_mode;		/* 0x1fa */
-	u16 root_dev;		/* 0x1fc */
-	u16 boot_sector_magic;	/* 0x1fe */
-	/* 2.00+ */
-	u8 reserved3[2];	/* 0x200 */
-	u8 header_magic[4];	/* 0x202 */
-	u16 protocol_version;	/* 0x206 */
-	u32 realmode_swtch;	/* 0x208 */
-	u16 start_sys;		/* 0x20c */
-	u16 kver_addr;		/* 0x20e */
-	u8 type_of_loader;	/* 0x210 */
-	u8 loadflags;		/* 0x211 */
-	u16 setup_move_size;	/* 0x212 */
-	u32 code32_start;	/* 0x214 */
-	u32 ramdisk_image;	/* 0x218 */
-	u32 ramdisk_size;	/* 0x21c */
-	u8 reserved4[4];	/* 0x220 */
-	/* 2.01+ */
-	u16 heap_end_ptr;	/* 0x224 */
-	u8 reserved5[2];	/* 0x226 */
-	/* 2.02+ */
-	u32 cmd_line_ptr;	/* 0x228 */
-	/* 2.03+ */
-	u32 initrd_addr_max;	/* 0x22c */
-	/* 2.05+ */
-	u32 kernel_alignment;	/* 0x230 */
-	u8 relocatable_kernel;	/* 0x234 */
-	u8 min_alignment;	/* 0x235 (2.10+) */
-	u8 reserved6[2];	/* 0x236 */
-	/* 2.06+ */
-	u32 cmdline_size;	/* 0x238 */
-	/* 2.07+ */
-	u32 hardware_subarch;	/* 0x23c */
-	u64 hardware_subarch_data;/* 0x240 */
-	/* 2.08+ */
-	u32 payload_offset;	/* 0x248 */
-	u32 payload_length;	/* 0x24c */
-	/* 2.09+ */
-	u64 setup_data;		/* 0x250 */
-	/* 2.10+ */
-	u64 pref_address;	/* 0x258 */
-	u32 init_size;		/* 0x260 */
-} __attribute__ ((packed));
-
-/* Paramters passed to 32-bit part of Linux
- * This is another view of the structure above.. */
-struct linux_params {
-	u8 orig_x;		/* 0x00 */
-	u8 orig_y;		/* 0x01 */
-	u16 ext_mem_k;		/* 0x02 -- EXT_MEM_K sits here */
-	u16 orig_video_page;	/* 0x04 */
-	u8 orig_video_mode;	/* 0x06 */
-	u8 orig_video_cols;	/* 0x07 */
-	u16 unused2;		/* 0x08 */
-	u16 orig_video_ega_bx;	/* 0x0a */
-	u16 unused3;		/* 0x0c */
-	u8 orig_video_lines;	/* 0x0e */
-	u8 orig_video_isVGA;	/* 0x0f */
-	u16 orig_video_points;	/* 0x10 */
-
-	/* VESA graphic mode -- linear frame buffer */
-	u16 lfb_width;		/* 0x12 */
-	u16 lfb_height;		/* 0x14 */
-	u16 lfb_depth;		/* 0x16 */
-	u32 lfb_base;		/* 0x18 */
-	u32 lfb_size;		/* 0x1c */
-	u16 cl_magic;		/* 0x20 */
-#define CL_MAGIC_VALUE 0xA33F
-	u16 cl_offset;		/* 0x22 */
-	u16 lfb_linelength;	/* 0x24 */
-	u8 red_size;		/* 0x26 */
-	u8 red_pos;		/* 0x27 */
-	u8 green_size;		/* 0x28 */
-	u8 green_pos;		/* 0x29 */
-	u8 blue_size;		/* 0x2a */
-	u8 blue_pos;		/* 0x2b */
-	u8 rsvd_size;		/* 0x2c */
-	u8 rsvd_pos;		/* 0x2d */
-	u16 vesapm_seg;		/* 0x2e */
-	u16 vesapm_off;		/* 0x30 */
-	u16 pages;		/* 0x32 */
-	u8 reserved4[12];	/* 0x34 -- 0x3f reserved for future expansion */
-
-	//struct apm_bios_info apm_bios_info;   /* 0x40 */
-	u8 apm_bios_info[0x40];
-	//struct drive_info_struct drive_info;  /* 0x80 */
-	u8 drive_info[0x20];
-	//struct sys_desc_table sys_desc_table; /* 0xa0 */
-	u8 sys_desc_table[0x140];
-	u32 alt_mem_k;		/* 0x1e0 */
-	u8 reserved5[4];	/* 0x1e4 */
-	u8 e820_map_nr;		/* 0x1e8 */
-	u8 reserved6[9];	/* 0x1e9 */
-	u16 mount_root_rdonly;	/* 0x1f2 */
-	u8 reserved7[4];	/* 0x1f4 */
-	u16 ramdisk_flags;	/* 0x1f8 */
-#define RAMDISK_IMAGE_START_MASK  	0x07FF
-#define RAMDISK_PROMPT_FLAG		0x8000
-#define RAMDISK_LOAD_FLAG		0x4000
-	u8 reserved8[2];	/* 0x1fa */
-	u16 orig_root_dev;	/* 0x1fc */
-	u8 reserved9[1];	/* 0x1fe */
-	u8 aux_device_info;	/* 0x1ff */
-	u8 reserved10[2];	/* 0x200 */
-	u8 param_block_signature[4];	/* 0x202 */
-	u16 param_block_version;	/* 0x206 */
-	u8 reserved11[8];	/* 0x208 */
-	u8 loader_type;		/* 0x210 */
-#define LOADER_TYPE_LOADLIN         1
-#define LOADER_TYPE_BOOTSECT_LOADER 2
-#define LOADER_TYPE_SYSLINUX        3
-#define LOADER_TYPE_ETHERBOOT       4
-#define LOADER_TYPE_KERNEL          5
-	u8 loader_flags;	/* 0x211 */
-	u8 reserved12[2];	/* 0x212 */
-	u32 kernel_start;	/* 0x214 */
-	u32 initrd_start;	/* 0x218 */
-	u32 initrd_size;	/* 0x21c */
-	u8 reserved12_5[8];	/* 0x220 */
-	u32 cmd_line_ptr;	/* 0x228 */
-	u32 initrd_addr_max;	/* 0x22c */
-	u32 kernel_alignment;	/* 0x230 */
-	u8 relocatable_kernel;	/* 0x234 */
-	u8 reserved13[155];		/* 0x22c */
-	struct e820entry e820_map[E820MAX];	/* 0x2d0 */
-	u8 reserved16[688];	/* 0x550 */
-#define COMMAND_LINE_SIZE 256
-	/* Command line is copied here by 32-bit i386/kernel/head.S.
-	 * So I will follow the boot protocol, rather than putting it
-	 * directly here. --ts1 */
-	u8 command_line[COMMAND_LINE_SIZE];	/* 0x800 */
-	u8 reserved17[1792];	/* 0x900 - 0x1000 */
-};
-
-u64 forced_memsize;
-
-/* Load the first part the file and check if it's Linux */
-static u32 load_linux_header(struct linux_header *hdr)
-{
-	u32 kern_addr = 0;
-	int load_high;
-
-	if (file_read(hdr, sizeof *hdr) != sizeof *hdr) {
-		printf("Can't read Linux header\n");
-		return 0;
-	}
-
-	if (hdr->boot_sector_magic != 0xaa55) {
-		printf("Not a Linux kernel image\n");
-		return 0;
-	}
-
-	/* Linux is found. Print some information */
-	if (memcmp(hdr->header_magic, "HdrS", 4) != 0) {
-		/* This may be floppy disk image or something.
-		 * Perform a simple (incomplete) sanity check. */
-		if (hdr->setup_sects >= 16 || file_size() - (hdr->setup_sects << 9) >= 512 << 10) {
-			printf("This looks like a bootdisk image but not like Linux...\n");
-			return 0;
-		}
-
-		printf("Possible very old Linux");
-		/* This kernel does not even have a protocol version.
-		 * Force the value. */
-		hdr->protocol_version = 0;	/* pre-2.00 */
-	} else {
-		printf("Found Linux");
-	}
-
-	if (hdr->protocol_version >= 0x200 && hdr->kver_addr) {
-		char kver[256];
-		file_seek(hdr->kver_addr + 0x200);
-		if (file_read(kver, sizeof kver) != 0) {
-			kver[255] = 0;
-			printf(" version %s", kver);
-		}
-	}
-	debug(" (protocol %#x)", hdr->protocol_version);
-
-	load_high = 0;
-	if (hdr->protocol_version >= 0x200) {
-		debug(" (loadflags %#x)", hdr->loadflags);
-		load_high = hdr->loadflags & 1;
-	}
-
-	/* determine kernel load address */
-	if (hdr->protocol_version >= 0x20a) {
-		if (hdr->pref_address >> 32) {
-			debug(" (ignoring 64bit pref_address)");
-		} else {
-			kern_addr = hdr->pref_address;
-		}
-	}
-
-	if (hdr->protocol_version >= 0x205 && hdr->relocatable_kernel) {
-		printf(" relocatable");
-	}
-
-	if (load_high) {
-		printf(" bzImage");
-		if (kern_addr == 0)
-			kern_addr = 0x100000;
-	} else {
-		printf(" zImage or Image");
-		if (kern_addr == 0)
-			kern_addr = 0x1000;
-	}
-
-	printf(".\n");
-
-	return kern_addr;
-}
-
-/* Set up parameters for 32-bit kernel */
-static void
-init_linux_params(struct linux_params *params, struct linux_header *hdr)
-{
-	debug("Setting up paramters at %#lx\n", virt_to_phys(params));
-	memset(params, 0, sizeof *params);
-
-	/* Copy some useful values from header */
-	params->mount_root_rdonly = hdr->root_flags;
-	params->orig_root_dev = hdr->root_dev;
-
-	/* Video parameters.
-	 * This assumes we have VGA in standard 80x25 text mode,
-	 * just like our vga.c does.
-	 * Cursor position is filled later to allow some more printf's.
-	 */
-	params->orig_video_mode = 3;
-	params->orig_video_cols = 80;
-	params->orig_video_lines = 25;
-	params->orig_video_isVGA = 1;
-	params->orig_video_points = 16;
-
-	params->loader_type = 0xff;	/* Unregistered Linux loader */
-
-	/* copy alignment fields for relocatable kernels */
-	if (hdr->protocol_version >= 0x205) {
-		params->relocatable_kernel = hdr->relocatable_kernel;
-		params->kernel_alignment = hdr->kernel_alignment;
-	}
-}
-
-/* Memory map */
-static void set_memory_size(struct linux_params *params)
-{
-	int i;
-	uint64_t end;
-	u32 ramtop = 0;
-	struct e820entry *linux_map;
-	struct sysinfo_t *info = &lib_sysinfo;
-	struct memrange *filo_map;
-
-	linux_map = params->e820_map;
-	filo_map = info->memrange;
-	for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) {
-		if (i < E820MAX) {
-			/* Convert to BIOS e820 style */
-			linux_map->addr = filo_map->base;
-			linux_map->size = filo_map->size;
-			linux_map->type = filo_map->type;
-			debug("%016llx - %016llx (%d)\n", linux_map->addr,
-			      linux_map->addr + linux_map->size,
-			      linux_map->type);
-			params->e820_map_nr = i + 1;
-		}
-
-		/* Find out top of RAM. XXX This ignores hole above 1MB */
-		end = filo_map->base + filo_map->size;
-		if (end < (1ULL << 32)) { /* don't count memory above 4GB */
-			if (end > ramtop)
-				ramtop = (u32) end;
-		}
-	}
-
-	debug("ramtop=%#x\n", ramtop);
-	/* Size of memory above 1MB in KB */
-	params->alt_mem_k = (ramtop - (1 << 20)) >> 10;
-	/* old style, 64MB max */
-	if (ramtop >= (64 << 20))
-		params->ext_mem_k = (63 << 10);
-	else
-		params->ext_mem_k = params->alt_mem_k;
-	debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k,
-	      params->alt_mem_k);
-}
-
-/* Video mode */
-static void set_video_mode(struct linux_params *params)
-{
-#if CONFIG_COREBOOT_VIDEO_CONSOLE
-	/* Are we running on a framebuffer console? */
-	if (!lib_sysinfo.framebuffer)
-		return;
-
-	struct cb_framebuffer *fb = phys_to_virt(lib_sysinfo.framebuffer);
-
-	params->lfb_width = fb->x_resolution;
-	params->lfb_height = fb->y_resolution;
-	params->lfb_depth = fb->bits_per_pixel;
-	params->lfb_linelength = fb->bytes_per_line;
-	params->lfb_base = fb->physical_address;
-
-	// prolly not enough for the boot splash?!
-	params->lfb_size =
-	    (params->lfb_linelength * params->lfb_height + 65535) >> 16;
-	params->red_size = fb->red_mask_size;
-	params->red_pos = fb->red_mask_pos;
-	params->green_size = fb->green_mask_size;
-	params->green_pos = fb->green_mask_pos;
-	params->blue_size = fb->blue_mask_size;
-	params->blue_pos = fb->blue_mask_pos;
-	params->rsvd_size = fb->reserved_mask_size;
-	params->rsvd_pos = fb->reserved_mask_pos;
-#endif
-}
-
-/*
- * Parse command line
- * Some parameters, like initrd=<file>, are not passed to kernel,
- * we are responsible to process them.
- * Parameters for kernel are copied to kern_cmdline. Returns name of initrd.
- */
-static char *parse_command_line(const char *orig_cmdline,
-				char *kern_cmdline)
-{
-	const char *start, *sep, *end, *val;
-	char name[64];
-	int len;
-	int k_len;
-	int to_kern;
-	char *initrd = 0;
-	int toolong = 0;
-
-	forced_memsize = 0;
-
-	if (!orig_cmdline) {
-		*kern_cmdline = 0;
-		return 0;
-	}
-
-	k_len = 0;
-	debug("original command line: \"%s\"\n", orig_cmdline);
-	debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline));
-
-	start = orig_cmdline;
-	while (*start == ' ')
-		start++;
-	while (*start) {
-		end = strchr(start, ' ');
-		if (!end)
-			end = start + strlen(start);
-		sep = strchr(start, '=');
-		if (!sep || sep > end)
-			sep = end;
-		len = sep - start;
-		if (len >= sizeof(name))
-			len = sizeof(name) - 1;
-		memcpy(name, start, len);
-		name[len] = 0;
-
-		if (*sep == '=') {
-			val = sep + 1;
-			len = end - val;
-		} else {
-			val = 0;
-			len = 0;
-		}
-
-		/* Only initrd= and mem= are handled here. vga= is not,
-		 * which I believe is a paramter to the realmode part of Linux,
-		 * which we don't execute.
-		 */
-		if (strcmp(name, "initrd") == 0) {
-			if (!val) {
-				printf
-				    ("Missing filename to initrd parameter\n");
-			} else {
-				initrd = malloc(len + 1);
-				memcpy(initrd, val, len);
-				initrd[len] = 0;
-				debug("initrd=%s\n", initrd);
-			}
-			/* Don't pass this to kernel */
-			to_kern = 0;
-		} else if (strcmp(name, "mem") == 0) {
-			if (!val) {
-				printf
-				    ("Missing value for mem parameter\n");
-			} else {
-				forced_memsize =
-				    strtoull_with_suffix(val,
-							 (char **) &val,
-							 0);
-				if (forced_memsize == 0)
-					printf
-					    ("Invalid mem option, ignored\n");
-				if (val != end) {
-					printf
-					    ("Garbage after mem=<size>, ignored\n");
-					forced_memsize = 0;
-				}
-				debug("mem=%Lu\n", forced_memsize);
-			}
-			/* mem= is for both loader and kernel */
-			to_kern = 1;
-		} else {
-			to_kern = 1;
-		}
-
-		if (to_kern) {
-			/* Copy to kernel command line buffer */
-			if (k_len != 0)
-				kern_cmdline[k_len++] = ' ';	/* put separator */
-			len = end - start;
-			if (k_len + len >= COMMAND_LINE_SIZE) {
-				len = COMMAND_LINE_SIZE - k_len - 1;
-				if (!toolong) {
-					printf
-					    ("Kernel command line is too long; truncated to "
-					     "%d bytes\n",
-					     COMMAND_LINE_SIZE - 1);
-					toolong = 1;
-				}
-			}
-			memcpy(kern_cmdline + k_len, start, len);
-			k_len += len;
-		}
-
-		start = end;
-		while (*start == ' ')
-			start++;
-	}
-	kern_cmdline[k_len] = 0;
-	debug("kernel command line (%d bytes): \"%s\"\n", k_len,
-	      kern_cmdline);
-
-	return initrd;
-}
-
-/* Set command line location */
-static void set_command_line_loc(struct linux_params *params,
-				 struct linux_header *hdr)
-{
-	if (hdr->protocol_version >= 0x202) {
-		/* new style */
-		params->cmd_line_ptr = COMMAND_LINE_LOC;
-	} else {
-		/* old style */
-		params->cl_magic = CL_MAGIC_VALUE;
-		params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC;
-	}
-}
-
-/* Load 32-bit part of kernel */
-static int load_linux_kernel(struct linux_header *hdr, u32 kern_addr)
-{
-	u32 kern_offset, kern_size;
-
-	if (hdr->setup_sects == 0)
-		hdr->setup_sects = 4;
-	kern_offset = (hdr->setup_sects + 1) * 512;
-	file_seek(kern_offset);
-	kern_size = file_size() - kern_offset;
-	debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr,
-	      kern_size);
-
-	if (using_devsize) {
-		printf("Attempt to load up to end of device as kernel; "
-		       "specify the image size\n");
-		return 0;
-	}
-
-	printf("Loading kernel... ");
-	if (file_read(phys_to_virt(kern_addr), kern_size) != kern_size) {
-		printf("Can't read kernel\n");
-		return 0;
-	}
-	printf("ok\n");
-
-	return kern_size;
-}
-
-static int load_initrd(struct linux_header *hdr,
-		       u32 kern_end, struct linux_params *params,
-		       const char *initrd_file)
-{
-	u32 max;
-	u32 start, end, size;
-	uint64_t forced;
-	extern char _start[];
-#if 0
-	extern char _end[];
-#endif
-
-	if (!file_open(initrd_file)) {
-		printf("Can't open initrd: %s\n", initrd_file);
-		return -1;
-	}
-	if (using_devsize) {
-		printf("Attempt to load up to end of device as initrd; "
-		       "specify the image size\n");
-		return -1;
-	}
-	size = file_size();
-
-
-	/* Find out the kernel's restriction on how high the initrd can be
-	 * placed */
-	if (hdr->protocol_version >= 0x203)
-		max = hdr->initrd_addr_max;
-	else
-		max = 0x38000000;	/* Hardcoded value for older kernels */
-
-	/* FILO itself is at the top of RAM. (relocated)
-	 * So, try putting initrd just below us. */
-	end = virt_to_phys(_start - 1);
-	if (end > max)
-		end = max;
-
-	/* If "mem=" option is given, we have to put the initrd within
-	 * the specified range. */
-	if (forced_memsize) {
-		forced = forced_memsize;
-		if (forced > max)
-			forced = max;
-		/* If the "mem=" is lower, it's easy */
-		if (forced <= end)
-			end = forced;
-#if 0
-		else {
-			/* Otherwise, see if we can put it above us.
-			 * 
-			 *   This would be a good idea if we could easily find
-			 *   out where the memory hole lives.
-			 *   
-			 *   There's nothing wrong with the initrd living below
-			 *   FILO. (stepan)
-			 *
-			 *   The problems is even a 64bit kernel will live in
-			 *   32bit address space, so if you have a lot of
-			 *   memory and specify mem=xG with x>4, the maximum
-			 *   allowed initrd address (2.6.x sets this to
-			 *   0xffffffff) will be used for the high limit.
-			 *   (offset 22c in vmlinuz)
-			 *
-			 *   you might want to enable this if you limit memory
-			 *   with mem=yG with y<4.
-			 */
-			if (virt_to_phys(_end) + size <= forced)
-				end = forced;	/* Ok */
-		}
-#endif
-	}
-
-	start = end - size;
-	start &= ~0xfff;	/* page align */
-	end = start + size;
-
-	debug("start=%#x end=%#x\n", start, end);
-
-	if (start < kern_end) {
-		printf("Initrd is too big to fit in memory\n");
-		return -1;
-	}
-
-	printf("Loading initrd... ");
-	if (file_read(phys_to_virt(start), size) != size) {
-		printf("Can't read initrd\n");
-		return -1;
-	}
-	printf("ok\n");
-
-	params->initrd_start = start;
-	params->initrd_size = size;
-
-	return 0;
-}
-
-static void hardware_setup(void)
-{
-	/* Disable nmi */
-	outb(0x80, 0x70);
-
-	/* Make sure any coprocessor is properly reset.. */
-	outb(0, 0xf0);
-	outb(0, 0xf1);
-
-	/* we're getting screwed again and again by this problem of the 8259.
-	 * so we're going to leave this lying around for inclusion into crt0.S
-	 * on an as-needed basis. 
-	 *
-	 * well, that went ok, I hope. Now we have to reprogram the interrupts
-	 * :-(
-	 * we put them right after the intel-reserved hardware interrupts, at
-	 * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
-	 * messed this up with the original PC, and they haven't been able to
-	 * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
-	 * which is used for the internal hardware interrupts as well. We just
-	 * have to reprogram the 8259's, and it isn't fun.
-	 */
-
-	outb(0x11, 0x20);	/* initialization sequence to 8259A-1 */
-	outb(0x11, 0xA0);	/* and to 8259A-2 */
-
-	outb(0x20, 0x21);	/* start of hardware int's (0x20) */
-	outb(0x28, 0xA1);	/* start of hardware int's 2 (0x28) */
-
-	outb(0x04, 0x21);	/* 8259-1 is master */
-	outb(0x02, 0xA1);	/* 8259-2 is slave */
-
-	outb(0x01, 0x21);	/* 8086 mode for both */
-	outb(0x01, 0xA1);
-
-	outb(0xFF, 0xA1);	/* mask off all interrupts for now */
-	outb(0xFB, 0x21);	/* mask all irq's but irq2 which is cascaded */
-}
-
-/* Start Linux */
-static int start_linux(u32 kern_addr, struct linux_params *params)
-{
-	struct segment_desc *linux_gdt;
-	struct context *ctx;
-#ifdef CONFIG_VGA_VIDEO_CONSOLE
-	unsigned int cursor_x, cursor_y, cursor_en;
-#endif
-#ifdef CONFIG_PCMCIA_CF
-	unsigned char *cf_bar;
-	int i;
-#endif
-
-	ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0);
-
-	/* Linux expects GDT being in low memory */
-	linux_gdt = phys_to_virt(GDT_LOC);
-	memset(linux_gdt, 0, 13 * sizeof(struct segment_desc));
-	/* Normal kernel code/data segments */
-	linux_gdt[2] = gdt[FLAT_CODE];
-	linux_gdt[3] = gdt[FLAT_DATA];
-	/* 2.6 kernel uses 12 and 13, but head.S uses backward-compatible
-	 * segments (2 and 3), so it SHOULD not be a problem. 
-	 * However, some distro kernels (eg. RH9) with backported threading 
-	 * patch use 12 and 13 also when booting... */
-	linux_gdt[12] = gdt[FLAT_CODE];
-	linux_gdt[13] = gdt[FLAT_DATA];
-	ctx->gdt_base = GDT_LOC;
-	ctx->gdt_limit = 14 * 8 - 1;
-	ctx->cs = 0x10;
-	ctx->ds = 0x18;
-	ctx->es = 0x18;
-	ctx->fs = 0x18;
-	ctx->gs = 0x18;
-	ctx->ss = 0x18;
-
-	/* Parameter location */
-	ctx->esi = virt_to_phys(params);
-
-	/* Entry point */
-	ctx->eip = kern_addr;
-
-	/* set this field in any case to support relocatable kernels */
-	params->kernel_start = kern_addr;
-
-	debug("EIP=%#x\n", kern_addr);
-	printf("Jumping to entry point...\n");
-
-#ifdef CONFIG_VGA_VIDEO_CONSOLE
-	/* Update VGA cursor position.
-	 * This must be here because the printf changes the value! */
-	video_console_get_cursor(&cursor_x, &cursor_y, &cursor_en);
-	params->orig_x = cursor_x;
-	params->orig_y = cursor_y;
-#endif
-
-#ifdef CONFIG_PCMCIA_CF
-	cf_bar = phys_to_virt(pci_read_config32(PCI_DEV(0, 0xa, 1), 0x10));
-	for (i = 0x836; i < 0x840; i++) {
-		cf_bar[i] = 0;
-	}
-#endif
-	/* Go... */
-	ctx = switch_to(ctx);
-
-	/* It's impossible but... */
-	printf("Returned with EAX=%#x\n", ctx->eax);
-
-	return ctx->eax;
-}
-
-int linux_load(const char *file, const char *cmdline)
-{
-	struct linux_header hdr;
-	struct linux_params *params;
-	u32 kern_addr, kern_size;
-	char *initrd_file = 0;
-
-	if (!file_open(file))
-		return -1;
-
-	kern_addr = load_linux_header(&hdr);
-	if (kern_addr == 0) {
-		file_close();
-		return LOADER_NOT_SUPPORT;
-	}
-
-	params = phys_to_virt(LINUX_PARAM_LOC);
-	init_linux_params(params, &hdr);
-	set_memory_size(params);
-	set_video_mode(params);
-	initrd_file =
-	    parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC));
-	set_command_line_loc(params, &hdr);
-
-	kern_size = load_linux_kernel(&hdr, kern_addr);
-	if (kern_size == 0) {
-		if (initrd_file)
-			free(initrd_file);
-		file_close();
-		return -1;
-	}
-
-	if (initrd_file) {
-		if (load_initrd(&hdr, kern_addr + kern_size,
-					params, initrd_file) != 0) {
-			free(initrd_file);
-			file_close();
-			return -1;
-		}
-		free(initrd_file);
-	}
-
-	file_close();
-#if defined(CONFIG_USB)
-	usb_exit();
-#endif
-
-	hardware_setup();
-
-	start_linux(kern_addr, params);
-	return 0;
-}
diff --git a/i386/segment.c b/i386/segment.c
deleted file mode 100644
index ea38096..0000000
--- a/i386/segment.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * This file is part of FILO.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-
-/* Segmentation of the i386 architecture.
- *
- * 2003-07 by SONE Takeshi
- */
-
-#include <libpayload.h>
-#include <coreboot_tables.h>
-#include <config.h>
-#include "segment.h"
-
-#define DEBUG_THIS CONFIG_DEBUG_SEGMENT
-#include <debug.h>
-
-/* i386 lgdt argument */
-struct gdtarg {
-	unsigned short limit;
-	unsigned int base;
-} __attribute__ ((packed));
-
-/* How far the virtual address (used in C) is different from physical 
- * address. Since we start in flat mode, the initial value is zero. */
-unsigned long virt_offset = 0;
-
-/* GDT, the global descriptor table */
-struct segment_desc gdt[NUM_SEG] = {
-	/* 0x00: null segment */
-	{0, 0, 0, 0, 0, 0},
-	/* 0x08: flat code segment */
-	{0xffff, 0, 0, 0x9f, 0xcf, 0},
-	/* 0x10: flat data segment */
-	{0xffff, 0, 0, 0x93, 0xcf, 0},
-	/* 0x18: code segment for relocated execution */
-	{0xffff, 0, 0, 0x9f, 0xcf, 0},
-	/* 0x20: data segment for relocated execution */
-	{0xffff, 0, 0, 0x93, 0xcf, 0},
-};
-
-extern char _start[], _end[];
-
-void relocate(void)
-{
-	int i;
-	unsigned long prog_addr;
-	unsigned long prog_size;
-	unsigned long addr, new_base;
-	unsigned long long segsize;
-	unsigned long new_offset;
-	unsigned d0, d1, d2;
-	struct gdtarg gdtarg;
-	struct sysinfo_t *info = &lib_sysinfo;
-#define ALIGNMENT 0x1000
-
-	prog_addr = virt_to_phys(&_start);
-	prog_size = virt_to_phys(&_end) - virt_to_phys(&_start);
-	debug("Current location: %#lx-%#lx\n", prog_addr,
-	      prog_addr + prog_size - 1);
-
-	new_base = 0;
-	for (i = 0; i < info->n_memranges; i++) {
-		if (info->memrange[i].type != CB_MEM_RAM)
-			continue;
-		if (info->memrange[i].base >= 1ULL << 32)
-			continue;
-		segsize = info->memrange[i].size;
-		if (info->memrange[i].base + segsize > 1ULL << 32)
-			segsize = (1ULL << 32) - info->memrange[i].base;
-		if (segsize < prog_size + ALIGNMENT)
-			continue;
-		addr = info->memrange[i].base + segsize - prog_size;
-		addr &= ~(ALIGNMENT - 1);
-		if (addr >= prog_addr && addr < prog_addr + prog_size)
-			continue;
-		if (prog_addr >= addr && prog_addr < addr + prog_size)
-			continue;
-		if (addr > new_base)
-			new_base = addr;
-	}
-	if (new_base == 0) {
-		printf("Can't find address to relocate\n");
-		return;
-	}
-
-	debug("Relocating to %#lx-%#lx... ",
-	      new_base, new_base + prog_size - 1);
-
-	/* New virtual address offset */
-	new_offset = new_base - (unsigned long) &_start;
-
-	/* Tweak the GDT */
-	gdt[RELOC_CODE].base_0 = (unsigned short) new_offset;
-	gdt[RELOC_CODE].base_16 = (unsigned char) (new_offset >> 16);
-	gdt[RELOC_CODE].base_24 = (unsigned char) (new_offset >> 24);
-	gdt[RELOC_DATA].base_0 = (unsigned short) new_offset;
-	gdt[RELOC_DATA].base_16 = (unsigned char) (new_offset >> 16);
-	gdt[RELOC_DATA].base_24 = (unsigned char) (new_offset >> 24);
-
-	/* Load new GDT and reload segments */
-	gdtarg.base = new_offset + (unsigned long) gdt;
-	gdtarg.limit = GDT_LIMIT;
-	__asm__ __volatile__("rep; movsb\n\t"	/* copy everything */
-			     "lgdt %3\n\t"
-			     "ljmp %4, $1f\n1:\t"
-			     "movw %5, %%ds\n\t"
-			     "movw %5, %%es\n\t"
-			     "movw %5, %%fs\n\t"
-			     "movw %5, %%gs\n\t"
-			     "movw %5, %%ss\n":"=&S"(d0), "=&D"(d1),
-			     "=&c"(d2)
-			     :"m"(gdtarg), "n"(RELOC_CS),
-			     "q"((unsigned short) RELOC_DS), "0"(&_start),
-			     "1"(new_base), "2"(prog_size));
-
-	virt_offset = new_offset;	// for FILO
-	virtual_offset = new_offset;	// for libpayload
-
-	debug("ok\n");
-}
diff --git a/i386/segment.h b/i386/segment.h
deleted file mode 100644
index 43130e6..0000000
--- a/i386/segment.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * This file is part of FILO.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-
-/* Segment indexes. Must match the gdt definition in segment.c. */
-enum {
-	NULL_SEG,
-	FLAT_CODE,
-	FLAT_DATA,
-	RELOC_CODE,
-	RELOC_DATA,
-	NUM_SEG,
-};
-
-/* Values for segment selector register */
-#define FLAT_CS (FLAT_CODE << 3)
-#define FLAT_DS (FLAT_DATA << 3)
-#define RELOC_CS (RELOC_CODE << 3)
-#define RELOC_DS (RELOC_DATA << 3)
-
-/* i386 segment descriptor */
-struct segment_desc {
-	unsigned short limit_0;
-	unsigned short base_0;
-	unsigned char base_16;
-	unsigned char types;
-	unsigned char flags;
-	unsigned char base_24;
-};
-
-extern struct segment_desc gdt[NUM_SEG];
-
-#define GDT_LIMIT ((NUM_SEG << 3) - 1)
diff --git a/i386/switch.S b/i386/switch.S
deleted file mode 100644
index 50f5f71..0000000
--- a/i386/switch.S
+++ /dev/null
@@ -1,116 +0,0 @@
-	.globl	entry, __switch_context, __exit_context, halt
-
-	.section ".boot", "xa"
-	.align	4
-
-/*
- * Entry point
- * We start execution from here.
- * It is assumed that CPU is in 32-bit protected mode and 
- * all segments are 4GB and base zero (flat model).
- */
-entry:
-	/* Save boot context and switch to our main context.
-	 * Main context is statically defined in C.
-	 */
-	pushl	%cs
-	call	__switch_context
-
-	/* We get here when the main context switches back to
-	 * the boot context.
-	 * Return to previous bootloader.
-	 */
-	ret
-
-/*
- * Switch execution context
- * This saves registers, segments, and GDT in the stack, then
- * switches the stack, and restores everything from the new stack.
- * This function takes no argument. New stack pointer is
- * taken from global variable __context, and old stack pointer
- * is also saved to __context. This way we can just jump to 
- * this routine to get back to the original context.
- *
- * Call this routine with lcall or pushl %cs; call.
- */
-__switch_context:
-	/* Save everything in current stack */
-	pushfl		    /* 56 */
-	pushl	%ds	    /* 52 */
-	pushl	%es	    /* 48 */
-	pushl	%fs	    /* 44 */
-	pushl	%gs	    /* 40 */
-	pushal		    /* 8 */
-	subl	$8, %esp
-	movw	%ss, (%esp) /* 0 */
-	sgdt	2(%esp)	    /* 2 */
-
-#if 0
-	/* Swap %cs and %eip on the stack, so lret will work */
-	movl	60(%esp), %eax
-	xchgl	%eax, 64(%esp)
-	movl	%eax, 60(%esp)
-#endif
-	
-	/* At this point we don't know if we are on flat segment
-	 * or relocated. So compute the address offset from %eip.
-	 * Assuming CS.base==DS.base==SS.base.
-	 */
-	call	1f
-1:	popl	%ebx
-	subl	$1b, %ebx
-
-	/* Interrupts are not allowed... */
-	cli
-	
-	/* Current context pointer is our stack pointer */
-	movl	%esp, %esi
-
-	/* Normalize the ctx pointer */
-	subl	%ebx, %esi
-
-	/* Swap it with new value */
-	xchgl	%esi, __context(%ebx)
-
-	/* Adjust new ctx pointer for current address offset */
-	addl	%ebx, %esi
-
-	/* Load new %ss and %esp to temporary */
-	movzwl	(%esi), %edx
-	movl	20(%esi), %eax
-
-	/* Load new GDT */
-	lgdt	2(%esi)
-
-	/* Load new stack segment with new GDT */
-	movl	%edx, %ss
-
-	/* Set new stack pointer, but we have to adjust it because
-	 * pushal saves %esp value before pushal, and we want the value
-	 * after pushal.
-	 */
-	leal	-32(%eax), %esp
-
-	/* Load the rest from new stack */
-	popal
-	popl	%gs
-	popl	%fs
-	popl	%es
-	popl	%ds
-	popfl
-
-	/* Finally, load new %cs and %eip */
-	lret
-
-__exit_context:
-	/* Get back to the original context */
-	pushl	%cs
-	call	__switch_context
-
-	/* We get here if the other context attempt to switch to this
-	 * dead context. This should not happen. */
-
-halt:
-	cli
-	hlt
-	jmp	halt
diff --git a/i386/sys_info.c b/i386/sys_info.c
deleted file mode 100644
index 8e7d14e..0000000
--- a/i386/sys_info.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * This file is part of FILO.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-#include <libpayload.h>
-#include <config.h>
-#include <sys_info.h>
-#include "context.h"
-#define DEBUG_THIS CONFIG_DEBUG_SYS_INFO
-#include <debug.h>
-
-void collect_sys_info(struct sys_info *info)
-{
-	/* Pick up paramters given by bootloader to us */
-	info->boot_type = boot_ctx->eax;
-	info->boot_data = boot_ctx->ebx;
-	info->boot_arg = boot_ctx->param[0];
-	debug("boot EAX = %#lx\n", info->boot_type);
-	debug("boot EBX = %#lx\n", info->boot_data);
-	debug("boot arg = %#lx\n", info->boot_arg);
-}
diff --git a/i386/timer.c b/i386/timer.c
deleted file mode 100644
index 739c9ed..0000000
--- a/i386/timer.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * This file is part of FILO.
- *
- * (C) 2004-2008 coresystems GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-#include <libpayload.h>
-#include <arch/rdtsc.h>
-#include <arch/timer.h>
-
-u64 currticks(void)
-{
-	/* Read the Time Stamp Counter */
-	return  rdtsc();
-}
-
-int getrtsecs (void)
-{
-	u64 t;
-	t=currticks();
-	t=t/(TICKS_PER_SEC);
-	return (int)t;
-}
-
-
diff --git a/i386/wince_load.c b/i386/wince_load.c
deleted file mode 100644
index 993815f..0000000
--- a/i386/wince_load.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*******************************************************************************
- *
- *	WindowsCE/i386 loader 
- *
- *	Copyright 2006 Andrei Birjukov <andrei.birjukov at artecdesign.ee> and
- *	Artec Design LLC http://www.artecdesign.ee
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	This program is distributed in the hope that 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.
- *
- *	You should have received a copy of the GNU General Public License
- *	along with this program; if not, write to the Free Software
- *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ******************************************************************************/
-
-#include <libpayload.h>
-#include <lib.h>
-#include <fs.h>
-#include <arch/io.h>
-#include "context.h"
-#include "segment.h"
-
-#define DEBUG_THIS DEBUG_WINCELOAD
-#include <debug.h>
-
-#define BOOTARG_PTR_LOCATION	0x001FFFFC
-#define BOOTARG_LOCATION		0x001FFF00
-#define BOOTARG_SIGNATURE		0x544F4F42
-#define BOOTARG_VERSION_SIG		0x12345678
-#define BOOTARG_MAJOR_VER		1
-#define BOOTARG_MINOR_VER		0
-
-#define MAX_DEV_NAMELEN			16	// Should match EDBG_MAX_DEV_NAMELEN.
-
-#define LDRFL_USE_EDBG			0x0001	// Set to attempt to use debug Ethernet
-// The following two flags are only looked at if LDRFL_USE_EDBG is set
-#define LDRFL_ADDR_VALID		0x0002	// Set if EdbgAddr field is valid
-#define LDRFL_JUMPIMG			0x0004	// If set, don't communicate with eshell to get
-// The following flag is only used for backup FLASH operation
-#define LDRFL_FLASH_BACKUP		0x80
-// configuration, use ucEshellFlags field.
-// Use this constant in EdbgIRQ to specify that EDBG should run without an interrupt.
-#define EDBG_IRQ_NONE			0xFF
-
-#define EDBG_ADAPTER_DEFAULT	2
-#define EDBG_ADAPTER_RTL8139	4
-
-#define PSIZE					(1500)	// Max Packet Size
-#define DSIZE					(PSIZE+12)
-#define BIN_HDRSIG_SIZE			7
-
-#define ROM_SIGNATURE_OFFSET	0x40	// Offset from the image's physfirst address to the ROM signature.
-#define ROM_SIGNATURE			0x43454345
-#define ROM_TOC_POINTER_OFFSET	0x44	// Offset from the image's physfirst address to the TOC pointer.
-#define ROM_TOC_OFFSET_OFFSET	0x48	// Offset from the image's physfirst address to the TOC offset (from physfirst).
-
-#define GDT_LOC					0x92000
-#define STACK_LOC				0x93000
-
-typedef struct _EDBG_ADDR {
-	u32 dwIP;
-	u16 wMAC[3];
-	u16 wPort;
-} EDBG_ADDR;
-
-typedef struct _BOOT_ARGS {
-	u8 ucVideoMode;
-	u8 ucComPort;
-	u8 ucBaudDivisor;
-	u8 ucPCIConfigType;
-	u32 dwSig;
-	u32 dwLen;
-	u8 ucLoaderFlags;
-	u8 ucEshellFlags;
-	u8 ucEdbgAdapterType;
-	u8 ucEdbgIRQ;
-	u32 dwEdbgBaseAddr;
-	u32 dwEdbgDebugZone;
-	EDBG_ADDR EdbgAddr;
-	EDBG_ADDR EshellHostAddr;
-	EDBG_ADDR DbgHostAddr;
-	EDBG_ADDR CeshHostAddr;
-	EDBG_ADDR KdbgHostAddr;
-	u32 DHCPLeaseTime;
-	u16 EdbgFlags;
-	u16 KitlTransport;
-	u32 dwEBootFlag;
-	u32 dwEBootAddr;
-	u32 dwLaunchAddr;
-	u32 pvFlatFrameBuffer;
-	u16 vesaMode;
-	u16 cxDisplayScreen;
-	u16 cyDisplayScreen;
-	u16 cxPhysicalScreen;
-	u16 cyPhysicalScreen;
-	u16 cbScanLineLength;
-	u16 bppScreen;
-	u8 RedMaskSize;
-	u8 RedMaskPosition;
-	u8 GreenMaskSize;
-	u8 GreenMaskPosition;
-	u8 BlueMaskSize;
-	u8 BlueMaskPosition;
-	u32 dwVersionSig;
-	u16 MajorVersion;
-	u16 MinorVersion;
-	u8 szDeviceNameRoot[MAX_DEV_NAMELEN];
-	u32 dwImgStoreAddr;
-	u32 dwImgLoadAddr;
-	u32 dwImgLength;
-	u8 NANDBootFlags;
-	u8 NANDBusNumber;
-	u32 NANDSlotNumber;
-} BOOT_ARGS;
-
-typedef struct _ROMHDR {
-	u32 dllfirst;
-	u32 dlllast;
-	u32 physfirst;
-	u32 physlast;
-	u32 nummods;
-	u32 ulRAMStart;
-	u32 ulRAMFree;
-	u32 ulRAMEnd;
-	u32 ulCopyEntries;
-	u32 ulCopyOffset;
-	u32 ulProfileLen;
-	u32 ulProfileOffset;
-	u32 numfiles;
-	u32 ulKernelFlags;
-	u32 ulFSRamPercent;
-	u32 ulDrivglobStart;
-	u32 ulDrivglobLen;
-	u16 usCPUType;
-	u16 usMiscFlags;
-	void *pExtensions;
-	u32 ulTrackingStart;
-	u32 ulTrackingLen;
-} ROMHDR;
-
-typedef struct _SEGMENT_INFO {
-	u32 segAddr;
-	u32 segSize;
-	u32 checkSum;
-} SEGMENT_INFO;
-
-typedef void (*PFN_LAUNCH) ();	// WinCE launch function proto
-
-static u8 g_ceSignature[] = { 'B', '0', '0', '0', 'F', 'F', '\n' };
-static void **g_ppBootArgs = NULL;
-BOOT_ARGS *g_pBootArgs = NULL;
-static ROMHDR *pROMHeader = NULL;
-
-static u32 g_imageStart = 0;
-static u32 g_imageSize = 0;
-static u32 g_romOffset = 0;
-
-static int verifyCheckSum(u8 * pData, int nSize, u32 checkSum)
-{
-	// check the CRC
-	u32 crc = 0;
-	int i;
-
-	for (i = 0; i < nSize; i++)
-		crc += *pData++;
-
-	return (crc == checkSum);
-}
-
-int wince_launch(u32 imageStart, u32 imageSize,
-		 u32 entryPoint, ROMHDR * pRomHdr)
-{
-	struct segment_desc *wince_gdt;
-	struct context *ctx;
-
-	debug("start Windows CE from address 0x%x, image loaded 0x%x,%d\n",
-	      entryPoint, imageStart, imageSize);
-
-	// initialize new stack
-	ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0);
-
-	// initialize GDT in low memory
-	wince_gdt = phys_to_virt(GDT_LOC);
-	memset(wince_gdt, 0, 13 * sizeof(struct segment_desc));
-	// flat kernel code/data segments
-	wince_gdt[2] = gdt[FLAT_CODE];
-	wince_gdt[3] = gdt[FLAT_DATA];
-
-	wince_gdt[12] = gdt[FLAT_CODE];
-	wince_gdt[13] = gdt[FLAT_DATA];
-	ctx->gdt_base = GDT_LOC;
-	ctx->gdt_limit = 14 * 8 - 1;
-	ctx->cs = 0x10;
-	ctx->ds = 0x18;
-	ctx->es = 0x18;
-	ctx->fs = 0x18;
-	ctx->gs = 0x18;
-	ctx->ss = 0x18;
-
-	// kernel entry point
-	ctx->eip = entryPoint;
-
-	printf("Launching Windows CE...\n");
-
-	// go...!
-	ctx = switch_to(ctx);
-
-	// may never return here
-	printf("returned with eax=%#x\n", ctx->eax);
-	return ctx->eax;
-}
-
-void wince_init_bootarg(u32 entryPoint)
-{
-	// init the BOOT_ARGS pointer at the known address
-	g_ppBootArgs = phys_to_virt(BOOTARG_PTR_LOCATION);
-	*g_ppBootArgs = (void *) BOOTARG_LOCATION;
-
-	// keep our BOOT_ARGS somewhere in a dry dark place 
-	g_pBootArgs = phys_to_virt(BOOTARG_LOCATION);
-
-	debug("BOOT_ARGS at addr 0x%x, pointer at 0x%x [%x]\n",
-	      (unsigned int) *g_ppBootArgs, BOOTARG_PTR_LOCATION,
-	      (unsigned int) g_ppBootArgs);
-
-	memset(g_pBootArgs, 0, sizeof(BOOT_ARGS));
-
-	// this data was copied from WinCE EDBG boot args       
-	g_pBootArgs->ucEdbgAdapterType = EDBG_ADAPTER_DEFAULT;
-	// use the first PCI NIC available
-	g_pBootArgs->ucEdbgIRQ = 0;
-	g_pBootArgs->dwEdbgBaseAddr = 0;
-
-	// set the KITL device name to something adequate
-	strcpy((char *) g_pBootArgs->szDeviceNameRoot, "FILO");
-
-	g_pBootArgs->dwSig = BOOTARG_SIGNATURE;
-	g_pBootArgs->dwLen = sizeof(BOOT_ARGS);
-	g_pBootArgs->dwVersionSig = BOOTARG_VERSION_SIG;
-	g_pBootArgs->MajorVersion = BOOTARG_MAJOR_VER;
-	g_pBootArgs->MinorVersion = BOOTARG_MINOR_VER;
-
-/*
-	g_pBootArgs->ucVideoMode = 255;
-	g_pBootArgs->ucComPort = 1;
-	g_pBootArgs->ucBaudDivisor = 3;
-	g_pBootArgs->ucPCIConfigType = 1;
-	g_pBootArgs->ucLoaderFlags = 0x7;
-*/
-
-	debug("Boot arguments initialized at 0x%x\n",
-	      (unsigned int) *g_ppBootArgs);
-}
-
-int wince_load(const char *file, const char *cmdline)
-{
-	u8 signBuf[BIN_HDRSIG_SIZE], *pDest = NULL;
-	SEGMENT_INFO segInfo;
-	u32 totalBytes = 0;
-
-	if (!file_open(file)) {
-		printf("Failed opening image file: %s\n", file);
-		return LOADER_NOT_SUPPORT;
-	}
-	// read the image signature
-	file_read((void *) signBuf, BIN_HDRSIG_SIZE);
-
-	if (memcmp(signBuf, g_ceSignature, BIN_HDRSIG_SIZE)) {
-		printf("Bad or unknown Windows CE image signature\n");
-		file_close();
-		return LOADER_NOT_SUPPORT;
-	}
-	// now read image start address and size        
-	file_read((void *) &g_imageStart, sizeof(u32));
-	file_read((void *) &g_imageSize, sizeof(u32));
-
-	if (!g_imageStart || !g_imageSize)	// sanity check
-	{
-		printf("Invalid image descriptors\n");
-		file_close();
-		return LOADER_NOT_SUPPORT;
-	}
-
-	printf("Windows CE BIN image, start 0x%x, length %d\n",
-	       g_imageStart, g_imageSize);
-
-	// main image reading loop      
-	while (1) {
-		// first grab the segment descriptor
-		if (file_read(&segInfo, sizeof(SEGMENT_INFO)) <
-		    sizeof(SEGMENT_INFO)) {
-			printf ("\nFailed reading image segment descriptor\n");
-			file_close();
-			return LOADER_NOT_SUPPORT;
-		}
-
-		totalBytes += sizeof(SEGMENT_INFO);	// update data counter
-		printf("#");	// that's a progress bar :)
-
-		// now check if that's the last one
-		if (segInfo.segAddr == 0 && segInfo.checkSum == 0)
-			break;
-
-		// map segment address to current address space
-		pDest = (u8 *) phys_to_virt(segInfo.segAddr);
-		debug("fetched segment address 0x%x [%x] size %d\n",
-		      segInfo.segAddr, (unsigned int) pDest,
-		      segInfo.segSize);
-
-		// read the image segment data from VFS
-		if (file_read((void *) pDest, segInfo.segSize) <
-		    segInfo.segSize) {
-			printf ("\nFailed reading image segment data (address 0x%x, size %d)\n",
-			     segInfo.segAddr, segInfo.segSize);
-			file_close();
-			return LOADER_NOT_SUPPORT;
-		}
-		// check the data integrity
-		if (!verifyCheckSum
-		    (pDest, segInfo.segSize, segInfo.checkSum)) {
-			printf ("\nFailed verifying segment checksum at address 0x%x, size %d\n",
-			     (unsigned int) pDest, segInfo.segSize);
-			file_close();
-			return LOADER_NOT_SUPPORT;
-		}
-		// Look for ROMHDR to compute ROM offset.  NOTE: romimage guarantees that the record containing
-		// the TOC signature and pointer will always come before the record that contains the ROMHDR contents.
-
-		if (segInfo.segSize == sizeof(ROMHDR) && 
-				(*(u32 *) phys_to_virt(g_imageStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE)) {
-			u32 tempOffset =
-			    (segInfo.segAddr -
-			     *(u32 *) phys_to_virt(g_imageStart +
-							ROM_SIGNATURE_OFFSET
-							+ sizeof(long)));
-			ROMHDR *pROMhdr = (ROMHDR *) pDest;
-
-			// check to make sure this record really contains the ROMHDR.
-			if ((pROMhdr->physfirst == (g_imageStart - tempOffset)) && 
-					(pROMhdr->physlast == (g_imageStart - tempOffset + g_imageSize)) &&
-			    		(u32) (((pROMhdr-> dllfirst << 16) & 0xffff0000) <= pROMhdr->dlllast) &&
-			    		(u32) (((pROMhdr-> dllfirst << 16) & 0x0000ffff) <= pROMhdr->dlllast)) {
-				g_romOffset = tempOffset;
-				debug("\nROM offset = 0x%x\n", g_romOffset);
-			}
-		}
-
-		totalBytes += segInfo.segSize;	// update data counter
-	}
-
-	// we should have moved all image segments to RAM by now
-	printf("\nOS image loaded.\n");
-
-	// check for pTOC signature ("CECE") here, after image in place
-	if (*(u32 *) phys_to_virt(g_imageStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE) {
-		// a pointer to the ROMHDR structure lives just past the ROM_SIGNATURE (which is a longword value).  Note that
-		// this pointer is remapped since it might be a flash address (image destined for flash), but is actually cached
-		// in RAM.
-
-		u32 cacheAddress = *(u32 *) phys_to_virt(g_imageStart + ROM_SIGNATURE_OFFSET + sizeof(u32));
-
-		pROMHeader =
-		    (ROMHDR *) phys_to_virt(cacheAddress + g_romOffset);
-		debug("ROMHDR at address 0x%xh\n",
-		      cacheAddress + g_romOffset);
-	}
-
-	file_close();
-
-	// prepare the boot arguments
-	// note that the last segment size carries the launch address 
-	wince_init_bootarg(segInfo.segSize);
-
-	// finally, call the generic launch() function
-	return wince_launch(g_imageStart, g_imageSize, segInfo.segSize,
-			    pROMHeader);
-}
diff --git a/x86/Makefile.inc b/x86/Makefile.inc
new file mode 100644
index 0000000..f01ca72
--- /dev/null
+++ b/x86/Makefile.inc
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2008 by coresystems GmbH 
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+TARGETS-$(CONFIG_TARGET_I386) += x86/context.o x86/switch.S.o x86/segment.o
+TARGETS-$(CONFIG_TARGET_I386) += x86/timer.o x86/sys_info.o
+TARGETS-$(CONFIG_LINUX_LOADER) += x86/linux_load.o
+TARGETS-$(CONFIG_WINCE_LOADER) += x86/wince_load.o
+TARGETS-$(CONFIG_ARTEC_BOOT) += x86/artecboot.o
diff --git a/x86/artecboot.c b/x86/artecboot.c
new file mode 100644
index 0000000..697a05b
--- /dev/null
+++ b/x86/artecboot.c
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ *
+ *	FILO Artecboot loader, enables multiboot through custom header 
+ *
+ *	Copyright 2006 Andrei Birjukov <andrei.birjukov at artecdesign.ee> and
+ *	Artec Design LLC http://www.artecdesign.ee
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that 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.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ******************************************************************************/
+
+#include <libpayload.h>
+#include <config.h>
+#include <fs.h>
+#include "artecboot.h"
+#include "../fs/filesys.h"
+
+#define DEBUG_THIS CONFIG_DEBUG_ARTECBOOT
+#include <debug.h>
+
+static ARTECBOOT_HEADER bootHdr;
+
+int artecboot_load(const char *file, const char *cmdline)
+{
+	int i;
+
+	printf("Starting the Artecboot loader...\n");
+	// clear the boot header
+	memset(&bootHdr, 0, sizeof(bootHdr));
+	
+	// try opening the boot parameter file
+	if (!file_open(file))
+	{
+		printf("Boot error: failed to open image file: %s\n", file);
+		return LOADER_NOT_SUPPORT;
+	}
+
+	file_seek(0);	// seek to the beginning of the parameter file
+	
+	// now read out the boot header
+	if(file_read(&bootHdr, sizeof(ARTECBOOT_HEADER)) != sizeof(ARTECBOOT_HEADER))
+	{
+		printf("Boot error: failed reading the boot image header\n");
+		file_close();
+		return LOADER_NOT_SUPPORT;
+	}
+	
+	// check whether the parameter data is valid at all
+	if(bootHdr.magicHeader != ARTECBOOT_HEADER_MAGIC)
+	{
+		debug("No Artecboot signature found, aborting\n");
+		file_close();
+		return LOADER_NOT_SUPPORT;
+	}
+
+	// check the version number
+	if(bootHdr.bootVersion > CURRENT_VERSION)
+	{
+		printf("Boot error: incompatible version number: %x\n", bootHdr.bootVersion);
+		file_close();
+		return LOADER_NOT_SUPPORT;
+	}
+	
+	// shall we replace the command line?
+	if(bootHdr.bitFlags & FLAG_CMDLINE)
+	{
+		// check the command line and wipe out all junk
+		for(i=0; bootHdr.cmdLine[i] != 0; i++)
+			switch(bootHdr.cmdLine[i])
+			{
+			case '\n':
+			case '\r':
+				bootHdr.cmdLine[i] = ' ';
+				break;
+			default:
+				// do nothing
+				break;
+			}
+	}
+	else if(cmdline) 
+		strncpy(bootHdr.cmdLine, cmdline, sizeof(bootHdr.cmdLine));
+	
+	// proceed basing on the specified OS type
+	switch(bootHdr.osType)
+	{
+	case OS_LINUX:
+		if(bootHdr.bitFlags & FLAG_INITRD)
+		{
+			char initrdParam[100];
+			if(bootHdr.bitFlags & FLAG_FILESYSTEM)
+			{
+				// we are using a real filesystem, so format the initrd file as usually
+				sprintf(initrdParam, " initrd=%s", bootHdr.initrdFile); 
+			}
+			else
+			{
+				// we are using a 'fake' filesystem, so use the image offset
+				sprintf(initrdParam, " initrd=%s at 0x%x,0x%x",
+						dev_name, bootHdr.initrdStart, bootHdr.initrdSize);
+			}			
+
+			debug("adding initrd parameter: %s\n", initrdParam); 
+			strncat(bootHdr.cmdLine, initrdParam, sizeof(bootHdr.cmdLine));
+		}
+	
+		printf("Starting Linux loader...\n");
+
+		// if using a real filesystem, load the kernel image from a specified file		
+		if(bootHdr.bitFlags & FLAG_FILESYSTEM)
+			linux_load(bootHdr.kernelFile, bootHdr.cmdLine);
+		// if using a 'fake' filesystem, consider reading from the same image
+		else
+		{
+			part_start = bootHdr.kernelStart >> DEV_SECTOR_BITS;	
+			part_length = ((bootHdr.kernelSize-1) >> DEV_SECTOR_BITS) + 1;
+			filemax = bootHdr.kernelSize;
+			using_devsize = 0;
+			linux_load(file, bootHdr.cmdLine);
+		}
+	
+		break;
+		
+	case OS_WINCE:
+
+		printf("Starting Windows CE loader...\n");
+		// if using a real filesystem, load the kernel image from a specified file		
+		if(bootHdr.bitFlags & FLAG_FILESYSTEM)
+			wince_load(bootHdr.kernelFile, bootHdr.cmdLine);
+		// if using a 'fake' filesystem, consider reading from the same image
+		else
+		{
+			part_start = bootHdr.kernelStart >> DEV_SECTOR_BITS;	
+			part_length = ((bootHdr.kernelSize-1) >> DEV_SECTOR_BITS) + 1;
+			filemax = bootHdr.kernelSize;	
+			wince_load(file, bootHdr.cmdLine);
+		}
+
+		break;	
+		
+	default:
+		printf("Boot error: unknown OS type, aborting: %d\n", bootHdr.osType);
+		return LOADER_NOT_SUPPORT;
+	}
+	
+	file_close();
+	return 0;
+}
diff --git a/x86/context.c b/x86/context.c
new file mode 100644
index 0000000..a06b97d
--- /dev/null
+++ b/x86/context.c
@@ -0,0 +1,135 @@
+/*
+ * This file is part of FILO.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+
+/*
+ * context switching
+ * 2003-10 by SONE Takeshi
+ */
+
+#include <libpayload.h>
+#include <lib.h>
+#include "segment.h"
+#include "context.h"
+
+#define MAIN_STACK_SIZE 16384
+#define IMAGE_STACK_SIZE 4096
+
+static void start_main(void);	/* forward decl. */
+void __exit_context(void);	/* assembly routine */
+
+/*
+ * Main context structure 
+ * It is placed at the bottom of our stack, and loaded by assembly routine
+ * to start us up.
+ */
+struct context main_ctx __attribute__ ((section(".initctx"))) = {
+	.gdt_base = (u32) gdt,
+	.gdt_limit = GDT_LIMIT,
+	.cs = FLAT_CS, .ds = FLAT_DS,
+	.es = FLAT_DS, .fs = FLAT_DS,
+	.gs = FLAT_DS, .ss = FLAT_DS,
+	.esp = (u32)ESP_LOC(&main_ctx),
+	.eip = (u32) start_main,
+	.return_addr = (u32) __exit_context
+};
+
+/* This is used by assembly routine to load/store the context which
+ * it is to switch/switched.  */
+struct context *__context = &main_ctx;
+
+/* Stack for loaded ELF image */
+static u8 image_stack[IMAGE_STACK_SIZE];
+
+/* Pointer to startup context (physical address) */
+unsigned long __boot_ctx;
+
+/*
+ * Main starter
+ * This is the C function that runs first.
+ */
+static void start_main(void)
+{
+	int retval;
+	extern int main(void);
+
+	/* Save startup context, so we can refer to it later.
+	 * We have to keep it in physical address since we will relocate. */
+	__boot_ctx = virt_to_phys(__context);
+
+	/* Start the real fun */
+	retval = main();
+
+	/* Pass return value to startup context. Bootloader may see it. */
+	boot_ctx->eax = retval;
+
+	/* Returning from here should jump to __exit_context */
+	__context = boot_ctx;
+}
+
+/* Setup a new context using the given stack.
+ */
+struct context *init_context(u8 * stack, u32 stack_size, int num_params)
+{
+	struct context *ctx;
+
+	ctx = (struct context *) (stack + stack_size - 
+			(sizeof(*ctx) + num_params * sizeof(u32)));
+	memset(ctx, 0, sizeof(*ctx));
+
+	/* Fill in reasonable default for flat memory model */
+	ctx->gdt_base = virt_to_phys(gdt);
+	ctx->gdt_limit = GDT_LIMIT;
+	ctx->cs = FLAT_CS;
+	ctx->ds = FLAT_DS;
+	ctx->es = FLAT_DS;
+	ctx->fs = FLAT_DS;
+	ctx->gs = FLAT_DS;
+	ctx->ss = FLAT_DS;
+	ctx->esp = virt_to_phys(ESP_LOC(ctx));
+	ctx->return_addr = virt_to_phys(__exit_context);
+
+	return ctx;
+}
+
+/* Switch to another context. */
+struct context *switch_to(struct context *ctx)
+{
+	struct context *save, *ret;
+
+	save = __context;
+	__context = ctx;
+	asm volatile ("push %%cs; call __switch_context" ::: "memory");
+	ret = __context;
+	__context = save;
+	return ret;
+}
+
+/* Start ELF Boot image */
+u32 start_elf(u32 entry_point, u32 param)
+{
+	struct context *ctx;
+
+	ctx = init_context(image_stack, sizeof image_stack, 1);
+	ctx->eip = entry_point;
+	ctx->param[0] = param;
+	ctx->eax = 0xe1fb007;
+	ctx->ebx = param;
+
+	ctx = switch_to(ctx);
+	return ctx->eax;
+}
diff --git a/x86/context.h b/x86/context.h
new file mode 100644
index 0000000..44e9665
--- /dev/null
+++ b/x86/context.h
@@ -0,0 +1,65 @@
+/*
+ * This file is part of FILO.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+
+#ifndef i386_CONTEXT_H
+#define i386_CONTEXT_H
+
+struct context {
+	/* Stack Segment, placed here because of the alignment issue... */
+	u16 ss;
+	/* Used with sgdt/lgdt */
+	u16 gdt_limit;
+	u32 gdt_base;
+	/* General registers, accessed with pushal/popal */
+	u32 edi;
+	u32 esi;
+	u32 ebp;
+	u32 esp;		/* points just below eax */
+	u32 ebx;
+	u32 edx;
+	u32 ecx;
+	u32 eax;
+#define ESP_LOC(ctx) (&(ctx)->gs)
+	/* Segment registers */
+	u32 gs;
+	u32 fs;
+	u32 es;
+	u32 ds;
+	/* Flags */
+	u32 eflags;
+	/* Code segment:offset */
+	u32 eip;
+	u32 cs;
+	/* Optional stack contents */
+	u32 return_addr;
+	u32 param[0];
+};
+
+/* Create a new context in the given stack */
+struct context *init_context(u8 * stack, u32 stack_size, int num_param);
+
+/* Switch context */
+struct context *switch_to(struct context *);
+
+/* Holds physical address of boot context */
+extern unsigned long __boot_ctx;
+
+/* This can always be safely used to refer to the boot context */
+#define boot_ctx ((struct context *) phys_to_virt(__boot_ctx))
+
+#endif				/* i386_CONTEXT_H */
diff --git a/x86/include/arch/byteorder.h b/x86/include/arch/byteorder.h
new file mode 100644
index 0000000..afaebfa
--- /dev/null
+++ b/x86/include/arch/byteorder.h
@@ -0,0 +1,64 @@
+#ifndef ARCH_ENDIAN_H
+#define ARCH_ENDIAN_H
+
+static inline u16 __i386_bswap_16(u16 x)
+{
+	__asm__("xchgb %b0,%h0\n\t"
+		: "=q" (x)
+		: "0" (x));
+	return x;
+}
+
+static inline u32 __i386_bswap_32(u32 x)
+{
+	__asm__("xchgb %b0,%h0\n\t"
+		"rorl $16,%0\n\t"
+		"xchgb %b0,%h0"
+		: "=q" (x)
+		: "0" (x));
+	return x;
+}
+
+
+#define __bswap_constant_16(x) \
+	((u16)((((u16)(x) & 0x00ff) << 8) | \
+		(((u16)(x) & 0xff00) >> 8)))
+
+#define __bswap_constant_32(x) \
+	((u32)((((u32)(x) & 0x000000ffU) << 24) | \
+		(((u32)(x) & 0x0000ff00U) <<  8) | \
+		(((u32)(x) & 0x00ff0000U) >>  8) | \
+		(((u32)(x) & 0xff000000U) >> 24)))
+
+#define __bswap_16(x) \
+	((u16)(__builtin_constant_p(x) ? \
+	__bswap_constant_16(x) : \
+	__i386_bswap_16(x)))
+
+
+#define __bswap_32(x) \
+	((u32)(__builtin_constant_p(x) ? \
+	__bswap_constant_32(x) : \
+	__i386_bswap_32(x)))
+
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#define le32_to_cpup(x) (*(u32 *)(x))
+#define cpu_to_le16p(x) (*(u16*)(x))
+
+#define ntohl(x)        __bswap_32(x)
+#define htonl(x)        __bswap_32(x)
+#define ntohs(x)        __bswap_16(x)
+#define htons(x)        __bswap_16(x)
+#define cpu_to_le32(x)  (x)
+#define cpu_to_le16(x)  (x)
+#define cpu_to_be32(x)  __bswap_32(x)
+#define cpu_to_be16(x)  __bswap_16(x)
+#define le32_to_cpu(x)  (x)
+#define le16_to_cpu(x)  (x)
+#define be32_to_cpu(x)  __bswap_32(x)
+#define be16_to_cpu(x)  __bswap_16(x)
+
+#endif /* ARCH_ENDIAN_H */
+
diff --git a/x86/include/arch/elf.h b/x86/include/arch/elf.h
new file mode 100644
index 0000000..86c6725
--- /dev/null
+++ b/x86/include/arch/elf.h
@@ -0,0 +1,5 @@
+#define ARCH_ELF_CLASS ELFCLASS32
+#define ARCH_ELF_DATA ELFDATA2LSB
+#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_386 || (x)==EM_486)
+typedef Elf32_Ehdr Elf_ehdr;
+typedef Elf32_Phdr Elf_phdr;
diff --git a/x86/include/arch/eltorito.h b/x86/include/arch/eltorito.h
new file mode 100644
index 0000000..d43e9aa
--- /dev/null
+++ b/x86/include/arch/eltorito.h
@@ -0,0 +1,3 @@
+#ifndef ELTORITO_PLATFORM
+#define ELTORITO_PLATFORM ELTORITO_PLATFORM_X86
+#endif /* ELTORITO_PLATFORM */
diff --git a/x86/include/arch/timer.h b/x86/include/arch/timer.h
new file mode 100644
index 0000000..3cdd9b4
--- /dev/null
+++ b/x86/include/arch/timer.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of FILO.
+ *
+ * (C) 2004-2008 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#ifndef	TIMER_H
+#define TIMER_H
+
+extern u32 cpu_khz;
+
+u64 currticks(void);
+int getrtsecs (void);
+
+#define TICKS_PER_SEC (cpu_khz * 1000)
+#define TICKS_PER_USEC (cpu_khz / 1000)
+
+
+#endif	/* TIMER_H */
diff --git a/x86/ldscript b/x86/ldscript
new file mode 100644
index 0000000..b260c51
--- /dev/null
+++ b/x86/ldscript
@@ -0,0 +1,93 @@
+/*
+ * This file is part of FILO.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+/* When started from General Software BIOS */
+/* BASE_ADDR = 0x40000; */
+/* When started from coreboot */
+BASE_ADDR = 0x100000;          
+
+
+OUTPUT_FORMAT(elf32-i386)
+OUTPUT_ARCH(i386)
+
+ENTRY(entry)
+
+/* 1024KB heap and 64KB stack */
+HEAP_SIZE = 1 * 1024 * 1024;
+STACK_SIZE = 64 * 1024;
+
+SECTIONS
+{
+    . = BASE_ADDR;
+
+    /* Put Multiboot header near beginning of file, if any. */
+    .hdr : { *(.hdr) *(.hdr.*) }
+
+    /* Start of the program. 
+     * Now the version string is in the note, we must include it
+     * in the program. Otherwise we lose the string after relocation. */
+    . = ALIGN(4096);
+    _start = .;
+
+    /* Putting ELF notes near beginning of file might help bootloaders.
+     * We discard .note sections other than .note.ELFBoot and .note.pinfo,
+     * because some versions of GCC generates useless ones. */
+    .note : { *(.note.ELFBoot) *(note.pinfo) }
+
+    /* Normal sections */
+    .boot : { *(.boot) *(.boot.*) }
+    .text : { *(.text) *(.text.*) }
+    .rodata : {
+	. = ALIGN(4);
+	drivers_start = .;
+	*(.rodata.drivers)
+	drivers_end = .;
+	*(.rodata)
+	*(.rodata.*)
+    }
+    .data : { *(.data) *(.data.*) }
+
+    .bss : {
+	*(.sbss)
+	*(.sbss.*)
+	*(.bss)
+	*(.bss.*)
+	*(COMMON)
+
+	/* heap and stack */
+
+	. = ALIGN(16);
+	_heap = .;
+	. += HEAP_SIZE;
+	. = ALIGN(16);
+	_eheap = .;
+
+	_stack = .;
+	. += STACK_SIZE;
+	. = ALIGN(16);
+	_estack = .;
+    }
+
+    .initctx : {
+	/* Initial contents of stack. This MUST BE just after the stack. */
+	*(.initctx)
+    }
+
+    _end = .;
+
+    /DISCARD/ : { *(.comment) *(.note) }
+}
diff --git a/x86/linux_load.c b/x86/linux_load.c
new file mode 100644
index 0000000..aa2f27e
--- /dev/null
+++ b/x86/linux_load.c
@@ -0,0 +1,803 @@
+/*
+ * This file is part of FILO.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+/*
+ * Linux/i386 loader
+ * Supports bzImage, zImage and Image format.
+ *
+ * Based on work by Steve Gehlbach.
+ * Portions are taken from mkelfImage.
+ *
+ * 2003-09 by SONE Takeshi
+ */
+
+#include <libpayload.h>
+#include <libpayload-config.h>
+#include <coreboot_tables.h>
+#include <config.h>
+#include <fs.h>
+#include "context.h"
+#include "segment.h"
+
+#define DEBUG_THIS CONFIG_DEBUG_LINUXLOAD
+#include <debug.h>
+
+#define LINUX_PARAM_LOC 0x90000
+#define COMMAND_LINE_LOC 0x91000
+#define GDT_LOC 0x92000
+#define STACK_LOC 0x93000
+
+#define E820MAX	32		/* number of entries in E820MAP */
+struct e820entry {
+	unsigned long long addr;	/* start of memory segment */
+	unsigned long long size;	/* size of memory segment */
+	unsigned long type;	/* type of memory segment */
+#define E820_RAM	1
+#define E820_RESERVED	2
+#define E820_ACPI	3	/* usable as RAM once ACPI tables have been read */
+#define E820_NVS	4
+};
+
+/* The header of Linux/i386 kernel */
+struct linux_header {
+	u8 reserved1[0x1f1];	/* 0x000 */
+	u8 setup_sects;		/* 0x1f1 */
+	u16 root_flags;		/* 0x1f2 */
+	u32 syssize;		/* 0x1f4 (2.04+) */
+	u8 reserved2[2];	/* 0x1f8 */
+	u16 vid_mode;		/* 0x1fa */
+	u16 root_dev;		/* 0x1fc */
+	u16 boot_sector_magic;	/* 0x1fe */
+	/* 2.00+ */
+	u8 reserved3[2];	/* 0x200 */
+	u8 header_magic[4];	/* 0x202 */
+	u16 protocol_version;	/* 0x206 */
+	u32 realmode_swtch;	/* 0x208 */
+	u16 start_sys;		/* 0x20c */
+	u16 kver_addr;		/* 0x20e */
+	u8 type_of_loader;	/* 0x210 */
+	u8 loadflags;		/* 0x211 */
+	u16 setup_move_size;	/* 0x212 */
+	u32 code32_start;	/* 0x214 */
+	u32 ramdisk_image;	/* 0x218 */
+	u32 ramdisk_size;	/* 0x21c */
+	u8 reserved4[4];	/* 0x220 */
+	/* 2.01+ */
+	u16 heap_end_ptr;	/* 0x224 */
+	u8 reserved5[2];	/* 0x226 */
+	/* 2.02+ */
+	u32 cmd_line_ptr;	/* 0x228 */
+	/* 2.03+ */
+	u32 initrd_addr_max;	/* 0x22c */
+	/* 2.05+ */
+	u32 kernel_alignment;	/* 0x230 */
+	u8 relocatable_kernel;	/* 0x234 */
+	u8 min_alignment;	/* 0x235 (2.10+) */
+	u8 reserved6[2];	/* 0x236 */
+	/* 2.06+ */
+	u32 cmdline_size;	/* 0x238 */
+	/* 2.07+ */
+	u32 hardware_subarch;	/* 0x23c */
+	u64 hardware_subarch_data;/* 0x240 */
+	/* 2.08+ */
+	u32 payload_offset;	/* 0x248 */
+	u32 payload_length;	/* 0x24c */
+	/* 2.09+ */
+	u64 setup_data;		/* 0x250 */
+	/* 2.10+ */
+	u64 pref_address;	/* 0x258 */
+	u32 init_size;		/* 0x260 */
+} __attribute__ ((packed));
+
+/* Paramters passed to 32-bit part of Linux
+ * This is another view of the structure above.. */
+struct linux_params {
+	u8 orig_x;		/* 0x00 */
+	u8 orig_y;		/* 0x01 */
+	u16 ext_mem_k;		/* 0x02 -- EXT_MEM_K sits here */
+	u16 orig_video_page;	/* 0x04 */
+	u8 orig_video_mode;	/* 0x06 */
+	u8 orig_video_cols;	/* 0x07 */
+	u16 unused2;		/* 0x08 */
+	u16 orig_video_ega_bx;	/* 0x0a */
+	u16 unused3;		/* 0x0c */
+	u8 orig_video_lines;	/* 0x0e */
+	u8 orig_video_isVGA;	/* 0x0f */
+	u16 orig_video_points;	/* 0x10 */
+
+	/* VESA graphic mode -- linear frame buffer */
+	u16 lfb_width;		/* 0x12 */
+	u16 lfb_height;		/* 0x14 */
+	u16 lfb_depth;		/* 0x16 */
+	u32 lfb_base;		/* 0x18 */
+	u32 lfb_size;		/* 0x1c */
+	u16 cl_magic;		/* 0x20 */
+#define CL_MAGIC_VALUE 0xA33F
+	u16 cl_offset;		/* 0x22 */
+	u16 lfb_linelength;	/* 0x24 */
+	u8 red_size;		/* 0x26 */
+	u8 red_pos;		/* 0x27 */
+	u8 green_size;		/* 0x28 */
+	u8 green_pos;		/* 0x29 */
+	u8 blue_size;		/* 0x2a */
+	u8 blue_pos;		/* 0x2b */
+	u8 rsvd_size;		/* 0x2c */
+	u8 rsvd_pos;		/* 0x2d */
+	u16 vesapm_seg;		/* 0x2e */
+	u16 vesapm_off;		/* 0x30 */
+	u16 pages;		/* 0x32 */
+	u8 reserved4[12];	/* 0x34 -- 0x3f reserved for future expansion */
+
+	//struct apm_bios_info apm_bios_info;   /* 0x40 */
+	u8 apm_bios_info[0x40];
+	//struct drive_info_struct drive_info;  /* 0x80 */
+	u8 drive_info[0x20];
+	//struct sys_desc_table sys_desc_table; /* 0xa0 */
+	u8 sys_desc_table[0x140];
+	u32 alt_mem_k;		/* 0x1e0 */
+	u8 reserved5[4];	/* 0x1e4 */
+	u8 e820_map_nr;		/* 0x1e8 */
+	u8 reserved6[9];	/* 0x1e9 */
+	u16 mount_root_rdonly;	/* 0x1f2 */
+	u8 reserved7[4];	/* 0x1f4 */
+	u16 ramdisk_flags;	/* 0x1f8 */
+#define RAMDISK_IMAGE_START_MASK  	0x07FF
+#define RAMDISK_PROMPT_FLAG		0x8000
+#define RAMDISK_LOAD_FLAG		0x4000
+	u8 reserved8[2];	/* 0x1fa */
+	u16 orig_root_dev;	/* 0x1fc */
+	u8 reserved9[1];	/* 0x1fe */
+	u8 aux_device_info;	/* 0x1ff */
+	u8 reserved10[2];	/* 0x200 */
+	u8 param_block_signature[4];	/* 0x202 */
+	u16 param_block_version;	/* 0x206 */
+	u8 reserved11[8];	/* 0x208 */
+	u8 loader_type;		/* 0x210 */
+#define LOADER_TYPE_LOADLIN         1
+#define LOADER_TYPE_BOOTSECT_LOADER 2
+#define LOADER_TYPE_SYSLINUX        3
+#define LOADER_TYPE_ETHERBOOT       4
+#define LOADER_TYPE_KERNEL          5
+	u8 loader_flags;	/* 0x211 */
+	u8 reserved12[2];	/* 0x212 */
+	u32 kernel_start;	/* 0x214 */
+	u32 initrd_start;	/* 0x218 */
+	u32 initrd_size;	/* 0x21c */
+	u8 reserved12_5[8];	/* 0x220 */
+	u32 cmd_line_ptr;	/* 0x228 */
+	u32 initrd_addr_max;	/* 0x22c */
+	u32 kernel_alignment;	/* 0x230 */
+	u8 relocatable_kernel;	/* 0x234 */
+	u8 reserved13[155];		/* 0x22c */
+	struct e820entry e820_map[E820MAX];	/* 0x2d0 */
+	u8 reserved16[688];	/* 0x550 */
+#define COMMAND_LINE_SIZE 256
+	/* Command line is copied here by 32-bit i386/kernel/head.S.
+	 * So I will follow the boot protocol, rather than putting it
+	 * directly here. --ts1 */
+	u8 command_line[COMMAND_LINE_SIZE];	/* 0x800 */
+	u8 reserved17[1792];	/* 0x900 - 0x1000 */
+};
+
+u64 forced_memsize;
+
+/* Load the first part the file and check if it's Linux */
+static u32 load_linux_header(struct linux_header *hdr)
+{
+	u32 kern_addr = 0;
+	int load_high;
+
+	if (file_read(hdr, sizeof *hdr) != sizeof *hdr) {
+		printf("Can't read Linux header\n");
+		return 0;
+	}
+
+	if (hdr->boot_sector_magic != 0xaa55) {
+		printf("Not a Linux kernel image\n");
+		return 0;
+	}
+
+	/* Linux is found. Print some information */
+	if (memcmp(hdr->header_magic, "HdrS", 4) != 0) {
+		/* This may be floppy disk image or something.
+		 * Perform a simple (incomplete) sanity check. */
+		if (hdr->setup_sects >= 16 || file_size() - (hdr->setup_sects << 9) >= 512 << 10) {
+			printf("This looks like a bootdisk image but not like Linux...\n");
+			return 0;
+		}
+
+		printf("Possible very old Linux");
+		/* This kernel does not even have a protocol version.
+		 * Force the value. */
+		hdr->protocol_version = 0;	/* pre-2.00 */
+	} else {
+		printf("Found Linux");
+	}
+
+	if (hdr->protocol_version >= 0x200 && hdr->kver_addr) {
+		char kver[256];
+		file_seek(hdr->kver_addr + 0x200);
+		if (file_read(kver, sizeof kver) != 0) {
+			kver[255] = 0;
+			printf(" version %s", kver);
+		}
+	}
+	debug(" (protocol %#x)", hdr->protocol_version);
+
+	load_high = 0;
+	if (hdr->protocol_version >= 0x200) {
+		debug(" (loadflags %#x)", hdr->loadflags);
+		load_high = hdr->loadflags & 1;
+	}
+
+	/* determine kernel load address */
+	if (hdr->protocol_version >= 0x20a) {
+		if (hdr->pref_address >> 32) {
+			debug(" (ignoring 64bit pref_address)");
+		} else {
+			kern_addr = hdr->pref_address;
+		}
+	}
+
+	if (hdr->protocol_version >= 0x205 && hdr->relocatable_kernel) {
+		printf(" relocatable");
+	}
+
+	if (load_high) {
+		printf(" bzImage");
+		if (kern_addr == 0)
+			kern_addr = 0x100000;
+	} else {
+		printf(" zImage or Image");
+		if (kern_addr == 0)
+			kern_addr = 0x1000;
+	}
+
+	printf(".\n");
+
+	return kern_addr;
+}
+
+/* Set up parameters for 32-bit kernel */
+static void
+init_linux_params(struct linux_params *params, struct linux_header *hdr)
+{
+	debug("Setting up paramters at %#lx\n", virt_to_phys(params));
+	memset(params, 0, sizeof *params);
+
+	/* Copy some useful values from header */
+	params->mount_root_rdonly = hdr->root_flags;
+	params->orig_root_dev = hdr->root_dev;
+
+	/* Video parameters.
+	 * This assumes we have VGA in standard 80x25 text mode,
+	 * just like our vga.c does.
+	 * Cursor position is filled later to allow some more printf's.
+	 */
+	params->orig_video_mode = 3;
+	params->orig_video_cols = 80;
+	params->orig_video_lines = 25;
+	params->orig_video_isVGA = 1;
+	params->orig_video_points = 16;
+
+	params->loader_type = 0xff;	/* Unregistered Linux loader */
+
+	/* copy alignment fields for relocatable kernels */
+	if (hdr->protocol_version >= 0x205) {
+		params->relocatable_kernel = hdr->relocatable_kernel;
+		params->kernel_alignment = hdr->kernel_alignment;
+	}
+}
+
+/* Memory map */
+static void set_memory_size(struct linux_params *params)
+{
+	int i;
+	uint64_t end;
+	u32 ramtop = 0;
+	struct e820entry *linux_map;
+	struct sysinfo_t *info = &lib_sysinfo;
+	struct memrange *filo_map;
+
+	linux_map = params->e820_map;
+	filo_map = info->memrange;
+	for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) {
+		if (i < E820MAX) {
+			/* Convert to BIOS e820 style */
+			linux_map->addr = filo_map->base;
+			linux_map->size = filo_map->size;
+			linux_map->type = filo_map->type;
+			debug("%016llx - %016llx (%d)\n", linux_map->addr,
+			      linux_map->addr + linux_map->size,
+			      linux_map->type);
+			params->e820_map_nr = i + 1;
+		}
+
+		/* Find out top of RAM. XXX This ignores hole above 1MB */
+		end = filo_map->base + filo_map->size;
+		if (end < (1ULL << 32)) { /* don't count memory above 4GB */
+			if (end > ramtop)
+				ramtop = (u32) end;
+		}
+	}
+
+	debug("ramtop=%#x\n", ramtop);
+	/* Size of memory above 1MB in KB */
+	params->alt_mem_k = (ramtop - (1 << 20)) >> 10;
+	/* old style, 64MB max */
+	if (ramtop >= (64 << 20))
+		params->ext_mem_k = (63 << 10);
+	else
+		params->ext_mem_k = params->alt_mem_k;
+	debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k,
+	      params->alt_mem_k);
+}
+
+/* Video mode */
+static void set_video_mode(struct linux_params *params)
+{
+#if CONFIG_COREBOOT_VIDEO_CONSOLE
+	/* Are we running on a framebuffer console? */
+	if (!lib_sysinfo.framebuffer)
+		return;
+
+	struct cb_framebuffer *fb = phys_to_virt(lib_sysinfo.framebuffer);
+
+	params->lfb_width = fb->x_resolution;
+	params->lfb_height = fb->y_resolution;
+	params->lfb_depth = fb->bits_per_pixel;
+	params->lfb_linelength = fb->bytes_per_line;
+	params->lfb_base = fb->physical_address;
+
+	// prolly not enough for the boot splash?!
+	params->lfb_size =
+	    (params->lfb_linelength * params->lfb_height + 65535) >> 16;
+	params->red_size = fb->red_mask_size;
+	params->red_pos = fb->red_mask_pos;
+	params->green_size = fb->green_mask_size;
+	params->green_pos = fb->green_mask_pos;
+	params->blue_size = fb->blue_mask_size;
+	params->blue_pos = fb->blue_mask_pos;
+	params->rsvd_size = fb->reserved_mask_size;
+	params->rsvd_pos = fb->reserved_mask_pos;
+#endif
+}
+
+/*
+ * Parse command line
+ * Some parameters, like initrd=<file>, are not passed to kernel,
+ * we are responsible to process them.
+ * Parameters for kernel are copied to kern_cmdline. Returns name of initrd.
+ */
+static char *parse_command_line(const char *orig_cmdline,
+				char *kern_cmdline)
+{
+	const char *start, *sep, *end, *val;
+	char name[64];
+	int len;
+	int k_len;
+	int to_kern;
+	char *initrd = 0;
+	int toolong = 0;
+
+	forced_memsize = 0;
+
+	if (!orig_cmdline) {
+		*kern_cmdline = 0;
+		return 0;
+	}
+
+	k_len = 0;
+	debug("original command line: \"%s\"\n", orig_cmdline);
+	debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline));
+
+	start = orig_cmdline;
+	while (*start == ' ')
+		start++;
+	while (*start) {
+		end = strchr(start, ' ');
+		if (!end)
+			end = start + strlen(start);
+		sep = strchr(start, '=');
+		if (!sep || sep > end)
+			sep = end;
+		len = sep - start;
+		if (len >= sizeof(name))
+			len = sizeof(name) - 1;
+		memcpy(name, start, len);
+		name[len] = 0;
+
+		if (*sep == '=') {
+			val = sep + 1;
+			len = end - val;
+		} else {
+			val = 0;
+			len = 0;
+		}
+
+		/* Only initrd= and mem= are handled here. vga= is not,
+		 * which I believe is a paramter to the realmode part of Linux,
+		 * which we don't execute.
+		 */
+		if (strcmp(name, "initrd") == 0) {
+			if (!val) {
+				printf
+				    ("Missing filename to initrd parameter\n");
+			} else {
+				initrd = malloc(len + 1);
+				memcpy(initrd, val, len);
+				initrd[len] = 0;
+				debug("initrd=%s\n", initrd);
+			}
+			/* Don't pass this to kernel */
+			to_kern = 0;
+		} else if (strcmp(name, "mem") == 0) {
+			if (!val) {
+				printf
+				    ("Missing value for mem parameter\n");
+			} else {
+				forced_memsize =
+				    strtoull_with_suffix(val,
+							 (char **) &val,
+							 0);
+				if (forced_memsize == 0)
+					printf
+					    ("Invalid mem option, ignored\n");
+				if (val != end) {
+					printf
+					    ("Garbage after mem=<size>, ignored\n");
+					forced_memsize = 0;
+				}
+				debug("mem=%Lu\n", forced_memsize);
+			}
+			/* mem= is for both loader and kernel */
+			to_kern = 1;
+		} else {
+			to_kern = 1;
+		}
+
+		if (to_kern) {
+			/* Copy to kernel command line buffer */
+			if (k_len != 0)
+				kern_cmdline[k_len++] = ' ';	/* put separator */
+			len = end - start;
+			if (k_len + len >= COMMAND_LINE_SIZE) {
+				len = COMMAND_LINE_SIZE - k_len - 1;
+				if (!toolong) {
+					printf
+					    ("Kernel command line is too long; truncated to "
+					     "%d bytes\n",
+					     COMMAND_LINE_SIZE - 1);
+					toolong = 1;
+				}
+			}
+			memcpy(kern_cmdline + k_len, start, len);
+			k_len += len;
+		}
+
+		start = end;
+		while (*start == ' ')
+			start++;
+	}
+	kern_cmdline[k_len] = 0;
+	debug("kernel command line (%d bytes): \"%s\"\n", k_len,
+	      kern_cmdline);
+
+	return initrd;
+}
+
+/* Set command line location */
+static void set_command_line_loc(struct linux_params *params,
+				 struct linux_header *hdr)
+{
+	if (hdr->protocol_version >= 0x202) {
+		/* new style */
+		params->cmd_line_ptr = COMMAND_LINE_LOC;
+	} else {
+		/* old style */
+		params->cl_magic = CL_MAGIC_VALUE;
+		params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC;
+	}
+}
+
+/* Load 32-bit part of kernel */
+static int load_linux_kernel(struct linux_header *hdr, u32 kern_addr)
+{
+	u32 kern_offset, kern_size;
+
+	if (hdr->setup_sects == 0)
+		hdr->setup_sects = 4;
+	kern_offset = (hdr->setup_sects + 1) * 512;
+	file_seek(kern_offset);
+	kern_size = file_size() - kern_offset;
+	debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr,
+	      kern_size);
+
+	if (using_devsize) {
+		printf("Attempt to load up to end of device as kernel; "
+		       "specify the image size\n");
+		return 0;
+	}
+
+	printf("Loading kernel... ");
+	if (file_read(phys_to_virt(kern_addr), kern_size) != kern_size) {
+		printf("Can't read kernel\n");
+		return 0;
+	}
+	printf("ok\n");
+
+	return kern_size;
+}
+
+static int load_initrd(struct linux_header *hdr,
+		       u32 kern_end, struct linux_params *params,
+		       const char *initrd_file)
+{
+	u32 max;
+	u32 start, end, size;
+	uint64_t forced;
+	extern char _start[];
+#if 0
+	extern char _end[];
+#endif
+
+	if (!file_open(initrd_file)) {
+		printf("Can't open initrd: %s\n", initrd_file);
+		return -1;
+	}
+	if (using_devsize) {
+		printf("Attempt to load up to end of device as initrd; "
+		       "specify the image size\n");
+		return -1;
+	}
+	size = file_size();
+
+
+	/* Find out the kernel's restriction on how high the initrd can be
+	 * placed */
+	if (hdr->protocol_version >= 0x203)
+		max = hdr->initrd_addr_max;
+	else
+		max = 0x38000000;	/* Hardcoded value for older kernels */
+
+	/* FILO itself is at the top of RAM. (relocated)
+	 * So, try putting initrd just below us. */
+	end = virt_to_phys(_start - 1);
+	if (end > max)
+		end = max;
+
+	/* If "mem=" option is given, we have to put the initrd within
+	 * the specified range. */
+	if (forced_memsize) {
+		forced = forced_memsize;
+		if (forced > max)
+			forced = max;
+		/* If the "mem=" is lower, it's easy */
+		if (forced <= end)
+			end = forced;
+#if 0
+		else {
+			/* Otherwise, see if we can put it above us.
+			 * 
+			 *   This would be a good idea if we could easily find
+			 *   out where the memory hole lives.
+			 *   
+			 *   There's nothing wrong with the initrd living below
+			 *   FILO. (stepan)
+			 *
+			 *   The problems is even a 64bit kernel will live in
+			 *   32bit address space, so if you have a lot of
+			 *   memory and specify mem=xG with x>4, the maximum
+			 *   allowed initrd address (2.6.x sets this to
+			 *   0xffffffff) will be used for the high limit.
+			 *   (offset 22c in vmlinuz)
+			 *
+			 *   you might want to enable this if you limit memory
+			 *   with mem=yG with y<4.
+			 */
+			if (virt_to_phys(_end) + size <= forced)
+				end = forced;	/* Ok */
+		}
+#endif
+	}
+
+	start = end - size;
+	start &= ~0xfff;	/* page align */
+	end = start + size;
+
+	debug("start=%#x end=%#x\n", start, end);
+
+	if (start < kern_end) {
+		printf("Initrd is too big to fit in memory\n");
+		return -1;
+	}
+
+	printf("Loading initrd... ");
+	if (file_read(phys_to_virt(start), size) != size) {
+		printf("Can't read initrd\n");
+		return -1;
+	}
+	printf("ok\n");
+
+	params->initrd_start = start;
+	params->initrd_size = size;
+
+	return 0;
+}
+
+static void hardware_setup(void)
+{
+	/* Disable nmi */
+	outb(0x80, 0x70);
+
+	/* Make sure any coprocessor is properly reset.. */
+	outb(0, 0xf0);
+	outb(0, 0xf1);
+
+	/* we're getting screwed again and again by this problem of the 8259.
+	 * so we're going to leave this lying around for inclusion into crt0.S
+	 * on an as-needed basis. 
+	 *
+	 * well, that went ok, I hope. Now we have to reprogram the interrupts
+	 * :-(
+	 * we put them right after the intel-reserved hardware interrupts, at
+	 * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
+	 * messed this up with the original PC, and they haven't been able to
+	 * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
+	 * which is used for the internal hardware interrupts as well. We just
+	 * have to reprogram the 8259's, and it isn't fun.
+	 */
+
+	outb(0x11, 0x20);	/* initialization sequence to 8259A-1 */
+	outb(0x11, 0xA0);	/* and to 8259A-2 */
+
+	outb(0x20, 0x21);	/* start of hardware int's (0x20) */
+	outb(0x28, 0xA1);	/* start of hardware int's 2 (0x28) */
+
+	outb(0x04, 0x21);	/* 8259-1 is master */
+	outb(0x02, 0xA1);	/* 8259-2 is slave */
+
+	outb(0x01, 0x21);	/* 8086 mode for both */
+	outb(0x01, 0xA1);
+
+	outb(0xFF, 0xA1);	/* mask off all interrupts for now */
+	outb(0xFB, 0x21);	/* mask all irq's but irq2 which is cascaded */
+}
+
+/* Start Linux */
+static int start_linux(u32 kern_addr, struct linux_params *params)
+{
+	struct segment_desc *linux_gdt;
+	struct context *ctx;
+#ifdef CONFIG_VGA_VIDEO_CONSOLE
+	unsigned int cursor_x, cursor_y, cursor_en;
+#endif
+#ifdef CONFIG_PCMCIA_CF
+	unsigned char *cf_bar;
+	int i;
+#endif
+
+	ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0);
+
+	/* Linux expects GDT being in low memory */
+	linux_gdt = phys_to_virt(GDT_LOC);
+	memset(linux_gdt, 0, 13 * sizeof(struct segment_desc));
+	/* Normal kernel code/data segments */
+	linux_gdt[2] = gdt[FLAT_CODE];
+	linux_gdt[3] = gdt[FLAT_DATA];
+	/* 2.6 kernel uses 12 and 13, but head.S uses backward-compatible
+	 * segments (2 and 3), so it SHOULD not be a problem. 
+	 * However, some distro kernels (eg. RH9) with backported threading 
+	 * patch use 12 and 13 also when booting... */
+	linux_gdt[12] = gdt[FLAT_CODE];
+	linux_gdt[13] = gdt[FLAT_DATA];
+	ctx->gdt_base = GDT_LOC;
+	ctx->gdt_limit = 14 * 8 - 1;
+	ctx->cs = 0x10;
+	ctx->ds = 0x18;
+	ctx->es = 0x18;
+	ctx->fs = 0x18;
+	ctx->gs = 0x18;
+	ctx->ss = 0x18;
+
+	/* Parameter location */
+	ctx->esi = virt_to_phys(params);
+
+	/* Entry point */
+	ctx->eip = kern_addr;
+
+	/* set this field in any case to support relocatable kernels */
+	params->kernel_start = kern_addr;
+
+	debug("EIP=%#x\n", kern_addr);
+	printf("Jumping to entry point...\n");
+
+#ifdef CONFIG_VGA_VIDEO_CONSOLE
+	/* Update VGA cursor position.
+	 * This must be here because the printf changes the value! */
+	video_console_get_cursor(&cursor_x, &cursor_y, &cursor_en);
+	params->orig_x = cursor_x;
+	params->orig_y = cursor_y;
+#endif
+
+#ifdef CONFIG_PCMCIA_CF
+	cf_bar = phys_to_virt(pci_read_config32(PCI_DEV(0, 0xa, 1), 0x10));
+	for (i = 0x836; i < 0x840; i++) {
+		cf_bar[i] = 0;
+	}
+#endif
+	/* Go... */
+	ctx = switch_to(ctx);
+
+	/* It's impossible but... */
+	printf("Returned with EAX=%#x\n", ctx->eax);
+
+	return ctx->eax;
+}
+
+int linux_load(const char *file, const char *cmdline)
+{
+	struct linux_header hdr;
+	struct linux_params *params;
+	u32 kern_addr, kern_size;
+	char *initrd_file = 0;
+
+	if (!file_open(file))
+		return -1;
+
+	kern_addr = load_linux_header(&hdr);
+	if (kern_addr == 0) {
+		file_close();
+		return LOADER_NOT_SUPPORT;
+	}
+
+	params = phys_to_virt(LINUX_PARAM_LOC);
+	init_linux_params(params, &hdr);
+	set_memory_size(params);
+	set_video_mode(params);
+	initrd_file =
+	    parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC));
+	set_command_line_loc(params, &hdr);
+
+	kern_size = load_linux_kernel(&hdr, kern_addr);
+	if (kern_size == 0) {
+		if (initrd_file)
+			free(initrd_file);
+		file_close();
+		return -1;
+	}
+
+	if (initrd_file) {
+		if (load_initrd(&hdr, kern_addr + kern_size,
+					params, initrd_file) != 0) {
+			free(initrd_file);
+			file_close();
+			return -1;
+		}
+		free(initrd_file);
+	}
+
+	file_close();
+#if defined(CONFIG_USB)
+	usb_exit();
+#endif
+
+	hardware_setup();
+
+	start_linux(kern_addr, params);
+	return 0;
+}
diff --git a/x86/segment.c b/x86/segment.c
new file mode 100644
index 0000000..ea38096
--- /dev/null
+++ b/x86/segment.c
@@ -0,0 +1,135 @@
+/*
+ * This file is part of FILO.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+
+/* Segmentation of the i386 architecture.
+ *
+ * 2003-07 by SONE Takeshi
+ */
+
+#include <libpayload.h>
+#include <coreboot_tables.h>
+#include <config.h>
+#include "segment.h"
+
+#define DEBUG_THIS CONFIG_DEBUG_SEGMENT
+#include <debug.h>
+
+/* i386 lgdt argument */
+struct gdtarg {
+	unsigned short limit;
+	unsigned int base;
+} __attribute__ ((packed));
+
+/* How far the virtual address (used in C) is different from physical 
+ * address. Since we start in flat mode, the initial value is zero. */
+unsigned long virt_offset = 0;
+
+/* GDT, the global descriptor table */
+struct segment_desc gdt[NUM_SEG] = {
+	/* 0x00: null segment */
+	{0, 0, 0, 0, 0, 0},
+	/* 0x08: flat code segment */
+	{0xffff, 0, 0, 0x9f, 0xcf, 0},
+	/* 0x10: flat data segment */
+	{0xffff, 0, 0, 0x93, 0xcf, 0},
+	/* 0x18: code segment for relocated execution */
+	{0xffff, 0, 0, 0x9f, 0xcf, 0},
+	/* 0x20: data segment for relocated execution */
+	{0xffff, 0, 0, 0x93, 0xcf, 0},
+};
+
+extern char _start[], _end[];
+
+void relocate(void)
+{
+	int i;
+	unsigned long prog_addr;
+	unsigned long prog_size;
+	unsigned long addr, new_base;
+	unsigned long long segsize;
+	unsigned long new_offset;
+	unsigned d0, d1, d2;
+	struct gdtarg gdtarg;
+	struct sysinfo_t *info = &lib_sysinfo;
+#define ALIGNMENT 0x1000
+
+	prog_addr = virt_to_phys(&_start);
+	prog_size = virt_to_phys(&_end) - virt_to_phys(&_start);
+	debug("Current location: %#lx-%#lx\n", prog_addr,
+	      prog_addr + prog_size - 1);
+
+	new_base = 0;
+	for (i = 0; i < info->n_memranges; i++) {
+		if (info->memrange[i].type != CB_MEM_RAM)
+			continue;
+		if (info->memrange[i].base >= 1ULL << 32)
+			continue;
+		segsize = info->memrange[i].size;
+		if (info->memrange[i].base + segsize > 1ULL << 32)
+			segsize = (1ULL << 32) - info->memrange[i].base;
+		if (segsize < prog_size + ALIGNMENT)
+			continue;
+		addr = info->memrange[i].base + segsize - prog_size;
+		addr &= ~(ALIGNMENT - 1);
+		if (addr >= prog_addr && addr < prog_addr + prog_size)
+			continue;
+		if (prog_addr >= addr && prog_addr < addr + prog_size)
+			continue;
+		if (addr > new_base)
+			new_base = addr;
+	}
+	if (new_base == 0) {
+		printf("Can't find address to relocate\n");
+		return;
+	}
+
+	debug("Relocating to %#lx-%#lx... ",
+	      new_base, new_base + prog_size - 1);
+
+	/* New virtual address offset */
+	new_offset = new_base - (unsigned long) &_start;
+
+	/* Tweak the GDT */
+	gdt[RELOC_CODE].base_0 = (unsigned short) new_offset;
+	gdt[RELOC_CODE].base_16 = (unsigned char) (new_offset >> 16);
+	gdt[RELOC_CODE].base_24 = (unsigned char) (new_offset >> 24);
+	gdt[RELOC_DATA].base_0 = (unsigned short) new_offset;
+	gdt[RELOC_DATA].base_16 = (unsigned char) (new_offset >> 16);
+	gdt[RELOC_DATA].base_24 = (unsigned char) (new_offset >> 24);
+
+	/* Load new GDT and reload segments */
+	gdtarg.base = new_offset + (unsigned long) gdt;
+	gdtarg.limit = GDT_LIMIT;
+	__asm__ __volatile__("rep; movsb\n\t"	/* copy everything */
+			     "lgdt %3\n\t"
+			     "ljmp %4, $1f\n1:\t"
+			     "movw %5, %%ds\n\t"
+			     "movw %5, %%es\n\t"
+			     "movw %5, %%fs\n\t"
+			     "movw %5, %%gs\n\t"
+			     "movw %5, %%ss\n":"=&S"(d0), "=&D"(d1),
+			     "=&c"(d2)
+			     :"m"(gdtarg), "n"(RELOC_CS),
+			     "q"((unsigned short) RELOC_DS), "0"(&_start),
+			     "1"(new_base), "2"(prog_size));
+
+	virt_offset = new_offset;	// for FILO
+	virtual_offset = new_offset;	// for libpayload
+
+	debug("ok\n");
+}
diff --git a/x86/segment.h b/x86/segment.h
new file mode 100644
index 0000000..43130e6
--- /dev/null
+++ b/x86/segment.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of FILO.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+
+/* Segment indexes. Must match the gdt definition in segment.c. */
+enum {
+	NULL_SEG,
+	FLAT_CODE,
+	FLAT_DATA,
+	RELOC_CODE,
+	RELOC_DATA,
+	NUM_SEG,
+};
+
+/* Values for segment selector register */
+#define FLAT_CS (FLAT_CODE << 3)
+#define FLAT_DS (FLAT_DATA << 3)
+#define RELOC_CS (RELOC_CODE << 3)
+#define RELOC_DS (RELOC_DATA << 3)
+
+/* i386 segment descriptor */
+struct segment_desc {
+	unsigned short limit_0;
+	unsigned short base_0;
+	unsigned char base_16;
+	unsigned char types;
+	unsigned char flags;
+	unsigned char base_24;
+};
+
+extern struct segment_desc gdt[NUM_SEG];
+
+#define GDT_LIMIT ((NUM_SEG << 3) - 1)
diff --git a/x86/switch.S b/x86/switch.S
new file mode 100644
index 0000000..50f5f71
--- /dev/null
+++ b/x86/switch.S
@@ -0,0 +1,116 @@
+	.globl	entry, __switch_context, __exit_context, halt
+
+	.section ".boot", "xa"
+	.align	4
+
+/*
+ * Entry point
+ * We start execution from here.
+ * It is assumed that CPU is in 32-bit protected mode and 
+ * all segments are 4GB and base zero (flat model).
+ */
+entry:
+	/* Save boot context and switch to our main context.
+	 * Main context is statically defined in C.
+	 */
+	pushl	%cs
+	call	__switch_context
+
+	/* We get here when the main context switches back to
+	 * the boot context.
+	 * Return to previous bootloader.
+	 */
+	ret
+
+/*
+ * Switch execution context
+ * This saves registers, segments, and GDT in the stack, then
+ * switches the stack, and restores everything from the new stack.
+ * This function takes no argument. New stack pointer is
+ * taken from global variable __context, and old stack pointer
+ * is also saved to __context. This way we can just jump to 
+ * this routine to get back to the original context.
+ *
+ * Call this routine with lcall or pushl %cs; call.
+ */
+__switch_context:
+	/* Save everything in current stack */
+	pushfl		    /* 56 */
+	pushl	%ds	    /* 52 */
+	pushl	%es	    /* 48 */
+	pushl	%fs	    /* 44 */
+	pushl	%gs	    /* 40 */
+	pushal		    /* 8 */
+	subl	$8, %esp
+	movw	%ss, (%esp) /* 0 */
+	sgdt	2(%esp)	    /* 2 */
+
+#if 0
+	/* Swap %cs and %eip on the stack, so lret will work */
+	movl	60(%esp), %eax
+	xchgl	%eax, 64(%esp)
+	movl	%eax, 60(%esp)
+#endif
+	
+	/* At this point we don't know if we are on flat segment
+	 * or relocated. So compute the address offset from %eip.
+	 * Assuming CS.base==DS.base==SS.base.
+	 */
+	call	1f
+1:	popl	%ebx
+	subl	$1b, %ebx
+
+	/* Interrupts are not allowed... */
+	cli
+	
+	/* Current context pointer is our stack pointer */
+	movl	%esp, %esi
+
+	/* Normalize the ctx pointer */
+	subl	%ebx, %esi
+
+	/* Swap it with new value */
+	xchgl	%esi, __context(%ebx)
+
+	/* Adjust new ctx pointer for current address offset */
+	addl	%ebx, %esi
+
+	/* Load new %ss and %esp to temporary */
+	movzwl	(%esi), %edx
+	movl	20(%esi), %eax
+
+	/* Load new GDT */
+	lgdt	2(%esi)
+
+	/* Load new stack segment with new GDT */
+	movl	%edx, %ss
+
+	/* Set new stack pointer, but we have to adjust it because
+	 * pushal saves %esp value before pushal, and we want the value
+	 * after pushal.
+	 */
+	leal	-32(%eax), %esp
+
+	/* Load the rest from new stack */
+	popal
+	popl	%gs
+	popl	%fs
+	popl	%es
+	popl	%ds
+	popfl
+
+	/* Finally, load new %cs and %eip */
+	lret
+
+__exit_context:
+	/* Get back to the original context */
+	pushl	%cs
+	call	__switch_context
+
+	/* We get here if the other context attempt to switch to this
+	 * dead context. This should not happen. */
+
+halt:
+	cli
+	hlt
+	jmp	halt
diff --git a/x86/sys_info.c b/x86/sys_info.c
new file mode 100644
index 0000000..8e7d14e
--- /dev/null
+++ b/x86/sys_info.c
@@ -0,0 +1,34 @@
+/*
+ * This file is part of FILO.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <libpayload.h>
+#include <config.h>
+#include <sys_info.h>
+#include "context.h"
+#define DEBUG_THIS CONFIG_DEBUG_SYS_INFO
+#include <debug.h>
+
+void collect_sys_info(struct sys_info *info)
+{
+	/* Pick up paramters given by bootloader to us */
+	info->boot_type = boot_ctx->eax;
+	info->boot_data = boot_ctx->ebx;
+	info->boot_arg = boot_ctx->param[0];
+	debug("boot EAX = %#lx\n", info->boot_type);
+	debug("boot EBX = %#lx\n", info->boot_data);
+	debug("boot arg = %#lx\n", info->boot_arg);
+}
diff --git a/x86/timer.c b/x86/timer.c
new file mode 100644
index 0000000..739c9ed
--- /dev/null
+++ b/x86/timer.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of FILO.
+ *
+ * (C) 2004-2008 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <libpayload.h>
+#include <arch/rdtsc.h>
+#include <arch/timer.h>
+
+u64 currticks(void)
+{
+	/* Read the Time Stamp Counter */
+	return  rdtsc();
+}
+
+int getrtsecs (void)
+{
+	u64 t;
+	t=currticks();
+	t=t/(TICKS_PER_SEC);
+	return (int)t;
+}
+
+
diff --git a/x86/wince_load.c b/x86/wince_load.c
new file mode 100644
index 0000000..993815f
--- /dev/null
+++ b/x86/wince_load.c
@@ -0,0 +1,385 @@
+/*******************************************************************************
+ *
+ *	WindowsCE/i386 loader 
+ *
+ *	Copyright 2006 Andrei Birjukov <andrei.birjukov at artecdesign.ee> and
+ *	Artec Design LLC http://www.artecdesign.ee
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that 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.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ******************************************************************************/
+
+#include <libpayload.h>
+#include <lib.h>
+#include <fs.h>
+#include <arch/io.h>
+#include "context.h"
+#include "segment.h"
+
+#define DEBUG_THIS DEBUG_WINCELOAD
+#include <debug.h>
+
+#define BOOTARG_PTR_LOCATION	0x001FFFFC
+#define BOOTARG_LOCATION		0x001FFF00
+#define BOOTARG_SIGNATURE		0x544F4F42
+#define BOOTARG_VERSION_SIG		0x12345678
+#define BOOTARG_MAJOR_VER		1
+#define BOOTARG_MINOR_VER		0
+
+#define MAX_DEV_NAMELEN			16	// Should match EDBG_MAX_DEV_NAMELEN.
+
+#define LDRFL_USE_EDBG			0x0001	// Set to attempt to use debug Ethernet
+// The following two flags are only looked at if LDRFL_USE_EDBG is set
+#define LDRFL_ADDR_VALID		0x0002	// Set if EdbgAddr field is valid
+#define LDRFL_JUMPIMG			0x0004	// If set, don't communicate with eshell to get
+// The following flag is only used for backup FLASH operation
+#define LDRFL_FLASH_BACKUP		0x80
+// configuration, use ucEshellFlags field.
+// Use this constant in EdbgIRQ to specify that EDBG should run without an interrupt.
+#define EDBG_IRQ_NONE			0xFF
+
+#define EDBG_ADAPTER_DEFAULT	2
+#define EDBG_ADAPTER_RTL8139	4
+
+#define PSIZE					(1500)	// Max Packet Size
+#define DSIZE					(PSIZE+12)
+#define BIN_HDRSIG_SIZE			7
+
+#define ROM_SIGNATURE_OFFSET	0x40	// Offset from the image's physfirst address to the ROM signature.
+#define ROM_SIGNATURE			0x43454345
+#define ROM_TOC_POINTER_OFFSET	0x44	// Offset from the image's physfirst address to the TOC pointer.
+#define ROM_TOC_OFFSET_OFFSET	0x48	// Offset from the image's physfirst address to the TOC offset (from physfirst).
+
+#define GDT_LOC					0x92000
+#define STACK_LOC				0x93000
+
+typedef struct _EDBG_ADDR {
+	u32 dwIP;
+	u16 wMAC[3];
+	u16 wPort;
+} EDBG_ADDR;
+
+typedef struct _BOOT_ARGS {
+	u8 ucVideoMode;
+	u8 ucComPort;
+	u8 ucBaudDivisor;
+	u8 ucPCIConfigType;
+	u32 dwSig;
+	u32 dwLen;
+	u8 ucLoaderFlags;
+	u8 ucEshellFlags;
+	u8 ucEdbgAdapterType;
+	u8 ucEdbgIRQ;
+	u32 dwEdbgBaseAddr;
+	u32 dwEdbgDebugZone;
+	EDBG_ADDR EdbgAddr;
+	EDBG_ADDR EshellHostAddr;
+	EDBG_ADDR DbgHostAddr;
+	EDBG_ADDR CeshHostAddr;
+	EDBG_ADDR KdbgHostAddr;
+	u32 DHCPLeaseTime;
+	u16 EdbgFlags;
+	u16 KitlTransport;
+	u32 dwEBootFlag;
+	u32 dwEBootAddr;
+	u32 dwLaunchAddr;
+	u32 pvFlatFrameBuffer;
+	u16 vesaMode;
+	u16 cxDisplayScreen;
+	u16 cyDisplayScreen;
+	u16 cxPhysicalScreen;
+	u16 cyPhysicalScreen;
+	u16 cbScanLineLength;
+	u16 bppScreen;
+	u8 RedMaskSize;
+	u8 RedMaskPosition;
+	u8 GreenMaskSize;
+	u8 GreenMaskPosition;
+	u8 BlueMaskSize;
+	u8 BlueMaskPosition;
+	u32 dwVersionSig;
+	u16 MajorVersion;
+	u16 MinorVersion;
+	u8 szDeviceNameRoot[MAX_DEV_NAMELEN];
+	u32 dwImgStoreAddr;
+	u32 dwImgLoadAddr;
+	u32 dwImgLength;
+	u8 NANDBootFlags;
+	u8 NANDBusNumber;
+	u32 NANDSlotNumber;
+} BOOT_ARGS;
+
+typedef struct _ROMHDR {
+	u32 dllfirst;
+	u32 dlllast;
+	u32 physfirst;
+	u32 physlast;
+	u32 nummods;
+	u32 ulRAMStart;
+	u32 ulRAMFree;
+	u32 ulRAMEnd;
+	u32 ulCopyEntries;
+	u32 ulCopyOffset;
+	u32 ulProfileLen;
+	u32 ulProfileOffset;
+	u32 numfiles;
+	u32 ulKernelFlags;
+	u32 ulFSRamPercent;
+	u32 ulDrivglobStart;
+	u32 ulDrivglobLen;
+	u16 usCPUType;
+	u16 usMiscFlags;
+	void *pExtensions;
+	u32 ulTrackingStart;
+	u32 ulTrackingLen;
+} ROMHDR;
+
+typedef struct _SEGMENT_INFO {
+	u32 segAddr;
+	u32 segSize;
+	u32 checkSum;
+} SEGMENT_INFO;
+
+typedef void (*PFN_LAUNCH) ();	// WinCE launch function proto
+
+static u8 g_ceSignature[] = { 'B', '0', '0', '0', 'F', 'F', '\n' };
+static void **g_ppBootArgs = NULL;
+BOOT_ARGS *g_pBootArgs = NULL;
+static ROMHDR *pROMHeader = NULL;
+
+static u32 g_imageStart = 0;
+static u32 g_imageSize = 0;
+static u32 g_romOffset = 0;
+
+static int verifyCheckSum(u8 * pData, int nSize, u32 checkSum)
+{
+	// check the CRC
+	u32 crc = 0;
+	int i;
+
+	for (i = 0; i < nSize; i++)
+		crc += *pData++;
+
+	return (crc == checkSum);
+}
+
+int wince_launch(u32 imageStart, u32 imageSize,
+		 u32 entryPoint, ROMHDR * pRomHdr)
+{
+	struct segment_desc *wince_gdt;
+	struct context *ctx;
+
+	debug("start Windows CE from address 0x%x, image loaded 0x%x,%d\n",
+	      entryPoint, imageStart, imageSize);
+
+	// initialize new stack
+	ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0);
+
+	// initialize GDT in low memory
+	wince_gdt = phys_to_virt(GDT_LOC);
+	memset(wince_gdt, 0, 13 * sizeof(struct segment_desc));
+	// flat kernel code/data segments
+	wince_gdt[2] = gdt[FLAT_CODE];
+	wince_gdt[3] = gdt[FLAT_DATA];
+
+	wince_gdt[12] = gdt[FLAT_CODE];
+	wince_gdt[13] = gdt[FLAT_DATA];
+	ctx->gdt_base = GDT_LOC;
+	ctx->gdt_limit = 14 * 8 - 1;
+	ctx->cs = 0x10;
+	ctx->ds = 0x18;
+	ctx->es = 0x18;
+	ctx->fs = 0x18;
+	ctx->gs = 0x18;
+	ctx->ss = 0x18;
+
+	// kernel entry point
+	ctx->eip = entryPoint;
+
+	printf("Launching Windows CE...\n");
+
+	// go...!
+	ctx = switch_to(ctx);
+
+	// may never return here
+	printf("returned with eax=%#x\n", ctx->eax);
+	return ctx->eax;
+}
+
+void wince_init_bootarg(u32 entryPoint)
+{
+	// init the BOOT_ARGS pointer at the known address
+	g_ppBootArgs = phys_to_virt(BOOTARG_PTR_LOCATION);
+	*g_ppBootArgs = (void *) BOOTARG_LOCATION;
+
+	// keep our BOOT_ARGS somewhere in a dry dark place 
+	g_pBootArgs = phys_to_virt(BOOTARG_LOCATION);
+
+	debug("BOOT_ARGS at addr 0x%x, pointer at 0x%x [%x]\n",
+	      (unsigned int) *g_ppBootArgs, BOOTARG_PTR_LOCATION,
+	      (unsigned int) g_ppBootArgs);
+
+	memset(g_pBootArgs, 0, sizeof(BOOT_ARGS));
+
+	// this data was copied from WinCE EDBG boot args       
+	g_pBootArgs->ucEdbgAdapterType = EDBG_ADAPTER_DEFAULT;
+	// use the first PCI NIC available
+	g_pBootArgs->ucEdbgIRQ = 0;
+	g_pBootArgs->dwEdbgBaseAddr = 0;
+
+	// set the KITL device name to something adequate
+	strcpy((char *) g_pBootArgs->szDeviceNameRoot, "FILO");
+
+	g_pBootArgs->dwSig = BOOTARG_SIGNATURE;
+	g_pBootArgs->dwLen = sizeof(BOOT_ARGS);
+	g_pBootArgs->dwVersionSig = BOOTARG_VERSION_SIG;
+	g_pBootArgs->MajorVersion = BOOTARG_MAJOR_VER;
+	g_pBootArgs->MinorVersion = BOOTARG_MINOR_VER;
+
+/*
+	g_pBootArgs->ucVideoMode = 255;
+	g_pBootArgs->ucComPort = 1;
+	g_pBootArgs->ucBaudDivisor = 3;
+	g_pBootArgs->ucPCIConfigType = 1;
+	g_pBootArgs->ucLoaderFlags = 0x7;
+*/
+
+	debug("Boot arguments initialized at 0x%x\n",
+	      (unsigned int) *g_ppBootArgs);
+}
+
+int wince_load(const char *file, const char *cmdline)
+{
+	u8 signBuf[BIN_HDRSIG_SIZE], *pDest = NULL;
+	SEGMENT_INFO segInfo;
+	u32 totalBytes = 0;
+
+	if (!file_open(file)) {
+		printf("Failed opening image file: %s\n", file);
+		return LOADER_NOT_SUPPORT;
+	}
+	// read the image signature
+	file_read((void *) signBuf, BIN_HDRSIG_SIZE);
+
+	if (memcmp(signBuf, g_ceSignature, BIN_HDRSIG_SIZE)) {
+		printf("Bad or unknown Windows CE image signature\n");
+		file_close();
+		return LOADER_NOT_SUPPORT;
+	}
+	// now read image start address and size        
+	file_read((void *) &g_imageStart, sizeof(u32));
+	file_read((void *) &g_imageSize, sizeof(u32));
+
+	if (!g_imageStart || !g_imageSize)	// sanity check
+	{
+		printf("Invalid image descriptors\n");
+		file_close();
+		return LOADER_NOT_SUPPORT;
+	}
+
+	printf("Windows CE BIN image, start 0x%x, length %d\n",
+	       g_imageStart, g_imageSize);
+
+	// main image reading loop      
+	while (1) {
+		// first grab the segment descriptor
+		if (file_read(&segInfo, sizeof(SEGMENT_INFO)) <
+		    sizeof(SEGMENT_INFO)) {
+			printf ("\nFailed reading image segment descriptor\n");
+			file_close();
+			return LOADER_NOT_SUPPORT;
+		}
+
+		totalBytes += sizeof(SEGMENT_INFO);	// update data counter
+		printf("#");	// that's a progress bar :)
+
+		// now check if that's the last one
+		if (segInfo.segAddr == 0 && segInfo.checkSum == 0)
+			break;
+
+		// map segment address to current address space
+		pDest = (u8 *) phys_to_virt(segInfo.segAddr);
+		debug("fetched segment address 0x%x [%x] size %d\n",
+		      segInfo.segAddr, (unsigned int) pDest,
+		      segInfo.segSize);
+
+		// read the image segment data from VFS
+		if (file_read((void *) pDest, segInfo.segSize) <
+		    segInfo.segSize) {
+			printf ("\nFailed reading image segment data (address 0x%x, size %d)\n",
+			     segInfo.segAddr, segInfo.segSize);
+			file_close();
+			return LOADER_NOT_SUPPORT;
+		}
+		// check the data integrity
+		if (!verifyCheckSum
+		    (pDest, segInfo.segSize, segInfo.checkSum)) {
+			printf ("\nFailed verifying segment checksum at address 0x%x, size %d\n",
+			     (unsigned int) pDest, segInfo.segSize);
+			file_close();
+			return LOADER_NOT_SUPPORT;
+		}
+		// Look for ROMHDR to compute ROM offset.  NOTE: romimage guarantees that the record containing
+		// the TOC signature and pointer will always come before the record that contains the ROMHDR contents.
+
+		if (segInfo.segSize == sizeof(ROMHDR) && 
+				(*(u32 *) phys_to_virt(g_imageStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE)) {
+			u32 tempOffset =
+			    (segInfo.segAddr -
+			     *(u32 *) phys_to_virt(g_imageStart +
+							ROM_SIGNATURE_OFFSET
+							+ sizeof(long)));
+			ROMHDR *pROMhdr = (ROMHDR *) pDest;
+
+			// check to make sure this record really contains the ROMHDR.
+			if ((pROMhdr->physfirst == (g_imageStart - tempOffset)) && 
+					(pROMhdr->physlast == (g_imageStart - tempOffset + g_imageSize)) &&
+			    		(u32) (((pROMhdr-> dllfirst << 16) & 0xffff0000) <= pROMhdr->dlllast) &&
+			    		(u32) (((pROMhdr-> dllfirst << 16) & 0x0000ffff) <= pROMhdr->dlllast)) {
+				g_romOffset = tempOffset;
+				debug("\nROM offset = 0x%x\n", g_romOffset);
+			}
+		}
+
+		totalBytes += segInfo.segSize;	// update data counter
+	}
+
+	// we should have moved all image segments to RAM by now
+	printf("\nOS image loaded.\n");
+
+	// check for pTOC signature ("CECE") here, after image in place
+	if (*(u32 *) phys_to_virt(g_imageStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE) {
+		// a pointer to the ROMHDR structure lives just past the ROM_SIGNATURE (which is a longword value).  Note that
+		// this pointer is remapped since it might be a flash address (image destined for flash), but is actually cached
+		// in RAM.
+
+		u32 cacheAddress = *(u32 *) phys_to_virt(g_imageStart + ROM_SIGNATURE_OFFSET + sizeof(u32));
+
+		pROMHeader =
+		    (ROMHDR *) phys_to_virt(cacheAddress + g_romOffset);
+		debug("ROMHDR at address 0x%xh\n",
+		      cacheAddress + g_romOffset);
+	}
+
+	file_close();
+
+	// prepare the boot arguments
+	// note that the last segment size carries the launch address 
+	wince_init_bootarg(segInfo.segSize);
+
+	// finally, call the generic launch() function
+	return wince_launch(g_imageStart, g_imageSize, segInfo.segSize,
+			    pROMHeader);
+}



More information about the coreboot mailing list