Merge https://gitlab.denx.de/u-boot/custodians/u-boot-x86

- Enable SD slot on Intel Edison
- Populate CSRT ACPI table for shared DMA controller on Intel Tangier
- Convert Intel ICH-SPI driver to use new spi-mem ops
- Enable config_distro_bootcmd for QEMU x86
- Support U-Boot as a payload for Intel Slim Bootloader
- Avoid writing temporary asl files into the source tree which fixes the
  parallel build issue occasionally seen
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 70f9398..218e817 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -115,6 +115,7 @@
 source "arch/x86/cpu/qemu/Kconfig"
 source "arch/x86/cpu/quark/Kconfig"
 source "arch/x86/cpu/queensbay/Kconfig"
+source "arch/x86/cpu/slimbootloader/Kconfig"
 source "arch/x86/cpu/tangier/Kconfig"
 
 # architecture-specific options below
@@ -344,9 +345,17 @@
 	  The filename of the file to use as Intel Management Engine in the
 	  board directory.
 
+config USE_HOB
+	bool "Use HOB (Hand-Off Block)"
+	help
+	  Select this option to access HOB (Hand-Off Block) data structures
+	  and parse HOBs. This HOB infra structure can be reused with
+	  different solutions across different platforms.
+
 config HAVE_FSP
 	bool "Add an Firmware Support Package binary"
 	depends on !EFI
+	select USE_HOB
 	help
 	  Select this option to add an Firmware Support Package binary to
 	  the resulting U-Boot image. It is a binary blob which U-Boot uses
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 85fd5e6..3f1f62d 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -42,6 +42,7 @@
 obj-$(CONFIG_INTEL_BRASWELL) += braswell/
 obj-$(CONFIG_INTEL_BROADWELL) += broadwell/
 obj-$(CONFIG_SYS_COREBOOT) += coreboot/
+obj-$(CONFIG_SYS_SLIMBOOTLOADER) += slimbootloader/
 obj-$(CONFIG_EFI) += efi/
 obj-$(CONFIG_QEMU) += qemu/
 obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
diff --git a/arch/x86/cpu/slimbootloader/Kconfig b/arch/x86/cpu/slimbootloader/Kconfig
new file mode 100644
index 0000000..3ea4c99
--- /dev/null
+++ b/arch/x86/cpu/slimbootloader/Kconfig
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2019 Intel Corporation <www.intel.com>
+
+config SYS_SLIMBOOTLOADER
+	bool
+	select USE_HOB
+	imply SYS_NS16550
+	imply AHCI_PCI
+	imply SCSI
+	imply SCSI_AHCI
+	imply MMC
+	imply MMC_PCI
+	imply MMC_SDHCI
+	imply MMC_SDHCI_SDMA
+	imply USB
+	imply USB_EHCI_HCD
+	imply USB_XHCI_HCD
+	imply E1000
diff --git a/arch/x86/cpu/slimbootloader/Makefile b/arch/x86/cpu/slimbootloader/Makefile
new file mode 100644
index 0000000..aac9fa3
--- /dev/null
+++ b/arch/x86/cpu/slimbootloader/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2019 Intel Corporation <www.intel.com>
+
+obj-y += car.o slimbootloader.o sdram.o serial.o
diff --git a/arch/x86/cpu/slimbootloader/car.S b/arch/x86/cpu/slimbootloader/car.S
new file mode 100644
index 0000000..6e03043
--- /dev/null
+++ b/arch/x86/cpu/slimbootloader/car.S
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <generated/asm-offsets.h>
+
+.section .text
+
+.globl car_init
+car_init:
+	/* Get hob pointer parameter from previous stage's stack */
+	mov	0x4(%esp), %esi
+	jmp	car_init_ret
diff --git a/arch/x86/cpu/slimbootloader/sdram.c b/arch/x86/cpu/slimbootloader/sdram.c
new file mode 100644
index 0000000..05d40d1
--- /dev/null
+++ b/arch/x86/cpu/slimbootloader/sdram.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <linux/sizes.h>
+#include <asm/e820.h>
+#include <asm/arch/slimbootloader.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * This returns a data pointer of memory map info from the guid hob.
+ *
+ * @return: A data pointer of memory map info hob
+ */
+static struct sbl_memory_map_info *get_memory_map_info(void)
+{
+	struct sbl_memory_map_info *data;
+	const efi_guid_t guid = SBL_MEMORY_MAP_INFO_GUID;
+
+	if (!gd->arch.hob_list)
+		return NULL;
+
+	data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid);
+	if (!data)
+		panic("memory map info hob not found\n");
+	if (!data->count)
+		panic("invalid number of memory map entries\n");
+
+	return data;
+}
+
+#define for_each_if(condition) if (!(condition)) {} else
+
+#define for_each_memory_map_entry_reversed(iter, entries) \
+	for (iter = entries->count - 1; iter >= 0; iter--) \
+		for_each_if(entries->entry[iter].type == E820_RAM)
+
+/**
+ * This is to give usable memory region information for u-boot relocation.
+ * so search usable memory region lower than 4GB.
+ * The memory map entries from Slim Bootloader hob are already sorted.
+ *
+ * @total_size: The memory size that u-boot occupies
+ * @return    : The top available memory address lower than 4GB
+ */
+ulong board_get_usable_ram_top(ulong total_size)
+{
+	struct sbl_memory_map_info *data;
+	int i;
+	u64 addr_start;
+	u64 addr_end;
+	ulong ram_top;
+
+	data = get_memory_map_info();
+
+	/**
+	 * sorted memory map entries from Slim Bootloader based on physical
+	 * start memory address, from low to high. So do reversed search to
+	 * get highest usable, suitable size, 4KB aligned available memory
+	 * under 4GB.
+	 */
+	ram_top = 0;
+	for_each_memory_map_entry_reversed(i, data) {
+		addr_start = data->entry[i].addr;
+		addr_end = addr_start + data->entry[i].size;
+
+		if (addr_start > SZ_4G)
+			continue;
+
+		if (addr_end > SZ_4G)
+			addr_end = SZ_4G;
+
+		if (addr_end < total_size)
+			continue;
+
+		/* to relocate u-boot at 4K aligned memory */
+		addr_end = rounddown(addr_end - total_size, SZ_4K);
+		if (addr_end >= addr_start) {
+			ram_top = (ulong)addr_end + total_size;
+			break;
+		}
+	}
+
+	if (!ram_top)
+		panic("failed to find available memory for relocation!");
+
+	return ram_top;
+}
+
+/**
+ * The memory initialization has already been done in previous Slim Bootloader
+ * stage thru FSP-M. Instead, this sets the ram_size from the memory map info
+ * hob.
+ */
+int dram_init(void)
+{
+	struct sbl_memory_map_info *data;
+	int i;
+	u64 ram_size;
+
+	data = get_memory_map_info();
+
+	/**
+	 * sorted memory map entries from Slim Bootloader based on physical
+	 * start memory address, from low to high. So do reversed search to
+	 * simply get highest usable memory address as RAM size
+	 */
+	ram_size = 0;
+	for_each_memory_map_entry_reversed(i, data) {
+		/* simply use the highest usable memory address as RAM size */
+		ram_size = data->entry[i].addr + data->entry[i].size;
+		break;
+	}
+
+	if (!ram_size)
+		panic("failed to detect memory size");
+
+	gd->ram_size = ram_size;
+	return 0;
+}
+
+int dram_init_banksize(void)
+{
+	if (!CONFIG_NR_DRAM_BANKS)
+		return 0;
+
+	/* simply use a single bank to have whole size for now */
+	gd->bd->bi_dram[0].start = 0;
+	gd->bd->bi_dram[0].size = gd->ram_size;
+	return 0;
+}
+
+unsigned int install_e820_map(unsigned int max_entries,
+			      struct e820_entry *entries)
+{
+	struct sbl_memory_map_info *data;
+	unsigned int i;
+
+	data = get_memory_map_info();
+
+	for (i = 0; i < data->count; i++) {
+		entries[i].addr = data->entry[i].addr;
+		entries[i].size = data->entry[i].size;
+		entries[i].type = data->entry[i].type;
+	}
+
+	return i;
+}
diff --git a/arch/x86/cpu/slimbootloader/serial.c b/arch/x86/cpu/slimbootloader/serial.c
new file mode 100644
index 0000000..7b44a59
--- /dev/null
+++ b/arch/x86/cpu/slimbootloader/serial.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ns16550.h>
+#include <serial.h>
+#include <asm/arch/slimbootloader.h>
+
+/**
+ * The serial port info hob is generated by Slim Bootloader, so eligible for
+ * Slim Bootloader based boards only.
+ */
+static int slimbootloader_serial_ofdata_to_platdata(struct udevice *dev)
+{
+	const efi_guid_t guid = SBL_SERIAL_PORT_INFO_GUID;
+	struct sbl_serial_port_info *data;
+	struct ns16550_platdata *plat = dev->platdata;
+
+	if (!gd->arch.hob_list)
+		panic("hob list not found!");
+
+	data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid);
+	if (!data) {
+		debug("failed to get serial port information\n");
+		return -ENOENT;
+	}
+	debug("type:%d base=0x%08x baudrate=%d stride=%d clk=%d\n",
+	      data->type,
+	      data->base,
+	      data->baud,
+	      data->stride,
+	      data->clk);
+
+	/*
+	 * The data->type provides port io or mmio access type info,
+	 * but the access type will be controlled by
+	 * CONFIG_SYS_NS16550_PORT_MAPPED or CONFIG_SYS_NS16550_MEM32.
+	 *
+	 * TBD: ns16550 access type configuration in runtime.
+	 *      ex) plat->access_type = data->type
+	 */
+	plat->base = data->base;
+	/* ns16550 uses reg_shift, then covert stride to shift */
+	plat->reg_shift = data->stride >> 1;
+	plat->clock = data->clk;
+
+	return 0;
+}
+
+static const struct udevice_id slimbootloader_serial_ids[] = {
+	{ .compatible = "intel,slimbootloader-uart" },
+	{}
+};
+
+U_BOOT_DRIVER(serial_slimbootloader) = {
+	.name	= "serial_slimbootloader",
+	.id	= UCLASS_SERIAL,
+	.of_match = slimbootloader_serial_ids,
+	.ofdata_to_platdata = slimbootloader_serial_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+	.priv_auto_alloc_size = sizeof(struct NS16550),
+	.probe	= ns16550_serial_probe,
+	.ops	= &ns16550_serial_ops,
+};
diff --git a/arch/x86/cpu/slimbootloader/slimbootloader.c b/arch/x86/cpu/slimbootloader/slimbootloader.c
new file mode 100644
index 0000000..e6b174c
--- /dev/null
+++ b/arch/x86/cpu/slimbootloader/slimbootloader.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+#include <asm/arch/slimbootloader.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * This sets tsc_base and clock_rate for early_timer and tsc_timer.
+ * The performance info guid hob has all performance timestamp data, but
+ * the only tsc frequency info is used for the timer driver for now.
+ *
+ * Slim Bootloader already calibrated TSC and provides it to U-Boot.
+ * Therefore, U-Boot does not have to re-calibrate TSC.
+ * Configuring tsc_base and clock_rate here makes x86 tsc_timer driver
+ * bypass TSC calibration and use the provided TSC frequency.
+ */
+static void tsc_init(void)
+{
+	struct sbl_performance_info *data;
+	const efi_guid_t guid = SBL_PERFORMANCE_INFO_GUID;
+
+	if (!gd->arch.hob_list)
+		panic("hob list not found!");
+
+	gd->arch.tsc_base = rdtsc();
+	debug("tsc_base=0x%llx\n", gd->arch.tsc_base);
+
+	data = hob_get_guid_hob_data(gd->arch.hob_list, NULL, &guid);
+	if (!data) {
+		debug("performance info hob not found\n");
+		return;
+	}
+
+	/* frequency is in KHz, so to Hz */
+	gd->arch.clock_rate = data->frequency * 1000;
+	debug("freq=0x%lx\n", gd->arch.clock_rate);
+}
+
+int arch_cpu_init(void)
+{
+	tsc_init();
+
+	return x86_cpu_init_f();
+}
+
+int checkcpu(void)
+{
+	return 0;
+}
+
+int print_cpuinfo(void)
+{
+	return default_print_cpuinfo();
+}
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 4a82add..71cd70f 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -97,7 +97,7 @@
 	jmp	car_init
 .globl car_init_ret
 car_init_ret:
-#ifndef CONFIG_HAVE_FSP
+#ifndef CONFIG_USE_HOB
 	/*
 	 * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM,
 	 * or fully initialised SDRAM - we really don't care which)
@@ -137,12 +137,13 @@
 
 	/* Get address of global_data */
 	mov	%fs:0, %edx
-#ifdef CONFIG_HAVE_FSP
+#ifdef CONFIG_USE_HOB
 	/* Store the HOB list if we have one */
 	test	%esi, %esi
 	jz	skip_hob
 	movl	%esi, GD_HOB_LIST(%edx)
 
+#ifdef CONFIG_HAVE_FSP
 	/*
 	 * After fsp_init() returns, the stack has already been switched to a
 	 * place within system memory as defined by CONFIG_FSP_TEMP_RAM_ADDR.
@@ -151,6 +152,7 @@
 	 */
 	subl	$CONFIG_FSP_SYS_MALLOC_F_LEN, %esp
 	movl	%esp, GD_MALLOC_BASE(%edx)
+#endif
 skip_hob:
 #else
 	/* Store table pointer */
diff --git a/arch/x86/cpu/tangier/acpi.c b/arch/x86/cpu/tangier/acpi.c
index 0e4f961..61b2642 100644
--- a/arch/x86/cpu/tangier/acpi.c
+++ b/arch/x86/cpu/tangier/acpi.c
@@ -68,6 +68,44 @@
 	return current;
 }
 
+static u32 acpi_fill_csrt_dma(struct acpi_csrt_group *grp)
+{
+	struct acpi_csrt_shared_info *si = (struct acpi_csrt_shared_info *)&grp[1];
+
+	/* Fill the Resource Group with Shared Information attached */
+	memset(grp, 0, sizeof(*grp));
+	grp->shared_info_length = sizeof(struct acpi_csrt_shared_info);
+	grp->length = sizeof(struct acpi_csrt_group) + grp->shared_info_length;
+	/* TODO: All values below should come from U-Boot DT somehow */
+	sprintf((char *)&grp->vendor_id, "%04X", 0x8086);
+	grp->device_id = 0x11a2;
+
+	/* Fill the Resource Group Shared Information */
+	memset(si, 0, sizeof(*si));
+	si->major_version = 1;
+	si->minor_version = 0;
+	/* TODO: All values below should come from U-Boot DT somehow */
+	si->mmio_base_low = 0xff192000;
+	si->mmio_base_high = 0;
+	si->gsi_interrupt = 32;
+	si->interrupt_polarity = 1;
+	si->interrupt_mode = 0;
+	si->num_channels = 8;
+	si->dma_address_width = 32;
+	si->base_request_line = 0;
+	si->num_handshake_signals = 16;
+	si->max_block_size = 0x20000;
+
+	return grp->length;
+}
+
+u32 acpi_fill_csrt(u32 current)
+{
+	current += acpi_fill_csrt_dma((struct acpi_csrt_group *)current);
+
+	return current;
+}
+
 void acpi_create_gnvs(struct acpi_global_nvs *gnvs)
 {
 	struct udevice *dev;
diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile
index fa717bc..d4bdf62 100644
--- a/arch/x86/dts/Makefile
+++ b/arch/x86/dts/Makefile
@@ -18,6 +18,7 @@
 	qemu-x86_i440fx.dtb \
 	qemu-x86_q35.dtb \
 	theadorable-x86-dfi-bt700.dtb \
+	slimbootloader.dtb \
 	baytrail_som-db5800-som-6867.dtb
 
 targets += $(dtb-y)
diff --git a/arch/x86/dts/edison.dts b/arch/x86/dts/edison.dts
index c048765..df24aa0 100644
--- a/arch/x86/dts/edison.dts
+++ b/arch/x86/dts/edison.dts
@@ -84,15 +84,10 @@
 		reg = <0xff3fc000 0x1000>;
 	};
 
-/*
- * FIXME: For now U-Boot DM model doesn't allow to power up this controller.
- * Enabling it will make U-Boot hang.
- *
 	sdcard: mmc@ff3fa000 {
 		compatible = "intel,sdhci-tangier";
 		reg = <0xff3fa000 0x1000>;
 	};
- */
 
 	pmu: power@ff00b000 {
 		compatible = "intel,pmu-mid";
diff --git a/arch/x86/dts/slimbootloader.dts b/arch/x86/dts/slimbootloader.dts
new file mode 100644
index 0000000..d04095c
--- /dev/null
+++ b/arch/x86/dts/slimbootloader.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+/include/ "reset.dtsi"
+/include/ "tsc_timer.dtsi"
+
+/ {
+	model = "slimbootloader x86 payload";
+	compatible = "slimbootloader,x86-payload";
+
+	chosen {
+		stdout-path = &serial;
+	};
+
+	serial: serial {
+		compatible = "intel,slimbootloader-uart";
+	};
+
+	pci {
+		compatible = "pci-x86";
+	};
+};
diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h
index e3b65cf..02aea12 100644
--- a/arch/x86/include/asm/acpi_table.h
+++ b/arch/x86/include/asm/acpi_table.h
@@ -303,6 +303,37 @@
 /* ACPI global NVS structure */
 struct acpi_global_nvs;
 
+/* CSRT (Core System Resource Table) */
+struct acpi_csrt {
+	struct acpi_table_header header;
+};
+
+struct acpi_csrt_group {
+	u32 length;
+	u32 vendor_id;
+	u32 subvendor_id;
+	u16 device_id;
+	u16 subdevice_id;
+	u16 revision;
+	u16 reserved;
+	u32 shared_info_length;
+};
+
+struct acpi_csrt_shared_info {
+	u16 major_version;
+	u16 minor_version;
+	u32 mmio_base_low;
+	u32 mmio_base_high;
+	u32 gsi_interrupt;
+	u8 interrupt_polarity;
+	u8 interrupt_mode;
+	u8 num_channels;
+	u8 dma_address_width;
+	u16 base_request_line;
+	u16 num_handshake_signals;
+	u32 max_block_size;
+};
+
 /* DBG2 definitions are partially used for SPCR interface_type */
 
 /* Types for port_type field */
@@ -370,6 +401,7 @@
 int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
 			      u16 seg_nr, u8 start, u8 end);
 u32 acpi_fill_mcfg(u32 current);
+u32 acpi_fill_csrt(u32 current);
 void acpi_create_gnvs(struct acpi_global_nvs *gnvs);
 ulong write_acpi_tables(ulong start);
 
diff --git a/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h b/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h
new file mode 100644
index 0000000..05dd1b2
--- /dev/null
+++ b/arch/x86/include/asm/arch-slimbootloader/slimbootloader.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#ifndef __SLIMBOOTLOADER_ARCH_H__
+#define __SLIMBOOTLOADER_ARCH_H__
+
+#include <common.h>
+#include <asm/hob.h>
+
+/**
+ * A GUID to get MemoryMap info hob which is provided by Slim Bootloader
+ */
+#define SBL_MEMORY_MAP_INFO_GUID \
+	EFI_GUID(0xa1ff7424, 0x7a1a, 0x478e, \
+		0xa9, 0xe4, 0x92, 0xf3, 0x57, 0xd1, 0x28, 0x32)
+
+/**
+ * A GUID to get SerialPort info hob which is provided by Slim Bootloader
+ */
+#define SBL_SERIAL_PORT_INFO_GUID \
+	EFI_GUID(0x6c6872fe, 0x56a9, 0x4403, \
+		0xbb, 0x98, 0x95, 0x8d, 0x62, 0xde, 0x87, 0xf1)
+
+/**
+ * A GUID to get boot performance info hob which is provided by Slim Bootloader
+ */
+#define SBL_PERFORMANCE_INFO_GUID \
+	EFI_GUID(0x868204be, 0x23d0, 0x4ff9, \
+		0xac, 0x34, 0xb9, 0x95, 0xac, 0x04, 0xb1, 0xb9)
+
+/**
+ * A single entry of memory map information
+ *
+ * @addr: start address of a memory map entry
+ * @size: size of a memory map entry
+ * @type: usable:1, reserved:2, acpi:3, nvs:4, unusable:5
+ * @flag: only used in Slim Bootloader
+ * @rsvd: padding for alignment
+ */
+struct sbl_memory_map_entry {
+	u64	addr;
+	u64	size;
+	u8	type;
+	u8	flag;
+	u8	rsvd[6];
+};
+
+/**
+ * This includes all memory map entries which is sorted based on physical start
+ * address, from low to high, and carved out reserved, acpi nvs, acpi reclaim
+ * and usable memory.
+ *
+ * @rev  : revision of memory_map_info structure. currently 1.
+ * @rsvd : padding for alignment
+ * @count: the number of memory map entries
+ * @entry: array of all memory map entries
+ */
+struct sbl_memory_map_info {
+	u8	rev;
+	u8	rsvd[3];
+	u32	count;
+	struct sbl_memory_map_entry	entry[0];
+};
+
+/**
+ * This includes serial port info which has already been initialized in previous
+ * Slim Bootloader stage.
+ * The Slim Bootloader initializes serial port regardless of debug/release build
+ * modes, and it passes the information to a payload thru hob. So, a payload can
+ * re-use the serial information without re-initializing serial port.
+ *
+ * @rev   : revision of serial_port_info structure. currently 1.
+ * @rsvd  : padding for alignment
+ * @type  : port io: 1, mmio: 2
+ * @base  : io base address. ex) 0x3f8, 0x80001000
+ * @baud  : uart baud rate
+ * @stride: register stride in Bytes
+ * @clk   : uart frequency in Hz
+ * @rsvd1 : reserved
+ */
+struct sbl_serial_port_info {
+	u8      rev;
+	u8      rsvd[3];
+	u32     type;
+	u32     base;
+	u32     baud;
+	u32     stride;
+	u32     clk;
+	u32     rsvd1;
+};
+
+/**
+ * This includes timestamp data which has been collected in Slim Bootloader
+ * stages from the reset vector. In addition, this has TSC frequency in KHz to
+ * calculate each timestamp.
+ *
+ * @rev   : revision of performance_info structure. currently 1.
+ * @rsvd  : padding for alignment
+ * @count : the number of collected timestamp data
+ * @flags : only used in Slim Bootloader
+ * @frequency: tsc frequency in KHz
+ * @timestamp: the array of timestamp data which has 64-bit tsc value
+ */
+struct sbl_performance_info {
+	u8      rev;
+	u8      rsvd[3];
+	u16     count;
+	u16     flags;
+	u32     frequency;
+	u64     timestamp[0];
+};
+
+#endif /* __SLIMBOOTLOADER_ARCH_H__ */
diff --git a/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl
index 8b5b709..b8b783b 100644
--- a/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl
+++ b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl
@@ -421,6 +421,28 @@
             }
         }
     }
+
+    Device (GDMA)
+    {
+        Name (_ADR, 0x00150000)
+        Name (_HID, "808611A2")
+        Name (_UID, Zero)
+
+        Method (_STA, 0, NotSerialized)
+        {
+            Return (STA_VISIBLE)
+        }
+
+        Method (_CRS, 0, Serialized)
+        {
+            Name (RBUF, ResourceTemplate ()
+            {
+                    Memory32Fixed(ReadWrite, 0xFF192000, 0x00001000)
+                    Interrupt(ResourceConsumer, Level, ActiveHigh, Shared, ,, ) { 32 }
+            })
+            Return (RBUF)
+        }
+    }
 }
 
 Device (FLIS)
diff --git a/arch/x86/include/asm/fsp/fsp_ffs.h b/arch/x86/include/asm/fsp/fsp_ffs.h
index 61ce63c..b7558e5 100644
--- a/arch/x86/include/asm/fsp/fsp_ffs.h
+++ b/arch/x86/include/asm/fsp/fsp_ffs.h
@@ -45,7 +45,7 @@
 	 * This GUID is the file name.
 	 * It is used to uniquely identify the file.
 	 */
-	struct efi_guid		name;
+	efi_guid_t		name;
 	/* Used to verify the integrity of the file */
 	union ffs_integrity	integrity;
 	/* Identifies the type of file */
@@ -68,7 +68,7 @@
 	 * Name in any given firmware volume, except if the file type is
 	 * EFI_FV_FILE_TYPE_FFS_PAD.
 	 */
-	struct efi_guid		name;
+	efi_guid_t		name;
 	/* Used to verify the integrity of the file */
 	union ffs_integrity	integrity;
 	/* Identifies the type of file */
diff --git a/arch/x86/include/asm/fsp/fsp_fv.h b/arch/x86/include/asm/fsp/fsp_fv.h
index 190aedc..511dfb7 100644
--- a/arch/x86/include/asm/fsp/fsp_fv.h
+++ b/arch/x86/include/asm/fsp/fsp_fv.h
@@ -80,7 +80,7 @@
 	 * Declares the file system with which the firmware volume
 	 * is formatted.
 	 */
-	struct efi_guid		fs_guid;
+	efi_guid_t		fs_guid;
 	/*
 	 * Length in bytes of the complete firmware volume, including
 	 * the header.
@@ -128,7 +128,7 @@
 /* Extension header pointed by ExtHeaderOffset of volume header */
 struct fv_ext_header {
 	/* firmware volume name */
-	struct efi_guid		fv_name;
+	efi_guid_t		fv_name;
 	/* Size of the rest of the extension header including this structure */
 	u32			ext_hdr_size;
 };
diff --git a/arch/x86/include/asm/fsp/fsp_hob.h b/arch/x86/include/asm/fsp/fsp_hob.h
index 00657b6..3bb79c4 100644
--- a/arch/x86/include/asm/fsp/fsp_hob.h
+++ b/arch/x86/include/asm/fsp/fsp_hob.h
@@ -7,124 +7,7 @@
 #ifndef __FSP_HOB_H__
 #define __FSP_HOB_H__
 
-#include <efi.h>
-
-/* Type of HOB Header */
-#define HOB_TYPE_MEM_ALLOC	0x0002
-#define HOB_TYPE_RES_DESC	0x0003
-#define HOB_TYPE_GUID_EXT	0x0004
-#define HOB_TYPE_UNUSED		0xFFFE
-#define HOB_TYPE_EOH		0xFFFF
-
-/*
- * Describes the format and size of the data inside the HOB.
- * All HOBs must contain this generic HOB header.
- */
-struct hob_header {
-	u16	type;		/* HOB type */
-	u16	len;		/* HOB length */
-	u32	reserved;	/* always zero */
-};
-
-/*
- * Describes all memory ranges used during the HOB producer phase that
- * exist outside the HOB list. This HOB type describes how memory is used,
- * not the physical attributes of memory.
- */
-struct hob_mem_alloc {
-	struct hob_header	hdr;
-	/*
-	 * A GUID that defines the memory allocation region's type and purpose,
-	 * as well as other fields within the memory allocation HOB. This GUID
-	 * is used to define the additional data within the HOB that may be
-	 * present for the memory allocation HOB. Type efi_guid is defined in
-	 * InstallProtocolInterface() in the UEFI 2.0 specification.
-	 */
-	struct efi_guid		name;
-	/*
-	 * The base address of memory allocated by this HOB.
-	 * Type phys_addr_t is defined in AllocatePages() in the UEFI 2.0
-	 * specification.
-	 */
-	phys_addr_t		mem_base;
-	/* The length in bytes of memory allocated by this HOB */
-	phys_size_t		mem_len;
-	/*
-	 * Defines the type of memory allocated by this HOB.
-	 * The memory type definition follows the EFI_MEMORY_TYPE definition.
-	 * Type EFI_MEMORY_TYPE is defined in AllocatePages() in the UEFI 2.0
-	 * specification.
-	 */
-	enum efi_mem_type	mem_type;
-	/* padding */
-	u8			reserved[4];
-};
-
-/* Value of ResourceType in HOB_RES_DESC */
-#define RES_SYS_MEM		0x00000000
-#define RES_MMAP_IO		0x00000001
-#define RES_IO			0x00000002
-#define RES_FW_DEVICE		0x00000003
-#define RES_MMAP_IO_PORT	0x00000004
-#define RES_MEM_RESERVED	0x00000005
-#define RES_IO_RESERVED		0x00000006
-#define RES_MAX_MEM_TYPE	0x00000007
-
-/*
- * These types can be ORed together as needed.
- *
- * The first three enumerations describe settings
- * The rest of the settings describe capabilities
- */
-#define RES_ATTR_PRESENT			0x00000001
-#define RES_ATTR_INITIALIZED			0x00000002
-#define RES_ATTR_TESTED				0x00000004
-#define RES_ATTR_SINGLE_BIT_ECC			0x00000008
-#define RES_ATTR_MULTIPLE_BIT_ECC		0x00000010
-#define RES_ATTR_ECC_RESERVED_1			0x00000020
-#define RES_ATTR_ECC_RESERVED_2			0x00000040
-#define RES_ATTR_READ_PROTECTED			0x00000080
-#define RES_ATTR_WRITE_PROTECTED		0x00000100
-#define RES_ATTR_EXECUTION_PROTECTED		0x00000200
-#define RES_ATTR_UNCACHEABLE			0x00000400
-#define RES_ATTR_WRITE_COMBINEABLE		0x00000800
-#define RES_ATTR_WRITE_THROUGH_CACHEABLE	0x00001000
-#define RES_ATTR_WRITE_BACK_CACHEABLE		0x00002000
-#define RES_ATTR_16_BIT_IO			0x00004000
-#define RES_ATTR_32_BIT_IO			0x00008000
-#define RES_ATTR_64_BIT_IO			0x00010000
-#define RES_ATTR_UNCACHED_EXPORTED		0x00020000
-
-/*
- * Describes the resource properties of all fixed, nonrelocatable resource
- * ranges found on the processor host bus during the HOB producer phase.
- */
-struct hob_res_desc {
-	struct hob_header	hdr;
-	/*
-	 * A GUID representing the owner of the resource. This GUID is
-	 * used by HOB consumer phase components to correlate device
-	 * ownership of a resource.
-	 */
-	struct efi_guid		owner;
-	u32			type;
-	u32			attr;
-	/* The physical start address of the resource region */
-	phys_addr_t		phys_start;
-	/* The number of bytes of the resource region */
-	phys_size_t		len;
-};
-
-/*
- * Allows writers of executable content in the HOB producer phase to
- * maintain and manage HOBs with specific GUID.
- */
-struct hob_guid {
-	struct hob_header	hdr;
-	/* A GUID that defines the contents of this HOB */
-	struct efi_guid		name;
-	/* GUID specific data goes here */
-};
+#include <asm/hob.h>
 
 enum pixel_format {
 	pixel_rgbx_8bpc,	/* RGB 8 bit per color */
@@ -146,70 +29,6 @@
 	u32 pixels_per_scanline;
 };
 
-/**
- * get_next_hob() - return a pointer to the next HOB in the HOB list
- *
- * This macro returns a pointer to HOB that follows the HOB specified by hob
- * in the HOB List.
- *
- * @hdr:    A pointer to a HOB.
- *
- * @return: A pointer to the next HOB in the HOB list.
- */
-static inline const struct hob_header *get_next_hob(const struct hob_header *hdr)
-{
-	return (const struct hob_header *)((uintptr_t)hdr + hdr->len);
-}
-
-/**
- * end_of_hob() - determine if a HOB is the last HOB in the HOB list
- *
- * This macro determine if the HOB specified by hob is the last HOB in the
- * HOB list.  If hob is last HOB in the HOB list, then true is returned.
- * Otherwise, false is returned.
- *
- * @hdr:          A pointer to a HOB.
- *
- * @retval true:  The HOB specified by hdr is the last HOB in the HOB list.
- * @retval false: The HOB specified by hdr is not the last HOB in the HOB list.
- */
-static inline bool end_of_hob(const struct hob_header *hdr)
-{
-	return hdr->type == HOB_TYPE_EOH;
-}
-
-/**
- * get_guid_hob_data() - return a pointer to data buffer from a HOB of
- *                       type HOB_TYPE_GUID_EXT
- *
- * This macro returns a pointer to the data buffer in a HOB specified by hob.
- * hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
- *
- * @hdr:    A pointer to a HOB.
- *
- * @return: A pointer to the data buffer in a HOB.
- */
-static inline void *get_guid_hob_data(const struct hob_header *hdr)
-{
-	return (void *)((uintptr_t)hdr + sizeof(struct hob_guid));
-}
-
-/**
- * get_guid_hob_data_size() - return the size of the data buffer from a HOB
- *                            of type HOB_TYPE_GUID_EXT
- *
- * This macro returns the size, in bytes, of the data buffer in a HOB
- * specified by hob. hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
- *
- * @hdr:    A pointer to a HOB.
- *
- * @return: The size of the data buffer.
- */
-static inline u16 get_guid_hob_data_size(const struct hob_header *hdr)
-{
-	return hdr->len - sizeof(struct hob_guid);
-}
-
 /* FSP specific GUID HOB definitions */
 #define FSP_GUID_DATA1		0x912740be
 #define FSP_GUID_DATA2		0x2284
@@ -223,56 +42,57 @@
 #define FSP_GUID_DATA4_6	0x3f
 #define FSP_GUID_DATA4_7	0x0c
 
+#define FSP_GUID_BYTE0		0xbe
+#define FSP_GUID_BYTE1		0x40
+#define FSP_GUID_BYTE2		0x27
+#define FSP_GUID_BYTE3		0x91
+#define FSP_GUID_BYTE4		0x84
+#define FSP_GUID_BYTE5		0x22
+#define FSP_GUID_BYTE6		0x34
+#define FSP_GUID_BYTE7		0x47
+#define FSP_GUID_BYTE8		FSP_GUID_DATA4_0
+#define FSP_GUID_BYTE9		FSP_GUID_DATA4_1
+#define FSP_GUID_BYTE10		FSP_GUID_DATA4_2
+#define FSP_GUID_BYTE11		FSP_GUID_DATA4_3
+#define FSP_GUID_BYTE12		FSP_GUID_DATA4_4
+#define FSP_GUID_BYTE13		FSP_GUID_DATA4_5
+#define FSP_GUID_BYTE14		FSP_GUID_DATA4_6
+#define FSP_GUID_BYTE15		FSP_GUID_DATA4_7
+
 #define FSP_HEADER_GUID \
-	{ \
-	FSP_GUID_DATA1, FSP_GUID_DATA2, FSP_GUID_DATA3, \
-	{ FSP_GUID_DATA4_0, FSP_GUID_DATA4_1, FSP_GUID_DATA4_2, \
-	  FSP_GUID_DATA4_3, FSP_GUID_DATA4_4, FSP_GUID_DATA4_5, \
-	  FSP_GUID_DATA4_6, FSP_GUID_DATA4_7 } \
-	}
+	EFI_GUID(FSP_GUID_DATA1, FSP_GUID_DATA2, FSP_GUID_DATA3, \
+		FSP_GUID_DATA4_0, FSP_GUID_DATA4_1, FSP_GUID_DATA4_2, \
+		FSP_GUID_DATA4_3, FSP_GUID_DATA4_4, FSP_GUID_DATA4_5, \
+		FSP_GUID_DATA4_6, FSP_GUID_DATA4_7)
 
 #define FSP_NON_VOLATILE_STORAGE_HOB_GUID \
-	{ \
-	0x721acf02, 0x4d77, 0x4c2a, \
-	{ 0xb3, 0xdc, 0x27, 0xb, 0x7b, 0xa9, 0xe4, 0xb0 } \
-	}
+	EFI_GUID(0x721acf02, 0x4d77, 0x4c2a, \
+		0xb3, 0xdc, 0x27, 0x0b, 0x7b, 0xa9, 0xe4, 0xb0)
 
 #define FSP_BOOTLOADER_TEMP_MEM_HOB_GUID \
-	{ \
-	0xbbcff46c, 0xc8d3, 0x4113, \
-	{ 0x89, 0x85, 0xb9, 0xd4, 0xf3, 0xb3, 0xf6, 0x4e } \
-	}
+	EFI_GUID(0xbbcff46c, 0xc8d3, 0x4113, \
+		0x89, 0x85, 0xb9, 0xd4, 0xf3, 0xb3, 0xf6, 0x4e)
 
 #define FSP_HOB_RESOURCE_OWNER_FSP_GUID \
-	{ \
-	0x69a79759, 0x1373, 0x4367, \
-	{ 0xa6, 0xc4, 0xc7, 0xf5, 0x9e, 0xfd, 0x98, 0x6e } \
-	}
+	EFI_GUID(0x69a79759, 0x1373, 0x4367, \
+		0xa6, 0xc4, 0xc7, 0xf5, 0x9e, 0xfd, 0x98, 0x6e)
 
 #define FSP_HOB_RESOURCE_OWNER_TSEG_GUID \
-	{ \
-	0xd038747c, 0xd00c, 0x4980, \
-	{ 0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55 } \
-	}
+	EFI_GUID(0xd038747c, 0xd00c, 0x4980, \
+		0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55)
 
 #define FSP_HOB_RESOURCE_OWNER_GRAPHICS_GUID \
-	{ \
-	0x9c7c3aa7, 0x5332, 0x4917, \
-	{ 0x82, 0xb9, 0x56, 0xa5, 0xf3, 0xe6, 0x2a, 0x07 } \
-	}
+	EFI_GUID(0x9c7c3aa7, 0x5332, 0x4917, \
+		0x82, 0xb9, 0x56, 0xa5, 0xf3, 0xe6, 0x2a, 0x07)
 
 /* The following GUIDs are newly introduced in FSP spec 1.1 */
 
 #define FSP_HOB_RESOURCE_OWNER_BOOTLOADER_TOLUM_GUID \
-	{ \
-	0x73ff4f56, 0xaa8e, 0x4451, \
-	{ 0xb3, 0x16, 0x36, 0x35, 0x36, 0x67, 0xad, 0x44 } \
-	}
+	EFI_GUID(0x73ff4f56, 0xaa8e, 0x4451, \
+		0xb3, 0x16, 0x36, 0x35, 0x36, 0x67, 0xad, 0x44)
 
 #define FSP_GRAPHICS_INFO_HOB_GUID \
-	{ \
-	0x39f62cce, 0x6825, 0x4669, \
-	{ 0xbb, 0x56, 0x54, 0x1a, 0xba, 0x75, 0x3a, 0x07 } \
-	}
+	EFI_GUID(0x39f62cce, 0x6825, 0x4669, \
+		0xbb, 0x56, 0x54, 0x1a, 0xba, 0x75, 0x3a, 0x07)
 
 #endif
diff --git a/arch/x86/include/asm/fsp/fsp_support.h b/arch/x86/include/asm/fsp/fsp_support.h
index 7e51f24..7b92392 100644
--- a/arch/x86/include/asm/fsp/fsp_support.h
+++ b/arch/x86/include/asm/fsp/fsp_support.h
@@ -8,10 +8,10 @@
 #define __FSP_SUPPORT_H__
 
 #include "fsp_types.h"
+#include "fsp_hob.h"
 #include "fsp_fv.h"
 #include "fsp_ffs.h"
 #include "fsp_api.h"
-#include "fsp_hob.h"
 #include "fsp_infoheader.h"
 #include "fsp_bootmode.h"
 #include "fsp_azalia.h"
@@ -106,7 +106,7 @@
  *            0 if this region does not exist.
  */
 u64 fsp_get_reserved_mem_from_guid(const void *hob_list,
-				   u64 *len, struct efi_guid *guid);
+				   u64 *len, const efi_guid_t *guid);
 
 /**
  * This function retrieves the FSP reserved normal memory.
@@ -132,41 +132,6 @@
 u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len);
 
 /**
- * Returns the next instance of a HOB type from the starting HOB.
- *
- * @type:     HOB type to search
- * @hob_list: A pointer to the HOB list
- *
- * @retval:   A HOB object with matching type; Otherwise NULL.
- */
-const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list);
-
-/**
- * Returns the next instance of the matched GUID HOB from the starting HOB.
- *
- * @guid:     GUID to search
- * @hob_list: A pointer to the HOB list
- *
- * @retval:   A HOB object with matching GUID; Otherwise NULL.
- */
-const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid,
-					       const void *hob_list);
-
-/**
- * This function retrieves a GUID HOB data buffer and size.
- *
- * @hob_list:      A HOB list pointer.
- * @len:           A pointer to the GUID HOB data buffer length.
- *                 If the GUID HOB is located, the length will be updated.
- * @guid           A pointer to HOB GUID.
- *
- * @retval NULL:   Failed to find the GUID HOB.
- * @retval others: GUID HOB data buffer pointer.
- */
-void *fsp_get_guid_hob_data(const void *hob_list, u32 *len,
-			    struct efi_guid *guid);
-
-/**
  * This function retrieves FSP Non-volatile Storage HOB buffer and size.
  *
  * @hob_list:      A HOB list pointer.
diff --git a/arch/x86/include/asm/fsp/fsp_types.h b/arch/x86/include/asm/fsp/fsp_types.h
index 5247102..3d5b17e 100644
--- a/arch/x86/include/asm/fsp/fsp_types.h
+++ b/arch/x86/include/asm/fsp/fsp_types.h
@@ -7,14 +7,6 @@
 #ifndef __FSP_TYPES_H__
 #define __FSP_TYPES_H__
 
-/* 128 bit buffer containing a unique identifier value */
-struct efi_guid {
-	u32	data1;
-	u16	data2;
-	u16	data3;
-	u8	data4[8];
-};
-
 /**
  * Returns a 16-bit signature built from 2 ASCII characters.
  *
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 9398ec3..797397e 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -83,7 +83,7 @@
 	const struct pch_gpio_map *gpio_map;	/* board GPIO map */
 	struct memory_info meminfo;	/* Memory information */
 	struct pei_memory_info pei_meminfo;	/* PEI memory information */
-#ifdef CONFIG_HAVE_FSP
+#ifdef CONFIG_USE_HOB
 	void *hob_list;			/* FSP HOB list */
 #endif
 	struct mtrr_request mtrr_req[MAX_MTRR_REQUESTS];
diff --git a/arch/x86/include/asm/hob.h b/arch/x86/include/asm/hob.h
new file mode 100644
index 0000000..b423982
--- /dev/null
+++ b/arch/x86/include/asm/hob.h
@@ -0,0 +1,230 @@
+/* SPDX-License-Identifier: Intel */
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#ifndef __HOB_H__
+#define __HOB_H__
+
+#include <efi.h>
+#include <efi_loader.h>
+
+/* Type of HOB Header */
+#define HOB_TYPE_MEM_ALLOC	0x0002
+#define HOB_TYPE_RES_DESC	0x0003
+#define HOB_TYPE_GUID_EXT	0x0004
+#define HOB_TYPE_UNUSED		0xFFFE
+#define HOB_TYPE_EOH		0xFFFF
+
+/* Value of ResourceType in HOB_RES_DESC */
+#define RES_SYS_MEM		0x00000000
+#define RES_MMAP_IO		0x00000001
+#define RES_IO			0x00000002
+#define RES_FW_DEVICE		0x00000003
+#define RES_MMAP_IO_PORT	0x00000004
+#define RES_MEM_RESERVED	0x00000005
+#define RES_IO_RESERVED		0x00000006
+#define RES_MAX_MEM_TYPE	0x00000007
+
+/*
+ * These types can be ORed together as needed.
+ *
+ * The first three enumerations describe settings
+ * The rest of the settings describe capabilities
+ */
+#define RES_ATTR_PRESENT			0x00000001
+#define RES_ATTR_INITIALIZED			0x00000002
+#define RES_ATTR_TESTED				0x00000004
+#define RES_ATTR_SINGLE_BIT_ECC			0x00000008
+#define RES_ATTR_MULTIPLE_BIT_ECC		0x00000010
+#define RES_ATTR_ECC_RESERVED_1			0x00000020
+#define RES_ATTR_ECC_RESERVED_2			0x00000040
+#define RES_ATTR_READ_PROTECTED			0x00000080
+#define RES_ATTR_WRITE_PROTECTED		0x00000100
+#define RES_ATTR_EXECUTION_PROTECTED		0x00000200
+#define RES_ATTR_UNCACHEABLE			0x00000400
+#define RES_ATTR_WRITE_COMBINEABLE		0x00000800
+#define RES_ATTR_WRITE_THROUGH_CACHEABLE	0x00001000
+#define RES_ATTR_WRITE_BACK_CACHEABLE		0x00002000
+#define RES_ATTR_16_BIT_IO			0x00004000
+#define RES_ATTR_32_BIT_IO			0x00008000
+#define RES_ATTR_64_BIT_IO			0x00010000
+#define RES_ATTR_UNCACHED_EXPORTED		0x00020000
+
+/*
+ * Describes the format and size of the data inside the HOB.
+ * All HOBs must contain this generic HOB header.
+ */
+struct hob_header {
+	u16	type;		/* HOB type */
+	u16	len;		/* HOB length */
+	u32	reserved;	/* always zero */
+};
+
+/*
+ * Describes all memory ranges used during the HOB producer phase that
+ * exist outside the HOB list. This HOB type describes how memory is used,
+ * not the physical attributes of memory.
+ */
+struct hob_mem_alloc {
+	struct hob_header	hdr;
+	/*
+	 * A GUID that defines the memory allocation region's type and purpose,
+	 * as well as other fields within the memory allocation HOB. This GUID
+	 * is used to define the additional data within the HOB that may be
+	 * present for the memory allocation HOB. Type efi_guid_t is defined in
+	 * InstallProtocolInterface() in the UEFI 2.0 specification.
+	 */
+	efi_guid_t		name;
+	/*
+	 * The base address of memory allocated by this HOB.
+	 * Type phys_addr_t is defined in AllocatePages() in the UEFI 2.0
+	 * specification.
+	 */
+	phys_addr_t		mem_base;
+	/* The length in bytes of memory allocated by this HOB */
+	phys_size_t		mem_len;
+	/*
+	 * Defines the type of memory allocated by this HOB.
+	 * The memory type definition follows the EFI_MEMORY_TYPE definition.
+	 * Type EFI_MEMORY_TYPE is defined in AllocatePages() in the UEFI 2.0
+	 * specification.
+	 */
+	enum efi_mem_type	mem_type;
+	/* padding */
+	u8			reserved[4];
+};
+
+/*
+ * Describes the resource properties of all fixed, nonrelocatable resource
+ * ranges found on the processor host bus during the HOB producer phase.
+ */
+struct hob_res_desc {
+	struct hob_header	hdr;
+	/*
+	 * A GUID representing the owner of the resource. This GUID is
+	 * used by HOB consumer phase components to correlate device
+	 * ownership of a resource.
+	 */
+	efi_guid_t		owner;
+	u32			type;
+	u32			attr;
+	/* The physical start address of the resource region */
+	phys_addr_t		phys_start;
+	/* The number of bytes of the resource region */
+	phys_size_t		len;
+};
+
+/*
+ * Allows writers of executable content in the HOB producer phase to
+ * maintain and manage HOBs with specific GUID.
+ */
+struct hob_guid {
+	struct hob_header	hdr;
+	/* A GUID that defines the contents of this HOB */
+	efi_guid_t		name;
+	/* GUID specific data goes here */
+};
+
+/**
+ * get_next_hob() - return a pointer to the next HOB in the HOB list
+ *
+ * This macro returns a pointer to HOB that follows the HOB specified by hob
+ * in the HOB List.
+ *
+ * @hdr:    A pointer to a HOB.
+ *
+ * @return: A pointer to the next HOB in the HOB list.
+ */
+static inline const struct hob_header *get_next_hob(const struct hob_header
+						    *hdr)
+{
+	return (const struct hob_header *)((uintptr_t)hdr + hdr->len);
+}
+
+/**
+ * end_of_hob() - determine if a HOB is the last HOB in the HOB list
+ *
+ * This macro determine if the HOB specified by hob is the last HOB in the
+ * HOB list.  If hob is last HOB in the HOB list, then true is returned.
+ * Otherwise, false is returned.
+ *
+ * @hdr:          A pointer to a HOB.
+ *
+ * @retval true:  The HOB specified by hdr is the last HOB in the HOB list.
+ * @retval false: The HOB specified by hdr is not the last HOB in the HOB list.
+ */
+static inline bool end_of_hob(const struct hob_header *hdr)
+{
+	return hdr->type == HOB_TYPE_EOH;
+}
+
+/**
+ * get_guid_hob_data() - return a pointer to data buffer from a HOB of
+ *                       type HOB_TYPE_GUID_EXT
+ *
+ * This macro returns a pointer to the data buffer in a HOB specified by hob.
+ * hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
+ *
+ * @hdr:    A pointer to a HOB.
+ *
+ * @return: A pointer to the data buffer in a HOB.
+ */
+static inline void *get_guid_hob_data(const struct hob_header *hdr)
+{
+	return (void *)((uintptr_t)hdr + sizeof(struct hob_guid));
+}
+
+/**
+ * get_guid_hob_data_size() - return the size of the data buffer from a HOB
+ *                            of type HOB_TYPE_GUID_EXT
+ *
+ * This macro returns the size, in bytes, of the data buffer in a HOB
+ * specified by hob. hob is assumed to be a HOB of type HOB_TYPE_GUID_EXT.
+ *
+ * @hdr:    A pointer to a HOB.
+ *
+ * @return: The size of the data buffer.
+ */
+static inline u16 get_guid_hob_data_size(const struct hob_header *hdr)
+{
+	return hdr->len - sizeof(struct hob_guid);
+}
+
+/**
+ * Returns the next instance of a HOB type from the starting HOB.
+ *
+ * @type:     HOB type to search
+ * @hob_list: A pointer to the HOB list
+ *
+ * @retval:   A HOB object with matching type; Otherwise NULL.
+ */
+const struct hob_header *hob_get_next_hob(uint type, const void *hob_list);
+
+/**
+ * Returns the next instance of the matched GUID HOB from the starting HOB.
+ *
+ * @guid:     GUID to search
+ * @hob_list: A pointer to the HOB list
+ *
+ * @retval:   A HOB object with matching GUID; Otherwise NULL.
+ */
+const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid,
+					       const void *hob_list);
+
+/**
+ * This function retrieves a GUID HOB data buffer and size.
+ *
+ * @hob_list:      A HOB list pointer.
+ * @len:           A pointer to the GUID HOB data buffer length.
+ *                 If the GUID HOB is located, the length will be updated.
+ * @guid           A pointer to HOB GUID.
+ *
+ * @retval NULL:   Failed to find the GUID HOB.
+ * @retval others: GUID HOB data buffer pointer.
+ */
+void *hob_get_guid_hob_data(const void *hob_list, u32 *len,
+			    const efi_guid_t *guid);
+
+#endif /* __HOB_H__ */
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 436252d..906be5e 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -42,6 +42,7 @@
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_CMD_ZBOOT)	+= zimage.o
 endif
+obj-$(CONFIG_USE_HOB) += hob.o
 obj-$(CONFIG_HAVE_FSP) += fsp/
 
 ifdef CONFIG_SPL_BUILD
diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c
index 270274f..0d69cf2 100644
--- a/arch/x86/lib/acpi_table.c
+++ b/arch/x86/lib/acpi_table.c
@@ -337,6 +337,30 @@
 	header->checksum = table_compute_checksum((void *)mcfg, header->length);
 }
 
+__weak u32 acpi_fill_csrt(u32 current)
+{
+	return current;
+}
+
+static void acpi_create_csrt(struct acpi_csrt *csrt)
+{
+	struct acpi_table_header *header = &(csrt->header);
+	u32 current = (u32)csrt + sizeof(struct acpi_csrt);
+
+	memset((void *)csrt, 0, sizeof(struct acpi_csrt));
+
+	/* Fill out header fields */
+	acpi_fill_header(header, "CSRT");
+	header->length = sizeof(struct acpi_csrt);
+	header->revision = 0;
+
+	current = acpi_fill_csrt(current);
+
+	/* (Re)calculate length and checksum */
+	header->length = current - (u32)csrt;
+	header->checksum = table_compute_checksum((void *)csrt, header->length);
+}
+
 static void acpi_create_spcr(struct acpi_spcr *spcr)
 {
 	struct acpi_table_header *header = &(spcr->header);
@@ -464,6 +488,7 @@
 	struct acpi_fadt *fadt;
 	struct acpi_mcfg *mcfg;
 	struct acpi_madt *madt;
+	struct acpi_csrt *csrt;
 	struct acpi_spcr *spcr;
 	int i;
 
@@ -553,6 +578,13 @@
 	acpi_add_table(rsdp, mcfg);
 	current = ALIGN(current, 16);
 
+	debug("ACPI:    * CSRT\n");
+	csrt = (struct acpi_csrt *)current;
+	acpi_create_csrt(csrt);
+	current += csrt->header.length;
+	acpi_add_table(rsdp, csrt);
+	current = ALIGN(current, 16);
+
 	debug("ACPI:    * SPCR\n");
 	spcr = (struct acpi_spcr *)current;
 	acpi_create_spcr(spcr);
diff --git a/arch/x86/lib/asm-offsets.c b/arch/x86/lib/asm-offsets.c
index 90dce22..47b38cd 100644
--- a/arch/x86/lib/asm-offsets.c
+++ b/arch/x86/lib/asm-offsets.c
@@ -17,7 +17,7 @@
 int main(void)
 {
 	DEFINE(GD_BIST, offsetof(gd_t, arch.bist));
-#ifdef CONFIG_HAVE_FSP
+#ifdef CONFIG_USE_HOB
 	DEFINE(GD_HOB_LIST, offsetof(gd_t, arch.hob_list));
 #endif
 	DEFINE(GD_TABLE, offsetof(gd_t, arch.table));
diff --git a/arch/x86/lib/fsp/fsp_support.c b/arch/x86/lib/fsp/fsp_support.c
index 90e4e7d..0eaa9b2 100644
--- a/arch/x86/lib/fsp/fsp_support.c
+++ b/arch/x86/lib/fsp/fsp_support.c
@@ -8,27 +8,6 @@
 #include <asm/fsp/fsp_support.h>
 #include <asm/post.h>
 
-/**
- * Compares two GUIDs
- *
- * If the GUIDs are identical then true is returned.
- * If there are any bit differences in the two GUIDs, then false is returned.
- *
- * @guid1:        A pointer to a 128 bit GUID.
- * @guid2:        A pointer to a 128 bit GUID.
- *
- * @retval true:  guid1 and guid2 are identical.
- * @retval false: guid1 and guid2 are not identical.
- */
-static bool compare_guid(const struct efi_guid *guid1,
-			 const struct efi_guid *guid2)
-{
-	if (memcmp(guid1, guid2, sizeof(struct efi_guid)) == 0)
-		return true;
-	else
-		return false;
-}
-
 struct fsp_header *__attribute__((optimize("O0"))) find_fsp_header(void)
 {
 	/*
@@ -58,17 +37,22 @@
 
 	/* Check the FFS GUID */
 	if (fsp &&
-	    ((struct ffs_file_header *)fsp)->name.data1 == FSP_GUID_DATA1 &&
-	    ((struct ffs_file_header *)fsp)->name.data2 == FSP_GUID_DATA2 &&
-	    ((struct ffs_file_header *)fsp)->name.data3 == FSP_GUID_DATA3 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[0] == FSP_GUID_DATA4_0 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[1] == FSP_GUID_DATA4_1 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[2] == FSP_GUID_DATA4_2 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[3] == FSP_GUID_DATA4_3 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[4] == FSP_GUID_DATA4_4 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[5] == FSP_GUID_DATA4_5 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[6] == FSP_GUID_DATA4_6 &&
-	    ((struct ffs_file_header *)fsp)->name.data4[7] == FSP_GUID_DATA4_7) {
+	    ((struct ffs_file_header *)fsp)->name.b[0] == FSP_GUID_BYTE0 &&
+	    ((struct ffs_file_header *)fsp)->name.b[1] == FSP_GUID_BYTE1 &&
+	    ((struct ffs_file_header *)fsp)->name.b[2] == FSP_GUID_BYTE2 &&
+	    ((struct ffs_file_header *)fsp)->name.b[3] == FSP_GUID_BYTE3 &&
+	    ((struct ffs_file_header *)fsp)->name.b[4] == FSP_GUID_BYTE4 &&
+	    ((struct ffs_file_header *)fsp)->name.b[5] == FSP_GUID_BYTE5 &&
+	    ((struct ffs_file_header *)fsp)->name.b[6] == FSP_GUID_BYTE6 &&
+	    ((struct ffs_file_header *)fsp)->name.b[7] == FSP_GUID_BYTE7 &&
+	    ((struct ffs_file_header *)fsp)->name.b[8] == FSP_GUID_BYTE8 &&
+	    ((struct ffs_file_header *)fsp)->name.b[9] == FSP_GUID_BYTE9 &&
+	    ((struct ffs_file_header *)fsp)->name.b[10] == FSP_GUID_BYTE10 &&
+	    ((struct ffs_file_header *)fsp)->name.b[11] == FSP_GUID_BYTE11 &&
+	    ((struct ffs_file_header *)fsp)->name.b[12] == FSP_GUID_BYTE12 &&
+	    ((struct ffs_file_header *)fsp)->name.b[13] == FSP_GUID_BYTE13 &&
+	    ((struct ffs_file_header *)fsp)->name.b[14] == FSP_GUID_BYTE14 &&
+	    ((struct ffs_file_header *)fsp)->name.b[15] == FSP_GUID_BYTE15) {
 		/* Add the FFS header size to find the raw section header */
 		fsp += sizeof(struct ffs_file_header);
 	} else {
@@ -305,7 +289,7 @@
 }
 
 u64 fsp_get_reserved_mem_from_guid(const void *hob_list, u64 *len,
-				   struct efi_guid *guid)
+				   const efi_guid_t *guid)
 {
 	const struct hob_header *hdr;
 	struct hob_res_desc *res_desc;
@@ -318,7 +302,7 @@
 		if (hdr->type == HOB_TYPE_RES_DESC) {
 			res_desc = (struct hob_res_desc *)hdr;
 			if (res_desc->type == RES_MEM_RESERVED) {
-				if (compare_guid(&res_desc->owner, guid)) {
+				if (!guidcmp(&res_desc->owner, guid)) {
 					if (len)
 						*len = (u32)(res_desc->len);
 
@@ -334,12 +318,12 @@
 
 u32 fsp_get_fsp_reserved_mem(const void *hob_list, u32 *len)
 {
-	const struct efi_guid guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID;
+	const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_FSP_GUID;
 	u64 length;
 	u32 base;
 
 	base = (u32)fsp_get_reserved_mem_from_guid(hob_list,
-			&length, (struct efi_guid *)&guid);
+			&length, &guid);
 	if ((len != 0) && (base != 0))
 		*len = (u32)length;
 
@@ -348,86 +332,35 @@
 
 u32 fsp_get_tseg_reserved_mem(const void *hob_list, u32 *len)
 {
-	const struct efi_guid guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID;
+	const efi_guid_t guid = FSP_HOB_RESOURCE_OWNER_TSEG_GUID;
 	u64 length;
 	u32 base;
 
 	base = (u32)fsp_get_reserved_mem_from_guid(hob_list,
-			&length, (struct efi_guid *)&guid);
+			&length, &guid);
 	if ((len != 0) && (base != 0))
 		*len = (u32)length;
 
 	return base;
 }
 
-const struct hob_header *fsp_get_next_hob(uint type, const void *hob_list)
-{
-	const struct hob_header *hdr;
-
-	hdr = hob_list;
-
-	/* Parse the HOB list until end of list or matching type is found */
-	while (!end_of_hob(hdr)) {
-		if (hdr->type == type)
-			return hdr;
-
-		hdr = get_next_hob(hdr);
-	}
-
-	return NULL;
-}
-
-const struct hob_header *fsp_get_next_guid_hob(const struct efi_guid *guid,
-					       const void *hob_list)
-{
-	const struct hob_header *hdr;
-	struct hob_guid *guid_hob;
-
-	hdr = hob_list;
-	while ((hdr = fsp_get_next_hob(HOB_TYPE_GUID_EXT,
-			hdr)) != NULL) {
-		guid_hob = (struct hob_guid *)hdr;
-		if (compare_guid(guid, &(guid_hob->name)))
-			break;
-		hdr = get_next_hob(hdr);
-	}
-
-	return hdr;
-}
-
-void *fsp_get_guid_hob_data(const void *hob_list, u32 *len,
-			    struct efi_guid *guid)
-{
-	const struct hob_header *guid_hob;
-
-	guid_hob = fsp_get_next_guid_hob(guid, hob_list);
-	if (guid_hob == NULL) {
-		return NULL;
-	} else {
-		if (len)
-			*len = get_guid_hob_data_size(guid_hob);
-
-		return get_guid_hob_data(guid_hob);
-	}
-}
-
 void *fsp_get_nvs_data(const void *hob_list, u32 *len)
 {
-	const struct efi_guid guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID;
+	const efi_guid_t guid = FSP_NON_VOLATILE_STORAGE_HOB_GUID;
 
-	return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid);
+	return hob_get_guid_hob_data(hob_list, len, &guid);
 }
 
 void *fsp_get_bootloader_tmp_mem(const void *hob_list, u32 *len)
 {
-	const struct efi_guid guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID;
+	const efi_guid_t guid = FSP_BOOTLOADER_TEMP_MEM_HOB_GUID;
 
-	return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid);
+	return hob_get_guid_hob_data(hob_list, len, &guid);
 }
 
 void *fsp_get_graphics_info(const void *hob_list, u32 *len)
 {
-	const struct efi_guid guid = FSP_GRAPHICS_INFO_HOB_GUID;
+	const efi_guid_t guid = FSP_GRAPHICS_INFO_HOB_GUID;
 
-	return fsp_get_guid_hob_data(hob_list, len, (struct efi_guid *)&guid);
+	return hob_get_guid_hob_data(hob_list, len, &guid);
 }
diff --git a/arch/x86/lib/hob.c b/arch/x86/lib/hob.c
new file mode 100644
index 0000000..dcee29b
--- /dev/null
+++ b/arch/x86/lib/hob.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: Intel
+/*
+ * Copyright (C) 2013, Intel Corporation
+ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <asm/hob.h>
+
+/**
+ * Returns the next instance of a HOB type from the starting HOB.
+ *
+ * @type:     HOB type to search
+ * @hob_list: A pointer to the HOB list
+ *
+ * @retval:   A HOB object with matching type; Otherwise NULL.
+ */
+const struct hob_header *hob_get_next_hob(uint type, const void *hob_list)
+{
+	const struct hob_header *hdr;
+
+	hdr = hob_list;
+
+	/* Parse the HOB list until end of list or matching type is found */
+	while (!end_of_hob(hdr)) {
+		if (hdr->type == type)
+			return hdr;
+
+		hdr = get_next_hob(hdr);
+	}
+
+	return NULL;
+}
+
+/**
+ * Returns the next instance of the matched GUID HOB from the starting HOB.
+ *
+ * @guid:     GUID to search
+ * @hob_list: A pointer to the HOB list
+ *
+ * @retval:   A HOB object with matching GUID; Otherwise NULL.
+ */
+const struct hob_header *hob_get_next_guid_hob(const efi_guid_t *guid,
+					       const void *hob_list)
+{
+	const struct hob_header *hdr;
+	struct hob_guid *guid_hob;
+
+	hdr = hob_list;
+	while ((hdr = hob_get_next_hob(HOB_TYPE_GUID_EXT, hdr))) {
+		guid_hob = (struct hob_guid *)hdr;
+		if (!guidcmp(guid, &guid_hob->name))
+			break;
+		hdr = get_next_hob(hdr);
+	}
+
+	return hdr;
+}
+
+/**
+ * This function retrieves a GUID HOB data buffer and size.
+ *
+ * @hob_list:      A HOB list pointer.
+ * @len:           A pointer to the GUID HOB data buffer length.
+ *                 If the GUID HOB is located, the length will be updated.
+ * @guid           A pointer to HOB GUID.
+ *
+ * @retval NULL:   Failed to find the GUID HOB.
+ * @retval others: GUID HOB data buffer pointer.
+ */
+void *hob_get_guid_hob_data(const void *hob_list, u32 *len,
+			    const efi_guid_t *guid)
+{
+	const struct hob_header *guid_hob;
+
+	guid_hob = hob_get_next_guid_hob(guid, hob_list);
+	if (!guid_hob)
+		return NULL;
+
+	if (len)
+		*len = get_guid_hob_data_size(guid_hob);
+
+	return get_guid_hob_data(guid_hob);
+}
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index 0481f45..5e19f13 100644
--- a/arch/x86/lib/init_helpers.c
+++ b/arch/x86/lib/init_helpers.c
@@ -18,7 +18,8 @@
 
 int init_cache_f_r(void)
 {
-#if CONFIG_IS_ENABLED(X86_32BIT_INIT) && !defined(CONFIG_HAVE_FSP)
+#if CONFIG_IS_ENABLED(X86_32BIT_INIT) && !defined(CONFIG_HAVE_FSP) && \
+		!defined(CONFIG_SYS_SLIMBOOTLOADER)
 	int ret;
 
 	ret = mtrr_commit(false);
diff --git a/board/intel/Kconfig b/board/intel/Kconfig
index 5131836..7b16ec4 100644
--- a/board/intel/Kconfig
+++ b/board/intel/Kconfig
@@ -73,6 +73,19 @@
 	  Note that PCIE_ECAM_BASE is set up by the FSP so the value used
 	  by U-Boot matches that value.
 
+config TARGET_SLIMBOOTLOADER
+	bool "slimbootloader"
+	help
+	  This target is used for running U-Boot on top of Slim Bootloader
+	  boot firmware as a payload. Slim Bootloader does memory initialization
+	  and silicon initialization, and it passes necessary information in
+	  HOB (Hand Off Block) to a payload. The payload consumes HOB data
+	  which is generated by Slim Bootloader for its driver initialization.
+	  Slim Bootloader consumes FSP and its HOB, but FSP HOB is cleared
+	  Before launching a payload. Instead, Slim Bootloader generates its
+	  HOB data such as memory info, serial port info and so on.
+	  Refer to doc/board/intel/slimbootloader.rst for the details.
+
 endchoice
 
 source "board/intel/bayleybay/Kconfig"
@@ -82,5 +95,6 @@
 source "board/intel/edison/Kconfig"
 source "board/intel/galileo/Kconfig"
 source "board/intel/minnowmax/Kconfig"
+source "board/intel/slimbootloader/Kconfig"
 
 endif
diff --git a/board/intel/edison/edison.c b/board/intel/edison/edison.c
index 5faf3c5..d80ee3a 100644
--- a/board/intel/edison/edison.c
+++ b/board/intel/edison/edison.c
@@ -13,9 +13,19 @@
 #include <linux/usb/gadget.h>
 
 #include <asm/cache.h>
+#include <asm/pmu.h>
 #include <asm/scu.h>
 #include <asm/u-boot-x86.h>
 
+/* List of Intel Tangier LSSs */
+#define PMU_LSS_TANGIER_SDIO0_01	1
+
+int board_early_init_r(void)
+{
+	pmu_turn_power(PMU_LSS_TANGIER_SDIO0_01, true);
+	return 0;
+}
+
 static struct dwc3_device dwc3_device_data = {
 	.maximum_speed = USB_SPEED_HIGH,
 	.base = CONFIG_SYS_USB_OTG_BASE,
diff --git a/board/intel/slimbootloader/Kconfig b/board/intel/slimbootloader/Kconfig
new file mode 100644
index 0000000..8c7e22c
--- /dev/null
+++ b/board/intel/slimbootloader/Kconfig
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2019 Intel Corporation <www.intel.com>
+
+if TARGET_SLIMBOOTLOADER
+
+config SYS_BOARD
+	default "slimbootloader"
+
+config SYS_VENDOR
+	default "intel"
+
+config SYS_SOC
+	default "slimbootloader"
+
+config SYS_CONFIG_NAME
+	default "slimbootloader"
+
+config SYS_TEXT_BASE
+	default 0x00100000
+
+config BOARD_SPECIFIC_OPTIONS
+	def_bool y
+	select SYS_SLIMBOOTLOADER
+	select USB_STORAGE
+	select USB_KEYBOARD
+
+endif
diff --git a/board/intel/slimbootloader/MAINTAINERS b/board/intel/slimbootloader/MAINTAINERS
new file mode 100644
index 0000000..e693551
--- /dev/null
+++ b/board/intel/slimbootloader/MAINTAINERS
@@ -0,0 +1,6 @@
+Intel Slim Bootloader Payload
+M:	Aiden Park <aiden.park@intel.com>
+S:	Maintained
+F:	board/intel/slimbootloader
+F:	include/configs/slimbootloader.h
+F:	configs/slimbootloader_defconfig
diff --git a/board/intel/slimbootloader/Makefile b/board/intel/slimbootloader/Makefile
new file mode 100644
index 0000000..fd8fa98
--- /dev/null
+++ b/board/intel/slimbootloader/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2019 Intel Corporation <www.intel.com>
+
+obj-y	+= start.o slimbootloader.o
diff --git a/board/intel/slimbootloader/slimbootloader.c b/board/intel/slimbootloader/slimbootloader.c
new file mode 100644
index 0000000..f50eeb8
--- /dev/null
+++ b/board/intel/slimbootloader/slimbootloader.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#include <common.h>
+
+int board_early_init_r(void)
+{
+	/*
+	 * Make sure PCI bus is enumerated so that peripherals on the PCI bus
+	 * can be discovered by their drivers.
+	 *
+	 * Slim Bootloader has already done PCI bus enumeration before loading
+	 * U-Boot, so U-Boot needs to preserve PCI configuration.
+	 * Therefore, '# CONFIG_PCI_PNP is not set' is included in defconfig.
+	 */
+	pci_init();
+
+	return 0;
+}
diff --git a/board/intel/slimbootloader/start.S b/board/intel/slimbootloader/start.S
new file mode 100644
index 0000000..5c3f3df
--- /dev/null
+++ b/board/intel/slimbootloader/start.S
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+/* board early initialization */
+.globl early_board_init
+early_board_init:
+	jmp	early_board_init_ret
diff --git a/cmd/x86/Makefile b/cmd/x86/Makefile
index 7071614..144b1cf 100644
--- a/cmd/x86/Makefile
+++ b/cmd/x86/Makefile
@@ -2,4 +2,5 @@
 
 obj-y += mtrr.o
 obj-$(CONFIG_CMD_EXCEPTION) += exception.o
+obj-$(CONFIG_USE_HOB) += hob.o
 obj-$(CONFIG_HAVE_FSP) += fsp.o
diff --git a/cmd/x86/fsp.c b/cmd/x86/fsp.c
index 9f94ca9..efa1838 100644
--- a/cmd/x86/fsp.c
+++ b/cmd/x86/fsp.c
@@ -9,21 +9,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static char *hob_type[] = {
-	"reserved",
-	"Hand-off",
-	"Mem Alloc",
-	"Res Desc",
-	"GUID Ext",
-	"FV",
-	"CPU",
-	"Mem Pool",
-	"reserved",
-	"FV2",
-	"Load PEIM",
-	"Capsule",
-};
-
 static int do_hdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	struct fsp_header *hdr = find_fsp_header();
@@ -72,57 +57,8 @@
 	return 0;
 }
 
-static int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	const struct hob_header *hdr;
-	uint type;
-	char *desc;
-	int i = 0;
-
-	hdr = gd->arch.hob_list;
-
-	printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr);
-
-	printf("#  | Address  | Type      | Len  | ");
-	printf("%42s\n", "GUID");
-	printf("---|----------|-----------|------|-");
-	printf("------------------------------------------\n");
-	while (!end_of_hob(hdr)) {
-		printf("%02x | %08x | ", i, (unsigned int)hdr);
-		type = hdr->type;
-		if (type == HOB_TYPE_UNUSED)
-			desc = "*Unused*";
-		else if (type == HOB_TYPE_EOH)
-			desc = "*EOH*";
-		else if (type >= 0 && type <= ARRAY_SIZE(hob_type))
-			desc = hob_type[type];
-		else
-			desc = "*Invalid*";
-		printf("%-9s | %04x | ", desc, hdr->len);
-
-		if (type == HOB_TYPE_MEM_ALLOC || type == HOB_TYPE_RES_DESC ||
-		    type == HOB_TYPE_GUID_EXT) {
-			struct efi_guid *guid = (struct efi_guid *)(hdr + 1);
-			int j;
-
-			printf("%08x-%04x-%04x", guid->data1,
-			       guid->data2, guid->data3);
-			for (j = 0; j < ARRAY_SIZE(guid->data4); j++)
-				printf("-%02x", guid->data4[j]);
-		} else {
-			printf("%42s", "Not Available");
-		}
-		printf("\n");
-		hdr = get_next_hob(hdr);
-		i++;
-	}
-
-	return 0;
-}
-
 static cmd_tbl_t fsp_commands[] = {
 	U_BOOT_CMD_MKENT(hdr, 0, 1, do_hdr, "", ""),
-	U_BOOT_CMD_MKENT(hob, 0, 1, do_hob, "", ""),
 };
 
 static int do_fsp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -146,6 +82,5 @@
 U_BOOT_CMD(
 	fsp,	2,	1,	do_fsp,
 	"Show Intel Firmware Support Package (FSP) related information",
-	"hdr - Print FSP header information\n"
-	"fsp hob - Print FSP Hand-Off Block (HOB) information"
+	"hdr - Print FSP header information"
 );
diff --git a/cmd/x86/hob.c b/cmd/x86/hob.c
new file mode 100644
index 0000000..3967a7c
--- /dev/null
+++ b/cmd/x86/hob.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014-2015, Bin Meng <bmeng.cn@gmail.com>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <efi.h>
+#include <asm/hob.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char *hob_type[] = {
+	"reserved",
+	"Hand-off",
+	"Mem Alloc",
+	"Res Desc",
+	"GUID Ext",
+	"FV",
+	"CPU",
+	"Mem Pool",
+	"reserved",
+	"FV2",
+	"Load PEIM",
+	"Capsule",
+};
+
+static int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	const struct hob_header *hdr;
+	uint type;
+	char *desc;
+	int i = 0;
+	efi_guid_t *guid;
+	char uuid[UUID_STR_LEN + 1];
+
+	hdr = gd->arch.hob_list;
+
+	printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr);
+
+	printf("#  | Address  | Type      | Len  | ");
+	printf("%36s\n", "GUID");
+	printf("---|----------|-----------|------|-");
+	printf("------------------------------------\n");
+	while (!end_of_hob(hdr)) {
+		printf("%02x | %08x | ", i, (unsigned int)hdr);
+		type = hdr->type;
+		if (type == HOB_TYPE_UNUSED)
+			desc = "*Unused*";
+		else if (type == HOB_TYPE_EOH)
+			desc = "*EOH*";
+		else if (type >= 0 && type <= ARRAY_SIZE(hob_type))
+			desc = hob_type[type];
+		else
+			desc = "*Invalid*";
+		printf("%-9s | %04x | ", desc, hdr->len);
+
+		if (type == HOB_TYPE_MEM_ALLOC || type == HOB_TYPE_RES_DESC ||
+		    type == HOB_TYPE_GUID_EXT) {
+			guid = (efi_guid_t *)(hdr + 1);
+			uuid_bin_to_str(guid->b, uuid, UUID_STR_FORMAT_GUID);
+			printf("%s", uuid);
+		} else {
+			printf("%36s", "Not Available");
+		}
+		printf("\n");
+		hdr = get_next_hob(hdr);
+		i++;
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(hob, 1, 1, do_hob,
+	   "Print Hand-Off Block (HOB) information",
+	   ""
+);
diff --git a/configs/edison_defconfig b/configs/edison_defconfig
index 4687544..cac6e42 100644
--- a/configs/edison_defconfig
+++ b/configs/edison_defconfig
@@ -4,6 +4,7 @@
 CONFIG_VENDOR_INTEL=y
 CONFIG_TARGET_EDISON=y
 CONFIG_SMP=y
+CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_LAST_STAGE_INIT=y
 CONFIG_HUSH_PARSER=y
 # CONFIG_CMDLINE_EDITING is not set
diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig
index 532611f..53d9c8c 100644
--- a/configs/qemu-x86_64_defconfig
+++ b/configs/qemu-x86_64_defconfig
@@ -12,6 +12,7 @@
 CONFIG_GENERATE_PIRQ_TABLE=y
 CONFIG_GENERATE_MP_TABLE=y
 CONFIG_GENERATE_ACPI_TABLE=y
+CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BUILD_ROM=y
 CONFIG_FIT=y
 CONFIG_SPL_LOAD_FIT=y
diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig
index ef85c52..ad56135 100644
--- a/configs/qemu-x86_defconfig
+++ b/configs/qemu-x86_defconfig
@@ -6,6 +6,7 @@
 CONFIG_GENERATE_PIRQ_TABLE=y
 CONFIG_GENERATE_MP_TABLE=y
 CONFIG_GENERATE_ACPI_TABLE=y
+CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BUILD_ROM=y
 CONFIG_FIT=y
 CONFIG_BOOTSTAGE=y
diff --git a/configs/slimbootloader_defconfig b/configs/slimbootloader_defconfig
new file mode 100644
index 0000000..b16ed71
--- /dev/null
+++ b/configs/slimbootloader_defconfig
@@ -0,0 +1,22 @@
+CONFIG_X86=y
+CONFIG_VENDOR_INTEL=y
+CONFIG_TARGET_SLIMBOOTLOADER=y
+CONFIG_DEFAULT_DEVICE_TREE="slimbootloader"
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_BOARD_EARLY_INIT_R=y
+CONFIG_LAST_STAGE_INIT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_USB=y
+CONFIG_DOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_OF_CONTROL=y
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_BOOTDELAY=10
+CONFIG_CONSOLE_SCROLL_LINES=5
+# CONFIG_PCI_PNP is not set
diff --git a/doc/board/emulation/qemu-x86.rst b/doc/board/emulation/qemu-x86.rst
index c2e704a..db842f2 100644
--- a/doc/board/emulation/qemu-x86.rst
+++ b/doc/board/emulation/qemu-x86.rst
@@ -54,6 +54,23 @@
 Multicore is also supported by QEMU via '-smp n' where n is the number of cores
 to instantiate. Note, the maximum supported CPU number in QEMU is 255.
 
+U-Boot uses 'distro_bootcmd' by default when booting on x86 QEMU. This tries to
+load a boot script, kernel, and ramdisk from several different interfaces. For
+the default boot order, see 'qemu-x86.h'. For more information, see
+'README.distro'. Most Linux distros can be booted by writing a uboot script.
+For example, Debian (stretch) can be booted by creating a script file named
+'boot.txt' with the contents::
+
+   setenv bootargs root=/dev/sda1 ro
+   load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} /vmlinuz
+   load ${devtype} ${devnum}:${distro_bootpart} ${ramdisk_addr_r} /initrd.img
+   zboot ${kernel_addr_r} - ${ramdisk_addr_r} ${filesize}
+
+Then compile and install it with::
+
+   $ apt install u-boot-tools && \
+     mkimage -T script -C none -n "Boot script" -d boot.txt /boot/boot.scr
+
 The fw_cfg interface in QEMU also provides information about kernel data,
 initrd, command-line arguments and more. U-Boot supports directly accessing
 these informtion from fw_cfg interface, which saves the time of loading them
diff --git a/doc/board/intel/index.rst b/doc/board/intel/index.rst
index f416801..f545dee 100644
--- a/doc/board/intel/index.rst
+++ b/doc/board/intel/index.rst
@@ -13,3 +13,4 @@
    edison
    galileo
    minnowmax
+   slimbootloader
diff --git a/doc/board/intel/slimbootloader.rst b/doc/board/intel/slimbootloader.rst
new file mode 100644
index 0000000..4a46fed
--- /dev/null
+++ b/doc/board/intel/slimbootloader.rst
@@ -0,0 +1,174 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. sectionauthor:: Aiden Park <aiden.park@intel.com>
+
+Slim Bootloader
+===============
+
+Introduction
+------------
+
+This target is to enable U-Boot_ as a payload of `Slim Bootloader`_ (a.k.a SBL)
+boot firmware which currently supports QEMU, Apollolake, Whiskeylake,
+Coffeelake-R platforms.
+
+The `Slim Bootloader`_ is designed with multi-stages (Stage1A/B, Stage2, Payload)
+architecture to cover from reset vector to OS booting and it consumes
+`Intel FSP`_ for silicon initialization.
+
+* Stage1A: Reset vector, CAR init with FSP-T
+* Stage1B: Memory init with FSP-M, CAR teardown, Continue execution in memory
+* Stage2 : Rest of Silicon init with FSP-S, Create HOB, Hand-off to Payload
+* Payload: Payload init with HOB, Load OS from media, Booting OS
+
+The Slim Bootloader stages (Stage1A/B, Stage2) focus on chipset, hardware and
+platform specific initialization, and it provides useful information to a
+payload in a HOB (Hand-Off Block) which has serial port, memory map, performance
+data info and so on. This is Slim Bootloader architectural design to make a
+payload light-weight, platform independent and more generic across different
+boot solutions or payloads, and to minimize hardware re-initialization in a
+payload.
+
+Build Instruction for U-Boot as a Slim Bootloader payload
+---------------------------------------------------------
+
+Build U-Boot and obtain u-boot-dtb.bin::
+
+   $ make distclean
+   $ make slimbootloader_defconfig
+   $ make all
+
+Prepare Slim Bootloader
+-----------------------
+
+1. Setup Build Environment for Slim Bootloader.
+
+   Refer to `Getting Started`_ page in `Slim Bootloader`_ document site.
+
+2. Get source code. Let's simply clone the repo::
+
+   $ git clone https://github.com/slimbootloader/slimbootloader.git
+
+3. Copy u-boot-dtb.bin to Slim Bootloader.
+   Slim Bootloader looks for a payload from the specific location.
+   Copy the build u-boot-dtb.bin to the expected location::
+
+   $ mkdir -p <Slim Bootloader Dir>/PayloadPkg/PayloadBins/
+   $ cp <U-Boot Dir>/u-boot-dtb.bin <Slim Bootloader Dir>/PayloadPkg/PayloadBins/u-boot-dtb.bin
+
+Build Instruction for Slim Bootloader for QEMU target
+-----------------------------------------------------
+
+Slim Bootloader supports multiple payloads, and a board of Slim Bootloader
+detects its target payload by PayloadId in board configuration.
+The PayloadId can be any 4 Bytes value.
+
+1. Update PayloadId. Let's use 'U-BT' as an example::
+
+    $ vi Platform/QemuBoardPkg/CfgData/CfgDataExt_Brd1.dlt
+    -GEN_CFG_DATA.PayloadId                     | 'AUTO'
+    +GEN_CFG_DATA.PayloadId                     | 'U-BT'
+
+2. Update payload text base. PAYLOAD_EXE_BASE must be the same as U-Boot
+   CONFIG_SYS_TEXT_BASE in board/intel/slimbootloader/Kconfig.
+   PAYLOAD_LOAD_HIGH must be 0::
+
+    $ vi Platform/QemuBoardPkg/BoardConfig.py
+    +               self.PAYLOAD_LOAD_HIGH    = 0
+    +               self.PAYLOAD_EXE_BASE     = 0x00100000
+
+3. Build QEMU target. Make sure u-boot-dtb.bin and U-BT PayloadId
+   in build command. The output is Outputs/qemu/SlimBootloader.bin::
+
+   $ python BuildLoader.py build qemu -p "OsLoader.efi:LLDR:Lz4;u-boot-dtb.bin:U-BT:Lzma"
+
+4. Launch Slim Bootloader on QEMU.
+   You should reach at U-Boot serial console::
+
+   $ qemu-system-x86_64 -machine q35 -nographic -serial mon:stdio -pflash Outputs/qemu/SlimBootloader.bin
+
+Build Instruction for Slim Bootloader for LeafHill (APL) target
+--------------------------------------------------------------
+
+LeafHill is using PCI UART2 device as a serial port.
+For MEM32 serial port, CONFIG_SYS_NS16550_MEM32 needs to be enabled in U-Boot.
+
+1. Enable CONFIG_SYS_NS16550_MEM32 in U-Boot::
+
+    $ vi include/configs/slimbootloader.h
+    +#define CONFIG_SYS_NS16550_MEM32
+     #ifdef CONFIG_SYS_NS16550_MEM3
+
+2. Build U-Boot::
+
+   $ make disclean
+   $ make slimbootloader_defconfig
+   $ make all
+
+3. Copy u-boot-dtb.bin to Slim Bootloader.
+   Slim Bootloader looks for a payload from the specific location.
+   Copy the build u-boot-dtb.bin to the expected location::
+
+   $ mkdir -p <Slim Bootloader Dir>/PayloadPkg/PayloadBins/
+   $ cp <U-Boot Dir>/u-boot-dtb.bin <Slim Bootloader Dir>/PayloadPkg/PayloadBins/u-boot-dtb.bin
+
+4. Update PayloadId. Let's use 'U-BT' as an example::
+
+    $ vi Platform/ApollolakeBoardPkg/CfgData/CfgData_Int_LeafHill.dlt
+    -GEN_CFG_DATA.PayloadId                     | 'AUTO
+    +GEN_CFG_DATA.PayloadId                     | 'U-BT'
+
+5. Update payload text base.
+
+* PAYLOAD_EXE_BASE must be the same as U-Boot CONFIG_SYS_TEXT_BASE
+  in board/intel/slimbootloader/Kconfig.
+* PAYLOAD_LOAD_HIGH must be 0::
+
+    $ vi Platform/ApollolakeBoardPkg/BoardConfig.py
+    +               self.PAYLOAD_LOAD_HIGH    = 0
+    +               self.PAYLOAD_EXE_BASE     = 0x00100000
+
+6. Build APL target. Make sure u-boot-dtb.bin and U-BT PayloadId
+   in build command. The output is Outputs/apl/Stitch_Components.zip::
+
+   $ python BuildLoader.py build apl -p "OsLoader.efi:LLDR:Lz4;u-boot-dtb.bin:U-BT:Lzma"
+
+7. Stitch IFWI.
+
+   Refer to Apollolake_ page in Slim Bootloader document site::
+
+   $ python Platform/ApollolakeBoardPkg/Script/StitchLoader.py -i <Existing IFWI> -s Outputs/apl/Stitch_Components.zip -o <Output IFWI>
+
+8. Flash IFWI.
+
+   Use DediProg to flash IFWI. You should reach at U-Boot serial console.
+
+
+Build Instruction to use ELF U-Boot
+-----------------------------------
+
+1. Enable CONFIG_OF_EMBED::
+
+    $ vi configs/slimbootloader_defconfig
+    +CONFIG_OF_EMBED=y
+
+2. Build U-Boot::
+
+   $ make disclean
+   $ make slimbootloader_defconfig
+   $ make all
+   $ strip u-boot (removing symbol for reduced size)
+
+3. Do same steps as above
+
+* Copy u-boot (ELF) to PayloadBins directory
+* Update PayloadId 'U-BT' as above.
+* No need to set PAYLOAD_LOAD_HIGH and PAYLOAD_EXE_BASE.
+* Build Slim Bootloader. Use u-boot instead of u-boot-dtb.bin::
+
+   $ python BuildLoader.py build <qemu or apl> -p "OsLoader.efi:LLDR:Lz4;u-boot:U-BT:Lzma"
+
+.. _U-Boot: https://gitlab.denx.de/
+.. _`Slim Bootloader`: https://github.com/slimbootloader/
+.. _`Intel FSP`: https://github.com/IntelFsp/
+.. _`Getting Started`: https://slimbootloader.github.io/getting-started/
+.. _Apollolake: https://slimbootloader.github.io/supported-hardware/apollo-lake-crb.html#stitching
diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c
index 4f362d1..fb806b5 100644
--- a/drivers/bios_emulator/atibios.c
+++ b/drivers/bios_emulator/atibios.c
@@ -136,7 +136,6 @@
 		bool linear_ok;
 		int attr;
 
-		break;
 		debug("Mode %x: ", mode);
 		memset(buffer, '\0', sizeof(struct vbe_mode_info));
 		regs->e.eax = VESA_GET_MODE_INFO;
diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index 03531a8..fbb58c7 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -14,6 +14,8 @@
 #include <pci_ids.h>
 #include <spi.h>
 #include <asm/io.h>
+#include <spi-mem.h>
+#include <div64.h>
 
 #include "ich.h"
 
@@ -171,18 +173,6 @@
 	return 0;
 }
 
-static inline void spi_use_out(struct spi_trans *trans, unsigned bytes)
-{
-	trans->out += bytes;
-	trans->bytesout -= bytes;
-}
-
-static inline void spi_use_in(struct spi_trans *trans, unsigned bytes)
-{
-	trans->in += bytes;
-	trans->bytesin -= bytes;
-}
-
 static void spi_lock_down(struct ich_spi_platdata *plat, void *sbase)
 {
 	if (plat->ich_version == ICHV_7) {
@@ -213,47 +203,12 @@
 	return lock != 0;
 }
 
-static void spi_setup_type(struct spi_trans *trans, int data_bytes)
-{
-	trans->type = 0xFF;
-
-	/* Try to guess spi type from read/write sizes */
-	if (trans->bytesin == 0) {
-		if (trans->bytesout + data_bytes > 4)
-			/*
-			 * If bytesin = 0 and bytesout > 4, we presume this is
-			 * a write data operation, which is accompanied by an
-			 * address.
-			 */
-			trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
-		else
-			trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
-		return;
-	}
-
-	if (trans->bytesout == 1) {	/* and bytesin is > 0 */
-		trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
-		return;
-	}
-
-	if (trans->bytesout == 4)	/* and bytesin is > 0 */
-		trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
-
-	/* Fast read command is called with 5 bytes instead of 4 */
-	if (trans->out[0] == SPI_OPCODE_FAST_READ && trans->bytesout == 5) {
-		trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
-		--trans->bytesout;
-	}
-}
-
 static int spi_setup_opcode(struct ich_spi_priv *ctlr, struct spi_trans *trans,
 			    bool lock)
 {
 	uint16_t optypes;
 	uint8_t opmenu[ctlr->menubytes];
 
-	trans->opcode = trans->out[0];
-	spi_use_out(trans, 1);
 	if (!lock) {
 		/* The lock is off, so just use index 0. */
 		ich_writeb(ctlr, trans->opcode, ctlr->opmenu);
@@ -285,12 +240,7 @@
 
 		optypes = ich_readw(ctlr, ctlr->optype);
 		optype = (optypes >> (opcode_index * 2)) & 0x3;
-		if (trans->type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS &&
-		    optype == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS &&
-		    trans->bytesout >= 3) {
-			/* We guessed wrong earlier. Fix it up. */
-			trans->type = optype;
-		}
+
 		if (optype != trans->type) {
 			printf("ICH SPI: Transaction doesn't fit type %d\n",
 			       optype);
@@ -300,26 +250,6 @@
 	}
 }
 
-static int spi_setup_offset(struct spi_trans *trans)
-{
-	/* Separate the SPI address and data */
-	switch (trans->type) {
-	case SPI_OPCODE_TYPE_READ_NO_ADDRESS:
-	case SPI_OPCODE_TYPE_WRITE_NO_ADDRESS:
-		return 0;
-	case SPI_OPCODE_TYPE_READ_WITH_ADDRESS:
-	case SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS:
-		trans->offset = ((uint32_t)trans->out[0] << 16) |
-				((uint32_t)trans->out[1] << 8) |
-				((uint32_t)trans->out[2] << 0);
-		spi_use_out(trans, 3);
-		return 1;
-	default:
-		printf("Unrecognized SPI transaction type %#x\n", trans->type);
-		return -EPROTO;
-	}
-}
-
 /*
  * Wait for up to 6s til status register bit(s) turn 1 (in case wait_til_set
  * below is true) or 0. In case the wait was for the bit(s) to set - write
@@ -350,7 +280,7 @@
 	return -ETIMEDOUT;
 }
 
-void ich_spi_config_opcode(struct udevice *dev)
+static void ich_spi_config_opcode(struct udevice *dev)
 {
 	struct ich_spi_priv *ctlr = dev_get_priv(dev);
 
@@ -365,90 +295,38 @@
 	ich_writel(ctlr, SPI_OPMENU_UPPER, ctlr->opmenu + sizeof(u32));
 }
 
-static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
-			const void *dout, void *din, unsigned long flags)
+static int ich_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
 {
-	struct udevice *bus = dev_get_parent(dev);
+	struct udevice *bus = dev_get_parent(slave->dev);
 	struct ich_spi_platdata *plat = dev_get_platdata(bus);
 	struct ich_spi_priv *ctlr = dev_get_priv(bus);
 	uint16_t control;
 	int16_t opcode_index;
 	int with_address;
 	int status;
-	int bytes = bitlen / 8;
 	struct spi_trans *trans = &ctlr->trans;
-	unsigned type = flags & (SPI_XFER_BEGIN | SPI_XFER_END);
-	int using_cmd = 0;
 	bool lock = spi_lock_status(plat, ctlr->base);
-	int ret;
+	int ret = 0;
 
-	/* We don't support writing partial bytes */
-	if (bitlen % 8) {
-		debug("ICH SPI: Accessing partial bytes not supported\n");
-		return -EPROTONOSUPPORT;
-	}
+	trans->in = NULL;
+	trans->out = NULL;
+	trans->type = 0xFF;
 
-	/* An empty end transaction can be ignored */
-	if (type == SPI_XFER_END && !dout && !din)
-		return 0;
-
-	if (type & SPI_XFER_BEGIN)
-		memset(trans, '\0', sizeof(*trans));
-
-	/* Dp we need to come back later to finish it? */
-	if (dout && type == SPI_XFER_BEGIN) {
-		if (bytes > ICH_MAX_CMD_LEN) {
-			debug("ICH SPI: Command length limit exceeded\n");
-			return -ENOSPC;
+	if (op->data.nbytes) {
+		if (op->data.dir == SPI_MEM_DATA_IN) {
+			trans->in = op->data.buf.in;
+			trans->bytesin = op->data.nbytes;
+		} else {
+			trans->out = op->data.buf.out;
+			trans->bytesout = op->data.nbytes;
 		}
-		memcpy(trans->cmd, dout, bytes);
-		trans->cmd_len = bytes;
-		debug_trace("ICH SPI: Saved %d bytes\n", bytes);
+	}
+
+	if (trans->opcode != op->cmd.opcode)
+		trans->opcode = op->cmd.opcode;
+
+	if (lock && trans->opcode == SPI_OPCODE_WRDIS)
 		return 0;
-	}
-
-	/*
-	 * We process a 'middle' spi_xfer() call, which has no
-	 * SPI_XFER_BEGIN/END, as an independent transaction as if it had
-	 * an end. We therefore repeat the command. This is because ICH
-	 * seems to have no support for this, or because interest (in digging
-	 * out the details and creating a special case in the code) is low.
-	 */
-	if (trans->cmd_len) {
-		trans->out = trans->cmd;
-		trans->bytesout = trans->cmd_len;
-		using_cmd = 1;
-		debug_trace("ICH SPI: Using %d bytes\n", trans->cmd_len);
-	} else {
-		trans->out = dout;
-		trans->bytesout = dout ? bytes : 0;
-	}
-
-	trans->in = din;
-	trans->bytesin = din ? bytes : 0;
-
-	/* There has to always at least be an opcode */
-	if (!trans->bytesout) {
-		debug("ICH SPI: No opcode for transfer\n");
-		return -EPROTO;
-	}
-
-	ret = ich_status_poll(ctlr, SPIS_SCIP, 0);
-	if (ret < 0)
-		return ret;
-
-	if (plat->ich_version == ICHV_7)
-		ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
-	else
-		ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
-
-	spi_setup_type(trans, using_cmd ? bytes : 0);
-	opcode_index = spi_setup_opcode(ctlr, trans, lock);
-	if (opcode_index < 0)
-		return -EINVAL;
-	with_address = spi_setup_offset(trans);
-	if (with_address < 0)
-		return -EINVAL;
 
 	if (trans->opcode == SPI_OPCODE_WREN) {
 		/*
@@ -461,6 +339,40 @@
 		return 0;
 	}
 
+	ret = ich_status_poll(ctlr, SPIS_SCIP, 0);
+	if (ret < 0)
+		return ret;
+
+	if (plat->ich_version == ICHV_7)
+		ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
+	else
+		ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status);
+
+	/* Try to guess spi transaction type */
+	if (op->data.dir == SPI_MEM_DATA_OUT) {
+		if (op->addr.nbytes)
+			trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
+		else
+			trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
+	} else {
+		if (op->addr.nbytes)
+			trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
+		else
+			trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
+	}
+	/* Special erase case handling */
+	if (op->addr.nbytes && !op->data.buswidth)
+		trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
+
+	opcode_index = spi_setup_opcode(ctlr, trans, lock);
+	if (opcode_index < 0)
+		return -EINVAL;
+
+	if (op->addr.nbytes) {
+		trans->offset = op->addr.val;
+		with_address = 1;
+	}
+
 	if (ctlr->speed && ctlr->max_speed >= 33000000) {
 		int byte;
 
@@ -472,13 +384,6 @@
 		ich_writeb(ctlr, byte, ctlr->speed);
 	}
 
-	/* See if we have used up the command data */
-	if (using_cmd && dout && bytes) {
-		trans->out = dout;
-		trans->bytesout = bytes;
-		debug_trace("ICH SPI: Moving to data, %d bytes\n", bytes);
-	}
-
 	/* Preset control fields */
 	control = SPIC_SCGO | ((opcode_index & 0x07) << 4);
 
@@ -513,22 +418,6 @@
 		return 0;
 	}
 
-	/*
-	 * Check if this is a write command atempting to transfer more bytes
-	 * than the controller can handle. Iterations for writes are not
-	 * supported here because each SPI write command needs to be preceded
-	 * and followed by other SPI commands, and this sequence is controlled
-	 * by the SPI chip driver.
-	 */
-	if (trans->bytesout > ctlr->databytes) {
-		debug("ICH SPI: Too much to write. This should be prevented by the driver's max_write_size?\n");
-		return -EPROTO;
-	}
-
-	/*
-	 * Read or write up to databytes bytes at a time until everything has
-	 * been sent.
-	 */
 	while (trans->bytesout || trans->bytesin) {
 		uint32_t data_length;
 
@@ -543,9 +432,7 @@
 		/* Program data into FDATA0 to N */
 		if (trans->bytesout) {
 			write_reg(ctlr, trans->out, ctlr->data, data_length);
-			spi_use_out(trans, data_length);
-			if (with_address)
-				trans->offset += data_length;
+			trans->bytesout -= data_length;
 		}
 
 		/* Add proper control fields' values */
@@ -568,9 +455,7 @@
 
 		if (trans->bytesin) {
 			read_reg(ctlr, ctlr->data, trans->in, data_length);
-			spi_use_in(trans, data_length);
-			if (with_address)
-				trans->offset += data_length;
+			trans->bytesin -= data_length;
 		}
 	}
 
@@ -581,6 +466,40 @@
 	return 0;
 }
 
+static int ich_spi_adjust_size(struct spi_slave *slave, struct spi_mem_op *op)
+{
+	unsigned int page_offset;
+	int addr = op->addr.val;
+	unsigned int byte_count = op->data.nbytes;
+
+	if (hweight32(ICH_BOUNDARY) == 1) {
+		page_offset = addr & (ICH_BOUNDARY - 1);
+	} else {
+		u64 aux = addr;
+
+		page_offset = do_div(aux, ICH_BOUNDARY);
+	}
+
+	if (op->data.dir == SPI_MEM_DATA_IN && slave->max_read_size) {
+		op->data.nbytes = min(ICH_BOUNDARY - page_offset,
+				      slave->max_read_size);
+	} else if (slave->max_write_size) {
+		op->data.nbytes = min(ICH_BOUNDARY - page_offset,
+				      slave->max_write_size);
+	}
+
+	op->data.nbytes = min(op->data.nbytes, byte_count);
+
+	return 0;
+}
+
+static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			const void *dout, void *din, unsigned long flags)
+{
+	printf("ICH SPI: Only supports memory operations\n");
+	return -1;
+}
+
 static int ich_spi_probe(struct udevice *dev)
 {
 	struct ich_spi_platdata *plat = dev_get_platdata(dev);
@@ -686,10 +605,17 @@
 	return ret;
 }
 
+static const struct spi_controller_mem_ops ich_controller_mem_ops = {
+	.adjust_op_size	= ich_spi_adjust_size,
+	.supports_op	= NULL,
+	.exec_op	= ich_spi_exec_op,
+};
+
 static const struct dm_spi_ops ich_spi_ops = {
 	.xfer		= ich_spi_xfer,
 	.set_speed	= ich_spi_set_speed,
 	.set_mode	= ich_spi_set_mode,
+	.mem_ops	= &ich_controller_mem_ops,
 	/*
 	 * cs_info is not needed, since we require all chip selects to be
 	 * in the device tree explicitly
diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h
index a974241..3dfb2aa 100644
--- a/drivers/spi/ich.h
+++ b/drivers/spi/ich.h
@@ -100,13 +100,8 @@
 	HSFC_FSMIE =		0x8000
 };
 
-enum {
-	ICH_MAX_CMD_LEN		= 5,
-};
-
 struct spi_trans {
-	uint8_t cmd[ICH_MAX_CMD_LEN];
-	int cmd_len;
+	uint8_t cmd;
 	const uint8_t *out;
 	uint32_t bytesout;
 	uint8_t *in;
@@ -166,6 +161,8 @@
 #define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \
 			  (SPI_OPMENU_1 <<  8) | (SPI_OPMENU_0 <<  0))
 
+#define ICH_BOUNDARY	0x1000
+
 enum ich_version {
 	ICHV_7,
 	ICHV_9,
diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h
index 64e7a60..c557420 100644
--- a/include/configs/qemu-x86.h
+++ b/include/configs/qemu-x86.h
@@ -10,8 +10,23 @@
 #ifndef __CONFIG_H
 #define __CONFIG_H
 
+#include <linux/sizes.h>
+
+#define BOOT_TARGET_DEVICES(func) \
+	func(USB, usb, 0) \
+	func(SCSI, scsi, 0) \
+	func(VIRTIO, virtio, 0) \
+	func(IDE, ide, 0) \
+	func(DHCP, dhcp, na)
+
+#include <config_distro_bootcmd.h>
 #include <configs/x86-common.h>
 
+#undef CONFIG_ENV_SIZE
+#define CONFIG_ENV_SIZE			SZ_256K
+
+#define CONFIG_PREBOOT "pci enum"
+
 #define CONFIG_SYS_MONITOR_LEN		(1 << 20)
 
 #define CONFIG_STD_DEVICES_SETTINGS	"stdin=serial,i8042-kbd\0" \
diff --git a/include/configs/slimbootloader.h b/include/configs/slimbootloader.h
new file mode 100644
index 0000000..e0011ed
--- /dev/null
+++ b/include/configs/slimbootloader.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Intel Corporation <www.intel.com>
+ */
+
+#ifndef __SLIMBOOTLOADER_CONFIG_H__
+#define __SLIMBOOTLOADER_CONFIG_H__
+
+#include <configs/x86-common.h>
+
+/*
+ * By default, CONFIG_SYS_NS16550_PORT_MAPPED is enabled for port io serial.
+ * To use mmio base serial, enable CONFIG_SYS_NS16550_MEM32 and disable
+ * CONFIG_SYS_NS16550_PORT_MAPPED until ns16550 driver supports serial port
+ * configuration in run-time.
+ *
+ * #define CONFIG_SYS_NS16550_MEM32
+ * #undef CONFIG_SYS_NS16550_PORT_MAPPED
+ */
+#ifdef CONFIG_SYS_NS16550_MEM32
+#undef CONFIG_SYS_NS16550_PORT_MAPPED
+#endif
+
+#define CONFIG_STD_DEVICES_SETTINGS		\
+	"stdin=serial,i8042-kbd,usbkbd\0"	\
+	"stdout=serial\0"			\
+	"stderr=serial\0"
+
+/*
+ * Override CONFIG_EXTRA_ENV_SETTINGS in x86-common.h
+ */
+#undef CONFIG_EXTRA_ENV_SETTINGS
+#define CONFIG_EXTRA_ENV_SETTINGS		\
+	CONFIG_STD_DEVICES_SETTINGS		\
+	"netdev=eth0\0"				\
+	"consoledev=ttyS0\0"			\
+	"ramdiskaddr=0x4000000\0"		\
+	"ramdiskfile=initrd\0"			\
+	"bootdev=usb\0"				\
+	"bootdevnum=0\0"			\
+	"bootdevpart=0\0"			\
+	"bootfsload=fatload\0"			\
+	"bootusb=setenv bootdev usb; boot\0"	\
+	"bootscsi=setenv bootdev scsi; boot\0"	\
+	"bootmmc=setenv bootdev mmc; boot\0"	\
+	"bootargs=console=ttyS0,115200 console=tty0\0"
+
+/*
+ * Override CONFIG_BOOTCOMMAND in x86-common.h
+ */
+#undef CONFIG_BOOTCOMMAND
+#define CONFIG_BOOTCOMMAND						\
+	"if test ${bootdev} = \"usb\"; then ${bootdev} start; fi; "	\
+	"if test ${bootdev} = \"scsi\"; then ${bootdev} scan; fi; "	\
+	"${bootdev} info; "						\
+	"${bootfsload} ${bootdev} ${bootdevnum}:${bootdevpart} "	\
+	"${loadaddr} ${bootfile}; "					\
+	"${bootfsload} ${bootdev} ${bootdevnum}:${bootdevpart} "	\
+	"${ramdiskaddr} ${ramdiskfile}; "				\
+	"zboot ${loadaddr} 0 ${ramdiskaddr} ${filesize}"
+
+#endif /* __SLIMBOOTLOADER_CONFIG_H__ */
diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h
index c4deef8..ca27a4f 100644
--- a/include/configs/x86-common.h
+++ b/include/configs/x86-common.h
@@ -105,30 +105,37 @@
 #define CONFIG_OTHBOOTARGS	"othbootargs=acpi=off\0"
 #endif
 
+#ifndef CONFIG_DISTRO_DEFAULTS
+#define BOOTENV
+#endif
+
 #define CONFIG_EXTRA_ENV_SETTINGS			\
 	CONFIG_STD_DEVICES_SETTINGS			\
 	"pciconfighost=1\0"				\
 	"netdev=eth0\0"					\
 	"consoledev=ttyS0\0"				\
 	CONFIG_OTHBOOTARGS				\
-	"ramdiskaddr=0x4000000\0"			\
-	"ramdiskfile=initramfs.gz\0"
+	"scriptaddr=0x7000000\0"			\
+	"kernel_addr_r=0x1000000\0"			\
+	"ramdisk_addr_r=0x4000000\0"			\
+	"ramdiskfile=initramfs.gz\0"			\
+	BOOTENV
 
 #define CONFIG_RAMBOOTCOMMAND				\
 	"setenv bootargs root=/dev/ram rw "		\
 	"ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname:$netdev:off " \
 	"console=$consoledev,$baudrate $othbootargs;"	\
-	"tftpboot $loadaddr $bootfile;"			\
-	"tftpboot $ramdiskaddr $ramdiskfile;"		\
-	"zboot $loadaddr 0 $ramdiskaddr $filesize"
+	"tftpboot $kernel_addr_r $bootfile;"		\
+	"tftpboot $ramdisk_addr_r $ramdiskfile;"	\
+	"zboot $kernel_addr_r 0 $ramdisk_addr_r $filesize"
 
 #define CONFIG_NFSBOOTCOMMAND				\
 	"setenv bootargs root=/dev/nfs rw "		\
 	"nfsroot=$serverip:$rootpath "			\
 	"ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname:$netdev:off " \
 	"console=$consoledev,$baudrate $othbootargs;"	\
-	"tftpboot $loadaddr $bootfile;"			\
-	"zboot $loadaddr"
+	"tftpboot $kernel_addr_r $bootfile;"		\
+	"zboot $kernel_addr_r"
 
 
 #endif	/* __CONFIG_H */
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 2f5e28c..ef116e0 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -395,11 +395,22 @@
 
 # ACPI
 # ---------------------------------------------------------------------------
+#
+# This first sends the file (typically dsdt.asl) through the preprocessor
+# resolve includes and any CONFIG options used. This produces dsdt.asl.tmp
+# which is pure ASL code. The Intel ASL (ACPI (Advanced Configuration and Power
+# Interface) Source Language compiler (iasl) then converts this ASL code into a
+# C file containing the hex data to build into U-Boot. This file is called
+# dsdt.hex (despite us setting the prefix to .../dsdt.asl.tmp) so must be
+# renamed to dsdt.c for consumption by the build system.
+ASL_TMP = $(patsubst %.c,%.asl.tmp,$@)
+
 quiet_cmd_acpi_c_asl= ASL     $<
 cmd_acpi_c_asl=         \
-	$(CPP) -x assembler-with-cpp -D__ASSEMBLY__ -P $(UBOOTINCLUDE) -o $<.tmp $<; \
-	iasl -p $< -tc $<.tmp $(if $(KBUILD_VERBOSE:1=), >/dev/null) && \
-	mv $(patsubst %.asl,%.hex,$<) $@
+	$(CPP) -x assembler-with-cpp -D__ASSEMBLY__ -P $(UBOOTINCLUDE) \
+		-o $(ASL_TMP) $< && \
+	iasl -p $@ -tc $(ASL_TMP) $(if $(KBUILD_VERBOSE:1=), >/dev/null) && \
+	mv $(patsubst %.c,%.hex,$@) $@
 
 $(obj)/dsdt.c:    $(src)/dsdt.asl
 	$(call cmd,acpi_c_asl)