x86: Add support for U-Boot as an EFI application

Add the required x86 glue code. This includes the initial start-up,
relocation and jumping to efi_main(). We also need to avoid fiddling with
interrupts.

Signed-off-by: Ben Stoltz <stoltz@google.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 8a8e63e..5e058c0 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -14,6 +14,7 @@
 
 obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
 obj-$(CONFIG_SYS_COREBOOT) += coreboot/
+obj-$(CONFIG_EFI_APP) += efi/
 obj-$(CONFIG_QEMU) += qemu/
 obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
 obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
diff --git a/arch/x86/cpu/efi/Makefile b/arch/x86/cpu/efi/Makefile
new file mode 100644
index 0000000..e091637
--- /dev/null
+++ b/arch/x86/cpu/efi/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2015 Google, Inc
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += efi.o
+obj-y += sdram.o
diff --git a/arch/x86/cpu/efi/efi.c b/arch/x86/cpu/efi/efi.c
new file mode 100644
index 0000000..75ba0d4
--- /dev/null
+++ b/arch/x86/cpu/efi/efi.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <netdev.h>
+
+int arch_cpu_init(void)
+{
+#ifdef CONFIG_SYS_X86_TSC_TIMER
+	timer_set_base(rdtsc());
+#endif
+
+	return 0;
+}
+
+int board_early_init_f(void)
+{
+	return 0;
+}
+
+int print_cpuinfo(void)
+{
+	return default_print_cpuinfo();
+}
+
+void board_final_cleanup(void)
+{
+}
+
+int misc_init_r(void)
+{
+	return 0;
+}
+
+int arch_misc_init(void)
+{
+	return 0;
+}
diff --git a/arch/x86/cpu/efi/elf_ia32_efi.lds b/arch/x86/cpu/efi/elf_ia32_efi.lds
new file mode 100644
index 0000000..cd3b0a9
--- /dev/null
+++ b/arch/x86/cpu/efi/elf_ia32_efi.lds
@@ -0,0 +1,94 @@
+/*
+ * U-Boot EFI linker script
+ *
+ * SPDX-License-Identifier:	BSD-2-Clause
+ *
+ * Modified from usr/lib32/elf_ia32_efi.lds in gnu-efi
+ */
+
+#include <config.h>
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+	image_base = .;
+	.hash : { *(.hash) }	/* this MUST come first, EFI expects it */
+	. = ALIGN(4096);
+	.text :
+	{
+		*(.text)
+		*(.text.*)
+		*(.gnu.linkonce.t.*)
+	}
+	. = ALIGN(4096);
+	.sdata :
+	{
+		*(.got.plt)
+		*(.got)
+		*(.srodata)
+		*(.sdata)
+		*(.sbss)
+		*(.scommon)
+	}
+	. = ALIGN(4096);
+	.data :
+	{
+		*(.rodata*)
+		*(.data)
+		*(.data1)
+		*(.data.*)
+		*(.sdata)
+		*(.got.plt)
+		*(.got)
+		/*
+		 * the EFI loader doesn't seem to like a .bss section, so we
+		 * stick it all into .data:
+		 */
+		*(.sbss)
+		*(.scommon)
+		*(.dynbss)
+		*(.bss)
+		*(COMMON)
+
+		/* U-Boot lists and device tree */
+		. = ALIGN(8);
+		*(SORT(.u_boot_list*));
+		. = ALIGN(8);
+		*(.dtb*);
+	}
+
+	. = ALIGN(4096);
+	.dynamic  : { *(.dynamic) }
+	. = ALIGN(4096);
+	.rel :
+	{
+		*(.rel.data)
+		*(.rel.data.*)
+		*(.rel.got)
+		*(.rel.stab)
+		*(.data.rel.ro.local)
+		*(.data.rel.local)
+		*(.data.rel.ro)
+		*(.data.rel*)
+		*(.rel.u_boot_list*)
+	}
+	. = ALIGN(4096);
+		.reloc :	/* This is the PECOFF .reloc section! */
+	{
+	*(.reloc)
+	}
+	. = ALIGN(4096);
+	.dynsym   : { *(.dynsym) }
+	. = ALIGN(4096);
+	.dynstr   : { *(.dynstr) }
+	. = ALIGN(4096);
+	/DISCARD/ :
+	{
+		*(.rel.reloc)
+		*(.eh_frame)
+		*(.note.GNU-stack)
+	}
+	.comment 0 : { *(.comment) }
+}
diff --git a/arch/x86/cpu/efi/sdram.c b/arch/x86/cpu/efi/sdram.c
new file mode 100644
index 0000000..5159944
--- /dev/null
+++ b/arch/x86/cpu/efi/sdram.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <efi.h>
+#include <asm/u-boot-x86.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+ulong board_get_usable_ram_top(ulong total_size)
+{
+	return (ulong)efi_get_ram_base() + gd->ram_size;
+}
+
+int dram_init(void)
+{
+	/* gd->ram_size is set as part of EFI init */
+
+	return 0;
+}
+
+void dram_init_banksize(void)
+{
+	gd->bd->bi_dram[0].start = efi_get_ram_base();
+	gd->bd->bi_dram[0].size = CONFIG_EFI_RAM_SIZE;
+}
diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c
index 3a9c2d4..a112938 100644
--- a/arch/x86/cpu/interrupts.c
+++ b/arch/x86/cpu/interrupts.c
@@ -242,6 +242,11 @@
 
 int interrupt_init(void)
 {
+	/*
+	 * When running as an EFI application we are not in control of
+	 * interrupts and should leave them alone.
+	 */
+#ifndef CONFIG_EFI_APP
 	/* Just in case... */
 	disable_interrupts();
 
@@ -255,6 +260,7 @@
 
 	/* It is now safe to enable interrupts */
 	enable_interrupts();
+#endif
 
 	return 0;
 }