Patchwork tinybootblock

login
register
about
Submitter Patrick Georgi
Date 2009-12-22 21:27:19
Message ID <4B3139B7.5090202@georgi-clan.de>
Download mbox | patch
Permalink /patch/693/
State Accepted
Headers show

Comments

Patrick Georgi - 2009-12-22 21:27:19
Hi,

attached patch implements my tinybootblock concept (formerly known as
newfailover) in Kconfig. It's designed to be non-instrusive, so boards
will continue to build as usual unless they're changed to use the feature.
As a proof of concept (which I used for development), emulation/qemu-x86
is changed to tinybootblock, but other boards will require more changes,
so it not a complete example on how to convert a board.

Objectives of tinybootblock (when fully implemented):
- Fix Fam10 boards on Kconfig, which require >64kb for raminit. That
should help with replacing newconfig with kconfig completely.
newconfig requires the failover mechanism on those boards to work around
this limit, and this solves it similarily by splitting the code in a
top-64k block and "the rest".

- Use CBFS
The newconfig failover mechanism uses the pre-CBFS image layout
(cat(1)ing files together and relying on magic offsets to determine
entry points). CBFS provides a clean solution for that.

- Provide a framework to build image selection logic
In newconfig, most boards have their own code to select the image. The
goal in this layout is to have generic decision routines to take care of
that, and encourage their use.

- Push as much as possible out of the bootblock
The failover mechanism so far did CAR in the bootblock and raminit in
the later stage. With tinybootblock, CAR is supposed to end up outside
the bootblock. "Safe updates", once we provide them, will be able to
update CAR support for new CPU types, too.


Code flow in tinybootblock:
- 16bit reset vector (0xfffffff0)
- jump to 32bit mode
- Do whatever is necessary to have the entire ROM around (C code,
compiled with romcc)
- Look up fallback/romstage in CBFS (this can be extended with selection
logic if desired) ("selection logic" is C, compiled with romcc, lookup
is assembly)
- Fetch the entry point which is stored in the romstage's header
- Jump to the entry point. fallback/romstage is linked for the address
where it finally resides in the image, so it's execute in place.
- fallback/romstage is the original bootblock code (except for ROM
enable): Setup CAR if available, do raminit, call coreboot_ram


Current issues:
- No support for rom enable sequences yet. QEmu doesn't need them, but
they're what I do next.

- The bootblock isn't exactly tiny, it's 64kb. Most of it is empty (on
qemu, it's ~400 used bytes including id section and reset vector, ~350
byte for all code). To be done after rom enable works.

- There might be better places to push files to (both in the sources and
in the build tree)

- There's some problem with the various section types in ELF which I
worked around in cbfstool: If the section starts earlier than the
desired load address, strip the bytes before the load address. This is
no problem in automatic operation but can have lead to mistakes in
manual operation.


Future developments:
- At some point we might want to have various variants of the bootblock:
Unconditionally loading a given romstage (what we have now), selecting
between fallback/normal by CMOS (as in newconfig), enabling a rescue
flash routine on GPIO, etc.


As mentioned, ROM enable support is still missing. Once this is done,
tinybootblock should be useful for a broader audience (eg. to port
boards), but I wanted to get the current state out now, as it finally works.

Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
Patrick Georgi - 2009-12-22 22:07:28
Hi again,

It was brought to my attention that svn didn't track the file copies in
the diff. The following copies are necessary:
cp src/arch/i386/init/crt0.S.lb src/arch/i386/init/bootblock_prologue.c
cp src/arch/i386/Makefile.inc src/arch/i386/Makefile.tinybootblock.inc
cp src/arch/i386/Makefile.inc src/arch/i386/Makefile.bigbootblock.inc

Then, the patch will work.

I'm sorry for the trouble,
Patrick
Myles Watson - 2009-12-22 22:17:35
On Tue, Dec 22, 2009 at 2:27 PM, Patrick Georgi <patrick@georgi-clan.de>wrote:

>
> - Provide a framework to build image selection logic
> In newconfig, most boards have their own code to select the image. The
> goal in this layout is to have generic decision routines to take care of
> that, and encourage their use.
>
Is it possible to have it be generic?  Won't we have to unify CMOS layouts
for that to happen?


> - Push as much as possible out of the bootblock
> The failover mechanism so far did CAR in the bootblock and raminit in
> the later stage. With tinybootblock, CAR is supposed to end up outside
> the bootblock. "Safe updates", once we provide them, will be able to
> update CAR support for new CPU types, too.
>
>
> Code flow in tinybootblock:
> - 16bit reset vector (0xfffffff0)
> - jump to 32bit mode
> - Do whatever is necessary to have the entire ROM around (C code,
> compiled with romcc)
>
I think it would be a mistake to bring romcc to targets that don't need it
now.


> - Look up fallback/romstage in CBFS (this can be extended with selection
> logic if desired) ("selection logic" is C, compiled with romcc, lookup
> is assembly)
>
It's more important to me to avoid assembly than to have the absolute
minimum size bootblock.  Especially for K8 & Fam10, there's plenty of space
to not have to do this.

Picky detail:
Since CONFIG_TINY_BOOTBLOCK is referenced in a Makefile that isn't board
specific, the Kconfig entry for it should go there too (with a default n).
There should just be a "select" in qemu-x86/Kconfig


> Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
>

I think it's a good start, and since it doesn't break anything until it's
used...

Acked-by: Myles Watson <mylesgw@gmail.com>
ron minnich - 2009-12-23 03:49:58
Sweet!

Acked-by: Ronald G. Minnich <rminnich@gmail.com>
Patrick Georgi - 2009-12-23 12:55:07
Am 22.12.2009 23:17, schrieb Myles Watson:
> On Tue, Dec 22, 2009 at 2:27 PM, Patrick Georgi
> <patrick@georgi-clan.de <mailto:patrick@georgi-clan.de>> wrote:
>
>
>     - Provide a framework to build image selection logic
>     In newconfig, most boards have their own code to select the image. The
>     goal in this layout is to have generic decision routines to take
>     care of
>     that, and encourage their use.
>
> Is it possible to have it be generic?  Won't we have to unify CMOS
> layouts for that to happen?
In a way, it's just the do_normal_boot() code in
src/pc80/mc146818rtc_early.c.
We already have everything in the tree to make it all generic, but we
didn't properly use it. Maybe because the generic code came after the
copied versions and no-one dared to refactor things.

It's not simply a port because of the intrusive change of moving CAR out
of the bootblock, and this time, the generic code will be around from
the start, so it has a chance to be used.
> I think it would be a mistake to bring romcc to targets that don't
> need it now.
The alternative at that point is to do that code in assembly, or to move
CAR to the bootblock again.
romcc works quite fine for small code, and the code in the bootblock is
supposed to be small.

>     - Look up fallback/romstage in CBFS (this can be extended with
>     selection
>     logic if desired) ("selection logic" is C, compiled with romcc, lookup
>     is assembly)
>
> It's more important to me to avoid assembly than to have the absolute
> minimum size bootblock.  Especially for K8 & Fam10, there's plenty of
> space to not have to do this.
Among the reasons: The way it is done now, it's always exactly one copy
of the tree walker. If it's written in C and compiled with romcc, it
could end up several times in the bootblock, if there are various calls
(fallback, normal, ...), probably giving the register allocator a harder
time.

> Picky detail:
> Since CONFIG_TINY_BOOTBLOCK is referenced in a Makefile that isn't
> board specific, the Kconfig entry for it should go there too (with a
> default n).  There should just be a "select" in qemu-x86/Kconfig
Fixed, thanks for the reminder. I wanted to keep things minimal and
forgot about it. It's not a big issue, as in Makefiles, missing
variables simply expand to the empty string, but it's cleaner the way
you proposed.

> Acked-by: Myles Watson <mylesgw@gmail.com <mailto:mylesgw@gmail.com>>
Thanks, r4989
Kevin O'Connor - 2009-12-23 19:34:51
On Tue, Dec 22, 2009 at 10:27:19PM +0100, Patrick Georgi wrote:
> attached patch implements my tinybootblock concept (formerly known as
> newfailover) in Kconfig.

Very nice!

Thanks.
-Kevin

Patch

Index: src/cpu/x86/32bit/entry32.lds
===================================================================
--- src/cpu/x86/32bit/entry32.lds	(revision 4988)
+++ src/cpu/x86/32bit/entry32.lds	(working copy)
@@ -0,0 +1 @@ 
+ENTRY(protected_start)
Index: src/mainboard/emulation/qemu-x86/Kconfig
===================================================================
--- src/mainboard/emulation/qemu-x86/Kconfig	(revision 4988)
+++ src/mainboard/emulation/qemu-x86/Kconfig	(working copy)
@@ -26,3 +26,8 @@ 
 	bool
 	default n
 	depends on BOARD_EMULATION_QEMU_X86
+
+config TINY_BOOTBLOCK
+	bool
+	default y
+	depends on BOARD_EMULATION_QEMU_X86
Index: src/mainboard/emulation/qemu-x86/Makefile.inc
===================================================================
--- src/mainboard/emulation/qemu-x86/Makefile.inc	(revision 4988)
+++ src/mainboard/emulation/qemu-x86/Makefile.inc	(working copy)
@@ -1,18 +1,12 @@ 
 initobj-y += crt0.o
-crt0-y += ../../../../src/cpu/x86/16bit/entry16.inc
 crt0-y += ../../../../src/cpu/x86/32bit/entry32.inc
-crt0-y += ../../../../src/cpu/x86/16bit/reset16.inc
-crt0-y += ../../../../src/arch/i386/lib/id.inc
 crt0-y += auto.inc
 
 obj-y += mainboard.o
 obj-$(CONFIG_GENERATE_PIRQ_TABLE) += irq_tables.o
 
 ldscript-y += ../../../../src/arch/i386/init/ldscript_fallback_cbfs.lb
-ldscript-y += ../../../../src/cpu/x86/16bit/entry16.lds
 ldscript-y += ../../../../src/cpu/x86/32bit/entry32.lds
-ldscript-y += ../../../../src/cpu/x86/16bit/reset16.lds
-ldscript-y += ../../../../src/arch/i386/lib/id.lds
 
 ifdef POST_EVALUATION
 
Index: src/arch/i386/init/bootblock.c
===================================================================
--- src/arch/i386/init/bootblock.c	(revision 0)
+++ src/arch/i386/init/bootblock.c	(revision 0)
@@ -0,0 +1,24 @@ 
+static unsigned long findstage(char* target)
+{
+	unsigned long entry;
+	asm volatile (
+		"mov $1f, %%esp\n\t"
+		"jmp walkcbfs\n\t"
+		"1:\n\t" : "=a" (entry) : "S" (target) : "ebx", "ecx", "edx", "edi", "ebp", "esp");
+	return entry;
+}
+
+static void call(unsigned long addr)
+{
+	asm volatile ("jmp %0\n\t" : : "r" (addr));
+}
+
+static void main(void)
+{
+	const char* target1 = "fallback/romstage";
+	unsigned long entry;
+	entry = findstage(target1);
+	if (entry) call(entry);
+	asm volatile ("1:\n\thlt\n\tjmp 1b\n\t");
+}
+
Index: src/arch/i386/init/bootblock_prologue.c
===================================================================
--- src/arch/i386/init/bootblock_prologue.c	(revision 4988)
+++ src/arch/i386/init/bootblock_prologue.c	(working copy)
@@ -35,112 +35,3 @@ 
 
 	intel_chip_post_macro(0x01)             /* delay for chipsets */
 
-#include "crt0_includes.h"
-
-#if CONFIG_USE_DCACHE_RAM == 0
-#ifndef CONSOLE_DEBUG_TX_STRING
-	/* uses:	 esp, ebx, ax, dx */
-# define __CRT_CONSOLE_TX_STRING(string) \
-	mov	string, %ebx	; \
-	CALLSP(crt_console_tx_string)
-
-# if defined(CONFIG_TTYS0_BASE) && (ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG)
-#  define CONSOLE_DEBUG_TX_STRING(string)        __CRT_CONSOLE_TX_STRING(string)
-# else
-#  define CONSOLE_DEBUG_TX_STRING(string)
-# endif
-#endif
-
-	/* clear boot_complete flag */
-	xorl	%ebp, %ebp
-__main:
-	CONSOLE_DEBUG_TX_STRING($str_copying_to_ram)
-
-	/*
-	 *	Copy data into RAM and clear the BSS. Since these segments
-	 *	isn\'t really that big we just copy/clear using bytes, not
-	 *	double words.
-	 */
-	intel_chip_post_macro(0x11)		/* post 11 */
-
-	cld				/* clear direction flag */
-	
-	/* copy coreboot from it's initial load location to 
-	 * the location it is compiled to run at.
-	 * Normally this is copying from FLASH ROM to RAM.
-	 */
-	movl	%ebp, %esi
-	/* FIXME: look for a proper place for the stack */
-	movl	$0x4000000, %esp
-	movl	%esp, %ebp
-	pushl %esi
-	pushl $str_coreboot_ram_name
-	call cbfs_and_run_core
-
-.Lhlt:	
-	intel_chip_post_macro(0xee)	/* post fe */
-	hlt
-	jmp	.Lhlt
-
-#ifdef __CRT_CONSOLE_TX_STRING
-	/* Uses esp, ebx, ax, dx  */
-crt_console_tx_string:
-	mov	(%ebx), %al
-	inc	%ebx
-	cmp	$0, %al
-	jne	9f
-	RETSP
-9:
-/* Base Address */
-#ifndef CONFIG_TTYS0_BASE
-#define CONFIG_TTYS0_BASE	0x3f8
-#endif
-/* Data */
-#define TTYS0_RBR (CONFIG_TTYS0_BASE+0x00)
-
-/* Control */
-#define TTYS0_TBR TTYS0_RBR
-#define TTYS0_IER (CONFIG_TTYS0_BASE+0x01)
-#define TTYS0_IIR (CONFIG_TTYS0_BASE+0x02)
-#define TTYS0_FCR TTYS0_IIR
-#define TTYS0_LCR (CONFIG_TTYS0_BASE+0x03)
-#define TTYS0_MCR (CONFIG_TTYS0_BASE+0x04)
-#define TTYS0_DLL TTYS0_RBR
-#define TTYS0_DLM TTYS0_IER
-
-/* Status */
-#define TTYS0_LSR (CONFIG_TTYS0_BASE+0x05)
-#define TTYS0_MSR (CONFIG_TTYS0_BASE+0x06)
-#define TTYS0_SCR (CONFIG_TTYS0_BASE+0x07)
-	
-	mov	%al, %ah
-10:	mov	$TTYS0_LSR, %dx
-	inb	%dx, %al
-	test	$0x20, %al
-	je	10b
-	mov	$TTYS0_TBR, %dx
-	mov	%ah, %al
-	outb	%al, %dx
-
-	jmp crt_console_tx_string
-#endif /* __CRT_CONSOLE_TX_STRING */
-
-#if defined(CONSOLE_DEBUG_TX_STRING) && (ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG)
-.section ".rom.data"
-#if CONFIG_COMPRESS
-str_copying_to_ram:  .string "Uncompressing coreboot to RAM.\r\n"
-#else
-str_copying_to_ram:  .string "Copying coreboot to RAM.\r\n"
-#endif
-str_pre_main:        .string "Jumping to coreboot.\r\n"
-.previous
-
-#endif /* ASM_CONSOLE_LOGLEVEL > BIOS_DEBUG */
-
-#if CONFIG_USE_FALLBACK_IMAGE == 1
-str_coreboot_ram_name:	.string "fallback/coreboot_ram"
-#else
-str_coreboot_ram_name:	.string "normal/coreboot_ram"
-#endif
-
-#endif /* CONFIG_USE_DCACHE_RAM */
Index: src/arch/i386/Makefile.bigbootblock.inc
===================================================================
--- src/arch/i386/Makefile.bigbootblock.inc	(revision 4988)
+++ src/arch/i386/Makefile.bigbootblock.inc	(working copy)
@@ -1,39 +1,12 @@ 
-#######################################################################
-# Take care of subdirectories
-subdirs-y += boot
-subdirs-y += init
-subdirs-y += lib
-subdirs-y += smp
-
-obj-$(CONFIG_HAVE_OPTION_TABLE) += ../../option_table.o
-
 ifdef POST_EVALUATION
 
 #######################################################################
 # Build the final rom image
 
-$(obj)/coreboot.rom: $(obj)/coreboot.bootblock $(obj)/coreboot_ram $(CBFSTOOL)
+$(obj)/coreboot.pre: $(obj)/coreboot.bootblock $(CBFSTOOL)
 	rm -f $@
 	$(CBFSTOOL) $@ create $(CONFIG_COREBOOT_ROMSIZE_KB)K $(obj)/coreboot.bootblock
-	if [ -f fallback/coreboot_apc ]; \
-	then \
-		$(CBFSTOOL) $@ add-stage fallback/coreboot_apc fallback/coreboot_apc $(CBFS_COMPRESS_FLAG); \
-	fi
-	$(CBFSTOOL) $@ add-stage $(obj)/coreboot_ram fallback/coreboot_ram $(CBFS_COMPRESS_FLAG)
-ifeq ($(CONFIG_PAYLOAD_NONE),y)
-	@printf "    PAYLOAD    none (as specified by user)\n"
-else
-	@printf "    PAYLOAD    $(CONFIG_FALLBACK_PAYLOAD_FILE) $(CBFS_PAYLOAD_COMPRESS_FLAG)\n"
-	$(CBFSTOOL) $(obj)/coreboot.rom add-payload $(CONFIG_FALLBACK_PAYLOAD_FILE) fallback/payload $(CBFS_PAYLOAD_COMPRESS_FLAG)
-endif
-ifeq ($(CONFIG_VGA_BIOS),y)
-	@printf "    VGABIOS    $(CONFIG_FALLBACK_VGA_BIOS_FILE) $(CONFIG_FALLBACK_VGA_BIOS_ID)\n"
-	$(CBFSTOOL) $(obj)/coreboot.rom add $(CONFIG_FALLBACK_VGA_BIOS_FILE) "pci$(CONFIG_FALLBACK_VGA_BIOS_ID).rom" optionrom
-endif
-	@printf "    CBFSPRINT  $(subst $(obj)/,,$(@))\n\n"
-	$(CBFSTOOL) $(obj)/coreboot.rom print
 
-
 #######################################################################
 # Build the bootblock
 
@@ -59,35 +32,4 @@ 
 	$(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(obj)/ldscript.ld $(initobjs)
 	$(NM) -n $(obj)/coreboot | sort > $(obj)/coreboot.map
 
-#######################################################################
-# i386 specific tools
-
-$(obj)/option_table.h $(obj)/option_table.c: $(obj)/build_opt_tbl $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout
-	@printf "    OPTION     $(subst $(obj)/,,$(@))\n"
-	$(obj)/build_opt_tbl --config $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout --header $(obj)/option_table.h --option $(obj)/option_table.c
-
-$(obj)/build_opt_tbl: $(top)/util/options/build_opt_tbl.c $(top)/src/include/pc80/mc146818rtc.h $(top)/src/include/boot/coreboot_tables.h $(obj)/config.h
-	@printf "    HOSTCC     $(subst $(obj)/,,$(@))\n"
-	$(HOSTCC) $(HOSTCFLAGS) -include $(obj)/config.h $< -o $@
-
-#######################################################################
-# Build the coreboot_ram (stage 2)
-
-$(obj)/coreboot_ram: $(obj)/coreboot_ram.o $(src)/config/coreboot_ram.ld #ldoptions
-	@printf "    CC         $(subst $(obj)/,,$(@))\n"
-	$(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(src)/config/coreboot_ram.ld $(obj)/coreboot_ram.o
-	$(NM) -n $(obj)/coreboot_ram | sort > $(obj)/coreboot_ram.map
-
-$(obj)/coreboot_ram.o: $(obj)/arch/i386/lib/c_start.o $(drivers) $(obj)/coreboot.a $(LIBGCC_FILE_NAME)
-	@printf "    CC         $(subst $(obj)/,,$(@))\n"
-	$(CC) -nostdlib -r -o $@ $(obj)/arch/i386/lib/c_start.o $(drivers) -Wl,-\( $(obj)/coreboot.a $(LIBGCC_FILE_NAME) -Wl,-\)
-
-$(obj)/coreboot.a: $(objs)
-	@printf "    AR         $(subst $(obj)/,,$(@))\n"
-	rm -f $(obj)/coreboot.a
-	$(AR) cr $(obj)/coreboot.a $(objs)
-
-#######################################################################
-# done
-
 endif
Index: src/arch/i386/Makefile.inc
===================================================================
--- src/arch/i386/Makefile.inc	(revision 4988)
+++ src/arch/i386/Makefile.inc	(working copy)
@@ -11,10 +11,8 @@ 
 
 #######################################################################
 # Build the final rom image
-
-$(obj)/coreboot.rom: $(obj)/coreboot.bootblock $(obj)/coreboot_ram $(CBFSTOOL)
-	rm -f $@
-	$(CBFSTOOL) $@ create $(CONFIG_COREBOOT_ROMSIZE_KB)K $(obj)/coreboot.bootblock
+$(obj)/coreboot.rom: $(obj)/coreboot.pre $(obj)/coreboot_ram $(CBFSTOOL)
+	cp $(obj)/coreboot.pre $@
 	if [ -f fallback/coreboot_apc ]; \
 	then \
 		$(CBFSTOOL) $@ add-stage fallback/coreboot_apc fallback/coreboot_apc $(CBFS_COMPRESS_FLAG); \
@@ -33,36 +31,10 @@ 
 	@printf "    CBFSPRINT  $(subst $(obj)/,,$(@))\n\n"
 	$(CBFSTOOL) $(obj)/coreboot.rom print
 
-
 #######################################################################
-# Build the bootblock
-
-$(obj)/coreboot.bootblock: $(obj)/coreboot
-	@printf "    OBJCOPY    $(subst $(obj)/,,$(@))\n"
-	$(OBJCOPY) -O binary $< $@
-
-$(obj)/ldscript.ld: $(ldscripts) $(obj)/ldoptions
-	printf 'INCLUDE "ldoptions"\n' > $@
-	printf '$(foreach ldscript,$(ldscripts),INCLUDE "$(ldscript:$(obj)/%=%)"\n)' >> $@
-
-$(obj)/crt0_includes.h: $(crt0s)
-	printf '$(foreach crt0,config.h $(crt0s),#include "$(crt0:$(obj)/%=%)"\n)' > $@
-
-$(obj)/mainboard/$(MAINBOARDDIR)/crt0.o: $(obj)/mainboard/$(MAINBOARDDIR)/crt0.s
-	$(CC) -I$(obj) -Wa,-acdlns -c -o $@ $<  > $(dir $@)/crt0.disasm
-
-$(obj)/mainboard/$(MAINBOARDDIR)/crt0.s: $(src)/arch/i386/init/crt0.S.lb $(obj)/crt0_includes.h
-	$(CC) -x assembler-with-cpp -DASSEMBLY -E -I$(src)/include -I$(src)/arch/i386/include -I$(obj) -include $(obj)/config.h -I. -I$(src) $< > $@.new && mv $@.new $@
-
-$(obj)/coreboot: $(initobjs) $(obj)/ldscript.ld
-	@printf "    LINK       $(subst $(obj)/,,$(@))\n"
-	$(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(obj)/ldscript.ld $(initobjs)
-	$(NM) -n $(obj)/coreboot | sort > $(obj)/coreboot.map
-
-#######################################################################
 # i386 specific tools
 
-$(obj)/option_table.h $(obj)/option_table.c: $(obj)/build_opt_tbl $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout
+$(obj)/option_table.h $(obj)/option_table.c $(obj)/arch/i386/../../option_table.c: $(obj)/build_opt_tbl $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout
 	@printf "    OPTION     $(subst $(obj)/,,$(@))\n"
 	$(obj)/build_opt_tbl --config $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout --header $(obj)/option_table.h --option $(obj)/option_table.c
 
@@ -91,3 +63,9 @@ 
 # done
 
 endif
+
+ifeq ($(CONFIG_TINY_BOOTBLOCK),y)
+include $(src)/arch/i386/Makefile.tinybootblock.inc
+else
+include $(src)/arch/i386/Makefile.bigbootblock.inc
+endif
Index: src/arch/i386/lib/walkcbfs.S
===================================================================
--- src/arch/i386/lib/walkcbfs.S	(revision 0)
+++ src/arch/i386/lib/walkcbfs.S	(revision 0)
@@ -0,0 +1,94 @@ 
+#define CBFS_HEADER_PTR 0xfffffffc
+
+#define CBFS_HEADER_MAGIC 0
+#define CBFS_HEADER_VERSION (CBFS_HEADER_MAGIC + 4)
+#define CBFS_HEADER_ROMSIZE (CBFS_HEADER_VERSION + 4)
+#define CBFS_HEADER_BOOTBLOCKSIZE (CBFS_HEADER_ROMSIZE + 4)
+#define CBFS_HEADER_ALIGN (CBFS_HEADER_BOOTBLOCKSIZE + 4)
+#define CBFS_HEADER_OFFSET (CBFS_HEADER_ALIGN + 4)
+
+#define CBFS_FILE_MAGIC 0
+#define CBFS_FILE_LEN (CBFS_FILE_MAGIC + 8)
+#define CBFS_FILE_TYPE (CBFS_FILE_LEN + 4)
+#define CBFS_FILE_CHECKSUM (CBFS_FILE_TYPE + 4)
+#define CBFS_FILE_OFFSET (CBFS_FILE_CHECKSUM + 4)
+
+#define CBFS_FILE_STRUCTSIZE (CBFS_FILE_OFFSET + 4)
+
+#define CBFS_STAGE_COMPRESSION 0
+#define CBFS_STAGE_ENTRY (CBFS_STAGE_COMPRESSION + 4)
+#define CBFS_STAGE_LOAD (CBFS_STAGE_ENTRY + 8)
+#define CBFS_STAGE_LEN (CBFS_STAGE_LOAD + 8)
+#define CBFS_STAGE_MEMLEN (CBFS_STAGE_LEN + 4)
+
+/*
+  input %esi: filename
+  input %esp: return address (not pointer to return address!)
+  output %eax: entry point
+  clobbers %ebx, %ecx, %edx, %edi, %ebp
+*/
+walkcbfs:
+	mov %esi, %ebp /* stash away filename pointer */
+	mov $0, %edx
+1:
+	cmpb $0, (%edx,%esi)
+	jz 2f
+	add $1, %edx
+	jmp 1b
+2:
+	add $1, %edx
+	mov CBFS_HEADER_PTR, %eax
+	mov CBFS_HEADER_ROMSIZE(%eax), %ecx
+	bswap %ecx
+	mov $0, %ebx
+	sub %ecx, %ebx
+	mov CBFS_HEADER_OFFSET(%eax), %ecx
+	bswap %ecx
+	add %ecx, %ebx
+	mov CBFS_HEADER_ALIGN(%eax), %eax
+	bswap %eax
+	sub $1, %eax
+
+walker:
+	mov %ebp, %esi
+	mov %ebx, %edi
+	add $CBFS_FILE_STRUCTSIZE, %edi /* edi = address of first byte after struct cbfs_file */
+	mov %edx, %ecx
+	repe cmpsb
+	# zero flag set if strings are equal
+	jnz tryharder
+
+	# we found it!
+	mov CBFS_FILE_OFFSET(%ebx), %eax
+	bswap %eax
+	add %ebx, %eax
+	add $CBFS_STAGE_ENTRY, %eax /* eax = ((cbfs_stage* (cbfs_file* ebx)->offset)->entry) */
+	mov 0(%eax), %eax
+	jmp *%esp
+
+tryharder:
+	mov CBFS_FILE_OFFSET(%ebx), %ecx
+	bswap %ecx
+	add %ebx, %ecx
+	mov CBFS_FILE_LEN(%ebx), %edi
+	bswap %edi
+	add %edi, %ecx
+	add %eax, %ecx
+	mov %eax, %edi
+	not %edi
+	and %edi, %ecx
+	mov %ecx, %ebx
+
+	/* look if we should exit */
+	mov CBFS_HEADER_PTR, %esi
+	mov CBFS_HEADER_ROMSIZE(%esi), %ecx
+	bswap %ecx
+	not %ecx
+	add $1, %ecx
+
+	cmp %ebx, %ecx
+	/* if we're still inside the ROM area, jump back */
+	jbe walker
+
+	mov $0, %eax
+	jmp *%esp
Index: src/arch/i386/Makefile.tinybootblock.inc
===================================================================
--- src/arch/i386/Makefile.tinybootblock.inc	(revision 4988)
+++ src/arch/i386/Makefile.tinybootblock.inc	(working copy)
@@ -1,93 +1,87 @@ 
-#######################################################################
-# Take care of subdirectories
-subdirs-y += boot
-subdirs-y += init
-subdirs-y += lib
-subdirs-y += smp
-
-obj-$(CONFIG_HAVE_OPTION_TABLE) += ../../option_table.o
-
 ifdef POST_EVALUATION
 
 #######################################################################
 # Build the final rom image
 
-$(obj)/coreboot.rom: $(obj)/coreboot.bootblock $(obj)/coreboot_ram $(CBFSTOOL)
+$(obj)/coreboot.pre1: $(obj)/coreboot.bootblock $(CBFSTOOL)
 	rm -f $@
 	$(CBFSTOOL) $@ create $(CONFIG_COREBOOT_ROMSIZE_KB)K $(obj)/coreboot.bootblock
-	if [ -f fallback/coreboot_apc ]; \
-	then \
-		$(CBFSTOOL) $@ add-stage fallback/coreboot_apc fallback/coreboot_apc $(CBFS_COMPRESS_FLAG); \
-	fi
-	$(CBFSTOOL) $@ add-stage $(obj)/coreboot_ram fallback/coreboot_ram $(CBFS_COMPRESS_FLAG)
-ifeq ($(CONFIG_PAYLOAD_NONE),y)
-	@printf "    PAYLOAD    none (as specified by user)\n"
-else
-	@printf "    PAYLOAD    $(CONFIG_FALLBACK_PAYLOAD_FILE) $(CBFS_PAYLOAD_COMPRESS_FLAG)\n"
-	$(CBFSTOOL) $(obj)/coreboot.rom add-payload $(CONFIG_FALLBACK_PAYLOAD_FILE) fallback/payload $(CBFS_PAYLOAD_COMPRESS_FLAG)
-endif
-ifeq ($(CONFIG_VGA_BIOS),y)
-	@printf "    VGABIOS    $(CONFIG_FALLBACK_VGA_BIOS_FILE) $(CONFIG_FALLBACK_VGA_BIOS_ID)\n"
-	$(CBFSTOOL) $(obj)/coreboot.rom add $(CONFIG_FALLBACK_VGA_BIOS_FILE) "pci$(CONFIG_FALLBACK_VGA_BIOS_ID).rom" optionrom
-endif
-	@printf "    CBFSPRINT  $(subst $(obj)/,,$(@))\n\n"
-	$(CBFSTOOL) $(obj)/coreboot.rom print
 
+$(obj)/coreboot.pre: $(obj)/coreboot.romstage $(obj)/coreboot.pre1 $(CBFSTOOL)
+	rm -f $@
+	cp $(obj)/coreboot.pre1 $@
+	$(CBFSTOOL) $@ add-stage $(obj)/romstage.elf fallback/romstage x 0x$(shell cat $(obj)/location.txt)
+#FIXME: location.txt might require an offset of header size
 
 #######################################################################
 # Build the bootblock
 
-$(obj)/coreboot.bootblock: $(obj)/coreboot
+$(obj)/coreboot.bootblock: $(obj)/bootblock.elf
 	@printf "    OBJCOPY    $(subst $(obj)/,,$(@))\n"
 	$(OBJCOPY) -O binary $< $@
 
-$(obj)/ldscript.ld: $(ldscripts) $(obj)/ldoptions
-	printf 'INCLUDE "ldoptions"\n' > $@
-	printf '$(foreach ldscript,$(ldscripts),INCLUDE "$(ldscript:$(obj)/%=%)"\n)' >> $@
+bootblock_lds := $(src)/arch/i386/init/ldscript_failover.lb
+bootblock_lds += $(src)/cpu/x86/16bit/entry16.lds
+bootblock_lds += $(src)/cpu/x86/16bit/reset16.lds
+bootblock_lds += $(src)/arch/i386/lib/id.lds
 
-$(obj)/crt0_includes.h: $(crt0s)
-	printf '$(foreach crt0,config.h $(crt0s),#include "$(crt0:$(obj)/%=%)"\n)' > $@
+bootblock_inc := $(src)/arch/i386/init/bootblock_prologue.c
+bootblock_inc += $(src)/cpu/x86/16bit/entry16.inc
+bootblock_inc += $(src)/cpu/x86/16bit/reset16.inc
+bootblock_inc += $(src)/cpu/x86/32bit/entry32.inc
+bootblock_inc += $(src)/arch/i386/lib/id.inc
+bootblock_inc += $(obj)/mainboard/$(MAINBOARDDIR)/bootblock.inc
+bootblock_inc += $(src)/arch/i386/lib/walkcbfs.S
 
-$(obj)/mainboard/$(MAINBOARDDIR)/crt0.o: $(obj)/mainboard/$(MAINBOARDDIR)/crt0.s
-	$(CC) -I$(obj) -Wa,-acdlns -c -o $@ $<  > $(dir $@)/crt0.disasm
+$(obj)/bootblock/ldscript.ld: $(bootblock_ldscripts) $(obj)/ldoptions
+	mkdir -p $(obj)/bootblock
+	printf '$(foreach ldscript,ldoptions $(bootblock_lds),INCLUDE "$(ldscript)"\n)' > $@
 
-$(obj)/mainboard/$(MAINBOARDDIR)/crt0.s: $(src)/arch/i386/init/crt0.S.lb $(obj)/crt0_includes.h
-	$(CC) -x assembler-with-cpp -DASSEMBLY -E -I$(src)/include -I$(src)/arch/i386/include -I$(obj) -include $(obj)/config.h -I. -I$(src) $< > $@.new && mv $@.new $@
+$(obj)/bootblock/bootblock.c: $(bootblock_inc)
+	mkdir -p $(obj)/bootblock
+	printf '$(foreach crt0,config.h $(bootblock_inc),#include "$(crt0)"\n)' > $@
 
-$(obj)/coreboot: $(initobjs) $(obj)/ldscript.ld
-	@printf "    LINK       $(subst $(obj)/,,$(@))\n"
-	$(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(obj)/ldscript.ld $(initobjs)
-	$(NM) -n $(obj)/coreboot | sort > $(obj)/coreboot.map
+$(obj)/mainboard/$(MAINBOARDDIR)/bootblock.o: $(obj)/mainboard/$(MAINBOARDDIR)/bootblock.s
+	$(CC) -I$(obj) -Wa,-acdlns -c -o $@ $<  > $(dir $@)/crt0.disasm
 
-#######################################################################
-# i386 specific tools
+$(obj)/mainboard/$(MAINBOARDDIR)/bootblock.s: $(obj)/bootblock/bootblock.c
+	$(CC) -x assembler-with-cpp -DASSEMBLY -E -I$(src)/include -I$(src)/arch/i386/include -I$(obj) -I$(obj)/bootblock -include $(obj)/config.h -I. -I$(src) $< > $@.new && mv $@.new $@
 
-$(obj)/option_table.h $(obj)/option_table.c: $(obj)/build_opt_tbl $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout
-	@printf "    OPTION     $(subst $(obj)/,,$(@))\n"
-	$(obj)/build_opt_tbl --config $(top)/src/mainboard/$(MAINBOARDDIR)/cmos.layout --header $(obj)/option_table.h --option $(obj)/option_table.c
+$(obj)/mainboard/$(MAINBOARDDIR)/bootblock.inc: $(obj)/romcc $(src)/arch/i386/init/bootblock.c
+	$(obj)/romcc $(ROMCCFLAGS) $(INCLUDES) $(src)/arch/i386/init/bootblock.c -o $@
 
-$(obj)/build_opt_tbl: $(top)/util/options/build_opt_tbl.c $(top)/src/include/pc80/mc146818rtc.h $(top)/src/include/boot/coreboot_tables.h $(obj)/config.h
-	@printf "    HOSTCC     $(subst $(obj)/,,$(@))\n"
-	$(HOSTCC) $(HOSTCFLAGS) -include $(obj)/config.h $< -o $@
+$(obj)/bootblock.elf: $(obj)/mainboard/$(MAINBOARDDIR)/bootblock.o $(obj)/bootblock/ldscript.ld
+	@printf "    LINK       $(subst $(obj)/,,$(@))\n"
+	$(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(obj)/bootblock/ldscript.ld $<
+	$(NM) -n $(obj)/bootblock.elf | sort > $(obj)/bootblock.map
 
 #######################################################################
-# Build the coreboot_ram (stage 2)
+# Build the romstage
+$(obj)/coreboot.romstage: $(obj)/coreboot.pre1 $(initobjs) $(obj)/romstage/ldscript.ld
+	@printf "    LINK       $(subst $(obj)/,,$(@))\n"
+	printf "CONFIG_ROMBASE = 0x0;\n" > $(obj)/location.ld
+	$(CC) -nostdlib -nostartfiles -static -o $(obj)/romstage.elf -L$(obj) -T $(obj)/romstage/ldscript.ld $(initobjs)
+	$(OBJCOPY) -O binary $(obj)/romstage.elf $(obj)/romstage.bin
+	printf "CONFIG_ROMBASE = 0x" > $(obj)/location.ld
+	$(CBFSTOOL) $(obj)/coreboot.pre1 locate $(obj)/romstage.bin fallback/romstage $(CONFIG_XIP_ROM_SIZE) > $(obj)/location.txt
+	cat $(obj)/location.txt >> $(obj)/location.ld
+	printf ";\n" >> $(obj)/location.ld
+	$(CC) -nostdlib -nostartfiles -static -o $(obj)/romstage.elf -L$(obj) -T $(obj)/romstage/ldscript.ld $(initobjs)
+	$(NM) -n $(obj)/romstage.elf | sort > $(obj)/romstage.map
+	$(OBJCOPY) -O binary $(obj)/romstage.elf $@
 
-$(obj)/coreboot_ram: $(obj)/coreboot_ram.o $(src)/config/coreboot_ram.ld #ldoptions
-	@printf "    CC         $(subst $(obj)/,,$(@))\n"
-	$(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T $(src)/config/coreboot_ram.ld $(obj)/coreboot_ram.o
-	$(NM) -n $(obj)/coreboot_ram | sort > $(obj)/coreboot_ram.map
+$(obj)/romstage/ldscript.ld: $(ldscripts) $(obj)/ldoptions
+	mkdir -p $(obj)/romstage
+	printf '$(foreach ldscript,ldoptions location.ld $(ldscripts),INCLUDE "$(ldscript:$(obj)/%=%)"\n)' > $@
 
-$(obj)/coreboot_ram.o: $(obj)/arch/i386/lib/c_start.o $(drivers) $(obj)/coreboot.a $(LIBGCC_FILE_NAME)
-	@printf "    CC         $(subst $(obj)/,,$(@))\n"
-	$(CC) -nostdlib -r -o $@ $(obj)/arch/i386/lib/c_start.o $(drivers) -Wl,-\( $(obj)/coreboot.a $(LIBGCC_FILE_NAME) -Wl,-\)
+$(obj)/romstage/crt0_includes.h: $(crt0s)
+	mkdir -p $(obj)/romstage
+	printf '$(foreach crt0,config.h $(crt0s),#include "$(crt0:$(obj)/%=%)"\n)' > $@
 
-$(obj)/coreboot.a: $(objs)
-	@printf "    AR         $(subst $(obj)/,,$(@))\n"
-	rm -f $(obj)/coreboot.a
-	$(AR) cr $(obj)/coreboot.a $(objs)
+$(obj)/mainboard/$(MAINBOARDDIR)/crt0.o: $(obj)/mainboard/$(MAINBOARDDIR)/crt0.s
+	$(CC) -I$(obj) -Wa,-acdlns -c -o $@ $<  > $(dir $@)/crt0.disasm
 
-#######################################################################
-# done
+$(obj)/mainboard/$(MAINBOARDDIR)/crt0.s: $(src)/arch/i386/init/crt0.S.lb $(obj)/romstage/crt0_includes.h
+	$(CC) -x assembler-with-cpp -DASSEMBLY -E -I$(src)/include -I$(src)/arch/i386/include -I$(obj) -I$(obj)/romstage -include $(obj)/config.h -I. -I$(src) $< > $@.new && mv $@.new $@
 
 endif
Index: util/cbfstool/cbfs-mkstage.c
===================================================================
--- util/cbfstool/cbfs-mkstage.c	(revision 4988)
+++ util/cbfstool/cbfs-mkstage.c	(working copy)
@@ -122,6 +122,10 @@ 
 			mem_end = mend;
 	}
 
+	if (data_start < *location) {
+		data_start = *location;
+	}
+
 	/* allocate an intermediate buffer for the data */
 	buffer = calloc(data_end - data_start, 1);
 
@@ -133,6 +137,7 @@ 
 	/* Copy the file data into the buffer */
 
 	for (i = 0; i < headers; i++) {
+		unsigned int l_start, l_offset = 0;
 
 		if (elf32_to_native(phdr[i].p_type) != PT_LOAD)
 			continue;
@@ -140,9 +145,15 @@ 
 		if (elf32_to_native(phdr[i].p_memsz) == 0)
 			continue;
 
-		memcpy(buffer + (elf32_to_native(phdr[i].p_paddr) - data_start),
-		       &header[elf32_to_native(phdr[i].p_offset)],
-		       elf32_to_native(phdr[i].p_filesz));
+		l_start = elf32_to_native(phdr[i].p_paddr);
+		if (l_start < *location) {
+			l_offset = *location - l_start;
+			l_start = *location;
+		}
+
+		memcpy(buffer + (l_start - data_start),
+		       &header[elf32_to_native(phdr[i].p_offset)+l_offset],
+		       elf32_to_native(phdr[i].p_filesz)-l_offset);
 	}
 
 	/* Now make the output buffer */
Index: Makefile
===================================================================
--- Makefile	(revision 4988)
+++ Makefile	(working copy)
@@ -293,6 +293,7 @@ 
 
 clean: doxygen-clean
 	rm -f $(allobjs) $(obj)/coreboot*
+	rm -rf $(obj)/bootblock* $(obj)/romstage* $(obj)/location.*
 	rm -f $(obj)/option_table.* $(obj)/crt0_includes.h $(obj)/ldscript
 	rm -f $(obj)/mainboard/$(MAINBOARDDIR)/static.c $(obj)/mainboard/$(MAINBOARDDIR)/config.py $(obj)/mainboard/$(MAINBOARDDIR)/static.dot
 	rm -f $(obj)/mainboard/$(MAINBOARDDIR)/auto.inc $(obj)/mainboard/$(MAINBOARDDIR)/crt0.s $(obj)/mainboard/$(MAINBOARDDIR)/crt0.disasm