Merge git://git.denx.de/u-boot-x86

Conflicts:
	arch/x86/cpu/Makefile

Signed-off-by: Tom Rini <trini@ti.com>
diff --git a/Makefile b/Makefile
index 590fec8..db82dfe 100644
--- a/Makefile
+++ b/Makefile
@@ -746,6 +746,9 @@
 endif
 ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf
 
+# We can't do this yet due to the need for binary blobs
+# ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
+
 # enable combined SPL/u-boot/dtb rules for tegra
 ifneq ($(CONFIG_TEGRA),)
 ifeq ($(CONFIG_SPL),y)
@@ -814,7 +817,8 @@
 u-boot.hex u-boot.srec: u-boot FORCE
 	$(call if_changed,objcopy)
 
-OBJCOPYFLAGS_u-boot.bin := -O binary
+OBJCOPYFLAGS_u-boot.bin := -O binary \
+		$(if $(CONFIG_X86_RESET_VECTOR),-R .start16 -R .resetvec)
 
 binary_size_check: u-boot.bin FORCE
 	@file_size=$(shell wc -c u-boot.bin | awk '{print $$1}') ; \
@@ -953,6 +957,36 @@
 	$(call if_changed,mkimage)
 	@dd if=/dev/zero bs=8 count=1 2>/dev/null >> $@
 
+# x86 uses a large ROM. We fill it with 0xff, put the 16-bit stuff (including
+# reset vector) at the top, Intel ME descriptor at the bottom, and U-Boot in
+# the middle.
+ifneq ($(CONFIG_X86_RESET_VECTOR),)
+rom: u-boot.rom FORCE
+
+u-boot.rom: u-boot-x86-16bit.bin u-boot-dtb.bin \
+		$(srctree)/board/$(BOARDDIR)/mrc.bin
+	$(objtree)/tools/ifdtool -c -r $(CONFIG_ROM_SIZE) u-boot.tmp
+	if [ -n "$(CONFIG_HAVE_INTEL_ME)" ]; then \
+		$(objtree)/tools/ifdtool -D \
+			$(srctree)/board/$(BOARDDIR)/descriptor.bin u-boot.tmp; \
+		$(objtree)/tools/ifdtool \
+			-i ME:$(srctree)/board/$(BOARDDIR)/me.bin u-boot.tmp; \
+	fi
+	$(objtree)/tools/ifdtool -w \
+		$(CONFIG_SYS_TEXT_BASE):$(objtree)/u-boot-dtb.bin u-boot.tmp
+	$(objtree)/tools/ifdtool -w \
+		$(CONFIG_X86_MRC_START):$(srctree)/board/$(BOARDDIR)/mrc.bin \
+		u-boot.tmp
+	$(objtree)/tools/ifdtool -w \
+		$(CONFIG_SYS_X86_START16):$(objtree)/u-boot-x86-16bit.bin \
+		u-boot.tmp
+	mv u-boot.tmp $@
+
+OBJCOPYFLAGS_u-boot-x86-16bit.bin := -O binary -j .start16 -j .resetvec
+u-boot-x86-16bit.bin: u-boot FORCE
+	$(call if_changed,objcopy)
+endif
+
 ifneq ($(CONFIG_SUNXI),)
 OBJCOPYFLAGS_u-boot-sunxi-with-spl.bin = -I binary -O binary \
 				   --pad-to=$(CONFIG_SPL_PAD_TO) --gap-fill=0xff
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0dba8ac..6e29868 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -12,9 +12,81 @@
 
 config TARGET_COREBOOT
 	bool "Support coreboot"
+	help
+	  This target is used for running U-Boot on top of Coreboot. In
+	  this case Coreboot does the early inititalisation, and U-Boot
+	  takes over once the RAM, video and CPU are fully running.
+	  U-Boot is loaded as a fallback payload from Coreboot, in
+	  Coreboot terminology. This method was used for the Chromebook
+	  Pixel when launched.
+
+config TARGET_CHROMEBOOK_LINK
+	bool "Support Chromebook link"
+	help
+	  This is the Chromebook Pixel released in 2013. It uses an Intel
+	  i5 Ivybridge which is a die-shrink of Sandybridge, with 4GB of
+	  SDRAM. It has a Panther Point platform controller hub, PCIe
+	  WiFi and Bluetooth. It also includes a 720p webcam, USB SD
+	  reader, microphone and speakers, display port and 32GB SATA
+	  solid state drive. There is a Chrome OS EC connected on LPC,
+	  and it provides a 2560x1700 high resolution touch-enabled LCD
+	  display.
 
 endchoice
 
-source "board/chromebook-x86/coreboot/Kconfig"
+config RAMBASE
+	hex
+	default 0x100000
+
+config RAMTOP
+	hex
+	default 0x200000
+
+config XIP_ROM_SIZE
+	hex
+	default 0x10000
+
+config CPU_ADDR_BITS
+	int
+	default 36
+
+config HPET_ADDRESS
+	hex
+	default 0xfed00000 if !HPET_ADDRESS_OVERRIDE
+
+config SMM_TSEG
+	bool
+	default n
+
+config SMM_TSEG_SIZE
+	hex
+
+config ROM_SIZE
+	hex
+	default 0x800000
+
+config HAVE_INTEL_ME
+	bool "Platform requires Intel Management Engine"
+	help
+	  Newer higher-end devices have an Intel Management Engine (ME)
+	  which is a very large binary blob (typically 1.5MB) which is
+	  required for the platform to work. This enforces a particular
+	  SPI flash format. You will need to supply the me.bin file in
+	  your board directory.
+
+config X86_RAMTEST
+	bool "Perform a simple RAM test after SDRAM initialisation"
+	help
+	  If there is something wrong with SDRAM then the platform will
+	  often crash within U-Boot or the kernel. This option enables a
+	  very simple RAM test that quickly checks whether the SDRAM seems
+	  to work correctly. It is not exhaustive but can save time by
+	  detecting obvious failures.
+
+source "arch/x86/cpu/ivybridge/Kconfig"
+
+source "board/coreboot/coreboot/Kconfig"
+
+source "board/google/chromebook_link/Kconfig"
 
 endmenu
diff --git a/arch/x86/config.mk b/arch/x86/config.mk
index 3e7fedb..bb2da46 100644
--- a/arch/x86/config.mk
+++ b/arch/x86/config.mk
@@ -15,7 +15,6 @@
 		     $(call cc-option, -mpreferred-stack-boundary=2)
 PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_X86)
 PLATFORM_CPPFLAGS += -fno-dwarf2-cfi-asm
-PLATFORM_CPPFLAGS += -DREALMODE_BASE=0x7c0
 PLATFORM_CPPFLAGS += -march=i386 -m32
 
 # Support generic board on x86
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 8dd7b06..2b9e9b9 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -13,3 +13,4 @@
 obj-y	+= interrupts.o cpu.o call64.o
 
 obj-$(CONFIG_SYS_COREBOOT) += coreboot/
+obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c
index e24f13a..2df7288 100644
--- a/arch/x86/cpu/coreboot/coreboot.c
+++ b/arch/x86/cpu/coreboot/coreboot.c
@@ -13,25 +13,25 @@
 #include <ns16550.h>
 #include <asm/msr.h>
 #include <asm/cache.h>
+#include <asm/cpu.h>
 #include <asm/io.h>
-#include <asm/arch-coreboot/tables.h>
-#include <asm/arch-coreboot/sysinfo.h>
+#include <asm/arch/tables.h>
+#include <asm/arch/sysinfo.h>
 #include <asm/arch/timestamp.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-/*
- * Miscellaneous platform dependent initializations
- */
-int cpu_init_f(void)
+int arch_cpu_init(void)
 {
 	int ret = get_coreboot_info(&lib_sysinfo);
-	if (ret != 0)
+	if (ret != 0) {
 		printf("Failed to parse coreboot tables.\n");
+		return ret;
+	}
 
 	timestamp_init();
 
-	return ret;
+	return x86_cpu_init_f();
 }
 
 int board_early_init_f(void)
@@ -50,27 +50,9 @@
 	return 0;
 }
 
-void show_boot_progress(int val)
+int print_cpuinfo(void)
 {
-#if MIN_PORT80_KCLOCKS_DELAY
-	/*
-	 * Scale the time counter reading to avoid using 64 bit arithmetics.
-	 * Can't use get_timer() here becuase it could be not yet
-	 * initialized or even implemented.
-	 */
-	if (!gd->arch.tsc_prev) {
-		gd->arch.tsc_base_kclocks = rdtsc() / 1000;
-		gd->arch.tsc_prev = 0;
-	} else {
-		uint32_t now;
-
-		do {
-			now = rdtsc() / 1000 - gd->arch.tsc_base_kclocks;
-		} while (now < (gd->arch.tsc_prev + MIN_PORT80_KCLOCKS_DELAY));
-		gd->arch.tsc_prev = now;
-	}
-#endif
-	outb(val, 0x80);
+	return default_print_cpuinfo();
 }
 
 int last_stage_init(void)
@@ -98,7 +80,7 @@
 #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
 #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
 
-int board_final_cleanup(void)
+void board_final_cleanup(void)
 {
 	/* Un-cache the ROM so the kernel has one
 	 * more MTRR available.
@@ -120,8 +102,6 @@
 	/* Issue SMI to Coreboot to lock down ME and registers */
 	printf("Finalizing Coreboot\n");
 	outb(0xcb, 0xb2);
-
-	return 0;
 }
 
 void panic_puts(const char *str)
diff --git a/arch/x86/cpu/coreboot/ipchecksum.c b/arch/x86/cpu/coreboot/ipchecksum.c
index 57733d8..5f6c009 100644
--- a/arch/x86/cpu/coreboot/ipchecksum.c
+++ b/arch/x86/cpu/coreboot/ipchecksum.c
@@ -30,7 +30,7 @@
  */
 
 #include <compiler.h>
-#include <asm/arch-coreboot/ipchecksum.h>
+#include <asm/arch/ipchecksum.h>
 
 unsigned short ipchksum(const void *vptr, unsigned long nbytes)
 {
diff --git a/arch/x86/cpu/coreboot/pci.c b/arch/x86/cpu/coreboot/pci.c
index b35d70c..6a3dd93 100644
--- a/arch/x86/cpu/coreboot/pci.c
+++ b/arch/x86/cpu/coreboot/pci.c
@@ -13,8 +13,6 @@
 #include <pci.h>
 #include <asm/pci.h>
 
-static struct pci_controller coreboot_hose;
-
 static void config_pci_bridge(struct pci_controller *hose, pci_dev_t dev,
 			      struct pci_config_table *table)
 {
@@ -31,19 +29,13 @@
 	{}
 };
 
-void pci_init_board(void)
+void board_pci_setup_hose(struct pci_controller *hose)
 {
-	coreboot_hose.config_table = pci_coreboot_config_table;
-	coreboot_hose.first_busno = 0;
-	coreboot_hose.last_busno = 0;
+	hose->config_table = pci_coreboot_config_table;
+	hose->first_busno = 0;
+	hose->last_busno = 0;
 
-	pci_set_region(coreboot_hose.regions + 0, 0x0, 0x0, 0xffffffff,
-		PCI_REGION_MEM);
-	coreboot_hose.region_count = 1;
-
-	pci_setup_type1(&coreboot_hose);
-
-	pci_register_hose(&coreboot_hose);
-
-	pci_hose_scan(&coreboot_hose);
+	pci_set_region(hose->regions + 0, 0x0, 0x0, 0xffffffff,
+		       PCI_REGION_MEM);
+	hose->region_count = 1;
 }
diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c
index 3140b6b..e98a230 100644
--- a/arch/x86/cpu/coreboot/sdram.c
+++ b/arch/x86/cpu/coreboot/sdram.c
@@ -11,8 +11,10 @@
 #include <asm/e820.h>
 #include <asm/u-boot-x86.h>
 #include <asm/global_data.h>
+#include <asm/init_helpers.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
+#include <asm/zimage.h>
 #include <asm/arch/sysinfo.h>
 #include <asm/arch/tables.h>
 
@@ -79,7 +81,7 @@
 	return (ulong)dest_addr;
 }
 
-int dram_init_f(void)
+int dram_init(void)
 {
 	int i;
 	phys_size_t ram_size = 0;
@@ -94,10 +96,11 @@
 	gd->ram_size = ram_size;
 	if (ram_size == 0)
 		return -1;
-	return 0;
+
+	return calculate_relocation_address();
 }
 
-int dram_init_banksize(void)
+void dram_init_banksize(void)
 {
 	int i, j;
 
@@ -114,10 +117,4 @@
 			}
 		}
 	}
-	return 0;
-}
-
-int dram_init(void)
-{
-	return dram_init_banksize();
 }
diff --git a/arch/x86/cpu/coreboot/tables.c b/arch/x86/cpu/coreboot/tables.c
index 0d91adc..92b7528 100644
--- a/arch/x86/cpu/coreboot/tables.c
+++ b/arch/x86/cpu/coreboot/tables.c
@@ -8,9 +8,9 @@
  */
 
 #include <common.h>
-#include <asm/arch-coreboot/ipchecksum.h>
-#include <asm/arch-coreboot/sysinfo.h>
-#include <asm/arch-coreboot/tables.h>
+#include <asm/arch/ipchecksum.h>
+#include <asm/arch/sysinfo.h>
+#include <asm/arch/tables.h>
 
 /*
  * This needs to be in the .data section so that it's copied over during
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index 2e25253..b391b7a 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -13,6 +13,9 @@
  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  * Alex Zuepke <azu@sysgo.de>
  *
+ * Part of this file is adapted from coreboot
+ * src/arch/x86/lib/cpu.c
+ *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
@@ -22,11 +25,14 @@
 #include <malloc.h>
 #include <asm/control_regs.h>
 #include <asm/cpu.h>
+#include <asm/post.h>
 #include <asm/processor.h>
 #include <asm/processor-flags.h>
 #include <asm/interrupt.h>
 #include <linux/compiler.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /*
  * Constructor for a conventional segment GDT (or LDT) entry
  * This is a macro so it can be used in initialisers
@@ -43,6 +49,52 @@
 	u32 ptr;
 } __packed;
 
+struct cpu_device_id {
+	unsigned vendor;
+	unsigned device;
+};
+
+struct cpuinfo_x86 {
+	uint8_t x86;            /* CPU family */
+	uint8_t x86_vendor;     /* CPU vendor */
+	uint8_t x86_model;
+	uint8_t x86_mask;
+};
+
+/*
+ * List of cpu vendor strings along with their normalized
+ * id values.
+ */
+static struct {
+	int vendor;
+	const char *name;
+} x86_vendors[] = {
+	{ X86_VENDOR_INTEL,     "GenuineIntel", },
+	{ X86_VENDOR_CYRIX,     "CyrixInstead", },
+	{ X86_VENDOR_AMD,       "AuthenticAMD", },
+	{ X86_VENDOR_UMC,       "UMC UMC UMC ", },
+	{ X86_VENDOR_NEXGEN,    "NexGenDriven", },
+	{ X86_VENDOR_CENTAUR,   "CentaurHauls", },
+	{ X86_VENDOR_RISE,      "RiseRiseRise", },
+	{ X86_VENDOR_TRANSMETA, "GenuineTMx86", },
+	{ X86_VENDOR_TRANSMETA, "TransmetaCPU", },
+	{ X86_VENDOR_NSC,       "Geode by NSC", },
+	{ X86_VENDOR_SIS,       "SiS SiS SiS ", },
+};
+
+static const char *const x86_vendor_name[] = {
+	[X86_VENDOR_INTEL]     = "Intel",
+	[X86_VENDOR_CYRIX]     = "Cyrix",
+	[X86_VENDOR_AMD]       = "AMD",
+	[X86_VENDOR_UMC]       = "UMC",
+	[X86_VENDOR_NEXGEN]    = "NexGen",
+	[X86_VENDOR_CENTAUR]   = "Centaur",
+	[X86_VENDOR_RISE]      = "Rise",
+	[X86_VENDOR_TRANSMETA] = "Transmeta",
+	[X86_VENDOR_NSC]       = "NSC",
+	[X86_VENDOR_SIS]       = "SiS",
+};
+
 static void load_ds(u32 segment)
 {
 	asm volatile("movl %0, %%ds" : : "r" (segment * X86_GDT_ENTRY_SIZE));
@@ -115,6 +167,129 @@
 	return 0;
 }
 
+/*
+ * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
+ * by the fact that they preserve the flags across the division of 5/2.
+ * PII and PPro exhibit this behavior too, but they have cpuid available.
+ */
+
+/*
+ * Perform the Cyrix 5/2 test. A Cyrix won't change
+ * the flags, while other 486 chips will.
+ */
+static inline int test_cyrix_52div(void)
+{
+	unsigned int test;
+
+	__asm__ __volatile__(
+	     "sahf\n\t"		/* clear flags (%eax = 0x0005) */
+	     "div %b2\n\t"	/* divide 5 by 2 */
+	     "lahf"		/* store flags into %ah */
+	     : "=a" (test)
+	     : "0" (5), "q" (2)
+	     : "cc");
+
+	/* AH is 0x02 on Cyrix after the divide.. */
+	return (unsigned char) (test >> 8) == 0x02;
+}
+
+/*
+ *	Detect a NexGen CPU running without BIOS hypercode new enough
+ *	to have CPUID. (Thanks to Herbert Oppmann)
+ */
+
+static int deep_magic_nexgen_probe(void)
+{
+	int ret;
+
+	__asm__ __volatile__ (
+		"	movw	$0x5555, %%ax\n"
+		"	xorw	%%dx,%%dx\n"
+		"	movw	$2, %%cx\n"
+		"	divw	%%cx\n"
+		"	movl	$0, %%eax\n"
+		"	jnz	1f\n"
+		"	movl	$1, %%eax\n"
+		"1:\n"
+		: "=a" (ret) : : "cx", "dx");
+	return  ret;
+}
+
+static bool has_cpuid(void)
+{
+	return flag_is_changeable_p(X86_EFLAGS_ID);
+}
+
+static int build_vendor_name(char *vendor_name)
+{
+	struct cpuid_result result;
+	result = cpuid(0x00000000);
+	unsigned int *name_as_ints = (unsigned int *)vendor_name;
+
+	name_as_ints[0] = result.ebx;
+	name_as_ints[1] = result.edx;
+	name_as_ints[2] = result.ecx;
+
+	return result.eax;
+}
+
+static void identify_cpu(struct cpu_device_id *cpu)
+{
+	char vendor_name[16];
+	int i;
+
+	vendor_name[0] = '\0'; /* Unset */
+	cpu->device = 0; /* fix gcc 4.4.4 warning */
+
+	/* Find the id and vendor_name */
+	if (!has_cpuid()) {
+		/* Its a 486 if we can modify the AC flag */
+		if (flag_is_changeable_p(X86_EFLAGS_AC))
+			cpu->device = 0x00000400; /* 486 */
+		else
+			cpu->device = 0x00000300; /* 386 */
+		if ((cpu->device == 0x00000400) && test_cyrix_52div()) {
+			memcpy(vendor_name, "CyrixInstead", 13);
+			/* If we ever care we can enable cpuid here */
+		}
+		/* Detect NexGen with old hypercode */
+		else if (deep_magic_nexgen_probe())
+			memcpy(vendor_name, "NexGenDriven", 13);
+	}
+	if (has_cpuid()) {
+		int  cpuid_level;
+
+		cpuid_level = build_vendor_name(vendor_name);
+		vendor_name[12] = '\0';
+
+		/* Intel-defined flags: level 0x00000001 */
+		if (cpuid_level >= 0x00000001) {
+			cpu->device = cpuid_eax(0x00000001);
+		} else {
+			/* Have CPUID level 0 only unheard of */
+			cpu->device = 0x00000400;
+		}
+	}
+	cpu->vendor = X86_VENDOR_UNKNOWN;
+	for (i = 0; i < ARRAY_SIZE(x86_vendors); i++) {
+		if (memcmp(vendor_name, x86_vendors[i].name, 12) == 0) {
+			cpu->vendor = x86_vendors[i].vendor;
+			break;
+		}
+	}
+}
+
+static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms)
+{
+	c->x86 = (tfms >> 8) & 0xf;
+	c->x86_model = (tfms >> 4) & 0xf;
+	c->x86_mask = tfms & 0xf;
+	if (c->x86 == 0xf)
+		c->x86 += (tfms >> 20) & 0xff;
+	if (c->x86 >= 0x6)
+		c->x86_model += ((tfms >> 16) & 0xF) << 4;
+}
+
 int x86_cpu_init_f(void)
 {
 	const u32 em_rst = ~X86_CR0_EM;
@@ -128,9 +303,22 @@
 	     "movl %%eax, %%cr0\n" \
 	     : : "i" (em_rst), "i" (mp_ne_set) : "eax");
 
+	/* identify CPU via cpuid and store the decoded info into gd->arch */
+	if (has_cpuid()) {
+		struct cpu_device_id cpu;
+		struct cpuinfo_x86 c;
+
+		identify_cpu(&cpu);
+		get_fms(&c, cpu.device);
+		gd->arch.x86 = c.x86;
+		gd->arch.x86_vendor = cpu.vendor;
+		gd->arch.x86_model = c.x86_model;
+		gd->arch.x86_mask = c.x86_mask;
+		gd->arch.x86_device = cpu.device;
+	}
+
 	return 0;
 }
-int cpu_init_f(void) __attribute__((weak, alias("x86_cpu_init_f")));
 
 int x86_cpu_init_r(void)
 {
@@ -198,14 +386,13 @@
 	"generate_gpf:\n"
 	"ljmp   $0x70, $0x47114711\n");
 
-void __reset_cpu(ulong addr)
+__weak void reset_cpu(ulong addr)
 {
 	printf("Resetting using x86 Triple Fault\n");
 	set_vector(13, generate_gpf);	/* general protection fault handler */
 	set_vector(8, generate_gpf);	/* double fault handler */
 	generate_gpf();			/* start the show */
 }
-void reset_cpu(ulong addr) __attribute__((weak, alias("__reset_cpu")));
 
 int dcache_status(void)
 {
@@ -279,55 +466,14 @@
 		: "eax");
 }
 
-static bool has_cpuid(void)
-{
-	unsigned long flag;
-
-	asm volatile("pushf\n" \
-		"pop %%eax\n"
-		"mov %%eax, %%ecx\n"	/* ecx = flags */
-		"xor %1, %%eax\n"
-		"push %%eax\n"
-		"popf\n"		/* flags ^= $2 */
-		"pushf\n"
-		"pop %%eax\n"		/* eax = flags */
-		"push %%ecx\n"
-		"popf\n"		/* flags = ecx */
-		"xor %%ecx, %%eax\n"
-		"mov %%eax, %0"
-		: "=r" (flag)
-		: "i" (1 << 21)
-		: "eax", "ecx", "memory");
-
-	return flag != 0;
-}
-
 static bool can_detect_long_mode(void)
 {
-	unsigned long flag;
-
-	asm volatile("mov $0x80000000, %%eax\n"
-		"cpuid\n"
-		"mov %%eax, %0"
-		: "=r" (flag)
-		:
-		: "eax", "ebx", "ecx", "edx", "memory");
-
-	return flag > 0x80000000UL;
+	return cpuid_eax(0x80000000) > 0x80000000UL;
 }
 
 static bool has_long_mode(void)
 {
-	unsigned long flag;
-
-	asm volatile("mov $0x80000001, %%eax\n"
-		"cpuid\n"
-		"mov %%edx, %0"
-		: "=r" (flag)
-		:
-		: "eax", "ebx", "ecx", "edx", "memory");
-
-	return flag & (1 << 29) ? true : false;
+	return cpuid_edx(0x80000001) & (1 << 29) ? true : false;
 }
 
 int cpu_has_64bit(void)
@@ -336,9 +482,47 @@
 		has_long_mode();
 }
 
-int print_cpuinfo(void)
+const char *cpu_vendor_name(int vendor)
 {
-	printf("CPU:   %s\n", cpu_has_64bit() ? "x86_64" : "x86");
+	const char *name;
+	name = "<invalid cpu vendor>";
+	if ((vendor < (ARRAY_SIZE(x86_vendor_name))) &&
+	    (x86_vendor_name[vendor] != 0))
+		name = x86_vendor_name[vendor];
+
+	return name;
+}
+
+char *cpu_get_name(char *name)
+{
+	unsigned int *name_as_ints = (unsigned int *)name;
+	struct cpuid_result regs;
+	char *ptr;
+	int i;
+
+	/* This bit adds up to 48 bytes */
+	for (i = 0; i < 3; i++) {
+		regs = cpuid(0x80000002 + i);
+		name_as_ints[i * 4 + 0] = regs.eax;
+		name_as_ints[i * 4 + 1] = regs.ebx;
+		name_as_ints[i * 4 + 2] = regs.ecx;
+		name_as_ints[i * 4 + 3] = regs.edx;
+	}
+	name[CPU_MAX_NAME_LEN - 1] = '\0';
+
+	/* Skip leading spaces. */
+	ptr = name;
+	while (*ptr == ' ')
+		ptr++;
+
+	return ptr;
+}
+
+int default_print_cpuinfo(void)
+{
+	printf("CPU: %s, vendor %s, device %xh\n",
+	       cpu_has_64bit() ? "x86_64" : "x86",
+	       cpu_vendor_name(gd->arch.x86_vendor), gd->arch.x86_device);
 
 	return 0;
 }
@@ -384,3 +568,26 @@
 
 	return -EFAULT;
 }
+
+void show_boot_progress(int val)
+{
+#if MIN_PORT80_KCLOCKS_DELAY
+	/*
+	 * Scale the time counter reading to avoid using 64 bit arithmetics.
+	 * Can't use get_timer() here becuase it could be not yet
+	 * initialized or even implemented.
+	 */
+	if (!gd->arch.tsc_prev) {
+		gd->arch.tsc_base_kclocks = rdtsc() / 1000;
+		gd->arch.tsc_prev = 0;
+	} else {
+		uint32_t now;
+
+		do {
+			now = rdtsc() / 1000 - gd->arch.tsc_base_kclocks;
+		} while (now < (gd->arch.tsc_prev + MIN_PORT80_KCLOCKS_DELAY));
+		gd->arch.tsc_prev = now;
+	}
+#endif
+	outb(val, POST_PORT);
+}
diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c
index 6f3d85f..51e2c59 100644
--- a/arch/x86/cpu/interrupts.c
+++ b/arch/x86/cpu/interrupts.c
@@ -31,7 +31,7 @@
 	"pushl $"#x"\n" \
 	"jmp irq_common_entry\n"
 
-void dump_regs(struct irq_regs *regs)
+static void dump_regs(struct irq_regs *regs)
 {
 	unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
 	unsigned long d0, d1, d2, d3, d6, d7;
diff --git a/arch/x86/cpu/ivybridge/Kconfig b/arch/x86/cpu/ivybridge/Kconfig
new file mode 100644
index 0000000..afca957
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/Kconfig
@@ -0,0 +1,172 @@
+#
+# From Coreboot src/northbridge/intel/sandybridge/Kconfig
+#
+# Copyright (C) 2010 Google Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0
+
+
+config NORTHBRIDGE_INTEL_SANDYBRIDGE
+	bool
+	select CACHE_MRC_BIN
+	select CPU_INTEL_MODEL_206AX
+
+config NORTHBRIDGE_INTEL_IVYBRIDGE
+	bool
+	select CACHE_MRC_BIN
+	select CPU_INTEL_MODEL_306AX
+
+if NORTHBRIDGE_INTEL_SANDYBRIDGE
+
+config VGA_BIOS_ID
+	string
+	default "8086,0106"
+
+config CACHE_MRC_SIZE_KB
+	int
+	default 256
+
+config MRC_CACHE_BASE
+	hex
+	default 0xff800000
+
+config MRC_CACHE_LOCATION
+	hex
+	depends on !CHROMEOS
+	default 0x1ec000
+
+config MRC_CACHE_SIZE
+	hex
+	depends on !CHROMEOS
+	default 0x10000
+
+config DCACHE_RAM_BASE
+	hex
+	default 0xff7f0000
+
+config DCACHE_RAM_SIZE
+	hex
+	default 0x10000
+
+endif
+
+if NORTHBRIDGE_INTEL_IVYBRIDGE
+
+config VGA_BIOS_ID
+	string
+	default "8086,0166"
+
+config EXTERNAL_MRC_BLOB
+	bool
+	default n
+
+config CACHE_MRC_SIZE_KB
+	int
+	default 512
+
+config MRC_CACHE_BASE
+	hex
+	default 0xff800000
+
+config MRC_CACHE_LOCATION
+	hex
+	depends on !CHROMEOS
+	default 0x370000
+
+config MRC_CACHE_SIZE
+	hex
+	depends on !CHROMEOS
+	default 0x10000
+
+config DCACHE_RAM_BASE
+	hex
+	default 0xff7e0000
+
+config DCACHE_RAM_SIZE
+	hex
+	default 0x20000
+
+endif
+
+if NORTHBRIDGE_INTEL_SANDYBRIDGE || NORTHBRIDGE_INTEL_IVYBRIDGE
+
+config HAVE_MRC
+        bool "Add a System Agent binary"
+        help
+          Select this option to add a System Agent binary to
+          the resulting U-Boot image. MRC stands for Memory Reference Code.
+          It is a binary blob which U-Boot uses to set up SDRAM.
+
+          Note: Without this binary U-Boot will not be able to set up its
+          SDRAM so will not boot.
+
+config DCACHE_RAM_MRC_VAR_SIZE
+	hex
+	default 0x4000
+	help
+	  This is the amount of CAR (Cache as RAM) reserved for use by the
+	  memory reference code. This should be set to 16KB (0x4000 hex)
+	  so that MRC has enough space to run.
+
+config MRC_FILE
+	string "Intel System Agent path and filename"
+	depends on HAVE_MRC
+	default "systemagent-ivybridge.bin" if NORTHBRIDGE_INTEL_IVYBRIDGE
+	default "systemagent-sandybridge.bin" if NORTHBRIDGE_INTEL_SANDYBRIDGE
+	help
+	  The path and filename of the file to use as System Agent
+	  binary.
+
+config CPU_SPECIFIC_OPTIONS
+	def_bool y
+	select SMM_TSEG
+	select ARCH_BOOTBLOCK_X86_32
+	select ARCH_ROMSTAGE_X86_32
+	select ARCH_RAMSTAGE_X86_32
+	select SMP
+	select SSE2
+	select UDELAY_LAPIC
+	select CPU_MICROCODE_IN_CBFS
+	select TSC_SYNC_MFENCE
+	select HAVE_INTEL_ME
+	select X86_RAMTEST
+
+config SMM_TSEG_SIZE
+	hex
+	default 0x800000
+
+config ENABLE_VMX
+	bool "Enable VMX for virtualization"
+	default n
+	help
+	  Virtual Machine Extensions are provided in many x86 CPUs. These
+	  provide various facilities for allowing a host OS to provide an
+	  environment where potentially several guest OSes have only
+	  limited access to the underlying hardware. This is achieved
+	  without resorting to software trapping and/or instruction set
+	  emulation (which would be very slow).
+
+	  Intel's implementation of this is called VT-x. This option enables
+	  VT-x this so that the OS that is booted by U-Boot can make use of
+	  these facilities. If this option is not enabled, then the host OS
+	  will be unable to support virtualisation, or it will run very
+	  slowly.
+
+endif
+
+config CPU_INTEL_SOCKET_RPGA989
+	bool
+
+if CPU_INTEL_SOCKET_RPGA989
+
+config SOCKET_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	select MMX
+	select SSE
+	select CACHE_AS_RAM
+
+config CACHE_MRC_BIN
+	bool
+	default n
+
+endif
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile
new file mode 100644
index 0000000..721b37e
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/Makefile
@@ -0,0 +1,16 @@
+#
+# Copyright (c) 2014 Google, Inc
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += car.o
+obj-y += cpu.o
+obj-y += early_init.o
+obj-y += early_me.o
+obj-y += lpc.o
+obj-y += me_status.o
+obj-y += microcode_intel.o
+obj-y += pci.o
+obj-y += report_platform.o
+obj-y += sdram.o
diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S
new file mode 100644
index 0000000..dca68e4
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/car.S
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * From Coreboot file cpu/intel/model_206ax/cache_as_ram.inc
+ *
+ * Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
+ * Copyright (C) 2005 Tyan (written by Yinghai Lu for Tyan)
+ * Copyright (C) 2007-2008 coresystems GmbH
+ * Copyright (C) 2012 Kyösti Mälkki <kyosti.malkki@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/mtrr.h>
+#include <asm/post.h>
+#include <asm/processor-flags.h>
+
+#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg))
+#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1)
+
+#define CACHE_AS_RAM_SIZE	CONFIG_DCACHE_RAM_SIZE
+#define CACHE_AS_RAM_BASE	CONFIG_DCACHE_RAM_BASE
+
+/* Cache 4GB - MRC_SIZE_KB for MRC */
+#define CACHE_MRC_BYTES	((CONFIG_CACHE_MRC_SIZE_KB << 10) - 1)
+#define CACHE_MRC_BASE		(0xFFFFFFFF - CACHE_MRC_BYTES)
+#define CACHE_MRC_MASK		(~CACHE_MRC_BYTES)
+
+#define CPU_PHYSMASK_HI	(1 << (CONFIG_CPU_ADDR_BITS - 32) - 1)
+
+#define NOEVICTMOD_MSR	0x2e0
+
+	/*
+	 * Note: ebp must not be touched in this code as it holds the BIST
+	 * value (built-in self test). We preserve this value until it can
+	 * be written to global_data when CAR is ready for use.
+	 */
+.globl car_init
+car_init:
+	post_code(POST_CAR_START)
+
+	/* Send INIT IPI to all excluding ourself */
+	movl	$0x000C4500, %eax
+	movl	$0xFEE00300, %esi
+	movl	%eax, (%esi)
+
+	post_code(POST_CAR_SIPI)
+	/* Zero out all fixed range and variable range MTRRs */
+	movl	$mtrr_table, %esi
+	movl	$((mtrr_table_end - mtrr_table) / 2), %edi
+	xorl	%eax, %eax
+	xorl	%edx, %edx
+clear_mtrrs:
+	movw	(%esi), %bx
+	movzx	%bx, %ecx
+	wrmsr
+	add	$2, %esi
+	dec	%edi
+	jnz	clear_mtrrs
+
+	post_code(POST_CAR_MTRR)
+	/* Configure the default memory type to uncacheable */
+	movl	$MTRRdefType_MSR, %ecx
+	rdmsr
+	andl	$(~0x00000cff), %eax
+	wrmsr
+
+	post_code(POST_CAR_UNCACHEABLE)
+	/* Set Cache-as-RAM base address */
+	movl	$(MTRR_PHYS_BASE_MSR(0)), %ecx
+	movl	$(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax
+	xorl	%edx, %edx
+	wrmsr
+
+	post_code(POST_CAR_BASE_ADDRESS)
+	/* Set Cache-as-RAM mask */
+	movl	$(MTRR_PHYS_MASK_MSR(0)), %ecx
+	movl	$(~(CACHE_AS_RAM_SIZE - 1) | MTRRphysMaskValid), %eax
+	movl	$CPU_PHYSMASK_HI, %edx
+	wrmsr
+
+	post_code(POST_CAR_MASK)
+
+	/* Enable MTRR */
+	movl	$MTRRdefType_MSR, %ecx
+	rdmsr
+	orl	$MTRRdefTypeEn, %eax
+	wrmsr
+
+	/* Enable cache (CR0.CD = 0, CR0.NW = 0) */
+        movl	%cr0, %eax
+	andl	$(~(X86_CR0_CD | X86_CR0_NW)), %eax
+	invd
+	movl	%eax, %cr0
+
+	/* enable the 'no eviction' mode */
+	movl    $NOEVICTMOD_MSR, %ecx
+	rdmsr
+	orl     $1, %eax
+	andl    $~2, %eax
+	wrmsr
+
+       /* Clear the cache memory region. This will also fill up the cache */
+	movl	$CACHE_AS_RAM_BASE, %esi
+	movl	%esi, %edi
+	movl	$(CACHE_AS_RAM_SIZE / 4), %ecx
+	xorl	%eax, %eax
+	rep	stosl
+
+	/* enable the 'no eviction run' state */
+	movl    $NOEVICTMOD_MSR, %ecx
+	rdmsr
+	orl     $3, %eax
+	wrmsr
+
+	post_code(POST_CAR_FILL)
+	/* Enable Cache-as-RAM mode by disabling cache */
+	movl	%cr0, %eax
+	orl	$X86_CR0_CD, %eax
+	movl	%eax, %cr0
+
+	/* Enable cache for our code in Flash because we do XIP here */
+	movl	$MTRR_PHYS_BASE_MSR(1), %ecx
+	xorl	%edx, %edx
+	movl    $car_init_ret, %eax
+	andl    $(~(CONFIG_XIP_ROM_SIZE - 1)), %eax
+	orl	$MTRR_TYPE_WRPROT, %eax
+	wrmsr
+
+	movl	$MTRR_PHYS_MASK_MSR(1), %ecx
+	movl	$CPU_PHYSMASK_HI, %edx
+	movl	$(~(CONFIG_XIP_ROM_SIZE - 1) | MTRRphysMaskValid), %eax
+	wrmsr
+
+	post_code(POST_CAR_ROM_CACHE)
+#ifdef CONFIG_CACHE_MRC_BIN
+	/* Enable caching for ram init code to run faster */
+	movl	$MTRR_PHYS_BASE_MSR(2), %ecx
+	movl	$(CACHE_MRC_BASE | MTRR_TYPE_WRPROT), %eax
+	xorl	%edx, %edx
+	wrmsr
+	movl	$MTRR_PHYS_MASK_MSR(2), %ecx
+	movl	$(CACHE_MRC_MASK | MTRRphysMaskValid), %eax
+	movl	$CPU_PHYSMASK_HI, %edx
+	wrmsr
+#endif
+
+	post_code(POST_CAR_MRC_CACHE)
+	/* Enable cache */
+	movl	%cr0, %eax
+	andl	$(~(X86_CR0_CD | X86_CR0_NW)), %eax
+	movl	%eax, %cr0
+
+	post_code(POST_CAR_CPU_CACHE)
+
+	/* All CPUs need to be in Wait for SIPI state */
+wait_for_sipi:
+	movl	(%esi), %eax
+	bt	$12, %eax
+	jc	wait_for_sipi
+
+	/* return */
+	jmp	car_init_ret
+
+mtrr_table:
+	/* Fixed MTRRs */
+	.word 0x250, 0x258, 0x259
+	.word 0x268, 0x269, 0x26A
+	.word 0x26B, 0x26C, 0x26D
+	.word 0x26E, 0x26F
+	/* Variable MTRRs */
+	.word 0x200, 0x201, 0x202, 0x203
+	.word 0x204, 0x205, 0x206, 0x207
+	.word 0x208, 0x209, 0x20A, 0x20B
+	.word 0x20C, 0x20D, 0x20E, 0x20F
+	.word 0x210, 0x211, 0x212, 0x213
+mtrr_table_end:
diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c
new file mode 100644
index 0000000..60976db
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/cpu.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ * (C) Copyright 2008
+ * Graeme Russ, graeme.russ@gmail.com.
+ *
+ * Some portions from coreboot src/mainboard/google/link/romstage.c
+ * and src/cpu/intel/model_206ax/bootblock.c
+ * Copyright (C) 2007-2010 coresystems GmbH
+ * Copyright (C) 2011 Google Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/lapic.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/pci.h>
+#include <asm/post.h>
+#include <asm/processor.h>
+#include <asm/arch/model_206ax.h>
+#include <asm/arch/microcode.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/sandybridge.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void enable_port80_on_lpc(struct pci_controller *hose, pci_dev_t dev)
+{
+	/* Enable port 80 POST on LPC */
+	pci_hose_write_config_dword(hose, dev, PCH_RCBA_BASE, DEFAULT_RCBA | 1);
+	clrbits_le32(RCB_REG(GCS), 4);
+}
+
+/*
+ * Enable Prefetching and Caching.
+ */
+static void enable_spi_prefetch(struct pci_controller *hose, pci_dev_t dev)
+{
+	u8 reg8;
+
+	pci_hose_read_config_byte(hose, dev, 0xdc, &reg8);
+	reg8 &= ~(3 << 2);
+	reg8 |= (2 << 2); /* Prefetching and Caching Enabled */
+	pci_hose_write_config_byte(hose, dev, 0xdc, reg8);
+}
+
+static void set_var_mtrr(
+	unsigned reg, unsigned base, unsigned size, unsigned type)
+
+{
+	/* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
+	/* FIXME: It only support 4G less range */
+	wrmsr(MTRRphysBase_MSR(reg), base | type, 0);
+	wrmsr(MTRRphysMask_MSR(reg), ~(size - 1) | MTRRphysMaskValid,
+	      (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1);
+}
+
+static void enable_rom_caching(void)
+{
+	disable_caches();
+	set_var_mtrr(1, 0xffc00000, 4 << 20, MTRR_TYPE_WRPROT);
+	enable_caches();
+
+	/* Enable Variable MTRRs */
+	wrmsr(MTRRdefType_MSR, 0x800, 0);
+}
+
+static int set_flex_ratio_to_tdp_nominal(void)
+{
+	msr_t flex_ratio, msr;
+	u8 nominal_ratio;
+
+	/* Minimum CPU revision for configurable TDP support */
+	if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
+		return -EINVAL;
+
+	/* Check for Flex Ratio support */
+	flex_ratio = msr_read(MSR_FLEX_RATIO);
+	if (!(flex_ratio.lo & FLEX_RATIO_EN))
+		return -EINVAL;
+
+	/* Check for >0 configurable TDPs */
+	msr = msr_read(MSR_PLATFORM_INFO);
+	if (((msr.hi >> 1) & 3) == 0)
+		return -EINVAL;
+
+	/* Use nominal TDP ratio for flex ratio */
+	msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
+	nominal_ratio = msr.lo & 0xff;
+
+	/* See if flex ratio is already set to nominal TDP ratio */
+	if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
+		return 0;
+
+	/* Set flex ratio to nominal TDP ratio */
+	flex_ratio.lo &= ~0xff00;
+	flex_ratio.lo |= nominal_ratio << 8;
+	flex_ratio.lo |= FLEX_RATIO_LOCK;
+	msr_write(MSR_FLEX_RATIO, flex_ratio);
+
+	/* Set flex ratio in soft reset data register bits 11:6 */
+	clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
+			(nominal_ratio & 0x3f) << 6);
+
+	/* Set soft reset control to use register value */
+	setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
+
+	/* Issue warm reset, will be "CPU only" due to soft reset data */
+	outb(0x0, PORT_RESET);
+	outb(0x6, PORT_RESET);
+	cpu_hlt();
+
+	/* Not reached */
+	return -EINVAL;
+}
+
+static void set_spi_speed(void)
+{
+	u32 fdod;
+
+	/* Observe SPI Descriptor Component Section 0 */
+	writel(0x1000, RCB_REG(SPI_DESC_COMP0));
+
+	/* Extract the1 Write/Erase SPI Frequency from descriptor */
+	fdod = readl(RCB_REG(SPI_FREQ_WR_ERA));
+	fdod >>= 24;
+	fdod &= 7;
+
+	/* Set Software Sequence frequency to match */
+	clrsetbits_8(RCB_REG(SPI_FREQ_SWSEQ), 7, fdod);
+}
+
+int arch_cpu_init(void)
+{
+	const void *blob = gd->fdt_blob;
+	struct pci_controller *hose;
+	int node;
+	int ret;
+
+	post_code(POST_CPU_INIT);
+	timer_set_base(rdtsc());
+
+	ret = x86_cpu_init_f();
+	if (ret)
+		return ret;
+
+	ret = pci_early_init_hose(&hose);
+	if (ret)
+		return ret;
+
+	node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_LPC);
+	if (node < 0)
+		return -ENOENT;
+	ret = lpc_early_init(gd->fdt_blob, node, PCH_LPC_DEV);
+	if (ret)
+		return ret;
+
+	enable_spi_prefetch(hose, PCH_LPC_DEV);
+
+	/* This is already done in start.S, but let's do it in C */
+	enable_port80_on_lpc(hose, PCH_LPC_DEV);
+
+	/* already done in car.S */
+	if (false)
+		enable_rom_caching();
+
+	set_spi_speed();
+
+	/*
+	 * We should do as little as possible before the serial console is
+	 * up. Perhaps this should move to later. Our next lot of init
+	 * happens in print_cpuinfo() when we have a console
+	 */
+	ret = set_flex_ratio_to_tdp_nominal();
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int enable_smbus(void)
+{
+	pci_dev_t dev;
+	uint16_t value;
+
+	/* Set the SMBus device statically. */
+	dev = PCI_BDF(0x0, 0x1f, 0x3);
+
+	/* Check to make sure we've got the right device. */
+	value = pci_read_config16(dev, 0x0);
+	if (value != 0x8086) {
+		printf("SMBus controller not found\n");
+		return -ENOSYS;
+	}
+
+	/* Set SMBus I/O base. */
+	pci_write_config32(dev, SMB_BASE,
+			   SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO);
+
+	/* Set SMBus enable. */
+	pci_write_config8(dev, HOSTC, HST_EN);
+
+	/* Set SMBus I/O space enable. */
+	pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO);
+
+	/* Disable interrupt generation. */
+	outb(0, SMBUS_IO_BASE + SMBHSTCTL);
+
+	/* Clear any lingering errors, so transactions can run. */
+	outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
+	debug("SMBus controller enabled\n");
+
+	return 0;
+}
+
+#define PCH_EHCI0_TEMP_BAR0 0xe8000000
+#define PCH_EHCI1_TEMP_BAR0 0xe8000400
+#define PCH_XHCI_TEMP_BAR0  0xe8001000
+
+/*
+ * Setup USB controller MMIO BAR to prevent the reference code from
+ * resetting the controller.
+ *
+ * The BAR will be re-assigned during device enumeration so these are only
+ * temporary.
+ *
+ * This is used to speed up the resume path.
+ */
+static void enable_usb_bar(void)
+{
+	pci_dev_t usb0 = PCH_EHCI1_DEV;
+	pci_dev_t usb1 = PCH_EHCI2_DEV;
+	pci_dev_t usb3 = PCH_XHCI_DEV;
+	u32 cmd;
+
+	/* USB Controller 1 */
+	pci_write_config32(usb0, PCI_BASE_ADDRESS_0,
+			   PCH_EHCI0_TEMP_BAR0);
+	cmd = pci_read_config32(usb0, PCI_COMMAND);
+	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	pci_write_config32(usb0, PCI_COMMAND, cmd);
+
+	/* USB Controller 1 */
+	pci_write_config32(usb1, PCI_BASE_ADDRESS_0,
+			   PCH_EHCI1_TEMP_BAR0);
+	cmd = pci_read_config32(usb1, PCI_COMMAND);
+	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	pci_write_config32(usb1, PCI_COMMAND, cmd);
+
+	/* USB3 Controller */
+	pci_write_config32(usb3, PCI_BASE_ADDRESS_0,
+			   PCH_XHCI_TEMP_BAR0);
+	cmd = pci_read_config32(usb3, PCI_COMMAND);
+	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	pci_write_config32(usb3, PCI_COMMAND, cmd);
+}
+
+static int report_bist_failure(void)
+{
+	if (gd->arch.bist != 0) {
+		printf("BIST failed: %08x\n", gd->arch.bist);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int print_cpuinfo(void)
+{
+	enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE;
+	char processor_name[CPU_MAX_NAME_LEN];
+	const char *name;
+	uint32_t pm1_cnt;
+	uint16_t pm1_sts;
+	int ret;
+
+	/* Halt if there was a built in self test failure */
+	ret = report_bist_failure();
+	if (ret)
+		return ret;
+
+	enable_lapic();
+
+	ret = microcode_update_intel();
+	if (ret && ret != -ENOENT && ret != -EEXIST)
+		return ret;
+
+	/* Enable upper 128bytes of CMOS */
+	writel(1 << 2, RCB_REG(RC));
+
+	/* TODO: cmos_post_init() */
+	if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) {
+		debug("soft reset detected\n");
+		boot_mode = PEI_BOOT_SOFT_RESET;
+
+		/* System is not happy after keyboard reset... */
+		debug("Issuing CF9 warm reset\n");
+		outb(0x6, 0xcf9);
+		cpu_hlt();
+	}
+
+	/* Early chipset init required before RAM init can work */
+	sandybridge_early_init(SANDYBRIDGE_MOBILE);
+
+	/* Check PM1_STS[15] to see if we are waking from Sx */
+	pm1_sts = inw(DEFAULT_PMBASE + PM1_STS);
+
+	/* Read PM1_CNT[12:10] to determine which Sx state */
+	pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT);
+
+	if ((pm1_sts & WAK_STS) && ((pm1_cnt >> 10) & 7) == 5) {
+#if CONFIG_HAVE_ACPI_RESUME
+		debug("Resume from S3 detected.\n");
+		boot_mode = PEI_BOOT_RESUME;
+		/* Clear SLP_TYPE. This will break stage2 but
+		 * we care for that when we get there.
+		 */
+		outl(pm1_cnt & ~(7 << 10), DEFAULT_PMBASE + PM1_CNT);
+#else
+		debug("Resume from S3 detected, but disabled.\n");
+#endif
+	} else {
+		/*
+		 * TODO: An indication of life might be possible here (e.g.
+		 * keyboard light)
+		 */
+	}
+	post_code(POST_EARLY_INIT);
+
+	/* Enable SPD ROMs and DDR-III DRAM */
+	ret = enable_smbus();
+	if (ret)
+		return ret;
+
+	/* Prepare USB controller early in S3 resume */
+	if (boot_mode == PEI_BOOT_RESUME)
+		enable_usb_bar();
+
+	gd->arch.pei_boot_mode = boot_mode;
+
+	/* TODO: Move this to the board or driver */
+	pci_write_config32(PCH_LPC_DEV, GPIO_BASE, DEFAULT_GPIOBASE | 1);
+	pci_write_config32(PCH_LPC_DEV, GPIO_CNTL, 0x10);
+
+	/* Print processor name */
+	name = cpu_get_name(processor_name);
+	printf("CPU:   %s\n", name);
+
+	post_code(POST_CPU_INFO);
+
+	return 0;
+}
diff --git a/arch/x86/cpu/ivybridge/early_init.c b/arch/x86/cpu/ivybridge/early_init.c
new file mode 100644
index 0000000..eb8f613
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/early_init.c
@@ -0,0 +1,145 @@
+/*
+ * From Coreboot
+ *
+ * Copyright (C) 2007-2010 coresystems GmbH
+ * Copyright (C) 2011 Google Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/sandybridge.h>
+
+static void sandybridge_setup_bars(pci_dev_t pch_dev, pci_dev_t lpc_dev)
+{
+	/* Setting up Southbridge. In the northbridge code. */
+	debug("Setting up static southbridge registers\n");
+	pci_write_config32(lpc_dev, PCH_RCBA_BASE, DEFAULT_RCBA | 1);
+
+	pci_write_config32(lpc_dev, PMBASE, DEFAULT_PMBASE | 1);
+	pci_write_config8(lpc_dev, ACPI_CNTL, 0x80); /* Enable ACPI BAR */
+
+	debug("Disabling watchdog reboot\n");
+	setbits_le32(RCB_REG(GCS), 1 >> 5);	/* No reset */
+	outw(1 << 11, DEFAULT_PMBASE | 0x60 | 0x08);	/* halt timer */
+
+	/* Set up all hardcoded northbridge BARs */
+	debug("Setting up static registers\n");
+	pci_write_config32(pch_dev, EPBAR, DEFAULT_EPBAR | 1);
+	pci_write_config32(pch_dev, EPBAR + 4, (0LL + DEFAULT_EPBAR) >> 32);
+	pci_write_config32(pch_dev, MCHBAR, DEFAULT_MCHBAR | 1);
+	pci_write_config32(pch_dev, MCHBAR + 4, (0LL + DEFAULT_MCHBAR) >> 32);
+	/* 64MB - busses 0-63 */
+	pci_write_config32(pch_dev, PCIEXBAR, DEFAULT_PCIEXBAR | 5);
+	pci_write_config32(pch_dev, PCIEXBAR + 4,
+			   (0LL + DEFAULT_PCIEXBAR) >> 32);
+	pci_write_config32(pch_dev, DMIBAR, DEFAULT_DMIBAR | 1);
+	pci_write_config32(pch_dev, DMIBAR + 4, (0LL + DEFAULT_DMIBAR) >> 32);
+
+	/* Set C0000-FFFFF to access RAM on both reads and writes */
+	pci_write_config8(pch_dev, PAM0, 0x30);
+	pci_write_config8(pch_dev, PAM1, 0x33);
+	pci_write_config8(pch_dev, PAM2, 0x33);
+	pci_write_config8(pch_dev, PAM3, 0x33);
+	pci_write_config8(pch_dev, PAM4, 0x33);
+	pci_write_config8(pch_dev, PAM5, 0x33);
+	pci_write_config8(pch_dev, PAM6, 0x33);
+}
+
+static void sandybridge_setup_graphics(pci_dev_t pch_dev, pci_dev_t video_dev)
+{
+	u32 reg32;
+	u16 reg16;
+	u8 reg8;
+
+	reg16 = pci_read_config16(video_dev, PCI_DEVICE_ID);
+	switch (reg16) {
+	case 0x0102: /* GT1 Desktop */
+	case 0x0106: /* GT1 Mobile */
+	case 0x010a: /* GT1 Server */
+	case 0x0112: /* GT2 Desktop */
+	case 0x0116: /* GT2 Mobile */
+	case 0x0122: /* GT2 Desktop >=1.3GHz */
+	case 0x0126: /* GT2 Mobile >=1.3GHz */
+	case 0x0156: /* IvyBridge */
+	case 0x0166: /* IvyBridge */
+		break;
+	default:
+		debug("Graphics not supported by this CPU/chipset\n");
+		return;
+	}
+
+	debug("Initialising Graphics\n");
+
+	/* Setup IGD memory by setting GGC[7:3] = 1 for 32MB */
+	reg16 = pci_read_config16(pch_dev, GGC);
+	reg16 &= ~0x00f8;
+	reg16 |= 1 << 3;
+	/* Program GTT memory by setting GGC[9:8] = 2MB */
+	reg16 &= ~0x0300;
+	reg16 |= 2 << 8;
+	/* Enable VGA decode */
+	reg16 &= ~0x0002;
+	pci_write_config16(pch_dev, GGC, reg16);
+
+	/* Enable 256MB aperture */
+	reg8 = pci_read_config8(video_dev, MSAC);
+	reg8 &= ~0x06;
+	reg8 |= 0x02;
+	pci_write_config8(video_dev, MSAC, reg8);
+
+	/* Erratum workarounds */
+	reg32 = readl(MCHBAR_REG(0x5f00));
+	reg32 |= (1 << 9) | (1 << 10);
+	writel(reg32, MCHBAR_REG(0x5f00));
+
+	/* Enable SA Clock Gating */
+	reg32 = readl(MCHBAR_REG(0x5f00));
+	writel(reg32 | 1, MCHBAR_REG(0x5f00));
+
+	/* GPU RC6 workaround for sighting 366252 */
+	reg32 = readl(MCHBAR_REG(0x5d14));
+	reg32 |= (1 << 31);
+	writel(reg32, MCHBAR_REG(0x5d14));
+
+	/* VLW */
+	reg32 = readl(MCHBAR_REG(0x6120));
+	reg32 &= ~(1 << 0);
+	writel(reg32, MCHBAR_REG(0x6120));
+
+	reg32 = readl(MCHBAR_REG(0x5418));
+	reg32 |= (1 << 4) | (1 << 5);
+	writel(reg32, MCHBAR_REG(0x5418));
+}
+
+void sandybridge_early_init(int chipset_type)
+{
+	pci_dev_t pch_dev = PCH_DEV;
+	pci_dev_t video_dev = PCH_VIDEO_DEV;
+	pci_dev_t lpc_dev = PCH_LPC_DEV;
+	u32 capid0_a;
+	u8 reg8;
+
+	/* Device ID Override Enable should be done very early */
+	capid0_a = pci_read_config32(pch_dev, 0xe4);
+	if (capid0_a & (1 << 10)) {
+		reg8 = pci_read_config8(pch_dev, 0xf3);
+		reg8 &= ~7; /* Clear 2:0 */
+
+		if (chipset_type == SANDYBRIDGE_MOBILE)
+			reg8 |= 1; /* Set bit 0 */
+
+		pci_write_config8(pch_dev, 0xf3, reg8);
+	}
+
+	/* Setup all BARs required for early PCIe and raminit */
+	sandybridge_setup_bars(pch_dev, lpc_dev);
+
+	/* Device Enable */
+	pci_write_config32(pch_dev, DEVEN, DEVEN_HOST | DEVEN_IGD);
+
+	sandybridge_setup_graphics(pch_dev, video_dev);
+}
diff --git a/arch/x86/cpu/ivybridge/early_me.c b/arch/x86/cpu/ivybridge/early_me.c
new file mode 100644
index 0000000..b24dea1
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/early_me.c
@@ -0,0 +1,191 @@
+/*
+ * From Coreboot src/southbridge/intel/bd82x6x/early_me.c
+ *
+ * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/arch/me.h>
+#include <asm/arch/pch.h>
+#include <asm/io.h>
+
+static const char *const me_ack_values[] = {
+	[ME_HFS_ACK_NO_DID]	= "No DID Ack received",
+	[ME_HFS_ACK_RESET]	= "Non-power cycle reset",
+	[ME_HFS_ACK_PWR_CYCLE]	= "Power cycle reset",
+	[ME_HFS_ACK_S3]		= "Go to S3",
+	[ME_HFS_ACK_S4]		= "Go to S4",
+	[ME_HFS_ACK_S5]		= "Go to S5",
+	[ME_HFS_ACK_GBL_RESET]	= "Global Reset",
+	[ME_HFS_ACK_CONTINUE]	= "Continue to boot"
+};
+
+static inline void pci_read_dword_ptr(void *ptr, int offset)
+{
+	u32 dword;
+
+	dword = pci_read_config32(PCH_ME_DEV, offset);
+	memcpy(ptr, &dword, sizeof(dword));
+}
+
+static inline void pci_write_dword_ptr(void *ptr, int offset)
+{
+	u32 dword = 0;
+	memcpy(&dword, ptr, sizeof(dword));
+	pci_write_config32(PCH_ME_DEV, offset, dword);
+}
+
+void intel_early_me_status(void)
+{
+	struct me_hfs hfs;
+	struct me_gmes gmes;
+
+	pci_read_dword_ptr(&hfs, PCI_ME_HFS);
+	pci_read_dword_ptr(&gmes, PCI_ME_GMES);
+
+	intel_me_status(&hfs, &gmes);
+}
+
+int intel_early_me_init(void)
+{
+	int count;
+	struct me_uma uma;
+	struct me_hfs hfs;
+
+	debug("Intel ME early init\n");
+
+	/* Wait for ME UMA SIZE VALID bit to be set */
+	for (count = ME_RETRY; count > 0; --count) {
+		pci_read_dword_ptr(&uma, PCI_ME_UMA);
+		if (uma.valid)
+			break;
+		udelay(ME_DELAY);
+	}
+	if (!count) {
+		printf("ERROR: ME is not ready!\n");
+		return -EBUSY;
+	}
+
+	/* Check for valid firmware */
+	pci_read_dword_ptr(&hfs, PCI_ME_HFS);
+	if (hfs.fpt_bad) {
+		printf("WARNING: ME has bad firmware\n");
+		return -EBADF;
+	}
+
+	debug("Intel ME firmware is ready\n");
+
+	return 0;
+}
+
+int intel_early_me_uma_size(void)
+{
+	struct me_uma uma;
+
+	pci_read_dword_ptr(&uma, PCI_ME_UMA);
+	if (uma.valid) {
+		debug("ME: Requested %uMB UMA\n", uma.size);
+		return uma.size;
+	}
+
+	debug("ME: Invalid UMA size\n");
+	return -EINVAL;
+}
+
+static inline void set_global_reset(int enable)
+{
+	u32 etr3;
+
+	etr3 = pci_read_config32(PCH_LPC_DEV, ETR3);
+
+	/* Clear CF9 Without Resume Well Reset Enable */
+	etr3 &= ~ETR3_CWORWRE;
+
+	/* CF9GR indicates a Global Reset */
+	if (enable)
+		etr3 |= ETR3_CF9GR;
+	else
+		etr3 &= ~ETR3_CF9GR;
+
+	pci_write_config32(PCH_LPC_DEV, ETR3, etr3);
+}
+
+int intel_early_me_init_done(u8 status)
+{
+	u8 reset;
+	int count;
+	u32 mebase_l, mebase_h;
+	struct me_hfs hfs;
+	struct me_did did = {
+		.init_done = ME_INIT_DONE,
+		.status = status
+	};
+
+	/* MEBASE from MESEG_BASE[35:20] */
+	mebase_l = pci_read_config32(PCH_DEV, PCI_CPU_MEBASE_L);
+	mebase_h = pci_read_config32(PCH_DEV, PCI_CPU_MEBASE_H);
+	mebase_h &= 0xf;
+	did.uma_base = (mebase_l >> 20) | (mebase_h << 12);
+
+	/* Send message to ME */
+	debug("ME: Sending Init Done with status: %d, UMA base: 0x%04x\n",
+	      status, did.uma_base);
+
+	pci_write_dword_ptr(&did, PCI_ME_H_GS);
+
+	/* Must wait for ME acknowledgement */
+	for (count = ME_RETRY; count > 0; --count) {
+		pci_read_dword_ptr(&hfs, PCI_ME_HFS);
+		if (hfs.bios_msg_ack)
+			break;
+		udelay(ME_DELAY);
+	}
+	if (!count) {
+		printf("ERROR: ME failed to respond\n");
+		return -1;
+	}
+
+	/* Return the requested BIOS action */
+	debug("ME: Requested BIOS Action: %s\n", me_ack_values[hfs.ack_data]);
+
+	/* Check status after acknowledgement */
+	intel_early_me_status();
+
+	reset = 0;
+	switch (hfs.ack_data) {
+	case ME_HFS_ACK_CONTINUE:
+		/* Continue to boot */
+		return 0;
+	case ME_HFS_ACK_RESET:
+		/* Non-power cycle reset */
+		set_global_reset(0);
+		reset = 0x06;
+		break;
+	case ME_HFS_ACK_PWR_CYCLE:
+		/* Power cycle reset */
+		set_global_reset(0);
+		reset = 0x0e;
+		break;
+	case ME_HFS_ACK_GBL_RESET:
+		/* Global reset */
+		set_global_reset(1);
+		reset = 0x0e;
+		break;
+	case ME_HFS_ACK_S3:
+	case ME_HFS_ACK_S4:
+	case ME_HFS_ACK_S5:
+		break;
+	}
+
+	/* Perform the requested reset */
+	if (reset) {
+		outb(reset, 0xcf9);
+		cpu_hlt();
+	}
+	return -1;
+}
diff --git a/arch/x86/cpu/ivybridge/lpc.c b/arch/x86/cpu/ivybridge/lpc.c
new file mode 100644
index 0000000..621ef2c
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/lpc.c
@@ -0,0 +1,48 @@
+/*
+ * From coreboot southbridge/intel/bd82x6x/lpc.c
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <pci.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+
+int lpc_early_init(const void *blob, int node, pci_dev_t dev)
+{
+	struct reg_info {
+		u32 base;
+		u32 size;
+	} values[4], *ptr;
+	int count;
+	int i;
+
+	count = fdtdec_get_int_array_count(blob, node, "gen-dec",
+			(u32 *)values, sizeof(values) / sizeof(u32));
+	if (count < 0)
+		return -EINVAL;
+
+	/* Set COM1/COM2 decode range */
+	pci_write_config16(dev, LPC_IO_DEC, 0x0010);
+
+	/* Enable PS/2 Keyboard/Mouse, EC areas and COM1 */
+	pci_write_config16(dev, LPC_EN, KBC_LPC_EN | MC_LPC_EN |
+			   GAMEL_LPC_EN | COMA_LPC_EN);
+
+	/* Write all registers but use 0 if we run out of data */
+	count = count * sizeof(u32) / sizeof(values[0]);
+	for (i = 0, ptr = values; i < ARRAY_SIZE(values); i++, ptr++) {
+		u32 reg = 0;
+
+		if (i < count)
+			reg = ptr->base | PCI_COMMAND_IO | (ptr->size << 16);
+		pci_write_config32(dev, LPC_GENX_DEC(i), reg);
+	}
+
+	return 0;
+}
diff --git a/arch/x86/cpu/ivybridge/me_status.c b/arch/x86/cpu/ivybridge/me_status.c
new file mode 100644
index 0000000..15cf69f
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/me_status.c
@@ -0,0 +1,195 @@
+/*
+ * From Coreboot src/southbridge/intel/bd82x6x/me_status.c
+ *
+ * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/arch/me.h>
+
+/* HFS1[3:0] Current Working State Values */
+static const char *const me_cws_values[] = {
+	[ME_HFS_CWS_RESET]	= "Reset",
+	[ME_HFS_CWS_INIT]	= "Initializing",
+	[ME_HFS_CWS_REC]	= "Recovery",
+	[ME_HFS_CWS_NORMAL]	= "Normal",
+	[ME_HFS_CWS_WAIT]	= "Platform Disable Wait",
+	[ME_HFS_CWS_TRANS]	= "OP State Transition",
+	[ME_HFS_CWS_INVALID]	= "Invalid CPU Plugged In"
+};
+
+/* HFS1[8:6] Current Operation State Values */
+static const char *const me_opstate_values[] = {
+	[ME_HFS_STATE_PREBOOT]	= "Preboot",
+	[ME_HFS_STATE_M0_UMA]	= "M0 with UMA",
+	[ME_HFS_STATE_M3]	= "M3 without UMA",
+	[ME_HFS_STATE_M0]	= "M0 without UMA",
+	[ME_HFS_STATE_BRINGUP]	= "Bring up",
+	[ME_HFS_STATE_ERROR]	= "M0 without UMA but with error"
+};
+
+/* HFS[19:16] Current Operation Mode Values */
+static const char *const me_opmode_values[] = {
+	[ME_HFS_MODE_NORMAL]	= "Normal",
+	[ME_HFS_MODE_DEBUG]	= "Debug",
+	[ME_HFS_MODE_DIS]	= "Soft Temporary Disable",
+	[ME_HFS_MODE_OVER_JMPR]	= "Security Override via Jumper",
+	[ME_HFS_MODE_OVER_MEI]	= "Security Override via MEI Message"
+};
+
+/* HFS[15:12] Error Code Values */
+static const char *const me_error_values[] = {
+	[ME_HFS_ERROR_NONE]	= "No Error",
+	[ME_HFS_ERROR_UNCAT]	= "Uncategorized Failure",
+	[ME_HFS_ERROR_IMAGE]	= "Image Failure",
+	[ME_HFS_ERROR_DEBUG]	= "Debug Failure"
+};
+
+/* GMES[31:28] ME Progress Code */
+static const char *const me_progress_values[] = {
+	[ME_GMES_PHASE_ROM]	= "ROM Phase",
+	[ME_GMES_PHASE_BUP]	= "BUP Phase",
+	[ME_GMES_PHASE_UKERNEL]	= "uKernel Phase",
+	[ME_GMES_PHASE_POLICY]	= "Policy Module",
+	[ME_GMES_PHASE_MODULE]	= "Module Loading",
+	[ME_GMES_PHASE_UNKNOWN]	= "Unknown",
+	[ME_GMES_PHASE_HOST]	= "Host Communication"
+};
+
+/* GMES[27:24] Power Management Event */
+static const char *const me_pmevent_values[] = {
+	[0x00] = "Clean Moff->Mx wake",
+	[0x01] = "Moff->Mx wake after an error",
+	[0x02] = "Clean global reset",
+	[0x03] = "Global reset after an error",
+	[0x04] = "Clean Intel ME reset",
+	[0x05] = "Intel ME reset due to exception",
+	[0x06] = "Pseudo-global reset",
+	[0x07] = "S0/M0->Sx/M3",
+	[0x08] = "Sx/M3->S0/M0",
+	[0x09] = "Non-power cycle reset",
+	[0x0a] = "Power cycle reset through M3",
+	[0x0b] = "Power cycle reset through Moff",
+	[0x0c] = "Sx/Mx->Sx/Moff"
+};
+
+/* Progress Code 0 states */
+static const char *const me_progress_rom_values[] = {
+	[0x00] = "BEGIN",
+	[0x06] = "DISABLE"
+};
+
+/* Progress Code 1 states */
+static const char *const me_progress_bup_values[] = {
+	[0x00] = "Initialization starts",
+	[0x01] = "Disable the host wake event",
+	[0x04] = "Flow determination start process",
+	[0x08] = "Error reading/matching the VSCC table in the descriptor",
+	[0x0a] = "Check to see if straps say ME DISABLED",
+	[0x0b] = "Timeout waiting for PWROK",
+	[0x0d] = "Possibly handle BUP manufacturing override strap",
+	[0x11] = "Bringup in M3",
+	[0x12] = "Bringup in M0",
+	[0x13] = "Flow detection error",
+	[0x15] = "M3 clock switching error",
+	[0x18] = "M3 kernel load",
+	[0x1c] = "T34 missing - cannot program ICC",
+	[0x1f] = "Waiting for DID BIOS message",
+	[0x20] = "Waiting for DID BIOS message failure",
+	[0x21] = "DID reported an error",
+	[0x22] = "Enabling UMA",
+	[0x23] = "Enabling UMA error",
+	[0x24] = "Sending DID Ack to BIOS",
+	[0x25] = "Sending DID Ack to BIOS error",
+	[0x26] = "Switching clocks in M0",
+	[0x27] = "Switching clocks in M0 error",
+	[0x28] = "ME in temp disable",
+	[0x32] = "M0 kernel load",
+};
+
+/* Progress Code 3 states */
+static const char *const me_progress_policy_values[] = {
+	[0x00] = "Entery into Policy Module",
+	[0x03] = "Received S3 entry",
+	[0x04] = "Received S4 entry",
+	[0x05] = "Received S5 entry",
+	[0x06] = "Received UPD entry",
+	[0x07] = "Received PCR entry",
+	[0x08] = "Received NPCR entry",
+	[0x09] = "Received host wake",
+	[0x0a] = "Received AC<>DC switch",
+	[0x0b] = "Received DRAM Init Done",
+	[0x0c] = "VSCC Data not found for flash device",
+	[0x0d] = "VSCC Table is not valid",
+	[0x0e] = "Flash Partition Boundary is outside address space",
+	[0x0f] = "ME cannot access the chipset descriptor region",
+	[0x10] = "Required VSCC values for flash parts do not match",
+};
+
+void intel_me_status(struct me_hfs *hfs, struct me_gmes *gmes)
+{
+	/* Check Current States */
+	debug("ME: FW Partition Table      : %s\n",
+	      hfs->fpt_bad ? "BAD" : "OK");
+	debug("ME: Bringup Loader Failure  : %s\n",
+	      hfs->ft_bup_ld_flr ? "YES" : "NO");
+	debug("ME: Firmware Init Complete  : %s\n",
+	      hfs->fw_init_complete ? "YES" : "NO");
+	debug("ME: Manufacturing Mode      : %s\n",
+	      hfs->mfg_mode ? "YES" : "NO");
+	debug("ME: Boot Options Present    : %s\n",
+	      hfs->boot_options_present ? "YES" : "NO");
+	debug("ME: Update In Progress      : %s\n",
+	      hfs->update_in_progress ? "YES" : "NO");
+	debug("ME: Current Working State   : %s\n",
+	      me_cws_values[hfs->working_state]);
+	debug("ME: Current Operation State : %s\n",
+	      me_opstate_values[hfs->operation_state]);
+	debug("ME: Current Operation Mode  : %s\n",
+	      me_opmode_values[hfs->operation_mode]);
+	debug("ME: Error Code              : %s\n",
+	      me_error_values[hfs->error_code]);
+	debug("ME: Progress Phase          : %s\n",
+	      me_progress_values[gmes->progress_code]);
+	debug("ME: Power Management Event  : %s\n",
+	      me_pmevent_values[gmes->current_pmevent]);
+
+	debug("ME: Progress Phase State    : ");
+	switch (gmes->progress_code) {
+	case ME_GMES_PHASE_ROM:		/* ROM Phase */
+		debug("%s", me_progress_rom_values[gmes->current_state]);
+		break;
+
+	case ME_GMES_PHASE_BUP:		/* Bringup Phase */
+		if (gmes->current_state < ARRAY_SIZE(me_progress_bup_values) &&
+		    me_progress_bup_values[gmes->current_state])
+			debug("%s",
+			      me_progress_bup_values[gmes->current_state]);
+		else
+			debug("0x%02x", gmes->current_state);
+		break;
+
+	case ME_GMES_PHASE_POLICY:	/* Policy Module Phase */
+		if (gmes->current_state <
+				ARRAY_SIZE(me_progress_policy_values) &&
+		    me_progress_policy_values[gmes->current_state])
+			debug("%s",
+			      me_progress_policy_values[gmes->current_state]);
+		else
+			debug("0x%02x", gmes->current_state);
+		break;
+
+	case ME_GMES_PHASE_HOST:	/* Host Communication Phase */
+		if (!gmes->current_state)
+			debug("Host communication established");
+		else
+			debug("0x%02x", gmes->current_state);
+		break;
+
+	default:
+		debug("Unknown 0x%02x", gmes->current_state);
+	}
+	debug("\n");
+}
diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c
new file mode 100644
index 0000000..8c11a63
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/microcode_intel.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ * Copyright (C) 2000 Ronald G. Minnich
+ *
+ * Microcode update for Intel PIII and later CPUs
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <asm/cpu.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+
+/**
+ * struct microcode_update - standard microcode header from Intel
+ *
+ * We read this information out of the device tree and use it to determine
+ * whether the update is applicable or not. We also use the same structure
+ * to read information from the CPU.
+ */
+struct microcode_update {
+	uint header_version;
+	uint update_revision;
+	uint date_code;
+	uint processor_signature;
+	uint checksum;
+	uint loader_revision;
+	uint processor_flags;
+	const void *data;
+	int size;
+};
+
+static int microcode_decode_node(const void *blob, int node,
+				 struct microcode_update *update)
+{
+	update->data = fdt_getprop(blob, node, "data", &update->size);
+	if (!update->data)
+		return -EINVAL;
+
+	update->header_version = fdtdec_get_int(blob, node,
+						"intel,header-version", 0);
+	update->update_revision = fdtdec_get_int(blob, node,
+						 "intel,update-revision", 0);
+	update->date_code = fdtdec_get_int(blob, node,
+					   "intel,date-code", 0);
+	update->processor_signature = fdtdec_get_int(blob, node,
+					"intel.processor-signature", 0);
+	update->checksum = fdtdec_get_int(blob, node, "intel,checksum", 0);
+	update->loader_revision = fdtdec_get_int(blob, node,
+						 "loader-revision", 0);
+	update->processor_flags = fdtdec_get_int(blob, node,
+						 "processor-flags", 0);
+
+	return 0;
+}
+
+static uint32_t microcode_read_rev(void)
+{
+	/*
+	 * Some Intel CPUs can be very finicky about the CPUID sequence used.
+	 * So this is implemented in assembly so that it works reliably.
+	 */
+	uint32_t low, high;
+
+	asm volatile (
+		"xorl %%eax, %%eax\n"
+		"xorl %%edx, %%edx\n"
+		"movl $0x8b, %%ecx\n"
+		"wrmsr\n"
+		"movl $0x01, %%eax\n"
+		"cpuid\n"
+		"movl $0x8b, %%ecx\n"
+		"rdmsr\n"
+		: /* outputs */
+		"=a" (low), "=d" (high)
+		: /* inputs */
+		: /* clobbers */
+		 "ebx", "ecx"
+	);
+
+	return high;
+}
+
+static void microcode_read_cpu(struct microcode_update *cpu)
+{
+	/* CPUID sets MSR 0x8B iff a microcode update has been loaded. */
+	unsigned int x86_model, x86_family;
+	struct cpuid_result result;
+	uint32_t low, high;
+
+	wrmsr(0x8b, 0, 0);
+	result = cpuid(1);
+	rdmsr(0x8b, low, cpu->update_revision);
+	x86_model = (result.eax >> 4) & 0x0f;
+	x86_family = (result.eax >> 8) & 0x0f;
+	cpu->processor_signature = result.eax;
+
+	cpu->processor_flags = 0;
+	if ((x86_model >= 5) || (x86_family > 6)) {
+		rdmsr(0x17, low, high);
+		cpu->processor_flags = 1 << ((high >> 18) & 7);
+	}
+	debug("microcode: sig=%#x pf=%#x revision=%#x\n",
+	      cpu->processor_signature, cpu->processor_flags,
+	      cpu->update_revision);
+}
+
+/* Get a microcode update from the device tree and apply it */
+int microcode_update_intel(void)
+{
+	struct microcode_update cpu, update;
+	const void *blob = gd->fdt_blob;
+	int count;
+	int node;
+	int ret;
+
+	microcode_read_cpu(&cpu);
+	node = 0;
+	count = 0;
+	do {
+		node = fdtdec_next_compatible(blob, node,
+					      COMPAT_INTEL_MICROCODE);
+		if (node < 0) {
+			debug("%s: Found %d updates\n", __func__, count);
+			return count ? 0 : -ENOENT;
+		}
+
+		ret = microcode_decode_node(blob, node, &update);
+		if (ret) {
+			debug("%s: Unable to decode update: %d\n", __func__,
+			      ret);
+			return ret;
+		}
+		if (update.processor_signature == cpu.processor_signature &&
+		    (update.processor_flags & cpu.processor_flags)) {
+			debug("%s: Update already exists\n", __func__);
+			return -EEXIST;
+		}
+
+		wrmsr(0x79, (ulong)update.data, 0);
+		debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n",
+		      microcode_read_rev(), update.date_code & 0xffff,
+		      (update.date_code >> 24) & 0xff,
+		      (update.date_code >> 16) & 0xff);
+		count++;
+	} while (1);
+}
diff --git a/arch/x86/cpu/ivybridge/pci.c b/arch/x86/cpu/ivybridge/pci.c
new file mode 100644
index 0000000..c1ae658
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/pci.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2008,2009
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/pci.h>
+
+static void config_pci_bridge(struct pci_controller *hose, pci_dev_t dev,
+			      struct pci_config_table *table)
+{
+	u8 secondary;
+
+	hose->read_byte(hose, dev, PCI_SECONDARY_BUS, &secondary);
+	if (secondary != 0)
+		pci_hose_scan_bus(hose, secondary);
+}
+
+static struct pci_config_table pci_ivybridge_config_table[] = {
+	/* vendor, device, class, bus, dev, func */
+	{ PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_BRIDGE_PCI,
+		PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, &config_pci_bridge },
+	{}
+};
+
+void board_pci_setup_hose(struct pci_controller *hose)
+{
+	hose->config_table = pci_ivybridge_config_table;
+	hose->first_busno = 0;
+	hose->last_busno = 0;
+
+	/* PCI memory space */
+	pci_set_region(hose->regions + 0,
+		       CONFIG_PCI_MEM_BUS,
+		       CONFIG_PCI_MEM_PHYS,
+		       CONFIG_PCI_MEM_SIZE,
+		       PCI_REGION_MEM);
+
+	/* PCI IO space */
+	pci_set_region(hose->regions + 1,
+		       CONFIG_PCI_IO_BUS,
+		       CONFIG_PCI_IO_PHYS,
+		       CONFIG_PCI_IO_SIZE,
+		       PCI_REGION_IO);
+
+	pci_set_region(hose->regions + 2,
+		       CONFIG_PCI_PREF_BUS,
+		       CONFIG_PCI_PREF_PHYS,
+		       CONFIG_PCI_PREF_SIZE,
+		       PCI_REGION_PREFETCH);
+
+	hose->region_count = 3;
+}
diff --git a/arch/x86/cpu/ivybridge/report_platform.c b/arch/x86/cpu/ivybridge/report_platform.c
new file mode 100644
index 0000000..69e31b3
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/report_platform.c
@@ -0,0 +1,89 @@
+/*
+ * From Coreboot src/northbridge/intel/sandybridge/report_platform.c
+ *
+ * Copyright (C) 2012 Google Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/cpu.h>
+#include <asm/pci.h>
+#include <asm/arch/pch.h>
+
+static void report_cpu_info(void)
+{
+	char cpu_string[CPU_MAX_NAME_LEN], *cpu_name;
+	const char *mode[] = {"NOT ", ""};
+	struct cpuid_result cpuidr;
+	int vt, txt, aes;
+	u32 index;
+
+	index = 0x80000000;
+	cpuidr = cpuid(index);
+	if (cpuidr.eax < 0x80000004) {
+		strcpy(cpu_string, "Platform info not available");
+		cpu_name = cpu_string;
+	} else {
+		cpu_name = cpu_get_name(cpu_string);
+	}
+
+	cpuidr = cpuid(1);
+	debug("CPU id(%x): %s\n", cpuidr.eax, cpu_name);
+	aes = (cpuidr.ecx & (1 << 25)) ? 1 : 0;
+	txt = (cpuidr.ecx & (1 << 6)) ? 1 : 0;
+	vt = (cpuidr.ecx & (1 << 5)) ? 1 : 0;
+	debug("AES %ssupported, TXT %ssupported, VT %ssupported\n",
+	      mode[aes], mode[txt], mode[vt]);
+}
+
+/* The PCI id name match comes from Intel document 472178 */
+static struct {
+	u16 dev_id;
+	const char *dev_name;
+} pch_table[] = {
+	{0x1E41, "Desktop Sample"},
+	{0x1E42, "Mobile Sample"},
+	{0x1E43, "SFF Sample"},
+	{0x1E44, "Z77"},
+	{0x1E45, "H71"},
+	{0x1E46, "Z75"},
+	{0x1E47, "Q77"},
+	{0x1E48, "Q75"},
+	{0x1E49, "B75"},
+	{0x1E4A, "H77"},
+	{0x1E53, "C216"},
+	{0x1E55, "QM77"},
+	{0x1E56, "QS77"},
+	{0x1E58, "UM77"},
+	{0x1E57, "HM77"},
+	{0x1E59, "HM76"},
+	{0x1E5D, "HM75"},
+	{0x1E5E, "HM70"},
+	{0x1E5F, "NM70"},
+};
+
+static void report_pch_info(void)
+{
+	const char *pch_type = "Unknown";
+	int i;
+	u16 dev_id;
+	uint8_t rev_id;
+
+	dev_id = pci_read_config16(PCH_LPC_DEV, 2);
+	for (i = 0; i < ARRAY_SIZE(pch_table); i++) {
+		if (pch_table[i].dev_id == dev_id) {
+			pch_type = pch_table[i].dev_name;
+			break;
+		}
+	}
+	rev_id = pci_read_config8(PCH_LPC_DEV, 8);
+	debug("PCH type: %s, device id: %x, rev id %x\n", pch_type, dev_id,
+	      rev_id);
+}
+
+void report_platform_info(void)
+{
+	report_cpu_info();
+	report_pch_info();
+}
diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c
new file mode 100644
index 0000000..df2b990
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/sdram.c
@@ -0,0 +1,571 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2010,2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * Portions from Coreboot mainboard/google/link/romstage.c
+ * Copyright (C) 2007-2010 coresystems GmbH
+ * Copyright (C) 2011 Google Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <asm/processor.h>
+#include <asm/gpio.h>
+#include <asm/global_data.h>
+#include <asm/pci.h>
+#include <asm/arch/me.h>
+#include <asm/arch/pei_data.h>
+#include <asm/arch/pch.h>
+#include <asm/post.h>
+#include <asm/arch/sandybridge.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This function looks for the highest region of memory lower than 4GB which
+ * has enough space for U-Boot where U-Boot is aligned on a page boundary.
+ * It overrides the default implementation found elsewhere which simply
+ * picks the end of ram, wherever that may be. The location of the stack,
+ * the relocation address, and how far U-Boot is moved by relocation are
+ * set in the global data structure.
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+	struct memory_info *info = &gd->arch.meminfo;
+	uintptr_t dest_addr = 0;
+	struct memory_area *largest = NULL;
+	int i;
+
+	/* Find largest area of memory below 4GB */
+
+	for (i = 0; i < info->num_areas; i++) {
+		struct memory_area *area = &info->area[i];
+
+		if (area->start >= 1ULL << 32)
+			continue;
+		if (!largest || area->size > largest->size)
+			largest = area;
+	}
+
+	/* If no suitable area was found, return an error. */
+	assert(largest);
+	if (!largest || largest->size < (2 << 20))
+		panic("No available memory found for relocation");
+
+	dest_addr = largest->start + largest->size;
+
+	return (ulong)dest_addr;
+}
+
+void dram_init_banksize(void)
+{
+	struct memory_info *info = &gd->arch.meminfo;
+	int num_banks;
+	int i;
+
+	for (i = 0, num_banks = 0; i < info->num_areas; i++) {
+		struct memory_area *area = &info->area[i];
+
+		if (area->start >= 1ULL << 32)
+			continue;
+		gd->bd->bi_dram[num_banks].start = area->start;
+		gd->bd->bi_dram[num_banks].size = area->size;
+		num_banks++;
+	}
+}
+
+static const char *const ecc_decoder[] = {
+	"inactive",
+	"active on IO",
+	"disabled on IO",
+	"active"
+};
+
+/*
+ * Dump in the log memory controller configuration as read from the memory
+ * controller registers.
+ */
+static void report_memory_config(void)
+{
+	u32 addr_decoder_common, addr_decode_ch[2];
+	int i;
+
+	addr_decoder_common = readl(MCHBAR_REG(0x5000));
+	addr_decode_ch[0] = readl(MCHBAR_REG(0x5004));
+	addr_decode_ch[1] = readl(MCHBAR_REG(0x5008));
+
+	debug("memcfg DDR3 clock %d MHz\n",
+	      (readl(MCHBAR_REG(0x5e04)) * 13333 * 2 + 50) / 100);
+	debug("memcfg channel assignment: A: %d, B % d, C % d\n",
+	      addr_decoder_common & 3,
+	      (addr_decoder_common >> 2) & 3,
+	      (addr_decoder_common >> 4) & 3);
+
+	for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) {
+		u32 ch_conf = addr_decode_ch[i];
+		debug("memcfg channel[%d] config (%8.8x):\n", i, ch_conf);
+		debug("   ECC %s\n", ecc_decoder[(ch_conf >> 24) & 3]);
+		debug("   enhanced interleave mode %s\n",
+		      ((ch_conf >> 22) & 1) ? "on" : "off");
+		debug("   rank interleave %s\n",
+		      ((ch_conf >> 21) & 1) ? "on" : "off");
+		debug("   DIMMA %d MB width x%d %s rank%s\n",
+		      ((ch_conf >> 0) & 0xff) * 256,
+		      ((ch_conf >> 19) & 1) ? 16 : 8,
+		      ((ch_conf >> 17) & 1) ? "dual" : "single",
+		      ((ch_conf >> 16) & 1) ? "" : ", selected");
+		debug("   DIMMB %d MB width x%d %s rank%s\n",
+		      ((ch_conf >> 8) & 0xff) * 256,
+		      ((ch_conf >> 20) & 1) ? 16 : 8,
+		      ((ch_conf >> 18) & 1) ? "dual" : "single",
+		      ((ch_conf >> 16) & 1) ? ", selected" : "");
+	}
+}
+
+static void post_system_agent_init(struct pei_data *pei_data)
+{
+	/* If PCIe init is skipped, set the PEG clock gating */
+	if (!pei_data->pcie_init)
+		setbits_le32(MCHBAR_REG(0x7010), 1);
+}
+
+static asmlinkage void console_tx_byte(unsigned char byte)
+{
+#ifdef DEBUG
+	putc(byte);
+#endif
+}
+
+/**
+ * Find the PEI executable in the ROM and execute it.
+ *
+ * @param pei_data: configuration data for UEFI PEI reference code
+ */
+int sdram_initialise(struct pei_data *pei_data)
+{
+	unsigned version;
+	const char *data;
+	uint16_t done;
+	int ret;
+
+	report_platform_info();
+
+	/* Wait for ME to be ready */
+	ret = intel_early_me_init();
+	if (ret)
+		return ret;
+	ret = intel_early_me_uma_size();
+	if (ret < 0)
+		return ret;
+
+	debug("Starting UEFI PEI System Agent\n");
+
+	/* If MRC data is not found we cannot continue S3 resume. */
+	if (pei_data->boot_mode == PEI_BOOT_RESUME && !pei_data->mrc_input) {
+		debug("Giving up in sdram_initialize: No MRC data\n");
+		outb(0x6, PORT_RESET);
+		cpu_hlt();
+	}
+
+	/* Pass console handler in pei_data */
+	pei_data->tx_byte = console_tx_byte;
+
+	debug("PEI data at %p, size %x:\n", pei_data, sizeof(*pei_data));
+
+	data = (char *)CONFIG_X86_MRC_START;
+	if (data) {
+		int rv;
+		int (*func)(struct pei_data *);
+
+		debug("Calling MRC at %p\n", data);
+		post_code(POST_PRE_MRC);
+		func = (int (*)(struct pei_data *))data;
+		rv = func(pei_data);
+		post_code(POST_MRC);
+		if (rv) {
+			switch (rv) {
+			case -1:
+				printf("PEI version mismatch.\n");
+				break;
+			case -2:
+				printf("Invalid memory frequency.\n");
+				break;
+			default:
+				printf("MRC returned %x.\n", rv);
+			}
+			printf("Nonzero MRC return value.\n");
+			return -EFAULT;
+		}
+	} else {
+		printf("UEFI PEI System Agent not found.\n");
+		return -ENOSYS;
+	}
+
+#if CONFIG_USBDEBUG
+	/* mrc.bin reconfigures USB, so reinit it to have debug */
+	early_usbdebug_init();
+#endif
+
+	version = readl(MCHBAR_REG(0x5034));
+	debug("System Agent Version %d.%d.%d Build %d\n",
+	      version >> 24 , (version >> 16) & 0xff,
+	      (version >> 8) & 0xff, version & 0xff);
+
+	/*
+	 * Send ME init done for SandyBridge here.  This is done inside the
+	 * SystemAgent binary on IvyBridge
+	 */
+	done = pci_read_config32(PCH_DEV, PCI_DEVICE_ID);
+	done &= BASE_REV_MASK;
+	if (BASE_REV_SNB == done)
+		intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
+	else
+		intel_early_me_status();
+
+	post_system_agent_init(pei_data);
+	report_memory_config();
+
+	return 0;
+}
+
+static int copy_spd(struct pei_data *peid)
+{
+	const int gpio_vector[] = {41, 42, 43, 10, -1};
+	int spd_index;
+	const void *blob = gd->fdt_blob;
+	int node, spd_node;
+	int ret, i;
+
+	for (i = 0; ; i++) {
+		if (gpio_vector[i] == -1)
+			break;
+		ret = gpio_requestf(gpio_vector[i], "spd_id%d", i);
+		if (ret) {
+			debug("%s: Could not request gpio %d\n", __func__,
+			      gpio_vector[i]);
+			return ret;
+		}
+	}
+	spd_index = gpio_get_values_as_int(gpio_vector);
+	debug("spd index %d\n", spd_index);
+	node = fdtdec_next_compatible(blob, 0, COMPAT_MEMORY_SPD);
+	if (node < 0) {
+		printf("SPD data not found.\n");
+		return -ENOENT;
+	}
+
+	for (spd_node = fdt_first_subnode(blob, node);
+	     spd_node > 0;
+	     spd_node = fdt_next_subnode(blob, spd_node)) {
+		const char *data;
+		int len;
+
+		if (fdtdec_get_int(blob, spd_node, "reg", -1) != spd_index)
+			continue;
+		data = fdt_getprop(blob, spd_node, "data", &len);
+		if (len < sizeof(peid->spd_data[0])) {
+			printf("Missing SPD data\n");
+			return -EINVAL;
+		}
+
+		debug("Using SDRAM SPD data for '%s'\n",
+		      fdt_get_name(blob, spd_node, NULL));
+		memcpy(peid->spd_data[0], data, sizeof(peid->spd_data[0]));
+		break;
+	}
+
+	if (spd_node < 0) {
+		printf("No SPD data found for index %d\n", spd_index);
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
+/**
+ * add_memory_area() - Add a new usable memory area to our list
+ *
+ * Note: @start and @end must not span the first 4GB boundary
+ *
+ * @info:	Place to store memory info
+ * @start:	Start of this memory area
+ * @end:	End of this memory area + 1
+ */
+static int add_memory_area(struct memory_info *info,
+			   uint64_t start, uint64_t end)
+{
+	struct memory_area *ptr;
+
+	if (info->num_areas == CONFIG_NR_DRAM_BANKS)
+		return -ENOSPC;
+
+	ptr = &info->area[info->num_areas];
+	ptr->start = start;
+	ptr->size = end - start;
+	info->total_memory += ptr->size;
+	if (ptr->start < (1ULL << 32))
+		info->total_32bit_memory += ptr->size;
+	debug("%d: memory %llx size %llx, total now %llx / %llx\n",
+	      info->num_areas, ptr->start, ptr->size,
+	      info->total_32bit_memory, info->total_memory);
+	info->num_areas++;
+
+	return 0;
+}
+
+/**
+ * sdram_find() - Find available memory
+ *
+ * This is a bit complicated since on x86 there are system memory holes all
+ * over the place. We create a list of available memory blocks
+ */
+static int sdram_find(pci_dev_t dev)
+{
+	struct memory_info *info = &gd->arch.meminfo;
+	uint32_t tseg_base, uma_size, tolud;
+	uint64_t tom, me_base, touud;
+	uint64_t uma_memory_base = 0;
+	uint64_t uma_memory_size;
+	unsigned long long tomk;
+	uint16_t ggc;
+
+	/* Total Memory 2GB example:
+	 *
+	 *  00000000  0000MB-1992MB  1992MB  RAM     (writeback)
+	 *  7c800000  1992MB-2000MB     8MB  TSEG    (SMRR)
+	 *  7d000000  2000MB-2002MB     2MB  GFX GTT (uncached)
+	 *  7d200000  2002MB-2034MB    32MB  GFX UMA (uncached)
+	 *  7f200000   2034MB TOLUD
+	 *  7f800000   2040MB MEBASE
+	 *  7f800000  2040MB-2048MB     8MB  ME UMA  (uncached)
+	 *  80000000   2048MB TOM
+	 * 100000000  4096MB-4102MB     6MB  RAM     (writeback)
+	 *
+	 * Total Memory 4GB example:
+	 *
+	 *  00000000  0000MB-2768MB  2768MB  RAM     (writeback)
+	 *  ad000000  2768MB-2776MB     8MB  TSEG    (SMRR)
+	 *  ad800000  2776MB-2778MB     2MB  GFX GTT (uncached)
+	 *  ada00000  2778MB-2810MB    32MB  GFX UMA (uncached)
+	 *  afa00000   2810MB TOLUD
+	 *  ff800000   4088MB MEBASE
+	 *  ff800000  4088MB-4096MB     8MB  ME UMA  (uncached)
+	 * 100000000   4096MB TOM
+	 * 100000000  4096MB-5374MB  1278MB  RAM     (writeback)
+	 * 14fe00000   5368MB TOUUD
+	 */
+
+	/* Top of Upper Usable DRAM, including remap */
+	touud = pci_read_config32(dev, TOUUD+4);
+	touud <<= 32;
+	touud |= pci_read_config32(dev, TOUUD);
+
+	/* Top of Lower Usable DRAM */
+	tolud = pci_read_config32(dev, TOLUD);
+
+	/* Top of Memory - does not account for any UMA */
+	tom = pci_read_config32(dev, 0xa4);
+	tom <<= 32;
+	tom |= pci_read_config32(dev, 0xa0);
+
+	debug("TOUUD %llx TOLUD %08x TOM %llx\n", touud, tolud, tom);
+
+	/* ME UMA needs excluding if total memory <4GB */
+	me_base = pci_read_config32(dev, 0x74);
+	me_base <<= 32;
+	me_base |= pci_read_config32(dev, 0x70);
+
+	debug("MEBASE %llx\n", me_base);
+
+	/* TODO: Get rid of all this shifting by 10 bits */
+	tomk = tolud >> 10;
+	if (me_base == tolud) {
+		/* ME is from MEBASE-TOM */
+		uma_size = (tom - me_base) >> 10;
+		/* Increment TOLUD to account for ME as RAM */
+		tolud += uma_size << 10;
+		/* UMA starts at old TOLUD */
+		uma_memory_base = tomk * 1024ULL;
+		uma_memory_size = uma_size * 1024ULL;
+		debug("ME UMA base %llx size %uM\n", me_base, uma_size >> 10);
+	}
+
+	/* Graphics memory comes next */
+	ggc = pci_read_config16(dev, GGC);
+	if (!(ggc & 2)) {
+		debug("IGD decoded, subtracting ");
+
+		/* Graphics memory */
+		uma_size = ((ggc >> 3) & 0x1f) * 32 * 1024ULL;
+		debug("%uM UMA", uma_size >> 10);
+		tomk -= uma_size;
+		uma_memory_base = tomk * 1024ULL;
+		uma_memory_size += uma_size * 1024ULL;
+
+		/* GTT Graphics Stolen Memory Size (GGMS) */
+		uma_size = ((ggc >> 8) & 0x3) * 1024ULL;
+		tomk -= uma_size;
+		uma_memory_base = tomk * 1024ULL;
+		uma_memory_size += uma_size * 1024ULL;
+		debug(" and %uM GTT\n", uma_size >> 10);
+	}
+
+	/* Calculate TSEG size from its base which must be below GTT */
+	tseg_base = pci_read_config32(dev, 0xb8);
+	uma_size = (uma_memory_base - tseg_base) >> 10;
+	tomk -= uma_size;
+	uma_memory_base = tomk * 1024ULL;
+	uma_memory_size += uma_size * 1024ULL;
+	debug("TSEG base 0x%08x size %uM\n", tseg_base, uma_size >> 10);
+
+	debug("Available memory below 4GB: %lluM\n", tomk >> 10);
+
+	/* Report the memory regions */
+	add_memory_area(info, 1 << 20, 2 << 28);
+	add_memory_area(info, (2 << 28) + (2 << 20), 4 << 28);
+	add_memory_area(info, (4 << 28) + (2 << 20), tseg_base);
+	add_memory_area(info, 1ULL << 32, touud);
+	/*
+	 * If >= 4GB installed then memory from TOLUD to 4GB
+	 * is remapped above TOM, TOUUD will account for both
+	 */
+	if (touud > (1ULL << 32ULL)) {
+		debug("Available memory above 4GB: %lluM\n",
+		      (touud >> 20) - 4096);
+	}
+
+	return 0;
+}
+
+static void rcba_config(void)
+{
+	/*
+	 *             GFX    INTA -> PIRQA (MSI)
+	 * D28IP_P3IP  WLAN   INTA -> PIRQB
+	 * D29IP_E1P   EHCI1  INTA -> PIRQD
+	 * D26IP_E2P   EHCI2  INTA -> PIRQF
+	 * D31IP_SIP   SATA   INTA -> PIRQF (MSI)
+	 * D31IP_SMIP  SMBUS  INTB -> PIRQH
+	 * D31IP_TTIP  THRT   INTC -> PIRQA
+	 * D27IP_ZIP   HDA    INTA -> PIRQA (MSI)
+	 *
+	 * TRACKPAD                -> PIRQE (Edge Triggered)
+	 * TOUCHSCREEN             -> PIRQG (Edge Triggered)
+	 */
+
+	/* Device interrupt pin register (board specific) */
+	writel((INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) |
+	       (INTB << D31IP_SMIP) | (INTA << D31IP_SIP), RCB_REG(D31IP));
+	writel(NOINT << D30IP_PIP, RCB_REG(D30IP));
+	writel(INTA << D29IP_E1P, RCB_REG(D29IP));
+	writel(INTA << D28IP_P3IP, RCB_REG(D28IP));
+	writel(INTA << D27IP_ZIP, RCB_REG(D27IP));
+	writel(INTA << D26IP_E2P, RCB_REG(D26IP));
+	writel(NOINT << D25IP_LIP, RCB_REG(D25IP));
+	writel(NOINT << D22IP_MEI1IP, RCB_REG(D22IP));
+
+	/* Device interrupt route registers */
+	writel(DIR_ROUTE(PIRQB, PIRQH, PIRQA, PIRQC), RCB_REG(D31IR));
+	writel(DIR_ROUTE(PIRQD, PIRQE, PIRQF, PIRQG), RCB_REG(D29IR));
+	writel(DIR_ROUTE(PIRQB, PIRQC, PIRQD, PIRQE), RCB_REG(D28IR));
+	writel(DIR_ROUTE(PIRQA, PIRQH, PIRQA, PIRQB), RCB_REG(D27IR));
+	writel(DIR_ROUTE(PIRQF, PIRQE, PIRQG, PIRQH), RCB_REG(D26IR));
+	writel(DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD), RCB_REG(D25IR));
+	writel(DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD), RCB_REG(D22IR));
+
+	/* Enable IOAPIC (generic) */
+	writew(0x0100, RCB_REG(OIC));
+	/* PCH BWG says to read back the IOAPIC enable register */
+	(void)readw(RCB_REG(OIC));
+
+	/* Disable unused devices (board specific) */
+	setbits_le32(RCB_REG(FD), PCH_DISABLE_ALWAYS);
+}
+
+int dram_init(void)
+{
+	struct pei_data pei_data __aligned(8) = {
+		.pei_version = PEI_VERSION,
+		.mchbar = DEFAULT_MCHBAR,
+		.dmibar = DEFAULT_DMIBAR,
+		.epbar = DEFAULT_EPBAR,
+		.pciexbar = CONFIG_MMCONF_BASE_ADDRESS,
+		.smbusbar = SMBUS_IO_BASE,
+		.wdbbar = 0x4000000,
+		.wdbsize = 0x1000,
+		.hpet_address = CONFIG_HPET_ADDRESS,
+		.rcba = DEFAULT_RCBABASE,
+		.pmbase = DEFAULT_PMBASE,
+		.gpiobase = DEFAULT_GPIOBASE,
+		.thermalbase = 0xfed08000,
+		.system_type = 0, /* 0 Mobile, 1 Desktop/Server */
+		.tseg_size = CONFIG_SMM_TSEG_SIZE,
+		.ts_addresses = { 0x00, 0x00, 0x00, 0x00 },
+		.ec_present = 1,
+		.ddr3lv_support = 1,
+		/*
+		 * 0 = leave channel enabled
+		 * 1 = disable dimm 0 on channel
+		 * 2 = disable dimm 1 on channel
+		 * 3 = disable dimm 0+1 on channel
+		 */
+		.dimm_channel0_disabled = 2,
+		.dimm_channel1_disabled = 2,
+		.max_ddr3_freq = 1600,
+		.usb_port_config = {
+			/*
+			 * Empty and onboard Ports 0-7, set to un-used pin
+			 * OC3
+			 */
+			{ 0, 3, 0x0000 }, /* P0= Empty */
+			{ 1, 0, 0x0040 }, /* P1= Left USB 1  (OC0) */
+			{ 1, 1, 0x0040 }, /* P2= Left USB 2  (OC1) */
+			{ 1, 3, 0x0040 }, /* P3= SDCARD      (no OC) */
+			{ 0, 3, 0x0000 }, /* P4= Empty */
+			{ 1, 3, 0x0040 }, /* P5= WWAN        (no OC) */
+			{ 0, 3, 0x0000 }, /* P6= Empty */
+			{ 0, 3, 0x0000 }, /* P7= Empty */
+			/*
+			 * Empty and onboard Ports 8-13, set to un-used pin
+			 * OC4
+			 */
+			{ 1, 4, 0x0040 }, /* P8= Camera      (no OC) */
+			{ 1, 4, 0x0040 }, /* P9= Bluetooth   (no OC) */
+			{ 0, 4, 0x0000 }, /* P10= Empty */
+			{ 0, 4, 0x0000 }, /* P11= Empty */
+			{ 0, 4, 0x0000 }, /* P12= Empty */
+			{ 0, 4, 0x0000 }, /* P13= Empty */
+		},
+	};
+	pci_dev_t dev = PCI_BDF(0, 0, 0);
+	int ret;
+
+	debug("Boot mode %d\n", gd->arch.pei_boot_mode);
+	debug("mcr_input %p\n", pei_data.mrc_input);
+	pei_data.boot_mode = gd->arch.pei_boot_mode;
+	ret = copy_spd(&pei_data);
+	if (!ret)
+		ret = sdram_initialise(&pei_data);
+	if (ret)
+		return ret;
+
+	rcba_config();
+	quick_ram_check();
+
+	writew(0xCAFE, MCHBAR_REG(SSKPD));
+
+	post_code(POST_DRAM);
+
+	ret = sdram_find(dev);
+	if (ret)
+		return ret;
+
+	gd->ram_size = gd->arch.meminfo.total_32bit_memory;
+
+	return 0;
+}
diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c
new file mode 100644
index 0000000..e399388
--- /dev/null
+++ b/arch/x86/cpu/pci.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2008,2009
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <pci.h>
+#include <asm/pci.h>
+
+static struct pci_controller x86_hose;
+
+int pci_early_init_hose(struct pci_controller **hosep)
+{
+	struct pci_controller *hose;
+
+	hose = calloc(1, sizeof(struct pci_controller));
+	if (!hose)
+		return -ENOMEM;
+
+	board_pci_setup_hose(hose);
+	pci_setup_type1(hose);
+	gd->arch.hose = hose;
+	*hosep = hose;
+
+	return 0;
+}
+
+void pci_init_board(void)
+{
+	struct pci_controller *hose = &x86_hose;
+
+	/* Stop using the early hose */
+	gd->arch.hose = NULL;
+
+	board_pci_setup_hose(hose);
+	pci_setup_type1(hose);
+	pci_register_hose(hose);
+
+	hose->last_busno = pci_hose_scan(hose);
+}
+
+static struct pci_controller *get_hose(void)
+{
+	if (gd->arch.hose)
+		return gd->arch.hose;
+
+	return pci_bus_to_hose(0);
+}
+
+unsigned int pci_read_config8(pci_dev_t dev, unsigned where)
+{
+	uint8_t value;
+
+	pci_hose_read_config_byte(get_hose(), dev, where, &value);
+
+	return value;
+}
+
+unsigned int pci_read_config16(pci_dev_t dev, unsigned where)
+{
+	uint16_t value;
+
+	pci_hose_read_config_word(get_hose(), dev, where, &value);
+
+	return value;
+}
+
+unsigned int pci_read_config32(pci_dev_t dev, unsigned where)
+{
+	uint32_t value;
+
+	pci_hose_read_config_dword(get_hose(), dev, where, &value);
+
+	return value;
+}
+
+void pci_write_config8(pci_dev_t dev, unsigned where, unsigned value)
+{
+	pci_hose_write_config_byte(get_hose(), dev, where, value);
+}
+
+void pci_write_config16(pci_dev_t dev, unsigned where, unsigned value)
+{
+	pci_hose_write_config_word(get_hose(), dev, where, value);
+}
+
+void pci_write_config32(pci_dev_t dev, unsigned where, unsigned value)
+{
+	pci_hose_write_config_dword(get_hose(), dev, where, value);
+}
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 338bab1..b0d0ac0 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -13,6 +13,7 @@
 #include <config.h>
 #include <version.h>
 #include <asm/global_data.h>
+#include <asm/post.h>
 #include <asm/processor.h>
 #include <asm/processor-flags.h>
 #include <generated/generic-asm-offsets.h>
@@ -49,6 +50,8 @@
 	 */
 	movw	$GD_FLG_COLD_BOOT, %bx
 1:
+	/* Save BIST */
+	movl	%eax, %ebp
 
 	/* Load the segement registes to match the gdt loaded in start16.S */
 	movl	$(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax
@@ -65,6 +68,7 @@
 	jmp	early_board_init
 .globl early_board_init_ret
 early_board_init_ret:
+	post_code(POST_START)
 
 	/* Initialise Cache-As-RAM */
 	jmp	car_init
@@ -74,16 +78,29 @@
 	 * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM,
 	 * or fully initialised SDRAM - we really don't care which)
 	 * starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack
+	 * and early malloc area. The MRC requires some space at the top.
+	 *
+	 * Stack grows down from top of CAR. We have:
+	 *
+	 * top-> CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE
+	 *	MRC area
+	 *	global_data
+	 *	x86 global descriptor table
+	 *	early malloc area
+	 *	stack
+	 * bottom-> CONFIG_SYS_CAR_ADDR
 	 */
-
-	/* Stack grows down from top of CAR */
-	movl	$(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE), %esp
+	movl	$(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %esp
+#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE
+	subl	$CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp
+#endif
 
 	/* Reserve space on stack for global data */
 	subl	$GENERATED_GBL_DATA_SIZE, %esp
 
 	/* Align global data to 16-byte boundary */
 	andl	$0xfffffff0, %esp
+	post_code(POST_START_STACK)
 
 	/* Zero the global data since it won't happen later */
 	xorl	%eax, %eax
@@ -91,31 +108,36 @@
 	movl	%esp, %edi
 	rep	stosb
 
-	/* Setup first parameter to setup_gdt */
+	/* Setup first parameter to setup_gdt, pointer to global_data */
 	movl	%esp, %eax
 
 	/* Reserve space for global descriptor table */
 	subl	$X86_GDT_SIZE, %esp
 
+	/* Align temporary global descriptor table to 16-byte boundary */
+	andl	$0xfffffff0, %esp
+	movl	%esp, %ecx
+
 #if defined(CONFIG_SYS_MALLOC_F_LEN)
 	subl	$CONFIG_SYS_MALLOC_F_LEN, %esp
 	movl	%eax, %edx
 	addl	$GD_MALLOC_BASE, %edx
 	movl	%esp, (%edx)
 #endif
-
-	/* Align temporary global descriptor table to 16-byte boundary */
-	andl	$0xfffffff0, %esp
+	/* Store BIST */
+	movl	%eax, %edx
+	addl	$GD_BIST, %edx
+	movl	%ebp, (%edx)
 
 	/* Set second parameter to setup_gdt */
-	movl	%esp, %edx
+	movl	%ecx, %edx
 
 	/* Setup global descriptor table so gd->xyz works */
 	call	setup_gdt
 
 	/* Set parameter to board_init_f() to boot flags */
+	post_code(POST_START_DONE)
 	xorl	%eax, %eax
-	movw	%bx, %ax
 
 	/* Enter, U-boot! */
 	call	board_init_f
diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S
index 6968fda..9550502 100644
--- a/arch/x86/cpu/start16.S
+++ b/arch/x86/cpu/start16.S
@@ -21,18 +21,16 @@
 .code16
 .globl start16
 start16:
+	/* Save BIST */
+	movl	%eax, %ecx
+
 	/* Set the Cold Boot / Hard Reset flag */
 	movl	$GD_FLG_COLD_BOOT, %ebx
 
-	/*
-	 * First we let the BSP do some early initialization
-	 * this code have to map the flash to its final position
-	 */
-	jmp	board_init16
-.globl board_init16_ret
-board_init16_ret:
+	xorl	%eax, %eax
+	movl	%eax, %cr3    /* Invalidate TLB */
 
-	/* Turn of cache (this might require a 486-class CPU) */
+	/* Turn off cache (this might require a 486-class CPU) */
 	movl	%cr0, %eax
 	orl	$(X86_CR0_NW | X86_CR0_CD), %eax
 	movl	%eax, %cr0
@@ -50,9 +48,11 @@
 	/* Flush the prefetch queue */
 	jmp	ff
 ff:
-	/* Finally jump to the 32bit initialization code */
+
+	/* Finally restore BIST and jump to the 32bit initialization code */
 	movw	$code32start, %ax
 	movw	%ax, %bp
+	movl	%ecx, %eax
 o32 cs	ljmp	*(%bp)
 
 	/* 48-bit far pointer */
diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile
index 48265ef..bb3b116 100644
--- a/arch/x86/dts/Makefile
+++ b/arch/x86/dts/Makefile
@@ -1,4 +1,5 @@
 dtb-y += link.dtb \
+	chromebook_link.dtb \
 	alex.dtb
 
 targets += $(dtb-y)
diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts
new file mode 120000
index 0000000..6f8c5cd
--- /dev/null
+++ b/arch/x86/dts/chromebook_link.dts
@@ -0,0 +1 @@
+link.dts
\ No newline at end of file
diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts
index f2fcb39..9329916 100644
--- a/arch/x86/dts/link.dts
+++ b/arch/x86/dts/link.dts
@@ -14,18 +14,21 @@
 
 	gpioa {
 		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
 		reg = <0 0x10>;
 		bank-name = "A";
 	};
 
 	gpiob {
 		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
 		reg = <0x30 0x10>;
 		bank-name = "B";
 	};
 
 	gpioc {
 		compatible = "intel,ich6-gpio";
+		u-boot,dm-pre-reloc;
 		reg = <0x40 0x10>;
 		bank-name = "C";
 	};
@@ -38,6 +41,117 @@
 	chosen { };
 	memory { device_type = "memory"; reg = <0 0>; };
 
+	spd {
+		compatible = "memory-spd";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		elpida_4Gb_1600_x16 {
+			reg = <0>;
+			data = [92 10 0b 03 04 19 02 02
+				03 52 01 08 0a 00 fe 00
+				69 78 69 3c 69 11 18 81
+				20 08 3c 3c 01 40 83 81
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 0f 11 42 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 02 fe 00
+				11 52 00 00 00 07 7f 37
+				45 42 4a 32 30 55 47 36
+				45 42 55 30 2d 47 4e 2d
+				46 20 30 20 02 fe 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00];
+		};
+		samsung_4Gb_1600_1.35v_x16 {
+			reg = <1>;
+			data = [92 11 0b 03 04 19 02 02
+				03 11 01 08 0a 00 fe 00
+				69 78 69 3c 69 11 18 81
+				f0 0a 3c 3c 01 40 83 01
+				00 80 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 0f 11 02 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 80 ce 01
+				00 00 00 00 00 00 6a 04
+				4d 34 37 31 42 35 36 37
+				34 42 48 30 2d 59 4b 30
+				20 20 00 00 80 ce 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00];
+			};
+		micron_4Gb_1600_1.35v_x16 {
+			reg = <2>;
+			data = [92 11 0b 03 04 19 02 02
+				03 11 01 08 0a 00 fe 00
+				69 78 69 3c 69 11 18 81
+				20 08 3c 3c 01 40 83 05
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 0f 01 02 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 80 2c 00
+				00 00 00 00 00 00 ad 75
+				34 4b 54 46 32 35 36 36
+				34 48 5a 2d 31 47 36 45
+				31 20 45 31 80 2c 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00
+				ff ff ff ff ff ff ff ff
+				ff ff ff ff ff ff ff ff
+				ff ff ff ff ff ff ff ff
+				ff ff ff ff ff ff ff ff
+				ff ff ff ff ff ff ff ff
+				ff ff ff ff ff ff ff ff
+				ff ff ff ff ff ff ff ff
+				ff ff ff ff ff ff ff ff
+				ff ff ff ff ff ff ff ff
+				ff ff ff ff ff ff ff ff];
+		};
+	};
+
 	spi {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -53,6 +167,7 @@
 		compatible = "intel,lpc";
 		#address-cells = <1>;
 		#size-cells = <1>;
+		gen-dec = <0x800 0xfc 0x900 0xfc>;
 		cros-ec@200 {
 			compatible = "google,cros-ec";
 			reg = <0x204 1 0x200 1 0x880 0x80>;
@@ -66,4 +181,14 @@
 			};
 		};
 	};
+
+	microcode {
+		update@0 {
+#include "m12206a7_00000028.dtsi"
+		};
+		update@1 {
+#include "m12306a9_00000017.dtsi"
+		};
+	};
+
 };
diff --git a/arch/x86/dts/m12206a7_00000028.dtsi b/arch/x86/dts/m12206a7_00000028.dtsi
new file mode 100644
index 0000000..bcd5248
--- /dev/null
+++ b/arch/x86/dts/m12206a7_00000028.dtsi
@@ -0,0 +1,622 @@
+/*
+ * Copyright (c) <1995-2013>, Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution. Redistribution and use in binary form, without modification, are
+ * permitted provided that the following conditions are met:
+ *	.Redistributions must reproduce the above copyright notice and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Intel Corporation nor the names of its suppliers may be used
+ * to endorse or promote products derived from this software without specific prior
+ * written permission.
+ *	.No reverse engineering, decompilation, or disassembly of this software is
+ * permitted.
+ *	."Binary form" includes any format commonly used for electronic conveyance
+ * which is a reversible, bit-exact translation of binary representation to ASCII or
+ * ISO text, for example, "uuencode."
+ *
+ * DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *---
+ * This is a device tree fragment. Use #include to add these properties to a
+ * node.
+ */
+
+compatible = "intel,microcode";
+intel,header-version = <1>;
+intel,update-revision = <0x28>;
+intel,date-code = <0x04242012>;
+intel,processor-signature = <0x000206a7>;
+intel,checksum = <0xf3e9935d>;
+intel,loader-revision = <1>;
+intel,processor-flags = <0x12>;
+
+/* The 48-byte public header is omitted. */
+data = <
+	0x00000000	0x000000a1	0x00020001	0x00000028
+	0x00000000	0x00000000	0x20120423	0x000008f1
+	0x00000001	0x000206a7	0x00000000	0x00000000
+	0x00000000	0x00000000	0x00000000	0x00000000
+	0x00000000	0x000008f1	0x00000000	0x00000000
+	0x00000000	0x00000000	0x00000000	0x00000000
+	0x52b813ac	0xdb8994c7	0x70e9f6bb	0x9d6db2ff
+	0xf4d70f5d	0x5b1eccf6	0xac59106f	0x0ae2e2c1
+	0x1a7bbeb1	0x355a1d62	0x2e7eb594	0x09f8dea9
+	0x432a49e4	0xbf520253	0xdafa4010	0x893a858a
+	0x766e0efb	0xd91e196d	0x838bd2ef	0xe5146494
+	0xd515f413	0x29704828	0xe85598b6	0xdcbe6c51
+	0x88eabbfa	0xa1e8909f	0xd8931721	0x35386554
+	0x089a78a7	0xd9914775	0xd4644748	0x1556a4dc
+	0xf44448f6	0xd054d7db	0xf30f2b7d	0x5ae223d0
+	0xcbbb48b0	0x5c8b0383	0x177de157	0x9c1e5f73
+	0x2ec28289	0xd72a7b6c	0x823b6eb2	0x35e02171
+	0xba8deae4	0x06f4d468	0x13dbafaa	0x72b419f1
+	0x033385b5	0x05806920	0x4c6034cf	0x9bd117dc
+	0x976e2d04	0x250330f0	0x7250b5e1	0x184980c2
+	0x12a9d7d6	0x1bc808f9	0xae79994f	0xc6f87901
+	0xc0e3132f	0x671491c5	0x236cad39	0x37889d9c
+	0x67f7c3f3	0x964a6be5	0xbcced7da	0x57eeaa6e
+	0x7bca1522	0x654fee4c	0x2a1ca5d9	0xa1803cf3
+	0x00000011	0x8c316d2c	0x17603b7e	0x32e42981
+	0xc26c1400	0xf0fbccb6	0xeab6b43a	0x11d456a5
+	0x5b912d46	0x15195fe0	0x542f6db3	0x0b7f212e
+	0x47718dd9	0x7c41b108	0x06c21111	0x4445d5ea
+	0xb4fb8128	0xe07404a6	0x8d503da4	0x78fc7e44
+	0xb9919656	0x9968c797	0x87f26ab0	0x23bb1af7
+	0x1ec5d761	0x26f30d2c	0x7cdb747c	0xe4d42033
+	0x8a5d4801	0x768aff57	0xbcfd5d11	0x7c853c2d
+	0x231e6207	0x8b1988a6	0xd68fdb75	0x58dcb417
+	0x44422ef9	0x2a186ebb	0x7d27e85f	0x36ac31f7
+	0x1e487e77	0x2b0b8c37	0xd8ba682f	0x2cba791b
+	0xe6d3dece	0x1b2c2a99	0x4e5decab	0xfbd313a3
+	0xdbc78294	0x5a80cce7	0x2d8e0f0b	0xcf564f71
+	0x073d1f37	0x25162870	0x96cdb85b	0x9c553048
+	0x24eba740	0xfc0f352e	0x0c83be68	0x89b5076c
+	0xc39c4355	0x6a4cf25c	0x2bbd2682	0xc524fdb9
+	0x7ea19bae	0x191ad6f1	0xd3fbf3bf	0x21bf77fa
+	0x8f77fec4	0x0f90f635	0xe55e165c	0x868d58c0
+	0x966bc0ad	0x6c276364	0x9d8f7eff	0x4b7925d4
+	0x8b2f9326	0x4ab7b47e	0x33a9087c	0xf31ab949
+	0x69831dfb	0x4711a215	0x8128c1fa	0x8481c213
+	0x7401b01b	0xfdcfdc50	0xd6b55266	0xae9b23ac
+	0xfa2ad275	0xa225bb45	0x4dd720c4	0x760a20e6
+	0x5f1223c9	0x2f334372	0x6e1dcdab	0xe8ee8638
+	0x1c19ba8a	0xef9341c4	0x360aaa9d	0x90452ea9
+	0x65852446	0xe9398fa3	0xbba6a631	0x1a3e90b9
+	0xe2a73a56	0x6e8c0747	0x35c7c53d	0xcc1ac842
+	0x183356af	0xb6e98608	0x987b43c2	0xa8a3cfd2
+	0xc2c5fce0	0xcc3af64a	0xd6d3a291	0xe59ad1f5
+	0x124ca513	0x9522b50a	0x25150477	0xa2eb5797
+	0x7fc63626	0x648c48e3	0x9f5797ff	0x2307b84d
+	0x980625a4	0xabc05983	0x24980807	0x773c4f99
+	0x3407b872	0x07c3657a	0xa2cd9e48	0x49c1e6a8
+	0xa881b84c	0xf804d72c	0xb5319d2a	0x3e39780f
+	0x97518822	0x0acd54c2	0x0721a9ff	0x10e1d2fd
+	0xa7b6db77	0x845b1a56	0xef00160e	0x6b41bfd5
+	0xc994df0d	0xcf44a5ca	0x794b36a4	0xf9fdb127
+	0x922a1366	0x822aa8a9	0x4b137bd5	0x5722a49f
+	0x8933719a	0x17edc1a9	0x079d9538	0x21fae7d5
+	0xe534fd73	0x9d3038d5	0x48c3a056	0x5b22d58a
+	0x6f142866	0xf1d767cd	0xb51ad5a6	0x34a0ef85
+	0x0111703e	0xca4b3a30	0xa0f3c34d	0x9d48775a
+	0x3f2059f9	0xf2fe2c36	0x588861a9	0xed5bd9fe
+	0x8231f7cb	0x8c115969	0x3f82ba00	0x21b3730c
+	0xba757997	0x3ec0bb2c	0x16f11def	0x5d4356c6
+	0xdc2e0bc2	0x58c1eb6e	0x313ede0c	0xb68fcc52
+	0x84d3e1b5	0xcc6d9201	0x95046196	0x276b527b
+	0x80a4a729	0xe782916d	0x5cf09e0b	0x98aaf9fa
+	0x1de6dd43	0xab4f1962	0x49ece734	0x81455488
+	0xc2597b61	0x5b22af85	0x646f7b94	0x09213a1f
+	0x08edf7e4	0x963d343c	0x059ba888	0xb4e804ed
+	0xe7cc826c	0xf87bafc7	0xeecaec10	0x8e60919c
+	0xbf14c996	0xd3dcaee3	0xb8fa0b7e	0x81563c6e
+	0x7f59a258	0x2f344446	0x374d8aa6	0x9b6de5c9
+	0xbf992857	0xbc5b94fc	0x28adb080	0x17e41044
+	0xb87b469e	0xda504d12	0xf21bef8b	0xce75c1e3
+	0xdbd92c83	0x58bba0af	0x77b42977	0x506cfd75
+	0x1139e875	0x6ce5fe43	0xc6a5d7b3	0x87f9e628
+	0x7b5c500b	0x130066b3	0x789b611f	0xec8c1ba9
+	0xb7e6872d	0xaf828cd6	0xc28d3316	0x2a91f6d0
+	0xc725f063	0x065ac531	0x4f9ef4b8	0x2b9d927e
+	0xaf54f3f9	0x7c924f72	0xda1d77ad	0xff00db67
+	0xaf4f03c0	0xb4f4ee64	0x169e64e5	0x04653ac0
+	0xed51cb70	0xfeaff0e5	0x51dbf346	0x072a2407
+	0x23fb74f4	0x9a906eef	0x5d6fc3f0	0xbc3c374c
+	0x1cf9f063	0x919015d9	0x5b3e9d07	0xd6209d8b
+	0xa3710b3d	0x90ad23b8	0x420ceedc	0x58e8371f
+	0x5d419d1f	0xb8acd13f	0x7d100d6d	0x210c10d1
+	0xcd0a697e	0x5023db4b	0x33e6d8e7	0x44bbe6b4
+	0x827e859f	0x6ca4cc81	0x661bb2c3	0x71209ee8
+	0xb8c3ffaf	0xd1075f51	0xba1eae10	0x728b0a6a
+	0xe4af7a2f	0xca9bcf2e	0xb249a631	0xdce6be47
+	0x5c910321	0x425c3c27	0x33083e43	0xdea067ae
+	0xea594a23	0x41b75c2c	0x3a401a95	0xd33cd88a
+	0xc295cad0	0x67f48045	0x1dc9ad4c	0x4bc48864
+	0x53991b6e	0x7aadde5f	0x2b0bf775	0x06ba5380
+	0x9eb874be	0x2c4b967a	0x1bcc342f	0xe875001b
+	0x15b5642d	0x5be99c9d	0xcb210ace	0x1b4924ad
+	0x3793ed81	0x8b983114	0x3ec33981	0x75ec71e7
+	0x8b5b7df3	0x834756f4	0x100fad01	0x70037fdf
+	0x0cef9a36	0x3d9e3a2d	0x38b48efd	0xfc4034b6
+	0xa32e29dd	0x388944bc	0xc1c15614	0x3877e9c7
+	0xa5e733fa	0xa621bd53	0x4b651df6	0xce082970
+	0x85f30d6f	0x729a5c87	0x31dd7ba9	0xdb495828
+	0x7b12c698	0x953495c9	0x6b5f99e7	0x2cc42fa8
+	0x697ac512	0x1be679de	0xc116d305	0x94a36606
+	0x9e5e141e	0x874affed	0x58d40b0b	0x5e3cf5e5
+	0x5d05e9a9	0x06840efc	0xd2f98b21	0xa1e83ab2
+	0x4f726202	0xa6394535	0x62a02403	0x9f2167ec
+	0x4f9fc77b	0x98073be4	0x2bc781fa	0xfc8e4c89
+	0xc7179b97	0x692cf793	0x708ff7bb	0x12ecba93
+	0xacd06e21	0x202bef76	0x03852241	0xe84e02a1
+	0xf1f9ac8d	0xcee61aef	0x61a4f235	0xd22991eb
+	0x67a81345	0x375a15c6	0xe8fae8a3	0xb4ff2b37
+	0x339ee4ea	0x14ffadc3	0xf49340dd	0xf285e568
+	0x00fc6970	0x369c52d1	0x4f55368f	0x3f4d75f1
+	0x6a73b603	0x963c1f59	0x171e2bdc	0x72bac76b
+	0x9e2e5c32	0x307f7c3f	0xd3b48637	0x3a917acf
+	0xea52a65f	0xecd209fb	0xf0ad84bf	0xd4bdea70
+	0xa2647b38	0xce040b49	0xc6d5f13d	0x5d942c52
+	0xf8edc042	0x798fdefd	0x4b074246	0x1cb1873a
+	0x6793c186	0x23b9c774	0x77bb0202	0xc519b3aa
+	0xa30c09a2	0xe1f6669a	0xb7eddb8d	0x7aaa91d6
+	0x076a3789	0x0ac47791	0x1e503404	0x44fe8c54
+	0xf3cbbf49	0xd3234eef	0x0d898b3f	0xe854984b
+	0xe3986de9	0x923a5c76	0x2ee9abca	0x1a9fedbe
+	0xdf76dcd1	0xea07936b	0xcdaaf247	0xe62d98fa
+	0xa99c7f7b	0x34fc84d4	0x03a35111	0xad5675c8
+	0xcc64075b	0x408203f9	0x846e1f08	0xe934019e
+	0x423d1223	0x2f04f9e3	0xee1dbf40	0x65edc60f
+	0x097aa22f	0x7058a2b7	0x41c8a0a5	0xa68aa391
+	0x0f345c40	0x667517e6	0x860838ba	0x6dae933b
+	0x764d5919	0x6673fa0f	0xf0a5e97d	0x4262ebbe
+	0x64b413f2	0xd2c4145a	0x0b2c11f3	0xfdfe9f93
+	0x96c77107	0x1399fdda	0xf599f215	0xb504da5d
+	0xf8a95268	0x9ed1ef87	0x9ae33cfb	0x3b21f1ef
+	0xc6d447c2	0xe0694d4e	0x967febab	0xc13f631d
+	0x8393bfba	0x37438788	0x1724194d	0x8e77a045
+	0x20e2483c	0xb961c2fc	0x485cf593	0xb3462621
+	0xcb2959b8	0x10307e19	0xf71fbbfd	0xdda641e1
+	0x0daf5f66	0x56d85178	0x145f6749	0xebc46ed1
+	0x5593c249	0x94561f51	0x534cc654	0xca7c8814
+	0xb59a578c	0x40b2b614	0xeaf3437a	0x198d5b4e
+	0xf245fa53	0xfb75e0b0	0xa363c46d	0xc43b5468
+	0xdf036413	0xc59f5a36	0xd8ff4381	0xa3af3e36
+	0x7af63462	0x414526d7	0x7bdc41c5	0xa416f1e7
+	0x6987d9ad	0x472c5499	0x4f10ee37	0x47bb7ff7
+	0xc7f2e621	0x820008f7	0x33a475db	0x91ff5d72
+	0x0517401c	0x73d067c8	0xe417b69d	0xb86d9903
+	0x1ac9a032	0x74bbf582	0x8b65596e	0x883be34c
+	0x95dcc26f	0xe232c646	0xfae9c19f	0x35cb5273
+	0x6a94d095	0xfff6ca91	0xb9c40eb5	0xd351dcac
+	0xc90d464f	0x9b609642	0x15663b56	0x15f7f88d
+	0x22499f60	0x417fd6c5	0x2dc36fe2	0x712bf66a
+	0x22f1fba8	0x531b8092	0x40d269b6	0x1d227898
+	0xeb6ff35b	0x2490ac31	0xc958ed65	0x3ce6ffb7
+	0x9338a806	0x3beadfe2	0x1c361ac9	0x53d0e3b0
+	0x91d46102	0x4d57045f	0xb5c8afb3	0xfd2c9e7d
+	0x3d578410	0x2adb9406	0x10df7459	0x90abccfb
+	0xe3f217ed	0xef5f4e09	0x74925ce4	0x169b5879
+	0xfeff4ad5	0xb300dd1d	0xc96022ba	0x72da501b
+	0x1e694296	0x9efa33cb	0x0dc3ee6c	0x0ac4e7ea
+	0x73041130	0xf0e6a295	0xc46bdb6a	0x6a927044
+	0xd217ceca	0x0b744007	0xd5a2bafb	0x4220cd92
+	0x70d3352a	0x5ee4f661	0xfa07e5c0	0x155542d9
+	0x4a39fba0	0xcec0552d	0x30c1d8ef	0xbef9d21e
+	0x183879aa	0x5b3f30a8	0x54a06db4	0xef876e4e
+	0x5e823680	0x53e2a353	0xc9aa4112	0x13a56ee5
+	0x848859fd	0x0ba2b801	0xec15260f	0x7bb22672
+	0x1a097332	0xb141339f	0x752a67d9	0xdae373f3
+	0x3c8cfd49	0x2dfaf2a9	0x95820c6c	0x956b39a2
+	0x1ca0d24e	0x1312b978	0x7280e1bd	0xa7a7c2ff
+	0x0b48e987	0xb6083e55	0x4b4b82f4	0x9c6104ad
+	0xcb93beca	0xe1c34035	0x34de740d	0xbb151baa
+	0x71f5942f	0x1eaac228	0x0c68331b	0x3d2a1dd0
+	0xe7a3d41a	0x7253acae	0xfd4de230	0x79988d80
+	0x4468f19b	0xac4440fd	0x6e8a6ef3	0x5736adf8
+	0xded67716	0x1f1d5a4b	0x96c5f451	0x85bae181
+	0x1293ab28	0xc2ba53c2	0x729ff4cf	0x60218df8
+	0xc2870138	0x6127d844	0x89604e9e	0xd2b9ad4e
+	0x4f6ded9f	0xdd263849	0x1633bd92	0x64b03a24
+	0x96dabd4d	0x6e85d235	0x1ab69ad0	0x9aa80454
+	0x6b9041e0	0x106c7e9a	0x8f54812f	0xa274efe4
+	0xe45d6695	0xf3aa7bd3	0x6a5a2a63	0xe36f3525
+	0x6238fa4b	0x7d6cb06f	0x16d3b4a2	0xf3b04822
+	0x638f1a60	0x0e1875fa	0x1c0292b9	0x6b519ea4
+	0x9faba37b	0x209341ec	0x83c9061f	0x3387dfe8
+	0xc7f12ceb	0x2bef45d7	0x8f8acb47	0x35d9741b
+	0x7009f514	0xfd003802	0x6f9489c5	0xe2ea2504
+	0x910e996a	0xcc81d016	0x3280730d	0xdedfef59
+	0x5a7357cc	0x8fe8dd39	0x15543fe5	0x976c4207
+	0xe41cf62b	0x0ba6b4b5	0x5c3b7ced	0xa6c5b72b
+	0x72ad3b4d	0xff143181	0x2b78a157	0x7fe231a5
+	0x6ff0538a	0xe58ed1ac	0x81a311a5	0xefaa54b8
+	0xf04a797e	0xce6e69c7	0xdc810726	0x7bab7be3
+	0xdd5923e8	0x5a2413ed	0x31cef794	0x73dfd806
+	0x1b9223c1	0x0c370882	0x04fa3b68	0x87c50bc1
+	0x1d78c90f	0xf4e2cee6	0xebea941b	0x73e5838f
+	0xca8d39a6	0xe004296b	0x28cf8a0e	0x7c73e7ef
+	0x26a296c2	0x789d4c72	0xd1490265	0xd9a9e843
+	0xf03504c3	0xfae6dffb	0x7a48f00d	0x51e369c8
+	0xcb3eeee6	0x0625e936	0xe93d0d7d	0xfb15ba6b
+	0xec5c76da	0x8fdf44f1	0xa036653a	0x5730c4a3
+	0xe5bfe6dd	0x0b8c091f	0x3b51558c	0x403748f4
+	0xf4007f86	0x952b5db6	0x5524d8ba	0x8046409a
+	0xe3fc61a9	0x66f4ea56	0x5645150b	0xdb2bec15
+	0x50672218	0x7f40e87d	0x2b8359f8	0x438787dc
+	0x7f221597	0xf8b1590c	0x4f468251	0xff586d05
+	0xb9195380	0x0ee09e0b	0x2fa7dbd9	0xd197b327
+	0xa0dbad58	0xb485681f	0x5ef0937c	0x1e07ebb6
+	0xcb49fe3f	0xc2427cd9	0x6c2c5298	0x4a2e171a
+	0xa7f333a8	0xb3609ad6	0x94e374d6	0x0e1eb64d
+	0x22c3367d	0xcdf89975	0x647aceef	0x16727c9c
+	0xf476ae53	0x35a1212e	0x0db768b8	0xfff8b53d
+	0xbd4fe45e	0xab28a5a3	0x59cec0af	0x28bcd1ef
+	0x6f43ad69	0x2658a059	0x27aee0ec	0x4e8bbd15
+	0xa9fdcf04	0xc9aa329f	0x687f010f	0x5c968a07
+	0xb894e607	0x0e1cba22	0x2f00f203	0xe8e133ac
+	0x494a4746	0xe8bdff9a	0xf69791a2	0x64179ce2
+	0xbfd10dc6	0xc026f6d8	0x4871923a	0x8946b277
+	0x609f49a4	0x6466df1b	0xd8c3c131	0x46ef0291
+	0x0fdce8b6	0x2b9aedb7	0x225c4520	0x72b332cf
+	0x4e220d47	0xf2f69c36	0x2c23fad9	0x57a2a918
+	0xe017409c	0x490819af	0xf2121afd	0x951ff7ff
+	0x40363fcf	0x5078b94e	0x9e4be775	0xee97ef16
+	0xdb3a2390	0x17d42af9	0x96f56a51	0x1b4c2934
+	0xc866315c	0x2b746f99	0x9a3b73f6	0xa1e081fc
+	0xa9d07ebd	0xa6359fae	0xdf50d099	0x55304e01
+	0xfe5aaa81	0x1e74267d	0x38b1d2d7	0x8633e9af
+	0x99b013df	0x3aa05831	0x86279736	0xd2b464e0
+	0xdf036a9f	0xe8162915	0x876c0d4f	0x4beb7d0e
+	0xfec9b170	0x46bc9df4	0x46cb88fa	0x0cb5904d
+	0x2e2961cf	0x7ea5dc1a	0x60670df2	0xf935ca32
+	0x67e6777b	0x8bacc97a	0x5cd07248	0x32e483e6
+	0xfdf09b0d	0xca57150b	0x3f432d09	0xdea2d7db
+	0x9f6a2954	0x6f07dff3	0x4133f394	0x60272f97
+	0x1b98c9ec	0x2ab648d9	0xb5df14a8	0x0d2c38f2
+	0x5dfde2c4	0x7cb43ca3	0x8d0c6c01	0xe80ea41e
+	0x5f58b71e	0x4ca9fef2	0xabd201a4	0x50905c08
+	0xca8ba387	0x5592922b	0xfa4e05f5	0xceb64b14
+	0x0845c5bd	0x518d369b	0x727e570c	0x1daaab31
+	0x801e8b9c	0xec6568f3	0xd4c3760f	0x40a78d22
+	0x38af58b5	0xc406a76e	0x8c3a7779	0x18272c42
+	0x45cf7b70	0xa6f3c0f3	0x88021e41	0xda662504
+	0xe97aa709	0xe93bafe0	0x8862ed5f	0x35bc8268
+	0xf5a41551	0x3dd3bb21	0x1af0cf11	0x08fe1ad7
+	0x53ecae41	0x01a4a8ae	0xfed636b7	0xf09323e6
+	0x73b9b253	0x7ebd7ce2	0x7074b4de	0x21c719b2
+	0x50982743	0xd23cfd27	0x136a1f4a	0x23260f6e
+	0xfad89dcd	0x57586681	0xadc4fba5	0xad0f71b8
+	0x91a3f188	0x20d62385	0xfecda9cb	0x33d67776
+	0x2abb0e6c	0x0ad16087	0x486332da	0x2928d342
+	0xf6d1b174	0x5e133a4e	0x72fc0ad4	0x940578b8
+	0x320a42b1	0x9cbda7d4	0xf2a36135	0x00ab8de3
+	0x5bad9000	0x5778e633	0x3952763d	0xe0e58583
+	0xdfb0bf19	0xb11914b6	0xa67da7a1	0x8d9a9f81
+	0x638cbcf7	0x83bf931d	0x8703b0dd	0xcab30fa4
+	0xd6db2ee6	0x5cc2e5ac	0x717e636b	0xfdcbc760
+	0x563b3b25	0x0e4df458	0x9efb8fa7	0x95aaa7a1
+	0xf05b6680	0x5e237e59	0xc884018a	0x177b5a30
+	0x3ea2c9bc	0xd0325ee6	0xb1dae51b	0x812ee29d
+	0x6d58db21	0xb787fa68	0xfd092294	0x09683dd3
+	0xfe0d6405	0xfdd99aad	0x78744a59	0x936738e6
+	0x6ad6cba7	0x370f7f8f	0xd208c214	0x12239384
+	0xbe71f0e7	0xfc0ef264	0xc04e4a49	0x354f9cf3
+	0xf5d7572c	0x07839ad0	0x834a003d	0x23ba26e2
+	0xf4049ecf	0x5ff402b2	0xff9d6769	0x074ebe6d
+	0xdc829da1	0xc3d7697d	0x973efe4f	0xfc2a9165
+	0x126dc518	0x0b824ca4	0xc438fb70	0xb7b0ee00
+	0xbe56afd9	0xa3d8defd	0x971455ae	0xc11ffde7
+	0x346e619a	0xb41111a9	0x6004b62e	0x896c668d
+	0x738e458c	0x351f9fdd	0xe771b2ba	0xad6d7464
+	0x719b57c2	0x6f6a4611	0x8a676f2d	0xb8db1c43
+	0x3f102641	0x51bffdbc	0xb7862565	0x5d8dd231
+	0x7a79bd39	0xfa472894	0x0fd1d2ff	0x64cf589a
+	0x38234d7a	0x5c9acefd	0x8eb0b9f8	0x761e1c95
+	0xf2fe78fa	0xe06220d7	0xaf82a919	0xf4e196e1
+	0xa17c8935	0x06d08d16	0x6bad807b	0xf410805d
+	0x4ff2bce6	0x3297c81f	0x06e35353	0xbe1f5e1c
+	0x65d1cb92	0x0dc69b2f	0xac55d597	0x636ff24c
+	0xe2e4f2ba	0x63d64922	0x4b2e9f71	0xad2279ec
+	0x5f0b5c0e	0xac688638	0x35613358	0xf5531360
+	0x54a304e8	0x27ebfe65	0x977b5a3c	0x3dc5e10c
+	0x73b32ee9	0x3a2c9454	0x30a149c6	0x31e5b55c
+	0x2c10854f	0x745cd38a	0x2853a27b	0x6629e355
+	0x0bb67e39	0x5469184d	0x694a9bb6	0x0a0ca25f
+	0xa878c5de	0xee15fd46	0x23d92ff8	0x02328404
+	0x1c9402b5	0xa46b6ce0	0xefc3e947	0x0e9312ad
+	0x5830ae9e	0xe30e32f2	0x9db8ee81	0xe8aeebbc
+	0x30675c83	0x447278c2	0xab2bad3b	0x08ba3d0c
+	0x1124e681	0x3691242d	0x903c8d2b	0x3281c312
+	0x22af690f	0xd69a150c	0x57622c5b	0x29313c73
+	0x6ab2d7c6	0x39b06dad	0x6e1f9f81	0x03324986
+	0x53a49093	0x7654eba3	0x2527245a	0x9af596fb
+	0x818ffb3a	0xa3817173	0x6a2c4b80	0xfcc42ad5
+	0xfb1bbb69	0x3a3720a2	0x90a89bcf	0xed80308d
+	0x7753cb1c	0x1c2654a5	0xb01ee4af	0x81091e85
+	0x9067b3f1	0x2e2b9b5e	0x9fb0c7d1	0x78fd9f69
+	0x5771c46d	0xacdf498d	0xfd8b8e77	0x4c15fa61
+	0x607120ce	0x18a298d8	0x73716420	0x65e5e06a
+	0x18c53e04	0x35b84427	0xcd82b522	0x9a7d26bb
+	0xd56b4b74	0x49b47fe8	0x63178dc6	0x0bac0f46
+	0xc8b0755a	0x9bbaaf1f	0x18131d2b	0xcc019330
+	0x0ceb89bb	0x8808c2d6	0xfb5bd86c	0x6c945b71
+	0xdc911924	0x4ebb8d35	0x44e46d08	0xabfee615
+	0xf456931f	0x7a244955	0x0bffce7d	0x5533ca5f
+	0xb1b2c636	0x4f29075e	0x64012561	0x7aa5e7c7
+	0x9c8a0666	0x9698782d	0x3481ad8f	0x21a55b19
+	0x735aa45d	0x4245b9c4	0x0d4c3fdc	0xd1b10966
+	0x7035fcde	0xc2257947	0x4a37271a	0x9da464a9
+	0x228adbf8	0xbf309e03	0x096f560a	0xa2b8ca78
+	0x427702cd	0x35a99cf5	0x99811758	0x6953db58
+	0xec07533e	0xe95838b9	0x61c71654	0xc9cce595
+	0x275af106	0xc8697af3	0xb3f27e58	0x411d8d30
+	0xd0d90ecd	0x1503b9dc	0x76bf070e	0x49f89ef0
+	0x7333b083	0x53f9c44b	0x8330c3a2	0x6a1119c3
+	0xca555f2b	0x3d51fc6f	0xac7b3320	0xf8e42cdf
+	0x053753fe	0xc122336f	0x94d289c6	0x088b5a64
+	0xc3aac7f0	0x96a76344	0x2ff05828	0x9b4f2af3
+	0x46de6a46	0x4ed29d98	0xe2ab7634	0x27481ddc
+	0x300ca71f	0xce7ac539	0x88240e09	0xb1a14e78
+	0x2addd4c5	0xb3a7f320	0xe91f549b	0x6881c45b
+	0x0e381c47	0x1018feb4	0x64679650	0xe62281cc
+	0x670ee6d4	0x0d226160	0x947b7f08	0xbc595a74
+	0x2380c0b3	0xc0235785	0x63b41221	0x80b9cc31
+	0x3231b4ae	0x33ed5718	0xf2c5c90f	0xdd3b03ea
+	0x67dfca08	0x453e9d29	0xa2bdecbf	0x5e9a3181
+	0xad17aea2	0xff0a8f13	0xdf946849	0xcfbbecb7
+	0xb0a602d7	0xb1a820c6	0xfe7abbc8	0x7f70790d
+	0xeb5f8863	0x266d3cc1	0xbd552a44	0xe19b1b3d
+	0x856aefbd	0x51c11f1e	0xde661b7f	0x61c075d2
+	0xd0f6a834	0xff1d0d37	0x6793d1c2	0x70c133a5
+	0x20c4d2cf	0x8c80d4d3	0x61ebe382	0x788b74df
+	0x11c56903	0x535889ba	0x0a9c7380	0xf9de2837
+	0x09437fe7	0x1627c6b2	0xb943bdb8	0x69bc29b2
+	0xee9795a4	0x83c992e0	0x95437918	0x8ce166a2
+	0x56b56b66	0xb0680941	0x623d38a9	0x2add07ad
+	0xe583ba09	0x96f6532a	0x3eff4696	0x2a8a6b0b
+	0x905b913b	0xafc01673	0xe871e006	0x2c2339ad
+	0x248438e5	0x96d83e53	0xb3a75d6b	0x2258cf63
+	0x69ff39bf	0x95727173	0xc3ac09d5	0xea8d2c06
+	0x0e7c0a4b	0x144fcade	0x28a9a5a3	0x97c11ae8
+	0x89865e3d	0x1640cd32	0xe3e551f8	0x1f7ba770
+	0x6d23fb31	0x11eceae3	0xc8ccb8ee	0x46dd0bb0
+	0xd01a46ff	0x0504adf5	0xec6e170e	0x2e3d7ac5
+	0x70f893ac	0xaf9963db	0x061e283c	0xf0ad248f
+	0x2fe97e19	0x881fd340	0xc686c9d5	0x88ea8ba5
+	0x92f05cd7	0xd6716148	0x6fc47fc3	0x2c51d9b9
+	0xd50a7faf	0x4eccacd1	0x7c92f802	0xa63ffc83
+	0x7cb0ab1d	0x4492e81b	0x7d906554	0x43306ba1
+	0x73a5d57a	0xe57a05d6	0x6850b964	0xefed595c
+	0x7754978f	0x629e8236	0x62ec4dde	0x247439ee
+	0x8b9982fa	0x4eece5c2	0x48599175	0x0fdc752c
+	0xecd87b12	0x94936c75	0x17a45ea1	0x80a899ac
+	0x22a39ee7	0x745730b6	0x03ea4daf	0x4a7570d7
+	0x307621fa	0x7322e0a7	0x3a8e0316	0x454e46f7
+	0x08773750	0x156dcaad	0x5562bc06	0xa23a1ee3
+	0x20435211	0x1d679ea0	0xb220e205	0x682cc1a6
+	0xd64a71c7	0x3ca7f8e3	0x2e92f253	0xa7cfdd0b
+	0xd62b4053	0xf5c5f641	0xbf72dde1	0xdcb716c1
+	0xe2f7b05d	0xa03145ea	0xc09828d2	0x7dae7916
+	0x6fb97c79	0xb3a85204	0x998a9c7b	0x5f42ba8c
+	0xd9c628b3	0x6b17bacb	0xa889b716	0x450ff97d
+	0xe9166f3c	0x2d20777b	0x82a003ae	0x2c7ae0aa
+	0x6011a9fe	0xfeed34be	0x1328f67e	0xf61003a3
+	0xfaecdf20	0xee18c81e	0x731a0302	0x11a39e60
+	0x355d78dc	0x99088f2c	0xcf253759	0x97347603
+	0x736f71f1	0x37e4b395	0x9cc74540	0xf7e39994
+	0xf01c5f64	0xbec519f1	0xa79c1067	0x76000d5e
+	0x1ac85b6e	0x51e5b7a3	0x62a97ddf	0x6f20096a
+	0x2af51e77	0xea5554f6	0xb4e581da	0xc1ac4ba8
+	0xc8f22bf7	0x9e254d3b	0xd7dd62f6	0x6461ae3e
+	0x423e1f10	0xf143e7b9	0x18c73b04	0xa43de614
+	0x2da8d02f	0x9befa706	0xc01dcd49	0xa278f1e0
+	0xd85f3177	0x6b6679fd	0x1ccef04e	0x53af9252
+	0x34d751db	0xc8d32c86	0x3d725097	0xa64ed581
+	0xd090c42f	0x9e92bf3f	0x6f82b089	0xd42728eb
+	0x3dd651e0	0x1985bc52	0x4b0f4159	0x0f99bd7f
+	0xe2597023	0xca0cae4c	0xce48a894	0x7249dd88
+	0x8e146632	0xb4be1d6c	0x790ae7e5	0x6747b657
+	0x52143947	0xa2e42ed3	0xea359617	0x6ca01a11
+	0x35c5e2dc	0xc97b78fc	0x5db6db2a	0x80fe3414
+	0x27da19d4	0xd7431d04	0xa91e9110	0x7d8ecb23
+	0x2508700a	0xc8c71ed9	0xd28835af	0x018c2887
+	0x3d0a6fab	0x3e8523d6	0xd0688dee	0xe5c3865c
+	0x838d72e4	0x6bb73a1d	0x497a59ca	0xf77c56de
+	0x38ecb72e	0xa55e3565	0x04b12c92	0x1aec9997
+	0x037c340a	0xef0d04c3	0x78f74bd6	0xdec9b9e8
+	0xd95b61ea	0x5528e8f5	0x4ecd325c	0x88ffdc0b
+	0xb337ac61	0x899d90e7	0xb5eeb978	0x8295d9ae
+	0x1ed8978b	0xa8849eda	0x8633b4a3	0xb8c858b5
+	0xbe3c4375	0x28b9e84e	0xb2a26def	0x22f8f66b
+	0x3a4aed99	0x0c4914ea	0xad103249	0xba5a5eff
+	0x8a052461	0x26938899	0x915c6ed7	0xe6268ad9
+	0x246e8c74	0x75f3c196	0xc3e725d6	0x92e02549
+	0x1f78a5cb	0xeada57e5	0x40f14906	0x0215e49c
+	0x57c06bae	0xc1896b87	0x0cd40a63	0x60741d80
+	0x11a69899	0x80fed942	0x0497e115	0x56697b55
+	0xba89c3d4	0x27d6b7c5	0xddff87b0	0xd3b1ff2f
+	0x3160e528	0x9cca1286	0x13b4fdf1	0x38cdd907
+	0xb50c4597	0x4c151714	0x1cab86c7	0x23126a3e
+	0xe26e9749	0x289a0d0e	0xc4004640	0x9d33928d
+	0x33b691a2	0x15ed6e6b	0x6e773980	0xadd59678
+	0x188ba49f	0x08da4c6d	0x6d150d0b	0x0c6c7b98
+	0xc8e1df7e	0xb8b1e692	0x5e89fd35	0xcb253d24
+	0xfc6ee27c	0x8013de3d	0x1d38012b	0xe50a8f7b
+	0x7d410ff1	0xceee4e9f	0x0e8094b6	0xaa1a5f57
+	0xb395a551	0xbd62b2ae	0x5d7b34c8	0xbd2d6195
+	0x33af4109	0x0769ff18	0x9c6cc123	0x78ee6eb6
+	0x412644e7	0x70e0c6f4	0xf45d8fc6	0x0435f5af
+	0xd43622b7	0x27409d5b	0x6dd04e8f	0x9f02ecf5
+	0xca415f7d	0xc9f439c2	0x7198e539	0x20476b75
+	0x3cdd8dd8	0xce17fbb0	0xa5bc115e	0xb0ee52c1
+	0x0b074cfa	0xd26d4f99	0x3b43320b	0x230b680b
+	0x9908f2d2	0xcbcb1952	0xf45a2f53	0x7b4564c6
+	0xcf2fd983	0x414fe4b2	0x55ea7f11	0x63e8117d
+	0xe8954052	0x7c2ea344	0x97a02aaf	0x6ca874c3
+	0x1ae5b4ee	0x41754eae	0x6954abe0	0x115ddcda
+	0x9a27968b	0x32a53e65	0xffe47b2f	0x4fe7e5a7
+	0x6016dedc	0xb3c0893e	0x9626776d	0x5ec773f9
+	0x1104e01c	0x1473cfb3	0x43b2cedf	0x8ca9d119
+	0x7f1bc844	0xd8bb7387	0xba90d2ef	0x2bb0dcf4
+	0x2340f124	0xa5bd514c	0x50afab05	0x718f5ad5
+	0x7c03fad9	0x71d00d2d	0x1c31fdc2	0x4a938809
+	0x40945ded	0x437f2a0d	0x83c10d64	0xd224c6ab
+	0x0cd44481	0xb0040966	0x27fd6e7f	0x6ff45d4c
+	0xab057ad1	0x8fa4e5d4	0xac50270c	0x6e4926ca
+	0xc5721498	0x2529b458	0x40ee2ad5	0xde5e21f2
+	0xea8964ca	0x56766e60	0xdc3b8702	0xa93528d4
+	0x28d7713d	0x42edf022	0x59774dd8	0x200ff942
+	0xe7a4d769	0xd8c4ef5e	0xe177f715	0xe9d53cd6
+	0xc11270bb	0xb25977e5	0xb80867b4	0xfb48468b
+	0xdbf166a8	0x49700d85	0x0f85f98a	0xa7ca7a75
+	0x109817ce	0xca243f19	0x8bed7688	0x9a1c8231
+	0x94f0ce97	0xc36309ca	0x90ecac24	0x67e7e0de
+	0x86b18d62	0x18c7b7a5	0x622f5d3a	0x47e1e067
+	0xdc96b94d	0xe4a03beb	0x59d17692	0x040abc0d
+	0x44a5ae50	0x3d3dab7d	0xc18dfd30	0x2802b9d9
+	0x6818379f	0x56db41d7	0x97cbf039	0xe41d6a32
+	0x64b5fb01	0x6506e0b4	0xd60a3234	0xdf3573d2
+	0xac148579	0xe7f46ac0	0x05e1c763	0x904a5aa9
+	0xc7ca1ee0	0xe0c3b047	0x5e36e1bc	0x447a9141
+	0xe24654df	0x9853a49b	0x6a29cedb	0x022f00dc
+	0x6df2a7a7	0x3636da02	0x72bb9c81	0x4f0e0918
+	0xd649f4a5	0xbb0c81f9	0xc0ba93fd	0xc1b390f1
+	0xda84e720	0x1aea0064	0xf3ee67e1	0xb874ef4a
+	0x82467ce6	0x59abf506	0xafbf145a	0x9a4cf8a1
+	0x17247c89	0xd8669398	0x1796eaf7	0xbc2d24a9
+	0xcb486570	0x17a9db23	0x3e6504f0	0x08684517
+	0x2723ab28	0x7081b814	0x8a265a04	0x697e6d8b
+	0x69b146dc	0x6434c182	0x27ec8101	0x864405c5
+	0xfff86c9e	0x3052d8a6	0x23d283db	0x492970e8
+	0xbc6c64c3	0x46d8f98b	0xe16e7ff3	0x731e4f82
+	0xbd26b1af	0x6b30e6c1	0xff192fce	0x097e0bba
+	0x49df63a5	0x2fdc3f01	0x50aae053	0x60177b8f
+	0x1949eb85	0xa46084ce	0x9658f694	0xcb951fbc
+	0xc53806d9	0x63a17d30	0x3b3f86c2	0x8a37aa6c
+	0xedf8fe5c	0x87aee1d3	0x8c680126	0xfd8b27a6
+	0x231fa106	0x69358c25	0x4502c348	0xc107861c
+	0x46280e70	0xcf6067ac	0xf6a04ff3	0x3e488677
+	0x6f3fb4c1	0xeec1f758	0x560e1c48	0xb604c06b
+	0x69e34b1e	0x8ef41dec	0x854cea22	0x726581d7
+	0x55ea91f3	0x38ae4053	0x5ff7389d	0x6952cbf6
+	0x09aa0fc1	0xcccb1d50	0x5c1a633a	0xde1eba46
+	0x797212d8	0xa943fb3d	0x6063a1a8	0xbe68ef36
+	0x6ba0d5ba	0x0dbe2061	0x47711712	0x62679807
+	0x6f34009e	0xe6fe8f18	0x66a6a64b	0x3f80f472
+	0xe953d5e0	0xbcd8196a	0x086faad0	0x49da7f16
+	0x7f2199a5	0x55af4af2	0x085b4d38	0x22e634bd
+	0x6cff0416	0x343466f4	0xd121a7a6	0x6caa3942
+	0xe4f365a2	0xd832eb0c	0x616728e5	0xcca4c71a
+	0x4010cdc2	0xd0f1d1cb	0x5e695f89	0x27719206
+	0x0ec92854	0x76144a1b	0x49808021	0x12457a1b
+	0xdde7aa5c	0x8f1a077f	0x110a4a5a	0xb3a5ad31
+	0xaacebf8f	0x66ff7f33	0xa2340971	0xfb4c7e82
+	0x8dd536d7	0xafd2021a	0x72aa9c6e	0x22df6952
+	0x83c4b4fb	0xba515555	0x93eee8f0	0x22d0ed5a
+	0xbec05586	0x83828f28	0xe0d7f930	0xac0f0199
+	0xef6d76f9	0xf56ebdf8	0xf67323c9	0x8b805745
+	0xce5902c0	0xfa2ce3da	0x10f836dd	0xe1ac6d97
+	0xa0e415ea	0xbb7c32ad	0xc421f3b0	0x8166e898
+	0x74e7a73c	0xf454b82a	0x631369b1	0xe30ed23f
+	0xdaa1c75b	0xe7c9c6a7	0x5f33c375	0x99c05187
+	0xf2d6e6ae	0xcd2045b8	0x92ff3009	0x15082015
+	0xd1a1580e	0xdce25f9b	0x21984a75	0xa9be5388
+	0x099a5372	0x3ab9bcfa	0xdb9069aa	0x49a99be6
+	0x42a9ee0b	0xfe32d832	0x24e11ad3	0xd16f596b
+	0xb95982cc	0x754ab1c8	0x42ffa128	0x539e823d
+	0x28e0f976	0x262ddfc0	0x2a16e7ad	0x49b5acd9
+	0x931f3def	0xdc419b84	0x8412cc3c	0x81056cd9
+	0x91933e1f	0x57710b15	0xa55d2696	0x87d88724
+	0xd4fedfdc	0xcc3825c6	0x397f382f	0x80f9b6ba
+	0xcdd6d59f	0x24b984d8	0x8f1c5bcf	0x25bcef1d
+	0x00dc603a	0x76fd94c2	0xa267a7dc	0xa6e90a6a
+	0x5c5916d6	0x065a52cf	0xa28d3263	0x9b17b72d
+	0xb8436b48	0x1b1c2391	0x1fda3395	0xa6cecbcb
+	0xbc4ec502	0x1766b590	0x5945fbd6	0x6a124405
+	0xf92d06f2	0xe24694b7	0xf6befd08	0x8266cf5c
+	0x03ed670a	0x5f98be62	0xf27b7e2e	0x598cf22c
+	0x2e855591	0x879815fb	0x153799c6	0x3820faf6
+	0x3d3a2cc6	0xdbb6dece	0x1a3c46b2	0x5031bdda
+	0x47894c03	0xe43661fe	0x7a6ee548	0xa5ca9779
+	0x6aa9e105	0xbc8505a3	0xa03b860a	0x448faeb9
+	0x367de4a9	0xc9779c7d	0x6535ad8c	0x4b7fcacc
+	0xb2db5c10	0x0ab41ec6	0xe528ab90	0x5e6f03da
+	0x98bc76d3	0xf38df42e	0xea59b039	0x1c2eaa28
+	0xca30dac5	0xdb0eb8c6	0x60063860	0x18823f8d
+	0x164e2f28	0x7cbbe080	0x70a12315	0xb08f44d9
+	0x5fbb9453	0x4bc62738	0x9fa15ffc	0xe4033ca1
+	0xc9dfbc13	0x58245d7d	0x588113aa	0x8f5a6ac8
+	0x92588a60	0x26330c74	0xb2aaf0e3	0x24ada1ea
+	0xa9e973ae	0x624b73e7	0x4ef961db	0x95ede155
+	0xf2bb86ff	0x96bc79d9	0x95cd646b	0x1c3af453
+	0xf60fa711	0x10905115	0x0e24b740	0x169bb227
+	0x34cee6f0	0x990980db	0x18d8ace5	0xd4c87504
+	0x29515d32	0x2e5d9c04	0x87dffa60	0x12e815d1
+	0x021db8e9	0x2c5a42fd	0x6e3a1a13	0x88889ab5
+	0x3bc915a6	0x608919c5	0xd310a970	0xea8f3218
+	0x949f55bc	0x9ed7aadd	0x6d990157	0x181f1c2f
+	0xa940df64	0xf3be8c39	0x7ca2e699	0x7b4f07f9
+	0x89e83fee	0xe66b9493	0x54fc3d17	0xa63d2d46
+	0xd5e835d5	0x910e0144	0xecf67025	0x1fa6a93a
+	0xe692dbca	0x466af681	0xc2bc808c	0xbb4ebd60
+	0x74d5c729	0xa283ad25	0x1e66fa23	0x6d372988
+	0x753c9fcb	0x1742efdb	0x5b68cf15	0x372a0e33
+	0xaa3a7ebd	0xa0e944d5	0x95d5cbb4	0x4fb6020b
+	0xced927b0	0xb2afea78	0xd0646b72	0x1622fad4
+	0x4672c6b6	0x736ae4f8	0x8d46a4db	0x0e6a432e
+	0xe0a30a98	0x4c2bcf4f	0xd87acedd	0x19682d7a
+	0xf97c025c	0x55d8feb3	0xbcd4d2ff	0x236c6f9f
+	0x8ba0246d	0x42812f73	0x327636f5	0xc92cd30a
+	0x08a69d9d	0xc735a946	0x82eca01f	0xda0753a0
+	0x7077b1d1	0x17b05834	0xfa24bc02	0xf49f4473
+	0x8f9ac6b4	0xa880c630	0xf7457b4d	0xd5f829e4
+	0x25c49a99	0x1176a997	0xbb2d2009	0x61d35764
+	0xa322c752	0x6ef3ae02	0x5faae6f8	0x9a52acf1
+	0x19176f43	0x43843b07	0x14efc471	0xee474403
+	0x319c4857	0xa19adcf0	0xc0a466e1	0x02db14ad
+	0xb7f211f3	0x72aa6ca6	0x0eb9bffe	0x48a6d284
+	0x9a93a2ee	0xac09fc5f	0x92a62c4f	0xd34f0271
+	0xffb348c7	0xf229b6e2	0xc68ec1ca	0x19577dbc
+	0x069a10bf	0xf64ac347	0xf7c3c848	0x81975294
+	0x6376e550	0x93b53440	0x8bb17daa	0xc4c64c07
+	0xcaeff293	0xd51497b0	0x33da3565	0xa73d5def
+	0x4bf4dcde	0xfb470fcd	0xca7db864	0x7ef17022
+	0x47567363	0xd8fb8d74	0xa68c3c72	0x8202e4f3
+	0x75bf1798	0x16a70fd2	0xcc3b697f	0xab9a1075
+	0x13f56ef3	0x269d0302	0xcb655a43	0xc9a4de88
+	0xfb8363de	0xff40f36d	0xd2555489	0x647a7995
+	0xfd8eda6e	0xa3958c9a	0x20e029b4	0xbed3e225
+	0xa7df5f17	0x63bc3c1a	0x337ecc9d	0x6c329508
+	0x786aa47e	0x1db5b093	0xc0acd73b	0xf9587237
+	0x243e5d40	0xd3623c3a	0x338c4740	0xb672140e
+	0x43640a9b	0xb7ef3f6a	0x44151074	0x749bcc46
+	0xfa1f103b	0x0fefb19e	0x58855538	0x138ad276
+	0x2641fd80	0x297d99d0	0xfaa63ba2	0x00b6f11a
+	0x3793fb6b	0x124763a1	0x8b9419ac	0x56abf9eb
+	0xdbf83419	0x43570571	0x37299cd8	0x8b201e62
+	0xa4058fa5	0xb320e91b	0xbe7d40b7	0x4eca3b2d
+	0x8519c155	0xf4b17021	0x9e4c572a	0xdc1f9e16
+	0x39a589a3	0xa6cfc7a8	0x5b986910	0x64e150e7
+	0x60b6f2c1	0x02bacd3f	0x2f3b5a5c	0xc6f453a8
+	0x15a87a7e	0x76104a14	0xafa2ef63	0x2cd48dbe
+	0x3c7abddc	0xd786ea5a	0x4f65867a	0x355cda38
+	0x2ae03d9e	0x4f11f6be	0xfc0a0034	0xde4ea602
+	0x21ff83ea	0x0f12d913	0xedf4da28	0xc96d8fd1
+	0xd7e82c3c	0xfec63bdc	0x37a456d7	0x3007e18c
+	0x091a47b6	0x82f1c641	0x82219cce	0x3e7e6993
+	0x7b3a2115	0x0b8e1a02	0x40f88213	0xfa2f9c21
+	>;
diff --git a/arch/x86/dts/m12306a9_00000017.dtsi b/arch/x86/dts/m12306a9_00000017.dtsi
new file mode 100644
index 0000000..299d663
--- /dev/null
+++ b/arch/x86/dts/m12306a9_00000017.dtsi
@@ -0,0 +1,750 @@
+/*
+ * Copyright (c) <1995-2013>, Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution. Redistribution and use in binary form, without modification, are
+ * permitted provided that the following conditions are met:
+ *	.Redistributions must reproduce the above copyright notice and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ * Neither the name of Intel Corporation nor the names of its suppliers may be used
+ * to endorse or promote products derived from this software without specific prior
+ * written permission.
+ *	.No reverse engineering, decompilation, or disassembly of this software is
+ * permitted.
+ *	."Binary form" includes any format commonly used for electronic conveyance
+ * which is a reversible, bit-exact translation of binary representation to ASCII or
+ * ISO text, for example, "uuencode."
+ *
+ * DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+ * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *---
+ * This is a device tree fragment. Use #include to add these properties to a
+ * node.
+ */
+
+compatible = "intel,microcode";
+intel,header-version = <1>;
+intel,update-revision = <0x17>;
+intel,date-code = <0x01092013>;
+intel,processor-signature = <0x000306a9>;
+intel,checksum = <0x3546450b>;
+intel,loader-revision = <1>;
+intel,processor-flags = <0x12>;
+
+/* The 48-byte public header is omitted. */
+data = <
+	0x00000000	0x000000a1	0x00020001	0x00000017
+	0x00000000	0x00000000	0x20130107	0x00000a61
+	0x00000001	0x000306a9	0x00000000	0x00000000
+	0x00000000	0x00000000	0x00000000	0x00000000
+	0x00000000	0x00000000	0x00000000	0x00000000
+	0x00000000	0x00000000	0x00000000	0x00000000
+	0x86c5b0d4	0xf6978804	0x7f4f5870	0x6319dc3c
+	0xbb3b7d61	0x33cf9075	0xe8424658	0xf611a357
+	0x5a3401db	0x42caecce	0xb4d8e75e	0xe6dbaf24
+	0x7861b35f	0x6bd717bc	0x23b9b731	0x82ec1ac8
+	0x20337b64	0x5396dbf1	0x59973bff	0x724bc7e9
+	0x5237193b	0x0b8647c1	0x6a0d0e16	0xbf9ddb5b
+	0xace2cc1c	0xad707638	0x056f102f	0xa37e60f8
+	0x76255642	0xfb86e030	0xb8069a40	0x367795f1
+	0x653fb05e	0xab7f14ad	0xb6e8a8e1	0xd2598d20
+	0x2eba3f68	0x78b372f1	0xba8d13f8	0x1f1de861
+	0x97f951d5	0x8097c728	0x27dbf904	0xb97906a8
+	0xffe7a4ac	0x4b947668	0xc1dbd726	0x2adcf777
+	0x63b1bcf0	0x818e2a1b	0x49aa907b	0x2faf5e8d
+	0xae842352	0x82707fae	0x0aa12b41	0xa0bae11c
+	0xb4298c47	0xd2b4099c	0x4ff625f2	0xcd2630d4
+	0x79850981	0x05dbf57d	0xb05b81a5	0x56e73ec7
+	0x95cb3897	0xe262bda5	0xb2c6e288	0xcb7f8e77
+	0x72b8bdd3	0x3f400494	0x63ade65b	0xbc4adc71
+	0x00000011	0x06c0f8ff	0x0eb63d77	0xc54cdabf
+	0x76bc8860	0xdd142643	0xe7bfc220	0x17aa0a91
+	0x4fd676ba	0x4b6b1a15	0x2a1a1c16	0x4fed6de0
+	0x8c3d6bcf	0xbb319bf6	0xa82532f1	0x7c8ce014
+	0xb830a38b	0xec25bc6b	0x61c8a8a9	0x49a21dba
+	0xfcf8bad0	0x7372f29c	0x1f7fbcdd	0xc2ff42f4
+	0x780878f0	0xc967068e	0xe19cc3c9	0x155e6646
+	0x75235c43	0x9aaf3741	0x9dfd116d	0x0f031b6a
+	0x4963e039	0x6918daa8	0x7f0ca4ab	0xd77dad79
+	0x2f8847e8	0xf79c82a4	0x6a6aaad4	0x24f07dbc
+	0x895d3f6a	0xc96b2eb0	0xff50228f	0x573d364a
+	0x5fca9d56	0x3c11c35b	0x3e90fb12	0xc4604067
+	0x5c980234	0x7c42e0c7	0x60cca3de	0x637a4644
+	0xedc43956	0xb0efb4e1	0xe94716fa	0xa6478f51
+	0x33965654	0xdf6b40a3	0x48ac1b18	0xd6723c94
+	0xf040d6d1	0xaf850470	0xe2bcde48	0xb90a4998
+	0x8f620105	0x3d592878	0x2f697bad	0x9f7721d9
+	0xec34444a	0xb0594770	0xd7180f9f	0xa510a168
+	0x460563b0	0x5d4f34f4	0x21dfc16b	0x051de344
+	0xa57bc344	0xff2c7863	0xf0bc063d	0xf5a89004
+	0x79a81dab	0x9e8cb974	0x2309b0a4	0xa47a46de
+	0xcf9c0c44	0xf761c817	0x67ab642c	0x0db4422f
+	0xca3616fc	0x79e66c8a	0xd56a3332	0x5e0f338b
+	0x5814cb3a	0xed1b9a4d	0x47d59f72	0x25b03786
+	0x3edd1d42	0x8cd947cd	0x706e6ebd	0x82c2bada
+	0x1bf6a96b	0x77dd859a	0xda35335f	0x22fab458
+	0xd0661fd8	0x02bb4a42	0xe2a2bcdb	0x0616580e
+	0xd35be23f	0xc206d16c	0x401218be	0x51107c3d
+	0xba84b8be	0xace4d8f2	0x505b9b28	0xc517034b
+	0xac5ba582	0x7419fe54	0x43493cb1	0x2fe0a66e
+	0x206039b5	0x07569011	0x230ce53d	0x168d427f
+	0xbfe0bd10	0x82bf11be	0x5b55475b	0x5490a0e9
+	0x1c3c1e3c	0xacad77de	0x1666512f	0xfc3250d8
+	0x930a6312	0xdd85c066	0x1b95c18f	0xc8bbd3b0
+	0x1bb2a34e	0x642c7653	0x0f536213	0x1f7ab4eb
+	0xaa5ef677	0xe6ac9581	0xd7a2fe73	0xd417dc79
+	0x455a6877	0xae825a40	0xe0c98bec	0xac39ba49
+	0x299d9bd9	0x957d0bb0	0x1645111b	0xe9da4beb
+	0x1b005ce7	0xddb742ce	0x6c5f3ffc	0x24f74d2c
+	0xf4ace044	0xb21bc7ba	0x338002dc	0x240effa1
+	0xd208ae00	0xfe8c2b5c	0x9a457293	0xd9365ac4
+	0x98f24244	0xf6d1aaea	0x7b874350	0x1ba4086b
+	0x1d3bf168	0x2bb6f4fa	0xb27f8477	0x8da836f6
+	0xa8762693	0xc377fa64	0x74cfd979	0x90435c25
+	0x29d80e17	0xc3503c9c	0xaacd2178	0x232c748d
+	0x6fecd3ba	0x00fb4aa0	0xbac3ee19	0x6e5c63e3
+	0x17823c14	0x0e9d33bc	0x0fa9de06	0x998b14b2
+	0xfdd8c80d	0x01b0591b	0xf70bc4ce	0xb278c496
+	0xa7e30708	0x69cf8420	0x14f8b744	0x8bb8a0ff
+	0x168f6db0	0x95da6db2	0xf96d121d	0x67fd06f7
+	0xcd81d278	0x8693d095	0x15e1a24c	0xe5f554f2
+	0x499874e8	0x30fc0785	0x0f4fa1b9	0x65c93dad
+	0xd939bf24	0xdad29721	0xf253b752	0xf6ff59da
+	0xc5dfaffc	0xf0071f34	0xdb0db8b0	0x24475e2d
+	0x2a4d5b8a	0xf7624bea	0x3fdcbc90	0xb5a66e35
+	0xd0f08636	0x24643caa	0xc5d08e83	0xb134c55c
+	0x8e3653c7	0x34496b0c	0x6b2aeebc	0x2fbab601
+	0x105613a2	0x7babd55d	0xa01af846	0x248be690
+	0xed27917c	0x26ee6e13	0xa1dac5fe	0x852ed91a
+	0xfc83fcca	0xdf479c33	0xfd6efe96	0xdc62521b
+	0xa37d2a8c	0x1d2bad9e	0x4287614f	0xc4f7b62c
+	0x2aab0562	0xec6d4226	0x52853fb4	0x264e3507
+	0x1c3af366	0x33269776	0x81b8529d	0x115530dc
+	0xe035f98f	0x433d1b6c	0x1ea6daea	0xecfd2ad2
+	0xa57a0c22	0x1dbe3e12	0x6fafe41b	0x8e579e35
+	0x6c493fbb	0x034dd4f9	0xd17cd6f2	0x05c5cfa8
+	0xd9bffa39	0x0fc16e9c	0x831b88c8	0x7e7dce3e
+	0x3320bc7f	0xd5abafaa	0x217ab526	0xade2597d
+	0xf01b00f2	0xc9e34b72	0x00a4cb0b	0xdc198512
+	0xdc7cc8a1	0x89db07b5	0x6c2153ea	0xb8bdb8aa
+	0xdf8a1ae8	0xa517f6b1	0xd32569d9	0x37e79008
+	0x3c7527c3	0x7d5b2d3b	0xb31cb907	0x35db7f6c
+	0x0ab0cd65	0x75feaded	0x7c8260a9	0x5bc04f56
+	0x2fac9f60	0xd7b3a2c0	0x2b393634	0xc2df7f43
+	0x1ff2fa9f	0xc81af169	0x188b1f4e	0x08bf6f86
+	0x5ab2f188	0x0a71eb64	0x03b57501	0xa684fc23
+	0xa729ffef	0xe3b4a709	0xf9eb97d2	0x01506c95
+	0x0d9285f5	0x8e1ee93c	0x7d15a0d8	0xd9390673
+	0xf116ebd8	0x7e68798b	0x3dc8412e	0x5a9a04b4
+	0xe3805f51	0x00493bb1	0x4ec65ca2	0x2aedd69a
+	0x7f2a5b18	0x9994ac32	0x476f3703	0x7d3da882
+	0x5635f55f	0x7a0887e0	0x0af46feb	0xfc2f3591
+	0x02e29400	0x70fd3234	0xc549379e	0xaf34fa5a
+	0x5bf7c649	0xeb183cff	0xa236d508	0x4525ab64
+	0xc4301026	0xf281df99	0x0b298e46	0x9b7c1a99
+	0xc4b24e77	0xea536992	0x5a39e37c	0x570fb6df
+	0xae5d5c49	0x01142cc2	0xda05d3f1	0x337bf65c
+	0x3c986598	0xbecefd30	0xb5e34c2a	0xe7c3847f
+	0x18cb24b4	0x71278c26	0x4b8d6caa	0xaf7c300e
+	0xfb6ce9b8	0x94c4b785	0x67275f17	0x59498cf5
+	0xca8eeec6	0x3374e7a6	0x649affac	0x9049ba78
+	0xff9d3908	0xaceec446	0x225ece3a	0xac1d4fec
+	0xdc050fed	0x04e3ed8a	0xb303d8e9	0xe9d26aff
+	0x0a98691d	0xf243492d	0xe3b42f00	0x6c21a97b
+	0xa385ae98	0x14ba3f4d	0xc0215cc1	0xe1ba6c0d
+	0x412bbbe4	0x39f95d1c	0x593bd878	0x45d3066a
+	0x9fcee8a1	0x3f29b2fa	0xc9ae58ee	0xed6def92
+	0x6c8f2182	0xdba64e20	0x276c2c21	0x81ea9dfe
+	0x20ae00b2	0x8c2d2724	0x66c09f5c	0x24908e2e
+	0xfecf8194	0x6be61e94	0xcdf5d7db	0x98b829a3
+	0x4241ab07	0x1207ef2f	0x96e7b073	0x766293ea
+	0x58eb0882	0xf12a6426	0x741b074b	0xbd4302cb
+	0x909b6c4f	0x1c4949cc	0xd4d6a3e9	0x442b74b3
+	0xbc8cb3f9	0x0efad89a	0xa2ceff3d	0xecdf86bb
+	0x46a4a72e	0xe9d8abe4	0x94c91479	0xe99a80b9
+	0x1072b708	0xb8318ad3	0x0685426f	0x3e89a0d8
+	0x0b7c438e	0xb4b577d0	0x046599e2	0xd0ef85f2
+	0x3566d2d2	0x43ade22b	0x8753a78a	0x8f6d8e02
+	0xbdf33e56	0x8b2b6696	0x22a5e911	0xd0e0f4eb
+	0x42729c29	0x425921fb	0x82f7634e	0x2c145fd5
+	0xff59deeb	0x018a5372	0x33c4e11a	0xc001c097
+	0xf250cfcf	0x2f682912	0x21f40dc0	0x883196aa
+	0xcd5c58d0	0x7c329754	0x481c450e	0x9411c6c0
+	0x69a9df82	0xacb01a1a	0xc0b569a7	0x0b7fd1a9
+	0x4c339ad3	0xb0d9e211	0x07098664	0x14a5cff9
+	0x53beae37	0x4e173257	0x4e1d2e6c	0xce981dd1
+	0x45d6204f	0x3c193268	0x4f51ac3c	0x5ecffa12
+	0x48068ee9	0xde12270f	0x0a0aa980	0xd6fe8ca2
+	0x97d51da8	0xccf2db36	0xb3ad0598	0xbc56eb56
+	0x0adf5e5e	0x9e320aa1	0x8ebb75ef	0x3973a323
+	0x7e3d87e0	0x2c0d1858	0x83b7fa0c	0x36effdb5
+	0xcd9eba1a	0xab5b5790	0xa48fbf00	0x536e2ae9
+	0x2f2a3f61	0x05706a73	0xd2dfed08	0x7e4626b1
+	0x172c6ced	0xbf2e44ba	0x15aefc2e	0x9cf56c37
+	0x663c6695	0x04cece5f	0x4ce00027	0x465b1cd4
+	0x333dc2c7	0xce41f1f1	0x6dd8503b	0x52b79af7
+	0x564c81de	0x0e5e2daf	0x869753f5	0x16667889
+	0xe1acaf08	0x38ffbb0b	0x83400589	0x5144052f
+	0xa3819950	0xd21501c5	0x1bdadeda	0x0a874e2b
+	0x05480284	0xe8f76f11	0x582cad8a	0x0553f942
+	0xb6451cb9	0x76bdc86f	0x96ffe0c7	0xc630eba2
+	0xa82ec683	0x5902ef45	0xc362248c	0x18c412a9
+	0x1d09c103	0x2355ed98	0x5ec5c718	0x5037e359
+	0x1508f804	0x09cfea9d	0xa16cbdfa	0x5f962b17
+	0x85a35a27	0xa048dd30	0x6fe7ba90	0x0dc20150
+	0xcb56daa0	0x4188fb20	0xb4182598	0xa1bc5dd7
+	0x8c11e0bf	0x2104df35	0x025e74b8	0x79d177df
+	0xad74bb77	0x4b2419aa	0xe374add2	0x411593d5
+	0x796778da	0x9e43a420	0x4a2e0860	0xefb48578
+	0x47cafbdb	0xea15924d	0x70ac1467	0xf52fd888
+	0xd2df4bd6	0xc1fc63bb	0x119ab88e	0x0e147ead
+	0xa85bd8b5	0xc2e61ddb	0xd566417d	0x6bb9f9ec
+	0x69bbcf1e	0x24d46989	0x3caf067f	0x58151211
+	0xc2a6b6e5	0xb233416f	0x3da28155	0xf9cd9385
+	0x7a530045	0x1eab05ce	0xb86ed141	0xa8f13a5b
+	0xf9819f81	0x66d5d5c5	0x148c1a02	0x496d3c56
+	0x370dcd45	0x5f13f0b6	0xdd4eaeed	0x8dbad50d
+	0x0747ce54	0x69d2adcc	0xfb69c18f	0xd44ea186
+	0x74ab7537	0x0c642449	0x88b096cf	0x3a8ad683
+	0x408cd7aa	0x6daa6708	0xb267b312	0xa4225c7a
+	0x7a56dce7	0x6a8d497d	0x8837bcbb	0x6125397c
+	0xeb51d233	0x362bdde9	0x689657f7	0x32d09e1f
+	0x753a3d39	0xf77db5b2	0x8057908a	0xef12815d
+	0x594fffe6	0xcf3402c5	0x1a0d4923	0xca547b2f
+	0xaf9d604d	0x5d2e30f3	0xffe18005	0xe29bb0d9
+	0x36fc10f9	0x3720aac6	0x37bc1ad3	0x47d000ae
+	0xa4b0da0a	0xa178228b	0xdd9374e6	0xa1f3df5f
+	0x9ae2e451	0x21c4aceb	0x8f9fb226	0x5190b712
+	0x70253633	0x9c9cb5f1	0xc9178689	0x551c1a2d
+	0x6db67cc0	0xcf1b1ade	0x48449272	0xd18634f1
+	0x9d9c3de7	0x19025530	0x121d78d4	0xae4a39e1
+	0x62850819	0xf3d4af6a	0xe5ad5b80	0xfa053c7d
+	0x7ed68b9a	0xdbde2894	0x4b5c04de	0x65178203
+	0x9181cdd8	0xb17e27b9	0x0e29b338	0x50156ab4
+	0xf7726438	0x178108d6	0x1d8dc6b7	0xc3e7512f
+	0x0eb8339c	0xe2684a6f	0x7668ed31	0xd0ed6eda
+	0x4342a534	0x03840286	0xad1e6969	0xa9a6c98d
+	0x1bf77774	0xd32fc9d8	0x405620d2	0x8ab19efc
+	0xce4d7506	0x6f4eaae4	0x3e830dbd	0x76818782
+	0xfde4ee8d	0x1953cd0f	0xd47be276	0xf2480bc0
+	0xd1010013	0x2dd56a58	0x083084f4	0xc91b0ad6
+	0xc2524e12	0xa60710f2	0x3d955047	0xce380846
+	0x0f6dec2b	0x604d1492	0x5ca43ee1	0x6b51a626
+	0x350d5483	0x8d99ae30	0xcba06491	0xcc0185eb
+	0x7b64caa6	0x2f1754db	0xca0691f1	0x6219efb6
+	0x43291db0	0x259d3f12	0xeaf6ef9f	0x5f0e065b
+	0xad576541	0x8615a414	0x81124bdf	0x62b855a9
+	0xabdc529f	0x01bfdf75	0x10e4c656	0xf8e86f78
+	0x1fbe10d1	0xa6873c2c	0xdf83dcd8	0x20d35872
+	0xf46f2861	0x22f3d642	0xfdcda29a	0x16adbdb4
+	0x01e5844c	0x011e5454	0xf5432b04	0xd5f6a80d
+	0xb081fab6	0x64fc2fbd	0x4ca76e0f	0x3a8d8b29
+	0x3f03ec12	0x58e2bf6c	0x24f2b8b1	0x108e414f
+	0xe76a02ab	0xcb525af9	0x623ba7a3	0x31412c27
+	0x69c2f5db	0xd5546d8b	0x8200d2c9	0xf1e34a71
+	0x393e24dd	0x2b867933	0x0596e778	0xc5112b49
+	0xf433cdea	0xbc505e7b	0xf64bb064	0x1e892633
+	0xbf17307b	0x9118de2c	0x6b1d61a8	0x1945519c
+	0x32638ca4	0x5e436733	0x3dc20ff6	0x9babf127
+	0x485c1555	0x0d0c4e2d	0xc4d5d718	0x8cfffc16
+	0xf64050db	0xaa4ef416	0x8d398a00	0xe4a16eca
+	0x5d9d9314	0xefa2bf1c	0x05917dd4	0xca5f1660
+	0x59642534	0x02639b9f	0x12b895df	0xb2deaf0e
+	0x20d8f0b9	0x04d8342c	0xa1ba5f57	0xa26cdb06
+	0xca732ca8	0xdce0c561	0xf5e4b205	0xc05f5cfb
+	0xba4a41a6	0xaf219d7b	0xce08df01	0xa02bbdb9
+	0xc1adbc20	0xcb9ae4fd	0xd828cfb5	0x690b17db
+	0xd29ae8bc	0x8fc71289	0xd6fc9cf6	0x61c7a6fc
+	0x8e8012d5	0xd3320498	0x36e80084	0x0036d3ab
+	0x53141aae	0x987d0cba	0x57581df5	0xace4704c
+	0x3ce49642	0x991556c1	0x6cb0b984	0xac15e528
+	0xe7d208ca	0x2486d1c5	0x93b6623e	0x340b7622
+	0xe7e1cf7b	0x3cdeed88	0xa23c849a	0xcc6e8b3b
+	0x292add5a	0x17763ee1	0x9f87203e	0x72cf4551
+	0x2053e66f	0x06c3a411	0xb61c2e0c	0xa4a7f3ae
+	0x0ff87dbb	0x03999ed8	0x48aacedc	0x2e126ef3
+	0x799441bb	0xaee15b4d	0xea08bf54	0x47248787
+	0xb60afc11	0x8c3d6a20	0x7c04f801	0xb902760e
+	0x319040eb	0x370bbd5d	0x9a1dd5e6	0x63f7da1d
+	0xb3784eac	0x3b304dea	0x987ada9f	0x2b6b1cda
+	0xf9241003	0x0d3d16f2	0x1185dcbf	0x519b7a5f
+	0xeb612361	0x28b57da5	0xdeb8419a	0x0ba13122
+	0x062e28fa	0x5ffb9b36	0xb1258247	0x8337401f
+	0xed1f6423	0x730cafe6	0xf728c690	0xe40557eb
+	0xc4951a15	0x04a988a9	0xbf5fe18c	0x2766e40a
+	0xe4d74d13	0x8638d052	0x8eefeaf2	0x9ad07978
+	0x32042a87	0x4385f38d	0xc9b48f02	0x02ab0ae7
+	0x9eaeb632	0xf386c14d	0x8b1c2ab2	0xad432a24
+	0xfc5bd462	0x2d7ac5fe	0x45dff5c6	0xa235e1a6
+	0x825b770c	0x5568471b	0xa7ac3a3a	0xfcc6e40c
+	0x0c1be59c	0x77685a3c	0x5b1bafbd	0x40b8a139
+	0x3dd1bf01	0xb6651001	0xf2915a6a	0x16fe1cf2
+	0xe78467d1	0x4bec9fb1	0x88615320	0xa3920831
+	0xed4afac7	0x206cffba	0x96c42567	0xcc2b5215
+	0x7ca0193f	0x0e1a60e5	0xf3892c10	0x2ceee7b2
+	0x110d3311	0x9a322e7e	0x3cb7e5fc	0x3fb971c1
+	0x59971332	0x08386001	0xe4a2444d	0x17d9c47f
+	0x9f53c4a5	0xdb54e5c2	0xfaac9f08	0x975c07c6
+	0x8a6e6bcd	0x4392053a	0x6473bef8	0x4b3b91a3
+	0xfb7e8ebc	0x46c6ffed	0x04939839	0x71b93766
+	0x47e4f74a	0x786545c8	0x77f55b59	0xdf8e992d
+	0x60a0d2a5	0x6cc8a5cb	0x113ee95c	0xa378558d
+	0x5d3b8bd9	0x3c95b2a8	0x6efa3682	0x9535dd34
+	0x3e29974d	0xa477d069	0x2dbf58d2	0x165edae3
+	0xea25d53d	0x44e3ef71	0xba6341cf	0xc61b964c
+	0x4612838b	0x62151b9e	0xc1de2511	0xa364130c
+	0xa9710643	0x1a436c70	0x97030b09	0x5cef28e0
+	0xd5197e49	0x02b9ffa8	0x1b52dc7b	0x04f9428b
+	0x01ebed2a	0x1eaecbee	0xc53c4d54	0x3e34c125
+	0x05b4f37a	0x6e3d042b	0xf1c1f40d	0x39cfe9e1
+	0xd2938e89	0xa14b9846	0xb1333676	0x31068254
+	0x4b627e4b	0xb5185882	0x101b52bc	0x73e05abf
+	0x68a4e24c	0x67e301f4	0x6bf8b538	0xc502e1e1
+	0xc3889b5b	0xdfbc6d96	0x4239d0e1	0xbf3667ab
+	0xb0c4cb00	0x3efdcffd	0x7cd9661d	0x4f5eca03
+	0x0ef218dd	0x464f0826	0x048fc539	0x6a1c63fe
+	0x76cc341a	0x1ae2945c	0x7a339006	0x858fdc20
+	0x2a4a7270	0xd4cbe12c	0x7b27e5d8	0x998cf520
+	0x4795ccf7	0x52e15388	0x86aa7b96	0xff1845fa
+	0xd49d1061	0x035b6a80	0x1df18220	0x28fc4fd1
+	0xa8e8f333	0x3a9240a6	0x41a4caca	0xee736b6f
+	0xdfa7ce4b	0xd4bf5c0c	0x4e62f6d3	0xe98ae9b4
+	0x7f544550	0x2b0706df	0x8fb2e752	0x546af9d1
+	0x8517758f	0x53f522fc	0x03bd1819	0x6fd264e2
+	0x16839ef8	0x44a1200d	0xcd5a586b	0x1ead251c
+	0xf58dd3be	0x80217ce7	0x0367ff42	0x2d8f2ce8
+	0xe8a0a689	0xba33e366	0x5dc7980d	0x005c0eaf
+	0xc0c44118	0x5553076a	0xdaf39389	0x703e09eb
+	0xc54c8112	0x4a26135c	0x36a46f2b	0xdc93ee12
+	0x7060db72	0x7778befc	0xe028fc55	0x52e86278
+	0xd0b00188	0x6ed5565a	0xb5e2785c	0x3608bffa
+	0x55c3f5a3	0xe1e41afa	0x08a227fe	0x94c793ce
+	0x650934f7	0xddc36524	0x6dac40de	0x9eec3ceb
+	0x8fe3d1cc	0x3cebab86	0x61e4d63a	0x5382ea11
+	0xa90c9495	0x0277ccb3	0x412cecc1	0x5853c945
+	0x97df9a48	0x364d9b10	0x7e8c9bf1	0x6b4974ef
+	0xd3dbaeeb	0x6626dd26	0x2b746d2c	0xfb762155
+	0xf942f687	0x1317d1b5	0x0c989def	0x5f4c0ed6
+	0x31aebbd3	0x51cd8d5b	0x3d729511	0xc07c8f23
+	0xa7f3e6f7	0x7683dba9	0x5f051d5c	0x750437f5
+	0x1b9ffe98	0xa4de609b	0x4c498e9a	0x18dfc535
+	0x376c6c34	0x19a57039	0xa70e93eb	0x7e966bc7
+	0xb6e9d77a	0x3ab98e5f	0x1607125e	0xe8845aa3
+	0xa20a2d80	0xb17ac63b	0xa07a9790	0x71e5a14f
+	0xb6b5fc78	0x4c610f86	0xb57b21b6	0x1bcfb3ac
+	0xbf812998	0xd429986b	0x02b837e9	0x0823aca8
+	0xd8a85194	0x708bad39	0xff94ef19	0xc3599461
+	0xaee622f6	0xa8b5a808	0xf801b298	0x0aeb35b7
+	0x4db4bf27	0xfa31c205	0xa047dc66	0x7e0ae406
+	0x2ceea6cb	0xef0ef96f	0x4cc4fdba	0x6161256f
+	0x94505fd1	0xbced5596	0xbf9e36a5	0x271e68bd
+	0x7a3308b6	0xef1af50d	0xb55ede06	0x6783e602
+	0x1152acf0	0xdc644ccd	0x1b692da3	0x59f6886b
+	0xd7236158	0xe39d75a6	0xe7026697	0x25496283
+	0xb6b0a61c	0x09d0931c	0xe8d459a1	0x1a124097
+	0x88e50621	0xf2ed18ff	0x37681783	0x4afa1ffc
+	0x8a96ec4a	0x4474a860	0x274591b1	0x59df3968
+	0x34f56fb9	0xce821f96	0x7ec825b2	0x6ed4a9bf
+	0x687253cf	0xa511c1d3	0xaf2bd6f0	0xd1ce1a5c
+	0x241dd505	0x39037238	0x0c761934	0x53181db5
+	0x11ad47ec	0x915a527b	0x748bc970	0xeb8f2669
+	0xb8bfd5af	0xd8d19145	0x0361ff58	0x6dc6e2f2
+	0x1fd06556	0x120db4c5	0xbd704c8b	0x70a1a57c
+	0x27543851	0x095403a6	0x28171887	0x640e7c92
+	0xb48fd7d1	0x62ad2774	0x224767cd	0x347b8843
+	0x821ca7f3	0xf94749c6	0x2bc7f40f	0x700cc1d8
+	0x50d50832	0xc2f9465c	0xa6e1cbaa	0xe0f5e934
+	0x7f33617f	0x8876cb07	0x408c24fe	0xc0cfcdf7
+	0x39152b72	0xa0ba80ab	0x301a73eb	0x6e704f6c
+	0x3b73c24b	0xd433f861	0x43192007	0xa56d2ca4
+	0x2d28bd5d	0x14f4c9cd	0xb7fe189c	0x031e1818
+	0xf8f4133e	0xdc8e7727	0x4f8f5a06	0xe7b114cd
+	0x5cb9ff12	0xdb4c5a53	0xed956df5	0xf3634f5f
+	0x6cce1cc2	0x5393f9ac	0x1184c2f7	0x0b6fd240
+	0x64771374	0xaafed1a1	0xbdc55bcf	0x976414ef
+	0x6a333e56	0x0c5cefb2	0xff2574e0	0x11b059ef
+	0xff8b7f2a	0x9651e97b	0x594fe89b	0x7be60f6a
+	0x7b7695ac	0x612036f7	0x5be0d4fa	0x25855737
+	0x12e32ee2	0x8e86130f	0x46d75d41	0x3769d438
+	0xd14752d4	0x1612ad6d	0x8f86f2a0	0x63e01251
+	0x9a44ac4a	0x49fdb148	0xe1757062	0x42798804
+	0xf21f46c1	0xed0a3794	0x5528add4	0xeddc0c90
+	0x7f188ce8	0x59568b7a	0x8e25d50f	0x9277c492
+	0x955c6e6a	0x79f94a59	0x3a65fb08	0xceb23267
+	0x7d8dce01	0xd15c492d	0xa35f005c	0x0e7cba9a
+	0x950485d9	0x2d92e448	0x4aced016	0x0d10136d
+	0x3d2ec365	0xd982e881	0xe81940d2	0xb1a84849
+	0xdb30d967	0x9f51d3d4	0x4fbe18a9	0xef21cd28
+	0x5d3cba6c	0xaa89b02b	0xbe1e9526	0xa20a918e
+	0x0c26bd72	0x8372eff8	0xcf7ab414	0x1d3ab83f
+	0xfd2c8f79	0x4929f77e	0x2416e8df	0x65dcaaca
+	0x58fbf7b3	0x1c4a3089	0x9bfb6e26	0xc7338ac9
+	0x88e5ad26	0xc62bb3d4	0xad6d36f5	0x6445167d
+	0xe9de8daf	0xc391c6bc	0xa78b4558	0x0216bcdd
+	0xbd4365b9	0xb0a874b2	0xe95e9453	0x77296b9a
+	0x49803c1e	0xc01fd0ed	0x165a9d5d	0xf7da6442
+	0x4c00818d	0xaad5bfca	0xdb252937	0x0e4e0f74
+	0x0c2738e8	0xd075b8ba	0xe3b2df11	0x8aee60a4
+	0x36052cd8	0xb4aa190b	0x413e7155	0x3e7e646d
+	0x807e6eea	0x97993e6f	0xa5129ff5	0x98e01bca
+	0xa8bd70c9	0x8800721e	0xb3407ffa	0x266b2f99
+	0xd9da73ee	0xa06f634a	0xcaae53b1	0xd98e53c6
+	0x49368291	0xc89485fe	0x938a8a29	0xb57f77cc
+	0x58c867de	0xcdac8a84	0xf4d57b6f	0xc6daf080
+	0xe3d9c67f	0x0264b194	0xc3b2ca50	0x6d214667
+	0x88503872	0x549ed8cf	0xe827689f	0xcbe94e2e
+	0x4a02516d	0x24ddcfa1	0x3cbc736e	0x34c88707
+	0x9f4c9376	0x4ced4d41	0xfdbabfb5	0xafd291d9
+	0x2fa602a3	0x53e19d9c	0x44422427	0xf85e2c53
+	0x40e91ef7	0x02646045	0x3d1fa703	0x1613b99f
+	0xa108de10	0xf9cb3d04	0x7b9f9523	0x007d74b1
+	0x961771dc	0x2e49fe1b	0x5fefe27d	0x54737b43
+	0xa11d7c40	0x7f0cc2d9	0x67c6533e	0xd1ab10fa
+	0xb1950645	0x536087d2	0xd6937b40	0xc35960c1
+	0x2df0c356	0xecb5ab53	0x61e08998	0x1671bdd0
+	0xd72935b5	0xdf1a9d7c	0x70b1aa4e	0xa9272818
+	0x1f7b8d55	0xc7292a0f	0xda7af847	0x190076ad
+	0x58370ba6	0x3020fb4e	0xff8a4b30	0x13818958
+	0x6ba1ca38	0x6a90d39b	0x5e180929	0x206e8a22
+	0x0568f241	0x5f83ad21	0xef05e5c6	0x21d0521c
+	0xe7886eff	0x68eebbce	0x550c1659	0xa0843444
+	0x19468c2b	0x539cb9b8	0xa4b18b62	0xdab0680e
+	0x1b254dbc	0x47068aaf	0xa8193743	0x44b60b88
+	0x90c07337	0x2e55666a	0x632f4b23	0x68af10db
+	0x8e29f54b	0x5f436bcd	0x8bf81d55	0xb640ccc5
+	0x2e4ab6a9	0x198697a5	0x8a1c8481	0x572fb679
+	0x7597c416	0x608fd45e	0x57c8c7f4	0xe151d349
+	0xed9e17bb	0xa66f2816	0x8175fe68	0xd57d91ad
+	0x79df0711	0x7a349868	0x13403cd4	0x7d974c60
+	0x8860ce70	0x2e6d62ea	0x8916e2f2	0x0e336838
+	0xf54d382d	0xc4e172c8	0x94bfcfbf	0x5fa53172
+	0x2933cecd	0x4d5b8439	0x0ca0e6e4	0x8ef87b00
+	0x2fdd121c	0x24beae76	0xa85b47f4	0x4e38af2e
+	0x12b8734a	0xf698abf4	0xde2c2d93	0xeb100795
+	0x8ab19df8	0x93a6f4d1	0x43c4b2cb	0xbaff7c4a
+	0xf52b1471	0x72804f4f	0x0c0ca257	0x1dc24c77
+	0xbad7203b	0x3a998fa0	0x9cb20388	0x7ef1fb3b
+	0xbae66020	0x9a22144f	0x39ac47db	0x3f145996
+	0x05a32b6c	0xd201a2ec	0xd868727f	0x08b2df4f
+	0x4583bbfa	0x9a422baa	0xa6a2e8f5	0x236310ec
+	0x5aafc3cf	0x344156a6	0x6f964ceb	0xed0495ae
+	0xb5638c98	0x2c8e84ba	0x63d8c7a5	0xec956b66
+	0x69c54f32	0x767874ec	0xe8fb6ce1	0x68b1c780
+	0xe4b861e4	0x2787cc38	0x4b2202e7	0x23b476be
+	0xecdf296f	0x094aa000	0xe95ef073	0x4182ebb5
+	0x30daa31a	0xef68cb68	0x2fbcf6bc	0x21c52620
+	0x19abf83e	0x4de7528c	0x05fe4c05	0x32c2a1e9
+	0x8c23abdb	0xabba9a90	0xa6a215c1	0x891f915c
+	0x667cd65a	0xaa5a9b2c	0x689fd1e9	0x42b52c95
+	0xd9872e76	0x05dd5278	0xc19798f7	0x8d031d86
+	0x25690670	0x165f4b19	0x76b51d6f	0x61cd8232
+	0x7b530271	0xa8e9326c	0xd952e94d	0x56a7021b
+	0x128be860	0x4da40144	0xeb4ac3d5	0x82b7ff5a
+	0xea2abda7	0x690a9ebc	0x33562378	0x6bc91b2f
+	0x46134185	0x8fb77fb2	0x029518a2	0xe1fa1f4c
+	0xf78783b9	0x5d8ebe63	0x103e8050	0x924085bf
+	0x80593f2e	0x5be4bcb6	0xcb935edd	0x882d0a5f
+	0x7deb8205	0xcdc0fe2e	0x9c333db4	0x1d0c888d
+	0xf8dc3575	0x2f901125	0x6bf48cdb	0x98ab6fb4
+	0x491d7df2	0xa064922e	0xbbb86c70	0x88aad77d
+	0xfcff0669	0xb0c47c1c	0x0fcc6fe1	0x50df8a83
+	0x014460e4	0xb014e6ab	0xbeff4bc5	0x8d939fae
+	0xd750ae17	0x42dd29c9	0xdb1cbf70	0x82265be9
+	0xd11afd6a	0x21834e1c	0xd11e3c3a	0xbe568139
+	0x6cf92d50	0x9304ebf1	0xf177046b	0xa5b127a5
+	0xfb57e4a7	0xf94291df	0x0f089d58	0x07395b5f
+	0xde4ba5b9	0xf7371fc5	0xae44f190	0xd529271d
+	0xbcaea246	0xfa777c0b	0xad3bab9f	0x0d6251ec
+	0x6f4fa894	0xc39273e2	0x7710fcc3	0x81f08a5d
+	0x395b54ee	0x87295638	0x57398bb0	0xfd46c7c9
+	0x3f1dafc6	0x548479b7	0x37c42fba	0xa2130147
+	0x99dc0bb0	0x3596c5cf	0xbcca6bec	0x418735ed
+	0xfcd4273d	0xee141135	0x8457cf47	0x95fe7220
+	0x041aaf8a	0x6e947153	0xc963afa7	0x09390a74
+	0xc40dffd3	0x4208039c	0x319b1f84	0x42b6b3b7
+	0xade789da	0x83338c91	0xf2d74712	0xe80011dd
+	0xdd61645e	0x286fc63a	0x26e2fb23	0xfef2b4ea
+	0x3290efb8	0x595a0c17	0x6cd9bea9	0x7be1338e
+	0xe0ff2c09	0x1b93aea5	0xbbd97e91	0x5e1ae1e7
+	0x7c6c078b	0x0b9b3a03	0x43d38011	0x824cd94b
+	0x9725170d	0x87ce6f33	0x60525d85	0xc0a5e853
+	0x242e613b	0xebf72857	0xcb500fc6	0x0de5c3f0
+	0x382b625d	0x08840e50	0xcef30663	0x1bc848b6
+	0xefa78141	0x81b860d6	0x4eb125fe	0x7e125296
+	0x276a5558	0x45caa775	0x7c6ec23c	0x5dcddd08
+	0xc41aa32d	0x6a2851b1	0xb69ae1c1	0x8f603c43
+	0x763497f2	0x73344cbd	0xcffd175c	0xfccf5a91
+	0xb2318bf7	0x66ac628f	0xa98fa975	0xb68e5426
+	0x27555715	0x5157a93f	0x666fd404	0xb37fcc40
+	0x563b0512	0xb70f8446	0xe10d257f	0x73793ef2
+	0x31a84915	0xe0de9489	0x08dfa368	0x9169d4fd
+	0xc14f5c9a	0x92e6db4f	0xa30b6cec	0xca04670e
+	0x8a664367	0xe8984e70	0x1c96a39c	0x655f9abd
+	0x6999a190	0x76267621	0x0f49f963	0x8ddad3a1
+	0x51fdab6a	0xaf0d6863	0x23b71bdb	0x32818c8a
+	0x6398044d	0x26c60bec	0xb0b631fa	0x938f69c7
+	0x52f11913	0x1e6fbe7a	0x92dcd409	0x419bfeae
+	0xb147bb96	0xbac5bf9d	0x08de155a	0xde8ca968
+	0x20aef902	0x62df25a8	0x64a4042f	0xef19da4e
+	0xc75fd112	0xc9863e47	0xaccfdbcb	0xd29b6090
+	0x6dc67b4a	0xa84b3cd6	0x45a0e708	0xd28673bd
+	0x00bebebe	0xd5e518d7	0xc63d647c	0xa28f5f6d
+	0x3372edc8	0xa1c44ed1	0x88e61d44	0x5e095835
+	0x2d8713ce	0x6791a885	0xae89c04a	0xf1dc5105
+	0x6423f3b7	0xf4e2f384	0x2d2761a7	0x38ea905d
+	0xa263d776	0xd1936fa6	0x2fc54081	0x429a25c2
+	0x13f6c5df	0xffffa6c1	0xfaf82002	0xe4bbb103
+	0x2fc0c622	0x669ee281	0xec785fda	0x91156b25
+	0xa9f4444e	0x354fdfc2	0x7c5f5069	0x72ae591b
+	0x73bfd64e	0x6b96d744	0xf261daaa	0x2de15dae
+	0xedaba9c2	0xf287b3fd	0x8b2097b6	0x589934c0
+	0x7edc2a73	0x469b16eb	0x247b9a22	0x8b7e6c7b
+	0x3e71ffe2	0x5275f242	0x032a211f	0x977bff60
+	0x4306ad03	0x6a212383	0xceb36448	0xa2a79209
+	0xe3842f42	0xcee0cbe7	0x37cdb626	0x29a0a515
+	0x2857ead6	0x981d5d9b	0xf0ff9b06	0x95de8cad
+	0x4dcb565b	0x065d585d	0xe7eb754b	0x278fa774
+	0xe4d8fb7a	0xe152f018	0xfb7bb25e	0x50323b64
+	0xba618e43	0xf8cb1c61	0x1b6dce25	0xb4fc7867
+	0x2a7fb213	0xea9e646e	0x3f9b735b	0x5640315d
+	0x0793ba5b	0x71ff31fb	0x4b41f1d6	0xb1538146
+	0x336f4272	0xf176d509	0xb7fc03c5	0xd6a1c927
+	0x56a68c10	0x8b4740cd	0x14c54f8a	0xf07ad8a9
+	0xa8403db8	0x37c23f2b	0xdca69aba	0x4b39ef9d
+	0x2af13bdb	0x6baace1f	0x8c7ca0d2	0xba86bd02
+	0x2a74681c	0x5542ae58	0xc36709e2	0x82b34568
+	0x26ea06be	0xd4bf458c	0xde209de7	0xa311b4e5
+	0xdc00e139	0x7d305958	0xc5d76ed7	0x0943a285
+	0x48ce4e29	0xe371bd9a	0xfe6a6501	0x4167d215
+	0x402e47ba	0x588458be	0xbf4bcf37	0xf7fa27a8
+	0xb725f91a	0xc17f5c07	0xce771dbe	0x66f9d592
+	0xe8521ed4	0x42f75171	0x343b3e74	0x2d5448b5
+	0x2d1fca8c	0xd7a32431	0xc29a88d2	0xffb07fd7
+	0xcca0333f	0x43204f2f	0x866c1867	0xcb215814
+	0xfcb67d4f	0x423680be	0xdf22f6d6	0x03373eda
+	0x3bd202e3	0xd8972fe3	0xb7733d70	0x7a472c76
+	0x6cc8a627	0x3b27e643	0xa3475f3f	0x87ffb286
+	0xf823d69f	0x6d57c38e	0xa0fd464e	0x53e2e341
+	0xaaab23ef	0x439429ef	0x55ba2a2b	0x4da5ea4c
+	0xc1fe05fc	0x874b7a34	0x9a875956	0x713ccc90
+	0x49afcff2	0x5905dc0b	0x1f5dddb7	0x8ef5c1d9
+	0xf60eca50	0x25172569	0x3525639a	0x25804bbe
+	0x5729cd49	0x17f84e66	0xc540d86d	0x51524bc9
+	0x9a6e9901	0xf5bcc70e	0xf7a73ffd	0x54509c8f
+	0xec58b8a4	0x9993703b	0x6ef45fc4	0x5ce3a507
+	0x1d73c611	0x8780e8ff	0xc7d2e02b	0x0bc825f2
+	0x02f75fca	0xe80c0758	0x24646fe9	0xd378ff5a
+	0x592c5619	0x6c80372e	0x1f7351d1	0x4db5182d
+	0x3985fdfb	0x16ca9158	0x58ee1ae4	0xaf2b9fa0
+	0xe97f60ce	0xbb911e68	0x01748fa0	0xaef578d3
+	0xc3736418	0x8ab0deb5	0x0de16af1	0xb8369f7b
+	0x68e43c12	0x914ca0f6	0xe950ef28	0x834eff90
+	0x51adb952	0xc42ee4ce	0xf70ab4a5	0xbf9fc916
+	0xed9444b1	0x845a6a1e	0xf92e7b64	0xb9ca8a1b
+	0xa9cdfcd0	0xb5956bc8	0xb8520e59	0xdde7aa57
+	0xb41d390f	0x364aef3c	0xf39d4482	0x8b4e651e
+	0x0b82f5fb	0x7960e81c	0x12ed7b84	0xe9f123ca
+	0x88a64db2	0xa0c714cb	0x57b01471	0x80ff31a6
+	0x7571d8cd	0x857035d9	0x0508587c	0x594a4a42
+	0x011503e5	0x27c75e55	0x03264f62	0x9316ed1d
+	0x36e5cd1e	0xfa9b23b4	0x5bc8c606	0x0902bd38
+	0xd6745c69	0x6fa73118	0xa50f7b94	0xc529e962
+	0x28738486	0x7b85a599	0x2c495a35	0x85f2cbef
+	0xa09dfe51	0x1c763ab2	0x4effdb5c	0x506586f0
+	0xec182a58	0x45293146	0xaf8d78b8	0xa89bd228
+	0xec24826a	0x752cc421	0xbf36aa46	0x6760e225
+	0xe15d0987	0x6fa9bdf3	0x6837c755	0x9426d654
+	0x14b48f5b	0x5d70567d	0x63a14f92	0x809d5361
+	0x3b6e2729	0x84ce5415	0x7eaca6e0	0x9b467302
+	0x8f39d484	0x8e78398c	0x33108b33	0xdc07005c
+	0xbdc2500f	0x35f1f452	0x9d254e3d	0xfa61eb21
+	0x2ab6c7aa	0x83561fdc	0x8735d598	0x416e8591
+	0xfe10e93a	0x18da409d	0xab6d0bfd	0x675baaf1
+	0x287fdd24	0x6b50b63c	0x8c08abca	0x871a59c9
+	0x41bb2ae4	0xfba9abdf	0xb46491c7	0x4e433d5a
+	0x01e4fbda	0x0bc40399	0x3bdb61c2	0x3cf051ba
+	0x910daa46	0x8d4065d6	0x270667eb	0xf6d42459
+	0x01993a1b	0x00a95dda	0x6ed5a693	0xed4fbf7b
+	0x24dbb70f	0x67fd62ee	0xcef5f0a4	0x9e65b798
+	0x9a9913fd	0x3d0e7190	0x4265b4e4	0x80bfc46f
+	0x6b354d2c	0x2b90a987	0xc989cb75	0x773e6b64
+	0x55325e9f	0x18816a56	0x07413406	0x5177ae31
+	0x24a19ef7	0xdac405a4	0xdca2d3b4	0xab7c7b70
+	0x42b5de0e	0xfcf918a5	0xa54d934b	0xcaa9eab6
+	0x50e63e2a	0x4b168926	0xb2442913	0x594c0f94
+	0xf387f31f	0x4d716749	0xc8433297	0x34c1a5de
+	0xe929008e	0x5644251b	0x736476d0	0x0d00aee7
+	0xf20b2f64	0x5e158173	0x9af3e568	0x5f19fa7e
+	0xb23b2861	0x8659ee6e	0x94058a64	0x66ec4fb1
+	0x37cd6a4a	0xbd2944fe	0x0ea44ec6	0xe7d64c24
+	0x75a170e3	0xb4a9479c	0x2215716a	0x64a8a574
+	0x257e86ab	0x86bae993	0x3030352b	0x15cb88bc
+	0x576363a0	0x61138c36	0x7cc4fe7f	0x648977a8
+	0x0ef71fec	0x1c60df47	0xc75f70ea	0x88509798
+	0x172b407a	0xf888e400	0xef33cd15	0x5976757d
+	0xf8cfef13	0xbf024380	0xbb9c1b02	0xe4c38ec9
+	0xf30fce01	0x8efa5213	0xf4b48aad	0xc94c3a37
+	0xeb1bcece	0x09a18b56	0x4e83c0d3	0x6fcf9f77
+	0xf52f4d76	0xf3368a12	0x33b2797f	0x627b6e41
+	0xefd05154	0xa83ae2a0	0xea211129	0xd25723d5
+	0x7bbb0e3b	0x7131f088	0x5dd5193f	0xef5aa905
+	0x39f77be7	0xa21b48c1	0x1ded01c1	0x5cf98c5f
+	0x6e23d207	0xd7e7dadf	0x5932ed1a	0x2a729061
+	0x29a89f4a	0xac0e8447	0x01ff4205	0x8b1456c6
+	0x3fba0156	0x658c03f7	0x5c69f968	0xf6570582
+	0x21bb0145	0x8683bf5b	0xa4b6eba5	0x4ccfe5cb
+	0xd202898c	0xbd2411cc	0xc2fc702a	0x5c39b695
+	0x87584ccf	0xeae3c735	0xc472b6f9	0x4249f637
+	0x3fa89c0e	0xce5a8bd7	0xbb28138b	0xc080ecb1
+	0x9cbf1916	0xd70424e9	0x75cc4ed1	0xa575f3e9
+	0x1c571f68	0xe2906205	0xc26520cf	0xf9c1fc8e
+	0x61c982de	0x1af6cfcc	0xaf397c9a	0x46830771
+	0x623d98bb	0xda7b52fa	0x5a3c57d3	0xfa35d2f0
+	0x4783df19	0x6ad07325	0x487406f4	0x3fae5152
+	0x189137cb	0xd98a644e	0x17ffe880	0xeb6aa9f7
+	0x67184e3e	0xe475734b	0x0f1113c2	0x39a4df47
+	0xbf8f6ec9	0xe13a4d8b	0x63ec02f5	0xdfe7d75d
+	0x1379034c	0x5db7314a	0xa9d9ad3e	0xfaaed8f2
+	0xf0fb6074	0x12f27b84	0xc97a92bb	0xae5e3bb7
+	0x5f7fc2bf	0x00cbc1f7	0x9360a4d9	0x3632ba04
+	0xad044c83	0xeda13ec1	0x34a214c0	0xcf9c972a
+	0x96352243	0xf1a35357	0x2d77bc30	0x8485bbad
+	0x67fbaa99	0x8035b1a5	0x8ca763c0	0x109d7887
+	0xa1c35cd8	0xdc79e308	0x4495404d	0x64419226
+	0xacdcea08	0x9545c0ef	0x5493e09e	0x7fe16336
+	0x41381aa2	0x5c344f46	0xb40cab9f	0xc43951c4
+	0xd86e52a5	0xb141d934	0xd78efcff	0xf37ec320
+	0xc184a45b	0xf4a57954	0xc8aed0bd	0xe602c15a
+	0x71a6b48b	0xce837428	0x02733706	0xc4a4a044
+	0xa75efb97	0xcb63d62e	0xd0580b5a	0xce499087
+	0xc12bf4ca	0x9c995345	0x1d8adfbc	0xe62fd60e
+	0xccbf5412	0x6161f8d0	0x64268e34	0x565d066b
+	0x1896b63f	0x838f8f2a	0x1e314a00	0xac470276
+	0x1879cfdf	0x4702d7f9	0x83b4d777	0x81fcb068
+	0x1b6da94d	0xd075ed01	0x3c7734e8	0x56389a0b
+	0x0743b9cd	0xb6b0bf0d	0x63107ab9	0x193172bc
+	0xc7b84c8e	0x982ce2aa	0xb8e387a6	0xc264a4b0
+	0x2ac6c802	0xb89ea335	0x052332a4	0x49932ecc
+	0xb940f808	0xa7a09330	0x19f3f49d	0x7aef6b5a
+	0x201d8ed0	0xf29aac4b	0x8ae2ac0f	0x998c1ca7
+	0x665c3927	0xab4ef641	0xf136710d	0x9644ee9b
+	0x34efae96	0x4c596035	0x8cfe8b3b	0x5d9f742e
+	0xab2c63ca	0x017d864d	0xd0604d6e	0xab24eee0
+	0x75916a9a	0xad0d1167	0xbeb47775	0x6ac822d1
+	0x776907aa	0x9e9377f2	0x438c5d81	0xd70e9964
+	0x1c09c914	0xab90e5cf	0x31cee523	0x26ba6ea7
+	0xef00781d	0x622b886d	0x36a54031	0x88b1221c
+	0x666333f5	0x60e1c93e	0x5e4d0e0a	0x3ee6ff69
+	0xceb4c76b	0xa5deb4f8	0x0668ced8	0x30225378
+	0x6697cf37	0xc5d9661d	0x089eab85	0x7684a876
+	0x018a81af	0x221a7fb2	0x31d80de0	0x9f18ae90
+	0xa29c9af0	0xc3e2b00f	0xda0edbab	0x7ee9cd2a
+	0x3ab0f88e	0x02c58228	0x606fa7aa	0x7776cb0a
+	0x4e8ad99c	0x3b527469	0x58123d62	0x4ce428d2
+	0xee91a210	0x466ba2cc	0x043c57b9	0xaf7bdd43
+	0x98e76fee	0x8f3eac1b	0x00dffd6c	0x6fcb1c6a
+	0x5cb90573	0x485d4505	0x0df5418a	0x26eafe35
+	0x0faddf3e	0x4e972930	0xe113c823	0xe45944d1
+	0xa646077f	0xc1708ae5	0x6ba07c20	0xc7e4e234
+	0xc6754ed5	0xbd6e85aa	0x8cc1756e	0x02afda29
+	0x72809597	0x75b6f5a1	0x61141874	0x1774047f
+	0x7a10afed	0xfac2c4ad	0x42cf5c99	0x24f0350e
+	0x042f2864	0xfab55b67	0xc8ead5bc	0x914e9512
+	0x77c8ef6b	0x8369aeb1	0x71bc947f	0x0c6b49d8
+	0x8ddd0513	0x028ad10d	0x99a1b28f	0xe6cfbdc8
+	0x7978b4a6	0x3ebbade8	0x9985f5cf	0x431f42f1
+	0x004372b2	0x18b67f68	0x20111c21	0xbb6f77ff
+	0x1783b030	0xa045d7d1	0x0e9c7e09	0x3ccbd95f
+	0x0b84a2ed	0xf0ee3325	0x63f2e126	0x5ec4c67b
+	0x2ca782cc	0xcaf20d04	0x8b59d515	0x3212aa33
+	0x335ca0c3	0x6f9e0cdd	0x4d4bf189	0x44d2fa0c
+	0x5abe9396	0x492794ee	0x10dcfcb1	0x9acda9bd
+	0xe8aa2803	0x3f1b9605	0x3e2ecb5a	0x971bfa8a
+	0xcbf141d2	0x0afafe10	0x2fc906a6	0xefad20c0
+	0x9e922581	0xe69142cc	0xc9c0ba82	0xc069e640
+	0xb99c08b6	0x4b62ca1f	0xf3c5767a	0x6ab088c7
+	0x8f0f0c0b	0x6726f64a	0x9711a3cd	0x46462571
+	0x3a58350e	0xa2561911	0xe24dfdfe	0x97443fdc
+	0xf80540be	0x069978bf	0xb38a359b	0x8e574f62
+	0x69aea75c	0xdc753fcb	0x2a74002c	0xced027b4
+	0xda993254	0x03409b83	0xf827331d	0x75fb3271
+	0x01ad839d	0x68520842	0xca65c45c	0x1a3db5a0
+	0x91d37dd3	0x6168c0fb	0x935f5a08	0x002007c3
+	0x42eb4760	0xdab3a804	0x72a6297e	0x905c32d9
+	0x81abcfa9	0x1b21d04a	0x5a1289ae	0x424e7183
+	0xc207906c	0x31fe9134	0x5eb2e5af	0xc9253fc7
+	0xc32be24f	0xe5474cbd	0xeff6e1b0	0x710e5e69
+	0xe6c4c538	0x96b5f1de	0x2abc9c35	0xddbd1a92
+	0x8aca40d7	0xe359c238	0x954718f4	0x18b157e5
+	0xeeed790e	0x6948a963	0x24e70bfb	0x4d681547
+	0xf68369a7	0x5b54409a	0x1f0b787a	0xc2610047
+	0x0f8bd269	0xd7c8c154	0x9dee62d9	0xd4738ed8
+	0x1a66c6b1	0x5bad5a5b	0xb110311a	0xfaec6802
+	0x6b750f2d	0xcbf8d0e0	0x11edaf4b	0xf64a07bb
+	0x422e7c15	0xb1732663	0x1ff404f0	0x2d5052b0
+	0x6e45356c	0x7e2201e8	0x7c5ebcd1	0x1cb4425a
+	0xb1539a64	0xa2e4459f	0xcf1ade8a	0xfc476473
+	0xf4147deb	0x2afbdd77	0xff01fabc	0x6597408a
+	0x0951220b	0x6750f3ec	0x0a242763	0xf3d71c05
+	0x84cb1c26	0xdb7a81bd	0x7aea1a5d	0x7e719a48
+	0xc5c12fe1	0x0ce2e988	0x29ecc6f0	0x5ede901a
+	0xda8399b1	0x31c05d6b	0xe1956aff	0x59ed7c3d
+	0x60832637	0x9bcb7cac	0x63c530d1	0x14c677de
+	0x9225ed18	0x065327c9	0xd1ff6a0e	0x5516517e
+	0x53c6f5c2	0xed5983cf	0xaa1d18b9	0xbe300d7f
+	0xadc525a7	0x07ea81b6	0xfc517a09	0x4ead3f86
+	0x45435f41	0x2efa58df	0x02348ebc	0x30ed6783
+	0x190b4fb9	0x85c55d6e	0xc9ed8896	0x416ee113
+	0x9b3536d9	0x30577cc0	0xbc4b88c8	0xcda59612
+	0xdfe2bd89	0xd60cde71	0x98843881	0xcc1f32f2
+	0x18b3f643	0x671a14ca	0xd6482a47	0xac6a7d38
+	0x1897da16	0x91b6fcb3	0xf199bb35	0xd38c00ba
+	0xa8c946b6	0x52a1ad37	0xd38ed2d4	0xa1d6f81d
+	0x5af6865b	0xebdb858f	0xb844b110	0x53201ea2
+	0x08870945	0x10c869de	0x19849613	0xdb35d3ed
+	0xd68ebd6e	0x1056fd48	0xf1a0e305	0xe3982ebd
+	0x6f7cc391	0x5956374a	0xf414a5a2	0x325119ab
+	0x99ee1f96	0x6f044bd9	0x8374805b	0xb55c366c
+	0xa2c77051	0x68f199e5	0xd36a9714	0x878f847b
+	0xec0394ae	0x86d0584b	0xf4df66b9	0x451cd039
+	0xf4de06ae	0x35dd0554	0x818a342f	0xeefdbfc9
+	0x5b4e9edd	0x22d9313a	0x3b710d60	0x6deaeb4c
+	0xa9e26512	0x98d31867	0x3c2c2d61	0x7eb5ce41
+	0x40890db6	0x7a3aa660	0x3ef4f306	0x7322881f
+	0x49dac4d5	0x96efe685	0x27bb7f49	0xbb955283
+	0x79c5f2b7	0xff599c28	0x28ee7f5e	0x9f324b73
+	0x45edb7cf	0x39a8b79c	0xd0919c6e	0xe149b29d
+	0x62f5f82e	0xebcfa23e	0xd4d68937	0x54270090
+	0x958af0d4	0xa1e4e799	0xaf68ac19	0x82a84f4e
+	0x50f67b84	0xd5e59629	0xf5fdf24c	0xab1d63c5
+	0x30835807	0x431fce5f	0xe5f96f4d	0x3f6b4802
+	0x14010be8	0xdca45ae5	0xc82709af	0xff76ce2c
+	0x8b222c22	0x73a2d948	0xa8d59cea	0x8c31849e
+	0x469c2e5f	0x3777ee84	0x5fdfa5da	0x02ef9bb2
+	0x792d3194	0xbed63f21	0x0b6dc5f1	0xc9d7fe08
+	0x6df7883d	0x366566cf	0xef772769	0x37826465
+	0x1cdc3086	0xa69ff7b6	0x235012ea	0x292f7e75
+	0x30bdd0fd	0xffdc9df1	0x95c6d570	0xec206204
+	0xc6cd42cb	0xc0d6dfd9	0xb7a16b71	0x17fa527e
+	0x295f2c79	0x990f9820	0x8b8f447d	0x193f9ad1
+	0xebddb2af	0x5dd532eb	0xf1bbd8e8	0x3444a3f4
+	0x18ccce93	0x05edeb4f	0xc4a6b935	0xba37aab0
+	0x96076ba4	0x250dc2f7	0xc4093548	0x030e777d
+	0x7ea40933	0x8da7b1dd	0x59c0b79f	0x807d437c
+	0xf5233ddf	0x54c1983f	0xfc18771b	0xe74b85f0
+	0xdbd725b5	0x70cdd153	0x4ffe300c	0xfda4bdae
+	0xf4ac75d2	0x91c4e15a	0x34d92b97	0x16356a79
+	>;
diff --git a/arch/x86/include/asm/arch-coreboot/gpio.h b/arch/x86/include/asm/arch-coreboot/gpio.h
index 3ec1816..4951a8c 100644
--- a/arch/x86/include/asm/arch-coreboot/gpio.h
+++ b/arch/x86/include/asm/arch-coreboot/gpio.h
@@ -7,9 +7,4 @@
 #ifndef _X86_ARCH_GPIO_H_
 #define _X86_ARCH_GPIO_H_
 
-struct ich6_bank_platdata {
-	uint32_t base_addr;
-	const char *bank_name;
-};
-
 #endif /* _X86_ARCH_GPIO_H_ */
diff --git a/arch/x86/include/asm/arch-ivybridge/gpio.h b/arch/x86/include/asm/arch-ivybridge/gpio.h
new file mode 100644
index 0000000..4951a8c
--- /dev/null
+++ b/arch/x86/include/asm/arch-ivybridge/gpio.h
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2014, Google Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _X86_ARCH_GPIO_H_
+#define _X86_ARCH_GPIO_H_
+
+#endif /* _X86_ARCH_GPIO_H_ */
diff --git a/arch/x86/include/asm/arch-ivybridge/me.h b/arch/x86/include/asm/arch-ivybridge/me.h
new file mode 100644
index 0000000..3a0809d
--- /dev/null
+++ b/arch/x86/include/asm/arch-ivybridge/me.h
@@ -0,0 +1,356 @@
+/*
+ * From Coreboot src/southbridge/intel/bd82x6x/me.h
+ *
+ * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ASM_INTEL_ME_H
+#define _ASM_INTEL_ME_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#define ME_RETRY		100000	/* 1 second */
+#define ME_DELAY		10	/* 10 us */
+
+/*
+ * Management Engine PCI registers
+ */
+
+#define PCI_CPU_MEBASE_L	0x70	/* Set by MRC */
+#define PCI_CPU_MEBASE_H	0x74	/* Set by MRC */
+
+#define PCI_ME_HFS		0x40
+#define  ME_HFS_CWS_RESET	0
+#define  ME_HFS_CWS_INIT	1
+#define  ME_HFS_CWS_REC		2
+#define  ME_HFS_CWS_NORMAL	5
+#define  ME_HFS_CWS_WAIT	6
+#define  ME_HFS_CWS_TRANS	7
+#define  ME_HFS_CWS_INVALID	8
+#define  ME_HFS_STATE_PREBOOT	0
+#define  ME_HFS_STATE_M0_UMA	1
+#define  ME_HFS_STATE_M3	4
+#define  ME_HFS_STATE_M0	5
+#define  ME_HFS_STATE_BRINGUP	6
+#define  ME_HFS_STATE_ERROR	7
+#define  ME_HFS_ERROR_NONE	0
+#define  ME_HFS_ERROR_UNCAT	1
+#define  ME_HFS_ERROR_IMAGE	3
+#define  ME_HFS_ERROR_DEBUG	4
+#define  ME_HFS_MODE_NORMAL	0
+#define  ME_HFS_MODE_DEBUG	2
+#define  ME_HFS_MODE_DIS	3
+#define  ME_HFS_MODE_OVER_JMPR	4
+#define  ME_HFS_MODE_OVER_MEI	5
+#define  ME_HFS_BIOS_DRAM_ACK	1
+#define  ME_HFS_ACK_NO_DID	0
+#define  ME_HFS_ACK_RESET	1
+#define  ME_HFS_ACK_PWR_CYCLE	2
+#define  ME_HFS_ACK_S3		3
+#define  ME_HFS_ACK_S4		4
+#define  ME_HFS_ACK_S5		5
+#define  ME_HFS_ACK_GBL_RESET	6
+#define  ME_HFS_ACK_CONTINUE	7
+
+struct me_hfs {
+	u32 working_state:4;
+	u32 mfg_mode:1;
+	u32 fpt_bad:1;
+	u32 operation_state:3;
+	u32 fw_init_complete:1;
+	u32 ft_bup_ld_flr:1;
+	u32 update_in_progress:1;
+	u32 error_code:4;
+	u32 operation_mode:4;
+	u32 reserved:4;
+	u32 boot_options_present:1;
+	u32 ack_data:3;
+	u32 bios_msg_ack:4;
+} __packed;
+
+#define PCI_ME_UMA		0x44
+
+struct me_uma {
+	u32 size:6;
+	u32 reserved_1:10;
+	u32 valid:1;
+	u32 reserved_0:14;
+	u32 set_to_one:1;
+} __packed;
+
+#define PCI_ME_H_GS		0x4c
+#define  ME_INIT_DONE		1
+#define  ME_INIT_STATUS_SUCCESS	0
+#define  ME_INIT_STATUS_NOMEM	1
+#define  ME_INIT_STATUS_ERROR	2
+
+struct me_did {
+	u32 uma_base:16;
+	u32 reserved:8;
+	u32 status:4;
+	u32 init_done:4;
+} __packed;
+
+#define PCI_ME_GMES		0x48
+#define  ME_GMES_PHASE_ROM	0
+#define  ME_GMES_PHASE_BUP	1
+#define  ME_GMES_PHASE_UKERNEL	2
+#define  ME_GMES_PHASE_POLICY	3
+#define  ME_GMES_PHASE_MODULE	4
+#define  ME_GMES_PHASE_UNKNOWN	5
+#define  ME_GMES_PHASE_HOST	6
+
+struct me_gmes {
+	u32 bist_in_prog:1;
+	u32 icc_prog_sts:2;
+	u32 invoke_mebx:1;
+	u32 cpu_replaced_sts:1;
+	u32 mbp_rdy:1;
+	u32 mfs_failure:1;
+	u32 warm_rst_req_for_df:1;
+	u32 cpu_replaced_valid:1;
+	u32 reserved_1:2;
+	u32 fw_upd_ipu:1;
+	u32 reserved_2:4;
+	u32 current_state:8;
+	u32 current_pmevent:4;
+	u32 progress_code:4;
+} __packed;
+
+#define PCI_ME_HERES		0xbc
+#define  PCI_ME_EXT_SHA1	0x00
+#define  PCI_ME_EXT_SHA256	0x02
+#define PCI_ME_HER(x)		(0xc0+(4*(x)))
+
+struct me_heres {
+	u32 extend_reg_algorithm:4;
+	u32 reserved:26;
+	u32 extend_feature_present:1;
+	u32 extend_reg_valid:1;
+} __packed;
+
+/*
+ * Management Engine MEI registers
+ */
+
+#define MEI_H_CB_WW		0x00
+#define MEI_H_CSR		0x04
+#define MEI_ME_CB_RW		0x08
+#define MEI_ME_CSR_HA		0x0c
+
+struct mei_csr {
+	u32 interrupt_enable:1;
+	u32 interrupt_status:1;
+	u32 interrupt_generate:1;
+	u32 ready:1;
+	u32 reset:1;
+	u32 reserved:3;
+	u32 buffer_read_ptr:8;
+	u32 buffer_write_ptr:8;
+	u32 buffer_depth:8;
+} __packed;
+
+#define MEI_ADDRESS_CORE	0x01
+#define MEI_ADDRESS_AMT		0x02
+#define MEI_ADDRESS_RESERVED	0x03
+#define MEI_ADDRESS_WDT		0x04
+#define MEI_ADDRESS_MKHI	0x07
+#define MEI_ADDRESS_ICC		0x08
+#define MEI_ADDRESS_THERMAL	0x09
+
+#define MEI_HOST_ADDRESS	0
+
+struct mei_header {
+	u32 client_address:8;
+	u32 host_address:8;
+	u32 length:9;
+	u32 reserved:6;
+	u32 is_complete:1;
+} __packed;
+
+#define MKHI_GROUP_ID_CBM	0x00
+#define MKHI_GROUP_ID_FWCAPS	0x03
+#define MKHI_GROUP_ID_MDES	0x08
+#define MKHI_GROUP_ID_GEN	0xff
+
+#define MKHI_GLOBAL_RESET	0x0b
+
+#define MKHI_FWCAPS_GET_RULE	0x02
+
+#define MKHI_MDES_ENABLE	0x09
+
+#define MKHI_GET_FW_VERSION	0x02
+#define MKHI_END_OF_POST	0x0c
+#define MKHI_FEATURE_OVERRIDE	0x14
+
+struct mkhi_header {
+	u32 group_id:8;
+	u32 command:7;
+	u32 is_response:1;
+	u32 reserved:8;
+	u32 result:8;
+} __packed;
+
+struct me_fw_version {
+	u16 code_minor;
+	u16 code_major;
+	u16 code_build_number;
+	u16 code_hot_fix;
+	u16 recovery_minor;
+	u16 recovery_major;
+	u16 recovery_build_number;
+	u16 recovery_hot_fix;
+} __packed;
+
+
+#define HECI_EOP_STATUS_SUCCESS       0x0
+#define HECI_EOP_PERFORM_GLOBAL_RESET 0x1
+
+#define CBM_RR_GLOBAL_RESET	0x01
+
+#define GLOBAL_RESET_BIOS_MRC	0x01
+#define GLOBAL_RESET_BIOS_POST	0x02
+#define GLOBAL_RESET_MEBX	0x03
+
+struct me_global_reset {
+	u8 request_origin;
+	u8 reset_type;
+} __packed;
+
+enum me_bios_path {
+	ME_NORMAL_BIOS_PATH,
+	ME_S3WAKE_BIOS_PATH,
+	ME_ERROR_BIOS_PATH,
+	ME_RECOVERY_BIOS_PATH,
+	ME_DISABLE_BIOS_PATH,
+	ME_FIRMWARE_UPDATE_BIOS_PATH,
+};
+
+struct __packed mbp_fw_version_name {
+	u32 major_version:16;
+	u32 minor_version:16;
+	u32 hotfix_version:16;
+	u32 build_version:16;
+};
+
+struct __packed mbp_icc_profile {
+	u8 num_icc_profiles;
+	u8 icc_profile_soft_strap;
+	u8 icc_profile_index;
+	u8 reserved;
+	u32 register_lock_mask[3];
+};
+
+struct __packed mefwcaps_sku {
+	u32 full_net:1;
+	u32 std_net:1;
+	u32 manageability:1;
+	u32 small_business:1;
+	u32 l3manageability:1;
+	u32 intel_at:1;
+	u32 intel_cls:1;
+	u32 reserved:3;
+	u32 intel_mpc:1;
+	u32 icc_over_clocking:1;
+	u32 pavp:1;
+	u32 reserved_1:4;
+	u32 ipv6:1;
+	u32 kvm:1;
+	u32 och:1;
+	u32 vlan:1;
+	u32 tls:1;
+	u32 reserved_4:1;
+	u32 wlan:1;
+	u32 reserved_5:8;
+};
+
+struct __packed tdt_state_flag {
+	u16 lock_state:1;
+	u16 authenticate_module:1;
+	u16 s3authentication:1;
+	u16 flash_wear_out:1;
+	u16 flash_variable_security:1;
+	u16 wwan3gpresent:1;
+	u16 wwan3goob:1;
+	u16 reserved:9;
+};
+
+struct __packed tdt_state_info {
+	u8 state;
+	u8 last_theft_trigger;
+	struct tdt_state_flag flags;
+};
+
+struct __packed platform_type_rule_data {
+	u32 platform_target_usage_type:4;
+	u32 platform_target_market_type:2;
+	u32 super_sku:1;
+	u32 reserved:1;
+	u32 intel_me_fw_image_type:4;
+	u32 platform_brand:4;
+	u32 reserved_1:16;
+};
+
+struct __packed mbp_fw_caps {
+	struct mefwcaps_sku fw_capabilities;
+	u8 available;
+};
+
+struct __packed mbp_rom_bist_data {
+	u16 device_id;
+	u16 fuse_test_flags;
+	u32 umchid[4];
+};
+
+struct __packed mbp_platform_key {
+	u32 key[8];
+};
+
+struct __packed mbp_plat_type {
+	struct platform_type_rule_data rule_data;
+	u8 available;
+};
+
+struct __packed me_bios_payload {
+	struct mbp_fw_version_name fw_version_name;
+	struct mbp_fw_caps fw_caps_sku;
+	struct mbp_rom_bist_data rom_bist_data;
+	struct mbp_platform_key platform_key;
+	struct mbp_plat_type fw_plat_type;
+	struct mbp_icc_profile icc_profile;
+	struct tdt_state_info at_state;
+	u32 mfsintegrity;
+};
+
+struct __packed mbp_header {
+	u32 mbp_size:8;
+	u32 num_entries:8;
+	u32 rsvd:16;
+};
+
+struct __packed mbp_item_header {
+	u32 app_id:8;
+	u32 item_id:8;
+	u32 length:8;
+	u32 rsvd:8;
+};
+
+struct __packed me_fwcaps {
+	u32 id;
+	u8 length;
+	struct mefwcaps_sku caps_sku;
+	u8 reserved[3];
+};
+
+/* Defined in me_status.c for both romstage and ramstage */
+void intel_me_status(struct me_hfs *hfs, struct me_gmes *gmes);
+
+void intel_early_me_status(void);
+int intel_early_me_init(void);
+int intel_early_me_uma_size(void);
+int intel_early_me_init_done(u8 status);
+
+#endif
diff --git a/arch/x86/include/asm/arch-ivybridge/microcode.h b/arch/x86/include/asm/arch-ivybridge/microcode.h
new file mode 100644
index 0000000..bc9b87c
--- /dev/null
+++ b/arch/x86/include/asm/arch-ivybridge/microcode.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __ASM_ARCH_MICROCODE_H
+#define __ASM_ARCH_MICROCODE_H
+
+/**
+ * microcode_update_intel() - Apply microcode updates
+ *
+ * Applies any microcode updates in the device tree.
+ *
+ * @return 0 if OK, -EEXIST if the updates were already applied, -ENOENT if
+ * not updates were found, -EINVAL if an update was invalid
+ */
+int microcode_update_intel(void);
+
+#endif
diff --git a/arch/x86/include/asm/arch-ivybridge/model_206ax.h b/arch/x86/include/asm/arch-ivybridge/model_206ax.h
new file mode 100644
index 0000000..8281d7a
--- /dev/null
+++ b/arch/x86/include/asm/arch-ivybridge/model_206ax.h
@@ -0,0 +1,82 @@
+/*
+ * From Coreboot file of the same name
+ *
+ * Copyright (C) 2011 The ChromiumOS Authors.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ASM_ARCH_MODEL_206AX_H
+#define _ASM_ARCH_MODEL_206AX_H
+
+/* SandyBridge/IvyBridge bus clock is fixed at 100MHz */
+#define SANDYBRIDGE_BCLK		100
+
+#define  CPUID_VMX			(1 << 5)
+#define  CPUID_SMX			(1 << 6)
+#define MSR_FEATURE_CONFIG		0x13c
+#define MSR_FLEX_RATIO			0x194
+#define  FLEX_RATIO_LOCK		(1 << 20)
+#define  FLEX_RATIO_EN			(1 << 16)
+#define IA32_PLATFORM_DCA_CAP		0x1f8
+#define IA32_MISC_ENABLE		0x1a0
+#define MSR_TEMPERATURE_TARGET		0x1a2
+#define IA32_PERF_CTL			0x199
+#define IA32_THERM_INTERRUPT		0x19b
+#define IA32_ENERGY_PERFORMANCE_BIAS	0x1b0
+#define  ENERGY_POLICY_PERFORMANCE	0
+#define  ENERGY_POLICY_NORMAL		6
+#define  ENERGY_POLICY_POWERSAVE	15
+#define IA32_PACKAGE_THERM_INTERRUPT	0x1b2
+#define MSR_LT_LOCK_MEMORY		0x2e7
+#define IA32_MC0_STATUS		0x401
+
+#define MSR_PIC_MSG_CONTROL		0x2e
+#define  PLATFORM_INFO_SET_TDP		(1 << 29)
+
+#define MSR_MISC_PWR_MGMT		0x1aa
+#define  MISC_PWR_MGMT_EIST_HW_DIS	(1 << 0)
+#define MSR_TURBO_RATIO_LIMIT		0x1ad
+#define MSR_POWER_CTL			0x1fc
+
+#define MSR_PKGC3_IRTL			0x60a
+#define MSR_PKGC6_IRTL			0x60b
+#define MSR_PKGC7_IRTL			0x60c
+#define  IRTL_VALID			(1 << 15)
+#define  IRTL_1_NS			(0 << 10)
+#define  IRTL_32_NS			(1 << 10)
+#define  IRTL_1024_NS			(2 << 10)
+#define  IRTL_32768_NS			(3 << 10)
+#define  IRTL_1048576_NS		(4 << 10)
+#define  IRTL_33554432_NS		(5 << 10)
+#define  IRTL_RESPONSE_MASK		(0x3ff)
+
+/* long duration in low dword, short duration in high dword */
+#define  PKG_POWER_LIMIT_MASK		0x7fff
+#define  PKG_POWER_LIMIT_EN		(1 << 15)
+#define  PKG_POWER_LIMIT_CLAMP		(1 << 16)
+#define  PKG_POWER_LIMIT_TIME_SHIFT	17
+#define  PKG_POWER_LIMIT_TIME_MASK	0x7f
+
+#define MSR_PP0_CURRENT_CONFIG		0x601
+#define  PP0_CURRENT_LIMIT		(112 << 3) /* 112 A */
+#define MSR_PP1_CURRENT_CONFIG		0x602
+#define  PP1_CURRENT_LIMIT_SNB		(35 << 3) /* 35 A */
+#define  PP1_CURRENT_LIMIT_IVB		(50 << 3) /* 50 A */
+#define MSR_PKG_POWER_SKU_UNIT		0x606
+#define MSR_PKG_POWER_SKU		0x614
+
+#define IVB_CONFIG_TDP_MIN_CPUID	0x306a2
+#define MSR_CONFIG_TDP_NOMINAL		0x648
+#define MSR_CONFIG_TDP_LEVEL1		0x649
+#define MSR_CONFIG_TDP_LEVEL2		0x64a
+#define MSR_CONFIG_TDP_CONTROL		0x64b
+#define MSR_TURBO_ACTIVATION_RATIO	0x64c
+
+/* P-state configuration */
+#define PSS_MAX_ENTRIES			8
+#define PSS_RATIO_STEP			2
+#define PSS_LATENCY_TRANSITION		10
+#define PSS_LATENCY_BUSMASTER		10
+
+#endif
diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h
new file mode 100644
index 0000000..c6efdb8
--- /dev/null
+++ b/arch/x86/include/asm/arch-ivybridge/pch.h
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * From Coreboot src/southbridge/intel/bd82x6x/pch.h
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2012 The Chromium OS Authors.  All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ASM_ARCH_PCH_H
+#define _ASM_ARCH_PCH_H
+
+#include <pci.h>
+
+#define DEFAULT_GPIOBASE	0x0480
+#define DEFAULT_PMBASE		0x0500
+
+#define SMBUS_IO_BASE		0x0400
+
+#define PCH_EHCI1_DEV		PCI_BDF(0, 0x1d, 0)
+#define PCH_EHCI2_DEV		PCI_BDF(0, 0x1a, 0)
+#define PCH_XHCI_DEV		PCI_BDF(0, 0x14, 0)
+#define PCH_ME_DEV		PCI_BDF(0, 0x16, 0)
+#define PCH_PCIE_DEV_SLOT	28
+
+#define PCH_DEV			PCI_BDF(0, 0, 0)
+#define PCH_VIDEO_DEV		PCI_BDF(0, 2, 0)
+
+/* PCI Configuration Space (D31:F0): LPC */
+#define PCH_LPC_DEV		PCI_BDF(0, 0x1f, 0)
+
+#define GEN_PMCON_1		0xa0
+#define GEN_PMCON_2		0xa2
+#define GEN_PMCON_3		0xa4
+#define ETR3			0xac
+#define  ETR3_CWORWRE		(1 << 18)
+#define  ETR3_CF9GR		(1 << 20)
+
+#define PMBASE			0x40
+#define ACPI_CNTL		0x44
+#define BIOS_CNTL		0xDC
+#define GPIO_BASE		0x48 /* LPC GPIO Base Address Register */
+#define GPIO_CNTL		0x4C /* LPC GPIO Control Register */
+#define GPIO_ROUT		0xb8
+
+#define LPC_IO_DEC		0x80 /* IO Decode Ranges Register */
+#define LPC_EN			0x82 /* LPC IF Enables Register */
+#define  CNF2_LPC_EN		(1 << 13) /* 0x4e/0x4f */
+#define  CNF1_LPC_EN		(1 << 12) /* 0x2e/0x2f */
+#define  MC_LPC_EN		(1 << 11) /* 0x62/0x66 */
+#define  KBC_LPC_EN		(1 << 10) /* 0x60/0x64 */
+#define  GAMEH_LPC_EN		(1 << 9)  /* 0x208/0x20f */
+#define  GAMEL_LPC_EN		(1 << 8)  /* 0x200/0x207 */
+#define  FDD_LPC_EN		(1 << 3)  /* LPC_IO_DEC[12] */
+#define  LPT_LPC_EN		(1 << 2)  /* LPC_IO_DEC[9:8] */
+#define  COMB_LPC_EN		(1 << 1)  /* LPC_IO_DEC[6:4] */
+#define  COMA_LPC_EN		(1 << 0)  /* LPC_IO_DEC[3:2] */
+#define LPC_GEN1_DEC		0x84 /* LPC IF Generic Decode Range 1 */
+#define LPC_GEN2_DEC		0x88 /* LPC IF Generic Decode Range 2 */
+#define LPC_GEN3_DEC		0x8c /* LPC IF Generic Decode Range 3 */
+#define LPC_GEN4_DEC		0x90 /* LPC IF Generic Decode Range 4 */
+#define LPC_GENX_DEC(x)		(0x84 + 4 * (x))
+
+/* PCI Configuration Space (D31:F3): SMBus */
+#define PCH_SMBUS_DEV		PCI_BDF(0, 0x1f, 3)
+#define SMB_BASE		0x20
+#define HOSTC			0x40
+#define SMB_RCV_SLVA		0x09
+
+/* HOSTC bits */
+#define I2C_EN			(1 << 2)
+#define SMB_SMI_EN		(1 << 1)
+#define HST_EN			(1 << 0)
+
+/* SMBus I/O bits. */
+#define SMBHSTSTAT		0x0
+#define SMBHSTCTL		0x2
+#define SMBHSTCMD		0x3
+#define SMBXMITADD		0x4
+#define SMBHSTDAT0		0x5
+#define SMBHSTDAT1		0x6
+#define SMBBLKDAT		0x7
+#define SMBTRNSADD		0x9
+#define SMBSLVDATA		0xa
+#define SMLINK_PIN_CTL		0xe
+#define SMBUS_PIN_CTL		0xf
+
+#define SMBUS_TIMEOUT		(10 * 1000 * 100)
+
+
+/* Root Complex Register Block */
+#define DEFAULT_RCBA		0xfed1c000
+#define RCB_REG(reg)		(DEFAULT_RCBA + (reg))
+
+#define PCH_RCBA_BASE		0xf0
+
+#define VCH		0x0000	/* 32bit */
+#define VCAP1		0x0004	/* 32bit */
+#define VCAP2		0x0008	/* 32bit */
+#define PVC		0x000c	/* 16bit */
+#define PVS		0x000e	/* 16bit */
+
+#define V0CAP		0x0010	/* 32bit */
+#define V0CTL		0x0014	/* 32bit */
+#define V0STS		0x001a	/* 16bit */
+
+#define V1CAP		0x001c	/* 32bit */
+#define V1CTL		0x0020	/* 32bit */
+#define V1STS		0x0026	/* 16bit */
+
+#define RCTCL		0x0100	/* 32bit */
+#define ESD		0x0104	/* 32bit */
+#define ULD		0x0110	/* 32bit */
+#define ULBA		0x0118	/* 64bit */
+
+#define RP1D		0x0120	/* 32bit */
+#define RP1BA		0x0128	/* 64bit */
+#define RP2D		0x0130	/* 32bit */
+#define RP2BA		0x0138	/* 64bit */
+#define RP3D		0x0140	/* 32bit */
+#define RP3BA		0x0148	/* 64bit */
+#define RP4D		0x0150	/* 32bit */
+#define RP4BA		0x0158	/* 64bit */
+#define HDD		0x0160	/* 32bit */
+#define HDBA		0x0168	/* 64bit */
+#define RP5D		0x0170	/* 32bit */
+#define RP5BA		0x0178	/* 64bit */
+#define RP6D		0x0180	/* 32bit */
+#define RP6BA		0x0188	/* 64bit */
+
+#define RPC		0x0400	/* 32bit */
+#define RPFN		0x0404	/* 32bit */
+
+#define TRSR		0x1e00	/*  8bit */
+#define TRCR		0x1e10	/* 64bit */
+#define TWDR		0x1e18	/* 64bit */
+
+#define IOTR0		0x1e80	/* 64bit */
+#define IOTR1		0x1e88	/* 64bit */
+#define IOTR2		0x1e90	/* 64bit */
+#define IOTR3		0x1e98	/* 64bit */
+
+#define TCTL		0x3000	/*  8bit */
+
+#define NOINT		0
+#define INTA		1
+#define INTB		2
+#define INTC		3
+#define INTD		4
+
+#define DIR_IDR		12	/* Interrupt D Pin Offset */
+#define DIR_ICR		8	/* Interrupt C Pin Offset */
+#define DIR_IBR		4	/* Interrupt B Pin Offset */
+#define DIR_IAR		0	/* Interrupt A Pin Offset */
+
+#define PIRQA		0
+#define PIRQB		1
+#define PIRQC		2
+#define PIRQD		3
+#define PIRQE		4
+#define PIRQF		5
+#define PIRQG		6
+#define PIRQH		7
+
+/* IO Buffer Programming */
+#define IOBPIRI		0x2330
+#define IOBPD		0x2334
+#define IOBPS		0x2338
+#define  IOBPS_RW_BX    ((1 << 9)|(1 << 10))
+#define  IOBPS_WRITE_AX	((1 << 9)|(1 << 10))
+#define  IOBPS_READ_AX	((1 << 8)|(1 << 9)|(1 << 10))
+
+#define D31IP		0x3100	/* 32bit */
+#define D31IP_TTIP	24	/* Thermal Throttle Pin */
+#define D31IP_SIP2	20	/* SATA Pin 2 */
+#define D31IP_SMIP	12	/* SMBUS Pin */
+#define D31IP_SIP	8	/* SATA Pin */
+#define D30IP		0x3104	/* 32bit */
+#define D30IP_PIP	0	/* PCI Bridge Pin */
+#define D29IP		0x3108	/* 32bit */
+#define D29IP_E1P	0	/* EHCI #1 Pin */
+#define D28IP		0x310c	/* 32bit */
+#define D28IP_P8IP	28	/* PCI Express Port 8 */
+#define D28IP_P7IP	24	/* PCI Express Port 7 */
+#define D28IP_P6IP	20	/* PCI Express Port 6 */
+#define D28IP_P5IP	16	/* PCI Express Port 5 */
+#define D28IP_P4IP	12	/* PCI Express Port 4 */
+#define D28IP_P3IP	8	/* PCI Express Port 3 */
+#define D28IP_P2IP	4	/* PCI Express Port 2 */
+#define D28IP_P1IP	0	/* PCI Express Port 1 */
+#define D27IP		0x3110	/* 32bit */
+#define D27IP_ZIP	0	/* HD Audio Pin */
+#define D26IP		0x3114	/* 32bit */
+#define D26IP_E2P	0	/* EHCI #2 Pin */
+#define D25IP		0x3118	/* 32bit */
+#define D25IP_LIP	0	/* GbE LAN Pin */
+#define D22IP		0x3124	/* 32bit */
+#define D22IP_KTIP	12	/* KT Pin */
+#define D22IP_IDERIP	8	/* IDE-R Pin */
+#define D22IP_MEI2IP	4	/* MEI #2 Pin */
+#define D22IP_MEI1IP	0	/* MEI #1 Pin */
+#define D20IP		0x3128  /* 32bit */
+#define D20IP_XHCIIP	0
+#define D31IR		0x3140	/* 16bit */
+#define D30IR		0x3142	/* 16bit */
+#define D29IR		0x3144	/* 16bit */
+#define D28IR		0x3146	/* 16bit */
+#define D27IR		0x3148	/* 16bit */
+#define D26IR		0x314c	/* 16bit */
+#define D25IR		0x3150	/* 16bit */
+#define D22IR		0x315c	/* 16bit */
+#define D20IR		0x3160	/* 16bit */
+#define OIC		0x31fe	/* 16bit */
+
+#define SPI_FREQ_SWSEQ	0x3893
+#define SPI_DESC_COMP0	0x38b0
+#define SPI_FREQ_WR_ERA	0x38b4
+#define SOFT_RESET_CTRL 0x38f4
+#define SOFT_RESET_DATA 0x38f8
+
+#define DIR_ROUTE(a, b, c, d) \
+		(((d) << DIR_IDR) | ((c) << DIR_ICR) | \
+			((b) << DIR_IBR) | ((a) << DIR_IAR))
+
+#define RC		0x3400	/* 32bit */
+#define HPTC		0x3404	/* 32bit */
+#define GCS		0x3410	/* 32bit */
+#define BUC		0x3414	/* 32bit */
+#define PCH_DISABLE_GBE		(1 << 5)
+#define FD		0x3418	/* 32bit */
+#define DISPBDF		0x3424  /* 16bit */
+#define FD2		0x3428	/* 32bit */
+#define CG		0x341c	/* 32bit */
+
+/* Function Disable 1 RCBA 0x3418 */
+#define PCH_DISABLE_ALWAYS	((1 << 0)|(1 << 26))
+#define PCH_DISABLE_P2P		(1 << 1)
+#define PCH_DISABLE_SATA1	(1 << 2)
+#define PCH_DISABLE_SMBUS	(1 << 3)
+#define PCH_DISABLE_HD_AUDIO	(1 << 4)
+#define PCH_DISABLE_EHCI2	(1 << 13)
+#define PCH_DISABLE_LPC		(1 << 14)
+#define PCH_DISABLE_EHCI1	(1 << 15)
+#define PCH_DISABLE_PCIE(x)	(1 << (16 + x))
+#define PCH_DISABLE_THERMAL	(1 << 24)
+#define PCH_DISABLE_SATA2	(1 << 25)
+#define PCH_DISABLE_XHCI	(1 << 27)
+
+/* Function Disable 2 RCBA 0x3428 */
+#define PCH_DISABLE_KT		(1 << 4)
+#define PCH_DISABLE_IDER	(1 << 3)
+#define PCH_DISABLE_MEI2	(1 << 2)
+#define PCH_DISABLE_MEI1	(1 << 1)
+#define PCH_ENABLE_DBDF		(1 << 0)
+
+/* ICH7 GPIOBASE */
+#define GPIO_USE_SEL	0x00
+#define GP_IO_SEL	0x04
+#define GP_LVL		0x0c
+#define GPO_BLINK	0x18
+#define GPI_INV		0x2c
+#define GPIO_USE_SEL2	0x30
+#define GP_IO_SEL2	0x34
+#define GP_LVL2		0x38
+#define GPIO_USE_SEL3	0x40
+#define GP_IO_SEL3	0x44
+#define GP_LVL3		0x48
+#define GP_RST_SEL1	0x60
+#define GP_RST_SEL2	0x64
+#define GP_RST_SEL3	0x68
+
+/* ICH7 PMBASE */
+#define PM1_STS		0x00
+#define   WAK_STS	(1 << 15)
+#define   PCIEXPWAK_STS	(1 << 14)
+#define   PRBTNOR_STS	(1 << 11)
+#define   RTC_STS	(1 << 10)
+#define   PWRBTN_STS	(1 << 8)
+#define   GBL_STS	(1 << 5)
+#define   BM_STS	(1 << 4)
+#define   TMROF_STS	(1 << 0)
+#define PM1_EN		0x02
+#define   PCIEXPWAK_DIS	(1 << 14)
+#define   RTC_EN	(1 << 10)
+#define   PWRBTN_EN	(1 << 8)
+#define   GBL_EN	(1 << 5)
+#define   TMROF_EN	(1 << 0)
+#define PM1_CNT		0x04
+#define   SLP_EN	(1 << 13)
+#define   SLP_TYP	(7 << 10)
+#define    SLP_TYP_S0	0
+#define    SLP_TYP_S1	1
+#define    SLP_TYP_S3	5
+#define    SLP_TYP_S4	6
+#define    SLP_TYP_S5	7
+#define   GBL_RLS	(1 << 2)
+#define   BM_RLD	(1 << 1)
+#define   SCI_EN	(1 << 0)
+#define PM1_TMR		0x08
+#define PROC_CNT	0x10
+#define LV2		0x14
+#define LV3		0x15
+#define LV4		0x16
+#define PM2_CNT		0x50 /* mobile only */
+#define GPE0_STS	0x20
+#define   PME_B0_STS	(1 << 13)
+#define   PME_STS	(1 << 11)
+#define   BATLOW_STS	(1 << 10)
+#define   PCI_EXP_STS	(1 << 9)
+#define   RI_STS	(1 << 8)
+#define   SMB_WAK_STS	(1 << 7)
+#define   TCOSCI_STS	(1 << 6)
+#define   SWGPE_STS	(1 << 2)
+#define   HOT_PLUG_STS	(1 << 1)
+#define GPE0_EN		0x28
+#define   PME_B0_EN	(1 << 13)
+#define   PME_EN	(1 << 11)
+#define   TCOSCI_EN	(1 << 6)
+#define SMI_EN		0x30
+#define   INTEL_USB2_EN	 (1 << 18) /* Intel-Specific USB2 SMI logic */
+#define   LEGACY_USB2_EN (1 << 17) /* Legacy USB2 SMI logic */
+#define   PERIODIC_EN	 (1 << 14) /* SMI on PERIODIC_STS in SMI_STS */
+#define   TCO_EN	 (1 << 13) /* Enable TCO Logic (BIOSWE et al) */
+#define   MCSMI_EN	 (1 << 11) /* Trap microcontroller range access */
+#define   BIOS_RLS	 (1 <<  7) /* asserts SCI on bit set */
+#define   SWSMI_TMR_EN	 (1 <<  6) /* start software smi timer on bit set */
+#define   APMC_EN	 (1 <<  5) /* Writes to APM_CNT cause SMI# */
+#define   SLP_SMI_EN	 (1 <<  4) /* Write SLP_EN in PM1_CNT asserts SMI# */
+#define   LEGACY_USB_EN  (1 <<  3) /* Legacy USB circuit SMI logic */
+#define   BIOS_EN	 (1 <<  2) /* Assert SMI# on setting GBL_RLS bit */
+#define   EOS		 (1 <<  1) /* End of SMI (deassert SMI#) */
+#define   GBL_SMI_EN	 (1 <<  0) /* SMI# generation at all? */
+#define SMI_STS		0x34
+#define ALT_GP_SMI_EN	0x38
+#define ALT_GP_SMI_STS	0x3a
+#define GPE_CNTL	0x42
+#define DEVACT_STS	0x44
+#define SS_CNT		0x50
+#define C3_RES		0x54
+#define TCO1_STS	0x64
+#define   DMISCI_STS	(1 << 9)
+#define TCO2_STS	0x66
+
+/**
+ * lpc_early_init() - set up LPC serial ports and other early things
+ *
+ * @blob:	Device tree blob
+ * @node:	Offset of LPC node
+ * @dev:	PCH PCI device containing the LPC
+ * @return 0 if OK, -ve on error
+ */
+int lpc_early_init(const void *blob, int node, pci_dev_t dev);
+
+#endif
diff --git a/arch/x86/include/asm/arch-ivybridge/pei_data.h b/arch/x86/include/asm/arch-ivybridge/pei_data.h
new file mode 100644
index 0000000..5026c8b
--- /dev/null
+++ b/arch/x86/include/asm/arch-ivybridge/pei_data.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2011, Google Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef ASM_ARCH_PEI_DATA_H
+#define ASM_ARCH_PEI_DATA_H
+
+struct pch_usb3_controller_settings {
+	/* 0: Disable, 1: Enable, 2: Auto, 3: Smart Auto */
+	uint16_t mode;
+	/* 4 bit mask, 1: switchable, 0: not switchable */
+	uint16_t hs_port_switch_mask;
+	/* 0: No xHCI preOS driver, 1: xHCI preOS driver */
+	uint16_t preboot_support;
+	/* 0: Disable, 1: Enable */
+	uint16_t xhci_streams;
+};
+
+typedef asmlinkage void (*tx_byte_func)(unsigned char byte);
+
+#define PEI_VERSION 6
+
+struct __packed pei_data {
+	uint32_t pei_version;
+	uint32_t mchbar;
+	uint32_t dmibar;
+	uint32_t epbar;
+	uint32_t pciexbar;
+	uint16_t smbusbar;
+	uint32_t wdbbar;
+	uint32_t wdbsize;
+	uint32_t hpet_address;
+	uint32_t rcba;
+	uint32_t pmbase;
+	uint32_t gpiobase;
+	uint32_t thermalbase;
+	uint32_t system_type; /* 0 Mobile, 1 Desktop/Server */
+	uint32_t tseg_size;
+	uint8_t spd_addresses[4];
+	uint8_t ts_addresses[4];
+	int boot_mode;
+	int ec_present;
+	int gbe_enable;
+	/*
+	 * 0 = leave channel enabled
+	 * 1 = disable dimm 0 on channel
+	 * 2 = disable dimm 1 on channel
+	 * 3 = disable dimm 0+1 on channel
+	 */
+	int dimm_channel0_disabled;
+	int dimm_channel1_disabled;
+	/* Seed values saved in CMOS */
+	uint32_t scrambler_seed;
+	uint32_t scrambler_seed_s3;
+	/* Data read from flash and passed into MRC */
+	unsigned char *mrc_input;
+	unsigned int mrc_input_len;
+	/* Data from MRC that should be saved to flash */
+	unsigned char *mrc_output;
+	unsigned int mrc_output_len;
+	/*
+	 * Max frequency DDR3 could be ran at. Could be one of four values:
+	 * 800, 1067, 1333, 1600
+	 */
+	uint32_t max_ddr3_freq;
+	/*
+	 * USB Port Configuration:
+	 *  [0] = enable
+	 *  [1] = overcurrent pin
+	 *  [2] = length
+	 *
+	 * Ports 0-7 can be mapped to OC0-OC3
+	 * Ports 8-13 can be mapped to OC4-OC7
+	 *
+	 * Port Length
+	 *  MOBILE:
+	 *   < 0x050 = Setting 1 (back panel, 1-5in, lowest tx amplitude)
+	 *   < 0x140 = Setting 2 (back panel, 5-14in, highest tx amplitude)
+	 *  DESKTOP:
+	 *   < 0x080 = Setting 1 (front/back panel, <8in, lowest tx amplitude)
+	 *   < 0x130 = Setting 2 (back panel, 8-13in, higher tx amplitude)
+	 *   < 0x150 = Setting 3 (back panel, 13-15in, higest tx amplitude)
+	 */
+	uint16_t usb_port_config[16][3];
+	/* See the usb3 struct above for details */
+	struct pch_usb3_controller_settings usb3;
+	/*
+	 * SPD data array for onboard RAM. Specify address 0xf0,
+	 * 0xf1, 0xf2, 0xf3 to index one of the 4 slots in
+	 * spd_address for a given "DIMM".
+	 */
+	uint8_t spd_data[4][256];
+	tx_byte_func tx_byte;
+	int ddr3lv_support;
+	/*
+	 * pcie_init needs to be set to 1 to have the system agent initialise
+	 * PCIe. Note: This should only be required if your system has Gen3
+	 * devices and it will increase your boot time by at least 100ms.
+	 */
+	int pcie_init;
+	/*
+	 * N mode functionality. Leave this setting at 0.
+	 * 0 Auto
+	 * 1 1N
+	 * 2 2N
+	 */
+	int nmode;
+	/*
+	 * DDR refresh rate config. JEDEC Standard No.21-C Annex K allows
+	 * for DIMM SPD data to specify whether double-rate is required for
+	 * extended operating temperature range.
+	 * 0 Enable double rate based upon temperature thresholds
+	 * 1 Normal rate
+	 * 2 Always enable double rate
+	 */
+	int ddr_refresh_rate_config;
+};
+
+#endif
diff --git a/arch/x86/include/asm/arch-ivybridge/sandybridge.h b/arch/x86/include/asm/arch-ivybridge/sandybridge.h
new file mode 100644
index 0000000..114ee19
--- /dev/null
+++ b/arch/x86/include/asm/arch-ivybridge/sandybridge.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * From Coreboot file of the same name
+ *
+ * Copyright (C) 2007-2008 coresystems GmbH
+ * Copyright (C) 2011 Google Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ACH_ASM_SANDYBRIDGE_H
+#define _ACH_ASM_SANDYBRIDGE_H
+
+/* Chipset types */
+#define SANDYBRIDGE_MOBILE	0
+#define SANDYBRIDGE_DESKTOP	1
+#define SANDYBRIDGE_SERVER	2
+
+/* Device ID for SandyBridge and IvyBridge */
+#define BASE_REV_SNB	0x00
+#define BASE_REV_IVB	0x50
+#define BASE_REV_MASK	0x50
+
+/* SandyBridge CPU stepping */
+#define SNB_STEP_D0	(BASE_REV_SNB + 5) /* Also J0 */
+#define SNB_STEP_D1	(BASE_REV_SNB + 6)
+#define SNB_STEP_D2	(BASE_REV_SNB + 7) /* Also J1/Q0 */
+
+/* IvyBridge CPU stepping */
+#define IVB_STEP_A0	(BASE_REV_IVB + 0)
+#define IVB_STEP_B0	(BASE_REV_IVB + 2)
+#define IVB_STEP_C0	(BASE_REV_IVB + 4)
+#define IVB_STEP_K0	(BASE_REV_IVB + 5)
+#define IVB_STEP_D0	(BASE_REV_IVB + 6)
+
+/* Intel Enhanced Debug region must be 4MB */
+#define IED_SIZE	0x400000
+
+/* Northbridge BARs */
+#define DEFAULT_MCHBAR		0xfed10000	/* 16 KB */
+#define DEFAULT_DMIBAR		0xfed18000	/* 4 KB */
+#define DEFAULT_EPBAR		0xfed19000	/* 4 KB */
+#define DEFAULT_RCBABASE	0xfed1c000
+/* 4 KB per PCIe device */
+#define DEFAULT_PCIEXBAR	CONFIG_MMCONF_BASE_ADDRESS
+
+/* Device 0:0.0 PCI configuration space (Host Bridge) */
+#define EPBAR		0x40
+#define MCHBAR		0x48
+#define PCIEXBAR	0x60
+#define DMIBAR		0x68
+#define X60BAR		0x60
+
+#define GGC		0x50			/* GMCH Graphics Control */
+
+#define DEVEN		0x54			/* Device Enable */
+#define  DEVEN_PEG60	(1 << 13)
+#define  DEVEN_IGD	(1 << 4)
+#define  DEVEN_PEG10	(1 << 3)
+#define  DEVEN_PEG11	(1 << 2)
+#define  DEVEN_PEG12	(1 << 1)
+#define  DEVEN_HOST	(1 << 0)
+
+#define PAM0		0x80
+#define PAM1		0x81
+#define PAM2		0x82
+#define PAM3		0x83
+#define PAM4		0x84
+#define PAM5		0x85
+#define PAM6		0x86
+
+#define LAC		0x87	/* Legacy Access Control */
+#define SMRAM		0x88	/* System Management RAM Control */
+#define  D_OPEN		(1 << 6)
+#define  D_CLS		(1 << 5)
+#define  D_LCK		(1 << 4)
+#define  G_SMRAME	(1 << 3)
+#define  C_BASE_SEG	((0 << 2) | (1 << 1) | (0 << 0))
+
+#define TOM		0xa0
+#define TOUUD		0xa8	/* Top of Upper Usable DRAM */
+#define TSEG		0xb8	/* TSEG base */
+#define TOLUD		0xbc	/* Top of Low Used Memory */
+
+#define SKPAD		0xdc	/* Scratchpad Data */
+
+/* Device 0:1.0 PCI configuration space (PCI Express) */
+#define BCTRL1		0x3e	/* 16bit */
+
+/* Device 0:2.0 PCI configuration space (Graphics Device) */
+
+#define MSAC		0x62	/* Multi Size Aperture Control */
+#define SWSCI		0xe8	/* SWSCI  enable */
+#define ASLS		0xfc	/* OpRegion Base */
+
+/*
+ * MCHBAR
+ */
+#define MCHBAR_REG(reg)		(DEFAULT_RCBA + (reg))
+
+#define SSKPD		0x5d14	/* 16bit (scratchpad) */
+#define BIOS_RESET_CPL	0x5da8	/* 8bit */
+
+void report_platform_info(void);
+
+void sandybridge_early_init(int chipset_type);
+
+#endif
diff --git a/arch/x86/include/asm/config.h b/arch/x86/include/asm/config.h
index ff15828..c97d988 100644
--- a/arch/x86/include/asm/config.h
+++ b/arch/x86/include/asm/config.h
@@ -10,5 +10,6 @@
 #define CONFIG_SYS_GENERIC_BOARD
 #define CONFIG_LMB
 #define CONFIG_SYS_BOOT_RAMDISK_HIGH
+#define asmlinkage __attribute__((regparm(0)))
 
 #endif
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 6c6774a..c839291 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -1,16 +1,160 @@
 /*
  * Copyright (c) 2014 The Chromium OS Authors.
  *
+ * Part of this file is adapted from coreboot
+ * src/arch/x86/include/arch/cpu.h and
+ * src/arch/x86/lib/cpu.c
+ *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#ifndef __X86_CPU_H
-#define __X86_CPU_H
+#ifndef _ASM_CPU_H
+#define _ASM_CPU_H
 
- /**
+enum {
+	X86_VENDOR_INVALID = 0,
+	X86_VENDOR_INTEL,
+	X86_VENDOR_CYRIX,
+	X86_VENDOR_AMD,
+	X86_VENDOR_UMC,
+	X86_VENDOR_NEXGEN,
+	X86_VENDOR_CENTAUR,
+	X86_VENDOR_RISE,
+	X86_VENDOR_TRANSMETA,
+	X86_VENDOR_NSC,
+	X86_VENDOR_SIS,
+	X86_VENDOR_ANY = 0xfe,
+	X86_VENDOR_UNKNOWN = 0xff
+};
+
+struct cpuid_result {
+	uint32_t eax;
+	uint32_t ebx;
+	uint32_t ecx;
+	uint32_t edx;
+};
+
+/*
+ * Generic CPUID function
+ */
+static inline struct cpuid_result cpuid(int op)
+{
+	struct cpuid_result result;
+	asm volatile(
+		"mov %%ebx, %%edi;"
+		"cpuid;"
+		"mov %%ebx, %%esi;"
+		"mov %%edi, %%ebx;"
+		: "=a" (result.eax),
+		  "=S" (result.ebx),
+		  "=c" (result.ecx),
+		  "=d" (result.edx)
+		: "0" (op)
+		: "edi");
+	return result;
+}
+
+/*
+ * Generic Extended CPUID function
+ */
+static inline struct cpuid_result cpuid_ext(int op, unsigned ecx)
+{
+	struct cpuid_result result;
+	asm volatile(
+		"mov %%ebx, %%edi;"
+		"cpuid;"
+		"mov %%ebx, %%esi;"
+		"mov %%edi, %%ebx;"
+		: "=a" (result.eax),
+		  "=S" (result.ebx),
+		  "=c" (result.ecx),
+		  "=d" (result.edx)
+		: "0" (op), "2" (ecx)
+		: "edi");
+	return result;
+}
+
+/*
+ * CPUID functions returning a single datum
+ */
+static inline unsigned int cpuid_eax(unsigned int op)
+{
+	unsigned int eax;
+
+	__asm__("mov %%ebx, %%edi;"
+		"cpuid;"
+		"mov %%edi, %%ebx;"
+		: "=a" (eax)
+		: "0" (op)
+		: "ecx", "edx", "edi");
+	return eax;
+}
+
+static inline unsigned int cpuid_ebx(unsigned int op)
+{
+	unsigned int eax, ebx;
+
+	__asm__("mov %%ebx, %%edi;"
+		"cpuid;"
+		"mov %%ebx, %%esi;"
+		"mov %%edi, %%ebx;"
+		: "=a" (eax), "=S" (ebx)
+		: "0" (op)
+		: "ecx", "edx", "edi");
+	return ebx;
+}
+
+static inline unsigned int cpuid_ecx(unsigned int op)
+{
+	unsigned int eax, ecx;
+
+	__asm__("mov %%ebx, %%edi;"
+		"cpuid;"
+		"mov %%edi, %%ebx;"
+		: "=a" (eax), "=c" (ecx)
+		: "0" (op)
+		: "edx", "edi");
+	return ecx;
+}
+
+static inline unsigned int cpuid_edx(unsigned int op)
+{
+	unsigned int eax, edx;
+
+	__asm__("mov %%ebx, %%edi;"
+		"cpuid;"
+		"mov %%edi, %%ebx;"
+		: "=a" (eax), "=d" (edx)
+		: "0" (op)
+		: "ecx", "edi");
+	return edx;
+}
+
+/* Standard macro to see if a specific flag is changeable */
+static inline int flag_is_changeable_p(uint32_t flag)
+{
+	uint32_t f1, f2;
+
+	asm(
+		"pushfl\n\t"
+		"pushfl\n\t"
+		"popl %0\n\t"
+		"movl %0,%1\n\t"
+		"xorl %2,%0\n\t"
+		"pushl %0\n\t"
+		"popfl\n\t"
+		"pushfl\n\t"
+		"popl %0\n\t"
+		"popfl\n\t"
+		: "=&r" (f1), "=&r" (f2)
+		: "ir" (flag));
+	return ((f1^f2) & flag) != 0;
+}
+
+/**
  * cpu_enable_paging_pae() - Enable PAE-paging
  *
- * @pdpt:	Value to set in cr3 (PDPT or PML4T)
+ * @cr3:	Value to set in cr3 (PDPT or PML4T)
  */
 void cpu_enable_paging_pae(ulong cr3);
 
@@ -27,6 +171,27 @@
 int cpu_has_64bit(void);
 
 /**
+ * cpu_vendor_name() - Get CPU vendor name
+ *
+ * @vendor:	CPU vendor enumeration number
+ *
+ * @return:	Address to hold the CPU vendor name string
+ */
+const char *cpu_vendor_name(int vendor);
+
+#define CPU_MAX_NAME_LEN	49
+
+/**
+ * cpu_get_name() - Get the name of the current cpu
+ *
+ * @name: Place to put name, which must be CPU_MAX_NAME_LEN bytes including
+ * @return pointer to name, which will likely be a few bytes after the start
+ * of @name
+ * \0 terminator
+ */
+char *cpu_get_name(char *name);
+
+/**
  * cpu_call64() - Jump to a 64-bit Linux kernel (internal function)
  *
  * The kernel is uncompressed and the 64-bit entry point is expected to be
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 3e8e2cd..48bbd1a 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -10,13 +10,43 @@
 
 #ifndef __ASSEMBLY__
 
+enum pei_boot_mode_t {
+	PEI_BOOT_NONE = 0,
+	PEI_BOOT_SOFT_RESET,
+	PEI_BOOT_RESUME,
+
+};
+
+struct memory_area {
+	uint64_t start;
+	uint64_t size;
+};
+
+struct memory_info {
+	int num_areas;
+	uint64_t total_memory;
+	uint64_t total_32bit_memory;
+	struct memory_area area[CONFIG_NR_DRAM_BANKS];
+};
+
 /* Architecture-specific global data */
 struct arch_global_data {
 	struct global_data *gd_addr;		/* Location of Global Data */
+	uint8_t  x86;			/* CPU family */
+	uint8_t  x86_vendor;		/* CPU vendor */
+	uint8_t  x86_model;
+	uint8_t  x86_mask;
+	uint32_t x86_device;
 	uint64_t tsc_base;		/* Initial value returned by rdtsc() */
 	uint32_t tsc_base_kclocks;	/* Initial tsc as a kclocks value */
 	uint32_t tsc_prev;		/* For show_boot_progress() */
+	uint32_t tsc_mhz;		/* TSC frequency in MHz */
 	void *new_fdt;			/* Relocated FDT */
+	uint32_t bist;			/* Built-in self test value */
+	struct pci_controller *hose;	/* PCI hose for early use */
+	enum pei_boot_mode_t pei_boot_mode;
+	const struct pch_gpio_map *gpio_map;	/* board GPIO map */
+	struct memory_info meminfo;	/* Memory information */
 };
 
 #endif
diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h
index 8bda414..5540d42 100644
--- a/arch/x86/include/asm/gpio.h
+++ b/arch/x86/include/asm/gpio.h
@@ -1,12 +1,152 @@
 /*
  * Copyright (c) 2012, Google Inc. All rights reserved.
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0
  */
 
 #ifndef _X86_GPIO_H_
 #define _X86_GPIO_H_
 
+#include <linux/compiler.h>
 #include <asm/arch/gpio.h>
 #include <asm-generic/gpio.h>
 
+struct ich6_bank_platdata {
+	uint32_t base_addr;
+	const char *bank_name;
+};
+
+#define GPIO_MODE_NATIVE	0
+#define GPIO_MODE_GPIO		1
+#define GPIO_MODE_NONE		1
+
+#define GPIO_DIR_OUTPUT		0
+#define GPIO_DIR_INPUT		1
+
+#define GPIO_NO_INVERT		0
+#define GPIO_INVERT		1
+
+#define GPIO_LEVEL_LOW		0
+#define GPIO_LEVEL_HIGH		1
+
+#define GPIO_NO_BLINK		0
+#define GPIO_BLINK		1
+
+#define GPIO_RESET_PWROK	0
+#define GPIO_RESET_RSMRST	1
+
+struct pch_gpio_set1 {
+	u32 gpio0:1;
+	u32 gpio1:1;
+	u32 gpio2:1;
+	u32 gpio3:1;
+	u32 gpio4:1;
+	u32 gpio5:1;
+	u32 gpio6:1;
+	u32 gpio7:1;
+	u32 gpio8:1;
+	u32 gpio9:1;
+	u32 gpio10:1;
+	u32 gpio11:1;
+	u32 gpio12:1;
+	u32 gpio13:1;
+	u32 gpio14:1;
+	u32 gpio15:1;
+	u32 gpio16:1;
+	u32 gpio17:1;
+	u32 gpio18:1;
+	u32 gpio19:1;
+	u32 gpio20:1;
+	u32 gpio21:1;
+	u32 gpio22:1;
+	u32 gpio23:1;
+	u32 gpio24:1;
+	u32 gpio25:1;
+	u32 gpio26:1;
+	u32 gpio27:1;
+	u32 gpio28:1;
+	u32 gpio29:1;
+	u32 gpio30:1;
+	u32 gpio31:1;
+} __packed;
+
+struct pch_gpio_set2 {
+	u32 gpio32:1;
+	u32 gpio33:1;
+	u32 gpio34:1;
+	u32 gpio35:1;
+	u32 gpio36:1;
+	u32 gpio37:1;
+	u32 gpio38:1;
+	u32 gpio39:1;
+	u32 gpio40:1;
+	u32 gpio41:1;
+	u32 gpio42:1;
+	u32 gpio43:1;
+	u32 gpio44:1;
+	u32 gpio45:1;
+	u32 gpio46:1;
+	u32 gpio47:1;
+	u32 gpio48:1;
+	u32 gpio49:1;
+	u32 gpio50:1;
+	u32 gpio51:1;
+	u32 gpio52:1;
+	u32 gpio53:1;
+	u32 gpio54:1;
+	u32 gpio55:1;
+	u32 gpio56:1;
+	u32 gpio57:1;
+	u32 gpio58:1;
+	u32 gpio59:1;
+	u32 gpio60:1;
+	u32 gpio61:1;
+	u32 gpio62:1;
+	u32 gpio63:1;
+} __packed;
+
+struct pch_gpio_set3 {
+	u32 gpio64:1;
+	u32 gpio65:1;
+	u32 gpio66:1;
+	u32 gpio67:1;
+	u32 gpio68:1;
+	u32 gpio69:1;
+	u32 gpio70:1;
+	u32 gpio71:1;
+	u32 gpio72:1;
+	u32 gpio73:1;
+	u32 gpio74:1;
+	u32 gpio75:1;
+} __packed;
+
+/*
+ * This hilariously complex structure came from Coreboot. The
+ * setup_pch_gpios() function uses it. It could be move to device tree, or
+ * adjust to use masks instead of bitfields.
+ */
+struct pch_gpio_map {
+	struct {
+		const struct pch_gpio_set1 *mode;
+		const struct pch_gpio_set1 *direction;
+		const struct pch_gpio_set1 *level;
+		const struct pch_gpio_set1 *reset;
+		const struct pch_gpio_set1 *invert;
+		const struct pch_gpio_set1 *blink;
+	} set1;
+	struct {
+		const struct pch_gpio_set2 *mode;
+		const struct pch_gpio_set2 *direction;
+		const struct pch_gpio_set2 *level;
+		const struct pch_gpio_set2 *reset;
+	} set2;
+	struct {
+		const struct pch_gpio_set3 *mode;
+		const struct pch_gpio_set3 *direction;
+		const struct pch_gpio_set3 *level;
+		const struct pch_gpio_set3 *reset;
+	} set3;
+};
+
+void ich_gpio_set_gpio_map(const struct pch_gpio_map *map);
+
 #endif /* _X86_GPIO_H_ */
diff --git a/arch/x86/include/asm/i8254.h b/arch/x86/include/asm/i8254.h
index c3ccd4f..4116de1 100644
--- a/arch/x86/include/asm/i8254.h
+++ b/arch/x86/include/asm/i8254.h
@@ -36,4 +36,7 @@
 #define PIT_CMD_MODE4	0x08		/* Select mode 4 */
 #define PIT_CMD_MODE5	0x0A		/* Select mode 5 */
 
+/* The clock frequency of the i8253/i8254 PIT */
+#define PIT_TICK_RATE	1193182ul
+
 #endif
diff --git a/arch/x86/include/asm/init_helpers.h b/arch/x86/include/asm/init_helpers.h
index b07887e..8cbe08e 100644
--- a/arch/x86/include/asm/init_helpers.h
+++ b/arch/x86/include/asm/init_helpers.h
@@ -13,7 +13,5 @@
 int init_cache_f_r(void);
 int init_bd_struct_r(void);
 int init_func_spi(void);
-int find_fdt(void);
-int prepare_fdt(void);
 
 #endif	/* !_INIT_HELPERS_H_ */
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 86bac90..fcd9aa9 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -69,6 +69,55 @@
 #define memcpy_fromio(a,b,c)	memcpy((a),(b),(c))
 #define memcpy_toio(a,b,c)	memcpy((a),(b),(c))
 
+#define write_arch(type, endian, a, v) __raw_write##type(cpu_to_##endian(v), a)
+#define read_arch(type, endian, a) endian##_to_cpu(__raw_read##type(a))
+
+#define write_le64(a, v)	write_arch(q, le64, a, v)
+#define write_le32(a, v)	write_arch(l, le32, a, v)
+#define write_le16(a, v)	write_arch(w, le16, a, v)
+
+#define read_le64(a)	read_arch(q, le64, a)
+#define read_le32(a)	read_arch(l, le32, a)
+#define read_le16(a)	read_arch(w, le16, a)
+
+#define write_be32(a, v)	write_arch(l, be32, a, v)
+#define write_be16(a, v)	write_arch(w, be16, a, v)
+
+#define read_be32(a)	read_arch(l, be32, a)
+#define read_be16(a)	read_arch(w, be16, a)
+
+#define write_8(a, v)	__raw_writeb(v, a)
+#define read_8(a)	__raw_readb(a)
+
+#define clrbits(type, addr, clear) \
+	write_##type((addr), read_##type(addr) & ~(clear))
+
+#define setbits(type, addr, set) \
+	write_##type((addr), read_##type(addr) | (set))
+
+#define clrsetbits(type, addr, clear, set) \
+	write_##type((addr), (read_##type(addr) & ~(clear)) | (set))
+
+#define clrbits_be32(addr, clear) clrbits(be32, addr, clear)
+#define setbits_be32(addr, set) setbits(be32, addr, set)
+#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set)
+
+#define clrbits_le32(addr, clear) clrbits(le32, addr, clear)
+#define setbits_le32(addr, set) setbits(le32, addr, set)
+#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set)
+
+#define clrbits_be16(addr, clear) clrbits(be16, addr, clear)
+#define setbits_be16(addr, set) setbits(be16, addr, set)
+#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set)
+
+#define clrbits_le16(addr, clear) clrbits(le16, addr, clear)
+#define setbits_le16(addr, set) setbits(le16, addr, set)
+#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set)
+
+#define clrbits_8(addr, clear) clrbits(8, addr, clear)
+#define setbits_8(addr, set) setbits(8, addr, set)
+#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
+
 /*
  * ISA space is 'always mapped' on a typical x86 system, no need to
  * explicitly ioremap() it. The fact that the ISA IO space is mapped
diff --git a/arch/x86/include/asm/lapic.h b/arch/x86/include/asm/lapic.h
new file mode 100644
index 0000000..948e643
--- /dev/null
+++ b/arch/x86/include/asm/lapic.h
@@ -0,0 +1,59 @@
+/*
+ * From Coreboot file of same name
+ *
+ * Copyright (C) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ARCH_ASM_LAPIC_H
+#define _ARCH_ASM_LAPIC_H
+
+#include <asm/io.h>
+#include <asm/lapic_def.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+
+static inline __attribute__((always_inline))
+		unsigned long lapic_read(unsigned long reg)
+{
+	return readl(LAPIC_DEFAULT_BASE + reg);
+}
+
+static inline __attribute__((always_inline))
+		void lapic_write(unsigned long reg, unsigned long val)
+{
+	writel(val, LAPIC_DEFAULT_BASE + reg);
+}
+
+static inline __attribute__((always_inline)) void lapic_wait_icr_idle(void)
+{
+	do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
+}
+
+static inline void enable_lapic(void)
+{
+	msr_t msr;
+
+	msr = msr_read(LAPIC_BASE_MSR);
+	msr.hi &= 0xffffff00;
+	msr.lo &= 0x000007ff;
+	msr.lo |= LAPIC_DEFAULT_BASE | (1 << 11);
+	msr_write(LAPIC_BASE_MSR, msr);
+}
+
+static inline void disable_lapic(void)
+{
+	msr_t msr;
+
+	msr = msr_read(LAPIC_BASE_MSR);
+	msr.lo &= ~(1 << 11);
+	msr_write(LAPIC_BASE_MSR, msr);
+}
+
+static inline __attribute__((always_inline)) unsigned long lapicid(void)
+{
+	return lapic_read(LAPIC_ID) >> 24;
+}
+
+#endif
diff --git a/arch/x86/include/asm/lapic_def.h b/arch/x86/include/asm/lapic_def.h
new file mode 100644
index 0000000..722cead
--- /dev/null
+++ b/arch/x86/include/asm/lapic_def.h
@@ -0,0 +1,101 @@
+/*
+ * Taken from the Coreboot file of the same name
+ *
+ * (C) Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ASM_LAPIC_DEF_H
+#define _ASM_LAPIC_DEF_H
+
+#define LAPIC_BASE_MSR			0x1B
+#define LAPIC_BASE_MSR_BOOTSTRAP_PROCESSOR	(1 << 8)
+#define LAPIC_BASE_MSR_ENABLE		(1 << 11)
+#define LAPIC_BASE_MSR_ADDR_MASK	0xFFFFF000
+
+#define LOCAL_APIC_ADDR			0xfee00000
+#define LAPIC_DEFAULT_BASE		LOCAL_APIC_ADDR
+
+#define LAPIC_ID			0x020
+#define LAPIC_LVR			0x030
+#define LAPIC_TASKPRI			0x80
+#define LAPIC_TPRI_MASK			0xFF
+#define LAPIC_ARBID			0x090
+#define LAPIC_RRR			0x0C0
+#define LAPIC_SVR			0x0f0
+#define LAPIC_SPIV			0x0f0
+#define LAPIC_SPIV_ENABLE		0x100
+#define LAPIC_ESR			0x280
+#define LAPIC_ESR_SEND_CS		0x00001
+#define LAPIC_ESR_RECV_CS		0x00002
+#define LAPIC_ESR_SEND_ACC		0x00004
+#define LAPIC_ESR_RECV_ACC		0x00008
+#define LAPIC_ESR_SENDILL		0x00020
+#define LAPIC_ESR_RECVILL		0x00040
+#define LAPIC_ESR_ILLREGA		0x00080
+#define LAPIC_ICR			0x300
+#define LAPIC_DEST_SELF			0x40000
+#define LAPIC_DEST_ALLINC		0x80000
+#define LAPIC_DEST_ALLBUT		0xC0000
+#define LAPIC_ICR_RR_MASK		0x30000
+#define LAPIC_ICR_RR_INVALID		0x00000
+#define LAPIC_ICR_RR_INPROG		0x10000
+#define LAPIC_ICR_RR_VALID		0x20000
+#define LAPIC_INT_LEVELTRIG		0x08000
+#define LAPIC_INT_ASSERT		0x04000
+#define LAPIC_ICR_BUSY			0x01000
+#define LAPIC_DEST_LOGICAL		0x00800
+#define LAPIC_DM_FIXED			0x00000
+#define LAPIC_DM_LOWEST			0x00100
+#define LAPIC_DM_SMI			0x00200
+#define LAPIC_DM_REMRD			0x00300
+#define LAPIC_DM_NMI			0x00400
+#define LAPIC_DM_INIT			0x00500
+#define LAPIC_DM_STARTUP		0x00600
+#define LAPIC_DM_EXTINT			0x00700
+#define LAPIC_VECTOR_MASK		0x000FF
+#define LAPIC_ICR2			0x310
+#define GET_LAPIC_DEST_FIELD(x)		(((x) >> 24) & 0xFF)
+#define SET_LAPIC_DEST_FIELD(x)		((x) << 24)
+#define LAPIC_LVTT			0x320
+#define LAPIC_LVTPC			0x340
+#define LAPIC_LVT0			0x350
+#define LAPIC_LVT_TIMER_BASE_MASK	(0x3 << 18)
+#define GET_LAPIC_TIMER_BASE(x)		(((x) >> 18) & 0x3)
+#define SET_LAPIC_TIMER_BASE(x)		(((x) << 18))
+#define LAPIC_TIMER_BASE_CLKIN		0x0
+#define LAPIC_TIMER_BASE_TMBASE		0x1
+#define LAPIC_TIMER_BASE_DIV		0x2
+#define LAPIC_LVT_TIMER_PERIODIC	(1 << 17)
+#define LAPIC_LVT_MASKED		(1 << 16)
+#define LAPIC_LVT_LEVEL_TRIGGER		(1 << 15)
+#define LAPIC_LVT_REMOTE_IRR		(1 << 14)
+#define LAPIC_INPUT_POLARITY		(1 << 13)
+#define LAPIC_SEND_PENDING		(1 << 12)
+#define LAPIC_LVT_RESERVED_1		(1 << 11)
+#define LAPIC_DELIVERY_MODE_MASK	(7 << 8)
+#define LAPIC_DELIVERY_MODE_FIXED	(0 << 8)
+#define LAPIC_DELIVERY_MODE_NMI		(4 << 8)
+#define LAPIC_DELIVERY_MODE_EXTINT	(7 << 8)
+#define GET_LAPIC_DELIVERY_MODE(x)	(((x) >> 8) & 0x7)
+#define SET_LAPIC_DELIVERY_MODE(x, y)	(((x) & ~0x700)|((y) << 8))
+#define LAPIC_MODE_FIXED		0x0
+#define LAPIC_MODE_NMI			0x4
+#define LAPIC_MODE_EXINT		0x7
+#define LAPIC_LVT1			0x360
+#define LAPIC_LVTERR			0x370
+#define LAPIC_TMICT			0x380
+#define LAPIC_TMCCT			0x390
+#define LAPIC_TDCR			0x3E0
+#define LAPIC_TDR_DIV_TMBASE		(1 << 2)
+#define LAPIC_TDR_DIV_1			0xB
+#define LAPIC_TDR_DIV_2			0x0
+#define LAPIC_TDR_DIV_4			0x1
+#define LAPIC_TDR_DIV_8			0x2
+#define LAPIC_TDR_DIV_16		0x3
+#define LAPIC_TDR_DIV_32		0x8
+#define LAPIC_TDR_DIV_64		0x9
+#define LAPIC_TDR_DIV_128		0xA
+
+#endif
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 3b5915d..df43983 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -175,6 +175,25 @@
 	return native_wrmsr_safe_regs(regs);
 }
 
+typedef struct msr_t {
+	uint32_t lo;
+	uint32_t hi;
+} msr_t;
+
+static inline struct msr_t msr_read(unsigned msr_num)
+{
+	struct msr_t msr;
+
+	rdmsr(msr_num, msr.lo, msr.hi);
+
+	return msr;
+}
+
+static inline void msr_write(unsigned msr_num, msr_t msr)
+{
+	wrmsr(msr_num, msr.lo, msr.hi);
+}
+
 #define rdtscl(low)						\
 	((low) = (u32)__native_read_tsc())
 
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
new file mode 100644
index 0000000..5f05a48
--- /dev/null
+++ b/arch/x86/include/asm/mtrr.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * From Coreboot file of the same name
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ASM_MTRR_H
+#define _ASM_MTRR_H
+
+/*  These are the region types  */
+#define MTRR_TYPE_UNCACHEABLE 0
+#define MTRR_TYPE_WRCOMB     1
+/*#define MTRR_TYPE_         2*/
+/*#define MTRR_TYPE_         3*/
+#define MTRR_TYPE_WRTHROUGH  4
+#define MTRR_TYPE_WRPROT     5
+#define MTRR_TYPE_WRBACK     6
+#define MTRR_NUM_TYPES       7
+
+#define MTRRcap_MSR     0x0fe
+#define MTRRdefType_MSR 0x2ff
+
+#define MTRRdefTypeEn		(1 << 11)
+#define MTRRdefTypeFixEn	(1 << 10)
+
+#define SMRRphysBase_MSR 0x1f2
+#define SMRRphysMask_MSR 0x1f3
+
+#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
+#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
+
+#define MTRRphysMaskValid	(1 << 11)
+
+#define NUM_FIXED_RANGES 88
+#define RANGES_PER_FIXED_MTRR 8
+#define MTRRfix64K_00000_MSR 0x250
+#define MTRRfix16K_80000_MSR 0x258
+#define MTRRfix16K_A0000_MSR 0x259
+#define MTRRfix4K_C0000_MSR 0x268
+#define MTRRfix4K_C8000_MSR 0x269
+#define MTRRfix4K_D0000_MSR 0x26a
+#define MTRRfix4K_D8000_MSR 0x26b
+#define MTRRfix4K_E0000_MSR 0x26c
+#define MTRRfix4K_E8000_MSR 0x26d
+#define MTRRfix4K_F0000_MSR 0x26e
+#define MTRRfix4K_F8000_MSR 0x26f
+
+#if !defined(__ASSEMBLER__)
+
+/*
+ * The MTRR code has some side effects that the callers should be aware for.
+ * 1. The call sequence matters. x86_setup_mtrrs() calls
+ *    x86_setup_fixed_mtrrs_no_enable() then enable_fixed_mtrrs() (equivalent
+ *    of x86_setup_fixed_mtrrs()) then x86_setup_var_mtrrs(). If the callers
+ *    want to call the components of x86_setup_mtrrs() because of other
+ *    rquirements the ordering should still preserved.
+ * 2. enable_fixed_mtrr() will enable both variable and fixed MTRRs because
+ *    of the nature of the global MTRR enable flag. Therefore, all direct
+ *    or indirect callers of enable_fixed_mtrr() should ensure that the
+ *    variable MTRR MSRs do not contain bad ranges.
+ * 3. If CONFIG_CACHE_ROM is selected an MTRR is allocated for enabling
+ *    the caching of the ROM. However, it is set to uncacheable (UC). It
+ *    is the responsiblity of the caller to enable it by calling
+ *    x86_mtrr_enable_rom_caching().
+ */
+void x86_setup_mtrrs(void);
+/*
+ * x86_setup_var_mtrrs() parameters:
+ * address_bits - number of physical address bits supported by cpu
+ * above4gb - 2 means dynamically detect number of variable MTRRs available.
+ *            non-zero means handle memory ranges above 4GiB.
+ *            0 means ignore memory ranges above 4GiB
+ */
+void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb);
+void enable_fixed_mtrr(void);
+void x86_setup_fixed_mtrrs(void);
+/* Set up fixed MTRRs but do not enable them. */
+void x86_setup_fixed_mtrrs_no_enable(void);
+int x86_mtrr_check(void);
+/* ROM caching can be used after variable MTRRs are set up. Beware that
+ * enabling CONFIG_CACHE_ROM will eat through quite a few MTRRs based on
+ * one's IO hole size and WRCOMB resources. Be sure to check the console
+ * log when enabling CONFIG_CACHE_ROM or adding WRCOMB resources. Beware that
+ * on CPUs with core-scoped MTRR registers such as hyperthreaded CPUs the
+ * rom caching will be disabled if all threads run the MTRR code. Therefore,
+ * one needs to call x86_mtrr_enable_rom_caching() after all threads of the
+ * same core have run the MTRR code. */
+#if CONFIG_CACHE_ROM
+void x86_mtrr_enable_rom_caching(void);
+void x86_mtrr_disable_rom_caching(void);
+/* Return the variable range MTRR index of the ROM cache. */
+long x86_mtrr_rom_cache_var_index(void);
+#else
+static inline void x86_mtrr_enable_rom_caching(void) {}
+static inline void x86_mtrr_disable_rom_caching(void) {}
+static inline long x86_mtrr_rom_cache_var_index(void) { return -1; }
+#endif /* CONFIG_CACHE_ROM */
+
+#endif
+
+#if !defined(CONFIG_RAMTOP)
+# error "CONFIG_RAMTOP not defined"
+#endif
+
+#if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0)
+# error "CONFIG_XIP_ROM_SIZE is not a power of 2"
+#endif
+
+#if ((CONFIG_CACHE_ROM_SIZE & (CONFIG_CACHE_ROM_SIZE - 1)) != 0)
+# error "CONFIG_CACHE_ROM_SIZE is not a power of 2"
+#endif
+
+#define CACHE_ROM_BASE	(((1 << 20) - (CONFIG_CACHE_ROM_SIZE >> 12)) << 12)
+
+#if (CONFIG_RAMTOP & (CONFIG_RAMTOP - 1)) != 0
+# error "CONFIG_RAMTOP must be a power of 2"
+#endif
+
+#endif
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 6b16188..98817aa 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -12,5 +12,38 @@
 #define DEFINE_PCI_DEVICE_TABLE(_table) \
 	const struct pci_device_id _table[]
 
+struct pci_controller;
+
 void pci_setup_type1(struct pci_controller *hose);
+
+/**
+ * board_pci_setup_hose() - Set up the PCI hose
+ *
+ * This is called by the common x86 PCI code to set up the PCI controller
+ * hose. It may be called when no memory/BSS is available so should just
+ * store things in 'hose' and not in BSS variables.
+ */
+void board_pci_setup_hose(struct pci_controller *hose);
+
+/**
+ * pci_early_init_hose() - Set up PCI host before relocation
+ *
+ * This allocates memory for, sets up and returns the PCI hose. It can be
+ * called before relocation. The hose will be stored in gd->arch.hose for
+ * later use, but will become invalid one DRAM is available.
+ */
+int pci_early_init_hose(struct pci_controller **hosep);
+
+/*
+ * Simple PCI access routines - these work from either the early PCI hose
+ * or the 'real' one, created after U-Boot has memory available
+ */
+unsigned int pci_read_config8(pci_dev_t dev, unsigned where);
+unsigned int pci_read_config16(pci_dev_t dev, unsigned where);
+unsigned int pci_read_config32(pci_dev_t dev, unsigned where);
+
+void pci_write_config8(pci_dev_t dev, unsigned where, unsigned value);
+void pci_write_config16(pci_dev_t dev, unsigned where, unsigned value);
+void pci_write_config32(pci_dev_t dev, unsigned where, unsigned value);
+
 #endif
diff --git a/arch/x86/include/asm/post.h b/arch/x86/include/asm/post.h
new file mode 100644
index 0000000..ce68839
--- /dev/null
+++ b/arch/x86/include/asm/post.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _post_h
+#define _post_h
+
+/* port to use for post codes */
+#define POST_PORT		0x80
+
+/* post codes which represent various stages of init */
+#define POST_START		0x1e
+#define POST_CAR_START		0x1f
+#define POST_CAR_SIPI		0x20
+#define POST_CAR_MTRR		0x21
+#define POST_CAR_UNCACHEABLE	0x22
+#define POST_CAR_BASE_ADDRESS	0x23
+#define POST_CAR_MASK		0x24
+#define POST_CAR_FILL		0x25
+#define POST_CAR_ROM_CACHE	0x26
+#define POST_CAR_MRC_CACHE	0x27
+#define POST_CAR_CPU_CACHE	0x28
+#define POST_START_STACK	0x29
+#define POST_START_DONE		0x2a
+#define POST_CPU_INIT		0x2b
+#define POST_EARLY_INIT		0x2c
+#define POST_CPU_INFO		0x2d
+#define POST_PRE_MRC		0x2e
+#define POST_MRC		0x2f
+#define POST_DRAM		0x2f
+
+#define POST_RAM_FAILURE	0xea
+
+/* Output a post code using al - value must be 0 to 0xff */
+#ifdef __ASSEMBLY__
+#define post_code(value) \
+	movb	$value, %al; \
+	outb	%al, $POST_PORT
+#else
+#include <asm/io.h>
+
+static inline void post_code(int code)
+{
+	outb(code, POST_PORT);
+}
+#endif
+
+#endif
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index bb3172f..b9317cb 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -30,4 +30,25 @@
 
 #define X86_GDT_SIZE		(X86_GDT_NUM_ENTRIES * X86_GDT_ENTRY_SIZE)
 
+#ifndef __ASSEMBLY__
+
+#define PORT_RESET		0xcf9
+
+static inline __attribute__((always_inline)) void cpu_hlt(void)
+{
+	asm("hlt");
+}
+
+static inline ulong cpu_get_sp(void)
+{
+	ulong result;
+
+	asm volatile(
+		"mov %%esp, %%eax"
+		: "=a" (result));
+	return result;
+}
+
+#endif /* __ASSEMBLY__ */
+
 #endif
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 9e525dd..98217dd 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -9,6 +9,7 @@
 #define _U_BOOT_I386_H_	1
 
 /* cpu/.../cpu.c */
+int arch_cpu_init(void);
 int x86_cpu_init_r(void);
 int cpu_init_r(void);
 int x86_cpu_init_f(void);
@@ -27,8 +28,8 @@
 void timer_set_base(uint64_t base);
 int pcat_timer_init(void);
 
-/* Architecture specific - can be in arch/x86/cpu/, arch/x86/lib/, or $(BOARD)/ */
-int dram_init_f(void);
+/* Architecture specific DRAM init */
+int dram_init(void);
 
 /* cpu/.../interrupts.c */
 int cpu_init_interrupts(void);
@@ -36,6 +37,16 @@
 /* board/.../... */
 int dram_init(void);
 
+int cleanup_before_linux(void);
+int x86_cleanup_before_linux(void);
+void x86_enable_caches(void);
+void x86_disable_caches(void);
+int x86_init_cache(void);
+void reset_cpu(ulong addr);
+ulong board_get_usable_ram_top(ulong total_size);
+void dram_init_banksize(void);
+int default_print_cpuinfo(void);
+
 void setup_pcat_compatibility(void);
 
 void isa_unmap_rom(u32 addr);
@@ -59,4 +70,6 @@
 void timer_set_tsc_base(uint64_t new_base);
 uint64_t timer_get_tsc(void);
 
+void quick_ram_check(void);
+
 #endif	/* _U_BOOT_I386_H_ */
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 25b672a..e146e64 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_PCI) += pci_type1.o
 obj-y	+= relocate.o
 obj-y += physmem.o
+obj-$(CONFIG_X86_RAMTEST) += ramtest.o
 obj-y	+= string.o
 obj-$(CONFIG_SYS_X86_TSC_TIMER)	+= tsc_timer.o
 obj-$(CONFIG_VIDEO_VGA)	+= video.o
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index b5d937f..be4eb12 100644
--- a/arch/x86/lib/init_helpers.c
+++ b/arch/x86/lib/init_helpers.c
@@ -87,30 +87,3 @@
 	puts("ready\n");
 	return 0;
 }
-
-int find_fdt(void)
-{
-#ifdef CONFIG_OF_EMBED
-	/* Get a pointer to the FDT */
-	gd->fdt_blob = __dtb_dt_begin;
-#elif defined CONFIG_OF_SEPARATE
-	/* FDT is at end of image */
-	gd->fdt_blob = (ulong *)&_end;
-#endif
-	/* Allow the early environment to override the fdt address */
-	gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
-						(uintptr_t)gd->fdt_blob);
-
-	return 0;
-}
-
-int prepare_fdt(void)
-{
-	/* For now, put this check after the console is ready */
-	if (fdtdec_prepare_fdt()) {
-		panic("** CONFIG_OF_CONTROL defined but no FDT - please see "
-			"doc/README.fdt-control");
-	}
-
-	return 0;
-}
diff --git a/arch/x86/lib/ramtest.c b/arch/x86/lib/ramtest.c
new file mode 100644
index 0000000..c21be03
--- /dev/null
+++ b/arch/x86/lib/ramtest.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * From Coreboot src/lib/ramtest.c
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/post.h>
+
+static void write_phys(unsigned long addr, u32 value)
+{
+#if CONFIG_SSE2
+	asm volatile(
+		"movnti %1, (%0)"
+		: /* outputs */
+		: "r" (addr), "r" (value) /* inputs */
+		: /* clobbers */
+		);
+#else
+	writel(value, addr);
+#endif
+}
+
+static u32 read_phys(unsigned long addr)
+{
+	return readl(addr);
+}
+
+static void phys_memory_barrier(void)
+{
+#if CONFIG_SSE2
+	/* Needed for movnti */
+	asm volatile(
+		"sfence"
+		:
+		:
+		: "memory"
+	);
+#else
+	asm volatile(""
+		:
+		:
+		: "memory");
+#endif
+}
+
+void quick_ram_check(void)
+{
+	int fail = 0;
+	u32 backup;
+
+	backup = read_phys(CONFIG_RAMBASE);
+	write_phys(CONFIG_RAMBASE, 0x55555555);
+	phys_memory_barrier();
+	if (read_phys(CONFIG_RAMBASE) != 0x55555555)
+		fail = 1;
+	write_phys(CONFIG_RAMBASE, 0xaaaaaaaa);
+	phys_memory_barrier();
+	if (read_phys(CONFIG_RAMBASE) != 0xaaaaaaaa)
+		fail = 1;
+	write_phys(CONFIG_RAMBASE, 0x00000000);
+	phys_memory_barrier();
+	if (read_phys(CONFIG_RAMBASE) != 0x00000000)
+		fail = 1;
+	write_phys(CONFIG_RAMBASE, 0xffffffff);
+	phys_memory_barrier();
+	if (read_phys(CONFIG_RAMBASE) != 0xffffffff)
+		fail = 1;
+
+	write_phys(CONFIG_RAMBASE, backup);
+	if (fail) {
+		post_code(POST_RAM_FAILURE);
+		panic("RAM INIT FAILURE!\n");
+	}
+	phys_memory_barrier();
+}
diff --git a/arch/x86/lib/tsc_timer.c b/arch/x86/lib/tsc_timer.c
index 8b38702..fb9afed 100644
--- a/arch/x86/lib/tsc_timer.c
+++ b/arch/x86/lib/tsc_timer.c
@@ -1,6 +1,9 @@
 /*
  * Copyright (c) 2012 The Chromium OS Authors.
  *
+ * TSC calibration codes are adapted from Linux kernel
+ * arch/x86/kernel/tsc_msr.c and arch/x86/kernel/tsc.c
+ *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
@@ -12,8 +15,269 @@
 #include <asm/msr.h>
 #include <asm/u-boot-x86.h>
 
+/* CPU reference clock frequency: in KHz */
+#define FREQ_83		83200
+#define FREQ_100	99840
+#define FREQ_133	133200
+#define FREQ_166	166400
+
+#define MAX_NUM_FREQS	8
+
 DECLARE_GLOBAL_DATA_PTR;
 
+/*
+ * According to Intel 64 and IA-32 System Programming Guide,
+ * if MSR_PERF_STAT[31] is set, the maximum resolved bus ratio can be
+ * read in MSR_PLATFORM_ID[12:8], otherwise in MSR_PERF_STAT[44:40].
+ * Unfortunately some Intel Atom SoCs aren't quite compliant to this,
+ * so we need manually differentiate SoC families. This is what the
+ * field msr_plat does.
+ */
+struct freq_desc {
+	u8 x86_family;	/* CPU family */
+	u8 x86_model;	/* model */
+	/* 2: use 100MHz, 1: use MSR_PLATFORM_INFO, 0: MSR_IA32_PERF_STATUS */
+	u8 msr_plat;
+	u32 freqs[MAX_NUM_FREQS];
+};
+
+static struct freq_desc freq_desc_tables[] = {
+	/* PNW */
+	{ 6, 0x27, 0, { 0, 0, 0, 0, 0, FREQ_100, 0, FREQ_83 } },
+	/* CLV+ */
+	{ 6, 0x35, 0, { 0, FREQ_133, 0, 0, 0, FREQ_100, 0, FREQ_83 } },
+	/* TNG */
+	{ 6, 0x4a, 1, { 0, FREQ_100, FREQ_133, 0, 0, 0, 0, 0 } },
+	/* VLV2 */
+	{ 6, 0x37, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } },
+	/* Ivybridge */
+	{ 6, 0x3a, 2, { 0, 0, 0, 0, 0, 0, 0, 0 } },
+	/* ANN */
+	{ 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } },
+};
+
+static int match_cpu(u8 family, u8 model)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(freq_desc_tables); i++) {
+		if ((family == freq_desc_tables[i].x86_family) &&
+		    (model == freq_desc_tables[i].x86_model))
+			return i;
+	}
+
+	return -1;
+}
+
+/* Map CPU reference clock freq ID(0-7) to CPU reference clock freq(KHz) */
+#define id_to_freq(cpu_index, freq_id) \
+	(freq_desc_tables[cpu_index].freqs[freq_id])
+
+/*
+ * Do MSR calibration only for known/supported CPUs.
+ *
+ * Returns the calibration value or 0 if MSR calibration failed.
+ */
+static unsigned long try_msr_calibrate_tsc(void)
+{
+	u32 lo, hi, ratio, freq_id, freq;
+	unsigned long res;
+	int cpu_index;
+
+	cpu_index = match_cpu(gd->arch.x86, gd->arch.x86_model);
+	if (cpu_index < 0)
+		return 0;
+
+	if (freq_desc_tables[cpu_index].msr_plat) {
+		rdmsr(MSR_PLATFORM_INFO, lo, hi);
+		ratio = (lo >> 8) & 0x1f;
+	} else {
+		rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+		ratio = (hi >> 8) & 0x1f;
+	}
+	debug("Maximum core-clock to bus-clock ratio: 0x%x\n", ratio);
+
+	if (!ratio)
+		goto fail;
+
+	if (freq_desc_tables[cpu_index].msr_plat == 2) {
+		/* TODO: Figure out how best to deal with this */
+		freq = FREQ_100;
+		debug("Using frequency: %u KHz\n", freq);
+	} else {
+		/* Get FSB FREQ ID */
+		rdmsr(MSR_FSB_FREQ, lo, hi);
+		freq_id = lo & 0x7;
+		freq = id_to_freq(cpu_index, freq_id);
+		debug("Resolved frequency ID: %u, frequency: %u KHz\n",
+		      freq_id, freq);
+	}
+	if (!freq)
+		goto fail;
+
+	/* TSC frequency = maximum resolved freq * maximum resolved bus ratio */
+	res = freq * ratio / 1000;
+	debug("TSC runs at %lu MHz\n", res);
+
+	return res;
+
+fail:
+	debug("Fast TSC calibration using MSR failed\n");
+	return 0;
+}
+
+/*
+ * This reads the current MSB of the PIT counter, and
+ * checks if we are running on sufficiently fast and
+ * non-virtualized hardware.
+ *
+ * Our expectations are:
+ *
+ *  - the PIT is running at roughly 1.19MHz
+ *
+ *  - each IO is going to take about 1us on real hardware,
+ *    but we allow it to be much faster (by a factor of 10) or
+ *    _slightly_ slower (ie we allow up to a 2us read+counter
+ *    update - anything else implies a unacceptably slow CPU
+ *    or PIT for the fast calibration to work.
+ *
+ *  - with 256 PIT ticks to read the value, we have 214us to
+ *    see the same MSB (and overhead like doing a single TSC
+ *    read per MSB value etc).
+ *
+ *  - We're doing 2 reads per loop (LSB, MSB), and we expect
+ *    them each to take about a microsecond on real hardware.
+ *    So we expect a count value of around 100. But we'll be
+ *    generous, and accept anything over 50.
+ *
+ *  - if the PIT is stuck, and we see *many* more reads, we
+ *    return early (and the next caller of pit_expect_msb()
+ *    then consider it a failure when they don't see the
+ *    next expected value).
+ *
+ * These expectations mean that we know that we have seen the
+ * transition from one expected value to another with a fairly
+ * high accuracy, and we didn't miss any events. We can thus
+ * use the TSC value at the transitions to calculate a pretty
+ * good value for the TSC frequencty.
+ */
+static inline int pit_verify_msb(unsigned char val)
+{
+	/* Ignore LSB */
+	inb(0x42);
+	return inb(0x42) == val;
+}
+
+static inline int pit_expect_msb(unsigned char val, u64 *tscp,
+				 unsigned long *deltap)
+{
+	int count;
+	u64 tsc = 0, prev_tsc = 0;
+
+	for (count = 0; count < 50000; count++) {
+		if (!pit_verify_msb(val))
+			break;
+		prev_tsc = tsc;
+		tsc = rdtsc();
+	}
+	*deltap = rdtsc() - prev_tsc;
+	*tscp = tsc;
+
+	/*
+	 * We require _some_ success, but the quality control
+	 * will be based on the error terms on the TSC values.
+	 */
+	return count > 5;
+}
+
+/*
+ * How many MSB values do we want to see? We aim for
+ * a maximum error rate of 500ppm (in practice the
+ * real error is much smaller), but refuse to spend
+ * more than 50ms on it.
+ */
+#define MAX_QUICK_PIT_MS 50
+#define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
+
+static unsigned long quick_pit_calibrate(void)
+{
+	int i;
+	u64 tsc, delta;
+	unsigned long d1, d2;
+
+	/* Set the Gate high, disable speaker */
+	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+
+	/*
+	 * Counter 2, mode 0 (one-shot), binary count
+	 *
+	 * NOTE! Mode 2 decrements by two (and then the
+	 * output is flipped each time, giving the same
+	 * final output frequency as a decrement-by-one),
+	 * so mode 0 is much better when looking at the
+	 * individual counts.
+	 */
+	outb(0xb0, 0x43);
+
+	/* Start at 0xffff */
+	outb(0xff, 0x42);
+	outb(0xff, 0x42);
+
+	/*
+	 * The PIT starts counting at the next edge, so we
+	 * need to delay for a microsecond. The easiest way
+	 * to do that is to just read back the 16-bit counter
+	 * once from the PIT.
+	 */
+	pit_verify_msb(0);
+
+	if (pit_expect_msb(0xff, &tsc, &d1)) {
+		for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) {
+			if (!pit_expect_msb(0xff-i, &delta, &d2))
+				break;
+
+			/*
+			 * Iterate until the error is less than 500 ppm
+			 */
+			delta -= tsc;
+			if (d1+d2 >= delta >> 11)
+				continue;
+
+			/*
+			 * Check the PIT one more time to verify that
+			 * all TSC reads were stable wrt the PIT.
+			 *
+			 * This also guarantees serialization of the
+			 * last cycle read ('d2') in pit_expect_msb.
+			 */
+			if (!pit_verify_msb(0xfe - i))
+				break;
+			goto success;
+		}
+	}
+	debug("Fast TSC calibration failed\n");
+	return 0;
+
+success:
+	/*
+	 * Ok, if we get here, then we've seen the
+	 * MSB of the PIT decrement 'i' times, and the
+	 * error has shrunk to less than 500 ppm.
+	 *
+	 * As a result, we can depend on there not being
+	 * any odd delays anywhere, and the TSC reads are
+	 * reliable (within the error).
+	 *
+	 * kHz = ticks / time-in-seconds / 1000;
+	 * kHz = (t2 - t1) / (I * 256 / PIT_TICK_RATE) / 1000
+	 * kHz = ((t2 - t1) * PIT_TICK_RATE) / (I * 256 * 1000)
+	 */
+	delta *= PIT_TICK_RATE;
+	delta /= (i*256*1000);
+	debug("Fast TSC calibration using PIT\n");
+	return delta / 1000;
+}
+
 void timer_set_base(u64 base)
 {
 	gd->arch.tsc_base = base;
@@ -34,17 +298,24 @@
 	return now_tick - gd->arch.tsc_base;
 }
 
-#define PLATFORM_INFO_MSR 0xce
-
 /* Get the speed of the TSC timer in MHz */
 unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void)
 {
-	u32 ratio;
-	u64 platform_info = native_read_msr(PLATFORM_INFO_MSR);
+	unsigned long fast_calibrate;
 
-	/* 100MHz times Max Non Turbo ratio */
-	ratio = (platform_info >> 8) & 0xff;
-	return 100 * ratio;
+	if (gd->arch.tsc_mhz)
+		return gd->arch.tsc_mhz;
+
+	fast_calibrate = try_msr_calibrate_tsc();
+	if (!fast_calibrate) {
+
+		fast_calibrate = quick_pit_calibrate();
+		if (!fast_calibrate)
+			panic("TSC frequency is ZERO");
+	}
+
+	gd->arch.tsc_mhz = fast_calibrate;
+	return fast_calibrate;
 }
 
 unsigned long get_tbclk(void)
diff --git a/board/chromebook-x86/coreboot/Kconfig b/board/coreboot/coreboot/Kconfig
similarity index 86%
rename from board/chromebook-x86/coreboot/Kconfig
rename to board/coreboot/coreboot/Kconfig
index 83385c7..6ca6ced 100644
--- a/board/chromebook-x86/coreboot/Kconfig
+++ b/board/coreboot/coreboot/Kconfig
@@ -4,7 +4,7 @@
 	default "coreboot"
 
 config SYS_VENDOR
-	default "chromebook-x86"
+	default "coreboot"
 
 config SYS_SOC
 	default "coreboot"
diff --git a/board/chromebook-x86/coreboot/MAINTAINERS b/board/coreboot/coreboot/MAINTAINERS
similarity index 78%
rename from board/chromebook-x86/coreboot/MAINTAINERS
rename to board/coreboot/coreboot/MAINTAINERS
index 3b2fb52..6ce66f5 100644
--- a/board/chromebook-x86/coreboot/MAINTAINERS
+++ b/board/coreboot/coreboot/MAINTAINERS
@@ -1,6 +1,6 @@
 COREBOOT BOARD
 M:	Simon Glass <sjg@chromium.org>
 S:	Maintained
-F:	board/chromebook-x86/coreboot/
+F:	board/coreboot/coreboot/
 F:	include/configs/coreboot.h
 F:	configs/coreboot-x86_defconfig
diff --git a/board/chromebook-x86/coreboot/Makefile b/board/coreboot/coreboot/Makefile
similarity index 100%
rename from board/chromebook-x86/coreboot/Makefile
rename to board/coreboot/coreboot/Makefile
diff --git a/board/chromebook-x86/coreboot/coreboot.c b/board/coreboot/coreboot/coreboot.c
similarity index 100%
rename from board/chromebook-x86/coreboot/coreboot.c
rename to board/coreboot/coreboot/coreboot.c
diff --git a/board/chromebook-x86/coreboot/coreboot_start.S b/board/coreboot/coreboot/coreboot_start.S
similarity index 100%
rename from board/chromebook-x86/coreboot/coreboot_start.S
rename to board/coreboot/coreboot/coreboot_start.S
diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig
new file mode 100644
index 0000000..3a4f557
--- /dev/null
+++ b/board/google/chromebook_link/Kconfig
@@ -0,0 +1,31 @@
+if TARGET_CHROMEBOOK_LINK
+
+config SYS_BOARD
+	default "chromebook_link"
+
+config SYS_VENDOR
+	default "google"
+
+config SYS_SOC
+	default "ivybridge"
+
+config SYS_CONFIG_NAME
+	default "chromebook_link"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	select CPU_INTEL_SOCKET_RPGA989
+	select NORTHBRIDGE_INTEL_IVYBRIDGE
+	select SOUTHBRIDGE_INTEL_C216
+	select HAVE_ACPI_RESUME
+	select MARK_GRAPHICS_MEM_WRCOMB
+
+config MMCONF_BASE_ADDRESS
+	hex
+	default 0xf0000000
+
+config EARLY_POST_CROS_EC
+	bool "Enable early post to Chrome OS EC"
+	default y
+
+endif
diff --git a/board/google/chromebook_link/MAINTAINERS b/board/google/chromebook_link/MAINTAINERS
new file mode 100644
index 0000000..bc253a2
--- /dev/null
+++ b/board/google/chromebook_link/MAINTAINERS
@@ -0,0 +1,6 @@
+CHROMEBOOK LINK BOARD
+M:	Simon Glass <sjg@chromium.org>
+S:	Maintained
+F:	board/google/chromebook_link/
+F:	include/configs/chromebook_link.h
+F:	configs/chromebook_link_defconfig
diff --git a/board/google/chromebook_link/Makefile b/board/google/chromebook_link/Makefile
new file mode 100644
index 0000000..a133c2e
--- /dev/null
+++ b/board/google/chromebook_link/Makefile
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2011 The Chromium OS Authors.
+# (C) Copyright 2008
+# Graeme Russ, graeme.russ@gmail.com.
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2002
+# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	+= link.o
diff --git a/board/google/chromebook_link/link.c b/board/google/chromebook_link/link.c
new file mode 100644
index 0000000..88cee05
--- /dev/null
+++ b/board/google/chromebook_link/link.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+
+int arch_early_init_r(void)
+{
+	return 0;
+}
+
+int board_early_init_r(void)
+{
+	return 0;
+}
+
+static const struct pch_gpio_set1 pch_gpio_set1_mode = {
+	.gpio0 = GPIO_MODE_GPIO,  /* NMI_DBG# */
+	.gpio3 = GPIO_MODE_GPIO,  /* ALS_INT# */
+	.gpio5 = GPIO_MODE_GPIO,  /* SIM_DET */
+	.gpio7 = GPIO_MODE_GPIO,  /* EC_SCI# */
+	.gpio8 = GPIO_MODE_GPIO,  /* EC_SMI# */
+	.gpio9 = GPIO_MODE_GPIO,  /* RECOVERY# */
+	.gpio10 = GPIO_MODE_GPIO, /* SPD vector D3 */
+	.gpio11 = GPIO_MODE_GPIO, /* smbalert#, let's keep it initialized */
+	.gpio12 = GPIO_MODE_GPIO, /* TP_INT# */
+	.gpio14 = GPIO_MODE_GPIO, /* Touch_INT_L */
+	.gpio15 = GPIO_MODE_GPIO, /* EC_LID_OUT# (EC_WAKE#) */
+	.gpio21 = GPIO_MODE_GPIO, /* EC_IN_RW */
+	.gpio24 = GPIO_MODE_GPIO, /* DDR3L_EN */
+	.gpio28 = GPIO_MODE_GPIO, /* SLP_ME_CSW_DEV# */
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_direction = {
+	.gpio0 = GPIO_DIR_INPUT,
+	.gpio3 = GPIO_DIR_INPUT,
+	.gpio5 = GPIO_DIR_INPUT,
+	.gpio7 = GPIO_DIR_INPUT,
+	.gpio8 = GPIO_DIR_INPUT,
+	.gpio9 = GPIO_DIR_INPUT,
+	.gpio10 = GPIO_DIR_INPUT,
+	.gpio11 = GPIO_DIR_INPUT,
+	.gpio12 = GPIO_DIR_INPUT,
+	.gpio14 = GPIO_DIR_INPUT,
+	.gpio15 = GPIO_DIR_INPUT,
+	.gpio21 = GPIO_DIR_INPUT,
+	.gpio24 = GPIO_DIR_OUTPUT,
+	.gpio28 = GPIO_DIR_INPUT,
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_level = {
+	.gpio1 = GPIO_LEVEL_HIGH,
+	.gpio6 = GPIO_LEVEL_HIGH,
+	.gpio24 = GPIO_LEVEL_LOW,
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_invert = {
+	.gpio7 = GPIO_INVERT,
+	.gpio8 = GPIO_INVERT,
+	.gpio12 = GPIO_INVERT,
+	.gpio14 = GPIO_INVERT,
+	.gpio15 = GPIO_INVERT,
+};
+
+static const struct pch_gpio_set2 pch_gpio_set2_mode = {
+	.gpio36 = GPIO_MODE_GPIO, /* W_DISABLE_L */
+	.gpio41 = GPIO_MODE_GPIO, /* SPD vector D0 */
+	.gpio42 = GPIO_MODE_GPIO, /* SPD vector D1 */
+	.gpio43 = GPIO_MODE_GPIO, /* SPD vector D2 */
+	.gpio57 = GPIO_MODE_GPIO, /* PCH_SPI_WP_D */
+	.gpio60 = GPIO_MODE_GPIO, /* DRAMRST_CNTRL_PCH */
+};
+
+static const struct pch_gpio_set2 pch_gpio_set2_direction = {
+	.gpio36 = GPIO_DIR_OUTPUT,
+	.gpio41 = GPIO_DIR_INPUT,
+	.gpio42 = GPIO_DIR_INPUT,
+	.gpio43 = GPIO_DIR_INPUT,
+	.gpio57 = GPIO_DIR_INPUT,
+	.gpio60 = GPIO_DIR_OUTPUT,
+};
+
+static const struct pch_gpio_set2 pch_gpio_set2_level = {
+	.gpio36 = GPIO_LEVEL_HIGH,
+	.gpio60 = GPIO_LEVEL_HIGH,
+};
+
+static const struct pch_gpio_set3 pch_gpio_set3_mode = {
+};
+
+static const struct pch_gpio_set3 pch_gpio_set3_direction = {
+};
+
+static const struct pch_gpio_set3 pch_gpio_set3_level = {
+};
+
+static const struct pch_gpio_map link_gpio_map = {
+	.set1 = {
+		.mode      = &pch_gpio_set1_mode,
+		.direction = &pch_gpio_set1_direction,
+		.level     = &pch_gpio_set1_level,
+		.invert    = &pch_gpio_set1_invert,
+	},
+	.set2 = {
+		.mode      = &pch_gpio_set2_mode,
+		.direction = &pch_gpio_set2_direction,
+		.level     = &pch_gpio_set2_level,
+	},
+	.set3 = {
+		.mode      = &pch_gpio_set3_mode,
+		.direction = &pch_gpio_set3_direction,
+		.level     = &pch_gpio_set3_level,
+	},
+};
+
+int board_early_init_f(void)
+{
+	ich_gpio_set_gpio_map(&link_gpio_map);
+
+	return 0;
+}
diff --git a/board/google/common/Makefile b/board/google/common/Makefile
new file mode 100644
index 0000000..b38bc14
--- /dev/null
+++ b/board/google/common/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2014 Google, Inc
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += early_init.o
diff --git a/board/google/common/early_init.S b/board/google/common/early_init.S
new file mode 100644
index 0000000..7017185
--- /dev/null
+++ b/board/google/common/early_init.S
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+.globl early_board_init
+early_board_init:
+	/* Enable post codes to EC */
+#ifdef CONFIG_EARLY_POST_CROS_EC
+	mov    $0x1b, %ecx
+	rdmsr
+	and    $0x100, %eax
+	test   %eax, %eax
+	je     1f
+
+	mov    $0x8000f8f0, %eax
+	mov    $0xcf8, %dx
+	out    %eax, (%dx)
+	mov    $0xfed1c001, %eax
+	mov    $0xcfc, %dx
+	out    %eax, (%dx)
+	mov    $0xfed1f410, %esp
+	mov    (%esp), %eax
+	and    $0xfffffffb, %eax
+	mov    %eax, (%esp)
+1:
+#endif
+	jmp	early_board_init_ret
diff --git a/common/board_f.c b/common/board_f.c
index c6e38f3..f8fd324 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -820,22 +820,16 @@
 	setup_mon_len,
 	setup_fdt,
 	trace_early_init,
+	initf_malloc,
 #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
 	/* TODO: can this go into arch_cpu_init()? */
 	probecpu,
 #endif
 	arch_cpu_init,		/* basic arch cpu dependent setup */
-#ifdef CONFIG_X86
-	cpu_init_f,		/* TODO(sjg@chromium.org): remove */
-# ifdef CONFIG_OF_CONTROL
-	find_fdt,		/* TODO(sjg@chromium.org): remove */
-# endif
-#endif
 	mark_bootstage,
 #ifdef CONFIG_OF_CONTROL
 	fdtdec_check_fdt,
 #endif
-	initf_malloc,
 	initf_dm,
 #if defined(CONFIG_BOARD_EARLY_INIT_F)
 	board_early_init_f,
@@ -911,13 +905,9 @@
 #if defined(CONFIG_HARD_SPI)
 	init_func_spi,
 #endif
-#ifdef CONFIG_X86
-	dram_init_f,		/* configure available RAM banks */
-	calculate_relocation_address,
-#endif
 	announce_dram_init,
 	/* TODO: unify all these dram functions? */
-#ifdef CONFIG_ARM
+#if defined(CONFIG_ARM) || defined(CONFIG_X86)
 	dram_init,		/* configure available RAM banks */
 #endif
 #if defined(CONFIG_MIPS) || defined(CONFIG_PPC)
diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig
new file mode 100644
index 0000000..b83803e
--- /dev/null
+++ b/configs/chromebook_link_defconfig
@@ -0,0 +1,10 @@
+CONFIG_SYS_EXTRA_OPTIONS="SYS_TEXT_BASE=0xfff00000"
+CONFIG_X86=y
+CONFIG_TARGET_CHROMEBOOK_LINK=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_SEPARATE=y
+CONFIG_DEFAULT_DEVICE_TREE="chromebook_link"
+CONFIG_HAVE_MRC=y
+CONFIG_SMM_TSEG_SIZE=0x800000
+CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
+CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
diff --git a/doc/device-tree-bindings/misc/intel-lpc.txt b/doc/device-tree-bindings/misc/intel-lpc.txt
new file mode 100644
index 0000000..7e1b389
--- /dev/null
+++ b/doc/device-tree-bindings/misc/intel-lpc.txt
@@ -0,0 +1,23 @@
+Intel LPC Device Binding
+========================
+
+The device tree node which describes the operation of the Intel Low Pin
+Count device is as follows:
+
+Required properties :
+- compatible = "intel,lpc"
+- gen-dec : Specifies the values for the gen-dec registers. Up to four cell
+   pairs can be provided - the first of each pair is the base address and
+   the second is the size. These are written into the GENx_DEC registers of
+   the LPC device
+
+
+Example
+-------
+
+lpc {
+	compatible = "intel,lpc";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	gen-dec = <0x800 0xfc 0x900 0xfc>;
+};
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 45e9a5a..255700a 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -390,6 +390,25 @@
 	return 0;
 }
 
+/*
+ * get a number comprised of multiple GPIO values. gpio_num_array points to
+ * the array of gpio pin numbers to scan, terminated by -1.
+ */
+unsigned gpio_get_values_as_int(const int *gpio_num_array)
+{
+	int gpio;
+	unsigned bitmask = 1;
+	unsigned vector = 0;
+
+	while (bitmask &&
+	       ((gpio = *gpio_num_array++) != -1)) {
+		if (gpio_get_value(gpio))
+			vector |= bitmask;
+		bitmask <<= 1;
+	}
+	return vector;
+}
+
 /* We need to renumber the GPIOs when any driver is probed/removed */
 static int gpio_renumber(struct udevice *removed_dev)
 {
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index d3381b0..b095d17 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -33,6 +33,11 @@
 #include <pci.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
+#include <asm/pci.h>
+#ifdef CONFIG_X86_RESET_VECTOR
+#include <asm/arch/pch.h>
+#define SUPPORT_GPIO_SETUP
+#endif
 
 #define GPIO_PER_BANK	32
 
@@ -46,6 +51,53 @@
 	uint32_t lvl;
 };
 
+#ifdef SUPPORT_GPIO_SETUP
+static void setup_pch_gpios(const struct pch_gpio_map *gpio)
+{
+	u16 gpiobase = pci_read_config16(PCH_LPC_DEV, GPIO_BASE) & 0xfffc;
+
+	/* GPIO Set 1 */
+	if (gpio->set1.level)
+		outl(*((u32 *)gpio->set1.level), gpiobase + GP_LVL);
+	if (gpio->set1.mode)
+		outl(*((u32 *)gpio->set1.mode), gpiobase + GPIO_USE_SEL);
+	if (gpio->set1.direction)
+		outl(*((u32 *)gpio->set1.direction), gpiobase + GP_IO_SEL);
+	if (gpio->set1.reset)
+		outl(*((u32 *)gpio->set1.reset), gpiobase + GP_RST_SEL1);
+	if (gpio->set1.invert)
+		outl(*((u32 *)gpio->set1.invert), gpiobase + GPI_INV);
+	if (gpio->set1.blink)
+		outl(*((u32 *)gpio->set1.blink), gpiobase + GPO_BLINK);
+
+	/* GPIO Set 2 */
+	if (gpio->set2.level)
+		outl(*((u32 *)gpio->set2.level), gpiobase + GP_LVL2);
+	if (gpio->set2.mode)
+		outl(*((u32 *)gpio->set2.mode), gpiobase + GPIO_USE_SEL2);
+	if (gpio->set2.direction)
+		outl(*((u32 *)gpio->set2.direction), gpiobase + GP_IO_SEL2);
+	if (gpio->set2.reset)
+		outl(*((u32 *)gpio->set2.reset), gpiobase + GP_RST_SEL2);
+
+	/* GPIO Set 3 */
+	if (gpio->set3.level)
+		outl(*((u32 *)gpio->set3.level), gpiobase + GP_LVL3);
+	if (gpio->set3.mode)
+		outl(*((u32 *)gpio->set3.mode), gpiobase + GPIO_USE_SEL3);
+	if (gpio->set3.direction)
+		outl(*((u32 *)gpio->set3.direction), gpiobase + GP_IO_SEL3);
+	if (gpio->set3.reset)
+		outl(*((u32 *)gpio->set3.reset), gpiobase + GP_RST_SEL3);
+}
+
+/* TODO: Move this to device tree, or platform data */
+void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
+{
+	gd->arch.gpio_map = map;
+}
+#endif /* SUPPORT_GPIO_SETUP */
+
 static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
 {
 	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
@@ -60,13 +112,13 @@
 	pci_dev = PCI_BDF(0, 0x1f, 0);
 
 	/* Is the device present? */
-	pci_read_config_word(pci_dev, PCI_VENDOR_ID, &tmpword);
+	tmpword = pci_read_config16(pci_dev, PCI_VENDOR_ID);
 	if (tmpword != PCI_VENDOR_ID_INTEL) {
 		debug("%s: wrong VendorID\n", __func__);
 		return -ENODEV;
 	}
 
-	pci_read_config_word(pci_dev, PCI_DEVICE_ID, &tmpword);
+	tmpword = pci_read_config16(pci_dev, PCI_DEVICE_ID);
 	debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword);
 	/*
 	 * We'd like to validate the Device ID too, but pretty much any
@@ -76,34 +128,34 @@
 	 */
 
 	/* I/O should already be enabled (it's a RO bit). */
-	pci_read_config_word(pci_dev, PCI_COMMAND, &tmpword);
+	tmpword = pci_read_config16(pci_dev, PCI_COMMAND);
 	if (!(tmpword & PCI_COMMAND_IO)) {
 		debug("%s: device IO not enabled\n", __func__);
 		return -ENODEV;
 	}
 
 	/* Header Type must be normal (bits 6-0 only; see spec.) */
-	pci_read_config_byte(pci_dev, PCI_HEADER_TYPE, &tmpbyte);
+	tmpbyte = pci_read_config8(pci_dev, PCI_HEADER_TYPE);
 	if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
 		debug("%s: invalid Header type\n", __func__);
 		return -ENODEV;
 	}
 
 	/* Base Class must be a bridge device */
-	pci_read_config_byte(pci_dev, PCI_CLASS_CODE, &tmpbyte);
+	tmpbyte = pci_read_config8(pci_dev, PCI_CLASS_CODE);
 	if (tmpbyte != PCI_CLASS_CODE_BRIDGE) {
 		debug("%s: invalid class\n", __func__);
 		return -ENODEV;
 	}
 	/* Sub Class must be ISA */
-	pci_read_config_byte(pci_dev, PCI_CLASS_SUB_CODE, &tmpbyte);
+	tmpbyte = pci_read_config8(pci_dev, PCI_CLASS_SUB_CODE);
 	if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) {
 		debug("%s: invalid subclass\n", __func__);
 		return -ENODEV;
 	}
 
 	/* Programming Interface must be 0x00 (no others exist) */
-	pci_read_config_byte(pci_dev, PCI_CLASS_PROG, &tmpbyte);
+	tmpbyte = pci_read_config8(pci_dev, PCI_CLASS_PROG);
 	if (tmpbyte != 0x00) {
 		debug("%s: invalid interface type\n", __func__);
 		return -ENODEV;
@@ -114,7 +166,7 @@
 	 * that it was unused (or undocumented). Check that it looks
 	 * okay: not all ones or zeros, and mapped to I/O space (bit 0).
 	 */
-	pci_read_config_dword(pci_dev, PCI_CFG_GPIOBASE, &tmplong);
+	tmplong = pci_read_config32(pci_dev, PCI_CFG_GPIOBASE);
 	if (tmplong == 0x00000000 || tmplong == 0xffffffff ||
 	    !(tmplong & 0x00000001)) {
 		debug("%s: unexpected GPIOBASE value\n", __func__);
@@ -140,12 +192,18 @@
 	return 0;
 }
 
-int ich6_gpio_probe(struct udevice *dev)
+static int ich6_gpio_probe(struct udevice *dev)
 {
 	struct ich6_bank_platdata *plat = dev_get_platdata(dev);
 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
 
+#ifdef SUPPORT_GPIO_SETUP
+	if (gd->arch.gpio_map) {
+		setup_pch_gpios(gd->arch.gpio_map);
+		gd->arch.gpio_map = NULL;
+	}
+#endif
 	uc_priv->gpio_count = GPIO_PER_BANK;
 	uc_priv->bank_name = plat->bank_name;
 	bank->use_sel = plat->base_addr;
@@ -155,7 +213,8 @@
 	return 0;
 }
 
-int ich6_gpio_request(struct udevice *dev, unsigned offset, const char *label)
+static int ich6_gpio_request(struct udevice *dev, unsigned offset,
+			     const char *label)
 {
 	struct ich6_bank_priv *bank = dev_get_priv(dev);
 	u32 tmplong;
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 71f1a5c..0f019c8 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -19,15 +19,14 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-/* The currently-selected console serial device */
-struct udevice *cur_dev __attribute__ ((section(".data")));
-
 #ifndef CONFIG_SYS_MALLOC_F_LEN
 #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work"
 #endif
 
 static void serial_find_console_or_panic(void)
 {
+	struct udevice *dev;
+
 #ifdef CONFIG_OF_CONTROL
 	int node;
 
@@ -35,18 +34,21 @@
 	node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path");
 	if (node < 0)
 		node = fdtdec_get_alias_node(gd->fdt_blob, "console");
-	if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &cur_dev))
+	if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &dev)) {
+		gd->cur_serial_dev = dev;
 		return;
+	}
 
 	/*
 	 * If the console is not marked to be bound before relocation, bind
 	 * it anyway.
 	 */
 	if (node > 0 &&
-	    !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &cur_dev)) {
-		if (!device_probe(cur_dev))
+	    !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &dev)) {
+		if (!device_probe(dev)) {
+			gd->cur_serial_dev = dev;
 			return;
-		cur_dev = NULL;
+		}
 	}
 #endif
 	/*
@@ -61,11 +63,12 @@
 #else
 #define INDEX 0
 #endif
-	if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &cur_dev) &&
-	    uclass_get_device(UCLASS_SERIAL, INDEX, &cur_dev) &&
-	    (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev))
+	if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) &&
+	    uclass_get_device(UCLASS_SERIAL, INDEX, &dev) &&
+	    (uclass_first_device(UCLASS_SERIAL, &dev) || !dev))
 		panic("No serial driver found");
 #undef INDEX
+	gd->cur_serial_dev = dev;
 }
 
 /* Called prior to relocation */
@@ -127,30 +130,30 @@
 
 void serial_putc(char ch)
 {
-	_serial_putc(cur_dev, ch);
+	_serial_putc(gd->cur_serial_dev, ch);
 }
 
 void serial_puts(const char *str)
 {
-	_serial_puts(cur_dev, str);
+	_serial_puts(gd->cur_serial_dev, str);
 }
 
 int serial_getc(void)
 {
-	return _serial_getc(cur_dev);
+	return _serial_getc(gd->cur_serial_dev);
 }
 
 int serial_tstc(void)
 {
-	return _serial_tstc(cur_dev);
+	return _serial_tstc(gd->cur_serial_dev);
 }
 
 void serial_setbrg(void)
 {
-	struct dm_serial_ops *ops = serial_get_ops(cur_dev);
+	struct dm_serial_ops *ops = serial_get_ops(gd->cur_serial_dev);
 
 	if (ops->setbrg)
-		ops->setbrg(cur_dev, gd->baudrate);
+		ops->setbrg(gd->cur_serial_dev, gd->baudrate);
 }
 
 void serial_stdio_init(void)
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 74df210..f61acbc 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -91,6 +91,7 @@
 	unsigned long malloc_limit;	/* limit address */
 	unsigned long malloc_ptr;	/* current address */
 #endif
+	struct udevice *cur_serial_dev;	/* current serial device */
 	struct arch_global_data arch;	/* architecture-specific data */
 } gd_t;
 #endif
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index f81b51a..36a36c6 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -257,6 +257,15 @@
 int gpio_lookup_name(const char *name, struct udevice **devp,
 		     unsigned int *offsetp, unsigned int *gpiop);
 
-int name_to_gpio(const char *name);
+/**
+ * get_gpios() - Turn the values of a list of GPIOs into an integer
+ *
+ * This puts the value of the first GPIO into bit 0, the second into bit 1,
+ * etc. then returns the resulting integer.
+ *
+ * @gpio_list: List of GPIOs to collect
+ * @return resulting integer value
+ */
+unsigned gpio_get_values_as_int(const int *gpio_list);
 
 #endif	/* _ASM_GENERIC_GPIO_H_ */
diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h
new file mode 100644
index 0000000..8caeca6
--- /dev/null
+++ b/include/configs/chromebook_link.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2008
+ * Graeme Russ, graeme.russ@gmail.com.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/x86-common.h>
+
+#define CONFIG_SYS_CAR_ADDR			0xff7e0000
+#define CONFIG_SYS_CAR_SIZE			(128 * 1024)
+#define CONFIG_SYS_MONITOR_LEN			(1 << 20)
+#define CONFIG_DCACHE_RAM_MRC_VAR_SIZE		0x4000
+#define CONFIG_SYS_X86_START16			0xfffff800
+#define CONFIG_BOARD_EARLY_INIT_F
+#define CONFIG_BOARD_EARLY_INIT_R
+#define CONFIG_DISPLAY_CPUINFO
+
+#define CONFIG_X86_RESET_VECTOR
+#define CONFIG_NR_DRAM_BANKS			8
+#define CONFIG_X86_MRC_START			0xfffa0000
+#define CONFIG_CACHE_MRC_SIZE_KB		512
+
+#define CONFIG_COREBOOT_SERIAL
+
+#define CONFIG_SCSI_DEV_LIST		{PCI_VENDOR_ID_INTEL, \
+			PCI_DEVICE_ID_INTEL_NM10_AHCI},	      \
+	{PCI_VENDOR_ID_INTEL,		\
+			PCI_DEVICE_ID_INTEL_COUGARPOINT_AHCI_MOBILE}, \
+	{PCI_VENDOR_ID_INTEL, \
+			PCI_DEVICE_ID_INTEL_COUGARPOINT_AHCI_SERIES6}, \
+	{PCI_VENDOR_ID_INTEL,		\
+			PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE}
+
+/*
+ * These common x86 features are not yet supported, but are added in
+ * follow-on patches in this series. Add undefs here to avoid every patch
+ * having to put things back into x86-common.h
+ */
+#undef CONFIG_VIDEO
+#undef CONFIG_CFB_CONSOLE
+#undef CONFIG_ICH_SPI
+#undef CONFIG_SPI
+#undef CONFIG_CMD_SPI
+#undef CONFIG_CMD_SF
+#undef CONFIG_USB_EHCI
+#undef CONFIG_CMD_USB
+#undef CONFIG_CMD_SCSI
+
+#define CONFIG_PCI_MEM_BUS	0xe0000000
+#define CONFIG_PCI_MEM_PHYS	CONFIG_PCI_MEM_BUS
+#define CONFIG_PCI_MEM_SIZE	0x10000000
+
+#define CONFIG_PCI_PREF_BUS	0xd0000000
+#define CONFIG_PCI_PREF_PHYS	CONFIG_PCI_PREF_BUS
+#define CONFIG_PCI_PREF_SIZE	0x10000000
+
+#define CONFIG_PCI_IO_BUS	0x1000
+#define CONFIG_PCI_IO_PHYS	CONFIG_PCI_IO_BUS
+#define CONFIG_PCI_IO_SIZE	0xefff
+
+#define CONFIG_STD_DEVICES_SETTINGS     "stdin=usbkbd,vga,serial\0" \
+					"stdout=vga,serial\0" \
+					"stderr=vga,serial\0"
+
+#endif	/* __CONFIG_H */
diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h
index fef267f..2581380 100644
--- a/include/configs/coreboot.h
+++ b/include/configs/coreboot.h
@@ -6,7 +6,6 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
-#include <asm/ibmpc.h>
 /*
  * board/config.h - configuration options, board specific
  */
@@ -14,27 +13,23 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
+#include <configs/x86-common.h>
+
 /*
  * High Level Configuration Options
  * (easy to change)
  */
 #define CONFIG_SYS_COREBOOT
-#define CONFIG_SHOW_BOOT_PROGRESS
 #define CONFIG_LAST_STAGE_INIT
-#define CONFIG_SYS_VSNPRINTF
-#define CONFIG_ZBOOT_32
-#define CONFIG_PHYSMEM
 #define CONFIG_SYS_EARLY_PCI_INIT
-#define CONFIG_DISPLAY_BOARDINFO_LATE
-#define CONFIG_DISPLAY_CPUINFO
 
-#define CONFIG_DM
-#define CONFIG_CMD_DM
-#define CONFIG_DM_GPIO
-#define CONFIG_DM_SERIAL
+#define CONFIG_SYS_CAR_ADDR			0x19200000
+#define CONFIG_SYS_CAR_SIZE			(16 * 1024)
+#define CONFIG_SYS_MONITOR_LEN			(256 * 1024)
 
-#define CONFIG_LMB
-#define CONFIG_OF_LIBFDT
+#define CONFIG_TRACE_EARLY_SIZE		(8 << 20)
+#define CONFIG_TRACE_EARLY
+#define CONFIG_TRACE_EARLY_ADDR		0x01400000
 
 #define CONFIG_BOOTSTAGE
 #define CONFIG_BOOTSTAGE_REPORT
@@ -45,26 +40,6 @@
 #define CONFIG_BOOTSTAGE_STASH_SIZE	0x7fc
 #define CONFIG_BOOTSTAGE_USER_COUNT	60
 
-#define CONFIG_LZO
-#define CONFIG_FIT
-#undef CONFIG_ZLIB
-#undef CONFIG_GZIP
-#define CONFIG_SYS_BOOTM_LEN		(16 << 20)
-
-/*-----------------------------------------------------------------------
- * Watchdog Configuration
- */
-#undef CONFIG_WATCHDOG
-#undef CONFIG_HW_WATCHDOG
-
-/* SATA AHCI storage */
-
-#define CONFIG_SCSI_AHCI
-
-#ifdef CONFIG_SCSI_AHCI
-#define CONFIG_LIBATA
-#define CONFIG_SYS_64BIT_LBA
-#define CONFIG_SATA_INTEL		1
 #define CONFIG_SCSI_DEV_LIST		{PCI_VENDOR_ID_INTEL, \
 			PCI_DEVICE_ID_INTEL_NM10_AHCI},	      \
 	{PCI_VENDOR_ID_INTEL,		\
@@ -74,249 +49,27 @@
 	{PCI_VENDOR_ID_INTEL,		\
 			PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE}
 
-#define CONFIG_SYS_SCSI_MAX_SCSI_ID	2
-#define CONFIG_SYS_SCSI_MAX_LUN		1
-#define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
-					 CONFIG_SYS_SCSI_MAX_LUN)
-#endif
-
-/* Generic TPM interfaced through LPC bus */
-#define CONFIG_TPM
-#define CONFIG_TPM_TIS_LPC
-#define CONFIG_TPM_TIS_BASE_ADDRESS        0xfed40000
-
-/*-----------------------------------------------------------------------
- * Real Time Clock Configuration
- */
-#define CONFIG_RTC_MC146818
-#define CONFIG_SYS_ISA_IO_BASE_ADDRESS	0
-#define CONFIG_SYS_ISA_IO      CONFIG_SYS_ISA_IO_BASE_ADDRESS
-
-/*-----------------------------------------------------------------------
- * Serial Configuration
- */
 #define CONFIG_COREBOOT_SERIAL
-#define CONFIG_SYS_NS16550
-#define CONFIG_BAUDRATE			115200
-#define CONFIG_SYS_BAUDRATE_TABLE	{300, 600, 1200, 2400, 4800, \
-					 9600, 19200, 38400, 115200}
-#define CONFIG_SYS_NS16550_PORT_MAPPED
 
 #define CONFIG_STD_DEVICES_SETTINGS     "stdin=usbkbd,vga,serial\0" \
 					"stdout=vga,serial,cbmem\0" \
 					"stderr=vga,serial,cbmem\0"
 
-#define CONFIG_CONSOLE_MUX
-#define CONFIG_SYS_CONSOLE_IS_IN_ENV
-#define CONFIG_SYS_STDIO_DEREGISTER
 #define CONFIG_CBMEM_CONSOLE
 
-#define CONFIG_CMDLINE_EDITING
-#define CONFIG_COMMAND_HISTORY
-#define CONFIG_AUTO_COMPLETE
-#define CONFIG_SYS_HUSH_PARSER
-
-#define CONFIG_SUPPORT_VFAT
-/************************************************************
- * ATAPI support (experimental)
- ************************************************************/
-#define CONFIG_ATAPI
-
-/************************************************************
- * DISK Partition support
- ************************************************************/
-#define CONFIG_EFI_PARTITION
-#define CONFIG_DOS_PARTITION
-#define CONFIG_MAC_PARTITION
-#define CONFIG_ISO_PARTITION		/* Experimental */
-
-#define CONFIG_CMD_PART
-#define CONFIG_CMD_CBFS
-#define CONFIG_CMD_EXT4
-#define CONFIG_CMD_EXT4_WRITE
-#define CONFIG_PARTITION_UUIDS
-
-/*-----------------------------------------------------------------------
- * Video Configuration
- */
-#define CONFIG_VIDEO
 #define CONFIG_VIDEO_COREBOOT
-#define CONFIG_VIDEO_SW_CURSOR
-#define VIDEO_FB_16BPP_WORD_SWAP
-#define CONFIG_I8042_KBD
-#define CONFIG_CFB_CONSOLE
-#define CONFIG_SYS_CONSOLE_INFO_QUIET
 
-/* x86 GPIOs are accessed through a PCI device */
-#define CONFIG_INTEL_ICH6_GPIO
-
-/*-----------------------------------------------------------------------
- * Command line configuration.
- */
-#include <config_cmd_default.h>
+#define CONFIG_NR_DRAM_BANKS			4
 
 #define CONFIG_TRACE
 #define CONFIG_CMD_TRACE
 #define CONFIG_TRACE_BUFFER_SIZE	(16 << 20)
-#define CONFIG_TRACE_EARLY_SIZE		(8 << 20)
-#define CONFIG_TRACE_EARLY
-#define CONFIG_TRACE_EARLY_ADDR		0x01400000
-
-#define CONFIG_CMD_BDI
-#define CONFIG_CMD_BOOTD
-#define CONFIG_CMD_CONSOLE
-#define CONFIG_CMD_DATE
-#define CONFIG_CMD_ECHO
-#undef CONFIG_CMD_FLASH
-#define CONFIG_CMD_FPGA
-#define CONFIG_CMD_FPGA_LOADMK
-#define CONFIG_CMD_GPIO
-#define CONFIG_CMD_IMI
-#undef CONFIG_CMD_IMLS
-#define CONFIG_CMD_IO
-#define CONFIG_CMD_IRQ
-#define CONFIG_CMD_ITEST
-#define CONFIG_CMD_LOADB
-#define CONFIG_CMD_LOADS
-#define CONFIG_CMD_MEMORY
-#define CONFIG_CMD_MISC
-#define CONFIG_CMD_NET
-#undef CONFIG_CMD_NFS
-#define CONFIG_CMD_PCI
-#define CONFIG_CMD_PING
-#define CONFIG_CMD_RUN
-#define CONFIG_CMD_SAVEENV
-#define CONFIG_CMD_SETGETDCR
-#define CONFIG_CMD_SOURCE
-#define CONFIG_CMD_TIME
-#define CONFIG_CMD_GETTIME
-#define CONFIG_CMD_XIMG
-#define CONFIG_CMD_SCSI
-
-#define CONFIG_CMD_FAT
-#define CONFIG_CMD_EXT2
-
-#define CONFIG_CMD_ZBOOT
-#define CONFIG_CMD_ELF
 
 #define CONFIG_BOOTDELAY	2
-#define CONFIG_BOOTARGS		\
-	"root=/dev/sdb3 init=/sbin/init rootwait ro"
-#define CONFIG_BOOTCOMMAND	\
-	"ext2load scsi 0:3 01000000 /boot/vmlinuz; zboot 01000000"
-
-
-#if defined(CONFIG_CMD_KGDB)
-#define CONFIG_KGDB_BAUDRATE			115200
-#endif
-
-/*
- * Miscellaneous configurable options
- */
-#define CONFIG_SYS_LONGHELP
-#define CONFIG_SYS_CBSIZE			512
-#define CONFIG_SYS_PBSIZE			(CONFIG_SYS_CBSIZE + \
-						 sizeof(CONFIG_SYS_PROMPT) + \
-						 16)
-#define CONFIG_SYS_MAXARGS			16
-#define CONFIG_SYS_BARGSIZE			CONFIG_SYS_CBSIZE
-
-#define CONFIG_SYS_MEMTEST_START		0x00100000
-#define CONFIG_SYS_MEMTEST_END			0x01000000
-#define CONFIG_SYS_LOAD_ADDR			0x20000000
-
-/*-----------------------------------------------------------------------
- * SDRAM Configuration
- */
-#define CONFIG_NR_DRAM_BANKS			4
-
-/* CONFIG_SYS_SDRAM_DRCTMCTL Overrides the following*/
-#undef CONFIG_SYS_SDRAM_PRECHARGE_DELAY
-#undef CONFIG_SYS_SDRAM_RAS_CAS_DELAY
-#undef CONFIG_SYS_SDRAM_CAS_LATENCY_2T
-#undef CONFIG_SYS_SDRAM_CAS_LATENCY_3T
-
-/*-----------------------------------------------------------------------
- * CPU Features
- */
-
-#define CONFIG_SYS_X86_TSC_TIMER
-#define CONFIG_SYS_PCAT_INTERRUPTS
-#define CONFIG_SYS_PCAT_TIMER
-#define CONFIG_SYS_NUM_IRQS			16
-
-/*-----------------------------------------------------------------------
- * Memory organization:
- * 32kB Stack
- * 16kB Cache-As-RAM @ 0x19200000
- * 256kB Monitor
- * (128kB + Environment Sector Size) malloc pool
- */
-#define CONFIG_SYS_STACK_SIZE			(32 * 1024)
-#define CONFIG_SYS_CAR_ADDR			0x19200000
-#define CONFIG_SYS_CAR_SIZE			(16 * 1024)
-#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
-#define CONFIG_SYS_MONITOR_LEN			(256 * 1024)
-#define CONFIG_SYS_MALLOC_LEN			(0x20000 + 128 * 1024)
-#define CONFIG_SYS_MALLOC_F_LEN			(1 << 10)
-
-/* allow to overwrite serial and ethaddr */
-#define CONFIG_ENV_OVERWRITE
-
-/*-----------------------------------------------------------------------
- * FLASH configuration
- */
-#define CONFIG_ICH_SPI
-#define CONFIG_SPI_FLASH
-#define CONFIG_SPI_FLASH_MACRONIX
-#define CONFIG_SPI_FLASH_WINBOND
-#define CONFIG_SPI_FLASH_GIGADEVICE
-#define CONFIG_SYS_NO_FLASH
-#define CONFIG_CMD_SF
-#define CONFIG_CMD_SF_TEST
-#define CONFIG_CMD_SPI
-#define CONFIG_SPI
-
-/*-----------------------------------------------------------------------
- * Environment configuration
- */
-#define CONFIG_ENV_IS_NOWHERE
-#define CONFIG_ENV_SIZE			0x01000
-
-/*-----------------------------------------------------------------------
- * PCI configuration
- */
-#define CONFIG_PCI
 
 #define CONFIG_CROS_EC
 #define CONFIG_CROS_EC_LPC
 #define CONFIG_CMD_CROS_EC
 #define CONFIG_ARCH_EARLY_INIT_R
 
-/*-----------------------------------------------------------------------
- * USB configuration
- */
-#define CONFIG_USB_EHCI
-#define CONFIG_USB_EHCI_PCI
-#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS     12
-#define CONFIG_USB_MAX_CONTROLLER_COUNT        2
-#define CONFIG_USB_STORAGE
-#define CONFIG_USB_KEYBOARD
-#define CONFIG_SYS_USB_EVENT_POLL
-
-#define CONFIG_USB_HOST_ETHER
-#define CONFIG_USB_ETHER_ASIX
-#define CONFIG_USB_ETHER_SMSC95XX
-#define CONFIG_TFTP_TSIZE
-#define CONFIG_CMD_DHCP
-#define CONFIG_BOOTP_BOOTFILESIZE
-#define CONFIG_BOOTP_BOOTPATH
-#define CONFIG_BOOTP_GATEWAY
-#define CONFIG_BOOTP_HOSTNAME
-
-#define CONFIG_CMD_USB
-
-#define CONFIG_EXTRA_ENV_SETTINGS \
-	CONFIG_STD_DEVICES_SETTINGS
-
 #endif	/* __CONFIG_H */
diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h
new file mode 100644
index 0000000..f16ae32
--- /dev/null
+++ b/include/configs/x86-common.h
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2008
+ * Graeme Russ, graeme.russ@gmail.com.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/ibmpc.h>
+
+#ifndef __CONFIG_X86_COMMON_H
+#define __CONFIG_X86_COMMON_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#define CONFIG_SHOW_BOOT_PROGRESS
+#define CONFIG_SYS_VSNPRINTF
+#define CONFIG_ZBOOT_32
+#define CONFIG_PHYSMEM
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+#define CONFIG_DISPLAY_CPUINFO
+
+#define CONFIG_DM
+#define CONFIG_CMD_DM
+#define CONFIG_DM_GPIO
+#define CONFIG_DM_SERIAL
+
+#define CONFIG_LMB
+#define CONFIG_OF_LIBFDT
+
+#define CONFIG_LZO
+#define CONFIG_FIT
+#undef CONFIG_ZLIB
+#undef CONFIG_GZIP
+#define CONFIG_SYS_BOOTM_LEN		(16 << 20)
+
+/* SATA AHCI storage */
+
+#define CONFIG_SCSI_AHCI
+#define CONFIG_SATA_INTEL
+#ifdef CONFIG_SCSI_AHCI
+#define CONFIG_LIBATA
+#define CONFIG_SYS_64BIT_LBA
+
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID	2
+#define CONFIG_SYS_SCSI_MAX_LUN		1
+#define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+					 CONFIG_SYS_SCSI_MAX_LUN)
+#endif
+
+/* Generic TPM interfaced through LPC bus */
+#define CONFIG_TPM
+#define CONFIG_TPM_TIS_LPC
+#define CONFIG_TPM_TIS_BASE_ADDRESS        0xfed40000
+
+/*-----------------------------------------------------------------------
+ * Real Time Clock Configuration
+ */
+#define CONFIG_RTC_MC146818
+#define CONFIG_SYS_ISA_IO_BASE_ADDRESS	0
+#define CONFIG_SYS_ISA_IO      CONFIG_SYS_ISA_IO_BASE_ADDRESS
+
+/*-----------------------------------------------------------------------
+ * Serial Configuration
+ */
+#define CONFIG_SYS_NS16550
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_BAUDRATE_TABLE	{300, 600, 1200, 2400, 4800, \
+					 9600, 19200, 38400, 115200}
+#define CONFIG_SYS_NS16550_PORT_MAPPED
+
+#define CONFIG_CONSOLE_MUX
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_SYS_STDIO_DEREGISTER
+
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_COMMAND_HISTORY
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_SYS_HUSH_PARSER
+
+#define CONFIG_SUPPORT_VFAT
+/************************************************************
+ * ATAPI support (experimental)
+ ************************************************************/
+#define CONFIG_ATAPI
+
+/************************************************************
+ * DISK Partition support
+ ************************************************************/
+#define CONFIG_EFI_PARTITION
+#define CONFIG_DOS_PARTITION
+#define CONFIG_MAC_PARTITION
+#define CONFIG_ISO_PARTITION		/* Experimental */
+
+#define CONFIG_CMD_PART
+#define CONFIG_CMD_CBFS
+#define CONFIG_CMD_EXT4
+#define CONFIG_CMD_EXT4_WRITE
+#define CONFIG_PARTITION_UUIDS
+
+#define CONFIG_SYS_CONSOLE_INFO_QUIET
+
+/* x86 GPIOs are accessed through a PCI device */
+#define CONFIG_INTEL_ICH6_GPIO
+
+/*-----------------------------------------------------------------------
+ * Command line configuration.
+ */
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_BDI
+#define CONFIG_CMD_BOOTD
+#define CONFIG_CMD_CONSOLE
+#define CONFIG_CMD_DATE
+#define CONFIG_CMD_ECHO
+#undef CONFIG_CMD_FLASH
+#define CONFIG_CMD_FPGA
+#define CONFIG_CMD_FPGA_LOADMK
+#define CONFIG_CMD_GPIO
+#define CONFIG_CMD_IMI
+#undef CONFIG_CMD_IMLS
+#define CONFIG_CMD_IO
+#define CONFIG_CMD_IRQ
+#define CONFIG_CMD_ITEST
+#define CONFIG_CMD_LOADB
+#define CONFIG_CMD_LOADS
+#define CONFIG_CMD_MEMORY
+#define CONFIG_CMD_MISC
+#define CONFIG_CMD_NET
+#undef CONFIG_CMD_NFS
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_RUN
+#define CONFIG_CMD_SAVEENV
+#define CONFIG_CMD_SETGETDCR
+#define CONFIG_CMD_SOURCE
+#define CONFIG_CMD_TIME
+#define CONFIG_CMD_GETTIME
+#define CONFIG_CMD_XIMG
+#define CONFIG_CMD_SCSI
+
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+
+#define CONFIG_CMD_ZBOOT
+#define CONFIG_CMD_ELF
+
+#define CONFIG_BOOTARGS		\
+	"root=/dev/sdb3 init=/sbin/init rootwait ro"
+#define CONFIG_BOOTCOMMAND	\
+	"ext2load scsi 0:3 01000000 /boot/vmlinuz; zboot 01000000"
+
+#if defined(CONFIG_CMD_KGDB)
+#define CONFIG_KGDB_BAUDRATE			115200
+#endif
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_SYS_CBSIZE			512
+#define CONFIG_SYS_PBSIZE			(CONFIG_SYS_CBSIZE + \
+						 sizeof(CONFIG_SYS_PROMPT) + \
+						 16)
+#define CONFIG_SYS_MAXARGS			16
+#define CONFIG_SYS_BARGSIZE			CONFIG_SYS_CBSIZE
+
+#define CONFIG_SYS_MEMTEST_START		0x00100000
+#define CONFIG_SYS_MEMTEST_END			0x01000000
+#define CONFIG_SYS_LOAD_ADDR			0x20000000
+
+/*-----------------------------------------------------------------------
+ * Video Configuration
+ */
+#define CONFIG_VIDEO
+#define CONFIG_VIDEO_SW_CURSOR
+#define VIDEO_FB_16BPP_WORD_SWAP
+#define CONFIG_I8042_KBD
+#define CONFIG_CFB_CONSOLE
+
+/*-----------------------------------------------------------------------
+ * CPU Features
+ */
+
+#define CONFIG_SYS_X86_TSC_TIMER
+#define CONFIG_SYS_PCAT_INTERRUPTS
+#define CONFIG_SYS_PCAT_TIMER
+#define CONFIG_SYS_NUM_IRQS			16
+
+#define CONFIG_SYS_STACK_SIZE			(32 * 1024)
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_MALLOC_LEN			0x200000
+#define CONFIG_SYS_MALLOC_F_LEN			(2 << 10)
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+
+/*-----------------------------------------------------------------------
+ * FLASH configuration
+ */
+#define CONFIG_ICH_SPI
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_MACRONIX
+#define CONFIG_SPI_FLASH_WINBOND
+#define CONFIG_SPI_FLASH_GIGADEVICE
+#define CONFIG_SYS_NO_FLASH
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SF_TEST
+#define CONFIG_CMD_SPI
+#define CONFIG_SPI
+
+/*-----------------------------------------------------------------------
+ * Environment configuration
+ */
+#define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_SIZE			0x01000
+
+/*-----------------------------------------------------------------------
+ * PCI configuration
+ */
+#define CONFIG_PCI
+
+/*-----------------------------------------------------------------------
+ * USB configuration
+ */
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_PCI
+#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS     12
+#define CONFIG_USB_MAX_CONTROLLER_COUNT        2
+#define CONFIG_USB_STORAGE
+#define CONFIG_USB_KEYBOARD
+#define CONFIG_SYS_USB_EVENT_POLL
+
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_ASIX
+#define CONFIG_USB_ETHER_SMSC95XX
+#define CONFIG_TFTP_TSIZE
+#define CONFIG_CMD_DHCP
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+
+#define CONFIG_CMD_USB
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	CONFIG_STD_DEVICES_SETTINGS
+
+#endif	/* __CONFIG_H */
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 4ae77be..abfd678 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -118,6 +118,8 @@
 	COMPAT_SAMSUNG_EXYNOS_SYSMMU,	/* Exynos sysmmu */
 	COMPAT_PARADE_PS8625,		/* Parade PS8622 EDP->LVDS bridge */
 	COMPAT_INTEL_LPC,		/* Intel Low Pin Count I/F */
+	COMPAT_INTEL_MICROCODE,		/* Intel microcode update */
+	COMPAT_MEMORY_SPD,		/* Memory SPD information */
 
 	COMPAT_COUNT,
 };
@@ -445,6 +447,22 @@
 		u32 *array, int count);
 
 /**
+ * Look up a property in a node and return its contents in an integer
+ * array of given length. The property must exist but may have less data that
+ * expected (4*count bytes). It may have more, but this will be ignored.
+ *
+ * @param blob		FDT blob
+ * @param node		node to examine
+ * @param prop_name	name of property to find
+ * @param array		array to fill with data
+ * @param count		number of array elements
+ * @return number of array elements if ok, or -FDT_ERR_NOTFOUND if the
+ *		property is not found
+ */
+int fdtdec_get_int_array_count(const void *blob, int node,
+			       const char *prop_name, u32 *array, int count);
+
+/**
  * Look up a property in a node and return a pointer to its contents as a
  * unsigned int array of given length. The property must have at least enough
  * data for the array ('count' cells). It may have more, but this will be
diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c
index 129bc3e..580f763 100644
--- a/lib/asm-offsets.c
+++ b/lib/asm-offsets.c
@@ -31,6 +31,9 @@
 #ifdef CONFIG_SYS_MALLOC_F_LEN
 	DEFINE(GD_MALLOC_BASE, offsetof(struct global_data, malloc_base));
 #endif
+#ifdef CONFIG_X86
+	DEFINE(GD_BIST, offsetof(struct global_data, arch.bist));
+#endif
 
 #if defined(CONFIG_ARM)
 
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 9714620..aafc4f9 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -73,6 +73,8 @@
 	COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
 	COMPAT(PARADE_PS8625, "parade,ps8625"),
 	COMPAT(COMPAT_INTEL_LPC, "intel,lpc"),
+	COMPAT(INTEL_MICROCODE, "intel,microcode"),
+	COMPAT(MEMORY_SPD, "memory-spd"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
@@ -485,6 +487,26 @@
 	return err;
 }
 
+int fdtdec_get_int_array_count(const void *blob, int node,
+			       const char *prop_name, u32 *array, int count)
+{
+	const u32 *cell;
+	int len, elems;
+	int i;
+
+	debug("%s: %s\n", __func__, prop_name);
+	cell = fdt_getprop(blob, node, prop_name, &len);
+	if (!cell)
+		return -FDT_ERR_NOTFOUND;
+	elems = len / sizeof(u32);
+	if (count > elems)
+		count = elems;
+	for (i = 0; i < count; i++)
+		array[i] = fdt32_to_cpu(cell[i]);
+
+	return count;
+}
+
 const u32 *fdtdec_locate_array(const void *blob, int node,
 			       const char *prop_name, int count)
 {
diff --git a/tools/Makefile b/tools/Makefile
index c422b76..a4216a1 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -126,6 +126,8 @@
 hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl
 HOSTCFLAGS_mkexynosspl.o := -pedantic
 
+hostprogs-$(CONFIG_X86) += ifdtool
+
 hostprogs-$(CONFIG_MX23) += mxsboot
 hostprogs-$(CONFIG_MX28) += mxsboot
 HOSTCFLAGS_mxsboot.o := -pedantic
diff --git a/tools/ifdtool.c b/tools/ifdtool.c
new file mode 100644
index 0000000..a4b481f
--- /dev/null
+++ b/tools/ifdtool.c
@@ -0,0 +1,1039 @@
+/*
+ * ifdtool - Manage Intel Firmware Descriptor information
+ *
+ * Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ *
+ * From Coreboot project, but it got a serious code clean-up
+ * and a few new features
+ */
+
+#include <assert.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "ifdtool.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define debug(fmt, args...)	printf(fmt, ##args)
+#else
+#define debug(fmt, args...)
+#endif
+
+#define FD_SIGNATURE		0x0FF0A55A
+#define FLREG_BASE(reg)		((reg & 0x00000fff) << 12);
+#define FLREG_LIMIT(reg)	(((reg & 0x0fff0000) >> 4) | 0xfff);
+
+/**
+ * find_fd() - Find the flash description in the ROM image
+ *
+ * @image:	Pointer to image
+ * @size:	Size of image in bytes
+ * @return pointer to structure, or NULL if not found
+ */
+static struct fdbar_t *find_fd(char *image, int size)
+{
+	uint32_t *ptr, *end;
+
+	/* Scan for FD signature */
+	for (ptr = (uint32_t *)image, end = ptr + size / 4; ptr < end; ptr++) {
+		if (*ptr == FD_SIGNATURE)
+			break;
+	}
+
+	if (ptr == end) {
+		printf("No Flash Descriptor found in this image\n");
+		return NULL;
+	}
+
+	debug("Found Flash Descriptor signature at 0x%08x\n", i);
+
+	return (struct fdbar_t *)ptr;
+}
+
+/**
+ * get_region() - Get information about the selected region
+ *
+ * @frba:		Flash region list
+ * @region_type:	Type of region (0..MAX_REGIONS-1)
+ * @region:		Region information is written here
+ * @return 0 if OK, else -ve
+ */
+static int get_region(struct frba_t *frba, int region_type,
+		      struct region_t *region)
+{
+	if (region_type >= MAX_REGIONS) {
+		fprintf(stderr, "Invalid region type.\n");
+		return -1;
+	}
+
+	region->base = FLREG_BASE(frba->flreg[region_type]);
+	region->limit = FLREG_LIMIT(frba->flreg[region_type]);
+	region->size = region->limit - region->base + 1;
+
+	return 0;
+}
+
+static const char *region_name(int region_type)
+{
+	static const char *const regions[] = {
+		"Flash Descriptor",
+		"BIOS",
+		"Intel ME",
+		"GbE",
+		"Platform Data"
+	};
+
+	assert(region_type < MAX_REGIONS);
+
+	return regions[region_type];
+}
+
+static const char *region_filename(int region_type)
+{
+	static const char *const region_filenames[] = {
+		"flashregion_0_flashdescriptor.bin",
+		"flashregion_1_bios.bin",
+		"flashregion_2_intel_me.bin",
+		"flashregion_3_gbe.bin",
+		"flashregion_4_platform_data.bin"
+	};
+
+	assert(region_type < MAX_REGIONS);
+
+	return region_filenames[region_type];
+}
+
+static int dump_region(int num, struct frba_t *frba)
+{
+	struct region_t region;
+	int ret;
+
+	ret = get_region(frba, num, &region);
+	if (ret)
+		return ret;
+
+	printf("  Flash Region %d (%s): %08x - %08x %s\n",
+	       num, region_name(num), region.base, region.limit,
+	       region.size < 1 ? "(unused)" : "");
+
+	return ret;
+}
+
+static void dump_frba(struct frba_t *frba)
+{
+	int i;
+
+	printf("Found Region Section\n");
+	for (i = 0; i < MAX_REGIONS; i++) {
+		printf("FLREG%d:    0x%08x\n", i, frba->flreg[i]);
+		dump_region(i, frba);
+	}
+}
+
+static void decode_spi_frequency(unsigned int freq)
+{
+	switch (freq) {
+	case SPI_FREQUENCY_20MHZ:
+		printf("20MHz");
+		break;
+	case SPI_FREQUENCY_33MHZ:
+		printf("33MHz");
+		break;
+	case SPI_FREQUENCY_50MHZ:
+		printf("50MHz");
+		break;
+	default:
+		printf("unknown<%x>MHz", freq);
+	}
+}
+
+static void decode_component_density(unsigned int density)
+{
+	switch (density) {
+	case COMPONENT_DENSITY_512KB:
+		printf("512KiB");
+		break;
+	case COMPONENT_DENSITY_1MB:
+		printf("1MiB");
+		break;
+	case COMPONENT_DENSITY_2MB:
+		printf("2MiB");
+		break;
+	case COMPONENT_DENSITY_4MB:
+		printf("4MiB");
+		break;
+	case COMPONENT_DENSITY_8MB:
+		printf("8MiB");
+		break;
+	case COMPONENT_DENSITY_16MB:
+		printf("16MiB");
+		break;
+	default:
+		printf("unknown<%x>MiB", density);
+	}
+}
+
+static void dump_fcba(struct fcba_t *fcba)
+{
+	printf("\nFound Component Section\n");
+	printf("FLCOMP     0x%08x\n", fcba->flcomp);
+	printf("  Dual Output Fast Read Support:       %ssupported\n",
+	       (fcba->flcomp & (1 << 30)) ? "" : "not ");
+	printf("  Read ID/Read Status Clock Frequency: ");
+	decode_spi_frequency((fcba->flcomp >> 27) & 7);
+	printf("\n  Write/Erase Clock Frequency:         ");
+	decode_spi_frequency((fcba->flcomp >> 24) & 7);
+	printf("\n  Fast Read Clock Frequency:           ");
+	decode_spi_frequency((fcba->flcomp >> 21) & 7);
+	printf("\n  Fast Read Support:                   %ssupported",
+	       (fcba->flcomp & (1 << 20)) ? "" : "not ");
+	printf("\n  Read Clock Frequency:                ");
+	decode_spi_frequency((fcba->flcomp >> 17) & 7);
+	printf("\n  Component 2 Density:                 ");
+	decode_component_density((fcba->flcomp >> 3) & 7);
+	printf("\n  Component 1 Density:                 ");
+	decode_component_density(fcba->flcomp & 7);
+	printf("\n");
+	printf("FLILL      0x%08x\n", fcba->flill);
+	printf("  Invalid Instruction 3: 0x%02x\n",
+	       (fcba->flill >> 24) & 0xff);
+	printf("  Invalid Instruction 2: 0x%02x\n",
+	       (fcba->flill >> 16) & 0xff);
+	printf("  Invalid Instruction 1: 0x%02x\n",
+	       (fcba->flill >> 8) & 0xff);
+	printf("  Invalid Instruction 0: 0x%02x\n",
+	       fcba->flill & 0xff);
+	printf("FLPB       0x%08x\n", fcba->flpb);
+	printf("  Flash Partition Boundary Address: 0x%06x\n\n",
+	       (fcba->flpb & 0xfff) << 12);
+}
+
+static void dump_fpsba(struct fpsba_t *fpsba)
+{
+	int i;
+
+	printf("Found PCH Strap Section\n");
+	for (i = 0; i < MAX_STRAPS; i++)
+		printf("PCHSTRP%-2d:  0x%08x\n", i, fpsba->pchstrp[i]);
+}
+
+static const char *get_enabled(int flag)
+{
+	return flag ? "enabled" : "disabled";
+}
+
+static void decode_flmstr(uint32_t flmstr)
+{
+	printf("  Platform Data Region Write Access: %s\n",
+	       get_enabled(flmstr & (1 << 28)));
+	printf("  GbE Region Write Access:           %s\n",
+	       get_enabled(flmstr & (1 << 27)));
+	printf("  Intel ME Region Write Access:      %s\n",
+	       get_enabled(flmstr & (1 << 26)));
+	printf("  Host CPU/BIOS Region Write Access: %s\n",
+	       get_enabled(flmstr & (1 << 25)));
+	printf("  Flash Descriptor Write Access:     %s\n",
+	       get_enabled(flmstr & (1 << 24)));
+
+	printf("  Platform Data Region Read Access:  %s\n",
+	       get_enabled(flmstr & (1 << 20)));
+	printf("  GbE Region Read Access:            %s\n",
+	       get_enabled(flmstr & (1 << 19)));
+	printf("  Intel ME Region Read Access:       %s\n",
+	       get_enabled(flmstr & (1 << 18)));
+	printf("  Host CPU/BIOS Region Read Access:  %s\n",
+	       get_enabled(flmstr & (1 << 17)));
+	printf("  Flash Descriptor Read Access:      %s\n",
+	       get_enabled(flmstr & (1 << 16)));
+
+	printf("  Requester ID:                      0x%04x\n\n",
+	       flmstr & 0xffff);
+}
+
+static void dump_fmba(struct fmba_t *fmba)
+{
+	printf("Found Master Section\n");
+	printf("FLMSTR1:   0x%08x (Host CPU/BIOS)\n", fmba->flmstr1);
+	decode_flmstr(fmba->flmstr1);
+	printf("FLMSTR2:   0x%08x (Intel ME)\n", fmba->flmstr2);
+	decode_flmstr(fmba->flmstr2);
+	printf("FLMSTR3:   0x%08x (GbE)\n", fmba->flmstr3);
+	decode_flmstr(fmba->flmstr3);
+}
+
+static void dump_fmsba(struct fmsba_t *fmsba)
+{
+	int i;
+
+	printf("Found Processor Strap Section\n");
+	for (i = 0; i < 4; i++)
+		printf("????:      0x%08x\n", fmsba->data[0]);
+}
+
+static void dump_jid(uint32_t jid)
+{
+	printf("    SPI Component Device ID 1:          0x%02x\n",
+	       (jid >> 16) & 0xff);
+	printf("    SPI Component Device ID 0:          0x%02x\n",
+	       (jid >> 8) & 0xff);
+	printf("    SPI Component Vendor ID:            0x%02x\n",
+	       jid & 0xff);
+}
+
+static void dump_vscc(uint32_t vscc)
+{
+	printf("    Lower Erase Opcode:                 0x%02x\n",
+	       vscc >> 24);
+	printf("    Lower Write Enable on Write Status: 0x%02x\n",
+	       vscc & (1 << 20) ? 0x06 : 0x50);
+	printf("    Lower Write Status Required:        %s\n",
+	       vscc & (1 << 19) ? "Yes" : "No");
+	printf("    Lower Write Granularity:            %d bytes\n",
+	       vscc & (1 << 18) ? 64 : 1);
+	printf("    Lower Block / Sector Erase Size:    ");
+	switch ((vscc >> 16) & 0x3) {
+	case 0:
+		printf("256 Byte\n");
+		break;
+	case 1:
+		printf("4KB\n");
+		break;
+	case 2:
+		printf("8KB\n");
+		break;
+	case 3:
+		printf("64KB\n");
+		break;
+	}
+
+	printf("    Upper Erase Opcode:                 0x%02x\n",
+	       (vscc >> 8) & 0xff);
+	printf("    Upper Write Enable on Write Status: 0x%02x\n",
+	       vscc & (1 << 4) ? 0x06 : 0x50);
+	printf("    Upper Write Status Required:        %s\n",
+	       vscc & (1 << 3) ? "Yes" : "No");
+	printf("    Upper Write Granularity:            %d bytes\n",
+	       vscc & (1 << 2) ? 64 : 1);
+	printf("    Upper Block / Sector Erase Size:    ");
+	switch (vscc & 0x3) {
+	case 0:
+		printf("256 Byte\n");
+		break;
+	case 1:
+		printf("4KB\n");
+		break;
+	case 2:
+		printf("8KB\n");
+		break;
+	case 3:
+		printf("64KB\n");
+		break;
+	}
+}
+
+static void dump_vtba(struct vtba_t *vtba, int vtl)
+{
+	int i;
+	int num = (vtl >> 1) < 8 ? (vtl >> 1) : 8;
+
+	printf("ME VSCC table:\n");
+	for (i = 0; i < num; i++) {
+		printf("  JID%d:  0x%08x\n", i, vtba->entry[i].jid);
+		dump_jid(vtba->entry[i].jid);
+		printf("  VSCC%d: 0x%08x\n", i, vtba->entry[i].vscc);
+		dump_vscc(vtba->entry[i].vscc);
+	}
+	printf("\n");
+}
+
+static void dump_oem(uint8_t *oem)
+{
+	int i, j;
+	printf("OEM Section:\n");
+	for (i = 0; i < 4; i++) {
+		printf("%02x:", i << 4);
+		for (j = 0; j < 16; j++)
+			printf(" %02x", oem[(i<<4)+j]);
+		printf("\n");
+	}
+	printf("\n");
+}
+
+/**
+ * dump_fd() - Display a dump of the full flash description
+ *
+ * @image:	Pointer to image
+ * @size:	Size of image in bytes
+ * @return 0 if OK, -1 on error
+ */
+static int dump_fd(char *image, int size)
+{
+	struct fdbar_t *fdb = find_fd(image, size);
+
+	if (!fdb)
+		return -1;
+
+	printf("FLMAP0:    0x%08x\n", fdb->flmap0);
+	printf("  NR:      %d\n", (fdb->flmap0 >> 24) & 7);
+	printf("  FRBA:    0x%x\n", ((fdb->flmap0 >> 16) & 0xff) << 4);
+	printf("  NC:      %d\n", ((fdb->flmap0 >> 8) & 3) + 1);
+	printf("  FCBA:    0x%x\n", ((fdb->flmap0) & 0xff) << 4);
+
+	printf("FLMAP1:    0x%08x\n", fdb->flmap1);
+	printf("  ISL:     0x%02x\n", (fdb->flmap1 >> 24) & 0xff);
+	printf("  FPSBA:   0x%x\n", ((fdb->flmap1 >> 16) & 0xff) << 4);
+	printf("  NM:      %d\n", (fdb->flmap1 >> 8) & 3);
+	printf("  FMBA:    0x%x\n", ((fdb->flmap1) & 0xff) << 4);
+
+	printf("FLMAP2:    0x%08x\n", fdb->flmap2);
+	printf("  PSL:     0x%04x\n", (fdb->flmap2 >> 8) & 0xffff);
+	printf("  FMSBA:   0x%x\n", ((fdb->flmap2) & 0xff) << 4);
+
+	printf("FLUMAP1:   0x%08x\n", fdb->flumap1);
+	printf("  Intel ME VSCC Table Length (VTL):        %d\n",
+	       (fdb->flumap1 >> 8) & 0xff);
+	printf("  Intel ME VSCC Table Base Address (VTBA): 0x%06x\n\n",
+	       (fdb->flumap1 & 0xff) << 4);
+	dump_vtba((struct vtba_t *)
+			(image + ((fdb->flumap1 & 0xff) << 4)),
+			(fdb->flumap1 >> 8) & 0xff);
+	dump_oem((uint8_t *)image + 0xf00);
+	dump_frba((struct frba_t *)(image + (((fdb->flmap0 >> 16) & 0xff)
+			<< 4)));
+	dump_fcba((struct fcba_t *)(image + (((fdb->flmap0) & 0xff) << 4)));
+	dump_fpsba((struct fpsba_t *)
+			(image + (((fdb->flmap1 >> 16) & 0xff) << 4)));
+	dump_fmba((struct fmba_t *)(image + (((fdb->flmap1) & 0xff) << 4)));
+	dump_fmsba((struct fmsba_t *)(image + (((fdb->flmap2) & 0xff) << 4)));
+
+	return 0;
+}
+
+/**
+ * write_regions() - Write each region from an image to its own file
+ *
+ * The filename to use in each case is fixed - see region_filename()
+ *
+ * @image:	Pointer to image
+ * @size:	Size of image in bytes
+ * @return 0 if OK, -ve on error
+ */
+static int write_regions(char *image, int size)
+{
+	struct fdbar_t *fdb;
+	struct frba_t *frba;
+	int ret = 0;
+	int i;
+
+	fdb =  find_fd(image, size);
+	if (!fdb)
+		return -1;
+
+	frba = (struct frba_t *)(image + (((fdb->flmap0 >> 16) & 0xff) << 4));
+
+	for (i = 0; i < MAX_REGIONS; i++) {
+		struct region_t region;
+		int region_fd;
+
+		ret = get_region(frba, i, &region);
+		if (ret)
+			return ret;
+		dump_region(i, frba);
+		if (region.size == 0)
+			continue;
+		region_fd = open(region_filename(i),
+				 O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR |
+				 S_IWUSR | S_IRGRP | S_IROTH);
+		if (write(region_fd, image + region.base, region.size) !=
+				region.size) {
+			perror("Error while writing");
+			ret = -1;
+		}
+		close(region_fd);
+	}
+
+	return ret;
+}
+
+/**
+ * write_image() - Write the image to a file
+ *
+ * @filename:	Filename to use for the image
+ * @image:	Pointer to image
+ * @size:	Size of image in bytes
+ * @return 0 if OK, -ve on error
+ */
+static int write_image(char *filename, char *image, int size)
+{
+	int new_fd;
+
+	debug("Writing new image to %s\n", filename);
+
+	new_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR |
+		      S_IWUSR | S_IRGRP | S_IROTH);
+	if (write(new_fd, image, size) != size) {
+		perror("Error while writing");
+		return -1;
+	}
+	close(new_fd);
+
+	return 0;
+}
+
+/**
+ * set_spi_frequency() - Set the SPI frequency to use when booting
+ *
+ * Several frequencies are supported, some of which work with fast devices.
+ * For SPI emulators, the slowest (SPI_FREQUENCY_20MHZ) is often used. The
+ * Intel boot system uses this information somehow on boot.
+ *
+ * The image is updated with the supplied value
+ *
+ * @image:	Pointer to image
+ * @size:	Size of image in bytes
+ * @freq:	SPI frequency to use
+ */
+static void set_spi_frequency(char *image, int size, enum spi_frequency freq)
+{
+	struct fdbar_t *fdb = find_fd(image, size);
+	struct fcba_t *fcba;
+
+	fcba = (struct fcba_t *)(image + (((fdb->flmap0) & 0xff) << 4));
+
+	/* clear bits 21-29 */
+	fcba->flcomp &= ~0x3fe00000;
+	/* Read ID and Read Status Clock Frequency */
+	fcba->flcomp |= freq << 27;
+	/* Write and Erase Clock Frequency */
+	fcba->flcomp |= freq << 24;
+	/* Fast Read Clock Frequency */
+	fcba->flcomp |= freq << 21;
+}
+
+/**
+ * set_em100_mode() - Set a SPI frequency that will work with Dediprog EM100
+ *
+ * @image:	Pointer to image
+ * @size:	Size of image in bytes
+ */
+static void set_em100_mode(char *image, int size)
+{
+	struct fdbar_t *fdb = find_fd(image, size);
+	struct fcba_t *fcba;
+
+	fcba = (struct fcba_t *)(image + (((fdb->flmap0) & 0xff) << 4));
+	fcba->flcomp &= ~(1 << 30);
+	set_spi_frequency(image, size, SPI_FREQUENCY_20MHZ);
+}
+
+/**
+ * lock_descriptor() - Lock the NE descriptor so it cannot be updated
+ *
+ * @image:	Pointer to image
+ * @size:	Size of image in bytes
+ */
+static void lock_descriptor(char *image, int size)
+{
+	struct fdbar_t *fdb = find_fd(image, size);
+	struct fmba_t *fmba;
+
+	/*
+	 * TODO: Dynamically take Platform Data Region and GbE Region into
+	 * account.
+	 */
+	fmba = (struct fmba_t *)(image + (((fdb->flmap1) & 0xff) << 4));
+	fmba->flmstr1 = 0x0a0b0000;
+	fmba->flmstr2 = 0x0c0d0000;
+	fmba->flmstr3 = 0x08080118;
+}
+
+/**
+ * unlock_descriptor() - Lock the NE descriptor so it can be updated
+ *
+ * @image:	Pointer to image
+ * @size:	Size of image in bytes
+ */
+static void unlock_descriptor(char *image, int size)
+{
+	struct fdbar_t *fdb = find_fd(image, size);
+	struct fmba_t *fmba;
+
+	fmba = (struct fmba_t *)(image + (((fdb->flmap1) & 0xff) << 4));
+	fmba->flmstr1 = 0xffff0000;
+	fmba->flmstr2 = 0xffff0000;
+	fmba->flmstr3 = 0x08080118;
+}
+
+/**
+ * open_for_read() - Open a file for reading
+ *
+ * @fname:	Filename to open
+ * @sizep:	Returns file size in bytes
+ * @return 0 if OK, -1 on error
+ */
+int open_for_read(const char *fname, int *sizep)
+{
+	int fd = open(fname, O_RDONLY);
+	struct stat buf;
+
+	if (fd == -1) {
+		perror("Could not open file");
+		return -1;
+	}
+	if (fstat(fd, &buf) == -1) {
+		perror("Could not stat file");
+		return -1;
+	}
+	*sizep = buf.st_size;
+	debug("File %s is %d bytes\n", fname, *sizep);
+
+	return fd;
+}
+
+/**
+ * inject_region() - Add a file to an image region
+ *
+ * This puts a file into a particular region of the flash. Several pre-defined
+ * regions are used.
+ *
+ * @image:		Pointer to image
+ * @size:		Size of image in bytes
+ * @region_type:	Region where the file should be added
+ * @region_fname:	Filename to add to the image
+ * @return 0 if OK, -ve on error
+ */
+int inject_region(char *image, int size, int region_type, char *region_fname)
+{
+	struct fdbar_t *fdb = find_fd(image, size);
+	struct region_t region;
+	struct frba_t *frba;
+	int region_size;
+	int offset = 0;
+	int region_fd;
+	int ret;
+
+	if (!fdb)
+		exit(EXIT_FAILURE);
+	frba = (struct frba_t *)(image + (((fdb->flmap0 >> 16) & 0xff) << 4));
+
+	ret = get_region(frba, region_type, &region);
+	if (ret)
+		return -1;
+	if (region.size <= 0xfff) {
+		fprintf(stderr, "Region %s is disabled in target. Not injecting.\n",
+			region_name(region_type));
+		return -1;
+	}
+
+	region_fd = open_for_read(region_fname, &region_size);
+	if (region_fd < 0)
+		return region_fd;
+
+	if ((region_size > region.size) ||
+	    ((region_type != 1) && (region_size > region.size))) {
+		fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)  bytes. Not injecting.\n",
+			region_name(region_type), region.size,
+			region.size, region_size, region_size);
+		return -1;
+	}
+
+	if ((region_type == 1) && (region_size < region.size)) {
+		fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x) bytes. Padding before injecting.\n",
+			region_name(region_type), region.size,
+			region.size, region_size, region_size);
+		offset = region.size - region_size;
+		memset(image + region.base, 0xff, offset);
+	}
+
+	if (size < region.base + offset + region_size) {
+		fprintf(stderr, "Output file is too small. (%d < %d)\n",
+			size, region.base + offset + region_size);
+		return -1;
+	}
+
+	if (read(region_fd, image + region.base + offset, region_size)
+							!= region_size) {
+		perror("Could not read file");
+		return -1;
+	}
+
+	close(region_fd);
+
+	debug("Adding %s as the %s section\n", region_fname,
+	      region_name(region_type));
+
+	return 0;
+}
+
+/**
+ * write_data() - Write some raw data into a region
+ *
+ * This puts a file into a particular place in the flash, ignoring the
+ * regions. Be careful not to overwrite something important.
+ *
+ * @image:		Pointer to image
+ * @size:		Size of image in bytes
+ * @addr:		x86 ROM address to put file. The ROM ends at
+ *			0xffffffff so use an address relative to that. For an
+ *			8MB ROM the start address is 0xfff80000.
+ * @write_fname:	Filename to add to the image
+ * @return 0 if OK, -ve on error
+ */
+static int write_data(char *image, int size, unsigned int addr,
+		      const char *write_fname)
+{
+	int write_fd, write_size;
+	int offset;
+
+	write_fd = open_for_read(write_fname, &write_size);
+	if (write_fd < 0)
+		return write_fd;
+
+	offset = addr + size;
+	debug("Writing %s to offset %#x\n", write_fname, offset);
+
+	if (offset < 0 || offset + write_size > size) {
+		fprintf(stderr, "Output file is too small. (%d < %d)\n",
+			size, offset + write_size);
+		return -1;
+	}
+
+	if (read(write_fd, image + offset, write_size) != write_size) {
+		perror("Could not read file");
+		return -1;
+	}
+
+	close(write_fd);
+
+	return 0;
+}
+
+static void print_version(void)
+{
+	printf("ifdtool v%s -- ", IFDTOOL_VERSION);
+	printf("Copyright (C) 2014 Google Inc.\n\n");
+	printf("SPDX-License-Identifier:	GPL-2.0+\n");
+}
+
+static void print_usage(const char *name)
+{
+	printf("usage: %s [-vhdix?] <filename> [<outfile>]\n", name);
+	printf("\n"
+	       "   -d | --dump:                      dump intel firmware descriptor\n"
+	       "   -x | --extract:                   extract intel fd modules\n"
+	       "   -i | --inject <region>:<module>   inject file <module> into region <region>\n"
+	       "   -w | --write <addr>:<file>        write file to appear at memory address <addr>\n"
+	       "   -s | --spifreq <20|33|50>         set the SPI frequency\n"
+	       "   -e | --em100                      set SPI frequency to 20MHz and disable\n"
+	       "                                     Dual Output Fast Read Support\n"
+	       "   -l | --lock                       Lock firmware descriptor and ME region\n"
+	       "   -u | --unlock                     Unlock firmware descriptor and ME region\n"
+	       "   -r | --romsize                    Specify ROM size\n"
+	       "   -D | --write-descriptor <file>    Write descriptor at base\n"
+	       "   -c | --create                     Create a new empty image\n"
+	       "   -v | --version:                   print the version\n"
+	       "   -h | --help:                      print this help\n\n"
+	       "<region> is one of Descriptor, BIOS, ME, GbE, Platform\n"
+	       "\n");
+}
+
+/**
+ * get_two_words() - Convert a string into two words separated by :
+ *
+ * The supplied string is split at ':', two substrings are allocated and
+ * returned.
+ *
+ * @str:	String to split
+ * @firstp:	Returns first string
+ * @secondp:	Returns second string
+ * @return 0 if OK, -ve if @str does not have a :
+ */
+static int get_two_words(const char *str, char **firstp, char **secondp)
+{
+	const char *p;
+
+	p = strchr(str, ':');
+	if (!p)
+		return -1;
+	*firstp = strdup(str);
+	(*firstp)[p - str] = '\0';
+	*secondp = strdup(p + 1);
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	int opt, option_index = 0;
+	int mode_dump = 0, mode_extract = 0, mode_inject = 0;
+	int mode_spifreq = 0, mode_em100 = 0, mode_locked = 0;
+	int mode_unlocked = 0, mode_write = 0, mode_write_descriptor = 0;
+	int create = 0;
+	char *region_type_string = NULL, *src_fname = NULL;
+	char *addr_str = NULL;
+	int region_type = -1, inputfreq = 0;
+	enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
+	unsigned int addr = 0;
+	int rom_size = -1;
+	bool write_it;
+	char *filename;
+	char *outfile = NULL;
+	struct stat buf;
+	int size = 0;
+	int bios_fd;
+	char *image;
+	int ret;
+	static struct option long_options[] = {
+		{"create", 0, NULL, 'c'},
+		{"dump", 0, NULL, 'd'},
+		{"descriptor", 1, NULL, 'D'},
+		{"em100", 0, NULL, 'e'},
+		{"extract", 0, NULL, 'x'},
+		{"inject", 1, NULL, 'i'},
+		{"lock", 0, NULL, 'l'},
+		{"romsize", 1, NULL, 'r'},
+		{"spifreq", 1, NULL, 's'},
+		{"unlock", 0, NULL, 'u'},
+		{"write", 1, NULL, 'w'},
+		{"version", 0, NULL, 'v'},
+		{"help", 0, NULL, 'h'},
+		{0, 0, 0, 0}
+	};
+
+	while ((opt = getopt_long(argc, argv, "cdD:ehi:lr:s:uvw:x?",
+				  long_options, &option_index)) != EOF) {
+		switch (opt) {
+		case 'c':
+			create = 1;
+			break;
+		case 'd':
+			mode_dump = 1;
+			break;
+		case 'D':
+			mode_write_descriptor = 1;
+			src_fname = optarg;
+			break;
+		case 'e':
+			mode_em100 = 1;
+			break;
+		case 'i':
+			if (get_two_words(optarg, &region_type_string,
+					  &src_fname)) {
+				print_usage(argv[0]);
+				exit(EXIT_FAILURE);
+			}
+			if (!strcasecmp("Descriptor", region_type_string))
+				region_type = 0;
+			else if (!strcasecmp("BIOS", region_type_string))
+				region_type = 1;
+			else if (!strcasecmp("ME", region_type_string))
+				region_type = 2;
+			else if (!strcasecmp("GbE", region_type_string))
+				region_type = 3;
+			else if (!strcasecmp("Platform", region_type_string))
+				region_type = 4;
+			if (region_type == -1) {
+				fprintf(stderr, "No such region type: '%s'\n\n",
+					region_type_string);
+				print_usage(argv[0]);
+				exit(EXIT_FAILURE);
+			}
+			mode_inject = 1;
+			break;
+		case 'l':
+			mode_locked = 1;
+			break;
+		case 'r':
+			rom_size = strtol(optarg, NULL, 0);
+			debug("ROM size %d\n", rom_size);
+			break;
+		case 's':
+			/* Parse the requested SPI frequency */
+			inputfreq = strtol(optarg, NULL, 0);
+			switch (inputfreq) {
+			case 20:
+				spifreq = SPI_FREQUENCY_20MHZ;
+				break;
+			case 33:
+				spifreq = SPI_FREQUENCY_33MHZ;
+				break;
+			case 50:
+				spifreq = SPI_FREQUENCY_50MHZ;
+				break;
+			default:
+				fprintf(stderr, "Invalid SPI Frequency: %d\n",
+					inputfreq);
+				print_usage(argv[0]);
+				exit(EXIT_FAILURE);
+			}
+			mode_spifreq = 1;
+			break;
+		case 'u':
+			mode_unlocked = 1;
+			break;
+		case 'v':
+			print_version();
+			exit(EXIT_SUCCESS);
+			break;
+		case 'w':
+			mode_write = 1;
+			if (get_two_words(optarg, &addr_str, &src_fname)) {
+				print_usage(argv[0]);
+				exit(EXIT_FAILURE);
+			}
+			addr = strtol(optarg, NULL, 0);
+			break;
+		case 'x':
+			mode_extract = 1;
+			break;
+		case 'h':
+		case '?':
+		default:
+			print_usage(argv[0]);
+			exit(EXIT_SUCCESS);
+			break;
+		}
+	}
+
+	if (mode_locked == 1 && mode_unlocked == 1) {
+		fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (mode_inject == 1 && mode_write == 1) {
+		fprintf(stderr, "Inject/Write are mutually exclusive\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if ((mode_dump + mode_extract + mode_inject +
+		(mode_spifreq | mode_em100 | mode_unlocked |
+		 mode_locked)) > 1) {
+		fprintf(stderr, "You may not specify more than one mode.\n\n");
+		print_usage(argv[0]);
+		exit(EXIT_FAILURE);
+	}
+
+	if ((mode_dump + mode_extract + mode_inject + mode_spifreq +
+	     mode_em100 + mode_locked + mode_unlocked + mode_write +
+	     mode_write_descriptor) == 0 && !create) {
+		fprintf(stderr, "You need to specify a mode.\n\n");
+		print_usage(argv[0]);
+		exit(EXIT_FAILURE);
+	}
+
+	if (create && rom_size == -1) {
+		fprintf(stderr, "You need to specify a rom size when creating.\n\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (optind + 1 != argc) {
+		fprintf(stderr, "You need to specify a file.\n\n");
+		print_usage(argv[0]);
+		exit(EXIT_FAILURE);
+	}
+
+	filename = argv[optind];
+	if (optind + 2 != argc)
+		outfile = argv[optind + 1];
+
+	if (create)
+		bios_fd = open(filename, O_WRONLY | O_CREAT, 0666);
+	else
+		bios_fd = open(filename, outfile ? O_RDONLY : O_RDWR);
+
+	if (bios_fd == -1) {
+		perror("Could not open file");
+		exit(EXIT_FAILURE);
+	}
+
+	if (!create) {
+		if (fstat(bios_fd, &buf) == -1) {
+			perror("Could not stat file");
+			exit(EXIT_FAILURE);
+		}
+		size = buf.st_size;
+	}
+
+	debug("File %s is %d bytes\n", filename, size);
+
+	if (rom_size == -1)
+		rom_size = size;
+
+	image = malloc(rom_size);
+	if (!image) {
+		printf("Out of memory.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	memset(image, '\xff', rom_size);
+	if (!create && read(bios_fd, image, size) != size) {
+		perror("Could not read file");
+		exit(EXIT_FAILURE);
+	}
+	if (size != rom_size) {
+		debug("ROM size changed to %d bytes\n", rom_size);
+		size = rom_size;
+	}
+
+	write_it = true;
+	ret = 0;
+	if (mode_dump) {
+		ret = dump_fd(image, size);
+		write_it = false;
+	}
+
+	if (mode_extract) {
+		ret = write_regions(image, size);
+		write_it = false;
+	}
+
+	if (mode_write_descriptor)
+		ret = write_data(image, size, -size, src_fname);
+
+	if (mode_inject)
+		ret = inject_region(image, size, region_type, src_fname);
+
+	if (mode_write)
+		ret = write_data(image, size, addr, src_fname);
+
+	if (mode_spifreq)
+		set_spi_frequency(image, size, spifreq);
+
+	if (mode_em100)
+		set_em100_mode(image, size);
+
+	if (mode_locked)
+		lock_descriptor(image, size);
+
+	if (mode_unlocked)
+		unlock_descriptor(image, size);
+
+	if (write_it) {
+		if (outfile) {
+			ret = write_image(outfile, image, size);
+		} else {
+			if (lseek(bios_fd, 0, SEEK_SET)) {
+				perror("Error while seeking");
+				ret = -1;
+			}
+			if (write(bios_fd, image, size) != size) {
+				perror("Error while writing");
+				ret = -1;
+			}
+		}
+	}
+
+	free(image);
+	close(bios_fd);
+
+	return ret ? 1 : 0;
+}
diff --git a/tools/ifdtool.h b/tools/ifdtool.h
new file mode 100644
index 0000000..fbec421
--- /dev/null
+++ b/tools/ifdtool.h
@@ -0,0 +1,88 @@
+/*
+ * ifdtool - Manage Intel Firmware Descriptor information
+ *
+ * Copyright (C) 2011 The ChromiumOS Authors.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ *
+ * From Coreboot project
+ */
+
+#include <stdint.h>
+
+#define __packed	__attribute__((packed))
+
+#define IFDTOOL_VERSION "1.1-U-Boot"
+
+enum spi_frequency {
+	SPI_FREQUENCY_20MHZ = 0,
+	SPI_FREQUENCY_33MHZ = 1,
+	SPI_FREQUENCY_50MHZ = 4,
+};
+
+enum component_density {
+	COMPONENT_DENSITY_512KB = 0,
+	COMPONENT_DENSITY_1MB   = 1,
+	COMPONENT_DENSITY_2MB   = 2,
+	COMPONENT_DENSITY_4MB   = 3,
+	COMPONENT_DENSITY_8MB   = 4,
+	COMPONENT_DENSITY_16MB  = 5,
+};
+
+/* flash descriptor */
+struct __packed fdbar_t {
+	uint32_t flvalsig;
+	uint32_t flmap0;
+	uint32_t flmap1;
+	uint32_t flmap2;
+	uint8_t  reserved[0xefc - 0x20];
+	uint32_t flumap1;
+};
+
+#define MAX_REGIONS	5
+
+/* regions */
+struct __packed frba_t {
+	uint32_t flreg[MAX_REGIONS];
+};
+
+/* component section */
+struct __packed fcba_t {
+	uint32_t flcomp;
+	uint32_t flill;
+	uint32_t flpb;
+};
+
+#define MAX_STRAPS	18
+
+/* pch strap */
+struct __packed fpsba_t {
+	uint32_t pchstrp[MAX_STRAPS];
+};
+
+/* master */
+struct __packed fmba_t {
+	uint32_t flmstr1;
+	uint32_t flmstr2;
+	uint32_t flmstr3;
+};
+
+/* processor strap */
+struct __packed fmsba_t {
+	uint32_t data[8];
+};
+
+/* ME VSCC */
+struct vscc_t {
+	uint32_t jid;
+	uint32_t vscc;
+};
+
+struct vtba_t {
+	/* Actual number of entries specified in vtl */
+	struct vscc_t entry[8];
+};
+
+struct region_t {
+	int base, limit, size;
+};