coreboot: introduce CONFIG_RELOCATABLE_RAMSTAGE

This patch adds an option to build the ramstage as a reloctable binary.
It uses the rmodule library for the relocation. The main changes
consist of the following:

1. The ramstage is loaded just under the cmbem space.
2. Payloads cannot be loaded over where ramstage is loaded. If a payload
   is attempted to load where the relocatable ramstage resides the load
   is aborted.
3. The memory occupied by the ramstage is reserved from the OS's usage
   using the romstage_handoff structure stored in cbmem. This region is
   communicated to ramstage by an CBMEM_ID_ROMSTAGE_INFO entry in cbmem.
4. There is no need to reserve cbmem space for the OS controlled memory for
   the resume path because the ramsage region has been reserved in #3.
5. Since no memory needs to be preserved in the wake path, the loading
   and begin of execution of a elf payload is straight forward.

Change-Id: Ia66cf1be65c29fa25ca7bd9ea6c8f11d7eee05f5
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/2792
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@google.com>
diff --git a/src/arch/x86/boot/boot.c b/src/arch/x86/boot/boot.c
index d9cb02e..4892c5e 100644
--- a/src/arch/x86/boot/boot.c
+++ b/src/arch/x86/boot/boot.c
@@ -68,6 +68,34 @@
 
 }
 
+#if CONFIG_RELOCATABLE_RAMSTAGE
+/* When the ramstage is relocatable the elf loading ensures an elf image cannot
+ * be loaded over the ramstage code. */
+void jmp_to_elf_entry(void *entry, unsigned long unused1, unsigned long unused2)
+{
+	elf_boot_notes.hdr.b_checksum =
+		compute_ip_checksum(&elf_boot_notes, sizeof(elf_boot_notes));
+
+	/* Jump to kernel */
+	__asm__ __volatile__(
+		"	cld	\n\t"
+		/* Now jump to the loaded image */
+		"	call	*%0\n\t"
+
+		/* The loaded image returned? */
+		"	cli	\n\t"
+		"	cld	\n\t"
+
+		::
+		"r" (entry),
+#if CONFIG_MULTIBOOT
+		"b"(mbi), "a" (MB_MAGIC2)
+#else
+		"b"(&elf_boot_notes), "a" (0x0E1FB007)
+#endif
+		);
+}
+#else
 void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size)
 {
 	extern unsigned char _ram_seg, _eram_seg;
@@ -182,5 +210,6 @@
 #endif
 		);
 }
+#endif /* CONFIG_RELOCATABLE_RAMSTAGE */