Merge git://git.denx.de/u-boot-mmc
diff --git a/MAINTAINERS b/MAINTAINERS
index 754db55..d459153 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -287,9 +287,10 @@
 S:	Maintained
 T:	git git://github.com/agraf/u-boot.git
 F:	include/efi*
-F:	lib/efi*
+F:	lib/efi*/
 F:	test/py/tests/test_efi*
 F:	cmd/bootefi.c
+F:	tools/file2include.c
 
 FLATTENED DEVICE TREE
 M:	Simon Glass <sjg@chromium.org>
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
index 179cac6..9ee0dd2 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
@@ -158,6 +158,293 @@
 	serdes_prtcl_map[NONE] = 1;
 }
 
+__weak int get_serdes_volt(void)
+{
+	return -1;
+}
+
+__weak int set_serdes_volt(int svdd)
+{
+	return -1;
+}
+
+#define LNAGCR0_RT_RSTB		0x00600000
+
+#define RSTCTL_RESET_MASK	0x000000E0
+
+#define RSTCTL_RSTREQ		0x80000000
+#define RSTCTL_RST_DONE		0x40000000
+#define RSTCTL_RSTERR		0x20000000
+
+#define RSTCTL_SDEN		0x00000020
+#define RSTCTL_SDRST_B		0x00000040
+#define RSTCTL_PLLRST_B		0x00000080
+
+#define TCALCR_CALRST_B		0x08000000
+
+struct serdes_prctl_info {
+	u32 id;
+	u32 mask;
+	u32 shift;
+};
+
+struct serdes_prctl_info srds_prctl_info[] = {
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	{.id = 1,
+	 .mask = FSL_CHASSIS3_SRDS1_PRTCL_MASK,
+	 .shift = FSL_CHASSIS3_SRDS1_PRTCL_SHIFT
+	},
+
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	{.id = 2,
+	 .mask = FSL_CHASSIS3_SRDS2_PRTCL_MASK,
+	 .shift = FSL_CHASSIS3_SRDS2_PRTCL_SHIFT
+	},
+#endif
+	{} /* NULL ENTRY */
+};
+
+static int get_serdes_prctl_info_idx(u32 serdes_id)
+{
+	int pos = 0;
+	struct serdes_prctl_info *srds_info;
+
+	/* loop until NULL ENTRY defined by .id=0 */
+	for (srds_info = srds_prctl_info; srds_info->id != 0;
+	     srds_info++, pos++) {
+		if (srds_info->id == serdes_id)
+			return pos;
+	}
+
+	return -1;
+}
+
+static void do_enabled_lanes_reset(u32 serdes_id, u32 cfg,
+				   struct ccsr_serdes __iomem *serdes_base,
+				   bool cmplt)
+{
+	int i, pos;
+	u32 cfg_tmp;
+
+	pos = get_serdes_prctl_info_idx(serdes_id);
+	if (pos == -1) {
+		printf("invalid serdes_id %d\n", serdes_id);
+		return;
+	}
+
+	cfg_tmp = cfg & srds_prctl_info[pos].mask;
+	cfg_tmp >>= srds_prctl_info[pos].shift;
+
+	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
+		if (cmplt)
+			setbits_le32(&serdes_base->lane[i].gcr0,
+				     LNAGCR0_RT_RSTB);
+		else
+			clrbits_le32(&serdes_base->lane[i].gcr0,
+				     LNAGCR0_RT_RSTB);
+	}
+}
+
+static void do_pll_reset(u32 cfg,
+			 struct ccsr_serdes __iomem *serdes_base)
+{
+	int i;
+
+	for (i = 0; i < 2 && !(cfg & (0x1 << (1 - i))); i++) {
+		clrbits_le32(&serdes_base->bank[i].rstctl,
+			     RSTCTL_RESET_MASK);
+		udelay(1);
+
+		setbits_le32(&serdes_base->bank[i].rstctl,
+			     RSTCTL_RSTREQ);
+	}
+	udelay(1);
+}
+
+static void do_rx_tx_cal_reset(struct ccsr_serdes __iomem *serdes_base)
+{
+	clrbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B);
+	clrbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B);
+}
+
+static void do_rx_tx_cal_reset_comp(u32 cfg, int i,
+				    struct ccsr_serdes __iomem *serdes_base)
+{
+	if (!(cfg == 0x3 && i == 1)) {
+		udelay(1);
+		setbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B);
+		setbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B);
+	}
+	udelay(1);
+}
+
+static void do_pll_reset_done(u32 cfg,
+			      struct ccsr_serdes __iomem *serdes_base)
+{
+	int i;
+	u32 reg = 0;
+
+	for (i = 0; i < 2; i++) {
+		reg = in_le32(&serdes_base->bank[i].pllcr0);
+		if (!(cfg & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
+			setbits_le32(&serdes_base->bank[i].rstctl,
+				     RSTCTL_RST_DONE);
+		}
+	}
+}
+
+static void do_serdes_enable(u32 cfg,
+			     struct ccsr_serdes __iomem *serdes_base)
+{
+	int i;
+
+	for (i = 0; i < 2 && !(cfg & (0x1 << (1 - i))); i++) {
+		setbits_le32(&serdes_base->bank[i].rstctl, RSTCTL_SDEN);
+		udelay(1);
+
+		setbits_le32(&serdes_base->bank[i].rstctl, RSTCTL_PLLRST_B);
+		udelay(1);
+		/* Take the Rx/Tx calibration out of reset */
+		do_rx_tx_cal_reset_comp(cfg, i, serdes_base);
+	}
+}
+
+static void do_pll_lock(u32 cfg,
+			struct ccsr_serdes __iomem *serdes_base)
+{
+	int i;
+	u32 reg = 0;
+
+	for (i = 0; i < 2 && !(cfg & (0x1 << (1 - i))); i++) {
+		/* if the PLL is not locked, set RST_ERR */
+		reg = in_le32(&serdes_base->bank[i].pllcr0);
+		if (!((reg >> 23) & 0x1)) {
+			setbits_le32(&serdes_base->bank[i].rstctl,
+				     RSTCTL_RSTERR);
+		} else {
+			udelay(1);
+			setbits_le32(&serdes_base->bank[i].rstctl,
+				     RSTCTL_SDRST_B);
+			udelay(1);
+		}
+	}
+}
+
+int setup_serdes_volt(u32 svdd)
+{
+	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	struct ccsr_serdes __iomem *serdes1_base =
+			(void *)CONFIG_SYS_FSL_LSCH3_SERDES_ADDR;
+	u32 cfg_rcwsrds1 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]);
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	struct ccsr_serdes __iomem *serdes2_base =
+			(void *)(CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + 0x10000);
+	u32 cfg_rcwsrds2 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS2_REGSR - 1]);
+#endif
+	u32 cfg_tmp;
+	int svdd_cur, svdd_tar;
+	int ret = 1;
+
+	/* Only support switch SVDD to 900mV */
+	if (svdd != 900)
+		return -EINVAL;
+
+	/* Scale up to the LTC resolution is 1/4096V */
+	svdd = (svdd * 4096) / 1000;
+
+	svdd_tar = svdd;
+	svdd_cur = get_serdes_volt();
+	if (svdd_cur < 0)
+		return -EINVAL;
+
+	debug("%s: current SVDD: %x; target SVDD: %x\n",
+	      __func__, svdd_cur, svdd_tar);
+	if (svdd_cur == svdd_tar)
+		return 0;
+
+	/* Put the all enabled lanes in reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	do_enabled_lanes_reset(1, cfg_rcwsrds1, serdes1_base, false);
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	do_enabled_lanes_reset(2, cfg_rcwsrds2, serdes2_base, false);
+#endif
+
+	/* Put the all enabled PLL in reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = cfg_rcwsrds1 & 0x3;
+	do_pll_reset(cfg_tmp, serdes1_base);
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = cfg_rcwsrds1 & 0xC;
+	cfg_tmp >>= 2;
+	do_pll_reset(cfg_tmp, serdes2_base);
+#endif
+
+	/* Put the Rx/Tx calibration into reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	do_rx_tx_cal_reset(serdes1_base);
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	do_rx_tx_cal_reset(serdes2_base);
+#endif
+
+	ret = set_serdes_volt(svdd);
+	if (ret < 0) {
+		printf("could not change SVDD\n");
+		ret = -1;
+	}
+
+	/* For each PLL that’s not disabled via RCW enable the SERDES */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = cfg_rcwsrds1 & 0x3;
+	do_serdes_enable(cfg_tmp, serdes1_base);
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = cfg_rcwsrds1 & 0xC;
+	cfg_tmp >>= 2;
+	do_serdes_enable(cfg_tmp, serdes2_base);
+#endif
+
+	/* Wait for at at least 625us, ensure the PLLs being reset are locked */
+	udelay(800);
+
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = cfg_rcwsrds1 & 0x3;
+	do_pll_lock(cfg_tmp, serdes1_base);
+#endif
+
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = cfg_rcwsrds1 & 0xC;
+	cfg_tmp >>= 2;
+	do_pll_lock(cfg_tmp, serdes2_base);
+#endif
+	/* Take the all enabled lanes out of reset */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	do_enabled_lanes_reset(1, cfg_rcwsrds1, serdes1_base, true);
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	do_enabled_lanes_reset(2, cfg_rcwsrds2, serdes2_base, true);
+#endif
+
+	/* For each PLL being reset, and achieved PLL lock set RST_DONE */
+#ifdef CONFIG_SYS_FSL_SRDS_1
+	cfg_tmp = cfg_rcwsrds1 & 0x3;
+	do_pll_reset_done(cfg_tmp, serdes1_base);
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_2
+	cfg_tmp = cfg_rcwsrds1 & 0xC;
+	cfg_tmp >>= 2;
+	do_pll_reset_done(cfg_tmp, serdes2_base);
+#endif
+
+	return ret;
+}
+
 void fsl_serdes_init(void)
 {
 #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
index dc4a437..b9f837d 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
@@ -363,6 +363,45 @@
 }
 #endif
 
+/* Get VDD in the unit mV from voltage ID */
+int get_core_volt_from_fuse(void)
+{
+	struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+	int vdd;
+	u32 fusesr;
+	u8 vid;
+
+	/* get the voltage ID from fuse status register */
+	fusesr = in_le32(&gur->dcfg_fusesr);
+	debug("%s: fusesr = 0x%x\n", __func__, fusesr);
+	vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT) &
+		FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK;
+	if ((vid == 0) || (vid == FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK)) {
+		vid = (fusesr >> FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT) &
+			FSL_CHASSIS3_DCFG_FUSESR_VID_MASK;
+	}
+	debug("%s: VID = 0x%x\n", __func__, vid);
+	switch (vid) {
+	case 0x00: /* VID isn't supported */
+		vdd = -EINVAL;
+		debug("%s: The VID feature is not supported\n", __func__);
+		break;
+	case 0x08: /* 0.9V silicon */
+		vdd = 900;
+		break;
+	case 0x10: /* 1.0V silicon */
+		vdd = 1000;
+		break;
+	default:  /* Other core voltage */
+		vdd = -EINVAL;
+		debug("%s: The VID(%x) isn't supported\n", __func__, vid);
+		break;
+	}
+	debug("%s: The required minimum volt of CORE is %dmV\n", __func__, vdd);
+
+	return vdd;
+}
+
 #elif defined(CONFIG_FSL_LSCH2)
 #ifdef CONFIG_SCSI_AHCI_PLAT
 int sata_init(void)
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/spl.c b/arch/arm/cpu/armv8/fsl-layerscape/spl.c
index 1c694e7..4093d15 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/spl.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/spl.c
@@ -85,6 +85,9 @@
 #ifdef CONFIG_SPL_I2C_SUPPORT
 	i2c_init_all();
 #endif
+#ifdef CONFIG_VID
+	init_func_vid();
+#endif
 	dram_init();
 #ifdef CONFIG_SPL_FSL_LS_PPA
 #ifndef CONFIG_SYS_MEM_RESERVE_SECURE
diff --git a/arch/arm/dts/fsl-ls1012a-frdm.dts b/arch/arm/dts/fsl-ls1012a-frdm.dts
index 983e599..6ea5f82 100644
--- a/arch/arm/dts/fsl-ls1012a-frdm.dts
+++ b/arch/arm/dts/fsl-ls1012a-frdm.dts
@@ -3,7 +3,7 @@
  *
  * Copyright 2016, Freescale Semiconductor
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls1012a-frdm.dtsi b/arch/arm/dts/fsl-ls1012a-frdm.dtsi
index 25dcdd2..d453f5d 100644
--- a/arch/arm/dts/fsl-ls1012a-frdm.dtsi
+++ b/arch/arm/dts/fsl-ls1012a-frdm.dtsi
@@ -3,7 +3,7 @@
  *
  * Copyright 2016, Freescale Semiconductor
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /include/ "fsl-ls1012a.dtsi"
diff --git a/arch/arm/dts/fsl-ls1012a-qds.dts b/arch/arm/dts/fsl-ls1012a-qds.dts
index 76db36c..ccc9023 100644
--- a/arch/arm/dts/fsl-ls1012a-qds.dts
+++ b/arch/arm/dts/fsl-ls1012a-qds.dts
@@ -1,7 +1,7 @@
 /*
  * Copyright 2016 Freescale Semiconductor
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls1012a-qds.dtsi b/arch/arm/dts/fsl-ls1012a-qds.dtsi
index d17cd99..908fbed 100644
--- a/arch/arm/dts/fsl-ls1012a-qds.dtsi
+++ b/arch/arm/dts/fsl-ls1012a-qds.dtsi
@@ -1,7 +1,7 @@
 /*
  * Copyright 2016 Freescale Semiconductor
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /include/ "fsl-ls1012a.dtsi"
diff --git a/arch/arm/dts/fsl-ls1012a-rdb.dts b/arch/arm/dts/fsl-ls1012a-rdb.dts
index f683812..400cd9e 100644
--- a/arch/arm/dts/fsl-ls1012a-rdb.dts
+++ b/arch/arm/dts/fsl-ls1012a-rdb.dts
@@ -3,7 +3,7 @@
  *
  * Copyright 2016, Freescale Semiconductor
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls1012a-rdb.dtsi b/arch/arm/dts/fsl-ls1012a-rdb.dtsi
index bf407ae..c4b6adf 100644
--- a/arch/arm/dts/fsl-ls1012a-rdb.dtsi
+++ b/arch/arm/dts/fsl-ls1012a-rdb.dtsi
@@ -3,9 +3,7 @@
  *
  * Copyright 2016, Freescale Semiconductor
  *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
+ * SPDX-License-Identifier:    GPL-2.0+	X11
  */
 
 /include/ "fsl-ls1012a.dtsi"
diff --git a/arch/arm/dts/fsl-ls1012a.dtsi b/arch/arm/dts/fsl-ls1012a.dtsi
index 23b3cec..215e095 100644
--- a/arch/arm/dts/fsl-ls1012a.dtsi
+++ b/arch/arm/dts/fsl-ls1012a.dtsi
@@ -1,7 +1,7 @@
 /*
  * Copyright 2016 Freescale Semiconductor
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /include/ "skeleton64.dtsi"
diff --git a/arch/arm/dts/fsl-ls1043a-qds-duart.dts b/arch/arm/dts/fsl-ls1043a-qds-duart.dts
index 2124e38..cf53ab00 100644
--- a/arch/arm/dts/fsl-ls1043a-qds-duart.dts
+++ b/arch/arm/dts/fsl-ls1043a-qds-duart.dts
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2015, Freescale Semiconductor
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls1043a-qds-lpuart.dts b/arch/arm/dts/fsl-ls1043a-qds-lpuart.dts
index 18adb97..118c45d 100644
--- a/arch/arm/dts/fsl-ls1043a-qds-lpuart.dts
+++ b/arch/arm/dts/fsl-ls1043a-qds-lpuart.dts
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2015, Freescale Semiconductor
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls1043a-qds.dtsi b/arch/arm/dts/fsl-ls1043a-qds.dtsi
index 2101172..9611619 100644
--- a/arch/arm/dts/fsl-ls1043a-qds.dtsi
+++ b/arch/arm/dts/fsl-ls1043a-qds.dtsi
@@ -5,9 +5,7 @@
  *
  * Mingkai Hu <Mingkai.hu@freescale.com>
  *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
+ * SPDX-License-Identifier:    GPL-2.0+	X11
  */
 
 /include/ "fsl-ls1043a.dtsi"
diff --git a/arch/arm/dts/fsl-ls1043a-rdb.dts b/arch/arm/dts/fsl-ls1043a-rdb.dts
index f271e71..27670a8 100644
--- a/arch/arm/dts/fsl-ls1043a-rdb.dts
+++ b/arch/arm/dts/fsl-ls1043a-rdb.dts
@@ -5,9 +5,7 @@
  *
  * Mingkai Hu <Mingkai.hu@freescale.com>
  *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
+ * SPDX-License-Identifier:    GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls1043a.dtsi b/arch/arm/dts/fsl-ls1043a.dtsi
index fe6698f..3cc2077 100644
--- a/arch/arm/dts/fsl-ls1043a.dtsi
+++ b/arch/arm/dts/fsl-ls1043a.dtsi
@@ -5,9 +5,7 @@
  *
  * Mingkai Hu <Mingkai.hu@freescale.com>
  *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
+ * SPDX-License-Identifier:    GPL-2.0+	X11
  */
 
 /include/ "skeleton64.dtsi"
diff --git a/arch/arm/dts/fsl-ls1046a-qds-duart.dts b/arch/arm/dts/fsl-ls1046a-qds-duart.dts
index 10a95ea..9a4b84f 100644
--- a/arch/arm/dts/fsl-ls1046a-qds-duart.dts
+++ b/arch/arm/dts/fsl-ls1046a-qds-duart.dts
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2016, Freescale Semiconductor
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls1046a-qds-lpuart.dts b/arch/arm/dts/fsl-ls1046a-qds-lpuart.dts
index 21243d0..1c4d362 100644
--- a/arch/arm/dts/fsl-ls1046a-qds-lpuart.dts
+++ b/arch/arm/dts/fsl-ls1046a-qds-lpuart.dts
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2016, Freescale Semiconductor
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls1046a-qds.dtsi b/arch/arm/dts/fsl-ls1046a-qds.dtsi
index a49ca08..4e1920b 100644
--- a/arch/arm/dts/fsl-ls1046a-qds.dtsi
+++ b/arch/arm/dts/fsl-ls1046a-qds.dtsi
@@ -5,9 +5,7 @@
  *
  * Mingkai Hu <Mingkai.hu@nxp.com>
  *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
+ * SPDX-License-Identifier:    GPL-2.0+	X11
  */
 
 /include/ "fsl-ls1046a.dtsi"
diff --git a/arch/arm/dts/fsl-ls1046a-rdb.dts b/arch/arm/dts/fsl-ls1046a-rdb.dts
index 4902454..646e477 100644
--- a/arch/arm/dts/fsl-ls1046a-rdb.dts
+++ b/arch/arm/dts/fsl-ls1046a-rdb.dts
@@ -5,9 +5,7 @@
  *
  * Mingkai Hu <Mingkai.hu@freescale.com>
  *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
+ * SPDX-License-Identifier:    GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls1046a.dtsi b/arch/arm/dts/fsl-ls1046a.dtsi
index 408e81e..f46707d 100644
--- a/arch/arm/dts/fsl-ls1046a.dtsi
+++ b/arch/arm/dts/fsl-ls1046a.dtsi
@@ -5,9 +5,7 @@
  *
  * Mingkai Hu <mingkai.hu@nxp.com>
  *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
+ * SPDX-License-Identifier:    GPL-2.0+	X11
  */
 
 /include/ "skeleton64.dtsi"
diff --git a/arch/arm/dts/fsl-ls1088a-qds.dts b/arch/arm/dts/fsl-ls1088a-qds.dts
index 9b7bef4..225c7c5 100644
--- a/arch/arm/dts/fsl-ls1088a-qds.dts
+++ b/arch/arm/dts/fsl-ls1088a-qds.dts
@@ -3,7 +3,7 @@
  *
  * Copyright 2017 NXP
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls1088a-rdb.dts b/arch/arm/dts/fsl-ls1088a-rdb.dts
index 30ceed8..7b6ca1d 100644
--- a/arch/arm/dts/fsl-ls1088a-rdb.dts
+++ b/arch/arm/dts/fsl-ls1088a-rdb.dts
@@ -3,7 +3,7 @@
  *
  * Copyright 2017 NXP
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls1088a.dtsi b/arch/arm/dts/fsl-ls1088a.dtsi
index 64b4fcf..f8f8654 100644
--- a/arch/arm/dts/fsl-ls1088a.dtsi
+++ b/arch/arm/dts/fsl-ls1088a.dtsi
@@ -3,7 +3,7 @@
  *
  * Copyright 2017 NXP
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 / {
diff --git a/arch/arm/dts/fsl-ls2080a-qds.dts b/arch/arm/dts/fsl-ls2080a-qds.dts
index 0a7f1ff..b85b802 100644
--- a/arch/arm/dts/fsl-ls2080a-qds.dts
+++ b/arch/arm/dts/fsl-ls2080a-qds.dts
@@ -3,7 +3,7 @@
  *
  * Copyright 2013-2015 Freescale Semiconductor, Inc.
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls2080a-rdb.dts b/arch/arm/dts/fsl-ls2080a-rdb.dts
index 1a1813b..04b1a71 100644
--- a/arch/arm/dts/fsl-ls2080a-rdb.dts
+++ b/arch/arm/dts/fsl-ls2080a-rdb.dts
@@ -3,7 +3,7 @@
  *
  * Copyright 2013-2015 Freescale Semiconductor, Inc.
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls2080a.dtsi b/arch/arm/dts/fsl-ls2080a.dtsi
index 79047d5..69273a9 100644
--- a/arch/arm/dts/fsl-ls2080a.dtsi
+++ b/arch/arm/dts/fsl-ls2080a.dtsi
@@ -3,7 +3,7 @@
  *
  * Copyright 2013-2015 Freescale Semiconductor, Inc.
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 / {
diff --git a/arch/arm/dts/fsl-ls2081a-rdb.dts b/arch/arm/dts/fsl-ls2081a-rdb.dts
index aa4aa68..ef668a3 100644
--- a/arch/arm/dts/fsl-ls2081a-rdb.dts
+++ b/arch/arm/dts/fsl-ls2081a-rdb.dts
@@ -5,7 +5,7 @@
  *
  * Copyright 2017 NXP
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/fsl-ls2088a-rdb-qspi.dts b/arch/arm/dts/fsl-ls2088a-rdb-qspi.dts
index 3230e7e..9e3875d 100644
--- a/arch/arm/dts/fsl-ls2088a-rdb-qspi.dts
+++ b/arch/arm/dts/fsl-ls2088a-rdb-qspi.dts
@@ -5,7 +5,7 @@
  *
  * Copyright 2017 NXP
  *
- * SPDX-License-Identifier:	GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+	X11
  */
 
 /dts-v1/;
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
index 12fd6b8..9becdf3 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
@@ -164,6 +164,7 @@
 #ifdef CONFIG_FSL_LSCH2
 const char *serdes_clock_to_string(u32 clock);
 int get_serdes_protocol(void);
+#endif
 #ifdef CONFIG_SYS_HAS_SERDES
 /* Get the volt of SVDD in unit mV */
 int get_serdes_volt(void);
@@ -172,6 +173,5 @@
 /* The target volt of SVDD in unit mV */
 int setup_serdes_volt(u32 svdd);
 #endif
-#endif
 
 #endif /* __FSL_SERDES_H__ */
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
index 957e23b..642df2f 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch3.h
@@ -201,10 +201,15 @@
 	u32	gpporcr3;
 	u32	gpporcr4;
 	u8	res_030[0x60-0x30];
-#define FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT	2
 #define FSL_CHASSIS3_DCFG_FUSESR_VID_MASK	0x1F
-#define FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT	7
 #define FSL_CHASSIS3_DCFG_FUSESR_ALTVID_MASK	0x1F
+#if defined(CONFIG_ARCH_LS1088A)
+#define FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT	25
+#define FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT	20
+#else
+#define FSL_CHASSIS3_DCFG_FUSESR_VID_SHIFT	2
+#define FSL_CHASSIS3_DCFG_FUSESR_ALTVID_SHIFT	7
+#endif
 	u32	dcfg_fusesr;	/* Fuse status register */
 	u8	res_064[0x70-0x64];
 	u32	devdisr;	/* Device disable control 1 */
@@ -387,5 +392,39 @@
 	u32 ip_rev2;			/* 0xbfc */
 };
 
+struct ccsr_serdes {
+	struct {
+		u32     rstctl; /* Reset Control Register */
+		u32     pllcr0; /* PLL Control Register 0 */
+		u32     pllcr1; /* PLL Control Register 1 */
+		u32     pllcr2; /* PLL Control Register 2 */
+		u32     pllcr3; /* PLL Control Register 3 */
+		u32     pllcr4; /* PLL Control Register 4 */
+		u32     pllcr5; /* PLL Control Register 5 */
+		u8      res[0x20 - 0x1c];
+	} bank[2];
+	u8      res1[0x90 - 0x40];
+	u32     srdstcalcr;     /* TX Calibration Control */
+	u32     srdstcalcr1;    /* TX Calibration Control1 */
+	u8      res2[0xa0 - 0x98];
+	u32     srdsrcalcr;     /* RX Calibration Control */
+	u32     srdsrcalcr1;    /* RX Calibration Control1 */
+	u8      res3[0xb0 - 0xa8];
+	u32     srdsgr0;        /* General Register 0 */
+	u8      res4[0x800 - 0xb4];
+	struct serdes_lane {
+		u32     gcr0;   /* General Control Register 0 */
+		u32     gcr1;   /* General Control Register 1 */
+		u32     gcr2;   /* General Control Register 2 */
+		u32     ssc0;   /* Speed Switch Control 0 */
+		u32     rec0;   /* Receive Equalization Control 0 */
+		u32     rec1;   /* Receive Equalization Control 1 */
+		u32     tec0;   /* Transmit Equalization Control 0 */
+		u32     ssc1;   /* Speed Switch Control 1 */
+		u8      res1[0x840 - 0x820];
+	} lane[8];
+	u8 res5[0x19fc - 0xa00];
+};
+
 #endif /*__ASSEMBLY__*/
 #endif /* __ARCH_FSL_LSCH3_IMMAP_H_ */
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/soc.h b/arch/arm/include/asm/arch-fsl-layerscape/soc.h
index 1e65e4e..cb760b5 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/soc.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/soc.h
@@ -121,6 +121,7 @@
 
 #ifdef CONFIG_FSL_LSCH3
 void fsl_lsch3_early_init_f(void);
+int get_core_volt_from_fuse(void);
 #elif defined(CONFIG_FSL_LSCH2)
 void fsl_lsch2_early_init_f(void);
 int setup_chip_volt(void);
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index abffa10..876024f 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -112,4 +112,5 @@
 CFLAGS_REMOVE_$(EFI_RELOC) := $(CFLAGS_NON_EFI)
 
 extra-$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE) += $(EFI_CRT0) $(EFI_RELOC)
+extra-$(CONFIG_CMD_BOOTEFI_SELFTEST) += $(EFI_CRT0) $(EFI_RELOC)
 extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC)
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index 35e4e9b..51a70e0 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -6,47 +6,63 @@
 
 config TARGET_IPAM390
 	bool "IPAM390 board"
+	select MACH_DAVINCI_DA850_EVM
+	select SOC_DA850
 	select SUPPORT_SPL
-	select SYS_DA850_PLL_INIT
-	select SYS_DA850_DDR_INIT
 
 config TARGET_DA850EVM
 	bool "DA850 EVM board"
+	select MACH_DAVINCI_DA850_EVM
+	select SOC_DA850
 	select SUPPORT_SPL
-	select SYS_DA850_PLL_INIT
-	select SYS_DA850_DDR_INIT
 
 config TARGET_EA20
 	bool "EA20 board"
+	select MACH_DAVINCI_DA850_EVM
+	select SOC_DA850
 	select BOARD_LATE_INIT
 
 config TARGET_OMAPL138_LCDK
 	bool "OMAPL138 LCDK"
+	select SOC_DA8XX
 	select SUPPORT_SPL
-	select SYS_DA850_PLL_INIT
-	select SYS_DA850_DDR_INIT
 
 config TARGET_CALIMAIN
 	bool "Calimain board"
-	select SYS_DA850_PLL_INIT
-	select SYS_DA850_DDR_INIT
+	select SOC_DA850
 
 config TARGET_LEGOEV3
 	bool "LEGO MINDSTORMS EV3"
-	select SYS_DA850_PLL_INIT
-	select SYS_DA850_DDR_INIT
+	select MACH_DAVINCI_DA850_EVM
+	select SOC_DA850
 
 endchoice
 
 config SYS_SOC
 	default "davinci"
 
+config DA850_LOWLEVEL
+	bool "Enable Lowlevel DA850 initialization"
+	depends on SOC_DA850
+
 config SYS_DA850_PLL_INIT
 	bool
 
 config SYS_DA850_DDR_INIT
 	bool
 
+config SOC_DA850
+	bool
+	select SOC_DA8XX
+	select SYS_DA850_DDR_INIT if SUPPORT_SPL || DA850_LOWLEVEL
+
+config SOC_DA8XX
+	bool
+	select SYS_DA850_PLL_INIT if SUPPORT_SPL || DA850_LOWLEVEL
+
+config MACH_DAVINCI_DA850_EVM
+	bool
+
 source "board/Barix/ipam390/Kconfig"
 source "board/davinci/da8xxevm/Kconfig"
 source "board/davinci/ea20/Kconfig"
diff --git a/board/freescale/common/Kconfig b/board/freescale/common/Kconfig
index 280f7d4..8b89c10 100644
--- a/board/freescale/common/Kconfig
+++ b/board/freescale/common/Kconfig
@@ -20,3 +20,19 @@
 
 	    esbc_validate - validate signature using RSA verification
 	    esbc_halt - put the core in spin loop (Secure Boot Only)
+
+config VOL_MONITOR_LTC3882_READ
+	depends on VID
+	bool "Enable the LTC3882 voltage monitor read"
+	default n
+	help
+	 This option enables LTC3882 voltage monitor read
+	 functionality. It is used by common VID driver.
+
+config VOL_MONITOR_LTC3882_SET
+	depends on VID
+	bool "Enable the LTC3882 voltage monitor set"
+	default n
+	help
+	 This option enables LTC3882 voltage monitor set
+	 functionality. It is used by common VID driver.
diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile
index e13cb20..939e9c6 100644
--- a/board/freescale/common/Makefile
+++ b/board/freescale/common/Makefile
@@ -23,8 +23,8 @@
 obj-$(CONFIG_FSL_PIXIS)	+= pixis.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_FSL_NGPIXIS)	+= ngpixis.o
-obj-$(CONFIG_VID)		+= vid.o
 endif
+obj-$(CONFIG_VID)		+= vid.o
 obj-$(CONFIG_FSL_QIXIS)	+= qixis.o
 obj-$(CONFIG_PQ_MDS_PIB)	+= pq-mds-pib.o
 ifndef CONFIG_SPL_BUILD
diff --git a/board/freescale/common/qixis.c b/board/freescale/common/qixis.c
index 24459f8..844c00a 100644
--- a/board/freescale/common/qixis.c
+++ b/board/freescale/common/qixis.c
@@ -235,6 +235,28 @@
 #else
 		printf("Not implemented\n");
 #endif
+	} else if (strcmp(argv[1], "ifc") == 0) {
+#ifdef QIXIS_LBMAP_IFC
+		QIXIS_WRITE(rst_ctl, 0x30);
+		QIXIS_WRITE(rcfg_ctl, 0);
+		set_lbmap(QIXIS_LBMAP_IFC);
+		set_rcw_src(QIXIS_RCW_SRC_IFC);
+		QIXIS_WRITE(rcfg_ctl, 0x20);
+		QIXIS_WRITE(rcfg_ctl, 0x21);
+#else
+		printf("Not implemented\n");
+#endif
+	} else if (strcmp(argv[1], "emmc") == 0) {
+#ifdef QIXIS_LBMAP_EMMC
+		QIXIS_WRITE(rst_ctl, 0x30);
+		QIXIS_WRITE(rcfg_ctl, 0);
+		set_lbmap(QIXIS_LBMAP_EMMC);
+		set_rcw_src(QIXIS_RCW_SRC_EMMC);
+		QIXIS_WRITE(rcfg_ctl, 0x20);
+		QIXIS_WRITE(rcfg_ctl, 0x21);
+#else
+		printf("Not implemented\n");
+#endif
 	} else if (strcmp(argv[1], "sd_qspi") == 0) {
 #ifdef QIXIS_LBMAP_SD_QSPI
 		QIXIS_WRITE(rst_ctl, 0x30);
diff --git a/board/freescale/common/vid.c b/board/freescale/common/vid.c
index d6d1bfc..a9451c5 100644
--- a/board/freescale/common/vid.c
+++ b/board/freescale/common/vid.c
@@ -34,6 +34,16 @@
 }
 
 /*
+ * Board specific settings for specific voltage value
+ */
+int __weak board_adjust_vdd(int vdd)
+{
+	return 0;
+}
+
+#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
+	defined(CONFIG_VOL_MONITOR_IR36021_READ)
+/*
  * Get the i2c address configuration for the IR regulator chip
  *
  * There are some variance in the RDB HW regarding the I2C address configuration
@@ -65,6 +75,7 @@
 	}
 	return -1;
 }
+#endif
 
 /* Maximum loop count waiting for new voltage to take effect */
 #define MAX_LOOP_WAIT_NEW_VOL		100
@@ -163,6 +174,36 @@
 }
 #endif
 
+#ifdef CONFIG_VOL_MONITOR_LTC3882_READ
+/* read the current value of the LTC Regulator Voltage */
+static int read_voltage_from_LTC(int i2caddress)
+{
+	int  ret, vcode = 0;
+	u8 chan = PWM_CHANNEL0;
+
+	/* select the PAGE 0 using PMBus commands PAGE for VDD*/
+	ret = i2c_write(I2C_VOL_MONITOR_ADDR,
+			PMBUS_CMD_PAGE, 1, &chan, 1);
+	if (ret) {
+		printf("VID: failed to select VDD Page 0\n");
+		return ret;
+	}
+
+	/*read the output voltage using PMBus command READ_VOUT*/
+	ret = i2c_read(I2C_VOL_MONITOR_ADDR,
+		       PMBUS_CMD_READ_VOUT, 1, (void *)&vcode, 2);
+	if (ret) {
+		printf("VID: failed to read the volatge\n");
+		return ret;
+	}
+
+	/* Scale down to the real mV as LTC resolution is 1/4096V,rounding up */
+	vcode = DIV_ROUND_UP(vcode * 1000, 4096);
+
+	return vcode;
+}
+#endif
+
 static int read_voltage(int i2caddress)
 {
 	int voltage_read;
@@ -170,12 +211,15 @@
 	voltage_read = read_voltage_from_INA220(i2caddress);
 #elif defined CONFIG_VOL_MONITOR_IR36021_READ
 	voltage_read = read_voltage_from_IR(i2caddress);
+#elif defined CONFIG_VOL_MONITOR_LTC3882_READ
+	voltage_read = read_voltage_from_LTC(i2caddress);
 #else
 	return -1;
 #endif
 	return voltage_read;
 }
 
+#ifdef CONFIG_VOL_MONITOR_IR36021_SET
 /*
  * We need to calculate how long before the voltage stops to drop
  * or increase. It returns with the loop count. Each loop takes
@@ -235,7 +279,6 @@
 	return vdd_current;
 }
 
-#ifdef CONFIG_VOL_MONITOR_IR36021_SET
 /* Set the voltage to the IR chip */
 static int set_voltage_to_IR(int i2caddress, int vdd)
 {
@@ -270,14 +313,53 @@
 	debug("VID: Current voltage is %d mV\n", vdd_last);
 	return vdd_last;
 }
+
 #endif
 
+#ifdef CONFIG_VOL_MONITOR_LTC3882_SET
+/* this function sets the VDD and returns the value set */
+static int set_voltage_to_LTC(int i2caddress, int vdd)
+{
+	int ret, vdd_last, vdd_target = vdd;
+
+	/* Scale up to the LTC resolution is 1/4096V */
+	vdd = (vdd * 4096) / 1000;
+
+	/* 5-byte buffer which needs to be sent following the
+	 * PMBus command PAGE_PLUS_WRITE.
+	 */
+	u8 buff[5] = {0x04, PWM_CHANNEL0, PMBUS_CMD_VOUT_COMMAND,
+			vdd & 0xFF, (vdd & 0xFF00) >> 8};
+
+	/* Write the desired voltage code to the regulator */
+	ret = i2c_write(I2C_VOL_MONITOR_ADDR,
+			PMBUS_CMD_PAGE_PLUS_WRITE, 1, (void *)&buff, 5);
+	if (ret) {
+		printf("VID: I2C failed to write to the volatge regulator\n");
+		return -1;
+	}
+
+	/* Wait for the volatge to get to the desired value */
+	do {
+		vdd_last = read_voltage_from_LTC(i2caddress);
+		if (vdd_last < 0) {
+			printf("VID: Couldn't read sensor abort VID adjust\n");
+			return -1;
+		}
+	} while (vdd_last != vdd_target);
+
+	return vdd_last;
+}
+#endif
+
 static int set_voltage(int i2caddress, int vdd)
 {
 	int vdd_last = -1;
 
 #ifdef CONFIG_VOL_MONITOR_IR36021_SET
 	vdd_last = set_voltage_to_IR(i2caddress, vdd);
+#elif defined CONFIG_VOL_MONITOR_LTC3882_SET
+	vdd_last = set_voltage_to_LTC(i2caddress, vdd);
 #else
 	#error Specific voltage monitor must be defined
 #endif
@@ -290,11 +372,53 @@
 	int re_enable = disable_interrupts();
 	struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
 	u32 fusesr;
+#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
+	defined(CONFIG_VOL_MONITOR_IR36021_READ)
 	u8 vid, buf;
+#else
+	u8 vid;
+#endif
 	int vdd_target, vdd_current, vdd_last;
 	int ret, i2caddress;
 	unsigned long vdd_string_override;
 	char *vdd_string;
+#ifdef CONFIG_ARCH_LS1088A
+	static const uint16_t vdd[32] = {
+		10250,
+		9875,
+		9750,
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		9000,
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		10000,  /* 1.0000V */
+		10125,
+		10250,
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+		0,      /* reserved */
+	};
+
+#else
 	static const uint16_t vdd[32] = {
 		10500,
 		0,      /* reserved */
@@ -329,6 +453,7 @@
 		0,      /* reserved */
 		0,      /* reserved */
 	};
+#endif
 	struct vdd_drive {
 		u8 vid;
 		unsigned voltage;
@@ -340,6 +465,8 @@
 		ret = -1;
 		goto exit;
 	}
+#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
+	defined(CONFIG_VOL_MONITOR_IR36021_READ)
 	ret = find_ir_chip_on_i2c();
 	if (ret < 0) {
 		printf("VID: Could not find voltage regulator on I2C.\n");
@@ -364,6 +491,7 @@
 		ret = -1;
 		goto exit;
 	}
+#endif
 
 	/* get the voltage ID from fuse status register */
 	fusesr = in_le32(&gur->dcfg_fusesr);
@@ -415,6 +543,11 @@
 	}
 	vdd_current = vdd_last;
 	debug("VID: Core voltage is currently at %d mV\n", vdd_last);
+
+#ifdef CONFIG_VOL_MONITOR_LTC3882_SET
+	/* Set the target voltage */
+	vdd_last = vdd_current = set_voltage(i2caddress, vdd_target);
+#else
 	/*
 	  * Adjust voltage to at or one step above target.
 	  * As measurements are less precise than setting the values
@@ -432,6 +565,12 @@
 		vdd_last = set_voltage(i2caddress, vdd_current);
 	}
 
+#endif
+	if (board_adjust_vdd(vdd_target) < 0) {
+		ret = -1;
+		goto exit;
+	}
+
 	if (vdd_last > 0)
 		printf("VID: Core voltage after adjustment is at %d mV\n",
 		       vdd_last);
@@ -498,6 +637,8 @@
 		ret = -1;
 		goto exit;
 	}
+#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
+	defined(CONFIG_VOL_MONITOR_IR36021_READ)
 	ret = find_ir_chip_on_i2c();
 	if (ret < 0) {
 		printf("VID: Could not find voltage regulator on I2C.\n");
@@ -522,6 +663,7 @@
 		ret = -1;
 		goto exit;
 	}
+#endif
 
 	/* get the voltage ID from fuse status register */
 	fusesr = in_be32(&gur->dcfg_fusesr);
@@ -632,6 +774,8 @@
 		debug("VID : I2c failed to switch channel\n");
 		return -1;
 	}
+#if defined(CONFIG_VOL_MONITOR_IR36021_SET) || \
+	defined(CONFIG_VOL_MONITOR_IR36021_READ)
 	ret = find_ir_chip_on_i2c();
 	if (ret < 0) {
 		printf("VID: Could not find voltage regulator on I2C.\n");
@@ -640,6 +784,7 @@
 		i2caddress = ret;
 		debug("VID: IR Chip found on I2C address 0x%02x\n", i2caddress);
 	}
+#endif
 
 	/*
 	 * Read voltage monitor to check real voltage.
diff --git a/board/freescale/ls1088a/ddr.c b/board/freescale/ls1088a/ddr.c
index e24bfd5..2240454 100644
--- a/board/freescale/ls1088a/ddr.c
+++ b/board/freescale/ls1088a/ddr.c
@@ -13,6 +13,23 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#if defined(CONFIG_VID) && (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
+static void fsl_ddr_setup_0v9_volt(memctl_options_t *popts)
+{
+	int vdd;
+
+	vdd = get_core_volt_from_fuse();
+	/* Nothing to do for silicons doesn't support VID */
+	if (vdd < 0)
+		return;
+
+	if (vdd == 900) {
+		popts->ddr_cdr1 |= DDR_CDR1_V0PT9_EN;
+		debug("VID: configure DDR to support 900 mV\n");
+	}
+}
+#endif
+
 void fsl_ddr_board_options(memctl_options_t *popts,
 			   dimm_params_t *pdimm,
 			   unsigned int ctrl_num)
@@ -87,6 +104,10 @@
 	popts->addr_hash = 1;
 
 	popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_60ohm);
+#if defined(CONFIG_VID) && (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
+	fsl_ddr_setup_0v9_volt(popts);
+#endif
+
 	popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) |
 			  DDR_CDR2_VREF_TRAIN_EN | DDR_CDR2_VREF_RANGE_2;
 }
diff --git a/board/freescale/ls1088a/ls1088a.c b/board/freescale/ls1088a/ls1088a.c
index d12bcae..0769e90 100644
--- a/board/freescale/ls1088a/ls1088a.c
+++ b/board/freescale/ls1088a/ls1088a.c
@@ -19,9 +19,13 @@
 #include <asm/arch-fsl-layerscape/soc.h>
 #include <asm/arch/ppa.h>
 #include <hwconfig.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/soc.h>
 
 #include "../common/qixis.h"
 #include "ls1088a_qixis.h"
+#include "../common/vid.h"
+#include <fsl_immap.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -51,6 +55,16 @@
 }
 #endif
 
+#if defined(CONFIG_VID)
+int init_func_vid(void)
+{
+	if (adjust_vdd(0) < 0)
+		printf("core voltage not adjusted\n");
+
+	return 0;
+}
+#endif
+
 #if !defined(CONFIG_SPL_BUILD)
 int checkboard(void)
 {
@@ -207,6 +221,7 @@
 
 	return 66666666;
 }
+#endif
 
 int select_i2c_ch_pca9547(u8 ch)
 {
@@ -221,6 +236,7 @@
 	return 0;
 }
 
+#if !defined(CONFIG_SPL_BUILD)
 void board_retimer_init(void)
 {
 	u8 reg;
@@ -322,7 +338,122 @@
 	return 0;
 }
 #endif
+#endif
+
+int i2c_multiplexer_select_vid_channel(u8 channel)
+{
+	return select_i2c_ch_pca9547(channel);
+}
+
+#ifdef CONFIG_TARGET_LS1088AQDS
+/* read the current value(SVDD) of the LTM Regulator Voltage */
+int get_serdes_volt(void)
+{
+	int  ret, vcode = 0;
+	u8 chan = PWM_CHANNEL0;
 
+	/* Select the PAGE 0 using PMBus commands PAGE for VDD */
+	ret = i2c_write(I2C_SVDD_MONITOR_ADDR,
+			PMBUS_CMD_PAGE, 1, &chan, 1);
+	if (ret) {
+		printf("VID: failed to select VDD Page 0\n");
+		return ret;
+	}
+
+	/* Read the output voltage using PMBus command READ_VOUT */
+	ret = i2c_read(I2C_SVDD_MONITOR_ADDR,
+		       PMBUS_CMD_READ_VOUT, 1, (void *)&vcode, 2);
+	if (ret) {
+		printf("VID: failed to read the volatge\n");
+		return ret;
+	}
+
+	return vcode;
+}
+
+int set_serdes_volt(int svdd)
+{
+	int ret, vdd_last;
+	u8 buff[5] = {0x04, PWM_CHANNEL0, PMBUS_CMD_VOUT_COMMAND,
+			svdd & 0xFF, (svdd & 0xFF00) >> 8};
+
+	/* Write the desired voltage code to the SVDD regulator */
+	ret = i2c_write(I2C_SVDD_MONITOR_ADDR,
+			PMBUS_CMD_PAGE_PLUS_WRITE, 1, (void *)&buff, 5);
+	if (ret) {
+		printf("VID: I2C failed to write to the volatge regulator\n");
+		return -1;
+	}
+
+	/* Wait for the volatge to get to the desired value */
+	do {
+		vdd_last = get_serdes_volt();
+		if (vdd_last < 0) {
+			printf("VID: Couldn't read sensor abort VID adjust\n");
+			return -1;
+		}
+	} while (vdd_last != svdd);
+
+	return 1;
+}
+#else
+int get_serdes_volt(void)
+{
+	return 0;
+}
+
+int set_serdes_volt(int svdd)
+{
+	int ret;
+	u8 brdcfg4;
+
+	printf("SVDD changing of RDB\n");
+
+	/* Read the BRDCFG54 via CLPD */
+	ret = i2c_read(CONFIG_SYS_I2C_FPGA_ADDR,
+		       QIXIS_BRDCFG4_OFFSET, 1, (void *)&brdcfg4, 1);
+	if (ret) {
+		printf("VID: I2C failed to read the CPLD BRDCFG4\n");
+		return -1;
+	}
+
+	brdcfg4 = brdcfg4 | 0x08;
+
+	/* Write to the BRDCFG4 */
+	ret = i2c_write(CONFIG_SYS_I2C_FPGA_ADDR,
+			QIXIS_BRDCFG4_OFFSET, 1, (void *)&brdcfg4, 1);
+	if (ret) {
+		debug("VID: I2C failed to set the SVDD CPLD BRDCFG4\n");
+		return -1;
+	}
+
+	/* Wait for the volatge to get to the desired value */
+	udelay(10000);
+
+	return 1;
+}
+#endif
+
+/* this function disables the SERDES, changes the SVDD Voltage and enables it*/
+int board_adjust_vdd(int vdd)
+{
+	int ret = 0;
+
+	debug("%s: vdd = %d\n", __func__, vdd);
+
+	/* Special settings to be performed when voltage is 900mV */
+	if (vdd == 900) {
+		ret = setup_serdes_volt(vdd);
+		if (ret < 0) {
+			ret = -1;
+			goto exit;
+		}
+	}
+exit:
+	return ret;
+}
+
+#if !defined(CONFIG_SPL_BUILD)
 int board_init(void)
 {
 	init_final_memctl_regs();
diff --git a/board/logicpd/omap3som/omap3logic.c b/board/logicpd/omap3som/omap3logic.c
index b30fa24..4cbbf96 100644
--- a/board/logicpd/omap3som/omap3logic.c
+++ b/board/logicpd/omap3som/omap3logic.c
@@ -40,21 +40,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-/* This is only needed until SPL gets OF support */
-#ifdef CONFIG_SPL_BUILD
-static const struct ns16550_platdata omap3logic_serial = {
-	.base = OMAP34XX_UART1,
-	.reg_shift = 2,
-	.clock = V_NS16550_CLK,
-	.fcr = UART_FCR_DEFVAL,
-};
-
-U_BOOT_DEVICE(omap3logic_uart) = {
-	"ns16550_serial",
-	&omap3logic_serial
-};
-#endif
-
 /*
  * two dimensional array of strucures containining board name and Linux
  * machine IDs; row it selected based on CPU column is slected based
diff --git a/cmd/Kconfig b/cmd/Kconfig
index faa8bc6..35fe9d5 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1367,17 +1367,20 @@
 
 config CMD_EXT2
 	bool "ext2 command support"
+	select FS_EXT4
 	help
 	  Enables EXT2 FS command
 
 config CMD_EXT4
 	bool "ext4 command support"
+	select FS_EXT4
 	help
 	  Enables EXT4 FS command
 
 config CMD_EXT4_WRITE
 	depends on CMD_EXT4
 	bool "ext4 write command support"
+	select EXT4_WRITE
 	help
 	  Enables EXT4 FS write command
 
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 78ff109..51213c02 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -32,6 +32,9 @@
 {
 	efi_obj_list_initalized = 1;
 
+	/* Initialize EFI driver uclass */
+	efi_driver_init();
+
 	efi_console_register();
 #ifdef CONFIG_PARTITIONS
 	efi_disk_register();
@@ -103,11 +106,11 @@
 
 	/* Safe fdt location is at 128MB */
 	new_fdt_addr = fdt_ram_start + (128 * 1024 * 1024) + fdt_size;
-	if (efi_allocate_pages(1, EFI_BOOT_SERVICES_DATA, fdt_pages,
+	if (efi_allocate_pages(1, EFI_RUNTIME_SERVICES_DATA, fdt_pages,
 			       &new_fdt_addr) != EFI_SUCCESS) {
 		/* If we can't put it there, put it somewhere */
 		new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size);
-		if (efi_allocate_pages(1, EFI_BOOT_SERVICES_DATA, fdt_pages,
+		if (efi_allocate_pages(1, EFI_RUNTIME_SERVICES_DATA, fdt_pages,
 				       &new_fdt_addr) != EFI_SUCCESS) {
 			printf("ERROR: Failed to reserve space for FDT\n");
 			return NULL;
@@ -122,8 +125,8 @@
 }
 
 static efi_status_t efi_do_enter(
-			void *image_handle, struct efi_system_table *st,
-			asmlinkage ulong (*entry)(void *image_handle,
+			efi_handle_t image_handle, struct efi_system_table *st,
+			asmlinkage ulong (*entry)(efi_handle_t image_handle,
 						  struct efi_system_table *st))
 {
 	efi_status_t ret = EFI_LOAD_ERROR;
@@ -136,8 +139,8 @@
 
 #ifdef CONFIG_ARM64
 static efi_status_t efi_run_in_el2(asmlinkage ulong (*entry)(
-			void *image_handle, struct efi_system_table *st),
-			void *image_handle, struct efi_system_table *st)
+			efi_handle_t image_handle, struct efi_system_table *st),
+			efi_handle_t image_handle, struct efi_system_table *st)
 {
 	/* Enable caches again */
 	dcache_enable();
@@ -159,7 +162,7 @@
 	struct efi_device_path *memdp = NULL;
 	ulong ret;
 
-	ulong (*entry)(void *image_handle, struct efi_system_table *st)
+	ulong (*entry)(efi_handle_t image_handle, struct efi_system_table *st)
 		asmlinkage;
 	ulong fdt_pages, fdt_size, fdt_start, fdt_end;
 	const efi_guid_t fdt_guid = EFI_FDT_GUID;
diff --git a/common/board_f.c b/common/board_f.c
index 0bdce64..7f594d9 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -200,6 +200,13 @@
 }
 #endif
 
+#if defined(CONFIG_VID)
+__weak int init_func_vid(void)
+{
+	return 0;
+}
+#endif
+
 #if defined(CONFIG_HARD_SPI)
 static int init_func_spi(void)
 {
@@ -801,6 +808,9 @@
 #if defined(CONFIG_SYS_I2C)
 	init_func_i2c,
 #endif
+#if defined(CONFIG_VID) && !defined(CONFIG_SPL)
+	init_func_vid,
+#endif
 #if defined(CONFIG_HARD_SPI)
 	init_func_spi,
 #endif
diff --git a/common/hash.c b/common/hash.c
index cf4d70f..69d53ed 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -390,7 +390,7 @@
 
 	if (multi_hash()) {
 		struct hash_algo *algo;
-		uint8_t output[HASH_MAX_DIGEST_SIZE];
+		u8 *output;
 		uint8_t vsum[HASH_MAX_DIGEST_SIZE];
 		void *buf;
 
@@ -405,6 +405,9 @@
 			return 1;
 		}
 
+		output = memalign(ARCH_DMA_MINALIGN,
+				  sizeof(uint32_t) * HASH_MAX_DIGEST_SIZE);
+
 		buf = map_sysmem(addr, len);
 		algo->hash_func_ws(buf, len, output, algo->chunk_size);
 		unmap_sysmem(buf);
@@ -440,6 +443,8 @@
 				store_result(algo, output, *argv,
 					flags & HASH_FLAG_ENV);
 			}
+		unmap_sysmem(output);
+
 		}
 
 	/* Horrible code size hack for boards that just want crc32 */
diff --git a/configs/am335x_baltos_defconfig b/configs/am335x_baltos_defconfig
index 0ef9f42..548e045 100644
--- a/configs/am335x_baltos_defconfig
+++ b/configs/am335x_baltos_defconfig
@@ -55,6 +55,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am335x_boneblack_defconfig b/configs/am335x_boneblack_defconfig
index 50093cd..f14333d 100644
--- a/configs/am335x_boneblack_defconfig
+++ b/configs/am335x_boneblack_defconfig
@@ -33,6 +33,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am335x_boneblack_vboot_defconfig b/configs/am335x_boneblack_vboot_defconfig
index aa9fb97..016ec4e 100644
--- a/configs/am335x_boneblack_vboot_defconfig
+++ b/configs/am335x_boneblack_vboot_defconfig
@@ -43,6 +43,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig
index 9c97009..9e79d1c 100644
--- a/configs/am335x_evm_defconfig
+++ b/configs/am335x_evm_defconfig
@@ -47,6 +47,7 @@
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_MUSB_TI=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am335x_evm_nor_defconfig b/configs/am335x_evm_nor_defconfig
index 1813003..14aa267 100644
--- a/configs/am335x_evm_nor_defconfig
+++ b/configs/am335x_evm_nor_defconfig
@@ -34,6 +34,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am335x_evm_norboot_defconfig b/configs/am335x_evm_norboot_defconfig
index b38d7f6..22182f5 100644
--- a/configs/am335x_evm_norboot_defconfig
+++ b/configs/am335x_evm_norboot_defconfig
@@ -30,6 +30,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am335x_evm_spiboot_defconfig b/configs/am335x_evm_spiboot_defconfig
index 7a20576..71d6a28 100644
--- a/configs/am335x_evm_spiboot_defconfig
+++ b/configs/am335x_evm_spiboot_defconfig
@@ -32,6 +32,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am335x_evm_usbspl_defconfig b/configs/am335x_evm_usbspl_defconfig
index 1e80017..10d6d38 100644
--- a/configs/am335x_evm_usbspl_defconfig
+++ b/configs/am335x_evm_usbspl_defconfig
@@ -38,6 +38,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am335x_hs_evm_defconfig b/configs/am335x_hs_evm_defconfig
index 63e7a07..55565f4 100644
--- a/configs/am335x_hs_evm_defconfig
+++ b/configs/am335x_hs_evm_defconfig
@@ -56,6 +56,7 @@
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_MUSB_TI=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am335x_hs_evm_uart_defconfig b/configs/am335x_hs_evm_uart_defconfig
index 09aab29..7f05d56 100644
--- a/configs/am335x_hs_evm_uart_defconfig
+++ b/configs/am335x_hs_evm_uart_defconfig
@@ -53,6 +53,7 @@
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_MUSB_TI=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
diff --git a/configs/am3517_crane_defconfig b/configs/am3517_crane_defconfig
index a1766d9..2e8d943 100644
--- a/configs/am3517_crane_defconfig
+++ b/configs/am3517_crane_defconfig
@@ -31,4 +31,6 @@
 CONFIG_SPL_NAND_SIMPLE=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
+CONFIG_USB_MUSB_HCD=y
+CONFIG_USB_AM35X=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/am3517_evm_defconfig b/configs/am3517_evm_defconfig
index e6c17c7..bb7cc3f 100644
--- a/configs/am3517_evm_defconfig
+++ b/configs/am3517_evm_defconfig
@@ -40,5 +40,6 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
+CONFIG_USB_MUSB_AM35X=y
 # CONFIG_FAT_WRITE is not set
 CONFIG_BCH=y
diff --git a/configs/am43xx_evm_defconfig b/configs/am43xx_evm_defconfig
index c1802140..c75eab3 100644
--- a/configs/am43xx_evm_defconfig
+++ b/configs/am43xx_evm_defconfig
@@ -49,6 +49,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_PHY_OMAP=y
+CONFIG_OMAP_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am43xx_evm_ethboot_defconfig b/configs/am43xx_evm_ethboot_defconfig
index 60f0552..7f2acd9 100644
--- a/configs/am43xx_evm_ethboot_defconfig
+++ b/configs/am43xx_evm_ethboot_defconfig
@@ -60,6 +60,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_PHY_OMAP=y
+CONFIG_OMAP_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am43xx_evm_qspiboot_defconfig b/configs/am43xx_evm_qspiboot_defconfig
index d6a5263..a56abc9 100644
--- a/configs/am43xx_evm_qspiboot_defconfig
+++ b/configs/am43xx_evm_qspiboot_defconfig
@@ -49,6 +49,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_PHY_OMAP=y
+CONFIG_OMAP_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am43xx_evm_usbhost_boot_defconfig b/configs/am43xx_evm_usbhost_boot_defconfig
index 28cf04a..e9c3a05 100644
--- a/configs/am43xx_evm_usbhost_boot_defconfig
+++ b/configs/am43xx_evm_usbhost_boot_defconfig
@@ -72,6 +72,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_PHY_OMAP=y
+CONFIG_OMAP_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am43xx_hs_evm_defconfig b/configs/am43xx_hs_evm_defconfig
index bed0583..e8a641e 100644
--- a/configs/am43xx_hs_evm_defconfig
+++ b/configs/am43xx_hs_evm_defconfig
@@ -60,6 +60,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_PHY_OMAP=y
+CONFIG_OMAP_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig
index b3b3cf7..0bcda4f 100644
--- a/configs/am57xx_evm_defconfig
+++ b/configs/am57xx_evm_defconfig
@@ -70,6 +70,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_PHY_OMAP=y
+CONFIG_OMAP_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/am57xx_hs_evm_defconfig b/configs/am57xx_hs_evm_defconfig
index edfead0..2e0763c 100644
--- a/configs/am57xx_hs_evm_defconfig
+++ b/configs/am57xx_hs_evm_defconfig
@@ -73,6 +73,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_PHY_OMAP=y
+CONFIG_OMAP_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/birdland_bav335a_defconfig b/configs/birdland_bav335a_defconfig
index 61518f5..d6d5d71 100644
--- a/configs/birdland_bav335a_defconfig
+++ b/configs/birdland_bav335a_defconfig
@@ -62,6 +62,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/birdland_bav335b_defconfig b/configs/birdland_bav335b_defconfig
index c7360c3..0c14595 100644
--- a/configs/birdland_bav335b_defconfig
+++ b/configs/birdland_bav335b_defconfig
@@ -62,6 +62,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/brppt1_mmc_defconfig b/configs/brppt1_mmc_defconfig
index c41a7b4..aa3e317 100644
--- a/configs/brppt1_mmc_defconfig
+++ b/configs/brppt1_mmc_defconfig
@@ -55,6 +55,7 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_SYS_WHITE_ON_BLACK=y
 CONFIG_LCD=y
diff --git a/configs/brppt1_nand_defconfig b/configs/brppt1_nand_defconfig
index 3844413..c8063b9 100644
--- a/configs/brppt1_nand_defconfig
+++ b/configs/brppt1_nand_defconfig
@@ -57,6 +57,7 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_SYS_WHITE_ON_BLACK=y
 CONFIG_LCD=y
diff --git a/configs/brppt1_spi_defconfig b/configs/brppt1_spi_defconfig
index 25d8837..6385b1a 100644
--- a/configs/brppt1_spi_defconfig
+++ b/configs/brppt1_spi_defconfig
@@ -65,6 +65,7 @@
 CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_SYS_WHITE_ON_BLACK=y
 CONFIG_LCD=y
diff --git a/configs/brxre1_defconfig b/configs/brxre1_defconfig
index 0c2d7ed..15245dc 100644
--- a/configs/brxre1_defconfig
+++ b/configs/brxre1_defconfig
@@ -56,6 +56,7 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_SYS_WHITE_ON_BLACK=y
 CONFIG_LCD=y
diff --git a/configs/calimain_defconfig b/configs/calimain_defconfig
index a02926c..d8ab012 100644
--- a/configs/calimain_defconfig
+++ b/configs/calimain_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_DAVINCI=y
 CONFIG_TARGET_CALIMAIN=y
+CONFIG_DA850_LOWLEVEL=y
 CONFIG_BOOTDELAY=0
 CONFIG_VERSION_VARIABLE=y
 # CONFIG_DISPLAY_CPUINFO is not set
diff --git a/configs/chiliboard_defconfig b/configs/chiliboard_defconfig
index bc69df0..a32dab7 100644
--- a/configs/chiliboard_defconfig
+++ b/configs/chiliboard_defconfig
@@ -45,6 +45,7 @@
 CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_FAT_WRITE=y
 CONFIG_LZO=y
diff --git a/configs/chromebit_mickey_defconfig b/configs/chromebit_mickey_defconfig
index 2a74784..b350811 100644
--- a/configs/chromebit_mickey_defconfig
+++ b/configs/chromebit_mickey_defconfig
@@ -74,6 +74,7 @@
 CONFIG_ROCKCHIP_SPI=y
 CONFIG_SYSRESET=y
 CONFIG_USB=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
diff --git a/configs/chromebook_jerry_defconfig b/configs/chromebook_jerry_defconfig
index 81ed7d0..f80faae 100644
--- a/configs/chromebook_jerry_defconfig
+++ b/configs/chromebook_jerry_defconfig
@@ -75,6 +75,7 @@
 CONFIG_ROCKCHIP_SPI=y
 CONFIG_SYSRESET=y
 CONFIG_USB=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
diff --git a/configs/chromebook_minnie_defconfig b/configs/chromebook_minnie_defconfig
index 0565c03..ff94a4d 100644
--- a/configs/chromebook_minnie_defconfig
+++ b/configs/chromebook_minnie_defconfig
@@ -74,6 +74,7 @@
 CONFIG_ROCKCHIP_SPI=y
 CONFIG_SYSRESET=y
 CONFIG_USB=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
diff --git a/configs/cl-som-am57x_defconfig b/configs/cl-som-am57x_defconfig
index 9c3031b..e9b6fe0 100644
--- a/configs/cl-som-am57x_defconfig
+++ b/configs/cl-som-am57x_defconfig
@@ -57,6 +57,7 @@
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
+CONFIG_OMAP_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
diff --git a/configs/cm_t3517_defconfig b/configs/cm_t3517_defconfig
index 819a95b..fa78bde 100644
--- a/configs/cm_t3517_defconfig
+++ b/configs/cm_t3517_defconfig
@@ -48,6 +48,7 @@
 CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
+CONFIG_USB_MUSB_AM35X=y
 CONFIG_USB_STORAGE=y
 CONFIG_LCD=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/cm_t35_defconfig b/configs/cm_t35_defconfig
index c61a93b..0cb6e72 100644
--- a/configs/cm_t35_defconfig
+++ b/configs/cm_t35_defconfig
@@ -50,6 +50,9 @@
 CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_MUSB_UDC=y
+CONFIG_USB_OMAP3=y
+CONFIG_TWL4030_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_LCD=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/cm_t43_defconfig b/configs/cm_t43_defconfig
index a621ff2..e234bc6 100644
--- a/configs/cm_t43_defconfig
+++ b/configs/cm_t43_defconfig
@@ -72,6 +72,7 @@
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
+CONFIG_OMAP_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/da850_am18xxevm_defconfig b/configs/da850_am18xxevm_defconfig
index 824c383..0675401 100644
--- a/configs/da850_am18xxevm_defconfig
+++ b/configs/da850_am18xxevm_defconfig
@@ -42,4 +42,5 @@
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_DM_SPI=y
+CONFIG_DAVINCI_SPI=y
 # CONFIG_FAT_WRITE is not set
diff --git a/configs/da850evm_defconfig b/configs/da850evm_defconfig
index 067ddd7..4c2f8f3 100644
--- a/configs/da850evm_defconfig
+++ b/configs/da850evm_defconfig
@@ -45,4 +45,5 @@
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_DM_SPI=y
+CONFIG_DAVINCI_SPI=y
 # CONFIG_FAT_WRITE is not set
diff --git a/configs/da850evm_direct_nor_defconfig b/configs/da850evm_direct_nor_defconfig
index b00eea7..72b8169 100644
--- a/configs/da850evm_direct_nor_defconfig
+++ b/configs/da850evm_direct_nor_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_DAVINCI=y
 CONFIG_TARGET_DA850EVM=y
+CONFIG_DA850_LOWLEVEL=y
 CONFIG_TI_COMMON_CMD_OPTIONS=y
 CONFIG_DEFAULT_DEVICE_TREE="da850-evm"
 # CONFIG_SYS_MALLOC_F is not set
@@ -43,3 +44,4 @@
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SYS_NS16550=y
 CONFIG_DM_SPI=y
+CONFIG_DAVINCI_SPI=y
diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig
index 716a57b..b13a27e 100644
--- a/configs/dra7xx_evm_defconfig
+++ b/configs/dra7xx_evm_defconfig
@@ -80,6 +80,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_PHY_OMAP=y
+CONFIG_OMAP_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig
index f7418c7..7ccb4f0 100644
--- a/configs/dra7xx_hs_evm_defconfig
+++ b/configs/dra7xx_hs_evm_defconfig
@@ -82,6 +82,7 @@
 CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_DWC3_OMAP=y
 CONFIG_USB_DWC3_PHY_OMAP=y
+CONFIG_OMAP_USB_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
diff --git a/configs/draco_defconfig b/configs/draco_defconfig
index be0105f..5444260 100644
--- a/configs/draco_defconfig
+++ b/configs/draco_defconfig
@@ -64,6 +64,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
diff --git a/configs/ds109_defconfig b/configs/ds109_defconfig
index 6d513cf..428ac8c 100644
--- a/configs/ds109_defconfig
+++ b/configs/ds109_defconfig
@@ -22,3 +22,4 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_FS_EXT4=y
diff --git a/configs/duovero_defconfig b/configs/duovero_defconfig
index f52cbe7..a510294 100644
--- a/configs/duovero_defconfig
+++ b/configs/duovero_defconfig
@@ -32,6 +32,8 @@
 CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_MUSB_UDC=y
+CONFIG_USB_OMAP3=y
 CONFIG_USB_STORAGE=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/ea20_defconfig b/configs/ea20_defconfig
index eada103..abbb00a 100644
--- a/configs/ea20_defconfig
+++ b/configs/ea20_defconfig
@@ -32,5 +32,6 @@
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SYS_NS16550=y
+CONFIG_DAVINCI_SPI=y
 CONFIG_VIDEO=y
 # CONFIG_VIDEO_SW_CURSOR is not set
diff --git a/configs/etamin_defconfig b/configs/etamin_defconfig
index 8e8ef6f..608faf6 100644
--- a/configs/etamin_defconfig
+++ b/configs/etamin_defconfig
@@ -64,6 +64,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
diff --git a/configs/evb-rk3288_defconfig b/configs/evb-rk3288_defconfig
index 6024b86..c10bec2 100644
--- a/configs/evb-rk3288_defconfig
+++ b/configs/evb-rk3288_defconfig
@@ -65,6 +65,7 @@
 CONFIG_SYS_NS16550=y
 CONFIG_SYSRESET=y
 CONFIG_USB=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
diff --git a/configs/fennec-rk3288_defconfig b/configs/fennec-rk3288_defconfig
index d76e8c4..9ae1b33 100644
--- a/configs/fennec-rk3288_defconfig
+++ b/configs/fennec-rk3288_defconfig
@@ -66,6 +66,7 @@
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_DWC2=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
diff --git a/configs/firefly-rk3288_defconfig b/configs/firefly-rk3288_defconfig
index e9eb20c..3a0bd79 100644
--- a/configs/firefly-rk3288_defconfig
+++ b/configs/firefly-rk3288_defconfig
@@ -71,6 +71,7 @@
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_DWC2=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_USB_GADGET=y
diff --git a/configs/igep0032_defconfig b/configs/igep0032_defconfig
index e394aa5..b0daee1 100644
--- a/configs/igep0032_defconfig
+++ b/configs/igep0032_defconfig
@@ -39,6 +39,10 @@
 CONFIG_SMC911X_32_BIT=y
 CONFIG_SYS_NS16550=y
 CONFIG_OMAP3_SPI=y
+CONFIG_USB=y
+CONFIG_USB_MUSB_UDC=y
+CONFIG_USB_OMAP3=y
+CONFIG_TWL4030_USB=y
 CONFIG_FAT_WRITE=y
 CONFIG_BCH=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/igep00x0_defconfig b/configs/igep00x0_defconfig
index d70d4c6..22dbc70 100644
--- a/configs/igep00x0_defconfig
+++ b/configs/igep00x0_defconfig
@@ -40,6 +40,10 @@
 CONFIG_SMC911X_32_BIT=y
 CONFIG_SYS_NS16550=y
 CONFIG_OMAP3_SPI=y
+CONFIG_USB=y
+CONFIG_USB_MUSB_UDC=y
+CONFIG_USB_OMAP3=y
+CONFIG_TWL4030_USB=y
 CONFIG_FAT_WRITE=y
 CONFIG_BCH=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/k2e_evm_defconfig b/configs/k2e_evm_defconfig
index 317d4f0..e6dc298 100644
--- a/configs/k2e_evm_defconfig
+++ b/configs/k2e_evm_defconfig
@@ -44,6 +44,7 @@
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_DM_SPI=y
+CONFIG_DAVINCI_SPI=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/k2e_hs_evm_defconfig b/configs/k2e_hs_evm_defconfig
index b9be606..6c5e167 100644
--- a/configs/k2e_hs_evm_defconfig
+++ b/configs/k2e_hs_evm_defconfig
@@ -33,6 +33,7 @@
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_DM_SPI=y
+CONFIG_DAVINCI_SPI=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig
index 32353e9..6a1f8dc 100644
--- a/configs/k2g_evm_defconfig
+++ b/configs/k2g_evm_defconfig
@@ -47,6 +47,7 @@
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_DM_SPI=y
+CONFIG_DAVINCI_SPI=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/k2g_hs_evm_defconfig b/configs/k2g_hs_evm_defconfig
index 9c4530c..b4985b5 100644
--- a/configs/k2g_hs_evm_defconfig
+++ b/configs/k2g_hs_evm_defconfig
@@ -35,6 +35,7 @@
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_DM_SPI=y
+CONFIG_DAVINCI_SPI=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/k2hk_evm_defconfig b/configs/k2hk_evm_defconfig
index 7115443..1e3905f 100644
--- a/configs/k2hk_evm_defconfig
+++ b/configs/k2hk_evm_defconfig
@@ -44,6 +44,7 @@
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_DM_SPI=y
+CONFIG_DAVINCI_SPI=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/k2hk_hs_evm_defconfig b/configs/k2hk_hs_evm_defconfig
index f65185f..b4b08dd 100644
--- a/configs/k2hk_hs_evm_defconfig
+++ b/configs/k2hk_hs_evm_defconfig
@@ -33,6 +33,7 @@
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_DM_SPI=y
+CONFIG_DAVINCI_SPI=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/k2l_evm_defconfig b/configs/k2l_evm_defconfig
index d2ec226..074bed0 100644
--- a/configs/k2l_evm_defconfig
+++ b/configs/k2l_evm_defconfig
@@ -44,6 +44,7 @@
 CONFIG_DM_SERIAL=y
 CONFIG_SYS_NS16550=y
 CONFIG_DM_SPI=y
+CONFIG_DAVINCI_SPI=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/kc1_defconfig b/configs/kc1_defconfig
index 0ddf64c..e828405 100644
--- a/configs/kc1_defconfig
+++ b/configs/kc1_defconfig
@@ -38,6 +38,7 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_OMAP2PLUS=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0451
diff --git a/configs/legoev3_defconfig b/configs/legoev3_defconfig
index 209250a..d131079 100644
--- a/configs/legoev3_defconfig
+++ b/configs/legoev3_defconfig
@@ -26,5 +26,6 @@
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SYS_NS16550=y
+CONFIG_DAVINCI_SPI=y
 CONFIG_OF_LIBFDT=y
 # CONFIG_EFI_LOADER is not set
diff --git a/configs/miqi-rk3288_defconfig b/configs/miqi-rk3288_defconfig
index d0bcbd8..3a5ec2d 100644
--- a/configs/miqi-rk3288_defconfig
+++ b/configs/miqi-rk3288_defconfig
@@ -66,6 +66,7 @@
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_DWC2=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
diff --git a/configs/mx25pdk_defconfig b/configs/mx25pdk_defconfig
index 2905614..563c7ac 100644
--- a/configs/mx25pdk_defconfig
+++ b/configs/mx25pdk_defconfig
@@ -17,5 +17,6 @@
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_DOS_PARTITION=y
 CONFIG_ENV_IS_IN_MMC=y
+CONFIG_FS_EXT4=y
 CONFIG_FS_FAT=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/nokia_rx51_defconfig b/configs/nokia_rx51_defconfig
index 9057811..e93042e 100644
--- a/configs/nokia_rx51_defconfig
+++ b/configs/nokia_rx51_defconfig
@@ -26,6 +26,11 @@
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
 CONFIG_OMAP3_SPI=y
+CONFIG_USB=y
+CONFIG_USB_MUSB_HCD=y
+CONFIG_USB_MUSB_UDC=y
+CONFIG_USB_OMAP3=y
+CONFIG_TWL4030_USB=y
 CONFIG_VIDEO=y
 CONFIG_CFB_CONSOLE_ANSI=y
 # CONFIG_VGA_AS_SINGLE_DEVICE is not set
diff --git a/configs/omap3_beagle_defconfig b/configs/omap3_beagle_defconfig
index 95c8784..318c1f9 100644
--- a/configs/omap3_beagle_defconfig
+++ b/configs/omap3_beagle_defconfig
@@ -52,6 +52,8 @@
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_OMAP2PLUS=y
+CONFIG_TWL4030_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="TI"
diff --git a/configs/omap3_evm_defconfig b/configs/omap3_evm_defconfig
index d2b8d42..0ae1852 100644
--- a/configs/omap3_evm_defconfig
+++ b/configs/omap3_evm_defconfig
@@ -56,7 +56,9 @@
 CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OMAP3=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_OMAP2PLUS=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0451
diff --git a/configs/omap3_logic_defconfig b/configs/omap3_logic_defconfig
index db72e6f..3482538 100644
--- a/configs/omap3_logic_defconfig
+++ b/configs/omap3_logic_defconfig
@@ -29,6 +29,8 @@
 CONFIG_CMD_UBI=y
 CONFIG_ISO_PARTITION=y
 CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_SPL_OF_PLATDATA=y
 CONFIG_ENV_IS_IN_NAND=y
 # CONFIG_BLK is not set
 CONFIG_DM_I2C=y
@@ -48,7 +50,10 @@
 CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OMAP3=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_OMAP2PLUS=y
+CONFIG_TWL4030_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="TI"
@@ -56,3 +61,4 @@
 CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
 CONFIG_USB_ETHER=y
 CONFIG_BCH=y
+# CONFIG_SPL_OF_LIBFDT is not set
diff --git a/configs/omap3_zoom1_defconfig b/configs/omap3_zoom1_defconfig
index 6639c7e..1a915c5 100644
--- a/configs/omap3_zoom1_defconfig
+++ b/configs/omap3_zoom1_defconfig
@@ -41,5 +41,9 @@
 CONFIG_SMC911X_32_BIT=y
 CONFIG_SYS_NS16550=y
 CONFIG_OMAP3_SPI=y
+CONFIG_USB=y
+CONFIG_USB_MUSB_UDC=y
+CONFIG_USB_OMAP3=y
+CONFIG_TWL4030_USB=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/omap4_panda_defconfig b/configs/omap4_panda_defconfig
index 0faea77..aa0c36e 100644
--- a/configs/omap4_panda_defconfig
+++ b/configs/omap4_panda_defconfig
@@ -31,6 +31,8 @@
 CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_MUSB_UDC=y
+CONFIG_USB_OMAP3=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/omap4_sdp4430_defconfig b/configs/omap4_sdp4430_defconfig
index b7ba1f3..ac49571 100644
--- a/configs/omap4_sdp4430_defconfig
+++ b/configs/omap4_sdp4430_defconfig
@@ -27,5 +27,8 @@
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
 CONFIG_OMAP3_SPI=y
+CONFIG_USB=y
+CONFIG_USB_MUSB_UDC=y
+CONFIG_USB_OMAP3=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/omapl138_lcdk_defconfig b/configs/omapl138_lcdk_defconfig
index 0d4506e..944be2b 100644
--- a/configs/omapl138_lcdk_defconfig
+++ b/configs/omapl138_lcdk_defconfig
@@ -36,4 +36,5 @@
 CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SYS_NS16550=y
+CONFIG_DAVINCI_SPI=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/pcm051_rev1_defconfig b/configs/pcm051_rev1_defconfig
index 273fc30..c16711a 100644
--- a/configs/pcm051_rev1_defconfig
+++ b/configs/pcm051_rev1_defconfig
@@ -58,6 +58,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ETHER=y
diff --git a/configs/pcm051_rev3_defconfig b/configs/pcm051_rev3_defconfig
index f1ddaa6..a8fe7af 100644
--- a/configs/pcm051_rev3_defconfig
+++ b/configs/pcm051_rev3_defconfig
@@ -58,6 +58,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ETHER=y
diff --git a/configs/pengwyn_defconfig b/configs/pengwyn_defconfig
index 4bb6245..78a6b7d 100644
--- a/configs/pengwyn_defconfig
+++ b/configs/pengwyn_defconfig
@@ -62,6 +62,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_FAT_WRITE=y
diff --git a/configs/phycore-rk3288_defconfig b/configs/phycore-rk3288_defconfig
index aea47c5..969b0e6 100644
--- a/configs/phycore-rk3288_defconfig
+++ b/configs/phycore-rk3288_defconfig
@@ -69,6 +69,7 @@
 CONFIG_SYS_NS16550=y
 CONFIG_SYSRESET=y
 CONFIG_USB=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
diff --git a/configs/poplar_defconfig b/configs/poplar_defconfig
index 8f6ac2d..71ff228 100644
--- a/configs/poplar_defconfig
+++ b/configs/poplar_defconfig
@@ -17,4 +17,5 @@
 CONFIG_USB_STORAGE=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
+CONFIG_FAT_WRITE=y
 CONFIG_LIB_RAND=y
diff --git a/configs/popmetal-rk3288_defconfig b/configs/popmetal-rk3288_defconfig
index 6b860bb..94f4979 100644
--- a/configs/popmetal-rk3288_defconfig
+++ b/configs/popmetal-rk3288_defconfig
@@ -66,6 +66,7 @@
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_DWC2=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
diff --git a/configs/pxm2_defconfig b/configs/pxm2_defconfig
index 0ec1591..f682300 100644
--- a/configs/pxm2_defconfig
+++ b/configs/pxm2_defconfig
@@ -67,6 +67,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
diff --git a/configs/rastaban_defconfig b/configs/rastaban_defconfig
index 5ef1740..c714b07 100644
--- a/configs/rastaban_defconfig
+++ b/configs/rastaban_defconfig
@@ -64,6 +64,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
diff --git a/configs/rock2_defconfig b/configs/rock2_defconfig
index 43dce46..0a95e6a 100644
--- a/configs/rock2_defconfig
+++ b/configs/rock2_defconfig
@@ -66,6 +66,7 @@
 CONFIG_SYS_NS16550=y
 CONFIG_SYSRESET=y
 CONFIG_USB=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
diff --git a/configs/rock_defconfig b/configs/rock_defconfig
index b174e4b..483f64b 100644
--- a/configs/rock_defconfig
+++ b/configs/rock_defconfig
@@ -47,6 +47,8 @@
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_SPL_TINY_MEMSET=y
 CONFIG_TPL_TINY_MEMSET=y
 CONFIG_CMD_DHRYSTONE=y
diff --git a/configs/rut_defconfig b/configs/rut_defconfig
index 1711fc7..2269747 100644
--- a/configs/rut_defconfig
+++ b/configs/rut_defconfig
@@ -68,6 +68,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
diff --git a/configs/sniper_defconfig b/configs/sniper_defconfig
index a8a592f..a3bae56 100644
--- a/configs/sniper_defconfig
+++ b/configs/sniper_defconfig
@@ -39,6 +39,8 @@
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_OMAP2PLUS=y
+CONFIG_TWL4030_USB=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
 CONFIG_USB_GADGET_VENDOR_NUM=0x0451
diff --git a/configs/thuban_defconfig b/configs/thuban_defconfig
index 2575c00..df76145 100644
--- a/configs/thuban_defconfig
+++ b/configs/thuban_defconfig
@@ -64,6 +64,7 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
+CONFIG_USB_MUSB_DSPS=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Siemens AG"
diff --git a/configs/tinker-rk3288_defconfig b/configs/tinker-rk3288_defconfig
index c79dffd..a0df3fd 100644
--- a/configs/tinker-rk3288_defconfig
+++ b/configs/tinker-rk3288_defconfig
@@ -69,6 +69,7 @@
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB_DWC2=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
diff --git a/configs/vyasa-rk3288_defconfig b/configs/vyasa-rk3288_defconfig
index 30ad478..5d8fa22 100644
--- a/configs/vyasa-rk3288_defconfig
+++ b/configs/vyasa-rk3288_defconfig
@@ -63,6 +63,7 @@
 CONFIG_SYS_NS16550=y
 CONFIG_SYSRESET=y
 CONFIG_USB=y
+CONFIG_ROCKCHIP_USB2_PHY=y
 CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_KEYBOARD=y
diff --git a/doc/README.ext4 b/doc/README.ext4
index 2b0eab5..8ecd21e 100644
--- a/doc/README.ext4
+++ b/doc/README.ext4
@@ -2,10 +2,10 @@
 mode or in read-write mode.
 
 First, to enable support for both ext4 (and, automatically, ext2 as well),
-but without selecting the corresponding commands, use one of:
+but without selecting the corresponding commands, enable one of the following:
 
-  #define CONFIG_FS_EXT4	(for read-only)
-  #define CONFIG_EXT4_WRITE	(for read-write)
+  CONFIG_FS_EXT4	(for read-only)
+  CONFIG_EXT4_WRITE	(for read-write)
 
 Next, to select the ext2-related commands:
 
@@ -20,22 +20,22 @@
 
 use one or both of:
 
-  #define CONFIG_CMD_EXT2
-  #define CONFIG_CMD_EXT4
+  CONFIG_CMD_EXT2
+  CONFIG_CMD_EXT4
 
-Selecting either of the above automatically defines CONFIG_FS_EXT4 if it
-wasn't defined already.
+Selecting either of the above automatically selects CONFIG_FS_EXT4 if it
+wasn't enabled already.
 
-In addition, to get the write access command "ext4write", use:
+In addition, to get the write access command "ext4write", enable:
 
-  #define CONFIG_CMD_EXT4_WRITE
+  CONFIG_CMD_EXT4_WRITE
 
-which automatically defines CONFIG_EXT4_WRITE if it wasn't defined
+which automatically selects CONFIG_EXT4_WRITE if it wasn't defined
 already.
 
 Also relevant are the generic filesystem commands, selected by:
 
-  #define CONFIG_CMD_FS_GENERIC
+  CONFIG_CMD_FS_GENERIC
 
 This does not automatically enable EXT4 support for you, you still need
 to do that yourself.
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
index 010ed32..bfda221 100644
--- a/drivers/block/blk-uclass.c
+++ b/drivers/block/blk-uclass.c
@@ -24,6 +24,7 @@
 	[IF_TYPE_HOST]		= "host",
 	[IF_TYPE_SYSTEMACE]	= "ace",
 	[IF_TYPE_NVME]		= "nvme",
+	[IF_TYPE_EFI]		= "efi",
 };
 
 static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
@@ -36,8 +37,9 @@
 	[IF_TYPE_SD]		= UCLASS_INVALID,
 	[IF_TYPE_SATA]		= UCLASS_AHCI,
 	[IF_TYPE_HOST]		= UCLASS_ROOT,
-	[IF_TYPE_NVME]		= UCLASS_NVME,
 	[IF_TYPE_SYSTEMACE]	= UCLASS_INVALID,
+	[IF_TYPE_NVME]		= UCLASS_NVME,
+	[IF_TYPE_EFI]		= UCLASS_EFI,
 };
 
 static enum if_type if_typename_to_iftype(const char *if_typename)
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 876c2b8..dab106a 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -6,21 +6,21 @@
 #
 
 obj-$(CONFIG_$(SPL_TPL_)CLK) += clk-uclass.o clk_fixed_rate.o
-obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
-obj-$(CONFIG_SANDBOX) += clk_sandbox.o
-obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o
-obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
-obj-$(CONFIG_CLK_RENESAS) += renesas/
-obj-$(CONFIG_CLK_ZYNQ) += clk_zynq.o
-obj-$(CONFIG_CLK_ZYNQMP) += clk_zynqmp.o
 
 obj-y += tegra/
-obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
-obj-$(CONFIG_CLK_EXYNOS) += exynos/
+obj-$(CONFIG_ARCH_ASPEED) += aspeed/
+obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
 obj-$(CONFIG_CLK_AT91) += at91/
 obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o
 obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
+obj-$(CONFIG_CLK_EXYNOS) += exynos/
 obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o
-obj-$(CONFIG_ARCH_ASPEED) += aspeed/
+obj-$(CONFIG_CLK_RENESAS) += renesas/
 obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o
+obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
+obj-$(CONFIG_CLK_ZYNQ) += clk_zynq.o
+obj-$(CONFIG_CLK_ZYNQMP) += clk_zynqmp.o
+obj-$(CONFIG_MACH_PIC32) += clk_pic32.o
+obj-$(CONFIG_SANDBOX) += clk_sandbox.o
+obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o
 obj-$(CONFIG_STM32H7) += clk_stm32h7.o
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 83ba133..fbea720 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -13,11 +13,9 @@
 #include <dt-structs.h>
 #include <errno.h>
 
-DECLARE_GLOBAL_DATA_PTR;
-
-static inline struct clk_ops *clk_dev_ops(struct udevice *dev)
+static inline const struct clk_ops *clk_dev_ops(struct udevice *dev)
 {
-	return (struct clk_ops *)dev->driver->ops;
+	return (const struct clk_ops *)dev->driver->ops;
 }
 
 #if CONFIG_IS_ENABLED(OF_CONTROL)
@@ -60,7 +58,7 @@
 	int ret;
 	struct ofnode_phandle_args args;
 	struct udevice *dev_clk;
-	struct clk_ops *ops;
+	const struct clk_ops *ops;
 
 	debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk);
 
@@ -68,7 +66,7 @@
 	clk->dev = NULL;
 
 	ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0,
-					  index, &args);
+					 index, &args);
 	if (ret) {
 		debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
 		      __func__, ret);
@@ -142,7 +140,7 @@
 
 int clk_request(struct udevice *dev, struct clk *clk)
 {
-	struct clk_ops *ops = clk_dev_ops(dev);
+	const struct clk_ops *ops = clk_dev_ops(dev);
 
 	debug("%s(dev=%p, clk=%p)\n", __func__, dev, clk);
 
@@ -156,7 +154,7 @@
 
 int clk_free(struct clk *clk)
 {
-	struct clk_ops *ops = clk_dev_ops(clk->dev);
+	const struct clk_ops *ops = clk_dev_ops(clk->dev);
 
 	debug("%s(clk=%p)\n", __func__, clk);
 
@@ -168,7 +166,7 @@
 
 ulong clk_get_rate(struct clk *clk)
 {
-	struct clk_ops *ops = clk_dev_ops(clk->dev);
+	const struct clk_ops *ops = clk_dev_ops(clk->dev);
 
 	debug("%s(clk=%p)\n", __func__, clk);
 
@@ -180,7 +178,7 @@
 
 ulong clk_set_rate(struct clk *clk, ulong rate)
 {
-	struct clk_ops *ops = clk_dev_ops(clk->dev);
+	const struct clk_ops *ops = clk_dev_ops(clk->dev);
 
 	debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
 
@@ -192,7 +190,7 @@
 
 int clk_enable(struct clk *clk)
 {
-	struct clk_ops *ops = clk_dev_ops(clk->dev);
+	const struct clk_ops *ops = clk_dev_ops(clk->dev);
 
 	debug("%s(clk=%p)\n", __func__, clk);
 
@@ -204,7 +202,7 @@
 
 int clk_disable(struct clk *clk)
 {
-	struct clk_ops *ops = clk_dev_ops(clk->dev);
+	const struct clk_ops *ops = clk_dev_ops(clk->dev);
 
 	debug("%s(clk=%p)\n", __func__, clk);
 
diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c
index 63565b6..c9a9f0a 100644
--- a/drivers/clk/clk_fixed_rate.c
+++ b/drivers/clk/clk_fixed_rate.c
@@ -8,8 +8,6 @@
 #include <clk-uclass.h>
 #include <dm.h>
 
-DECLARE_GLOBAL_DATA_PTR;
-
 struct clk_fixed_rate {
 	unsigned long fixed_rate;
 };
@@ -31,8 +29,8 @@
 static int clk_fixed_rate_ofdata_to_platdata(struct udevice *dev)
 {
 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
-	to_clk_fixed_rate(dev)->fixed_rate = dev_read_u32_default(dev,
-							"clock-frequency", 0);
+	to_clk_fixed_rate(dev)->fixed_rate =
+		dev_read_u32_default(dev, "clock-frequency", 0);
 #endif
 
 	return 0;
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 9a46a7b..144ac2a 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -17,6 +17,7 @@
 #include <dm/device.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
+#include <dm/of_access.h>
 #include <dm/pinctrl.h>
 #include <dm/platdata.h>
 #include <dm/read.h>
@@ -703,8 +704,12 @@
 bool device_is_compatible(struct udevice *dev, const char *compat)
 {
 	const void *fdt = gd->fdt_blob;
+	ofnode node = dev_ofnode(dev);
 
-	return !fdt_node_check_compatible(fdt, dev_of_offset(dev), compat);
+	if (ofnode_is_np(node))
+		return of_device_is_compatible(ofnode_to_np(node), compat, NULL, NULL);
+	else
+		return !fdt_node_check_compatible(fdt, ofnode_to_offset(node), compat);
 }
 
 bool of_machine_is_compatible(const char *compat)
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 0030ab9..98f4b53 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -205,8 +205,13 @@
 					  &flags);
 		if (!prop_val)
 			return FDT_ADDR_T_NONE;
-		na = of_n_addr_cells(ofnode_to_np(node));
-		return of_read_number(prop_val, na);
+
+		if (IS_ENABLED(CONFIG_OF_TRANSLATE)) {
+			return of_translate_address(ofnode_to_np(node), prop_val);
+		} else {
+			na = of_n_addr_cells(ofnode_to_np(node));
+			return of_read_number(prop_val, na);
+		}
 	} else {
 		return fdt_get_base_address(gd->fdt_blob,
 					    ofnode_to_offset(node));
@@ -296,7 +301,8 @@
 		int ret;
 
 		ret = of_parse_phandle_with_args(ofnode_to_np(node),
-				list_name, cells_name, index, &args);
+						 list_name, cells_name, index,
+						 &args);
 		if (ret)
 			return ret;
 		ofnode_from_of_phandle_args(&args, out_args);
@@ -305,8 +311,9 @@
 		int ret;
 
 		ret = fdtdec_parse_phandle_with_args(gd->fdt_blob,
-				ofnode_to_offset(node), list_name, cells_name,
-				cell_count, index, &args);
+						     ofnode_to_offset(node),
+						     list_name, cells_name,
+						     cell_count, index, &args);
 		if (ret)
 			return ret;
 		ofnode_from_fdtdec_phandle_args(&args, out_args);
@@ -534,10 +541,10 @@
 				addr->phys_mid = fdt32_to_cpu(cell[1]);
 				addr->phys_lo = fdt32_to_cpu(cell[1]);
 				break;
-			} else {
-				cell += (FDT_PCI_ADDR_CELLS +
-					 FDT_PCI_SIZE_CELLS);
 			}
+
+			cell += (FDT_PCI_ADDR_CELLS +
+				 FDT_PCI_SIZE_CELLS);
 		}
 
 		if (i == num) {
@@ -546,10 +553,10 @@
 		}
 
 		return 0;
-	} else {
-		ret = -EINVAL;
 	}
 
+	ret = -EINVAL;
+
 fail:
 	debug("(not found)\n");
 	return ret;
@@ -642,3 +649,11 @@
 
 	return ofnode_read_resource(node, index, res);
 }
+
+u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr)
+{
+	if (ofnode_is_np(node))
+		return of_translate_address(ofnode_to_np(node), in_addr);
+	else
+		return fdt_translate_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
+}
diff --git a/drivers/core/read.c b/drivers/core/read.c
index 758d400..601d132 100644
--- a/drivers/core/read.c
+++ b/drivers/core/read.c
@@ -71,7 +71,7 @@
 }
 
 fdt_addr_t dev_read_addr_size(struct udevice *dev, const char *property,
-				fdt_size_t *sizep)
+			      fdt_size_t *sizep)
 {
 	return ofnode_get_addr_size(dev_ofnode(dev), property, sizep);
 }
@@ -82,7 +82,7 @@
 }
 
 int dev_read_stringlist_search(struct udevice *dev, const char *property,
-			  const char *string)
+			       const char *string)
 {
 	return ofnode_stringlist_search(dev_ofnode(dev), property, string);
 }
@@ -99,9 +99,8 @@
 }
 
 int dev_read_phandle_with_args(struct udevice *dev, const char *list_name,
-				const char *cells_name, int cell_count,
-				int index,
-				struct ofnode_phandle_args *out_args)
+			       const char *cells_name, int cell_count,
+			       int index, struct ofnode_phandle_args *out_args)
 {
 	return ofnode_parse_phandle_with_args(dev_ofnode(dev), list_name,
 					      cells_name, cell_count, index,
@@ -201,3 +200,8 @@
 {
 	return ofnode_read_resource_byname(dev_ofnode(dev), name, res);
 }
+
+u64 dev_translate_address(struct udevice *dev, const fdt32_t *in_addr)
+{
+	return ofnode_translate_address(dev_ofnode(dev), in_addr);
+}
diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c
index a63eba3..9373a39 100644
--- a/drivers/crypto/fsl/fsl_hash.c
+++ b/drivers/crypto/fsl/fsl_hash.c
@@ -7,6 +7,7 @@
 
 #include <common.h>
 #include <malloc.h>
+#include <memalign.h>
 #include "jobdesc.h"
 #include "desc.h"
 #include "jr.h"
@@ -163,20 +164,37 @@
 {
 	int ret = 0;
 	uint32_t *desc;
+	unsigned int size;
 
-	desc = malloc(sizeof(int) * MAX_CAAM_DESCSIZE);
+	desc = malloc_cache_aligned(sizeof(int) * MAX_CAAM_DESCSIZE);
 	if (!desc) {
 		debug("Not enough memory for descriptor allocation\n");
 		return -ENOMEM;
 	}
 
+	if (!IS_ALIGNED((uintptr_t)pbuf, ARCH_DMA_MINALIGN) ||
+	    !IS_ALIGNED((uintptr_t)pout, ARCH_DMA_MINALIGN)) {
+		puts("Error: Address arguments are not aligned\n");
+		return -EINVAL;
+	}
+
+	size = ALIGN(buf_len, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)pbuf, (unsigned long)pbuf + size);
+
 	inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout,
 				  driver_hash[algo].alg_type,
 				  driver_hash[algo].digestsize,
 				  0);
 
+	size = ALIGN(sizeof(int) * MAX_CAAM_DESCSIZE, ARCH_DMA_MINALIGN);
+	flush_dcache_range((unsigned long)desc, (unsigned long)desc + size);
+
 	ret = run_descriptor_jr(desc);
 
+	size = ALIGN(driver_hash[algo].digestsize, ARCH_DMA_MINALIGN);
+	invalidate_dcache_range((unsigned long)pout,
+				(unsigned long)pout + size);
+
 	free(desc);
 	return ret;
 }
diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c
index 058c9b9..b3a27ec 100644
--- a/drivers/ddr/fsl/fsl_ddr_gen4.c
+++ b/drivers/ddr/fsl/fsl_ddr_gen4.c
@@ -95,6 +95,9 @@
 	if (step == 2)
 		goto step2;
 
+	/* Set cdr1 first in case 0.9v VDD is enabled for some SoCs*/
+	ddr_out32(&ddr->ddr_cdr1, regs->ddr_cdr1);
+
 	if (regs->ddr_eor)
 		ddr_out32(&ddr->eor, regs->ddr_eor);
 
@@ -183,7 +186,6 @@
 	ddr_out32(&ddr->ddr_sdram_rcw_4, regs->ddr_sdram_rcw_4);
 	ddr_out32(&ddr->ddr_sdram_rcw_5, regs->ddr_sdram_rcw_5);
 	ddr_out32(&ddr->ddr_sdram_rcw_6, regs->ddr_sdram_rcw_6);
-	ddr_out32(&ddr->ddr_cdr1, regs->ddr_cdr1);
 #ifdef CONFIG_DEEP_SLEEP
 	if (is_warm_boot()) {
 		ddr_out32(&ddr->sdram_cfg_2,
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 494639f..5e31ee4 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -217,6 +217,12 @@
 	  used to access the SPI flash on AE3XX and AE250 platforms embedding
 	  this Andestech IP core.
 
+config DAVINCI_SPI
+	bool "Davinci & Keystone SPI driver"
+	depends on ARCH_DAVINCI || ARCH_KEYSTONE
+	help
+	  Enable the Davinci SPI driver
+
 config TI_QSPI
 	bool "TI QSPI driver"
 	help
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index e7658b4..7de4105 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -51,10 +51,14 @@
 
 source "drivers/usb/dwc3/Kconfig"
 
+source "drivers/usb/musb/Kconfig"
+
 source "drivers/usb/musb-new/Kconfig"
 
 source "drivers/usb/emul/Kconfig"
 
+source "drivers/usb/phy/Kconfig"
+
 source "drivers/usb/ulpi/Kconfig"
 
 comment "USB peripherals"
diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig
index caba42c..ea5bae2 100644
--- a/drivers/usb/musb-new/Kconfig
+++ b/drivers/usb/musb-new/Kconfig
@@ -23,6 +23,16 @@
 	  speed USB controller based on the Mentor Graphics
 	  silicon IP.
 
+config USB_MUSB_OMAP2PLUS
+	tristate "OMAP2430 and onwards"
+	depends on ARCH_OMAP2PLUS
+
+config USB_MUSB_AM35X
+	bool "AM35x"
+
+config USB_MUSB_DSPS
+	bool "TI DSPS platforms"
+
 if USB_MUSB_HOST || USB_MUSB_GADGET
 
 config USB_MUSB_PIC32
@@ -41,3 +51,10 @@
 	used on almost all sunxi boards.
 
 endif
+
+config USB_MUSB_PIO_ONLY
+	bool "Disable DMA (always use PIO)"
+	default y if USB_MUSB_AM35X || USB_MUSB_PIC32 || USB_MUSB_OMAP2PLUS || USB_MUSB_DSPS || USB_MUSB_SUNXI
+	help
+	  All data is copied between memory and FIFO by the CPU.
+	  DMA controllers are ignored.
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
new file mode 100644
index 0000000..4e2be37
--- /dev/null
+++ b/drivers/usb/musb/Kconfig
@@ -0,0 +1,29 @@
+#
+# (C) Copyright 2017
+# Adam Ford, Logic PD, aford173@gmail.com
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+comment "Legacy MUSB Support"
+
+config USB_MUSB_HCD
+	bool "Legacy MUSB Host Controller"
+
+config USB_MUSB_UDC
+	bool "Legacy USB Device Controller"
+
+config USB_DAVINCI
+	bool "Legacy MUSB DaVinci"
+	
+config USB_OMAP3
+	bool "Legacy MUSB OMAP3 / OMAP4"
+	depends on ARCH_OMAP2PLUS
+
+config USB_DA8XX
+	bool "Legacy MUSB DA8xx/OMAP-L1x"
+	depends on ARCH_DAVINCI
+
+config USB_AM35X
+	bool"Legacy MUSB AM35x"
+	depends on ARCH_OMAP2PLUS && !USB_OMAP3
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
new file mode 100644
index 0000000..bcc67a0
--- /dev/null
+++ b/drivers/usb/phy/Kconfig
@@ -0,0 +1,17 @@
+#
+# (C) Copyright 2017
+# Adam Ford, Logic PD, aford173@gmail.com
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+comment "USB Phy"
+
+config TWL4030_USB
+	bool "TWL4030 PHY"
+
+config OMAP_USB_PHY
+	bool "OMAP PHY"
+
+config ROCKCHIP_USB2_PHY
+	bool "Rockchip USB2 PHY"
diff --git a/env/Kconfig b/env/Kconfig
index 692f863..a243707 100644
--- a/env/Kconfig
+++ b/env/Kconfig
@@ -74,13 +74,11 @@
 config ENV_IS_IN_FAT
 	bool "Environment is in a FAT filesystem"
 	depends on !CHAIN_OF_TRUST
+	select FS_FAT
 	select FAT_WRITE
 	help
 	  Define this if you want to use the FAT file system for the environment.
 
-	  - CONFIG_FAT_WRITE:
-	  This must be enabled. Otherwise it cannot save the environment file.
-
 config ENV_IS_IN_EXT4
 	bool "Environment is in a EXT4 filesystem"
 	depends on !CHAIN_OF_TRUST
diff --git a/examples/api/Makefile b/examples/api/Makefile
index 8995272..9068727 100644
--- a/examples/api/Makefile
+++ b/examples/api/Makefile
@@ -4,6 +4,9 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+# Provide symbol API_BUILD to signal that the API example is being built.
+KBUILD_CPPFLAGS += -DAPI_BUILD
+
 ifeq ($(ARCH),powerpc)
 LOAD_ADDR = 0x40000
 endif
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index e69de29..1a913d2 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -0,0 +1,13 @@
+config FS_EXT4
+	bool "Enable ext4 filesystem support"
+	help
+	  This provides support for reading images from the ext4 filesystem.
+	  ext4 is a widely used general-purpose filesystem for Linux.
+	  You can also enable CMD_EXT4 to get access to ext4 commands.
+
+config EXT4_WRITE
+	bool "Enable ext4 filesystem write support"
+	depends on FS_EXT4
+	help
+	  This provides support for creating and writing new files to an
+	  existing ext4 filesystem partition.
diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig
index e7978aa..9bb11ea 100644
--- a/fs/fat/Kconfig
+++ b/fs/fat/Kconfig
@@ -14,7 +14,7 @@
 	  existing FAT filesystem partition.
 
 config FS_FAT_MAX_CLUSTSIZE
-	int "Set maximum possible clusersize"
+	int "Set maximum possible clustersize"
 	default 65536
 	depends on FS_FAT
 	help
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 1283818..dd7888c 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -22,12 +22,6 @@
 #include <linux/compiler.h>
 #include <linux/ctype.h>
 
-#ifdef CONFIG_SUPPORT_VFAT
-static const int vfat_enabled = 1;
-#else
-static const int vfat_enabled = 0;
-#endif
-
 /*
  * Convert a string to lowercase.  Converts at most 'len' characters,
  * 'len' may be larger than the length of 'str' if 'str' is NULL
@@ -605,9 +599,6 @@
 		return -1;
 	}
 
-	if (vfat_enabled)
-		debug("VFAT Support enabled\n");
-
 	debug("FAT%d, fat_sect: %d, fatlength: %d\n",
 	       mydata->fatsize, mydata->fat_sect, mydata->fatlength);
 	debug("Rootdir begins at cluster: %d, sector: %d, offset: %x\n"
@@ -857,8 +848,7 @@
 			continue;
 
 		if (dent->attr & ATTR_VOLUME) {
-			if (vfat_enabled &&
-			    (dent->attr & ATTR_VFAT) == ATTR_VFAT &&
+			if ((dent->attr & ATTR_VFAT) == ATTR_VFAT &&
 			    (dent->name[0] & LAST_LONG_ENTRY_MASK)) {
 				dent = extract_vfat_name(itr);
 				if (!dent)
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index cd65192..2b753df 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -819,8 +819,7 @@
 				continue;
 			}
 			if ((dentptr->attr & ATTR_VOLUME)) {
-				if (vfat_enabled &&
-				    (dentptr->attr & ATTR_VFAT) &&
+				if ((dentptr->attr & ATTR_VFAT) &&
 				    (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
 					get_long_file_name(mydata, curclust,
 						     get_dentfromdir_block,
diff --git a/include/blk.h b/include/blk.h
index 41b4d7e..69b5a98 100644
--- a/include/blk.h
+++ b/include/blk.h
@@ -34,6 +34,7 @@
 	IF_TYPE_HOST,
 	IF_TYPE_SYSTEMACE,
 	IF_TYPE_NVME,
+	IF_TYPE_EFI,
 
 	IF_TYPE_COUNT,			/* Number of interface types */
 };
diff --git a/include/common.h b/include/common.h
index 4362000..0fe9439 100644
--- a/include/common.h
+++ b/include/common.h
@@ -364,6 +364,9 @@
 
 int	misc_init_f   (void);
 int	misc_init_r   (void);
+#if defined(CONFIG_VID)
+int	init_func_vid(void);
+#endif
 
 /* common/exports.c */
 void	jumptable_init(void);
diff --git a/include/config_fallbacks.h b/include/config_fallbacks.h
index 2c4d43d..9695ee7 100644
--- a/include/config_fallbacks.h
+++ b/include/config_fallbacks.h
@@ -29,19 +29,6 @@
 #define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
 #endif
 
-#if defined(CONFIG_ENV_IS_IN_FAT) && !defined(CONFIG_FS_FAT)
-#define CONFIG_FS_FAT
-#endif
-
-#if (defined(CONFIG_CMD_EXT4) || defined(CONFIG_CMD_EXT2)) && \
-						!defined(CONFIG_FS_EXT4)
-#define CONFIG_FS_EXT4
-#endif
-
-#if defined(CONFIG_CMD_EXT4_WRITE) && !defined(CONFIG_EXT4_WRITE)
-#define CONFIG_EXT4_WRITE
-#endif
-
 /* Rather than repeat this expression each time, add a define for it */
 #if defined(CONFIG_IDE) || \
 	defined(CONFIG_SATA) || \
@@ -52,6 +39,7 @@
 	defined(CONFIG_MMC) || \
 	defined(CONFIG_NVME) || \
 	defined(CONFIG_SYSTEMACE) || \
+	(defined(CONFIG_EFI_LOADER) && !defined(CONFIG_SPL_BUILD)) || \
 	defined(CONFIG_SANDBOX)
 #define HAVE_BLOCK_DEVICE
 #endif
diff --git a/include/configs/MPC8349ITX.h b/include/configs/MPC8349ITX.h
index c88aa95..e2807a6 100644
--- a/include/configs/MPC8349ITX.h
+++ b/include/configs/MPC8349ITX.h
@@ -470,14 +470,6 @@
 #define CONFIG_BOOTP_GATEWAY
 #define CONFIG_BOOTP_HOSTNAME
 
-#if defined(CONFIG_COMPACT_FLASH) || defined(CONFIG_SATA_SIL3114) \
-				|| defined(CONFIG_USB_STORAGE)
-	#define CONFIG_SUPPORT_VFAT
-#endif
-
-#if defined(CONFIG_SATA_SIL3114) || defined(CONFIG_USB_STORAGE)
-#endif
-
 /* Watchdog */
 #undef CONFIG_WATCHDOG		/* watchdog disabled */
 
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index 856c546..31ab503 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -228,8 +228,6 @@
  * add mass storage support and for gadget we add both RNDIS ethernet
  * and DFU.
  */
-#define CONFIG_USB_MUSB_DSPS
-#define CONFIG_USB_MUSB_PIO_ONLY
 #define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
 #define CONFIG_AM335X_USB0
 #define CONFIG_AM335X_USB0_MODE	MUSB_PERIPHERAL
diff --git a/include/configs/am335x_shc.h b/include/configs/am335x_shc.h
index 32439f5..e2d329a 100644
--- a/include/configs/am335x_shc.h
+++ b/include/configs/am335x_shc.h
@@ -17,8 +17,6 @@
 
 /* settings we don;t want on this board */
 #undef CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC
-#undef CONFIG_CMD_EXT4
-#undef CONFIG_CMD_EXT4_WRITE
 #undef CONFIG_CMD_SPI
 
 #define CONFIG_CMD_CACHE
diff --git a/include/configs/am3517_crane.h b/include/configs/am3517_crane.h
index 400a06e..16212ef 100644
--- a/include/configs/am3517_crane.h
+++ b/include/configs/am3517_crane.h
@@ -72,8 +72,6 @@
  * Enable CONFIG_USB_MUSB_HCD for Host functionalities MSC, keyboard
  * Enable CONFIG_USB_MUSB_UDC for Device functionalities.
  */
-#define CONFIG_USB_AM35X		1
-#define CONFIG_USB_MUSB_HCD			1
 
 #ifdef CONFIG_USB_AM35X
 
diff --git a/include/configs/am3517_evm.h b/include/configs/am3517_evm.h
index 33ed85e..ac5070d 100644
--- a/include/configs/am3517_evm.h
+++ b/include/configs/am3517_evm.h
@@ -42,8 +42,6 @@
  * Enable CONFIG_USB_MUSB_HOST for Host functionalities MSC, keyboard
  * Enable CONFIG_USB_MUSB_GADGET for Device functionalities.
  */
-#define CONFIG_USB_MUSB_AM35X
-#define CONFIG_USB_MUSB_PIO_ONLY
 
 #ifdef CONFIG_USB_MUSB_AM35X
 
diff --git a/include/configs/am43xx_evm.h b/include/configs/am43xx_evm.h
index 302181b..77f8e76 100644
--- a/include/configs/am43xx_evm.h
+++ b/include/configs/am43xx_evm.h
@@ -77,7 +77,6 @@
 #define CONFIG_SYS_USB_FAT_BOOT_PARTITION		1
 #define CONFIG_USB_XHCI_OMAP
 
-#define CONFIG_OMAP_USB_PHY
 #define CONFIG_AM437X_USB2PHY2_HOST
 #endif
 
diff --git a/include/configs/am57xx_evm.h b/include/configs/am57xx_evm.h
index 28618a5..7546b3f 100644
--- a/include/configs/am57xx_evm.h
+++ b/include/configs/am57xx_evm.h
@@ -92,7 +92,6 @@
 /* USB xHCI HOST */
 #define CONFIG_USB_XHCI_OMAP
 
-#define CONFIG_OMAP_USB_PHY
 #define CONFIG_OMAP_USB3PHY1_HOST
 
 /* SATA */
diff --git a/include/configs/apf27.h b/include/configs/apf27.h
index 8294101..24afc84 100644
--- a/include/configs/apf27.h
+++ b/include/configs/apf27.h
@@ -204,7 +204,6 @@
  */
 #define CONFIG_MTD_DEVICE
 #define CONFIG_MTD_PARTITIONS
-#define CONFIG_SUPPORT_VFAT
 
 /*
  * Ethernet (on SOC imx FEC)
diff --git a/include/configs/baltos.h b/include/configs/baltos.h
index 3fc9e2f..939ee3b 100644
--- a/include/configs/baltos.h
+++ b/include/configs/baltos.h
@@ -272,8 +272,6 @@
  * add mass storage support and for gadget we add both RNDIS ethernet
  * and DFU.
  */
-#define CONFIG_USB_MUSB_DSPS
-#define CONFIG_USB_MUSB_PIO_ONLY
 #define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
 #define CONFIG_AM335X_USB0
 #define CONFIG_AM335X_USB0_MODE	MUSB_HOST
diff --git a/include/configs/bav335x.h b/include/configs/bav335x.h
index 8917bbe..d084af8 100644
--- a/include/configs/bav335x.h
+++ b/include/configs/bav335x.h
@@ -394,8 +394,6 @@
  * add mass storage support and for gadget we add both RNDIS ethernet
  * and DFU.
  */
-#define CONFIG_USB_MUSB_DSPS
-#define CONFIG_USB_MUSB_PIO_ONLY
 #define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
 #define CONFIG_AM335X_USB0
 #define CONFIG_AM335X_USB0_MODE	MUSB_PERIPHERAL
diff --git a/include/configs/brppt1.h b/include/configs/brppt1.h
index 2dadcae..a8022b8 100644
--- a/include/configs/brppt1.h
+++ b/include/configs/brppt1.h
@@ -210,8 +210,6 @@
 #endif /* CONFIG_NAND */
 
 /* USB configuration */
-#define CONFIG_USB_MUSB_DSPS
-#define CONFIG_USB_MUSB_PIO_ONLY
 #define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
 #define CONFIG_AM335X_USB0
 #define CONFIG_AM335X_USB0_MODE	MUSB_HOST
@@ -245,13 +243,5 @@
 #else
 #error "no storage for Environment defined!"
 #endif
-/*
- * Common filesystems support.  When we have removable storage we
- * enabled a number of useful commands and support.
- */
-#if defined(CONFIG_MMC) || defined(CONFIG_USB_STORAGE)
-#define CONFIG_FS_EXT4
-#define CONFIG_EXT4_WRITE
-#endif /* CONFIG_MMC, ... */
 
 #endif	/* ! __CONFIG_BRPPT1_H__ */
diff --git a/include/configs/brxre1.h b/include/configs/brxre1.h
index 8f92d7a..09042d4 100644
--- a/include/configs/brxre1.h
+++ b/include/configs/brxre1.h
@@ -80,8 +80,6 @@
 #define CONFIG_INITRD_TAG
 
 /* USB configuration */
-#define CONFIG_USB_MUSB_DSPS
-#define CONFIG_USB_MUSB_PIO_ONLY
 #define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
 #define CONFIG_AM335X_USB0
 #define CONFIG_AM335X_USB0_MODE	MUSB_HOST
diff --git a/include/configs/calimain.h b/include/configs/calimain.h
index 7686592..7dfc1fa 100644
--- a/include/configs/calimain.h
+++ b/include/configs/calimain.h
@@ -21,15 +21,12 @@
 /*
  * SoC Configuration
  */
-#define CONFIG_SOC_DA8XX		/* TI DA8xx SoC */
-#define CONFIG_SOC_DA850		/* TI DA850 SoC */
 #define CONFIG_SYS_EXCEPTION_VECTORS_HIGH
 #define CONFIG_SYS_CLK_FREQ		clk_get(DAVINCI_ARM_CLKID)
 #define CONFIG_SYS_OSCIN_FREQ		calimain_get_osc_freq()
 #define CONFIG_SYS_TIMERBASE		DAVINCI_TIMER0_BASE
 #define CONFIG_SYS_HZ_CLOCK		clk_get(DAVINCI_AUXCLK_CLKID)
 #define CONFIG_SYS_TEXT_BASE		0x60000000
-#define CONFIG_DA850_LOWLEVEL
 #define CONFIG_ARCH_CPU_INIT
 #define CONFIG_DA8XX_GPIO
 #define CONFIG_HW_WATCHDOG
diff --git a/include/configs/chiliboard.h b/include/configs/chiliboard.h
index 92fd235..89740ba 100644
--- a/include/configs/chiliboard.h
+++ b/include/configs/chiliboard.h
@@ -152,9 +152,7 @@
 /* NAND: SPL related configs */
 
 /* USB configuration */
-#define CONFIG_USB_MUSB_DSPS
 #define CONFIG_ARCH_MISC_INIT
-#define CONFIG_USB_MUSB_PIO_ONLY
 #define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
 #define CONFIG_AM335X_USB1
 #define CONFIG_AM335X_USB1_MODE MUSB_HOST
diff --git a/include/configs/cl-som-am57x.h b/include/configs/cl-som-am57x.h
index 6935b06..4f64672 100644
--- a/include/configs/cl-som-am57x.h
+++ b/include/configs/cl-som-am57x.h
@@ -77,7 +77,6 @@
 /* USB xHCI HOST */
 #define CONFIG_USB_XHCI_OMAP
 
-#define CONFIG_OMAP_USB_PHY
 #define CONFIG_OMAP_USB3PHY1_HOST
 
 /* USB Networking options */
diff --git a/include/configs/clearfog.h b/include/configs/clearfog.h
index bf87bac..512c463 100644
--- a/include/configs/clearfog.h
+++ b/include/configs/clearfog.h
@@ -40,11 +40,6 @@
  */
 #define CONFIG_SYS_MMC_BASE		MVEBU_SDIO_BASE
 
-/* Partition support */
-
-/* Additional FS support/configuration */
-#define CONFIG_SUPPORT_VFAT
-
 /* USB/EHCI configuration */
 #define CONFIG_EHCI_IS_TDI
 
diff --git a/include/configs/cm_t35.h b/include/configs/cm_t35.h
index dc1b6b5..3c64cb5 100644
--- a/include/configs/cm_t35.h
+++ b/include/configs/cm_t35.h
@@ -71,11 +71,6 @@
 #define CONFIG_SYS_BAUDRATE_TABLE	{4800, 9600, 19200, 38400, 57600,\
 					115200}
 
-/* USB */
-#define CONFIG_USB_OMAP3
-#define CONFIG_USB_MUSB_UDC
-#define CONFIG_TWL4030_USB
-
 /* USB device configuration */
 #define CONFIG_USB_DEVICE
 #define CONFIG_USB_TTY
diff --git a/include/configs/cm_t3517.h b/include/configs/cm_t3517.h
index a472b9f..fe8b39a 100644
--- a/include/configs/cm_t3517.h
+++ b/include/configs/cm_t3517.h
@@ -78,14 +78,10 @@
 					115200}
 
 /* USB */
-#define CONFIG_USB_MUSB_AM35X
 
 #ifndef CONFIG_USB_MUSB_AM35X
-#define CONFIG_USB_OMAP3
 #define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO 146
 #define CONFIG_OMAP_EHCI_PHY2_RESET_GPIO 147
-#else /* !CONFIG_USB_MUSB_AM35X */
-#define CONFIG_USB_MUSB_PIO_ONLY
 #endif /* CONFIG_USB_MUSB_AM35X */
 
 /* commands to include */
diff --git a/include/configs/cm_t43.h b/include/configs/cm_t43.h
index a222491..a564b86 100644
--- a/include/configs/cm_t43.h
+++ b/include/configs/cm_t43.h
@@ -55,7 +55,6 @@
 
 /* USB support */
 #define CONFIG_USB_XHCI_OMAP
-#define CONFIG_OMAP_USB_PHY
 #define CONFIG_AM437X_USB2PHY2_HOST
 
 /* SPI Flash support */
diff --git a/include/configs/controlcenterdc.h b/include/configs/controlcenterdc.h
index a882fa6..bf324bb 100644
--- a/include/configs/controlcenterdc.h
+++ b/include/configs/controlcenterdc.h
@@ -54,9 +54,6 @@
 #define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
 					 CONFIG_SYS_SCSI_MAX_LUN)
 
-/* Additional FS support/configuration */
-#define CONFIG_SUPPORT_VFAT
-
 /* USB/EHCI configuration */
 #define CONFIG_EHCI_IS_TDI
 
diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h
index 3ca5965..2a6916b 100644
--- a/include/configs/da850evm.h
+++ b/include/configs/da850evm.h
@@ -33,9 +33,6 @@
 /*
  * SoC Configuration
  */
-#define CONFIG_MACH_DAVINCI_DA850_EVM
-#define CONFIG_SOC_DA8XX		/* TI DA8xx SoC */
-#define CONFIG_SOC_DA850		/* TI DA850 SoC */
 #define CONFIG_SYS_EXCEPTION_VECTORS_HIGH
 #define CONFIG_SYS_CLK_FREQ		clk_get(DAVINCI_ARM_CLKID)
 #define CONFIG_SYS_OSCIN_FREQ		24000000
@@ -47,7 +44,6 @@
 #define CONFIG_DA8XX_GPIO
 #define CONFIG_SYS_TEXT_BASE		0x60000000
 #define CONFIG_SYS_DV_NOR_BOOT_CFG	(0x11)
-#define CONFIG_DA850_LOWLEVEL
 #else
 #define CONFIG_SYS_TEXT_BASE		0xc1080000
 #endif
@@ -150,7 +146,6 @@
 #define CONFIG_CONS_INDEX	1		/* use UART0 for console */
 
 #define CONFIG_SPI
-#define CONFIG_DAVINCI_SPI
 #define CONFIG_SYS_SPI_CLK		clk_get(DAVINCI_SPI1_CLKID)
 #ifdef CONFIG_SPL_BUILD
 #define CONFIG_SYS_SPI_BASE		DAVINCI_SPI1_BASE
diff --git a/include/configs/db-88f6720.h b/include/configs/db-88f6720.h
index cdaaced..67943ba 100644
--- a/include/configs/db-88f6720.h
+++ b/include/configs/db-88f6720.h
@@ -49,9 +49,6 @@
 
 #define CONFIG_SYS_ALT_MEMTEST
 
-/* Additional FS support/configuration */
-#define CONFIG_SUPPORT_VFAT
-
 /*
  * mv-common.h should be defined after CMD configs since it used them
  * to enable certain macros
diff --git a/include/configs/db-88f6820-amc.h b/include/configs/db-88f6820-amc.h
index b0e988d..69ec662 100644
--- a/include/configs/db-88f6820-amc.h
+++ b/include/configs/db-88f6820-amc.h
@@ -30,11 +30,6 @@
 #define CONFIG_SF_DEFAULT_SPEED		1000000
 #define CONFIG_SF_DEFAULT_MODE		SPI_MODE_3
 
-/* Partition support */
-
-/* Additional FS support/configuration */
-#define CONFIG_SUPPORT_VFAT
-
 /* USB/EHCI configuration */
 #define CONFIG_EHCI_IS_TDI
 
diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h
index 32f93f2..a3ab6ef 100644
--- a/include/configs/db-88f6820-gp.h
+++ b/include/configs/db-88f6820-gp.h
@@ -50,11 +50,6 @@
 #define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
 					 CONFIG_SYS_SCSI_MAX_LUN)
 
-/* Partition support */
-
-/* Additional FS support/configuration */
-#define CONFIG_SUPPORT_VFAT
-
 /* USB/EHCI configuration */
 #define CONFIG_EHCI_IS_TDI
 
diff --git a/include/configs/db-mv784mp-gp.h b/include/configs/db-mv784mp-gp.h
index 3dcc287..524a1ca 100644
--- a/include/configs/db-mv784mp-gp.h
+++ b/include/configs/db-mv784mp-gp.h
@@ -51,9 +51,6 @@
 #define CONFIG_SYS_SATA_MAX_DEVICE	2
 #define CONFIG_LBA48
 
-/* Additional FS support/configuration */
-#define CONFIG_SUPPORT_VFAT
-
 /* PCIe support */
 #ifndef CONFIG_SPL_BUILD
 #define CONFIG_PCI_MVEBU
diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h
index f777d57..ff90b6d 100644
--- a/include/configs/dra7xx_evm.h
+++ b/include/configs/dra7xx_evm.h
@@ -144,7 +144,6 @@
 /* USB xHCI HOST */
 #define CONFIG_USB_XHCI_OMAP
 
-#define CONFIG_OMAP_USB_PHY
 #define CONFIG_OMAP_USB2PHY2_HOST
 
 /* SATA */
diff --git a/include/configs/dragonboard820c.h b/include/configs/dragonboard820c.h
index 010bc44..e28a956 100644
--- a/include/configs/dragonboard820c.h
+++ b/include/configs/dragonboard820c.h
@@ -60,7 +60,6 @@
 	"pxefile_addr_r=0x90100000\0"\
 	BOOTENV
 
-#define CONFIG_EXT4_WRITE
 #define CONFIG_ENV_SIZE			0x4000
 #define CONFIG_ENV_VARS_UBOOT_CONFIG
 
diff --git a/include/configs/ds414.h b/include/configs/ds414.h
index c201dbf..c840c93 100644
--- a/include/configs/ds414.h
+++ b/include/configs/ds414.h
@@ -68,7 +68,6 @@
 #endif
 
 /* why is this only defined in mv-common.h if CONFIG_DM is undefined? */
-#define CONFIG_SUPPORT_VFAT
 #define CONFIG_SYS_MVFS
 
 /*
diff --git a/include/configs/ea20.h b/include/configs/ea20.h
index c5e6e9e..efc72b3 100644
--- a/include/configs/ea20.h
+++ b/include/configs/ea20.h
@@ -24,9 +24,6 @@
 /*
  * SoC Configuration
  */
-#define CONFIG_MACH_DAVINCI_DA850_EVM
-#define CONFIG_SOC_DA8XX		/* TI DA8xx SoC */
-#define CONFIG_SOC_DA850		/* TI DA850 SoC */
 #define CONFIG_SYS_CLK_FREQ		clk_get(DAVINCI_ARM_CLKID)
 #define CONFIG_SYS_OSCIN_FREQ		24000000
 #define CONFIG_SYS_TIMERBASE		DAVINCI_TIMER0_BASE
@@ -61,7 +58,6 @@
 #define CONFIG_CONS_INDEX	1		/* use UART0 for console */
 
 #define CONFIG_SPI
-#define CONFIG_DAVINCI_SPI
 #define CONFIG_SYS_SPI_BASE		DAVINCI_SPI1_BASE
 #define CONFIG_SYS_SPI_CLK		clk_get(DAVINCI_SPI1_CLKID)
 #define CONFIG_SF_DEFAULT_SPEED		30000000
diff --git a/include/configs/eco5pk.h b/include/configs/eco5pk.h
index 9dbd7a2..a75932f 100644
--- a/include/configs/eco5pk.h
+++ b/include/configs/eco5pk.h
@@ -15,8 +15,6 @@
 
 #include "tam3517-common.h"
 
-#undef CONFIG_USB_OMAP3
-
 /* Our console port is port3 */
 #undef CONFIG_CONS_INDEX
 #undef CONFIG_SYS_NS16550_COM1
diff --git a/include/configs/edminiv2.h b/include/configs/edminiv2.h
index b77cfc5..167fcf2 100644
--- a/include/configs/edminiv2.h
+++ b/include/configs/edminiv2.h
@@ -165,7 +165,6 @@
  */
 #ifdef CONFIG_CMD_USB
 #define ORION5X_USB20_HOST_PORT_BASE ORION5X_USB20_PORT0_BASE
-#define CONFIG_SUPPORT_VFAT
 #endif /* CONFIG_CMD_USB */
 
 /*
diff --git a/include/configs/gplugd.h b/include/configs/gplugd.h
index dddd300..67f0672 100644
--- a/include/configs/gplugd.h
+++ b/include/configs/gplugd.h
@@ -85,6 +85,4 @@
 #define CONFIG_EHCI_IS_TDI
 #endif /* CONFIG_CMD_USB */
 
-#define CONFIG_SUPPORT_VFAT
-
 #endif	/* __CONFIG_GPLUGD_H */
diff --git a/include/configs/hikey.h b/include/configs/hikey.h
index 7eaa6e4..130c769 100644
--- a/include/configs/hikey.h
+++ b/include/configs/hikey.h
@@ -66,8 +66,6 @@
 /* SD/MMC configuration */
 #define CONFIG_BOUNCE_BUFFER
 
-#define CONFIG_FS_EXT4
-
 /* Command line configuration */
 
 #define CONFIG_MTD_PARTITIONS
diff --git a/include/configs/ipam390.h b/include/configs/ipam390.h
index 1683855..618bf72 100644
--- a/include/configs/ipam390.h
+++ b/include/configs/ipam390.h
@@ -24,9 +24,6 @@
 /*
  * SoC Configuration
  */
-#define CONFIG_MACH_DAVINCI_DA850_EVM
-#define CONFIG_SOC_DA8XX		/* TI DA8xx SoC */
-#define CONFIG_SOC_DA850		/* TI DA850 SoC */
 #define CONFIG_SYS_EXCEPTION_VECTORS_HIGH
 #define CONFIG_SYS_CLK_FREQ		clk_get(DAVINCI_ARM_CLKID)
 #define CONFIG_SYS_OSCIN_FREQ		24000000
diff --git a/include/configs/kc1.h b/include/configs/kc1.h
index 8d8dc26..94c3d0a 100644
--- a/include/configs/kc1.h
+++ b/include/configs/kc1.h
@@ -115,9 +115,6 @@
  * USB gadget
  */
 
-#define CONFIG_USB_MUSB_PIO_ONLY
-#define CONFIG_USB_MUSB_OMAP2PLUS
-
 /*
  * Environment
  */
diff --git a/include/configs/legoev3.h b/include/configs/legoev3.h
index c27373c..3439cbe 100644
--- a/include/configs/legoev3.h
+++ b/include/configs/legoev3.h
@@ -18,9 +18,6 @@
 /*
  * SoC Configuration
  */
-#define CONFIG_MACH_DAVINCI_DA850_EVM
-#define CONFIG_SOC_DA8XX		/* TI DA8xx SoC */
-#define CONFIG_SOC_DA850		/* TI DA850 SoC */
 #define CONFIG_SYS_EXCEPTION_VECTORS_HIGH
 #define CONFIG_SYS_CLK_FREQ		clk_get(DAVINCI_ARM_CLKID)
 #define CONFIG_SYS_OSCIN_FREQ		24000000
@@ -124,7 +121,6 @@
 #define CONFIG_CONS_INDEX	1		/* use UART0 for console */
 
 #define CONFIG_SPI
-#define CONFIG_DAVINCI_SPI
 #define CONFIG_SYS_SPI_BASE		DAVINCI_SPI0_BASE
 #define CONFIG_SYS_SPI_CLK		clk_get(DAVINCI_SPI0_CLKID)
 #define CONFIG_SF_DEFAULT_SPEED		50000000
diff --git a/include/configs/ls1088aqds.h b/include/configs/ls1088aqds.h
index 8fbf890..5674a5d 100644
--- a/include/configs/ls1088aqds.h
+++ b/include/configs/ls1088aqds.h
@@ -170,9 +170,13 @@
 #define QIXIS_LBMAP_DFLTBANK		0x0e
 #define QIXIS_LBMAP_ALTBANK		0x2e
 #define QIXIS_LBMAP_SD			0x00
+#define QIXIS_LBMAP_EMMC		0x00
+#define QIXIS_LBMAP_IFC			0x00
 #define QIXIS_LBMAP_SD_QSPI		0x0e
 #define QIXIS_LBMAP_QSPI		0x0e
+#define QIXIS_RCW_SRC_IFC		0x25
 #define QIXIS_RCW_SRC_SD		0x40
+#define QIXIS_RCW_SRC_EMMC		0x41
 #define QIXIS_RCW_SRC_QSPI		0x62
 #define QIXIS_RST_CTL_RESET		0x41
 #define QIXIS_RCFG_CTL_RECONFIG_IDLE	0x20
@@ -279,6 +283,33 @@
 #define I2C_MUX_CH_DEFAULT		0x8
 #define I2C_MUX_CH5			0xD
 
+#define I2C_MUX_CH_VOL_MONITOR          0xA
+
+/* Voltage monitor on channel 2*/
+#define I2C_VOL_MONITOR_ADDR           0x63
+#define I2C_VOL_MONITOR_BUS_V_OFFSET   0x2
+#define I2C_VOL_MONITOR_BUS_V_OVF      0x1
+#define I2C_VOL_MONITOR_BUS_V_SHIFT    3
+#define I2C_SVDD_MONITOR_ADDR           0x4F
+
+#define CONFIG_VID_FLS_ENV              "ls1088aqds_vdd_mv"
+#define CONFIG_VID
+
+/* The lowest and highest voltage allowed for LS1088AQDS */
+#define VDD_MV_MIN			819
+#define VDD_MV_MAX			1212
+
+#define CONFIG_VOL_MONITOR_LTC3882_SET
+#define CONFIG_VOL_MONITOR_LTC3882_READ
+
+/* PM Bus commands code for LTC3882*/
+#define PMBUS_CMD_PAGE                  0x0
+#define PMBUS_CMD_READ_VOUT             0x8B
+#define PMBUS_CMD_PAGE_PLUS_WRITE       0x05
+#define PMBUS_CMD_VOUT_COMMAND          0x21
+
+#define PWM_CHANNEL0                    0x0
+
 /*
 * RTC configuration
 */
diff --git a/include/configs/ls1088ardb.h b/include/configs/ls1088ardb.h
index d0066e3..a6271f5 100644
--- a/include/configs/ls1088ardb.h
+++ b/include/configs/ls1088ardb.h
@@ -151,6 +151,7 @@
 #endif
 
 #define CONFIG_SYS_I2C_FPGA_ADDR	0x66
+#define QIXIS_BRDCFG4_OFFSET            0x54
 #define QIXIS_LBMAP_SWITCH		2
 #define QIXIS_QMAP_MASK			0xe0
 #define QIXIS_QMAP_SHIFT		5
@@ -159,9 +160,11 @@
 #define QIXIS_LBMAP_DFLTBANK		0x00
 #define QIXIS_LBMAP_ALTBANK		0x20
 #define QIXIS_LBMAP_SD			0x00
+#define QIXIS_LBMAP_EMMC		0x00
 #define QIXIS_LBMAP_SD_QSPI		0x00
 #define QIXIS_LBMAP_QSPI		0x00
 #define QIXIS_RCW_SRC_SD		0x40
+#define QIXIS_RCW_SRC_EMMC		0x41
 #define QIXIS_RCW_SRC_QSPI		0x62
 #define QIXIS_RST_CTL_RESET		0x31
 #define QIXIS_RCFG_CTL_RECONFIG_IDLE	0x20
@@ -225,6 +228,32 @@
 
 #define CONFIG_SYS_LS_MC_BOOT_TIMEOUT_MS 5000
 
+#define I2C_MUX_CH_VOL_MONITOR          0xA
+/* Voltage monitor on channel 2*/
+#define I2C_VOL_MONITOR_ADDR           0x63
+#define I2C_VOL_MONITOR_BUS_V_OFFSET   0x2
+#define I2C_VOL_MONITOR_BUS_V_OVF      0x1
+#define I2C_VOL_MONITOR_BUS_V_SHIFT    3
+#define I2C_SVDD_MONITOR_ADDR		0x4F
+
+#define CONFIG_VID_FLS_ENV              "ls1088ardb_vdd_mv"
+#define CONFIG_VID
+
+/* The lowest and highest voltage allowed for LS1088ARDB */
+#define VDD_MV_MIN			819
+#define VDD_MV_MAX			1212
+
+#define CONFIG_VOL_MONITOR_LTC3882_SET
+#define CONFIG_VOL_MONITOR_LTC3882_READ
+
+/* PM Bus commands code for LTC3882*/
+#define PMBUS_CMD_PAGE                  0x0
+#define PMBUS_CMD_READ_VOUT             0x8B
+#define PMBUS_CMD_PAGE_PLUS_WRITE       0x05
+#define PMBUS_CMD_VOUT_COMMAND          0x21
+
+#define PWM_CHANNEL0                    0x0
+
 /*
  * I2C bus multiplexer
  */
diff --git a/include/configs/mv-common.h b/include/configs/mv-common.h
index 7c2bab2..1721fef 100644
--- a/include/configs/mv-common.h
+++ b/include/configs/mv-common.h
@@ -116,13 +116,6 @@
 #endif
 
 /*
- * Common USB/EHCI configuration
- */
-#if defined(CONFIG_CMD_USB) && !defined(CONFIG_DM)
-#define CONFIG_SUPPORT_VFAT
-#endif /* CONFIG_CMD_USB */
-
-/*
  * File system
  */
 #ifdef CONFIG_SYS_MVFS
diff --git a/include/configs/mvebu_armada-37xx.h b/include/configs/mvebu_armada-37xx.h
index 9f2db09..5c53dd3 100644
--- a/include/configs/mvebu_armada-37xx.h
+++ b/include/configs/mvebu_armada-37xx.h
@@ -102,8 +102,6 @@
 #define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
 					 CONFIG_SYS_SCSI_MAX_LUN)
 
-#define CONFIG_SUPPORT_VFAT
-
 #include <config_distro_defaults.h>
 
 #define BOOT_TARGET_DEVICES(func) \
diff --git a/include/configs/mvebu_armada-8k.h b/include/configs/mvebu_armada-8k.h
index 7f14316..86e0d43 100644
--- a/include/configs/mvebu_armada-8k.h
+++ b/include/configs/mvebu_armada-8k.h
@@ -105,8 +105,6 @@
 #define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
 					 CONFIG_SYS_SCSI_MAX_LUN)
 
-#define CONFIG_SUPPORT_VFAT
-
 /*
  * PCI configuration
  */
diff --git a/include/configs/mx25pdk.h b/include/configs/mx25pdk.h
index 8e8946a..f82c4cc 100644
--- a/include/configs/mx25pdk.h
+++ b/include/configs/mx25pdk.h
@@ -65,11 +65,6 @@
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_SYS_LONGHELP
 
-/* U-Boot commands */
-
-/* Filesystem support */
-#define CONFIG_FS_EXT4
-
 /* Ethernet */
 #define CONFIG_FEC_MXC
 #define CONFIG_FEC_MXC_PHYADDR		0x1f
diff --git a/include/configs/nas220.h b/include/configs/nas220.h
index 089263f..90be7bd 100644
--- a/include/configs/nas220.h
+++ b/include/configs/nas220.h
@@ -91,7 +91,6 @@
 #ifdef CONFIG_CMD_USB
 #define CONFIG_USB_EHCI_KIRKWOOD	/* on Kirkwood platform	*/
 #define CONFIG_EHCI_IS_TDI
-#define CONFIG_SUPPORT_VFAT
 #endif /* CONFIG_CMD_USB */
 
 /*
diff --git a/include/configs/nokia_rx51.h b/include/configs/nokia_rx51.h
index b7fe734..00509e8 100644
--- a/include/configs/nokia_rx51.h
+++ b/include/configs/nokia_rx51.h
@@ -82,12 +82,6 @@
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_SYS_BAUDRATE_TABLE { 4800, 9600, 19200, 38400, 57600, 115200 }
 
-/* USB */
-#define CONFIG_USB_MUSB_UDC
-#define CONFIG_USB_MUSB_HCD
-#define CONFIG_USB_OMAP3
-#define CONFIG_TWL4030_USB
-
 /* USB device configuration */
 #define CONFIG_USB_DEVICE
 #define CONFIG_USBD_VENDORID		0x0421
diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h
index 843e345..d3dfe60 100644
--- a/include/configs/omap3_beagle.h
+++ b/include/configs/omap3_beagle.h
@@ -62,9 +62,6 @@
 
 /* MUSB */
 #define CONFIG_USB_OMAP3
-#define CONFIG_USB_MUSB_OMAP2PLUS
-#define CONFIG_USB_MUSB_PIO_ONLY
-#define CONFIG_TWL4030_USB
 
 /* USB EHCI */
 #define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO	147
diff --git a/include/configs/omap3_evm.h b/include/configs/omap3_evm.h
index 3ecfdbb..ba67e33 100644
--- a/include/configs/omap3_evm.h
+++ b/include/configs/omap3_evm.h
@@ -74,9 +74,6 @@
 #endif /* CONFIG_NAND */
 
 /* MUSB */
-#define CONFIG_USB_OMAP3
-#define CONFIG_USB_MUSB_OMAP2PLUS
-#define CONFIG_USB_MUSB_PIO_ONLY
 
 /* USB EHCI */
 #define CONFIG_SYS_USB_FAT_BOOT_PARTITION  1
diff --git a/include/configs/omap3_igep00x0.h b/include/configs/omap3_igep00x0.h
index 91b3a23..76d8e13 100644
--- a/include/configs/omap3_igep00x0.h
+++ b/include/configs/omap3_igep00x0.h
@@ -41,11 +41,6 @@
 #define GPIO_IGEP00X0_BOARD_DETECTION		28
 #define GPIO_IGEP00X0_REVISION_DETECTION	129
 
-/* USB */
-#define CONFIG_USB_MUSB_UDC		1
-#define CONFIG_USB_OMAP3		1
-#define CONFIG_TWL4030_USB		1
-
 /* USB device configuration */
 #define CONFIG_USB_DEVICE		1
 #define CONFIG_USB_TTY			1
diff --git a/include/configs/omap3_logic.h b/include/configs/omap3_logic.h
index b095814..70745a8 100644
--- a/include/configs/omap3_logic.h
+++ b/include/configs/omap3_logic.h
@@ -49,18 +49,9 @@
 
 /* Hardware drivers */
 
-#define CONFIG_USB_OMAP3
-
 /* I2C */
 #define CONFIG_SYS_I2C_EEPROM_ADDR	0x50	/* EEPROM AT24C64      */
 
-/* USB */
-#define CONFIG_USB_MUSB_OMAP2PLUS
-#define CONFIG_USB_MUSB_PIO_ONLY
-
-/* TWL4030 */
-#define CONFIG_TWL4030_USB
-
 /* Board NAND Info. */
 #ifdef CONFIG_NAND
 #define CONFIG_SYS_NAND_ADDR		NAND_BASE /* physical address */
diff --git a/include/configs/omap3_zoom1.h b/include/configs/omap3_zoom1.h
index d1ff48d..cc7c2fd 100644
--- a/include/configs/omap3_zoom1.h
+++ b/include/configs/omap3_zoom1.h
@@ -34,11 +34,6 @@
  * Hardware drivers
  */
 
-/* USB */
-#define CONFIG_USB_MUSB_UDC			1
-#define CONFIG_USB_OMAP3		1
-#define CONFIG_TWL4030_USB		1
-
 /* USB device configuration */
 #define CONFIG_USB_DEVICE		1
 #define CONFIG_USB_TTY			1
diff --git a/include/configs/omapl138_lcdk.h b/include/configs/omapl138_lcdk.h
index 5dba7d2..2cb9911 100644
--- a/include/configs/omapl138_lcdk.h
+++ b/include/configs/omapl138_lcdk.h
@@ -24,7 +24,6 @@
  */
 #define CONFIG_MACH_OMAPL138_LCDK
 #define CONFIG_ARM926EJS		/* arm926ejs CPU core */
-#define CONFIG_SOC_DA8XX		/* TI DA8xx SoC */
 #define CONFIG_SYS_CLK_FREQ		clk_get(DAVINCI_ARM_CLKID)
 #define CONFIG_SYS_OSCIN_FREQ		24000000
 #define CONFIG_SYS_TIMERBASE		DAVINCI_TIMER0_BASE
@@ -129,7 +128,6 @@
 #define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
 
 #define CONFIG_SPI
-#define CONFIG_DAVINCI_SPI
 #define CONFIG_SYS_SPI_BASE		DAVINCI_SPI1_BASE
 #define CONFIG_SYS_SPI_CLK		clk_get(DAVINCI_SPI1_CLKID)
 #define CONFIG_SF_DEFAULT_SPEED		30000000
diff --git a/include/configs/pcm051.h b/include/configs/pcm051.h
index 79f3f48..c6ff1e1 100644
--- a/include/configs/pcm051.h
+++ b/include/configs/pcm051.h
@@ -126,8 +126,6 @@
 /*
  * USB configuration
  */
-#define CONFIG_USB_MUSB_DSPS
-#define CONFIG_USB_MUSB_PIO_ONLY
 #define CONFIG_AM335X_USB0
 #define CONFIG_AM335X_USB0_MODE	MUSB_PERIPHERAL
 #define CONFIG_AM335X_USB1
diff --git a/include/configs/pengwyn.h b/include/configs/pengwyn.h
index 8afd64e..d9a50ca 100644
--- a/include/configs/pengwyn.h
+++ b/include/configs/pengwyn.h
@@ -162,8 +162,6 @@
  * board schematic and physical port wired to each.  Then for host we
  * add mass storage support.
  */
-#define CONFIG_USB_MUSB_DSPS
-#define CONFIG_USB_MUSB_PIO_ONLY
 #define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
 #define CONFIG_AM335X_USB0
 #define CONFIG_AM335X_USB0_MODE	MUSB_PERIPHERAL
diff --git a/include/configs/pic32mzdask.h b/include/configs/pic32mzdask.h
index 97636fe..7a959c4 100644
--- a/include/configs/pic32mzdask.h
+++ b/include/configs/pic32mzdask.h
@@ -80,16 +80,6 @@
 /*--------------------------------------------------
  * USB Configuration
  */
-#define CONFIG_USB_MUSB_PIO_ONLY
-
-/*-----------------------------------------------------------------------
- * File System Configuration
- */
-/* FAT FS */
-#define CONFIG_SUPPORT_VFAT
-
-/* EXT4 FS */
-#define CONFIG_FS_EXT4
 
 /* -------------------------------------------------
  * Environment
diff --git a/include/configs/poplar.h b/include/configs/poplar.h
index 8a12b52..acdce29 100644
--- a/include/configs/poplar.h
+++ b/include/configs/poplar.h
@@ -66,7 +66,6 @@
 #define CONFIG_SYS_MMC_ENV_DEV		0
 #define CONFIG_ENV_OFFSET		(0x780 * 512)	/* env_mmc_blknum */
 #define CONFIG_ENV_SIZE			0x10000	/* env_mmc_nblks bytes */
-#define CONFIG_FAT_WRITE
 #define CONFIG_ENV_VARS_UBOOT_CONFIG
 
 /* Monitor Command Prompt */
diff --git a/include/configs/rcar-gen2-common.h b/include/configs/rcar-gen2-common.h
index 2c10e61..d779297 100644
--- a/include/configs/rcar-gen2-common.h
+++ b/include/configs/rcar-gen2-common.h
@@ -11,11 +11,6 @@
 
 #include <asm/arch/rmobile.h>
 
-/* Support File sytems */
-#define CONFIG_SUPPORT_VFAT
-#define CONFIG_FS_EXT4
-#define CONFIG_EXT4_WRITE
-
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_SETUP_MEMORY_TAGS
 #define CONFIG_INITRD_TAG
diff --git a/include/configs/rcar-gen3-common.h b/include/configs/rcar-gen3-common.h
index 30a98b8..e9e5fec 100644
--- a/include/configs/rcar-gen3-common.h
+++ b/include/configs/rcar-gen3-common.h
@@ -17,11 +17,6 @@
 /* boot option */
 #define CONFIG_SUPPORT_RAW_INITRD
 
-/* Support File sytems */
-#define CONFIG_SUPPORT_VFAT
-#define CONFIG_FS_EXT4
-#define CONFIG_EXT4_WRITE
-
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_SETUP_MEMORY_TAGS
 #define CONFIG_INITRD_TAG
diff --git a/include/configs/rk3128_common.h b/include/configs/rk3128_common.h
index e915a56..8889046 100644
--- a/include/configs/rk3128_common.h
+++ b/include/configs/rk3128_common.h
@@ -30,9 +30,6 @@
 /* MMC/SD IP block */
 #define CONFIG_BOUNCE_BUFFER
 
-#define CONFIG_SUPPORT_VFAT
-#define CONFIG_FS_EXT4
-
 /* RAW SD card / eMMC locations. */
 #define CONFIG_SYS_SPI_U_BOOT_OFFS	(128 << 10)
 
diff --git a/include/configs/rk3188_common.h b/include/configs/rk3188_common.h
index 0cb0762..9ab5502 100644
--- a/include/configs/rk3188_common.h
+++ b/include/configs/rk3188_common.h
@@ -58,7 +58,6 @@
 
 #ifndef CONFIG_SPL_BUILD
 /* usb otg */
-#define CONFIG_ROCKCHIP_USB2_PHY
 
 /* usb host support */
 #define ENV_MEM_LAYOUT_SETTINGS \
diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
index e2f070f..c2bd378 100644
--- a/include/configs/rk3288_common.h
+++ b/include/configs/rk3288_common.h
@@ -58,7 +58,6 @@
 
 #ifndef CONFIG_SPL_BUILD
 /* usb otg */
-#define CONFIG_ROCKCHIP_USB2_PHY
 
 /* usb mass storage */
 #define CONFIG_USB_FUNCTION_MASS_STORAGE
diff --git a/include/configs/rk3328_common.h b/include/configs/rk3328_common.h
index af55632..eba5a22 100644
--- a/include/configs/rk3328_common.h
+++ b/include/configs/rk3328_common.h
@@ -24,9 +24,6 @@
 /* MMC/SD IP block */
 #define CONFIG_BOUNCE_BUFFER
 
-#define CONFIG_SUPPORT_VFAT
-#define CONFIG_FS_EXT4
-
 /* RAW SD card / eMMC locations. */
 #define CONFIG_SYS_SPI_U_BOOT_OFFS	(128 << 10)
 
diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h
index 561bfa7..95f544e 100644
--- a/include/configs/rk3399_common.h
+++ b/include/configs/rk3399_common.h
@@ -38,9 +38,6 @@
 #define CONFIG_BOUNCE_BUFFER
 #define CONFIG_ROCKCHIP_SDHCI_MAX_FREQ	200000000
 
-#define CONFIG_SUPPORT_VFAT
-#define CONFIG_FS_EXT4
-
 /* RAW SD card / eMMC locations. */
 #define CONFIG_SYS_SPI_U_BOOT_OFFS	(128 << 10)
 
diff --git a/include/configs/s5p_goni.h b/include/configs/s5p_goni.h
index 1aa1671..c31896d 100644
--- a/include/configs/s5p_goni.h
+++ b/include/configs/s5p_goni.h
@@ -187,11 +187,6 @@
 #define CONFIG_SAMSUNG_ONENAND		1
 #define CONFIG_SYS_ONENAND_BASE		0xB0000000
 
-/* write support for filesystems */
-#define CONFIG_EXT4_WRITE
-
-/* GPT */
-
 #define CONFIG_SYS_INIT_SP_ADDR	(CONFIG_SYS_LOAD_ADDR - 0x1000000)
 
 #define CONFIG_USB_GADGET_DWC2_OTG_PHY
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index f042656..cfb3e7a 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -25,8 +25,6 @@
 
 #define CONFIG_LMB
 
-#define CONFIG_FS_EXT4
-#define CONFIG_EXT4_WRITE
 #define CONFIG_HOST_MAX_DEVICES 4
 
 /*
diff --git a/include/configs/siemens-am33x-common.h b/include/configs/siemens-am33x-common.h
index 78708a2..85b6412 100644
--- a/include/configs/siemens-am33x-common.h
+++ b/include/configs/siemens-am33x-common.h
@@ -168,8 +168,6 @@
 /*
  * USB configuration
  */
-#define CONFIG_USB_MUSB_DSPS
-#define CONFIG_USB_MUSB_PIO_ONLY
 #define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
 
 #define CONFIG_AM335X_USB0
diff --git a/include/configs/sniper.h b/include/configs/sniper.h
index 5809942..0ed72cf 100644
--- a/include/configs/sniper.h
+++ b/include/configs/sniper.h
@@ -110,14 +110,6 @@
 					  115200 }
 
 /*
- * USB gadget
- */
-
-#define CONFIG_USB_MUSB_PIO_ONLY
-#define CONFIG_USB_MUSB_OMAP2PLUS
-#define CONFIG_TWL4030_USB
-
-/*
  * Environment
  */
 
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 3855c56..582aba2 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -302,10 +302,6 @@
 #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1
 #endif
 
-#ifdef CONFIG_USB_MUSB_SUNXI
-#define CONFIG_USB_MUSB_PIO_ONLY
-#endif
-
 #ifdef CONFIG_USB_MUSB_GADGET
 #define CONFIG_USB_FUNCTION_MASS_STORAGE
 #endif
diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h
index 743be6b..aea8f1f 100644
--- a/include/configs/tegra-common-post.h
+++ b/include/configs/tegra-common-post.h
@@ -113,11 +113,6 @@
 #ifdef CONFIG_CMD_I2C
 #endif
 
-/* remove partitions/filesystems */
-#ifdef CONFIG_FS_EXT4
-#undef CONFIG_FS_EXT4
-#endif
-
 /* remove USB */
 #ifdef CONFIG_USB_EHCI_TEGRA
 #undef CONFIG_USB_EHCI_TEGRA
diff --git a/include/configs/theadorable.h b/include/configs/theadorable.h
index 6e95aa1..438abf1 100644
--- a/include/configs/theadorable.h
+++ b/include/configs/theadorable.h
@@ -67,9 +67,6 @@
 #define CONFIG_SYS_SATA_MAX_DEVICE	1
 #define CONFIG_LBA48
 
-/* Additional FS support/configuration */
-#define CONFIG_SUPPORT_VFAT
-
 /* PCIe support */
 #ifdef CONFIG_CMD_PCI
 #ifndef CONFIG_SPL_BUILD
diff --git a/include/configs/ti_armv7_keystone2.h b/include/configs/ti_armv7_keystone2.h
index 7fb3aaf..bbed17a 100644
--- a/include/configs/ti_armv7_keystone2.h
+++ b/include/configs/ti_armv7_keystone2.h
@@ -78,7 +78,6 @@
 #endif
 
 /* SPI Configuration */
-#define CONFIG_DAVINCI_SPI
 #define CONFIG_SYS_SPI_CLK		ks_clk_get_rate(KS2_CLK1_6)
 #define CONFIG_SF_DEFAULT_SPEED		30000000
 #define CONFIG_ENV_SPI_MAX_HZ		CONFIG_SF_DEFAULT_SPEED
diff --git a/include/configs/ti_omap4_common.h b/include/configs/ti_omap4_common.h
index 91b2132..844a9e5 100644
--- a/include/configs/ti_omap4_common.h
+++ b/include/configs/ti_omap4_common.h
@@ -61,8 +61,6 @@
 #endif
 
 /* USB */
-#define CONFIG_USB_MUSB_UDC			1
-#define CONFIG_USB_OMAP3		1
 
 /* USB device configuration */
 #define CONFIG_USB_DEVICE		1
diff --git a/include/configs/turris_omnia.h b/include/configs/turris_omnia.h
index 3dbd2ca..40d94a2 100644
--- a/include/configs/turris_omnia.h
+++ b/include/configs/turris_omnia.h
@@ -59,9 +59,6 @@
 #define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
 					 CONFIG_SYS_SCSI_MAX_LUN)
 
-/* Additional FS support/configuration */
-#define CONFIG_SUPPORT_VFAT
-
 /* USB/EHCI configuration */
 #define CONFIG_EHCI_IS_TDI
 
diff --git a/include/configs/vct.h b/include/configs/vct.h
index 00ad134..a5b5aaf 100644
--- a/include/configs/vct.h
+++ b/include/configs/vct.h
@@ -72,7 +72,6 @@
  * Commands
  */
 #if defined(CONFIG_CMD_USB)
-#define CONFIG_SUPPORT_VFAT
 
 /*
  * USB/EHCI
diff --git a/include/configs/x600.h b/include/configs/x600.h
index 7363057..4aa5a2a 100644
--- a/include/configs/x600.h
+++ b/include/configs/x600.h
@@ -96,10 +96,6 @@
 #define CONFIG_USB_EHCI_SPEAR
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	2
 
-/* Filesystem support (for USB key) */
-#define CONFIG_SUPPORT_VFAT
-
-
 /*
  * U-Boot Environment placing definitions.
  */
diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h
index 064c546..994214e 100644
--- a/include/configs/x86-common.h
+++ b/include/configs/x86-common.h
@@ -58,8 +58,6 @@
 #define CONFIG_CMDLINE_EDITING
 #define CONFIG_AUTO_COMPLETE
 
-#define CONFIG_SUPPORT_VFAT
-
 /*-----------------------------------------------------------------------
  * Command line configuration.
  */
diff --git a/include/configs/zmx25.h b/include/configs/zmx25.h
index 1ae1ca4..f9783a2 100644
--- a/include/configs/zmx25.h
+++ b/include/configs/zmx25.h
@@ -82,7 +82,6 @@
 #define CONFIG_MXC_USB_PORTSC	MXC_EHCI_MODE_SERIAL
 #define CONFIG_MXC_USB_FLAGS	(MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN)
 #define CONFIG_EHCI_IS_TDI
-#define CONFIG_SUPPORT_VFAT
 #endif /* CONFIG_CMD_USB */
 
 /* SDRAM */
diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h
index b10cb3f..28cee15 100644
--- a/include/configs/zynq-common.h
+++ b/include/configs/zynq-common.h
@@ -124,10 +124,6 @@
 # define DFU_ALT_INFO
 #endif
 
-#if defined(CONFIG_MMC_SDHCI_ZYNQ) || defined(CONFIG_ZYNQ_USB)
-# define CONFIG_SUPPORT_VFAT
-#endif
-
 #if defined(CONFIG_ZYNQ_I2C0) || defined(CONFIG_ZYNQ_I2C1)
 #define CONFIG_SYS_I2C_ZYNQ
 #endif
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 8b9932a..c359a60 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -652,4 +652,17 @@
 	     ofnode_valid(node); \
 	     node = ofnode_next_subnode(node))
 
+/**
+ * ofnode_translate_address() - Tranlate a device-tree address
+ *
+ * Translate an address from the device-tree into a CPU physical address. This
+ * function walks up the tree and applies the various bus mappings along the
+ * way.
+ *
+ * @ofnode: Device tree node giving the context in which to translate the
+ *          address
+ * @in_addr: pointer to the address to translate
+ * @return the translated address; OF_BAD_ADDR on error
+ */
+u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr);
 #endif
diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h
index 0eb4b92..c6c8f61 100644
--- a/include/dm/pinctrl.h
+++ b/include/dm/pinctrl.h
@@ -137,6 +137,12 @@
 /**
  * Generic pin configuration paramters
  *
+ * enum pin_config_param - possible pin configuration parameters
+ * @PIN_CONFIG_BIAS_BUS_HOLD: the pin will be set to weakly latch so that it
+ *	weakly drives the last value on a tristate bus, also known as a "bus
+ *	holder", "bus keeper" or "repeater". This allows another device on the
+ *	bus to change the value by driving the bus high or low and switching to
+ *	tristate. The argument is ignored.
  * @PIN_CONFIG_BIAS_DISABLE: disable any pin bias on the pin, a
  *	transition from say pull-up to pull-down implies that you disable
  *	pull-up in the process, this setting disables all biasing.
@@ -146,14 +152,6 @@
  *	if for example some other pin is going to drive the signal connected
  *	to it for a while. Pins used for input are usually always high
  *	impedance.
- * @PIN_CONFIG_BIAS_BUS_HOLD: the pin will be set to weakly latch so that it
- *	weakly drives the last value on a tristate bus, also known as a "bus
- *	holder", "bus keeper" or "repeater". This allows another device on the
- *	bus to change the value by driving the bus high or low and switching to
- *	tristate. The argument is ignored.
- * @PIN_CONFIG_BIAS_PULL_UP: the pin will be pulled up (usually with high
- *	impedance to VDD). If the argument is != 0 pull-up is enabled,
- *	if it is 0, pull-up is total, i.e. the pin is connected to VDD.
  * @PIN_CONFIG_BIAS_PULL_DOWN: the pin will be pulled down (usually with high
  *	impedance to GROUND). If the argument is != 0 pull-down is enabled,
  *	if it is 0, pull-down is total, i.e. the pin is connected to GROUND.
@@ -165,10 +163,9 @@
  *	If the argument is != 0 pull up/down is enabled, if it is 0, the
  *	configuration is ignored. The proper way to disable it is to use
  *	@PIN_CONFIG_BIAS_DISABLE.
- * @PIN_CONFIG_DRIVE_PUSH_PULL: the pin will be driven actively high and
- *	low, this is the most typical case and is typically achieved with two
- *	active transistors on the output. Setting this config will enable
- *	push-pull mode, the argument is ignored.
+ * @PIN_CONFIG_BIAS_PULL_UP: the pin will be pulled up (usually with high
+ *	impedance to VDD). If the argument is != 0 pull-up is enabled,
+ *	if it is 0, pull-up is total, i.e. the pin is connected to VDD.
  * @PIN_CONFIG_DRIVE_OPEN_DRAIN: the pin will be driven with open drain (open
  *	collector) which means it is usually wired with other output ports
  *	which are then pulled up with an external resistor. Setting this
@@ -176,59 +173,82 @@
  * @PIN_CONFIG_DRIVE_OPEN_SOURCE: the pin will be driven with open source
  *	(open emitter). Setting this config will enable open source mode, the
  *	argument is ignored.
+ * @PIN_CONFIG_DRIVE_PUSH_PULL: the pin will be driven actively high and
+ *	low, this is the most typical case and is typically achieved with two
+ *	active transistors on the output. Setting this config will enable
+ *	push-pull mode, the argument is ignored.
  * @PIN_CONFIG_DRIVE_STRENGTH: the pin will sink or source at most the current
  *	passed as argument. The argument is in mA.
+ * @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode,
+ *	which means it will wait for signals to settle when reading inputs. The
+ *	argument gives the debounce time in usecs. Setting the
+ *	argument to zero turns debouncing off.
  * @PIN_CONFIG_INPUT_ENABLE: enable the pin's input.  Note that this does not
  *	affect the pin's ability to drive output.  1 enables input, 0 disables
  *	input.
- * @PIN_CONFIG_INPUT_SCHMITT_ENABLE: control schmitt-trigger mode on the pin.
- *      If the argument != 0, schmitt-trigger mode is enabled. If it's 0,
- *      schmitt-trigger mode is disabled.
  * @PIN_CONFIG_INPUT_SCHMITT: this will configure an input pin to run in
  *	schmitt-trigger mode. If the schmitt-trigger has adjustable hysteresis,
  *	the threshold value is given on a custom format as argument when
  *	setting pins to this mode.
- * @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode,
- *	which means it will wait for signals to settle when reading inputs. The
- *	argument gives the debounce time in usecs. Setting the
- *	argument to zero turns debouncing off.
+ * @PIN_CONFIG_INPUT_SCHMITT_ENABLE: control schmitt-trigger mode on the pin.
+ *      If the argument != 0, schmitt-trigger mode is enabled. If it's 0,
+ *      schmitt-trigger mode is disabled.
+ * @PIN_CONFIG_LOW_POWER_MODE: this will configure the pin for low power
+ *	operation, if several modes of operation are supported these can be
+ *	passed in the argument on a custom form, else just use argument 1
+ *	to indicate low power mode, argument 0 turns low power mode off.
+ * @PIN_CONFIG_OUTPUT_ENABLE: this will enable the pin's output mode
+ *	without driving a value there. For most platforms this reduces to
+ *	enable the output buffers and then let the pin controller current
+ *	configuration (eg. the currently selected mux function) drive values on
+ *	the line. Use argument 1 to enable output mode, argument 0 to disable
+ *	it.
+ * @PIN_CONFIG_OUTPUT: this will configure the pin as an output and drive a
+ *	value on the line. Use argument 1 to indicate high level, argument 0 to
+ *	indicate low level. (Please see Documentation/driver-api/pinctl.rst,
+ *	section "GPIO mode pitfalls" for a discussion around this parameter.)
  * @PIN_CONFIG_POWER_SOURCE: if the pin can select between different power
  *	supplies, the argument to this parameter (on a custom format) tells
  *	the driver which alternative power source to use.
+ * @PIN_CONFIG_SLEEP_HARDWARE_STATE: indicate this is sleep related state.
  * @PIN_CONFIG_SLEW_RATE: if the pin can select slew rate, the argument to
  *	this parameter (on a custom format) tells the driver which alternative
  *	slew rate to use.
- * @PIN_CONFIG_LOW_POWER_MODE: this will configure the pin for low power
- *	operation, if several modes of operation are supported these can be
- *	passed in the argument on a custom form, else just use argument 1
- *	to indicate low power mode, argument 0 turns low power mode off.
- * @PIN_CONFIG_OUTPUT: this will configure the pin as an output. Use argument
- *	1 to indicate high level, argument 0 to indicate low level. (Please
- *	see Documentation/pinctrl.txt, section "GPIO mode pitfalls" for a
- *	discussion around this parameter.)
+ * @PIN_CONFIG_SKEW_DELAY: if the pin has programmable skew rate (on inputs)
+ *	or latch delay (on outputs) this parameter (in a custom format)
+ *	specifies the clock skew or latch delay. It typically controls how
+ *	many double inverters are put in front of the line.
  * @PIN_CONFIG_END: this is the last enumerator for pin configurations, if
  *	you need to pass in custom configurations to the pin controller, use
  *	PIN_CONFIG_END+1 as the base offset.
+ * @PIN_CONFIG_MAX: this is the maximum configuration value that can be
+ *	presented using the packed format.
  */
-#define PIN_CONFIG_BIAS_DISABLE			0
-#define PIN_CONFIG_BIAS_HIGH_IMPEDANCE		1
-#define PIN_CONFIG_BIAS_BUS_HOLD		2
-#define PIN_CONFIG_BIAS_PULL_UP			3
-#define PIN_CONFIG_BIAS_PULL_DOWN		4
-#define PIN_CONFIG_BIAS_PULL_PIN_DEFAULT	5
-#define PIN_CONFIG_DRIVE_PUSH_PULL		6
-#define PIN_CONFIG_DRIVE_OPEN_DRAIN		7
-#define PIN_CONFIG_DRIVE_OPEN_SOURCE		8
-#define PIN_CONFIG_DRIVE_STRENGTH		9
-#define PIN_CONFIG_INPUT_ENABLE			10
-#define PIN_CONFIG_INPUT_SCHMITT_ENABLE		11
-#define PIN_CONFIG_INPUT_SCHMITT		12
-#define PIN_CONFIG_INPUT_DEBOUNCE		13
-#define PIN_CONFIG_POWER_SOURCE			14
-#define PIN_CONFIG_SLEW_RATE			15
-#define PIN_CONFIG_LOW_POWER_MODE		16
-#define PIN_CONFIG_OUTPUT			17
-#define PIN_CONFIG_END				0x7FFF
+enum pin_config_param {
+	PIN_CONFIG_BIAS_BUS_HOLD,
+	PIN_CONFIG_BIAS_DISABLE,
+	PIN_CONFIG_BIAS_HIGH_IMPEDANCE,
+	PIN_CONFIG_BIAS_PULL_DOWN,
+	PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
+	PIN_CONFIG_BIAS_PULL_UP,
+	PIN_CONFIG_DRIVE_OPEN_DRAIN,
+	PIN_CONFIG_DRIVE_OPEN_SOURCE,
+	PIN_CONFIG_DRIVE_PUSH_PULL,
+	PIN_CONFIG_DRIVE_STRENGTH,
+	PIN_CONFIG_INPUT_DEBOUNCE,
+	PIN_CONFIG_INPUT_ENABLE,
+	PIN_CONFIG_INPUT_SCHMITT,
+	PIN_CONFIG_INPUT_SCHMITT_ENABLE,
+	PIN_CONFIG_LOW_POWER_MODE,
+	PIN_CONFIG_OUTPUT_ENABLE,
+	PIN_CONFIG_OUTPUT,
+	PIN_CONFIG_POWER_SOURCE,
+	PIN_CONFIG_SLEEP_HARDWARE_STATE,
+	PIN_CONFIG_SLEW_RATE,
+	PIN_CONFIG_SKEW_DELAY,
+	PIN_CONFIG_END = 0x7F,
+	PIN_CONFIG_MAX = 0xFF,
+};
 
 #if CONFIG_IS_ENABLED(PINCTRL_GENERIC)
 /**
diff --git a/include/dm/read.h b/include/dm/read.h
index 5cacec8..f1f0dfd 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -420,6 +420,18 @@
 int dev_read_resource_byname(struct udevice *dev, const char *name,
 			     struct resource *res);
 
+/**
+ * dev_translate_address() - Tranlate a device-tree address
+ *
+ * Translate an address from the device-tree into a CPU physical address.  This
+ * function walks up the tree and applies the various bus mappings along the
+ * way.
+ *
+ * @dev: device giving the context in which to translate the address
+ * @in_addr: pointer to the address to translate
+ * @return the translated address; OF_BAD_ADDR on error
+ */
+u64 dev_translate_address(struct udevice *dev, const fdt32_t *in_addr);
 #else /* CONFIG_DM_DEV_READ_INLINE is enabled */
 
 static inline int dev_read_u32(struct udevice *dev,
@@ -598,6 +610,11 @@
 	return ofnode_read_resource_byname(dev_ofnode(dev), name, res);
 }
 
+static inline u64 dev_translate_address(struct udevice *dev, const fdt32_t *in_addr)
+{
+	return ofnode_translate_address(dev_ofnode(dev), in_addr);
+}
+
 #endif /* CONFIG_DM_DEV_READ_INLINE */
 
 /**
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 3fc2083..07fabc3 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -34,6 +34,7 @@
 	UCLASS_CROS_EC,		/* Chrome OS EC */
 	UCLASS_DISPLAY,		/* Display (e.g. DisplayPort, HDMI) */
 	UCLASS_DMA,		/* Direct Memory Access */
+	UCLASS_EFI,		/* EFI managed devices */
 	UCLASS_ETH,		/* Ethernet device */
 	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
 	UCLASS_FIRMWARE,	/* Firmware */
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 1818849..709f661 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -72,11 +72,11 @@
  * then this will be automatically allocated.
  * @per_child_auto_alloc_size: Each child device (of a parent in this
  * uclass) can hold parent data for the device/uclass. This value is only
- * used as a falback if this member is 0 in the driver.
+ * used as a fallback if this member is 0 in the driver.
  * @per_child_platdata_auto_alloc_size: A bus likes to store information about
  * its children. If non-zero this is the size of this data, to be allocated
  * in the child device's parent_platdata pointer. This value is only used as
- * a falback if this member is 0 in the driver.
+ * a fallback if this member is 0 in the driver.
  * @ops: Uclass operations, providing the consistent interface to devices
  * within the uclass.
  * @flags: Flags for this uclass (DM_UC_...)
diff --git a/include/efi_api.h b/include/efi_api.h
index 584016d..205f8f1 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -84,11 +84,12 @@
 	efi_status_t (EFIAPI *reinstall_protocol_interface)(
 			void *handle, const efi_guid_t *protocol,
 			void *old_interface, void *new_interface);
-	efi_status_t (EFIAPI *uninstall_protocol_interface)(void *handle,
-			const efi_guid_t *protocol, void *protocol_interface);
-	efi_status_t (EFIAPI *handle_protocol)(efi_handle_t,
-					       const efi_guid_t *protocol,
-					       void **protocol_interface);
+	efi_status_t (EFIAPI *uninstall_protocol_interface)(
+			efi_handle_t handle, const efi_guid_t *protocol,
+			void *protocol_interface);
+	efi_status_t (EFIAPI *handle_protocol)(
+			efi_handle_t handle, const efi_guid_t *protocol,
+			void **protocol_interface);
 	void *reserved;
 	efi_status_t (EFIAPI *register_protocol_notify)(
 			const efi_guid_t *protocol, struct efi_event *event,
@@ -113,7 +114,7 @@
 	efi_status_t (EFIAPI *exit)(efi_handle_t handle,
 				    efi_status_t exit_status,
 				    unsigned long exitdata_size, s16 *exitdata);
-	efi_status_t (EFIAPI *unload_image)(void *image_handle);
+	efi_status_t (EFIAPI *unload_image)(efi_handle_t image_handle);
 	efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t, unsigned long);
 
 	efi_status_t (EFIAPI *get_next_monotonic_count)(u64 *count);
@@ -125,8 +126,10 @@
 			efi_handle_t *driver_image_handle,
 			struct efi_device_path *remaining_device_path,
 			bool recursive);
-	efi_status_t (EFIAPI *disconnect_controller)(void *controller_handle,
-			void *driver_image_handle, void *child_handle);
+	efi_status_t (EFIAPI *disconnect_controller)(
+			efi_handle_t controller_handle,
+			efi_handle_t driver_image_handle,
+			efi_handle_t child_handle);
 #define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL  0x00000001
 #define EFI_OPEN_PROTOCOL_GET_PROTOCOL        0x00000002
 #define EFI_OPEN_PROTOCOL_TEST_PROTOCOL       0x00000004
@@ -137,9 +140,10 @@
 			const efi_guid_t *protocol, void **interface,
 			efi_handle_t agent_handle,
 			efi_handle_t controller_handle, u32 attributes);
-	efi_status_t (EFIAPI *close_protocol)(void *handle,
-			const efi_guid_t *protocol, void *agent_handle,
-			void *controller_handle);
+	efi_status_t (EFIAPI *close_protocol)(
+			efi_handle_t handle, const efi_guid_t *protocol,
+			efi_handle_t agent_handle,
+			efi_handle_t controller_handle);
 	efi_status_t(EFIAPI *open_protocol_information)(efi_handle_t handle,
 			const efi_guid_t *protocol,
 			struct efi_open_protocol_info_entry **entry_buffer,
@@ -243,11 +247,11 @@
 	struct efi_table_hdr hdr;
 	unsigned long fw_vendor;   /* physical addr of wchar_t vendor string */
 	u32 fw_revision;
-	unsigned long con_in_handle;
+	efi_handle_t con_in_handle;
 	struct efi_simple_input_interface *con_in;
-	unsigned long con_out_handle;
+	efi_handle_t con_out_handle;
 	struct efi_simple_text_output_protocol *con_out;
-	unsigned long stderr_handle;
+	efi_handle_t stderr_handle;
 	struct efi_simple_text_output_protocol *std_err;
 	struct efi_runtime_services *runtime;
 	struct efi_boot_services *boottime;
@@ -329,12 +333,27 @@
 } __packed;
 
 #define DEVICE_PATH_TYPE_MESSAGING_DEVICE	0x03
+#  define DEVICE_PATH_SUB_TYPE_MSG_ATAPI	0x01
+#  define DEVICE_PATH_SUB_TYPE_MSG_SCSI		0x02
 #  define DEVICE_PATH_SUB_TYPE_MSG_USB		0x05
 #  define DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR	0x0b
 #  define DEVICE_PATH_SUB_TYPE_MSG_USB_CLASS	0x0f
 #  define DEVICE_PATH_SUB_TYPE_MSG_SD		0x1a
 #  define DEVICE_PATH_SUB_TYPE_MSG_MMC		0x1d
 
+struct efi_device_path_atapi {
+	struct efi_device_path dp;
+	u8 primary_secondary;
+	u8 slave_master;
+	u16 logical_unit_number;
+} __packed;
+
+struct efi_device_path_scsi {
+	struct efi_device_path dp;
+	u16 target_id;
+	u16 logical_unit_number;
+} __packed;
+
 struct efi_device_path_usb {
 	struct efi_device_path dp;
 	u8 parent_port_number;
@@ -405,18 +424,26 @@
 	u32 io_align;
 	u8 pad2[4];
 	u64 last_block;
+	/* Added in revision 2 of the protocol */
+	u64 lowest_aligned_lba;
+	u32 logical_blocks_per_physical_block;
+	/* Added in revision 3 of the protocol */
+	u32 optimal_transfer_length_granualarity;
 };
 
+#define EFI_BLOCK_IO_PROTOCOL_REVISION2	0x00020001
+#define EFI_BLOCK_IO_PROTOCOL_REVISION3	0x0002001f
+
 struct efi_block_io {
 	u64 revision;
 	struct efi_block_io_media *media;
 	efi_status_t (EFIAPI *reset)(struct efi_block_io *this,
 			char extended_verification);
 	efi_status_t (EFIAPI *read_blocks)(struct efi_block_io *this,
-			u32 media_id, u64 lba, unsigned long buffer_size,
+			u32 media_id, u64 lba, efi_uintn_t buffer_size,
 			void *buffer);
 	efi_status_t (EFIAPI *write_blocks)(struct efi_block_io *this,
-			u32 media_id, u64 lba, unsigned long buffer_size,
+			u32 media_id, u64 lba, efi_uintn_t buffer_size,
 			void *buffer);
 	efi_status_t (EFIAPI *flush_blocks)(struct efi_block_io *this);
 };
@@ -790,4 +817,26 @@
 	s16 file_name[0];
 };
 
+#define EFI_DRIVER_BINDING_PROTOCOL_GUID \
+	EFI_GUID(0x18a031ab, 0xb443, 0x4d1a,\
+		 0xa5, 0xc0, 0x0c, 0x09, 0x26, 0x1e, 0x9f, 0x71)
+struct efi_driver_binding_protocol {
+	efi_status_t (EFIAPI * supported)(
+			struct efi_driver_binding_protocol *this,
+			efi_handle_t controller_handle,
+			struct efi_device_path *remaining_device_path);
+	efi_status_t (EFIAPI * start)(
+			struct efi_driver_binding_protocol *this,
+			efi_handle_t controller_handle,
+			struct efi_device_path *remaining_device_path);
+	efi_status_t (EFIAPI * stop)(
+			struct efi_driver_binding_protocol *this,
+			efi_handle_t controller_handle,
+			efi_uintn_t number_of_children,
+			efi_handle_t *child_handle_buffer);
+	u32 version;
+	efi_handle_t image_handle;
+	efi_handle_t driver_binding_handle;
+};
+
 #endif
diff --git a/include/efi_driver.h b/include/efi_driver.h
new file mode 100644
index 0000000..2bbe26c
--- /dev/null
+++ b/include/efi_driver.h
@@ -0,0 +1,30 @@
+/*
+ *  EFI application loader
+ *
+ *  Copyright (c) 2017 Heinrich Schuchardt
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _EFI_DRIVER_H
+#define _EFI_DRIVER_H 1
+
+#include <common.h>
+#include <dm.h>
+#include <efi_loader.h>
+
+struct efi_driver_ops {
+	const efi_guid_t *protocol;
+	const efi_guid_t *child_protocol;
+	int (*bind)(efi_handle_t handle, void *interface);
+};
+
+/*
+ * This structure adds internal fields to the driver binding protocol.
+ */
+struct efi_driver_binding_extended_protocol {
+	struct efi_driver_binding_protocol bp;
+	const struct efi_driver_ops *ops;
+};
+
+#endif /* _EFI_DRIVER_H */
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 6185055..21c03c5 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -69,10 +69,11 @@
 	} while(0)
 
 /*
- * Write GUID
+ * Write an indented message with EFI prefix
  */
-#define EFI_PRINT_GUID(txt, guid) ({ \
-	debug("%sEFI: %s %pUl\n", __efi_nesting(), txt, guid); \
+#define EFI_PRINT(format, ...) ({ \
+	debug("%sEFI: " format, __efi_nesting(), \
+		##__VA_ARGS__); \
 	})
 
 extern struct efi_runtime_services efi_runtime_services;
@@ -85,9 +86,13 @@
 
 uint16_t *efi_dp_str(struct efi_device_path *dp);
 
+/* GUID of the EFI_BLOCK_IO_PROTOCOL */
+extern const efi_guid_t efi_block_io_guid;
 extern const efi_guid_t efi_global_variable_guid;
 extern const efi_guid_t efi_guid_console_control;
 extern const efi_guid_t efi_guid_device_path;
+/* GUID of the EFI_DRIVER_BINDING_PROTOCOL */
+extern const efi_guid_t efi_guid_driver_binding_protocol;
 extern const efi_guid_t efi_guid_loaded_image;
 extern const efi_guid_t efi_guid_device_path_to_text_protocol;
 extern const efi_guid_t efi_simple_file_system_protocol_guid;
@@ -97,14 +102,27 @@
 extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop;
 
 /*
+ * When a protocol is opened a open protocol info entry is created.
+ * These are maintained in a list.
+ */
+struct efi_open_protocol_info_item {
+	/* Link to the list of open protocol info entries of a protocol */
+	struct list_head link;
+	struct efi_open_protocol_info_entry info;
+};
+
+/*
  * When the UEFI payload wants to open a protocol on an object to get its
  * interface (usually a struct with callback functions), this struct maps the
- * protocol GUID to the respective protocol interface */
+ * protocol GUID to the respective protocol interface
+ */
 struct efi_handler {
 	/* Link to the list of protocols of a handle */
 	struct list_head link;
 	const efi_guid_t *guid;
 	void *protocol_interface;
+	/* Link to the list of open protocol info items */
+	struct list_head open_infos;
 };
 
 /*
@@ -156,6 +174,10 @@
 int efi_console_register(void);
 /* Called by bootefi to make all disk storage accessible as EFI objects */
 int efi_disk_register(void);
+/* Create handles and protocols for the partitions of a block device */
+int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
+			       const char *if_typename, int diskid,
+			       const char *pdevname);
 /* Called by bootefi to make GOP (graphical) interface available */
 int efi_gop_register(void);
 /* Called by bootefi to make the network interface available */
@@ -189,23 +211,25 @@
 /* Add a new object to the object list. */
 void efi_add_handle(struct efi_object *obj);
 /* Create handle */
-efi_status_t efi_create_handle(void **handle);
+efi_status_t efi_create_handle(efi_handle_t *handle);
 /* Delete handle */
 void efi_delete_handle(struct efi_object *obj);
 /* Call this to validate a handle and find the EFI object for it */
-struct efi_object *efi_search_obj(const void *handle);
+struct efi_object *efi_search_obj(const efi_handle_t handle);
 /* Find a protocol on a handle */
-efi_status_t efi_search_protocol(const void *handle,
+efi_status_t efi_search_protocol(const efi_handle_t handle,
 				 const efi_guid_t *protocol_guid,
 				 struct efi_handler **handler);
 /* Install new protocol on a handle */
-efi_status_t efi_add_protocol(const void *handle, const efi_guid_t *protocol,
+efi_status_t efi_add_protocol(const efi_handle_t handle,
+			      const efi_guid_t *protocol,
 			      void *protocol_interface);
 /* Delete protocol from a handle */
-efi_status_t efi_remove_protocol(const void *handle, const efi_guid_t *protocol,
+efi_status_t efi_remove_protocol(const efi_handle_t handle,
+				 const efi_guid_t *protocol,
 				 void *protocol_interface);
 /* Delete all protocols from a handle */
-efi_status_t efi_remove_all_protocols(const void *handle);
+efi_status_t efi_remove_all_protocols(const efi_handle_t handle);
 /* Call this to create an event */
 efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
 			      void (EFIAPI *notify_function) (
@@ -216,7 +240,7 @@
 efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type,
 			   uint64_t trigger_time);
 /* Call this to signal an event */
-void efi_signal_event(struct efi_event *event);
+void efi_signal_event(struct efi_event *event, bool check_tpl);
 
 /* open file system: */
 struct efi_simple_file_system_protocol *efi_simple_file_system(
@@ -247,6 +271,8 @@
 /* Adds a range into the EFI memory map */
 uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
 			    bool overlap_only_ram);
+/* Called by board init to initialize the EFI drivers */
+int efi_driver_init(void);
 /* Called by board init to initialize the EFI memory map */
 int efi_memory_init(void);
 /* Adds new or overrides configuration table entry to the system table */
@@ -280,15 +306,20 @@
 
 struct efi_device_path *efi_dp_from_dev(struct udevice *dev);
 struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part);
+/* Create a device node for a block device partition. */
+struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part);
 struct efi_device_path *efi_dp_from_file(struct blk_desc *desc, int part,
 					 const char *path);
 struct efi_device_path *efi_dp_from_eth(void);
 struct efi_device_path *efi_dp_from_mem(uint32_t mem_type,
 					uint64_t start_address,
 					uint64_t end_address);
-void efi_dp_split_file_path(struct efi_device_path *full_path,
-			    struct efi_device_path **device_path,
-			    struct efi_device_path **file_path);
+/* Determine the last device path node that is not the end node. */
+const struct efi_device_path *efi_dp_last_node(
+			const struct efi_device_path *dp);
+efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
+				    struct efi_device_path **device_path,
+				    struct efi_device_path **file_path);
 
 #define EFI_DP_TYPE(_dp, _type, _subtype) \
 	(((_dp)->type == DEVICE_PATH_TYPE_##_type) && \
diff --git a/include/efi_selftest.h b/include/efi_selftest.h
index be5ba4b..08dd8e4 100644
--- a/include/efi_selftest.h
+++ b/include/efi_selftest.h
@@ -19,13 +19,19 @@
 #define EFI_ST_FAILURE 1
 
 /*
+ * Prints a message.
+ */
+#define efi_st_printf(...) \
+	(efi_st_printc(-1, __VA_ARGS__))
+
+/*
  * Prints an error message.
  *
  * @...	format string followed by fields to print
  */
 #define efi_st_error(...) \
-	(efi_st_printf("%s(%u):\nERROR: ", __FILE__, __LINE__), \
-	efi_st_printf(__VA_ARGS__)) \
+	(efi_st_printc(EFI_LIGHTRED, "%s(%u):\nERROR: ", __FILE__, __LINE__), \
+	efi_st_printc(EFI_LIGHTRED, __VA_ARGS__))
 
 /*
  * Prints a TODO message.
@@ -33,8 +39,8 @@
  * @...	format string followed by fields to print
  */
 #define efi_st_todo(...) \
-	(efi_st_printf("%s(%u):\nTODO: ", __FILE__, __LINE__), \
-	efi_st_printf(__VA_ARGS__)) \
+	(efi_st_printc(EFI_YELLOW, "%s(%u):\nTODO: ", __FILE__, __LINE__), \
+	efi_st_printc(EFI_YELLOW, __VA_ARGS__)) \
 
 /*
  * A test may be setup and executed at boottime,
@@ -61,14 +67,15 @@
 void efi_st_exit_boot_services(void);
 
 /*
- * Print a pointer to an u16 string
+ * Print a colored message
  *
- * @pointer: pointer
- * @buf: pointer to buffer address
- * on return position of terminating zero word
+ * @color	color, see constants in efi_api.h, use -1 for no color
+ * @fmt		printf format
+ * @...		arguments to be printed
+ *		on return position of terminating zero word
  */
-void efi_st_printf(const char *fmt, ...)
-		 __attribute__ ((format (__printf__, 1, 2)));
+void efi_st_printc(int color, const char *fmt, ...)
+		 __attribute__ ((format (__printf__, 2, 3)));
 
 /*
  * Compare memory.
diff --git a/include/fat.h b/include/fat.h
index bdeda95..fa95644 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -13,7 +13,6 @@
 #include <asm/byteorder.h>
 #include <fs.h>
 
-#define CONFIG_SUPPORT_VFAT
 /* Maximum Long File Name length supported here is 128 UTF-16 code units */
 #define VFAT_MAXLEN_BYTES	256 /* Maximum LFN buffer in bytes */
 #define VFAT_MAXSEQ		9   /* Up to 9 of 13 2-byte UTF-16 entries */
diff --git a/lib/Makefile b/lib/Makefile
index 8cd779f..0db41c1 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -8,6 +8,7 @@
 ifndef CONFIG_SPL_BUILD
 
 obj-$(CONFIG_EFI) += efi/
+obj-$(CONFIG_EFI_LOADER) += efi_driver/
 obj-$(CONFIG_EFI_LOADER) += efi_loader/
 obj-$(CONFIG_EFI_LOADER) += efi_selftest/
 obj-$(CONFIG_LZMA) += lzma/
diff --git a/lib/efi_driver/Makefile b/lib/efi_driver/Makefile
new file mode 100644
index 0000000..e35529a
--- /dev/null
+++ b/lib/efi_driver/Makefile
@@ -0,0 +1,13 @@
+#
+# (C) Copyright 2017 Heinrich Schuchardt
+#
+#  SPDX-License-Identifier:     GPL-2.0+
+#
+
+# This file only gets included with CONFIG_EFI_LOADER set, so all
+# object inclusion implicitly depends on it
+
+obj-y += efi_uclass.o
+ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy)
+obj-y += efi_block_device.o
+endif
diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c
new file mode 100644
index 0000000..d9d2b14
--- /dev/null
+++ b/lib/efi_driver/efi_block_device.c
@@ -0,0 +1,210 @@
+/*
+ *  EFI block driver
+ *
+ *  Copyright (c) 2017 Heinrich Schuchardt
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ *
+ * The EFI uclass creates a handle for this driver and installs the
+ * driver binding protocol on it.
+ *
+ * The EFI block driver binds to controllers implementing the block io
+ * protocol.
+ *
+ * When the bind function of the EFI block driver is called it creates a
+ * new U-Boot block device. It installs child handles for all partitions and
+ * installs the simple file protocol on these.
+ *
+ * The read and write functions of the EFI block driver delegate calls to the
+ * controller that it is bound to.
+ *
+ * A usage example is as following:
+ *
+ * U-Boot loads the iPXE snp.efi executable. iPXE connects an iSCSI drive and
+ * exposes a handle with the block IO protocol. It calls ConnectController.
+ *
+ * Now the EFI block driver installs the partitions with the simple file
+ * protocol.
+ *
+ * iPXE uses the simple file protocol to load Grub or the Linux Kernel.
+ */
+
+#include <efi_driver.h>
+#include <dm/device-internal.h>
+#include <dm/root.h>
+
+/*
+ * EFI attributes of the udevice handled by this driver.
+ *
+ * handle	handle of the controller on which this driver is installed
+ * io		block io protocol proxied by this driver
+ */
+struct efi_blk_priv {
+	efi_handle_t		handle;
+	struct efi_block_io	*io;
+};
+
+/*
+ * Read from block device
+ *
+ * @dev		device
+ * @blknr	first block to be read
+ * @blkcnt	number of blocks to read
+ * @buffer	output buffer
+ * @return	number of blocks transferred
+ */
+static ulong efi_bl_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+			 void *buffer)
+{
+	struct efi_blk_priv *priv = dev->priv;
+	struct efi_block_io *io = priv->io;
+	efi_status_t ret;
+
+	EFI_PRINT("%s: read '%s', from block " LBAFU ", " LBAFU " blocks\n",
+		  __func__, dev->name, blknr, blkcnt);
+	ret = EFI_CALL(io->read_blocks(
+				io, io->media->media_id, (u64)blknr,
+				(efi_uintn_t)blkcnt *
+				(efi_uintn_t)io->media->block_size, buffer));
+	EFI_PRINT("%s: r = %u\n", __func__,
+		  (unsigned int)(ret & ~EFI_ERROR_MASK));
+	if (ret != EFI_SUCCESS)
+		return 0;
+	return blkcnt;
+}
+
+/*
+ * Write to block device
+ *
+ * @dev		device
+ * @blknr	first block to be write
+ * @blkcnt	number of blocks to write
+ * @buffer	input buffer
+ * @return	number of blocks transferred
+ */
+static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+			  const void *buffer)
+{
+	struct efi_blk_priv *priv = dev->priv;
+	struct efi_block_io *io = priv->io;
+	efi_status_t ret;
+
+	EFI_PRINT("%s: write '%s', from block " LBAFU ", " LBAFU " blocks\n",
+		  __func__, dev->name, blknr, blkcnt);
+	ret = EFI_CALL(io->write_blocks(
+				io, io->media->media_id, (u64)blknr,
+				(efi_uintn_t)blkcnt *
+				(efi_uintn_t)io->media->block_size,
+				(void *)buffer));
+	EFI_PRINT("%s: r = %u\n", __func__,
+		  (unsigned int)(ret & ~EFI_ERROR_MASK));
+	if (ret != EFI_SUCCESS)
+		return 0;
+	return blkcnt;
+}
+
+/*
+ * Create partions for the block device.
+ *
+ * @handle	EFI handle of the block device
+ * @dev		udevice of the block device
+ */
+static int efi_bl_bind_partitions(efi_handle_t handle, struct udevice *dev)
+{
+	struct blk_desc *desc;
+	const char *if_typename;
+
+	desc = dev_get_uclass_platdata(dev);
+	if_typename = blk_get_if_type_name(desc->if_type);
+
+	return efi_disk_create_partitions(handle, desc, if_typename,
+					  desc->devnum, dev->name);
+}
+
+/*
+ * Create a block device for a handle
+ *
+ * @handle	handle
+ * @interface	block io protocol
+ * @return	0 = success
+ */
+static int efi_bl_bind(efi_handle_t handle, void *interface)
+{
+	struct udevice *bdev, *parent = dm_root();
+	int ret, devnum;
+	char *name;
+	struct efi_object *obj = efi_search_obj(handle);
+	struct efi_block_io *io = interface;
+	int disks;
+	struct efi_blk_priv *priv;
+
+	EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io);
+
+	if (!obj)
+		return -ENOENT;
+
+	devnum = blk_find_max_devnum(IF_TYPE_EFI);
+	if (devnum == -ENODEV)
+		devnum = 0;
+	else if (devnum < 0)
+		return devnum;
+
+	name = calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */
+	if (!name)
+		return -ENOMEM;
+	sprintf(name, "efiblk#%d", devnum);
+
+	/* Create driver model udevice for the EFI block io device */
+	ret = blk_create_device(parent, "efi_blk", name, IF_TYPE_EFI, devnum,
+				io->media->block_size,
+				(lbaint_t)io->media->last_block, &bdev);
+	if (ret)
+		return ret;
+	if (!bdev)
+		return -ENOENT;
+	/* Allocate priv */
+	ret = device_probe(bdev);
+	if (ret)
+		return ret;
+	EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
+
+	priv = bdev->priv;
+	priv->handle = handle;
+	priv->io = interface;
+
+	ret = blk_prepare_device(bdev);
+
+	/* Create handles for the partions of the block device */
+	disks = efi_bl_bind_partitions(handle, bdev);
+	EFI_PRINT("Found %d partitions\n", disks);
+
+	return 0;
+}
+
+/* Block device driver operators */
+static const struct blk_ops efi_blk_ops = {
+	.read	= efi_bl_read,
+	.write	= efi_bl_write,
+};
+
+/* Identify as block device driver */
+U_BOOT_DRIVER(efi_blk) = {
+	.name			= "efi_blk",
+	.id			= UCLASS_BLK,
+	.ops			= &efi_blk_ops,
+	.priv_auto_alloc_size	= sizeof(struct efi_blk_priv),
+};
+
+/* EFI driver operators */
+static const struct efi_driver_ops driver_ops = {
+	.protocol	= &efi_block_io_guid,
+	.child_protocol = &efi_block_io_guid,
+	.bind		= efi_bl_bind,
+};
+
+/* Identify as EFI driver */
+U_BOOT_DRIVER(efi_block) = {
+	.name		= "EFI block driver",
+	.id		= UCLASS_EFI,
+	.ops		= &driver_ops,
+};
diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c
new file mode 100644
index 0000000..90797f9
--- /dev/null
+++ b/lib/efi_driver/efi_uclass.c
@@ -0,0 +1,330 @@
+/*
+ *  Uclass for EFI drivers
+ *
+ *  Copyright (c) 2017 Heinrich Schuchardt
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ *
+ * For each EFI driver the uclass
+ * - creates a handle
+ * - installs the driver binding protocol
+ *
+ * The uclass provides the bind, start, and stop entry points for the driver
+ * binding protocol.
+ *
+ * In bind() and stop() it checks if the controller implements the protocol
+ * supported by the EFI driver. In the start() function it calls the bind()
+ * function of the EFI driver. In the stop() function it destroys the child
+ * controllers.
+ */
+
+#include <efi_driver.h>
+
+/*
+ * Check node type. We do not support partitions as controller handles.
+ *
+ * @handle	handle to be checked
+ * @return	status code
+ */
+static efi_status_t check_node_type(efi_handle_t handle)
+{
+	efi_status_t r, ret = EFI_SUCCESS;
+	const struct efi_device_path *dp;
+
+	/* Open the device path protocol */
+	r = EFI_CALL(systab.boottime->open_protocol(
+			handle, &efi_guid_device_path, (void **)&dp,
+			NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+	if (r == EFI_SUCCESS && dp) {
+		/* Get the last node */
+		const struct efi_device_path *node = efi_dp_last_node(dp);
+		/* We do not support partitions as controller */
+		if (!node || node->type == DEVICE_PATH_TYPE_MEDIA_DEVICE)
+			ret = EFI_UNSUPPORTED;
+	}
+	return ret;
+}
+
+/*
+ * Check if the driver supports the controller.
+ *
+ * @this			driver binding protocol
+ * @controller_handle		handle of the controller
+ * @remaining_device_path	path specifying the child controller
+ * @return			status code
+ */
+static efi_status_t EFIAPI efi_uc_supported(
+		struct efi_driver_binding_protocol *this,
+		efi_handle_t controller_handle,
+		struct efi_device_path *remaining_device_path)
+{
+	efi_status_t r, ret;
+	void *interface;
+	struct efi_driver_binding_extended_protocol *bp =
+			(struct efi_driver_binding_extended_protocol *)this;
+
+	EFI_ENTRY("%p, %p, %ls", this, controller_handle,
+		  efi_dp_str(remaining_device_path));
+
+	ret = EFI_CALL(systab.boottime->open_protocol(
+			controller_handle, bp->ops->protocol,
+			&interface, this->driver_binding_handle,
+			controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER));
+	switch (ret) {
+	case EFI_ACCESS_DENIED:
+	case EFI_ALREADY_STARTED:
+		goto out;
+	case EFI_SUCCESS:
+		break;
+	default:
+		ret = EFI_UNSUPPORTED;
+		goto out;
+	}
+
+	ret = check_node_type(controller_handle);
+
+	r = EFI_CALL(systab.boottime->close_protocol(
+				controller_handle, bp->ops->protocol,
+				this->driver_binding_handle,
+				controller_handle));
+	if (r != EFI_SUCCESS)
+		ret = EFI_UNSUPPORTED;
+out:
+	return EFI_EXIT(ret);
+}
+
+/*
+ * Create child controllers and attach driver.
+ *
+ * @this			driver binding protocol
+ * @controller_handle		handle of the controller
+ * @remaining_device_path	path specifying the child controller
+ * @return			status code
+ */
+static efi_status_t EFIAPI efi_uc_start(
+		struct efi_driver_binding_protocol *this,
+		efi_handle_t controller_handle,
+		struct efi_device_path *remaining_device_path)
+{
+	efi_status_t r, ret;
+	void *interface = NULL;
+	struct efi_driver_binding_extended_protocol *bp =
+			(struct efi_driver_binding_extended_protocol *)this;
+
+	EFI_ENTRY("%p, %pUl, %ls", this, controller_handle,
+		  efi_dp_str(remaining_device_path));
+
+	/* Attach driver to controller */
+	ret = EFI_CALL(systab.boottime->open_protocol(
+			controller_handle, bp->ops->protocol,
+			&interface, this->driver_binding_handle,
+			controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER));
+	switch (ret) {
+	case EFI_ACCESS_DENIED:
+	case EFI_ALREADY_STARTED:
+		goto out;
+	case EFI_SUCCESS:
+		break;
+	default:
+		ret =  EFI_UNSUPPORTED;
+		goto out;
+	}
+	ret = check_node_type(controller_handle);
+	if (ret != EFI_SUCCESS) {
+		r = EFI_CALL(systab.boottime->close_protocol(
+				controller_handle, bp->ops->protocol,
+				this->driver_binding_handle,
+				controller_handle));
+		if (r != EFI_SUCCESS)
+			EFI_PRINT("Failure to close handle\n");
+		goto out;
+	}
+
+	/* TODO: driver specific stuff */
+	bp->ops->bind(controller_handle, interface);
+
+out:
+	return EFI_EXIT(ret);
+}
+
+/*
+ * Remove a single child controller from the parent controller.
+ *
+ * @controller_handle	parent controller
+ * @child_handle	child controller
+ * @return		status code
+ */
+static efi_status_t disconnect_child(efi_handle_t controller_handle,
+				     efi_handle_t child_handle)
+{
+	efi_status_t ret;
+	efi_guid_t *guid_controller = NULL;
+	efi_guid_t *guid_child_controller = NULL;
+
+	ret = EFI_CALL(systab.boottime->close_protocol(
+				controller_handle, guid_controller,
+				child_handle, child_handle));
+	if (ret != EFI_SUCCESS) {
+		EFI_PRINT("Cannot close protocol\n");
+		return ret;
+	}
+	ret = EFI_CALL(systab.boottime->uninstall_protocol_interface(
+				child_handle, guid_child_controller, NULL));
+	if (ret != EFI_SUCCESS) {
+		EFI_PRINT("Cannot uninstall protocol interface\n");
+		return ret;
+	}
+	return ret;
+}
+
+/*
+ * Remove child controllers and disconnect the controller.
+ *
+ * @this			driver binding protocol
+ * @controller_handle		handle of the controller
+ * @number_of_children		number of child controllers to remove
+ * @child_handle_buffer		handles of the child controllers to remove
+ * @return			status code
+ */
+static efi_status_t EFIAPI efi_uc_stop(
+		struct efi_driver_binding_protocol *this,
+		efi_handle_t controller_handle,
+		size_t number_of_children,
+		efi_handle_t *child_handle_buffer)
+{
+	efi_status_t ret;
+	efi_uintn_t count;
+	struct efi_open_protocol_info_entry *entry_buffer;
+	efi_guid_t *guid_controller = NULL;
+
+	EFI_ENTRY("%p, %pUl, %zu, %p", this, controller_handle,
+		  number_of_children, child_handle_buffer);
+
+	/* Destroy provided child controllers */
+	if (number_of_children) {
+		efi_uintn_t i;
+
+		for (i = 0; i < number_of_children; ++i) {
+			ret = disconnect_child(controller_handle,
+					       child_handle_buffer[i]);
+			if (ret != EFI_SUCCESS)
+				return ret;
+		}
+		return EFI_SUCCESS;
+	}
+
+	/* Destroy all children */
+	ret = EFI_CALL(systab.boottime->open_protocol_information(
+					controller_handle, guid_controller,
+					&entry_buffer, &count));
+	if (ret != EFI_SUCCESS)
+		goto out;
+	while (count) {
+		if (entry_buffer[--count].attributes &
+		    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+			ret = disconnect_child(
+					controller_handle,
+					entry_buffer[count].agent_handle);
+			if (ret != EFI_SUCCESS)
+				goto out;
+		}
+	}
+	ret = EFI_CALL(systab.boottime->free_pool(entry_buffer));
+	if (ret != EFI_SUCCESS)
+		printf("%s(%u) %s: ERROR: Cannot free pool\n",
+		       __FILE__, __LINE__, __func__);
+
+	/* Detach driver from controller */
+	ret = EFI_CALL(systab.boottime->close_protocol(
+			controller_handle, guid_controller,
+			this->driver_binding_handle, controller_handle));
+out:
+	return EFI_EXIT(ret);
+}
+
+static efi_status_t efi_add_driver(struct driver *drv)
+{
+	efi_status_t ret;
+	const struct efi_driver_ops *ops = drv->ops;
+	struct efi_driver_binding_extended_protocol *bp;
+
+	debug("EFI: Adding driver '%s'\n", drv->name);
+	if (!ops->protocol) {
+		printf("EFI: ERROR: protocol GUID missing for driver '%s'\n",
+		       drv->name);
+		return EFI_INVALID_PARAMETER;
+	}
+	bp = calloc(1, sizeof(struct efi_driver_binding_extended_protocol));
+	if (!bp)
+		return EFI_OUT_OF_RESOURCES;
+
+	bp->bp.supported = efi_uc_supported;
+	bp->bp.start = efi_uc_start;
+	bp->bp.stop = efi_uc_stop;
+	bp->bp.version = 0xffffffff;
+	bp->ops = drv->ops;
+
+	ret = efi_create_handle(&bp->bp.driver_binding_handle);
+	if (ret != EFI_SUCCESS) {
+		free(bp);
+		goto out;
+	}
+	bp->bp.image_handle = bp->bp.driver_binding_handle;
+	ret = efi_add_protocol(bp->bp.driver_binding_handle,
+			       &efi_guid_driver_binding_protocol, bp);
+	if (ret != EFI_SUCCESS) {
+		efi_delete_handle(bp->bp.driver_binding_handle);
+		free(bp);
+		goto out;
+	}
+out:
+	return ret;
+}
+
+/*
+ * Initialize the EFI drivers.
+ * Called by board_init_r().
+ *
+ * @return	0 = success, any other value will stop further execution
+ */
+int efi_driver_init(void)
+{
+	struct driver *drv;
+	int ret = 0;
+
+	/* Save 'gd' pointer */
+	efi_save_gd();
+
+	debug("EFI: Initializing EFI driver framework\n");
+	for (drv = ll_entry_start(struct driver, driver);
+	     drv < ll_entry_end(struct driver, driver); ++drv) {
+		if (drv->id == UCLASS_EFI) {
+			ret = efi_add_driver(drv);
+			if (ret) {
+				printf("EFI: ERROR: failed to add driver %s\n",
+				       drv->name);
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
+static int efi_uc_init(struct uclass *class)
+{
+	printf("EFI: Initializing UCLASS_EFI\n");
+	return 0;
+}
+
+static int efi_uc_destroy(struct uclass *class)
+{
+	printf("Destroying  UCLASS_EFI\n");
+	return 0;
+}
+
+UCLASS_DRIVER(efi) = {
+	.name		= "efi",
+	.id		= UCLASS_EFI,
+	.init		= efi_uc_init,
+	.destroy	= efi_uc_destroy,
+};
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index b90bd0b..39d8511 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -56,6 +56,14 @@
 
 static int entry_count;
 static int nesting_level;
+/* GUID of the EFI_DRIVER_BINDING_PROTOCOL */
+const efi_guid_t efi_guid_driver_binding_protocol =
+			EFI_DRIVER_BINDING_PROTOCOL_GUID;
+
+static efi_status_t EFIAPI efi_disconnect_controller(
+					efi_handle_t controller_handle,
+					efi_handle_t driver_image_handle,
+					efi_handle_t child_handle);
 
 /* Called on every callback entry */
 int __efi_entry_check(void)
@@ -141,13 +149,14 @@
  * For the SignalEvent service see efi_signal_event_ext.
  *
  * @event	event to signal
+ * @check_tpl	check the TPL level
  */
-void efi_signal_event(struct efi_event *event)
+void efi_signal_event(struct efi_event *event, bool check_tpl)
 {
 	if (event->notify_function) {
 		event->is_queued = true;
 		/* Check TPL */
-		if (efi_tpl >= event->notify_tpl)
+		if (check_tpl && efi_tpl >= event->notify_tpl)
 			return;
 		EFI_CALL_VOID(event->notify_function(event,
 						     event->notify_context));
@@ -344,7 +353,7 @@
  * @handle	new handle
  * @return	status code
  */
-efi_status_t efi_create_handle(void **handle)
+efi_status_t efi_create_handle(efi_handle_t *handle)
 {
 	struct efi_object *obj;
 	efi_status_t r;
@@ -367,7 +376,7 @@
  * @handler		reference to the protocol
  * @return		status code
  */
-efi_status_t efi_search_protocol(const void *handle,
+efi_status_t efi_search_protocol(const efi_handle_t handle,
 				 const efi_guid_t *protocol_guid,
 				 struct efi_handler **handler)
 {
@@ -400,7 +409,8 @@
  * @protocol_interface		interface of the protocol implementation
  * @return			status code
  */
-efi_status_t efi_remove_protocol(const void *handle, const efi_guid_t *protocol,
+efi_status_t efi_remove_protocol(const efi_handle_t handle,
+				 const efi_guid_t *protocol,
 				 void *protocol_interface)
 {
 	struct efi_handler *handler;
@@ -422,21 +432,18 @@
  * @handle	handle from which the protocols shall be deleted
  * @return	status code
  */
-efi_status_t efi_remove_all_protocols(const void *handle)
+efi_status_t efi_remove_all_protocols(const efi_handle_t handle)
 {
 	struct efi_object *efiobj;
-	struct list_head *lhandle;
-	struct list_head *pos;
+	struct efi_handler *protocol;
+	struct efi_handler *pos;
 
 	efiobj = efi_search_obj(handle);
 	if (!efiobj)
 		return EFI_INVALID_PARAMETER;
-	list_for_each_safe(lhandle, pos, &efiobj->protocols) {
-		struct efi_handler *protocol;
+	list_for_each_entry_safe(protocol, pos, &efiobj->protocols, link) {
 		efi_status_t ret;
 
-		protocol = list_entry(lhandle, struct efi_handler, link);
-
 		ret = efi_remove_protocol(handle, protocol->guid,
 					  protocol->protocol_interface);
 		if (ret != EFI_SUCCESS)
@@ -559,7 +566,7 @@
 		if (!efi_events[i].type)
 			continue;
 		if (efi_events[i].is_queued)
-			efi_signal_event(&efi_events[i]);
+			efi_signal_event(&efi_events[i], true);
 		if (!(efi_events[i].type & EVT_TIMER) ||
 		    now < efi_events[i].trigger_next)
 			continue;
@@ -575,7 +582,7 @@
 			continue;
 		}
 		efi_events[i].is_signaled = true;
-		efi_signal_event(&efi_events[i]);
+		efi_signal_event(&efi_events[i], true);
 	}
 	WATCHDOG_RESET();
 }
@@ -684,7 +691,7 @@
 		if (!event[i]->type || event[i]->type & EVT_NOTIFY_SIGNAL)
 			return EFI_EXIT(EFI_INVALID_PARAMETER);
 		if (!event[i]->is_signaled)
-			efi_signal_event(event[i]);
+			efi_signal_event(event[i], true);
 	}
 
 	/* Wait for signal */
@@ -734,7 +741,7 @@
 			break;
 		event->is_signaled = true;
 		if (event->type & EVT_NOTIFY_SIGNAL)
-			efi_signal_event(event);
+			efi_signal_event(event, true);
 		break;
 	}
 	return EFI_EXIT(EFI_SUCCESS);
@@ -791,7 +798,7 @@
 		if (!event->type || event->type & EVT_NOTIFY_SIGNAL)
 			break;
 		if (!event->is_signaled)
-			efi_signal_event(event);
+			efi_signal_event(event, true);
 		if (event->is_signaled)
 			return EFI_EXIT(EFI_SUCCESS);
 		return EFI_EXIT(EFI_NOT_READY);
@@ -805,7 +812,7 @@
  * @handle	handle to find
  * @return	EFI object
  */
-struct efi_object *efi_search_obj(const void *handle)
+struct efi_object *efi_search_obj(const efi_handle_t handle)
 {
 	struct efi_object *efiobj;
 
@@ -818,6 +825,40 @@
 }
 
 /*
+ * Create open protocol info entry and add it to a protocol.
+ *
+ * @handler	handler of a protocol
+ * @return	open protocol info entry
+ */
+static struct efi_open_protocol_info_entry *efi_create_open_info(
+			struct efi_handler *handler)
+{
+	struct efi_open_protocol_info_item *item;
+
+	item = calloc(1, sizeof(struct efi_open_protocol_info_item));
+	if (!item)
+		return NULL;
+	/* Append the item to the open protocol info list. */
+	list_add_tail(&item->link, &handler->open_infos);
+
+	return &item->info;
+}
+
+/*
+ * Remove an open protocol info entry from a protocol.
+ *
+ * @handler	handler of a protocol
+ * @return	status code
+ */
+static efi_status_t efi_delete_open_info(
+			struct efi_open_protocol_info_item *item)
+{
+	list_del(&item->link);
+	free(item);
+	return EFI_SUCCESS;
+}
+
+/*
  * Install new protocol on a handle.
  *
  * @handle			handle on which the protocol shall be installed
@@ -825,7 +866,8 @@
  * @protocol_interface		interface of the protocol implementation
  * @return			status code
  */
-efi_status_t efi_add_protocol(const void *handle, const efi_guid_t *protocol,
+efi_status_t efi_add_protocol(const efi_handle_t handle,
+			      const efi_guid_t *protocol,
 			      void *protocol_interface)
 {
 	struct efi_object *efiobj;
@@ -843,7 +885,10 @@
 		return EFI_OUT_OF_RESOURCES;
 	handler->guid = protocol;
 	handler->protocol_interface = protocol_interface;
+	INIT_LIST_HEAD(&handler->open_infos);
 	list_add_tail(&handler->link, &efiobj->protocols);
+	if (!guidcmp(&efi_guid_device_path, protocol))
+		EFI_PRINT("installed device path '%pD'\n", protocol_interface);
 	return EFI_SUCCESS;
 }
 
@@ -907,9 +952,9 @@
  * @new_interface		interface to be installed
  * @return			status code
  */
-static efi_status_t EFIAPI efi_reinstall_protocol_interface(void *handle,
-			const efi_guid_t *protocol, void *old_interface,
-			void *new_interface)
+static efi_status_t EFIAPI efi_reinstall_protocol_interface(
+			efi_handle_t handle, const efi_guid_t *protocol,
+			void *old_interface, void *new_interface)
 {
 	EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface,
 		  new_interface);
@@ -917,6 +962,109 @@
 }
 
 /*
+ * Get all drivers associated to a controller.
+ * The allocated buffer has to be freed with free().
+ *
+ * @efiobj			handle of the controller
+ * @protocol			protocol guid (optional)
+ * @number_of_drivers		number of child controllers
+ * @driver_handle_buffer	handles of the the drivers
+ * @return			status code
+ */
+static efi_status_t efi_get_drivers(struct efi_object *efiobj,
+				    const efi_guid_t *protocol,
+				    efi_uintn_t *number_of_drivers,
+				    efi_handle_t **driver_handle_buffer)
+{
+	struct efi_handler *handler;
+	struct efi_open_protocol_info_item *item;
+	efi_uintn_t count = 0, i;
+	bool duplicate;
+
+	/* Count all driver associations */
+	list_for_each_entry(handler, &efiobj->protocols, link) {
+		if (protocol && guidcmp(handler->guid, protocol))
+			continue;
+		list_for_each_entry(item, &handler->open_infos, link) {
+			if (item->info.attributes &
+			    EFI_OPEN_PROTOCOL_BY_DRIVER)
+				++count;
+		}
+	}
+	/*
+	 * Create buffer. In case of duplicate driver assignments the buffer
+	 * will be too large. But that does not harm.
+	 */
+	*number_of_drivers = 0;
+	*driver_handle_buffer = calloc(count, sizeof(efi_handle_t));
+	if (!*driver_handle_buffer)
+		return EFI_OUT_OF_RESOURCES;
+	/* Collect unique driver handles */
+	list_for_each_entry(handler, &efiobj->protocols, link) {
+		if (protocol && guidcmp(handler->guid, protocol))
+			continue;
+		list_for_each_entry(item, &handler->open_infos, link) {
+			if (item->info.attributes &
+			    EFI_OPEN_PROTOCOL_BY_DRIVER) {
+				/* Check this is a new driver */
+				duplicate = false;
+				for (i = 0; i < *number_of_drivers; ++i) {
+					if ((*driver_handle_buffer)[i] ==
+					    item->info.agent_handle)
+						duplicate = true;
+				}
+				/* Copy handle to buffer */
+				if (!duplicate) {
+					i = (*number_of_drivers)++;
+					(*driver_handle_buffer)[i] =
+						item->info.agent_handle;
+				}
+			}
+		}
+	}
+	return EFI_SUCCESS;
+}
+
+/*
+ * Disconnect all drivers from a controller.
+ *
+ * This function implements the DisconnectController service.
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @efiobj		handle of the controller
+ * @protocol		protocol guid (optional)
+ * @child_handle	handle of the child to destroy
+ * @return		status code
+ */
+static efi_status_t efi_disconnect_all_drivers(
+				struct efi_object *efiobj,
+				const efi_guid_t *protocol,
+				efi_handle_t child_handle)
+{
+	efi_uintn_t number_of_drivers;
+	efi_handle_t *driver_handle_buffer;
+	efi_status_t r, ret;
+
+	ret = efi_get_drivers(efiobj, protocol, &number_of_drivers,
+			      &driver_handle_buffer);
+	if (ret != EFI_SUCCESS)
+		return ret;
+
+	ret = EFI_NOT_FOUND;
+	while (number_of_drivers) {
+		r = EFI_CALL(efi_disconnect_controller(
+				efiobj->handle,
+				driver_handle_buffer[--number_of_drivers],
+				child_handle));
+		if (r == EFI_SUCCESS)
+			ret = r;
+	}
+	free(driver_handle_buffer);
+	return ret;
+}
+
+/*
  * Uninstall protocol interface.
  *
  * This function implements the UninstallProtocolInterface service.
@@ -929,29 +1077,46 @@
  * @return			status code
  */
 static efi_status_t EFIAPI efi_uninstall_protocol_interface(
-				void *handle, const efi_guid_t *protocol,
+				efi_handle_t handle, const efi_guid_t *protocol,
 				void *protocol_interface)
 {
+	struct efi_object *efiobj;
 	struct efi_handler *handler;
+	struct efi_open_protocol_info_item *item;
+	struct efi_open_protocol_info_item *pos;
 	efi_status_t r;
 
 	EFI_ENTRY("%p, %pUl, %p", handle, protocol, protocol_interface);
 
-	if (!handle || !protocol) {
+	/* Check handle */
+	efiobj = efi_search_obj(handle);
+	if (!efiobj) {
 		r = EFI_INVALID_PARAMETER;
 		goto out;
 	}
-
 	/* Find the protocol on the handle */
 	r = efi_search_protocol(handle, protocol, &handler);
 	if (r != EFI_SUCCESS)
 		goto out;
-	if (handler->protocol_interface) {
-		/* TODO disconnect controllers */
+	/* Disconnect controllers */
+	efi_disconnect_all_drivers(efiobj, protocol, NULL);
+	if (!list_empty(&handler->open_infos)) {
 		r =  EFI_ACCESS_DENIED;
-	} else {
-		r = efi_remove_protocol(handle, protocol, protocol_interface);
+		goto out;
 	}
+	/* Close protocol */
+	list_for_each_entry_safe(item, pos, &handler->open_infos, link) {
+		if (item->info.attributes ==
+			EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL ||
+		    item->info.attributes == EFI_OPEN_PROTOCOL_GET_PROTOCOL ||
+		    item->info.attributes == EFI_OPEN_PROTOCOL_TEST_PROTOCOL)
+			list_del(&item->link);
+	}
+	if (!list_empty(&handler->open_infos)) {
+		r =  EFI_ACCESS_DENIED;
+		goto out;
+	}
+	r = efi_remove_protocol(handle, protocol, protocol_interface);
 out:
 	return EFI_EXIT(r);
 }
@@ -1310,7 +1475,7 @@
 	struct efi_object *obj;
 	efi_status_t ret;
 
-	EFI_ENTRY("%d, %p, %p, %p, %ld, %p", boot_policy, parent_image,
+	EFI_ENTRY("%d, %p, %pD, %p, %ld, %p", boot_policy, parent_image,
 		  file_path, source_buffer, source_size, image_handle);
 
 	info = calloc(1, sizeof(*info));
@@ -1369,8 +1534,10 @@
 					   unsigned long *exit_data_size,
 					   s16 **exit_data)
 {
-	ulong (*entry)(void *image_handle, struct efi_system_table *st);
+	asmlinkage ulong (*entry)(efi_handle_t image_handle,
+				  struct efi_system_table *st);
 	struct efi_loaded_image *info = image_handle;
+	efi_status_t ret;
 
 	EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
 	entry = info->reserved;
@@ -1379,18 +1546,37 @@
 
 	/* call the image! */
 	if (setjmp(&info->exit_jmp)) {
-		/* We returned from the child image */
+		/*
+		 * We called the entry point of the child image with EFI_CALL
+		 * in the lines below. The child image called the Exit() boot
+		 * service efi_exit() which executed the long jump that brought
+		 * us to the current line. This implies that the second half
+		 * of the EFI_CALL macro has not been executed.
+		 */
+#ifdef CONFIG_ARM
+		/*
+		 * efi_exit() called efi_restore_gd(). We have to undo this
+		 * otherwise __efi_entry_check() will put the wrong value into
+		 * app_gd.
+		 */
+		gd = app_gd;
+#endif
+		/*
+		 * To get ready to call EFI_EXIT below we have to execute the
+		 * missed out steps of EFI_CALL.
+		 */
+		assert(__efi_entry_check());
+		debug("%sEFI: %lu returned by started image\n",
+		      __efi_nesting_dec(),
+		      (unsigned long)((uintptr_t)info->exit_status &
+				      ~EFI_ERROR_MASK));
 		return EFI_EXIT(info->exit_status);
 	}
 
-	__efi_nesting_dec();
-	__efi_exit_check();
-	entry(image_handle, &systab);
-	__efi_entry_check();
-	__efi_nesting_inc();
+	ret = EFI_CALL(entry(image_handle, &systab));
 
 	/* Should usually never get here */
-	return EFI_EXIT(EFI_SUCCESS);
+	return EFI_EXIT(ret);
 }
 
 /*
@@ -1427,7 +1613,7 @@
 		  exit_data_size, exit_data);
 
 	/* Make sure entry/exit counts for EFI world cross-overs match */
-	__efi_exit_check();
+	EFI_EXIT(exit_status);
 
 	/*
 	 * But longjmp out with the U-Boot gd, not the application's, as
@@ -1451,7 +1637,7 @@
  * @image_handle	handle of the image to be unloaded
  * @return		status code
  */
-static efi_status_t EFIAPI efi_unload_image(void *image_handle)
+static efi_status_t EFIAPI efi_unload_image(efi_handle_t image_handle)
 {
 	struct efi_object *efiobj;
 
@@ -1479,33 +1665,43 @@
 }
 
 /*
- * Stop boot services.
+ * Stop all boot services.
  *
  * This function implements the ExitBootServices service.
  * See the Unified Extensible Firmware Interface (UEFI) specification
  * for details.
  *
+ * All timer events are disabled.
+ * For exit boot services events the notification function is called.
+ * The boot services are disabled in the system table.
+ *
  * @image_handle	handle of the loaded image
  * @map_key		key of the memory map
  * @return		status code
  */
-static efi_status_t EFIAPI efi_exit_boot_services(void *image_handle,
+static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
 						  unsigned long map_key)
 {
 	int i;
 
 	EFI_ENTRY("%p, %ld", image_handle, map_key);
 
+	/* Make sure that notification functions are not called anymore */
+	efi_tpl = TPL_HIGH_LEVEL;
+
+	/* Check if ExitBootServices has already been called */
+	if (!systab.boottime)
+		return EFI_EXIT(EFI_SUCCESS);
+
 	/* Notify that ExitBootServices is invoked. */
 	for (i = 0; i < ARRAY_SIZE(efi_events); ++i) {
 		if (efi_events[i].type != EVT_SIGNAL_EXIT_BOOT_SERVICES)
 			continue;
-		efi_signal_event(&efi_events[i]);
+		efi_events[i].is_signaled = true;
+		efi_signal_event(&efi_events[i], false);
 	}
-	/* Make sure that notification functions are not called anymore */
-	efi_tpl = TPL_HIGH_LEVEL;
 
-	/* XXX Should persist EFI variables here */
+	/* TODO Should persist EFI variables here */
 
 	board_quiesce_devices();
 
@@ -1515,6 +1711,20 @@
 	/* This stops all lingering devices */
 	bootm_disable_interrupts();
 
+	/* Disable boottime services */
+	systab.con_in_handle = NULL;
+	systab.con_in = NULL;
+	systab.con_out_handle = NULL;
+	systab.con_out = NULL;
+	systab.stderr_handle = NULL;
+	systab.std_err = NULL;
+	systab.boottime = NULL;
+
+	/* Recalculate CRC32 */
+	systab.hdr.crc32 = 0;
+	systab.hdr.crc32 = crc32(0, (const unsigned char *)&systab,
+				 sizeof(struct efi_system_table));
+
 	/* Give the payload some time to boot */
 	efi_set_watchdog(0);
 	WATCHDOG_RESET();
@@ -1581,51 +1791,6 @@
 }
 
 /*
- * Connect a controller to a driver.
- *
- * This function implements the ConnectController service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
- *
- * @controller_handle	handle of the controller
- * @driver_image_handle	handle of the driver
- * @remain_device_path	device path of a child controller
- * @recursive		true to connect all child controllers
- * @return		status code
- */
-static efi_status_t EFIAPI efi_connect_controller(
-			efi_handle_t controller_handle,
-			efi_handle_t *driver_image_handle,
-			struct efi_device_path *remain_device_path,
-			bool recursive)
-{
-	EFI_ENTRY("%p, %p, %p, %d", controller_handle, driver_image_handle,
-		  remain_device_path, recursive);
-	return EFI_EXIT(EFI_NOT_FOUND);
-}
-
-/*
- * Disconnect a controller from a driver.
- *
- * This function implements the DisconnectController service.
- * See the Unified Extensible Firmware Interface (UEFI) specification
- * for details.
- *
- * @controller_handle	handle of the controller
- * @driver_image_handle handle of the driver
- * @child_handle	handle of the child to destroy
- * @return		status code
- */
-static efi_status_t EFIAPI efi_disconnect_controller(void *controller_handle,
-						     void *driver_image_handle,
-						     void *child_handle)
-{
-	EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle,
-		  child_handle);
-	return EFI_EXIT(EFI_INVALID_PARAMETER);
-}
-
-/*
  * Close a protocol.
  *
  * This function implements the CloseProtocol service.
@@ -1638,14 +1803,38 @@
  * @controller_handle	handle of the controller
  * @return		status code
  */
-static efi_status_t EFIAPI efi_close_protocol(void *handle,
+static efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle,
 					      const efi_guid_t *protocol,
-					      void *agent_handle,
-					      void *controller_handle)
+					      efi_handle_t agent_handle,
+					      efi_handle_t controller_handle)
 {
+	struct efi_handler *handler;
+	struct efi_open_protocol_info_item *item;
+	struct efi_open_protocol_info_item *pos;
+	efi_status_t r;
+
 	EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, agent_handle,
 		  controller_handle);
-	return EFI_EXIT(EFI_NOT_FOUND);
+
+	if (!agent_handle) {
+		r = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+	r = efi_search_protocol(handle, protocol, &handler);
+	if (r != EFI_SUCCESS)
+		goto out;
+
+	r = EFI_NOT_FOUND;
+	list_for_each_entry_safe(item, pos, &handler->open_infos, link) {
+		if (item->info.agent_handle == agent_handle &&
+		    item->info.controller_handle == controller_handle) {
+			efi_delete_open_info(item);
+			r = EFI_SUCCESS;
+			break;
+		}
+	}
+out:
+	return EFI_EXIT(r);
 }
 
 /*
@@ -1666,9 +1855,49 @@
 			struct efi_open_protocol_info_entry **entry_buffer,
 			efi_uintn_t *entry_count)
 {
+	unsigned long buffer_size;
+	unsigned long count;
+	struct efi_handler *handler;
+	struct efi_open_protocol_info_item *item;
+	efi_status_t r;
+
 	EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, entry_buffer,
 		  entry_count);
-	return EFI_EXIT(EFI_NOT_FOUND);
+
+	/* Check parameters */
+	if (!entry_buffer) {
+		r = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+	r = efi_search_protocol(handle, protocol, &handler);
+	if (r != EFI_SUCCESS)
+		goto out;
+
+	/* Count entries */
+	count = 0;
+	list_for_each_entry(item, &handler->open_infos, link) {
+		if (item->info.open_count)
+			++count;
+	}
+	*entry_count = count;
+	*entry_buffer = NULL;
+	if (!count) {
+		r = EFI_SUCCESS;
+		goto out;
+	}
+
+	/* Copy entries */
+	buffer_size = count * sizeof(struct efi_open_protocol_info_entry);
+	r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, buffer_size,
+			      (void **)entry_buffer);
+	if (r != EFI_SUCCESS)
+		goto out;
+	list_for_each_entry_reverse(item, &handler->open_infos, link) {
+		if (item->info.open_count)
+			(*entry_buffer)[--count] = item->info;
+	}
+out:
+	return EFI_EXIT(r);
 }
 
 /*
@@ -1683,8 +1912,8 @@
  * @protocol_buffer_count	number of entries in the buffer
  * @return			status code
  */
-static efi_status_t EFIAPI efi_protocols_per_handle(void *handle,
-			efi_guid_t ***protocol_buffer,
+static efi_status_t EFIAPI efi_protocols_per_handle(
+			efi_handle_t handle, efi_guid_t ***protocol_buffer,
 			efi_uintn_t *protocol_buffer_count)
 {
 	unsigned long buffer_size;
@@ -1774,7 +2003,7 @@
 	r = efi_locate_handle(search_type, protocol, search_key, &buffer_size,
 			      *buffer);
 	if (r == EFI_SUCCESS)
-		*no_handles = buffer_size / sizeof(void *);
+		*no_handles = buffer_size / sizeof(efi_handle_t);
 out:
 	return EFI_EXIT(r);
 }
@@ -2071,6 +2300,101 @@
 /*
  * Open protocol interface on a handle.
  *
+ * @handler		handler of a protocol
+ * @protocol_interface	interface implementing the protocol
+ * @agent_handle	handle of the driver
+ * @controller_handle	handle of the controller
+ * @attributes		attributes indicating how to open the protocol
+ * @return		status code
+ */
+static efi_status_t efi_protocol_open(
+			struct efi_handler *handler,
+			void **protocol_interface, void *agent_handle,
+			void *controller_handle, uint32_t attributes)
+{
+	struct efi_open_protocol_info_item *item;
+	struct efi_open_protocol_info_entry *match = NULL;
+	bool opened_by_driver = false;
+	bool opened_exclusive = false;
+
+	/* If there is no agent, only return the interface */
+	if (!agent_handle)
+		goto out;
+
+	/* For TEST_PROTOCOL ignore interface attribute */
+	if (attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL)
+		*protocol_interface = NULL;
+
+	/*
+	 * Check if the protocol is already opened by a driver with the same
+	 * attributes or opened exclusively
+	 */
+	list_for_each_entry(item, &handler->open_infos, link) {
+		if (item->info.agent_handle == agent_handle) {
+			if ((attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) &&
+			    (item->info.attributes == attributes))
+				return EFI_ALREADY_STARTED;
+		}
+		if (item->info.attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE)
+			opened_exclusive = true;
+	}
+
+	/* Only one controller can open the protocol exclusively */
+	if (opened_exclusive && attributes &
+	    (EFI_OPEN_PROTOCOL_EXCLUSIVE | EFI_OPEN_PROTOCOL_BY_DRIVER))
+		return EFI_ACCESS_DENIED;
+
+	/* Prepare exclusive opening */
+	if (attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {
+		/* Try to disconnect controllers */
+		list_for_each_entry(item, &handler->open_infos, link) {
+			if (item->info.attributes ==
+					EFI_OPEN_PROTOCOL_BY_DRIVER)
+				EFI_CALL(efi_disconnect_controller(
+						item->info.controller_handle,
+						item->info.agent_handle,
+						NULL));
+		}
+		opened_by_driver = false;
+		/* Check if all controllers are disconnected */
+		list_for_each_entry(item, &handler->open_infos, link) {
+			if (item->info.attributes & EFI_OPEN_PROTOCOL_BY_DRIVER)
+				opened_by_driver = true;
+		}
+		/* Only one controller can be conncected */
+		if (opened_by_driver)
+			return EFI_ACCESS_DENIED;
+	}
+
+	/* Find existing entry */
+	list_for_each_entry(item, &handler->open_infos, link) {
+		if (item->info.agent_handle == agent_handle &&
+		    item->info.controller_handle == controller_handle)
+			match = &item->info;
+	}
+	/* None found, create one */
+	if (!match) {
+		match = efi_create_open_info(handler);
+		if (!match)
+			return EFI_OUT_OF_RESOURCES;
+	}
+
+	match->agent_handle = agent_handle;
+	match->controller_handle = controller_handle;
+	match->attributes = attributes;
+	match->open_count++;
+
+out:
+	/* For TEST_PROTOCOL ignore interface attribute. */
+	if (attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL)
+		*protocol_interface = handler->protocol_interface;
+
+	return EFI_SUCCESS;
+}
+
+/*
+ * Open protocol interface on a handle.
+ *
  * This function implements the OpenProtocol interface.
  * See the Unified Extensible Firmware Interface (UEFI) specification
  * for details.
@@ -2109,12 +2433,16 @@
 	case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
 		if (controller_handle == handle)
 			goto out;
+		/* fall-through */
 	case EFI_OPEN_PROTOCOL_BY_DRIVER:
 	case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
-		if (controller_handle == NULL)
+		/* Check that the controller handle is valid */
+		if (!efi_search_obj(controller_handle))
 			goto out;
+		/* fall-through */
 	case EFI_OPEN_PROTOCOL_EXCLUSIVE:
-		if (agent_handle == NULL)
+		/* Check that the agent handle is valid */
+		if (!efi_search_obj(agent_handle))
 			goto out;
 		break;
 	default:
@@ -2125,8 +2453,8 @@
 	if (r != EFI_SUCCESS)
 		goto out;
 
-	if (attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL)
-		*protocol_interface = handler->protocol_interface;
+	r = efi_protocol_open(handler, protocol_interface, agent_handle,
+			      controller_handle, attributes);
 out:
 	return EFI_EXIT(r);
 }
@@ -2143,7 +2471,7 @@
  * @protocol_interface  interface implementing the protocol
  * @return		status code
  */
-static efi_status_t EFIAPI efi_handle_protocol(void *handle,
+static efi_status_t EFIAPI efi_handle_protocol(efi_handle_t handle,
 					       const efi_guid_t *protocol,
 					       void **protocol_interface)
 {
@@ -2151,6 +2479,321 @@
 				 NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
 }
 
+static efi_status_t efi_bind_controller(
+			efi_handle_t controller_handle,
+			efi_handle_t driver_image_handle,
+			struct efi_device_path *remain_device_path)
+{
+	struct efi_driver_binding_protocol *binding_protocol;
+	efi_status_t r;
+
+	r = EFI_CALL(efi_open_protocol(driver_image_handle,
+				       &efi_guid_driver_binding_protocol,
+				       (void **)&binding_protocol,
+				       driver_image_handle, NULL,
+				       EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+	if (r != EFI_SUCCESS)
+		return r;
+	r = EFI_CALL(binding_protocol->supported(binding_protocol,
+						 controller_handle,
+						 remain_device_path));
+	if (r == EFI_SUCCESS)
+		r = EFI_CALL(binding_protocol->start(binding_protocol,
+						     controller_handle,
+						     remain_device_path));
+	EFI_CALL(efi_close_protocol(driver_image_handle,
+				    &efi_guid_driver_binding_protocol,
+				    driver_image_handle, NULL));
+	return r;
+}
+
+static efi_status_t efi_connect_single_controller(
+			efi_handle_t controller_handle,
+			efi_handle_t *driver_image_handle,
+			struct efi_device_path *remain_device_path)
+{
+	efi_handle_t *buffer;
+	size_t count;
+	size_t i;
+	efi_status_t r;
+	size_t connected = 0;
+
+	/* Get buffer with all handles with driver binding protocol */
+	r = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL,
+					      &efi_guid_driver_binding_protocol,
+					      NULL, &count, &buffer));
+	if (r != EFI_SUCCESS)
+		return r;
+
+	/*  Context Override */
+	if (driver_image_handle) {
+		for (; *driver_image_handle; ++driver_image_handle) {
+			for (i = 0; i < count; ++i) {
+				if (buffer[i] == *driver_image_handle) {
+					buffer[i] = NULL;
+					r = efi_bind_controller(
+							controller_handle,
+							*driver_image_handle,
+							remain_device_path);
+					/*
+					 * For drivers that do not support the
+					 * controller or are already connected
+					 * we receive an error code here.
+					 */
+					if (r == EFI_SUCCESS)
+						++connected;
+				}
+			}
+		}
+	}
+
+	/*
+	 * TODO: Some overrides are not yet implemented:
+	 * - Platform Driver Override
+	 * - Driver Family Override Search
+	 * - Bus Specific Driver Override
+	 */
+
+	/* Driver Binding Search */
+	for (i = 0; i < count; ++i) {
+		if (buffer[i]) {
+			r = efi_bind_controller(controller_handle,
+						buffer[i],
+						remain_device_path);
+			if (r == EFI_SUCCESS)
+				++connected;
+		}
+	}
+
+	efi_free_pool(buffer);
+	if (!connected)
+		return EFI_NOT_FOUND;
+	return EFI_SUCCESS;
+}
+
+/*
+ * Connect a controller to a driver.
+ *
+ * This function implements the ConnectController service.
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * First all driver binding protocol handles are tried for binding drivers.
+ * Afterwards all handles that have openened a protocol of the controller
+ * with EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER are connected to drivers.
+ *
+ * @controller_handle	handle of the controller
+ * @driver_image_handle	handle of the driver
+ * @remain_device_path	device path of a child controller
+ * @recursive		true to connect all child controllers
+ * @return		status code
+ */
+static efi_status_t EFIAPI efi_connect_controller(
+			efi_handle_t controller_handle,
+			efi_handle_t *driver_image_handle,
+			struct efi_device_path *remain_device_path,
+			bool recursive)
+{
+	efi_status_t r;
+	efi_status_t ret = EFI_NOT_FOUND;
+	struct efi_object *efiobj;
+
+	EFI_ENTRY("%p, %p, %p, %d", controller_handle, driver_image_handle,
+		  remain_device_path, recursive);
+
+	efiobj = efi_search_obj(controller_handle);
+	if (!efiobj) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	r = efi_connect_single_controller(controller_handle,
+					  driver_image_handle,
+					  remain_device_path);
+	if (r == EFI_SUCCESS)
+		ret = EFI_SUCCESS;
+	if (recursive) {
+		struct efi_handler *handler;
+		struct efi_open_protocol_info_item *item;
+
+		list_for_each_entry(handler, &efiobj->protocols, link) {
+			list_for_each_entry(item, &handler->open_infos, link) {
+				if (item->info.attributes &
+				    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+					r = EFI_CALL(efi_connect_controller(
+						item->info.controller_handle,
+						driver_image_handle,
+						remain_device_path,
+						recursive));
+					if (r == EFI_SUCCESS)
+						ret = EFI_SUCCESS;
+				}
+			}
+		}
+	}
+	/*  Check for child controller specified by end node */
+	if (ret != EFI_SUCCESS && remain_device_path &&
+	    remain_device_path->type == DEVICE_PATH_TYPE_END)
+		ret = EFI_SUCCESS;
+out:
+	return EFI_EXIT(ret);
+}
+
+/*
+ * Get all child controllers associated to a driver.
+ * The allocated buffer has to be freed with free().
+ *
+ * @efiobj			handle of the controller
+ * @driver_handle		handle of the driver
+ * @number_of_children		number of child controllers
+ * @child_handle_buffer		handles of the the child controllers
+ */
+static efi_status_t efi_get_child_controllers(
+				struct efi_object *efiobj,
+				efi_handle_t driver_handle,
+				efi_uintn_t *number_of_children,
+				efi_handle_t **child_handle_buffer)
+{
+	struct efi_handler *handler;
+	struct efi_open_protocol_info_item *item;
+	efi_uintn_t count = 0, i;
+	bool duplicate;
+
+	/* Count all child controller associations */
+	list_for_each_entry(handler, &efiobj->protocols, link) {
+		list_for_each_entry(item, &handler->open_infos, link) {
+			if (item->info.agent_handle == driver_handle &&
+			    item->info.attributes &
+			    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
+				++count;
+		}
+	}
+	/*
+	 * Create buffer. In case of duplicate child controller assignments
+	 * the buffer will be too large. But that does not harm.
+	 */
+	*number_of_children = 0;
+	*child_handle_buffer = calloc(count, sizeof(efi_handle_t));
+	if (!*child_handle_buffer)
+		return EFI_OUT_OF_RESOURCES;
+	/* Copy unique child handles */
+	list_for_each_entry(handler, &efiobj->protocols, link) {
+		list_for_each_entry(item, &handler->open_infos, link) {
+			if (item->info.agent_handle == driver_handle &&
+			    item->info.attributes &
+			    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+				/* Check this is a new child controller */
+				duplicate = false;
+				for (i = 0; i < *number_of_children; ++i) {
+					if ((*child_handle_buffer)[i] ==
+					    item->info.controller_handle)
+						duplicate = true;
+				}
+				/* Copy handle to buffer */
+				if (!duplicate) {
+					i = (*number_of_children)++;
+					(*child_handle_buffer)[i] =
+						item->info.controller_handle;
+				}
+			}
+		}
+	}
+	return EFI_SUCCESS;
+}
+
+/*
+ * Disconnect a controller from a driver.
+ *
+ * This function implements the DisconnectController service.
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @controller_handle	handle of the controller
+ * @driver_image_handle handle of the driver
+ * @child_handle	handle of the child to destroy
+ * @return		status code
+ */
+static efi_status_t EFIAPI efi_disconnect_controller(
+				efi_handle_t controller_handle,
+				efi_handle_t driver_image_handle,
+				efi_handle_t child_handle)
+{
+	struct efi_driver_binding_protocol *binding_protocol;
+	efi_handle_t *child_handle_buffer = NULL;
+	size_t number_of_children = 0;
+	efi_status_t r;
+	size_t stop_count = 0;
+	struct efi_object *efiobj;
+
+	EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle,
+		  child_handle);
+
+	efiobj = efi_search_obj(controller_handle);
+	if (!efiobj) {
+		r = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	if (child_handle && !efi_search_obj(child_handle)) {
+		r = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	/* If no driver handle is supplied, disconnect all drivers */
+	if (!driver_image_handle) {
+		r = efi_disconnect_all_drivers(efiobj, NULL, child_handle);
+		goto out;
+	}
+
+	/* Create list of child handles */
+	if (child_handle) {
+		number_of_children = 1;
+		child_handle_buffer = &child_handle;
+	} else {
+		efi_get_child_controllers(efiobj,
+					  driver_image_handle,
+					  &number_of_children,
+					  &child_handle_buffer);
+	}
+
+	/* Get the driver binding protocol */
+	r = EFI_CALL(efi_open_protocol(driver_image_handle,
+				       &efi_guid_driver_binding_protocol,
+				       (void **)&binding_protocol,
+				       driver_image_handle, NULL,
+				       EFI_OPEN_PROTOCOL_GET_PROTOCOL));
+	if (r != EFI_SUCCESS)
+		goto out;
+	/* Remove the children */
+	if (number_of_children) {
+		r = EFI_CALL(binding_protocol->stop(binding_protocol,
+						    controller_handle,
+						    number_of_children,
+						    child_handle_buffer));
+		if (r == EFI_SUCCESS)
+			++stop_count;
+	}
+	/* Remove the driver */
+	if (!child_handle)
+		r = EFI_CALL(binding_protocol->stop(binding_protocol,
+						    controller_handle,
+						    0, NULL));
+	if (r == EFI_SUCCESS)
+		++stop_count;
+	EFI_CALL(efi_close_protocol(driver_image_handle,
+				    &efi_guid_driver_binding_protocol,
+				    driver_image_handle, NULL));
+
+	if (stop_count)
+		r = EFI_SUCCESS;
+	else
+		r = EFI_NOT_FOUND;
+out:
+	if (!child_handle)
+		free(child_handle_buffer);
+	return EFI_EXIT(r);
+}
+
 static const struct efi_boot_services efi_boot_services = {
 	.hdr = {
 		.headersize = sizeof(struct efi_table_hdr),
@@ -2201,8 +2844,7 @@
 };
 
 
-static uint16_t __efi_runtime_data firmware_vendor[] =
-	{ 'D','a','s',' ','U','-','b','o','o','t',0 };
+static uint16_t __efi_runtime_data firmware_vendor[] = L"Das U-Boot";
 
 struct efi_system_table __efi_runtime_data systab = {
 	.hdr = {
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 98497db..28d6363 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -482,18 +482,26 @@
 {
 }
 
+/*
+ * Notification function of the console timer event.
+ *
+ * event:	console timer event
+ * context:	not used
+ */
 static void EFIAPI efi_console_timer_notify(struct efi_event *event,
 					    void *context)
 {
 	EFI_ENTRY("%p, %p", event, context);
+
+	/* Check if input is available */
 	if (tstc()) {
+		/* Queue the wait for key event */
 		efi_con_in.wait_for_key->is_signaled = true;
-		efi_signal_event(efi_con_in.wait_for_key);
-		}
+		efi_signal_event(efi_con_in.wait_for_key, true);
+	}
 	EFI_EXIT(EFI_SUCCESS);
 }
 
-
 /* This gets called from do_bootefi_exec(). */
 int efi_console_register(void)
 {
@@ -503,21 +511,21 @@
 	struct efi_object *efi_console_input_obj;
 
 	/* Create handles */
-	r = efi_create_handle((void **)&efi_console_control_obj);
+	r = efi_create_handle((efi_handle_t *)&efi_console_control_obj);
 	if (r != EFI_SUCCESS)
 		goto out_of_memory;
 	r = efi_add_protocol(efi_console_control_obj->handle,
 			     &efi_guid_console_control, &efi_console_control);
 	if (r != EFI_SUCCESS)
 		goto out_of_memory;
-	r = efi_create_handle((void **)&efi_console_output_obj);
+	r = efi_create_handle((efi_handle_t *)&efi_console_output_obj);
 	if (r != EFI_SUCCESS)
 		goto out_of_memory;
 	r = efi_add_protocol(efi_console_output_obj->handle,
 			     &efi_guid_text_output_protocol, &efi_con_out);
 	if (r != EFI_SUCCESS)
 		goto out_of_memory;
-	r = efi_create_handle((void **)&efi_console_input_obj);
+	r = efi_create_handle((efi_handle_t *)&efi_console_input_obj);
 	if (r != EFI_SUCCESS)
 		goto out_of_memory;
 	r = efi_add_protocol(efi_console_input_obj->handle,
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index ccb5933..ecc4eda 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -6,6 +6,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#define LOG_CATEGORY LOGL_ERR
+
 #include <common.h>
 #include <blk.h>
 #include <dm.h>
@@ -58,8 +60,11 @@
 {
 	void *buf;
 
-	if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) != EFI_SUCCESS)
+	if (efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, sz, &buf) !=
+	    EFI_SUCCESS) {
+		debug("EFI: ERROR: out of memory in %s\n", __func__);
 		return NULL;
+	}
 
 	return buf;
 }
@@ -108,7 +113,6 @@
 	}
 }
 
-
 /*
  * See UEFI spec (section 3.1.2, about short-form device-paths..
  * tl;dr: we can have a device-path that starts with a USB WWID
@@ -181,7 +185,6 @@
 	return NULL;
 }
 
-
 /*
  * Find an efiobj from device-path, if 'rem' is not NULL, returns the
  * remaining part of the device path after the matched object.
@@ -205,6 +208,26 @@
 	return efiobj;
 }
 
+/*
+ * Determine the last device path node that is not the end node.
+ *
+ * @dp		device path
+ * @return	last node before the end node if it exists
+ *		otherwise NULL
+ */
+const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp)
+{
+	struct efi_device_path *ret;
+
+	if (!dp || dp->type == DEVICE_PATH_TYPE_END)
+		return NULL;
+	while (dp) {
+		ret = (struct efi_device_path *)dp;
+		dp = efi_dp_next(dp);
+	}
+	return ret;
+}
+
 /* return size not including End node: */
 unsigned efi_dp_size(const struct efi_device_path *dp)
 {
@@ -227,6 +250,8 @@
 		return NULL;
 
 	ndp = dp_alloc(sz);
+	if (!ndp)
+		return NULL;
 	memcpy(ndp, dp, sz);
 
 	return ndp;
@@ -246,6 +271,8 @@
 		unsigned sz1 = efi_dp_size(dp1);
 		unsigned sz2 = efi_dp_size(dp2);
 		void *p = dp_alloc(sz1 + sz2 + sizeof(END));
+		if (!p)
+			return NULL;
 		memcpy(p, dp1, sz1);
 		memcpy(p + sz1, dp2, sz2);
 		memcpy(p + sz1 + sz2, &END, sizeof(END));
@@ -267,6 +294,8 @@
 	} else if (!dp) {
 		unsigned sz = node->length;
 		void *p = dp_alloc(sz + sizeof(END));
+		if (!p)
+			return NULL;
 		memcpy(p, node, sz);
 		memcpy(p + sz, &END, sizeof(END));
 		ret = p;
@@ -274,6 +303,8 @@
 		/* both dp and node are non-null */
 		unsigned sz = efi_dp_size(dp);
 		void *p = dp_alloc(sz + node->length + sizeof(END));
+		if (!p)
+			return NULL;
 		memcpy(p, dp, sz);
 		memcpy(p + sz, node, node->length);
 		memcpy(p + sz + node->length, &END, sizeof(END));
@@ -297,9 +328,36 @@
 	case UCLASS_SIMPLE_BUS:
 		/* stop traversing parents at this point: */
 		return sizeof(ROOT);
+	case UCLASS_ETH:
+		return dp_size(dev->parent) +
+			sizeof(struct efi_device_path_mac_addr);
+#ifdef CONFIG_BLK
+	case UCLASS_BLK:
+		switch (dev->parent->uclass->uc_drv->id) {
+#ifdef CONFIG_IDE
+		case UCLASS_IDE:
+			return dp_size(dev->parent) +
+				sizeof(struct efi_device_path_atapi);
+#endif
+#if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
+		case UCLASS_SCSI:
+			return dp_size(dev->parent) +
+				sizeof(struct efi_device_path_scsi);
+#endif
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
+		case UCLASS_MMC:
+			return dp_size(dev->parent) +
+				sizeof(struct efi_device_path_sd_mmc_path);
+#endif
+		default:
+			return dp_size(dev->parent);
+		}
+#endif
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
 	case UCLASS_MMC:
 		return dp_size(dev->parent) +
 			sizeof(struct efi_device_path_sd_mmc_path);
+#endif
 	case UCLASS_MASS_STORAGE:
 	case UCLASS_USB_HUB:
 		return dp_size(dev->parent) +
@@ -310,6 +368,13 @@
 	}
 }
 
+/*
+ * Recursively build a device path.
+ *
+ * @buf		pointer to the end of the device path
+ * @dev		device
+ * @return	pointer to the end of the device path
+ */
 static void *dp_fill(void *buf, struct udevice *dev)
 {
 	if (!dev || !dev->driver)
@@ -323,6 +388,79 @@
 		*vdp = ROOT;
 		return &vdp[1];
 	}
+#ifdef CONFIG_DM_ETH
+	case UCLASS_ETH: {
+		struct efi_device_path_mac_addr *dp =
+			dp_fill(buf, dev->parent);
+		struct eth_pdata *pdata = dev->platdata;
+
+		dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+		dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR;
+		dp->dp.length = sizeof(*dp);
+		memset(&dp->mac, 0, sizeof(dp->mac));
+		/* We only support IPv4 */
+		memcpy(&dp->mac, &pdata->enetaddr, ARP_HLEN);
+		/* Ethernet */
+		dp->if_type = 1;
+		return &dp[1];
+	}
+#endif
+#ifdef CONFIG_BLK
+	case UCLASS_BLK:
+		switch (dev->parent->uclass->uc_drv->id) {
+#ifdef CONFIG_IDE
+		case UCLASS_IDE: {
+			struct efi_device_path_atapi *dp =
+			dp_fill(buf, dev->parent);
+			struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+			dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+			dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_ATAPI;
+			dp->dp.length = sizeof(*dp);
+			dp->logical_unit_number = desc->devnum;
+			dp->primary_secondary = IDE_BUS(desc->devnum);
+			dp->slave_master = desc->devnum %
+				(CONFIG_SYS_IDE_MAXDEVICE /
+				 CONFIG_SYS_IDE_MAXBUS);
+			return &dp[1];
+			}
+#endif
+#if defined(CONFIG_SCSI) && defined(CONFIG_DM_SCSI)
+		case UCLASS_SCSI: {
+			struct efi_device_path_scsi *dp =
+				dp_fill(buf, dev->parent);
+			struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+			dp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+			dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_SCSI;
+			dp->dp.length = sizeof(*dp);
+			dp->logical_unit_number = desc->lun;
+			dp->target_id = desc->target;
+			return &dp[1];
+			}
+#endif
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
+		case UCLASS_MMC: {
+			struct efi_device_path_sd_mmc_path *sddp =
+				dp_fill(buf, dev->parent);
+			struct blk_desc *desc = dev_get_uclass_platdata(dev);
+
+			sddp->dp.type     = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+			sddp->dp.sub_type = is_sd(desc) ?
+				DEVICE_PATH_SUB_TYPE_MSG_SD :
+				DEVICE_PATH_SUB_TYPE_MSG_MMC;
+			sddp->dp.length   = sizeof(*sddp);
+			sddp->slot_number = dev->seq;
+			return &sddp[1];
+			}
+#endif
+		default:
+			debug("%s(%u) %s: unhandled parent class: %s (%u)\n",
+			      __FILE__, __LINE__, __func__,
+			      dev->name, dev->parent->uclass->uc_drv->id);
+			return dp_fill(buf, dev->parent);
+		}
+#endif
 #if defined(CONFIG_DM_MMC) && defined(CONFIG_MMC)
 	case UCLASS_MMC: {
 		struct efi_device_path_sd_mmc_path *sddp =
@@ -359,7 +497,8 @@
 		return &udp[1];
 	}
 	default:
-		debug("unhandled device class: %s (%u)\n",
+		debug("%s(%u) %s: unhandled device class: %s (%u)\n",
+		      __FILE__, __LINE__, __func__,
 		      dev->name, dev->driver->id);
 		return dp_fill(buf, dev->parent);
 	}
@@ -371,6 +510,8 @@
 	void *buf, *start;
 
 	start = buf = dp_alloc(dp_size(dev) + sizeof(END));
+	if (!buf)
+		return NULL;
 	buf = dp_fill(buf, dev);
 	*((struct efi_device_path *)buf) = END;
 
@@ -383,7 +524,14 @@
 	unsigned dpsize;
 
 #ifdef CONFIG_BLK
-	dpsize = dp_size(desc->bdev->parent);
+	{
+		struct udevice *dev;
+		int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
+
+		if (ret)
+			dev = desc->bdev->parent;
+		dpsize = dp_size(dev);
+	}
 #else
 	dpsize = sizeof(ROOT) + sizeof(struct efi_device_path_usb);
 #endif
@@ -400,43 +548,16 @@
 }
 
 /*
- * Create a device path for a block device or one of its partitions.
+ * Create a device node for a block device partition.
  *
  * @buf		buffer to which the device path is wirtten
  * @desc	block device descriptor
  * @part	partition number, 0 identifies a block device
  */
-static void *dp_part_fill(void *buf, struct blk_desc *desc, int part)
+static void *dp_part_node(void *buf, struct blk_desc *desc, int part)
 {
 	disk_partition_t info;
 
-#ifdef CONFIG_BLK
-	buf = dp_fill(buf, desc->bdev->parent);
-#else
-	/*
-	 * We *could* make a more accurate path, by looking at if_type
-	 * and handling all the different cases like we do for non-
-	 * legacy (ie CONFIG_BLK=y) case.  But most important thing
-	 * is just to have a unique device-path for if_type+devnum.
-	 * So map things to a fictitious USB device.
-	 */
-	struct efi_device_path_usb *udp;
-
-	memcpy(buf, &ROOT, sizeof(ROOT));
-	buf += sizeof(ROOT);
-
-	udp = buf;
-	udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
-	udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
-	udp->dp.length = sizeof(*udp);
-	udp->parent_port_number = desc->if_type;
-	udp->usb_interface = desc->devnum;
-	buf = &udp[1];
-#endif
-
-	if (part == 0) /* the actual disk, not a partition */
-		return buf;
-
 	part_get_info(desc, part, &info);
 
 	if (desc->part_type == PART_TYPE_ISO) {
@@ -491,6 +612,51 @@
 	return buf;
 }
 
+/*
+ * Create a device path for a block device or one of its partitions.
+ *
+ * @buf		buffer to which the device path is wirtten
+ * @desc	block device descriptor
+ * @part	partition number, 0 identifies a block device
+ */
+static void *dp_part_fill(void *buf, struct blk_desc *desc, int part)
+{
+#ifdef CONFIG_BLK
+	{
+		struct udevice *dev;
+		int ret = blk_find_device(desc->if_type, desc->devnum, &dev);
+
+		if (ret)
+			dev = desc->bdev->parent;
+		buf = dp_fill(buf, dev);
+	}
+#else
+	/*
+	 * We *could* make a more accurate path, by looking at if_type
+	 * and handling all the different cases like we do for non-
+	 * legacy (ie CONFIG_BLK=y) case.  But most important thing
+	 * is just to have a unique device-path for if_type+devnum.
+	 * So map things to a fictitious USB device.
+	 */
+	struct efi_device_path_usb *udp;
+
+	memcpy(buf, &ROOT, sizeof(ROOT));
+	buf += sizeof(ROOT);
+
+	udp = buf;
+	udp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+	udp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_USB;
+	udp->dp.length = sizeof(*udp);
+	udp->parent_port_number = desc->if_type;
+	udp->usb_interface = desc->devnum;
+	buf = &udp[1];
+#endif
+
+	if (part == 0) /* the actual disk, not a partition */
+		return buf;
+
+	return dp_part_node(buf, desc, part);
+}
 
 /* Construct a device-path from a partition on a blk device: */
 struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
@@ -498,6 +664,8 @@
 	void *buf, *start;
 
 	start = buf = dp_alloc(dp_part_size(desc, part) + sizeof(END));
+	if (!buf)
+		return NULL;
 
 	buf = dp_part_fill(buf, desc, part);
 
@@ -506,6 +674,29 @@
 	return start;
 }
 
+/*
+ * Create a device node for a block device partition.
+ *
+ * @buf		buffer to which the device path is wirtten
+ * @desc	block device descriptor
+ * @part	partition number, 0 identifies a block device
+ */
+struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part)
+{
+	efi_uintn_t dpsize;
+	void *buf;
+
+	if (desc->part_type == PART_TYPE_ISO)
+		dpsize = sizeof(struct efi_device_path_cdrom_path);
+	else
+		dpsize = sizeof(struct efi_device_path_hard_drive_path);
+	buf = dp_alloc(dpsize);
+
+	dp_part_node(buf, desc, part);
+
+	return buf;
+}
+
 /* convert path to an UEFI style path (ie. DOS style backslashes and utf16) */
 static void path_to_uefi(u16 *uefi, const char *path)
 {
@@ -536,6 +727,8 @@
 	dpsize += fpsize;
 
 	start = buf = dp_alloc(dpsize + sizeof(END));
+	if (!buf)
+		return NULL;
 
 	if (desc)
 		buf = dp_part_fill(buf, desc, part);
@@ -570,6 +763,8 @@
 	dpsize += sizeof(*ndp);
 
 	start = buf = dp_alloc(dpsize + sizeof(END));
+	if (!buf)
+		return NULL;
 
 #ifdef CONFIG_DM_ETH
 	buf = dp_fill(buf, eth_get_dev());
@@ -600,6 +795,8 @@
 	void *buf, *start;
 
 	start = buf = dp_alloc(sizeof(*mdp) + sizeof(END));
+	if (!buf)
+		return NULL;
 
 	mdp = buf;
 	mdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
@@ -619,22 +816,31 @@
  * Helper to split a full device path (containing both device and file
  * parts) into it's constituent parts.
  */
-void efi_dp_split_file_path(struct efi_device_path *full_path,
-			    struct efi_device_path **device_path,
-			    struct efi_device_path **file_path)
+efi_status_t efi_dp_split_file_path(struct efi_device_path *full_path,
+				    struct efi_device_path **device_path,
+				    struct efi_device_path **file_path)
 {
 	struct efi_device_path *p, *dp, *fp;
 
+	*device_path = NULL;
+	*file_path = NULL;
 	dp = efi_dp_dup(full_path);
+	if (!dp)
+		return EFI_OUT_OF_RESOURCES;
 	p = dp;
-	while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH))
+	while (!EFI_DP_TYPE(p, MEDIA_DEVICE, FILE_PATH)) {
 		p = efi_dp_next(p);
+		if (!p)
+			return EFI_OUT_OF_RESOURCES;
+	}
 	fp = efi_dp_dup(p);
-
+	if (!fp)
+		return EFI_OUT_OF_RESOURCES;
 	p->type = DEVICE_PATH_TYPE_END;
 	p->sub_type = DEVICE_PATH_SUB_TYPE_END;
 	p->length = sizeof(*p);
 
 	*device_path = dp;
 	*file_path = fp;
+	return EFI_SUCCESS;
 }
diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c
index 50d9e91..a79e60a 100644
--- a/lib/efi_loader/efi_device_path_to_text.c
+++ b/lib/efi_loader/efi_device_path_to_text.c
@@ -87,6 +87,20 @@
 static char *dp_msging(char *s, struct efi_device_path *dp)
 {
 	switch (dp->sub_type) {
+	case DEVICE_PATH_SUB_TYPE_MSG_ATAPI: {
+		struct efi_device_path_atapi *ide =
+			(struct efi_device_path_atapi *)dp;
+		s += sprintf(s, "Ata(%d,%d,%d)", ide->primary_secondary,
+			     ide->slave_master, ide->logical_unit_number);
+		break;
+	}
+	case DEVICE_PATH_SUB_TYPE_MSG_SCSI: {
+		struct efi_device_path_scsi *ide =
+			(struct efi_device_path_scsi *)dp;
+		s += sprintf(s, "Scsi(%u,%u)", ide->target_id,
+			     ide->logical_unit_number);
+		break;
+	}
 	case DEVICE_PATH_SUB_TYPE_MSG_USB: {
 		struct efi_device_path_usb *udp =
 			(struct efi_device_path_usb *)dp;
@@ -231,6 +245,8 @@
 	case DEVICE_PATH_TYPE_MEDIA_DEVICE:
 		str = dp_media(str, dp);
 		break;
+	case DEVICE_PATH_TYPE_END:
+		break;
 	default:
 		str = dp_unknown(str, dp);
 	}
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index d299fc8..ac39a65 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -14,7 +14,7 @@
 #include <part.h>
 #include <malloc.h>
 
-static const efi_guid_t efi_block_io_guid = BLOCK_IO_GUID;
+const efi_guid_t efi_block_io_guid = BLOCK_IO_GUID;
 
 struct efi_disk_obj {
 	/* Generic EFI object parent class data */
@@ -91,7 +91,7 @@
 }
 
 static efi_status_t EFIAPI efi_disk_read_blocks(struct efi_block_io *this,
-			u32 media_id, u64 lba, unsigned long buffer_size,
+			u32 media_id, u64 lba, efi_uintn_t buffer_size,
 			void *buffer)
 {
 	void *real_buffer = buffer;
@@ -112,7 +112,7 @@
 	real_buffer = efi_bounce_buffer;
 #endif
 
-	EFI_ENTRY("%p, %x, %"PRIx64", %lx, %p", this, media_id, lba,
+	EFI_ENTRY("%p, %x, %" PRIx64 ", %zx, %p", this, media_id, lba,
 		  buffer_size, buffer);
 
 	r = efi_disk_rw_blocks(this, media_id, lba, buffer_size, real_buffer,
@@ -126,7 +126,7 @@
 }
 
 static efi_status_t EFIAPI efi_disk_write_blocks(struct efi_block_io *this,
-			u32 media_id, u64 lba, unsigned long buffer_size,
+			u32 media_id, u64 lba, efi_uintn_t buffer_size,
 			void *buffer)
 {
 	void *real_buffer = buffer;
@@ -147,7 +147,7 @@
 	real_buffer = efi_bounce_buffer;
 #endif
 
-	EFI_ENTRY("%p, %x, %"PRIx64", %lx, %p", this, media_id, lba,
+	EFI_ENTRY("%p, %x, %" PRIx64 ", %zx, %p", this, media_id, lba,
 		  buffer_size, buffer);
 
 	/* Populate bounce buffer if necessary */
@@ -175,49 +175,72 @@
 };
 
 /*
- * Find filesystem from a device-path.  The passed in path 'p' probably
- * contains one or more /File(name) nodes, so the comparison stops at
- * the first /File() node, and returns the pointer to that via 'rp'.
- * This is mostly intended to be a helper to map a device-path to an
- * efi_file_handle object.
+ * Get the simple file system protocol for a file device path.
+ *
+ * The full path provided is split into device part and into a file
+ * part. The device part is used to find the handle on which the
+ * simple file system protocol is installed.
+ *
+ * @full_path	device path including device and file
+ * @return	simple file system protocol
  */
 struct efi_simple_file_system_protocol *
-efi_fs_from_path(struct efi_device_path *fp)
+efi_fs_from_path(struct efi_device_path *full_path)
 {
 	struct efi_object *efiobj;
-	struct efi_disk_obj *diskobj;
+	struct efi_handler *handler;
+	struct efi_device_path *device_path;
+	struct efi_device_path *file_path;
+	efi_status_t ret;
 
-	efiobj = efi_dp_find_obj(fp, NULL);
+	/* Split the path into a device part and a file part */
+	ret = efi_dp_split_file_path(full_path, &device_path, &file_path);
+	if (ret != EFI_SUCCESS)
+		return NULL;
+	efi_free_pool(file_path);
+
+	/* Get the EFI object for the partition */
+	efiobj = efi_dp_find_obj(device_path, NULL);
+	efi_free_pool(device_path);
 	if (!efiobj)
 		return NULL;
 
-	diskobj = container_of(efiobj, struct efi_disk_obj, parent);
+	/* Find the simple file system protocol */
+	ret = efi_search_protocol(efiobj, &efi_simple_file_system_protocol_guid,
+				  &handler);
+	if (ret != EFI_SUCCESS)
+		return NULL;
 
-	return diskobj->volume;
+	/* Return the simple file system protocol for the partition */
+	return handler->protocol_interface;
 }
 
 /*
- * Create a device for a disk
+ * Create a handle for a partition or disk
  *
- * @name	not used
+ * @parent	parent handle
+ * @dp_parent	parent device path
  * @if_typename interface name for block device
  * @desc	internal block device
  * @dev_index   device index for block device
  * @offset	offset into disk for simple partitions
+ * @return	disk object
  */
-static void efi_disk_add_dev(const char *name,
-			     const char *if_typename,
-			     struct blk_desc *desc,
-			     int dev_index,
-			     lbaint_t offset,
-			     unsigned int part)
+static struct efi_disk_obj *efi_disk_add_dev(
+				efi_handle_t parent,
+				struct efi_device_path *dp_parent,
+				const char *if_typename,
+				struct blk_desc *desc,
+				int dev_index,
+				lbaint_t offset,
+				unsigned int part)
 {
 	struct efi_disk_obj *diskobj;
 	efi_status_t ret;
 
 	/* Don't add empty devices */
 	if (!desc->lba)
-		return;
+		return NULL;
 
 	diskobj = calloc(1, sizeof(*diskobj));
 	if (!diskobj)
@@ -227,7 +250,14 @@
 	efi_add_handle(&diskobj->parent);
 
 	/* Fill in object data */
-	diskobj->dp = efi_dp_from_part(desc, part);
+	if (part) {
+		struct efi_device_path *node = efi_dp_part_node(desc, part);
+
+		diskobj->dp = efi_dp_append_node(dp_parent, node);
+		efi_free_pool(node);
+	} else {
+		diskobj->dp = efi_dp_from_part(desc, part);
+	}
 	diskobj->part = part;
 	ret = efi_add_protocol(diskobj->parent.handle, &efi_block_io_guid,
 			       &diskobj->ops);
@@ -242,7 +272,7 @@
 							 diskobj->dp);
 		ret = efi_add_protocol(diskobj->parent.handle,
 				       &efi_simple_file_system_protocol_guid,
-				       &diskobj->volume);
+				       diskobj->volume);
 		if (ret != EFI_SUCCESS)
 			goto out_of_memory;
 	}
@@ -261,20 +291,38 @@
 	if (part != 0)
 		diskobj->media.logical_partition = 1;
 	diskobj->ops.media = &diskobj->media;
-	return;
+	return diskobj;
 out_of_memory:
 	printf("ERROR: Out of memory\n");
+	return NULL;
 }
 
-static int efi_disk_create_partitions(struct blk_desc *desc,
-				      const char *if_typename,
-				      int diskid,
-				      const char *pdevname)
+/*
+ * Create handles and protocols for the partitions of a block device
+ *
+ * @parent		handle of the parent disk
+ * @blk_desc		block device
+ * @if_typename		interface type
+ * @diskid		device number
+ * @pdevname		device name
+ * @return		number of partitions created
+ */
+int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
+			       const char *if_typename, int diskid,
+			       const char *pdevname)
 {
 	int disks = 0;
 	char devname[32] = { 0 }; /* dp->str is u16[32] long */
 	disk_partition_t info;
 	int part;
+	struct efi_device_path *dp = NULL;
+	efi_status_t ret;
+	struct efi_handler *handler;
+
+	/* Get the device path of the parent */
+	ret = efi_search_protocol(parent, &efi_guid_device_path, &handler);
+	if (ret == EFI_SUCCESS)
+		dp = handler->protocol_interface;
 
 	/* Add devices for each partition */
 	for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
@@ -282,7 +330,7 @@
 			continue;
 		snprintf(devname, sizeof(devname), "%s:%d", pdevname,
 			 part);
-		efi_disk_add_dev(devname, if_typename, desc, diskid,
+		efi_disk_add_dev(parent, dp, if_typename, desc, diskid,
 				 info.start, part);
 		disks++;
 	}
@@ -303,6 +351,7 @@
  */
 int efi_disk_register(void)
 {
+	struct efi_disk_obj *disk;
 	int disks = 0;
 #ifdef CONFIG_BLK
 	struct udevice *dev;
@@ -311,19 +360,21 @@
 	     dev;
 	     uclass_next_device_check(&dev)) {
 		struct blk_desc *desc = dev_get_uclass_platdata(dev);
-		const char *if_typename = dev->driver->name;
+		const char *if_typename = blk_get_if_type_name(desc->if_type);
 
 		printf("Scanning disk %s...\n", dev->name);
 
 		/* Add block device for the full device */
-		efi_disk_add_dev(dev->name, if_typename, desc,
-				 desc->devnum, 0, 0);
-
+		disk = efi_disk_add_dev(NULL, NULL, if_typename,
+					desc, desc->devnum, 0, 0);
+		if (!disk)
+			return -ENOMEM;
 		disks++;
 
 		/* Partitions show up as block devices in EFI */
-		disks += efi_disk_create_partitions(desc, if_typename,
-						    desc->devnum, dev->name);
+		disks += efi_disk_create_partitions(
+					disk->parent.handle, desc, if_typename,
+					desc->devnum, dev->name);
 	}
 #else
 	int i, if_type;
@@ -353,12 +404,16 @@
 				 if_typename, i);
 
 			/* Add block device for the full device */
-			efi_disk_add_dev(devname, if_typename, desc, i, 0, 0);
+			disk = efi_disk_add_dev(NULL, NULL, if_typename, desc,
+						i, 0, 0);
+			if (!disk)
+				return -ENOMEM;
 			disks++;
 
 			/* Partitions show up as block devices in EFI */
-			disks += efi_disk_create_partitions(desc, if_typename,
-							    i, devname);
+			disks += efi_disk_create_partitions(
+						disk->parent.handle, desc,
+						if_typename, i, devname);
 		}
 	}
 #endif
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index af29cc4..9d2214b 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -74,6 +74,40 @@
 }
 
 /*
+ * Determine the memory types to be used for code and data.
+ *
+ * @loaded_image_info	image descriptor
+ * @image_type		field Subsystem of the optional header for
+ *			Windows specific field
+ */
+static void efi_set_code_and_data_type(
+			struct efi_loaded_image *loaded_image_info,
+			uint16_t image_type)
+{
+	switch (image_type) {
+	case IMAGE_SUBSYSTEM_EFI_APPLICATION:
+		loaded_image_info->image_code_type = EFI_LOADER_CODE;
+		loaded_image_info->image_data_type = EFI_LOADER_DATA;
+		break;
+	case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
+		loaded_image_info->image_code_type = EFI_BOOT_SERVICES_CODE;
+		loaded_image_info->image_data_type = EFI_BOOT_SERVICES_DATA;
+		break;
+	case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
+	case IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
+		loaded_image_info->image_code_type = EFI_RUNTIME_SERVICES_CODE;
+		loaded_image_info->image_data_type = EFI_RUNTIME_SERVICES_DATA;
+		break;
+	default:
+		printf("%s: invalid image type: %u\n", __func__, image_type);
+		/* Let's assume it is an application */
+		loaded_image_info->image_code_type = EFI_LOADER_CODE;
+		loaded_image_info->image_data_type = EFI_LOADER_DATA;
+		break;
+	}
+}
+
+/*
  * This function loads all sections from a PE binary into a newly reserved
  * piece of memory. On successful load it then returns the entry point for
  * the binary. Otherwise NULL.
@@ -94,7 +128,6 @@
 	unsigned long virt_size = 0;
 	bool can_run_nt64 = true;
 	bool can_run_nt32 = true;
-	uint16_t image_type;
 
 #if defined(CONFIG_ARM64)
 	can_run_nt32 = false;
@@ -131,55 +164,38 @@
 		IMAGE_NT_HEADERS64 *nt64 = (void *)nt;
 		IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader;
 		image_size = opt->SizeOfImage;
-		efi_reloc = efi_alloc(virt_size, EFI_LOADER_DATA);
+		efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
+		efi_reloc = efi_alloc(virt_size,
+				      loaded_image_info->image_code_type);
 		if (!efi_reloc) {
-			printf("%s: Could not allocate %ld bytes\n",
-				__func__, virt_size);
+			printf("%s: Could not allocate %lu bytes\n",
+			       __func__, virt_size);
 			return NULL;
 		}
 		entry = efi_reloc + opt->AddressOfEntryPoint;
 		rel_size = opt->DataDirectory[rel_idx].Size;
 		rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
-		image_type = opt->Subsystem;
 	} else if (can_run_nt32 &&
 		   (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)) {
 		IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader;
 		image_size = opt->SizeOfImage;
-		efi_reloc = efi_alloc(virt_size, EFI_LOADER_DATA);
+		efi_set_code_and_data_type(loaded_image_info, opt->Subsystem);
+		efi_reloc = efi_alloc(virt_size,
+				      loaded_image_info->image_code_type);
 		if (!efi_reloc) {
-			printf("%s: Could not allocate %ld bytes\n",
-				__func__, virt_size);
+			printf("%s: Could not allocate %lu bytes\n",
+			       __func__, virt_size);
 			return NULL;
 		}
 		entry = efi_reloc + opt->AddressOfEntryPoint;
 		rel_size = opt->DataDirectory[rel_idx].Size;
 		rel = efi_reloc + opt->DataDirectory[rel_idx].VirtualAddress;
-		image_type = opt->Subsystem;
 	} else {
 		printf("%s: Invalid optional header magic %x\n", __func__,
 		       nt->OptionalHeader.Magic);
 		return NULL;
 	}
 
-	switch (image_type) {
-	case IMAGE_SUBSYSTEM_EFI_APPLICATION:
-		loaded_image_info->image_code_type = EFI_LOADER_CODE;
-		loaded_image_info->image_data_type = EFI_LOADER_DATA;
-		break;
-	case IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
-		loaded_image_info->image_code_type = EFI_BOOT_SERVICES_CODE;
-		loaded_image_info->image_data_type = EFI_BOOT_SERVICES_DATA;
-		break;
-	case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
-	case IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
-		loaded_image_info->image_code_type = EFI_RUNTIME_SERVICES_CODE;
-		loaded_image_info->image_data_type = EFI_RUNTIME_SERVICES_DATA;
-		break;
-	default:
-		printf("%s: invalid image type: %u\n", __func__, image_type);
-		break;
-	}
-
 	/* Load sections into RAM */
 	for (i = num_sections - 1; i >= 0; i--) {
 		IMAGE_SECTION_HEADER *sec = &sections[i];
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 0aa3e08..aaf6442 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -275,6 +275,15 @@
 	return 0;
 }
 
+/*
+ * Allocate memory pages.
+ *
+ * @type		type of allocation to be performed
+ * @memory_type		usage type of the allocated memory
+ * @pages		number of pages to be allocated
+ * @memory		allocated memory
+ * @return		status code
+ */
 efi_status_t efi_allocate_pages(int type, int memory_type,
 				efi_uintn_t pages, uint64_t *memory)
 {
@@ -338,6 +347,13 @@
 	return NULL;
 }
 
+/*
+ * Free memory pages.
+ *
+ * @memory	start of the memory area to be freed
+ * @pages	number of pages to be freed
+ * @return	status code
+ */
 efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
 {
 	uint64_t r = 0;
@@ -351,8 +367,15 @@
 	return EFI_NOT_FOUND;
 }
 
-efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size,
-			       void **buffer)
+/*
+ * Allocate memory from pool.
+ *
+ * @pool_type	type of the pool from which memory is to be allocated
+ * @size	number of bytes to be allocated
+ * @buffer	allocated memory
+ * @return	status code
+ */
+efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer)
 {
 	efi_status_t r;
 	efi_physical_addr_t t;
@@ -375,6 +398,12 @@
 	return r;
 }
 
+/*
+ * Free memory from pool.
+ *
+ * @buffer	start of memory to be freed
+ * @return	status code
+ */
 efi_status_t efi_free_pool(void *buffer)
 {
 	efi_status_t r;
@@ -392,6 +421,17 @@
 	return r;
 }
 
+/*
+ * Get map describing memory usage.
+ *
+ * @memory_map_size	on entry the size, in bytes, of the memory map buffer,
+ *			on exit the size of the copied memory map
+ * @memory_map		buffer to which the memory map is written
+ * @map_key		key for the memory map
+ * @descriptor_size	size of an individual memory descriptor
+ * @descriptor_version	version number of the memory descriptor structure
+ * @return		status code
+ */
 efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
 				struct efi_mem_desc *memory_map,
 				efi_uintn_t *map_key,
diff --git a/lib/efi_loader/helloworld.c b/lib/efi_loader/helloworld.c
index b8c147d..1ec0179 100644
--- a/lib/efi_loader/helloworld.c
+++ b/lib/efi_loader/helloworld.c
@@ -14,6 +14,22 @@
 #include <efi_api.h>
 
 static const efi_guid_t loaded_image_guid = LOADED_IMAGE_GUID;
+static const efi_guid_t fdt_guid = EFI_FDT_GUID;
+static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
+
+static int hw_memcmp(const void *buf1, const void *buf2, size_t length)
+{
+	const u8 *pos1 = buf1;
+	const u8 *pos2 = buf2;
+
+	for (; length; --length) {
+		if (*pos1 != *pos2)
+			return *pos1 - *pos2;
+		++pos1;
+		++pos2;
+	}
+	return 0;
+}
 
 /*
  * Entry point of the EFI application.
@@ -29,6 +45,7 @@
 	struct efi_boot_services *boottime = systable->boottime;
 	struct efi_loaded_image *loaded_image;
 	efi_status_t ret;
+	efi_uintn_t i;
 
 	con_out->output_string(con_out, L"Hello, world!\n");
 
@@ -40,6 +57,15 @@
 				       L"Cannot open loaded image protocol\n");
 		goto out;
 	}
+	/* Find configuration tables */
+	for (i = 0; i < systable->nr_tables; ++i) {
+		if (!hw_memcmp(&systable->tables[i].guid, &fdt_guid,
+			       sizeof(efi_guid_t)))
+			con_out->output_string(con_out, L"Have device tree\n");
+		if (!hw_memcmp(&systable->tables[i].guid, &smbios_guid,
+			       sizeof(efi_guid_t)))
+			con_out->output_string(con_out, L"Have SMBIOS table\n");
+	}
 	/* Output the load options */
 	con_out->output_string(con_out, L"Load options: ");
 	if (loaded_image->load_options_size && loaded_image->load_options)
diff --git a/lib/efi_selftest/.gitignore b/lib/efi_selftest/.gitignore
new file mode 100644
index 0000000..c527e46
--- /dev/null
+++ b/lib/efi_selftest/.gitignore
@@ -0,0 +1,2 @@
+efi_miniapp_file_image.h
+*.efi
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 837e862..90246f7 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -7,8 +7,12 @@
 # This file only gets included with CONFIG_EFI_LOADER set, so all
 # object inclusion implicitly depends on it
 
+CFLAGS_efi_selftest_miniapp.o := $(CFLAGS_EFI) -Os -ffreestanding
+CFLAGS_REMOVE_efi_selftest_miniapp.o := $(CFLAGS_NON_EFI) -Os
+
 obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += \
 efi_selftest.o \
+efi_selftest_controllers.o \
 efi_selftest_console.o \
 efi_selftest_devicepath.o \
 efi_selftest_events.o \
@@ -20,3 +24,39 @@
 efi_selftest_tpl.o \
 efi_selftest_util.o \
 efi_selftest_watchdog.o
+
+ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy)
+obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest_block_device.o
+endif
+
+# TODO: As of v2018.01 the relocation code for the EFI application cannot
+# be built on x86_64.
+ifeq ($(CONFIG_X86_64),)
+
+ifneq ($(CONFIG_CMD_BOOTEFI_SELFTEST),)
+
+obj-y += \
+efi_selftest_startimage_exit.o \
+efi_selftest_startimage_return.o
+
+targets += \
+efi_miniapp_file_image_exit.h \
+efi_miniapp_file_image_return.h \
+efi_selftest_miniapp_exit.efi \
+efi_selftest_miniapp_return.efi
+
+$(obj)/efi_miniapp_file_image_exit.h: $(obj)/efi_selftest_miniapp_exit.efi
+	$(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exit.efi > \
+	$(obj)/efi_miniapp_file_image_exit.h
+
+$(obj)/efi_miniapp_file_image_return.h: $(obj)/efi_selftest_miniapp_return.efi
+	$(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_return.efi > \
+	$(obj)/efi_miniapp_file_image_return.h
+
+$(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_image_exit.h
+
+$(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_image_return.h
+
+endif
+
+endif
diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c
index 4e5a12c..fc5ef25 100644
--- a/lib/efi_selftest/efi_selftest.c
+++ b/lib/efi_selftest/efi_selftest.c
@@ -65,7 +65,7 @@
 		efi_st_error("ExitBootServices did not return EFI_SUCCESS\n");
 		return;
 	}
-	efi_st_printf("\nBoot services terminated\n");
+	efi_st_printc(EFI_WHITE, "\nBoot services terminated\n");
 }
 
 /*
@@ -81,13 +81,14 @@
 
 	if (!test->setup)
 		return EFI_ST_SUCCESS;
-	efi_st_printf("\nSetting up '%s'\n", test->name);
+	efi_st_printc(EFI_LIGHTBLUE, "\nSetting up '%s'\n", test->name);
 	ret = test->setup(handle, systable);
 	if (ret != EFI_ST_SUCCESS) {
 		efi_st_error("Setting up '%s' failed\n", test->name);
 		++*failures;
 	} else {
-		efi_st_printf("Setting up '%s' succeeded\n", test->name);
+		efi_st_printc(EFI_LIGHTGREEN,
+			      "Setting up '%s' succeeded\n", test->name);
 	}
 	return ret;
 }
@@ -105,13 +106,14 @@
 
 	if (!test->execute)
 		return EFI_ST_SUCCESS;
-	efi_st_printf("\nExecuting '%s'\n", test->name);
+	efi_st_printc(EFI_LIGHTBLUE, "\nExecuting '%s'\n", test->name);
 	ret = test->execute();
 	if (ret != EFI_ST_SUCCESS) {
 		efi_st_error("Executing '%s' failed\n", test->name);
 		++*failures;
 	} else {
-		efi_st_printf("Executing '%s' succeeded\n", test->name);
+		efi_st_printc(EFI_LIGHTGREEN,
+			      "Executing '%s' succeeded\n", test->name);
 	}
 	return ret;
 }
@@ -129,13 +131,14 @@
 
 	if (!test->teardown)
 		return EFI_ST_SUCCESS;
-	efi_st_printf("\nTearing down '%s'\n", test->name);
+	efi_st_printc(EFI_LIGHTBLUE, "\nTearing down '%s'\n", test->name);
 	ret = test->teardown();
 	if (ret != EFI_ST_SUCCESS) {
 		efi_st_error("Tearing down '%s' failed\n", test->name);
 		++*failures;
 	} else {
-		efi_st_printf("Tearing down '%s' succeeded\n", test->name);
+		efi_st_printc(EFI_LIGHTGREEN,
+			      "Tearing down '%s' succeeded\n", test->name);
 	}
 	return ret;
 }
@@ -262,12 +265,12 @@
 		}
 	}
 
-	efi_st_printf("\nTesting EFI API implementation\n");
+	efi_st_printc(EFI_WHITE, "\nTesting EFI API implementation\n");
 
 	if (testname)
-		efi_st_printf("\nSelected test: '%ps'\n", testname);
+		efi_st_printc(EFI_WHITE, "\nSelected test: '%ps'\n", testname);
 	else
-		efi_st_printf("\nNumber of tests to execute: %u\n",
+		efi_st_printc(EFI_WHITE, "\nNumber of tests to execute: %u\n",
 			      ll_entry_count(struct efi_unit_test,
 					     efi_unit_test));
 
@@ -291,7 +294,7 @@
 			&failures);
 
 	/* Give feedback */
-	efi_st_printf("\nSummary: %u failures\n\n", failures);
+	efi_st_printc(EFI_WHITE, "\nSummary: %u failures\n\n", failures);
 
 	/* Reset system */
 	efi_st_printf("Preparing for reset. Press any key.\n");
diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c
new file mode 100644
index 0000000..9e4b93d
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_block_device.c
@@ -0,0 +1,395 @@
+/*
+ * efi_selftest_block
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This test checks the driver for block IO devices.
+ * A disk image is created in memory.
+ * A handle is created for the new block IO device.
+ * The block I/O protocol is installed on the handle.
+ * ConnectController is used to setup partitions and to install the simple
+ * file protocol.
+ * A known file is read from the file system and verified.
+ */
+
+#include <efi_selftest.h>
+#include "efi_selftest_disk_image.h"
+
+/* Block size of compressed disk image */
+#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
+
+/* Binary logarithm of the block size */
+#define LB_BLOCK_SIZE 9
+
+static struct efi_boot_services *boottime;
+
+static const efi_guid_t block_io_protocol_guid = BLOCK_IO_GUID;
+static const efi_guid_t guid_device_path = DEVICE_PATH_GUID;
+static const efi_guid_t guid_simple_file_system_protocol =
+					EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
+static efi_guid_t guid_vendor =
+	EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d,
+		 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xb7, 0xb8);
+
+static struct efi_device_path *dp;
+
+/* One 8 byte block of the compressed disk image */
+struct line {
+	size_t addr;
+	char *line;
+};
+
+/* Compressed disk image */
+struct compressed_disk_image {
+	size_t length;
+	struct line lines[];
+};
+
+static const struct compressed_disk_image img = EFI_ST_DISK_IMG;
+
+/* Decompressed disk image */
+static u8 *image;
+
+/*
+ * Reset service of the block IO protocol.
+ *
+ * @this	block IO protocol
+ * @return	status code
+ */
+static efi_status_t EFIAPI reset(
+			struct efi_block_io *this,
+			char extended_verification)
+{
+	return EFI_SUCCESS;
+}
+
+/*
+ * Read service of the block IO protocol.
+ *
+ * @this	block IO protocol
+ * @media_id	media id
+ * @lba		start of the read in logical blocks
+ * @buffer_size	number of bytes to read
+ * @buffer	target buffer
+ * @return	status code
+ */
+static efi_status_t EFIAPI read_blocks(
+			struct efi_block_io *this, u32 media_id, u64 lba,
+			efi_uintn_t buffer_size, void *buffer)
+{
+	u8 *start;
+
+	if ((lba << LB_BLOCK_SIZE) + buffer_size > img.length)
+		return EFI_INVALID_PARAMETER;
+	start = image + (lba << LB_BLOCK_SIZE);
+
+	boottime->copy_mem(buffer, start, buffer_size);
+
+	return EFI_SUCCESS;
+}
+
+/*
+ * Write service of the block IO protocol.
+ *
+ * @this	block IO protocol
+ * @media_id	media id
+ * @lba		start of the write in logical blocks
+ * @buffer_size	number of bytes to read
+ * @buffer	source buffer
+ * @return	status code
+ */
+static efi_status_t EFIAPI write_blocks(
+			struct efi_block_io *this, u32 media_id, u64 lba,
+			efi_uintn_t buffer_size, void *buffer)
+{
+	u8 *start;
+
+	if ((lba << LB_BLOCK_SIZE) + buffer_size > img.length)
+		return EFI_INVALID_PARAMETER;
+	start = image + (lba << LB_BLOCK_SIZE);
+
+	boottime->copy_mem(start, buffer, buffer_size);
+
+	return EFI_SUCCESS;
+}
+
+/*
+ * Flush service of the block IO protocol.
+ *
+ * @this	block IO protocol
+ * @return	status code
+ */
+static efi_status_t EFIAPI flush_blocks(struct efi_block_io *this)
+{
+	return EFI_SUCCESS;
+}
+
+/*
+ * Decompress the disk image.
+ *
+ * @image	decompressed disk image
+ * @return	status code
+ */
+static efi_status_t decompress(u8 **image)
+{
+	u8 *buf;
+	size_t i;
+	size_t addr;
+	size_t len;
+	efi_status_t ret;
+
+	ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
+				      (void **)&buf);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Out of memory\n");
+		return ret;
+	}
+	boottime->set_mem(buf, img.length, 0);
+
+	for (i = 0; ; ++i) {
+		if (!img.lines[i].line)
+			break;
+		addr = img.lines[i].addr;
+		len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
+		if (addr + len > img.length)
+			len = img.length - addr;
+		boottime->copy_mem(buf + addr, img.lines[i].line, len);
+	}
+	*image = buf;
+	return ret;
+}
+
+static struct efi_block_io_media media;
+
+static struct efi_block_io block_io = {
+	.media = &media,
+	.reset = reset,
+	.read_blocks = read_blocks,
+	.write_blocks = write_blocks,
+	.flush_blocks = flush_blocks,
+};
+
+/* Handle for the block IO device */
+static efi_handle_t disk_handle;
+
+/*
+ * Setup unit test.
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+		 const struct efi_system_table *systable)
+{
+	efi_status_t ret;
+	struct efi_device_path_vendor vendor_node;
+	struct efi_device_path end_node;
+
+	boottime = systable->boottime;
+
+	decompress(&image);
+
+	block_io.media->block_size = 1 << LB_BLOCK_SIZE;
+	block_io.media->last_block = img.length >> LB_BLOCK_SIZE;
+
+	ret = boottime->install_protocol_interface(
+				&disk_handle, &block_io_protocol_guid,
+				EFI_NATIVE_INTERFACE, &block_io);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to install block I/O protocol\n");
+		return EFI_ST_FAILURE;
+	}
+
+	ret = boottime->allocate_pool(EFI_LOADER_DATA,
+				      sizeof(struct efi_device_path_vendor) +
+				      sizeof(struct efi_device_path),
+				      (void **)&dp);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Out of memory\n");
+		return EFI_ST_FAILURE;
+	}
+	vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
+	vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
+	vendor_node.dp.length = sizeof(struct efi_device_path_vendor);
+
+	boottime->copy_mem(&vendor_node.guid, &guid_vendor,
+			   sizeof(efi_guid_t));
+	boottime->copy_mem(dp, &vendor_node,
+			   sizeof(struct efi_device_path_vendor));
+	end_node.type = DEVICE_PATH_TYPE_END;
+	end_node.sub_type = DEVICE_PATH_SUB_TYPE_END;
+	end_node.length = sizeof(struct efi_device_path);
+
+	boottime->copy_mem((char *)dp + sizeof(struct efi_device_path_vendor),
+			   &end_node, sizeof(struct efi_device_path));
+	ret = boottime->install_protocol_interface(&disk_handle,
+						   &guid_device_path,
+						   EFI_NATIVE_INTERFACE,
+						   dp);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("InstallProtocolInterface failed\n");
+		return EFI_ST_FAILURE;
+	}
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+	efi_status_t r = EFI_ST_SUCCESS;
+
+	if (disk_handle) {
+		r = boottime->uninstall_protocol_interface(disk_handle,
+							   &guid_device_path,
+							   dp);
+		if (r != EFI_SUCCESS) {
+			efi_st_error("Uninstall device path failed\n");
+			return EFI_ST_FAILURE;
+		}
+		r = boottime->uninstall_protocol_interface(
+				disk_handle, &block_io_protocol_guid,
+				&block_io);
+		if (r != EFI_SUCCESS) {
+			efi_st_todo(
+				"Failed to uninstall block I/O protocol\n");
+			return EFI_ST_SUCCESS;
+		}
+	}
+
+	if (image) {
+		r = efi_free_pool(image);
+		if (r != EFI_SUCCESS) {
+			efi_st_error("Failed to free image\n");
+			return EFI_ST_FAILURE;
+		}
+	}
+	return r;
+}
+
+/*
+ * Get length of device path without end tag.
+ *
+ * @dp		device path
+ * @return	length of device path in bytes
+ */
+static efi_uintn_t dp_size(struct efi_device_path *dp)
+{
+	struct efi_device_path *pos = dp;
+
+	while (pos->type != DEVICE_PATH_TYPE_END)
+		pos = (struct efi_device_path *)((char *)pos + pos->length);
+	return (char *)pos - (char *)dp;
+}
+
+/*
+ * Execute unit test.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+	efi_status_t ret;
+	efi_uintn_t no_handles, i, len;
+	efi_handle_t *handles;
+	efi_handle_t handle_partition = NULL;
+	struct efi_device_path *dp_partition;
+	struct efi_simple_file_system_protocol *file_system;
+	struct efi_file_handle *root, *file;
+	u64 buf_size;
+	char buf[16] __aligned(ARCH_DMA_MINALIGN);
+
+	ret = boottime->connect_controller(disk_handle, NULL, NULL, 1);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to connect controller\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->locate_handle_buffer(
+				BY_PROTOCOL, &guid_device_path, NULL,
+				&no_handles, &handles);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to locate handles\n");
+		return EFI_ST_FAILURE;
+	}
+	len = dp_size(dp);
+	for (i = 0; i < no_handles; ++i) {
+		ret = boottime->open_protocol(handles[i], &guid_device_path,
+					      (void **)&dp_partition,
+					      NULL, NULL,
+					      EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("Failed to open device path protocol\n");
+			return EFI_ST_FAILURE;
+		}
+		if (len >= dp_size(dp_partition))
+			continue;
+		if (efi_st_memcmp(dp, dp_partition, len))
+			continue;
+		handle_partition = handles[i];
+		break;
+	}
+	ret = boottime->free_pool(handles);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to free pool memory\n");
+		return EFI_ST_FAILURE;
+	}
+	if (!handle_partition) {
+		efi_st_error("Partition handle not found\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->open_protocol(handle_partition,
+				      &guid_simple_file_system_protocol,
+				      (void **)&file_system, NULL, NULL,
+				      EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to open simple file system protocol\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = file_system->open_volume(file_system, &root);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to open volume\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = root->open(root, &file, (s16 *)L"hello.txt", EFI_FILE_MODE_READ,
+			 0);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to open file\n");
+		return EFI_ST_FAILURE;
+	}
+	buf_size = sizeof(buf) - 1;
+	ret = file->read(file, &buf_size, buf);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to read file\n");
+		return EFI_ST_FAILURE;
+	}
+	if (efi_st_memcmp(buf, "Hello world!", 12)) {
+		efi_st_error("Unexpected file content\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = file->close(file);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to close file\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = root->close(root);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to close volume\n");
+		return EFI_ST_FAILURE;
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(blkdev) = {
+	.name = "block device",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+	.teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_console.c b/lib/efi_selftest/efi_selftest_console.c
index 6a7fd20..e1649f4 100644
--- a/lib/efi_selftest/efi_selftest_console.c
+++ b/lib/efi_selftest/efi_selftest_console.c
@@ -130,22 +130,25 @@
 }
 
 /*
- * Print a formatted string to the EFI console
+ * Print a colored formatted string to the EFI console
  *
- * @fmt: format string
- * @...: optional arguments
+ * @color	color, see constants in efi_api.h, use -1 for no color
+ * @fmt		format string
+ * @...		optional arguments
  */
-void efi_st_printf(const char *fmt, ...)
+void efi_st_printc(int color, const char *fmt, ...)
 {
 	va_list args;
 	u16 buf[160];
 	const char *c;
 	u16 *pos = buf;
 	const char *s;
-	const u16 *u;
+	u16 *u;
 
 	va_start(args, fmt);
 
+	if (color >= 0)
+		con_out->set_attribute(con_out, (unsigned long)color);
 	c = fmt;
 	for (; *c; ++c) {
 		switch (*c) {
@@ -188,9 +191,13 @@
 				/* u16 string */
 				case 's':
 					u = va_arg(args, u16*);
-					/* Ensure string fits into buffer */
-					for (; *u && pos < buf + 120; ++u)
-						*pos++ = *u;
+					if (pos > buf) {
+						*pos = 0;
+						con_out->output_string(con_out,
+								       buf);
+					}
+					con_out->output_string(con_out, u);
+					pos = buf;
 					break;
 				default:
 					--c;
@@ -216,6 +223,8 @@
 	va_end(args);
 	*pos = 0;
 	con_out->output_string(con_out, buf);
+	if (color >= 0)
+		con_out->set_attribute(con_out, EFI_LIGHTGRAY);
 }
 
 /*
diff --git a/lib/efi_selftest/efi_selftest_controllers.c b/lib/efi_selftest/efi_selftest_controllers.c
new file mode 100644
index 0000000..1a22aba
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_controllers.c
@@ -0,0 +1,385 @@
+/*
+ * efi_selftest_controllers
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This unit test checks the following protocol services:
+ * ConnectController, DisconnectController,
+ * InstallProtocol, UninstallProtocol,
+ * OpenProtocol, CloseProtcol, OpenProtocolInformation
+ */
+
+#include <efi_selftest.h>
+
+#define NUMBER_OF_CHILD_CONTROLLERS 4
+
+static struct efi_boot_services *boottime;
+const efi_guid_t guid_driver_binding_protocol =
+			EFI_DRIVER_BINDING_PROTOCOL_GUID;
+static efi_guid_t guid_controller =
+	EFI_GUID(0xe6ab1d96, 0x6bff, 0xdb42,
+		 0xaa, 0x05, 0xc8, 0x1f, 0x7f, 0x45, 0x26, 0x34);
+static efi_guid_t guid_child_controller =
+	EFI_GUID(0x1d41f6f5, 0x2c41, 0xddfb,
+		 0xe2, 0x9b, 0xb8, 0x0e, 0x2e, 0xe8, 0x3a, 0x85);
+static efi_handle_t handle_controller;
+static efi_handle_t handle_child_controller[NUMBER_OF_CHILD_CONTROLLERS];
+static efi_handle_t handle_driver;
+
+/*
+ * Count child controllers
+ *
+ * @handle	handle on which child controllers are installed
+ * @protocol	protocol for which the child controlles where installed
+ * @count	number of child controllers
+ * @return	status code
+ */
+static efi_status_t count_child_controllers(efi_handle_t handle,
+					    efi_guid_t *protocol,
+					    efi_uintn_t *count)
+{
+	efi_status_t ret;
+	efi_uintn_t entry_count;
+	struct efi_open_protocol_info_entry *entry_buffer;
+
+	*count = 0;
+	ret = boottime->open_protocol_information(handle, protocol,
+						  &entry_buffer, &entry_count);
+	if (ret != EFI_SUCCESS)
+		return ret;
+	if (!entry_count)
+		return EFI_SUCCESS;
+	while (entry_count) {
+		if (entry_buffer[--entry_count].attributes &
+		    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
+			++*count;
+	}
+	ret = boottime->free_pool(entry_buffer);
+	if (ret != EFI_SUCCESS)
+		efi_st_error("Cannot free buffer\n");
+	return ret;
+}
+
+/*
+ * Check if the driver supports the controller.
+ *
+ * @this			driver binding protocol
+ * @controller_handle		handle of the controller
+ * @remaining_device_path	path specifying the child controller
+ * @return			status code
+ */
+static efi_status_t EFIAPI supported(
+		struct efi_driver_binding_protocol *this,
+		efi_handle_t controller_handle,
+		struct efi_device_path *remaining_device_path)
+{
+	efi_status_t ret;
+	void *interface;
+
+	ret = boottime->open_protocol(
+			controller_handle, &guid_controller,
+			&interface, handle_driver,
+			controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+	switch (ret) {
+	case EFI_ACCESS_DENIED:
+	case EFI_ALREADY_STARTED:
+		return ret;
+	case EFI_SUCCESS:
+		break;
+	default:
+		return EFI_UNSUPPORTED;
+	}
+	ret = boottime->close_protocol(
+				controller_handle, &guid_controller,
+				handle_driver, controller_handle);
+	if (ret != EFI_SUCCESS)
+		ret = EFI_UNSUPPORTED;
+	return ret;
+}
+
+/*
+ * Create child controllers and attach driver.
+ *
+ * @this			driver binding protocol
+ * @controller_handle		handle of the controller
+ * @remaining_device_path	path specifying the child controller
+ * @return			status code
+ */
+static efi_status_t EFIAPI start(
+		struct efi_driver_binding_protocol *this,
+		efi_handle_t controller_handle,
+		struct efi_device_path *remaining_device_path)
+{
+	size_t i;
+	efi_status_t ret;
+	void *interface;
+
+	/* Attach driver to controller */
+	ret = boottime->open_protocol(
+			controller_handle, &guid_controller,
+			&interface, handle_driver,
+			controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+	switch (ret) {
+	case EFI_ACCESS_DENIED:
+	case EFI_ALREADY_STARTED:
+		return ret;
+	case EFI_SUCCESS:
+		break;
+	default:
+		return EFI_UNSUPPORTED;
+	}
+
+	/* Create child controllers */
+	for (i = 0; i < NUMBER_OF_CHILD_CONTROLLERS; ++i) {
+		ret = boottime->install_protocol_interface(
+			&handle_child_controller[i], &guid_child_controller,
+			EFI_NATIVE_INTERFACE, NULL);
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("InstallProtocolInterface failed\n");
+			return EFI_ST_FAILURE;
+		}
+		ret = boottime->open_protocol(
+			controller_handle, &guid_controller,
+			&interface, handle_child_controller[i],
+			handle_child_controller[i],
+			EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("OpenProtocol failed\n");
+			return EFI_ST_FAILURE;
+		}
+	}
+	return ret;
+}
+
+/*
+ * Remove a single child controller from the parent controller.
+ *
+ * @controller_handle	parent controller
+ * @child_handle	child controller
+ * @return		status code
+ */
+static efi_status_t disconnect_child(efi_handle_t controller_handle,
+				     efi_handle_t child_handle)
+{
+	efi_status_t ret;
+
+	ret = boottime->close_protocol(
+				controller_handle, &guid_controller,
+				child_handle, child_handle);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Cannot close protocol\n");
+		return ret;
+	}
+	ret = boottime->uninstall_protocol_interface(
+				child_handle, &guid_child_controller, NULL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Cannot uninstall protocol interface\n");
+		return ret;
+	}
+	return ret;
+}
+
+/*
+ * Remove child controllers and disconnect the controller.
+ *
+ * @this			driver binding protocol
+ * @controller_handle		handle of the controller
+ * @number_of_children		number of child controllers to remove
+ * @child_handle_buffer		handles of the child controllers to remove
+ * @return			status code
+ */
+static efi_status_t EFIAPI stop(
+		struct efi_driver_binding_protocol *this,
+		efi_handle_t controller_handle,
+		size_t number_of_children,
+		efi_handle_t *child_handle_buffer)
+{
+	efi_status_t ret;
+	efi_uintn_t count;
+	struct efi_open_protocol_info_entry *entry_buffer;
+
+	/* Destroy provided child controllers */
+	if (number_of_children) {
+		efi_uintn_t i;
+
+		for (i = 0; i < number_of_children; ++i) {
+			ret = disconnect_child(controller_handle,
+					       child_handle_buffer[i]);
+			if (ret != EFI_SUCCESS)
+				return ret;
+		}
+		return EFI_SUCCESS;
+	}
+
+	/* Destroy all children */
+	ret = boottime->open_protocol_information(
+					controller_handle, &guid_controller,
+					&entry_buffer, &count);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("OpenProtocolInformation failed\n");
+		return ret;
+	}
+	while (count) {
+		if (entry_buffer[--count].attributes &
+		    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+			ret = disconnect_child(
+					controller_handle,
+					entry_buffer[count].agent_handle);
+			if (ret != EFI_SUCCESS)
+				return ret;
+		}
+	}
+	ret = boottime->free_pool(entry_buffer);
+	if (ret != EFI_SUCCESS)
+		efi_st_error("Cannot free buffer\n");
+
+	/* Detach driver from controller */
+	ret = boottime->close_protocol(
+			controller_handle, &guid_controller,
+			handle_driver, controller_handle);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Cannot close protocol\n");
+		return ret;
+	}
+	return EFI_SUCCESS;
+}
+
+/* Driver binding protocol interface */
+static struct efi_driver_binding_protocol binding_interface = {
+	supported,
+	start,
+	stop,
+	0xffffffff,
+	NULL,
+	NULL,
+	};
+
+/*
+ * Setup unit test.
+ *
+ * @handle	handle of the loaded image
+ * @systable	system table
+ */
+static int setup(const efi_handle_t img_handle,
+		 const struct efi_system_table *systable)
+{
+	efi_status_t ret;
+
+	boottime = systable->boottime;
+
+	/* Create controller handle */
+	ret = boottime->install_protocol_interface(
+			&handle_controller, &guid_controller,
+			EFI_NATIVE_INTERFACE, NULL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("InstallProtocolInterface failed\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Create driver handle */
+	ret = boottime->install_protocol_interface(
+			&handle_driver,  &guid_driver_binding_protocol,
+			EFI_NATIVE_INTERFACE, &binding_interface);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("InstallProtocolInterface failed\n");
+		return EFI_ST_FAILURE;
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * The number of child controllers is checked after each of the following
+ * actions:
+ *
+ * Connect a controller to a driver.
+ * Disconnect and destroy a child controller.
+ * Disconnect and destroy the remaining child controllers.
+ *
+ * Connect a controller to a driver.
+ * Uninstall the driver protocol from the controller.
+ */
+static int execute(void)
+{
+	efi_status_t ret;
+	efi_uintn_t count;
+
+	/* Connect controller to driver */
+	ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to connect controller\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Check number of child controllers */
+	ret = count_child_controllers(handle_controller, &guid_controller,
+				      &count);
+	if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
+		efi_st_error("Number of children %u != %u\n",
+			     (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
+	}
+	/* Destroy second child controller */
+	ret = boottime->disconnect_controller(handle_controller,
+					      handle_driver,
+					      handle_child_controller[1]);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to disconnect child controller\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Check number of child controllers */
+	ret = count_child_controllers(handle_controller, &guid_controller,
+				      &count);
+	if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS - 1) {
+		efi_st_error("Destroying single child controller failed\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Destroy remaining child controllers and disconnect controller */
+	ret = boottime->disconnect_controller(handle_controller, NULL, NULL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to disconnect controller\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Check number of child controllers */
+	ret = count_child_controllers(handle_controller, &guid_controller,
+				      &count);
+	if (ret != EFI_SUCCESS || count) {
+		efi_st_error("Destroying child controllers failed\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* Connect controller to driver */
+	ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to connect controller\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Check number of child controllers */
+	ret = count_child_controllers(handle_controller, &guid_controller,
+				      &count);
+	if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
+		efi_st_error("Number of children %u != %u\n",
+			     (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
+	}
+	/* Uninstall controller protocol */
+	ret = boottime->uninstall_protocol_interface(handle_controller,
+						     &guid_controller, NULL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to uninstall protocols\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Check number of child controllers */
+	ret = count_child_controllers(handle_controller, &guid_controller,
+				      &count);
+	if (ret == EFI_SUCCESS)
+		efi_st_error("Uninstall failed\n");
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(controllers) = {
+	.name = "controllers",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_devicepath.c b/lib/efi_selftest/efi_selftest_devicepath.c
index 1ab54eb..92940c7 100644
--- a/lib/efi_selftest/efi_selftest_devicepath.c
+++ b/lib/efi_selftest/efi_selftest_devicepath.c
@@ -192,31 +192,41 @@
 {
 	efi_status_t ret;
 
-	ret = boottime->uninstall_protocol_interface(&handle1,
+	ret = boottime->uninstall_protocol_interface(handle1,
 						     &guid_device_path,
 						     dp1);
-	if (ret != EFI_SUCCESS)
-		efi_st_todo("UninstallProtocolInterface failed\n");
-	ret = boottime->uninstall_protocol_interface(&handle1,
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("UninstallProtocolInterface failed\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->uninstall_protocol_interface(handle1,
 						     &guid_protocol,
 						     &interface);
-	if (ret != EFI_SUCCESS)
-		efi_st_todo("UninstallProtocolInterface failed\n");
-	ret = boottime->uninstall_protocol_interface(&handle2,
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("UninstallProtocolInterface failed\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->uninstall_protocol_interface(handle2,
 						     &guid_device_path,
 						     dp2);
-	if (ret != EFI_SUCCESS)
-		efi_st_todo("UninstallProtocolInterface failed\n");
-	ret = boottime->uninstall_protocol_interface(&handle2,
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("UninstallProtocolInterface failed\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->uninstall_protocol_interface(handle2,
 						     &guid_protocol,
 						     &interface);
-	if (ret != EFI_SUCCESS)
-		efi_st_todo("UninstallProtocolInterface failed\n");
-	ret = boottime->uninstall_protocol_interface(&handle3,
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("UninstallProtocolInterface failed\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->uninstall_protocol_interface(handle3,
 						     &guid_device_path,
 						     dp3);
-	if (ret != EFI_SUCCESS)
-		efi_st_todo("UninstallProtocolInterface failed\n");
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("UninstallProtocolInterface failed\n");
+		return EFI_ST_FAILURE;
+	}
 	if (dp1) {
 		ret = boottime->free_pool(dp1);
 		if (ret != EFI_SUCCESS) {
@@ -299,17 +309,16 @@
 			efi_st_error("FreePool failed\n");
 			return EFI_ST_FAILURE;
 		}
-		ret = boottime->close_protocol(handles[i], &guid_device_path,
-					       NULL, NULL);
-		if (ret != EFI_SUCCESS)
-			efi_st_todo("Cannot close device path protocol.\n");
+		/*
+		 * CloseProtocol cannot be called without agent handle.
+		 * There is no need to close the device path protocol.
+		 */
 	}
 	ret = boottime->free_pool(handles);
 	if (ret != EFI_SUCCESS) {
 		efi_st_error("FreePool failed\n");
 		return EFI_ST_FAILURE;
 	}
-	efi_st_printf("\n");
 
 	/* Test ConvertDevicePathToText */
 	string = device_path_to_text->convert_device_path_to_text(
@@ -318,15 +327,14 @@
 		efi_st_error("ConvertDevicePathToText failed\n");
 		return EFI_ST_FAILURE;
 	}
-	efi_st_printf("dp2: %ps\n", string);
 	if (efi_st_strcmp_16_8(
 		string,
 		"/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbb1)/VenHw(dbca4c98-6cb0-694d-0872-819c650cbba2)")
 	    ) {
+		efi_st_printf("dp2: %ps\n", string);
 		efi_st_error("Incorrect text from ConvertDevicePathToText\n");
 		return EFI_ST_FAILURE;
 	}
-
 	ret = boottime->free_pool(string);
 	if (ret != EFI_SUCCESS) {
 		efi_st_error("FreePool failed\n");
@@ -340,17 +348,17 @@
 		efi_st_error("ConvertDeviceNodeToText failed\n");
 		return EFI_ST_FAILURE;
 	}
-	efi_st_printf("dp_node: %ps\n", string);
-	ret = boottime->free_pool(string);
-	if (ret != EFI_SUCCESS) {
-		efi_st_error("FreePool failed\n");
-		return EFI_ST_FAILURE;
-	}
 	if (efi_st_strcmp_16_8(string, "u-boot")) {
+		efi_st_printf("dp_node: %ps\n", string);
 		efi_st_error(
 			"Incorrect conversion by ConvertDeviceNodeToText\n");
 		return EFI_ST_FAILURE;
 	}
+	ret = boottime->free_pool(string);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("FreePool failed\n");
+		return EFI_ST_FAILURE;
+	}
 
 	/* Test LocateDevicePath */
 	remaining_dp = (struct efi_device_path *)dp3;
@@ -370,13 +378,18 @@
 		efi_st_error("ConvertDevicePathToText failed\n");
 		return EFI_ST_FAILURE;
 	}
-	efi_st_printf("remaining device path: %ps\n", string);
 	if (efi_st_strcmp_16_8(string,
 			       "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbc3)")
 	    ) {
+		efi_st_printf("remaining device path: %ps\n", string);
 		efi_st_error("LocateDevicePath: wrong remaining device path\n");
 		return EFI_ST_FAILURE;
 	}
+	ret = boottime->free_pool(string);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("FreePool failed\n");
+		return EFI_ST_FAILURE;
+	}
 
 	return EFI_ST_SUCCESS;
 }
diff --git a/lib/efi_selftest/efi_selftest_disk_image.h b/lib/efi_selftest/efi_selftest_disk_image.h
new file mode 100644
index 0000000..4775dac
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_disk_image.h
@@ -0,0 +1,69 @@
+/*
+ *  Non-zero 8 byte strings of a disk image
+ *
+ *  Generated with tools/file2include
+ *
+ *  SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#define EFI_ST_DISK_IMG { 0x00010000, { \
+	{0x000001b8, "\x94\x37\x69\xfc\x00\x00\x00\x00"}, /* .7i..... */ \
+	{0x000001c0, "\x02\x00\x83\x02\x02\x00\x01\x00"}, /* ........ */ \
+	{0x000001c8, "\x00\x00\x7f\x00\x00\x00\x00\x00"}, /* ........ */ \
+	{0x000001f8, "\x00\x00\x00\x00\x00\x00\x55\xaa"}, /* ......U. */ \
+	{0x00000200, "\xeb\x3c\x90\x6d\x6b\x66\x73\x2e"}, /* .<.mkfs. */ \
+	{0x00000208, "\x66\x61\x74\x00\x02\x04\x01\x00"}, /* fat..... */ \
+	{0x00000210, "\x02\x00\x02\x7f\x00\xf8\x01\x00"}, /* ........ */ \
+	{0x00000218, "\x20\x00\x40\x00\x00\x00\x00\x00"}, /*  .@..... */ \
+	{0x00000220, "\x00\x00\x00\x00\x80\x00\x29\x86"}, /* ......). */ \
+	{0x00000228, "\xe8\x82\x80\x4e\x4f\x20\x4e\x41"}, /* ...NO NA */ \
+	{0x00000230, "\x4d\x45\x20\x20\x20\x20\x46\x41"}, /* ME    FA */ \
+	{0x00000238, "\x54\x31\x32\x20\x20\x20\x0e\x1f"}, /* T12   .. */ \
+	{0x00000240, "\xbe\x5b\x7c\xac\x22\xc0\x74\x0b"}, /* .[|.".t. */ \
+	{0x00000248, "\x56\xb4\x0e\xbb\x07\x00\xcd\x10"}, /* V....... */ \
+	{0x00000250, "\x5e\xeb\xf0\x32\xe4\xcd\x16\xcd"}, /* ^..2.... */ \
+	{0x00000258, "\x19\xeb\xfe\x54\x68\x69\x73\x20"}, /* ...This  */ \
+	{0x00000260, "\x69\x73\x20\x6e\x6f\x74\x20\x61"}, /* is not a */ \
+	{0x00000268, "\x20\x62\x6f\x6f\x74\x61\x62\x6c"}, /*  bootabl */ \
+	{0x00000270, "\x65\x20\x64\x69\x73\x6b\x2e\x20"}, /* e disk.  */ \
+	{0x00000278, "\x20\x50\x6c\x65\x61\x73\x65\x20"}, /*  Please  */ \
+	{0x00000280, "\x69\x6e\x73\x65\x72\x74\x20\x61"}, /* insert a */ \
+	{0x00000288, "\x20\x62\x6f\x6f\x74\x61\x62\x6c"}, /*  bootabl */ \
+	{0x00000290, "\x65\x20\x66\x6c\x6f\x70\x70\x79"}, /* e floppy */ \
+	{0x00000298, "\x20\x61\x6e\x64\x0d\x0a\x70\x72"}, /*  and..pr */ \
+	{0x000002a0, "\x65\x73\x73\x20\x61\x6e\x79\x20"}, /* ess any  */ \
+	{0x000002a8, "\x6b\x65\x79\x20\x74\x6f\x20\x74"}, /* key to t */ \
+	{0x000002b0, "\x72\x79\x20\x61\x67\x61\x69\x6e"}, /* ry again */ \
+	{0x000002b8, "\x20\x2e\x2e\x2e\x20\x0d\x0a\x00"}, /*  ... ... */ \
+	{0x000003f8, "\x00\x00\x00\x00\x00\x00\x55\xaa"}, /* ......U. */ \
+	{0x00000400, "\xf8\xff\xff\x00\x00\x00\x00\xf0"}, /* ........ */ \
+	{0x00000408, "\xff\x00\x00\x00\x00\x00\x00\x00"}, /* ........ */ \
+	{0x00000600, "\xf8\xff\xff\x00\x00\x00\x00\xf0"}, /* ........ */ \
+	{0x00000608, "\xff\x00\x00\x00\x00\x00\x00\x00"}, /* ........ */ \
+	{0x00000800, "\xe5\x70\x00\x00\x00\xff\xff\xff"}, /* .p...... */ \
+	{0x00000808, "\xff\xff\xff\x0f\x00\x0e\xff\xff"}, /* ........ */ \
+	{0x00000810, "\xff\xff\xff\xff\xff\xff\xff\xff"}, /* ........ */ \
+	{0x00000818, "\xff\xff\x00\x00\xff\xff\xff\xff"}, /* ........ */ \
+	{0x00000820, "\xe5\x2e\x00\x68\x00\x65\x00\x6c"}, /* ...h.e.l */ \
+	{0x00000828, "\x00\x6c\x00\x0f\x00\x0e\x6f\x00"}, /* .l....o. */ \
+	{0x00000830, "\x2e\x00\x74\x00\x78\x00\x74\x00"}, /* ..t.x.t. */ \
+	{0x00000838, "\x2e\x00\x00\x00\x73\x00\x77\x00"}, /* ....s.w. */ \
+	{0x00000840, "\xe5\x45\x4c\x4c\x4f\x54\x7e\x31"}, /* .ELLOT~1 */ \
+	{0x00000848, "\x53\x57\x50\x20\x00\x64\xd0\x8a"}, /* SWP .d.. */ \
+	{0x00000850, "\x92\x4b\x92\x4b\x00\x00\xd0\x8a"}, /* .K.K.... */ \
+	{0x00000858, "\x92\x4b\x00\x00\x00\x00\x00\x00"}, /* .K...... */ \
+	{0x00000860, "\x41\x68\x00\x65\x00\x6c\x00\x6c"}, /* Ah.e.l.l */ \
+	{0x00000868, "\x00\x6f\x00\x0f\x00\xf1\x2e\x00"}, /* .o...... */ \
+	{0x00000870, "\x74\x00\x78\x00\x74\x00\x00\x00"}, /* t.x.t... */ \
+	{0x00000878, "\xff\xff\x00\x00\xff\xff\xff\xff"}, /* ........ */ \
+	{0x00000880, "\x48\x45\x4c\x4c\x4f\x20\x20\x20"}, /* HELLO    */ \
+	{0x00000888, "\x54\x58\x54\x20\x00\x64\xd4\x8a"}, /* TXT .d.. */ \
+	{0x00000890, "\x92\x4b\x92\x4b\x00\x00\xd4\x8a"}, /* .K.K.... */ \
+	{0x00000898, "\x92\x4b\x05\x00\x0d\x00\x00\x00"}, /* .K...... */ \
+	{0x000008a0, "\xe5\x45\x4c\x4c\x4f\x54\x7e\x31"}, /* .ELLOT~1 */ \
+	{0x000008a8, "\x53\x57\x58\x20\x00\x64\xd0\x8a"}, /* SWX .d.. */ \
+	{0x000008b0, "\x92\x4b\x92\x4b\x00\x00\xd0\x8a"}, /* .K.K.... */ \
+	{0x000008b8, "\x92\x4b\x00\x00\x00\x00\x00\x00"}, /* .K...... */ \
+	{0x00006000, "\x48\x65\x6c\x6c\x6f\x20\x77\x6f"}, /* Hello wo */ \
+	{0x00006008, "\x72\x6c\x64\x21\x0a\x00\x00\x00"}, /* rld!.... */ \
+	{0, NULL} } }
diff --git a/lib/efi_selftest/efi_selftest_events.c b/lib/efi_selftest/efi_selftest_events.c
index ad9490bd..5393e39 100644
--- a/lib/efi_selftest/efi_selftest_events.c
+++ b/lib/efi_selftest/efi_selftest_events.c
@@ -142,8 +142,8 @@
 		efi_st_error("WaitForEvent returned wrong index\n");
 		return EFI_ST_FAILURE;
 	}
-	efi_st_printf("Notification count periodic: %u\n", timer_ticks);
 	if (timer_ticks < 8 || timer_ticks > 12) {
+		efi_st_printf("Notification count periodic: %u\n", timer_ticks);
 		efi_st_error("Incorrect timing of events\n");
 		return EFI_ST_FAILURE;
 	}
@@ -170,8 +170,9 @@
 		efi_st_error("Could not wait for event\n");
 		return EFI_ST_FAILURE;
 	}
-	efi_st_printf("Notification count single shot: %u\n", timer_ticks);
 	if (timer_ticks != 1) {
+		efi_st_printf("Notification count single shot: %u\n",
+			      timer_ticks);
 		efi_st_error("Single shot timer failed\n");
 		return EFI_ST_FAILURE;
 	}
@@ -180,8 +181,9 @@
 		efi_st_error("Could not wait for event\n");
 		return EFI_ST_FAILURE;
 	}
-	efi_st_printf("Notification count stopped timer: %u\n", timer_ticks);
 	if (timer_ticks != 1) {
+		efi_st_printf("Notification count stopped timer: %u\n",
+			      timer_ticks);
 		efi_st_error("Stopped timer fired\n");
 		return EFI_ST_FAILURE;
 	}
diff --git a/lib/efi_selftest/efi_selftest_manageprotocols.c b/lib/efi_selftest/efi_selftest_manageprotocols.c
index f20f152..874f861 100644
--- a/lib/efi_selftest/efi_selftest_manageprotocols.c
+++ b/lib/efi_selftest/efi_selftest_manageprotocols.c
@@ -194,7 +194,7 @@
 						&guid3, &interface3,
 						NULL);
 	if (ret == EFI_SUCCESS) {
-		efi_st_todo("UninstallMultipleProtocolInterfaces did not catch error\n");
+		efi_st_error("UninstallMultipleProtocolInterfaces did not catch error\n");
 		return EFI_ST_FAILURE;
 	}
 
@@ -273,8 +273,8 @@
 						&guid2, &interface2,
 						NULL);
 	if (ret != EFI_SUCCESS) {
-		efi_st_todo("UninstallMultipleProtocolInterfaces failed\n");
-		/* This test is known to fail due to missing implementation */
+		efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
+		return EFI_ST_FAILURE;
 	}
 	/*
 	 * Check that the protocols are really uninstalled.
@@ -287,8 +287,8 @@
 		return EFI_ST_FAILURE;
 	}
 	if (count != 1) {
-		efi_st_todo("UninstallMultipleProtocolInterfaces failed to uninstall protocols\n");
-		/* This test is known to fail due to missing implementation */
+		efi_st_error("UninstallMultipleProtocolInterfaces failed to uninstall protocols\n");
+		return EFI_ST_FAILURE;
 	}
 	ret = find_in_buffer(handle1, count, buffer);
 	if (ret != EFI_SUCCESS) {
@@ -327,19 +327,19 @@
 	ret = boottime->uninstall_protocol_interface(handle1, &guid1,
 						     &interface1);
 	if (ret != EFI_SUCCESS) {
-		efi_st_todo("UninstallProtocolInterface failed\n");
-		/* This test is known to fail due to missing implementation */
+		efi_st_error("UninstallProtocolInterface failed\n");
+		return EFI_ST_FAILURE;
 	}
 	ret = boottime->handle_protocol(handle1, &guid1, (void **)&interface);
 	if (ret == EFI_SUCCESS) {
-		efi_st_todo("UninstallProtocolInterface failed\n");
-		/* This test is known to fail due to missing implementation */
+		efi_st_error("UninstallProtocolInterface failed\n");
+		return EFI_ST_FAILURE;
 	}
 	ret = boottime->uninstall_protocol_interface(handle1, &guid3,
 						     &interface1);
 	if (ret != EFI_SUCCESS) {
-		efi_st_todo("UninstallProtocolInterface failed\n");
-		/* This test is known to fail due to missing implementation */
+		efi_st_error("UninstallProtocolInterface failed\n");
+		return EFI_ST_FAILURE;
 	}
 
 	return EFI_ST_SUCCESS;
diff --git a/lib/efi_selftest/efi_selftest_miniapp_exit.c b/lib/efi_selftest/efi_selftest_miniapp_exit.c
new file mode 100644
index 0000000..5ec57ab
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_miniapp_exit.c
@@ -0,0 +1,37 @@
+/*
+ * efi_selftest_miniapp_exit
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This EFI application is run by the StartImage selftest.
+ * It uses the Exit boot service to return.
+ */
+
+#include <common.h>
+#include <efi_api.h>
+
+/*
+ * Entry point of the EFI application.
+ *
+ * @handle	handle of the loaded image
+ * @systable	system table
+ * @return	status code
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t handle,
+			     struct efi_system_table *systable)
+{
+	struct efi_simple_text_output_protocol *con_out = systable->con_out;
+
+	con_out->output_string(con_out, L"EFI application calling Exit\n");
+
+	/* The return value is checked by the calling test */
+	systable->boottime->exit(handle, EFI_UNSUPPORTED, 0, NULL);
+
+	/*
+	 * This statement should not be reached.
+	 * To enable testing use a different return value.
+	 */
+	return EFI_SUCCESS;
+}
diff --git a/lib/efi_selftest/efi_selftest_miniapp_return.c b/lib/efi_selftest/efi_selftest_miniapp_return.c
new file mode 100644
index 0000000..0a82391
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_miniapp_return.c
@@ -0,0 +1,32 @@
+/*
+ * efi_selftest_miniapp_return
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This EFI application is run by the StartImage selftest.
+ * It returns directly without calling the Exit boot service.
+ */
+
+#include <common.h>
+#include <efi_api.h>
+
+/*
+ * Entry point of the EFI application.
+ *
+ * @handle	handle of the loaded image
+ * @systable	system table
+ * @return	status code
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t handle,
+			     struct efi_system_table *systable)
+{
+	struct efi_simple_text_output_protocol *con_out = systable->con_out;
+
+	con_out->output_string(con_out,
+			       L"EFI application returning w/o calling Exit\n");
+
+	/* The return value is checked by the calling test */
+	return EFI_INCOMPATIBLE_VERSION;
+}
diff --git a/lib/efi_selftest/efi_selftest_startimage_exit.c b/lib/efi_selftest/efi_selftest_startimage_exit.c
new file mode 100644
index 0000000..0809690
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_startimage_exit.c
@@ -0,0 +1,149 @@
+/*
+ * efi_selftest_start_image
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This test checks the StartImage boot service.
+ * The efi_selftest_miniapp_exit.efi application is loaded into memory
+ * and started.
+ */
+
+#include <efi_selftest.h>
+/* Include containing the miniapp.efi application */
+#include "efi_miniapp_file_image_exit.h"
+
+/* Block size of compressed disk image */
+#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
+
+/* Binary logarithm of the block size */
+#define LB_BLOCK_SIZE 9
+
+static efi_handle_t image_handle;
+static struct efi_boot_services *boottime;
+
+/* One 8 byte block of the compressed disk image */
+struct line {
+	size_t addr;
+	char *line;
+};
+
+/* Compressed file image */
+struct compressed_file_image {
+	size_t length;
+	struct line lines[];
+};
+
+static struct compressed_file_image img = EFI_ST_DISK_IMG;
+
+/* Decompressed file image */
+static u8 *image;
+
+/*
+ * Decompress the disk image.
+ *
+ * @image	decompressed disk image
+ * @return	status code
+ */
+static efi_status_t decompress(u8 **image)
+{
+	u8 *buf;
+	size_t i;
+	size_t addr;
+	size_t len;
+	efi_status_t ret;
+
+	ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
+				      (void **)&buf);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Out of memory\n");
+		return ret;
+	}
+	boottime->set_mem(buf, img.length, 0);
+
+	for (i = 0; ; ++i) {
+		if (!img.lines[i].line)
+			break;
+		addr = img.lines[i].addr;
+		len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
+		if (addr + len > img.length)
+			len = img.length - addr;
+		boottime->copy_mem(buf + addr, img.lines[i].line, len);
+	}
+	*image = buf;
+	return ret;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+		 const struct efi_system_table *systable)
+{
+	image_handle = handle;
+	boottime = systable->boottime;
+
+	/* Load the application image into memory */
+	decompress(&image);
+
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+	efi_status_t r = EFI_ST_SUCCESS;
+
+	if (image) {
+		r = efi_free_pool(image);
+		if (r != EFI_SUCCESS) {
+			efi_st_error("Failed to free image\n");
+			return EFI_ST_FAILURE;
+		}
+	}
+	return r;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Load and start the application image.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+	efi_status_t ret;
+	efi_handle_t handle;
+
+	ret = boottime->load_image(false, image_handle, NULL, image,
+				   img.length, &handle);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to load image\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->start_image(handle, NULL, NULL);
+	if (ret != EFI_UNSUPPORTED) {
+		efi_st_error("Wrong return value from application\n");
+		return EFI_ST_FAILURE;
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(startimage_exit) = {
+	.name = "start image exit",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+	.teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_startimage_return.c b/lib/efi_selftest/efi_selftest_startimage_return.c
new file mode 100644
index 0000000..2209911
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_startimage_return.c
@@ -0,0 +1,149 @@
+/*
+ * efi_selftest_start_image
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * This test checks the StartImage boot service.
+ * The efi_selftest_miniapp_return.efi application is loaded into memory
+ * and started.
+ */
+
+#include <efi_selftest.h>
+/* Include containing the miniapp.efi application */
+#include "efi_miniapp_file_image_return.h"
+
+/* Block size of compressed disk image */
+#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
+
+/* Binary logarithm of the block size */
+#define LB_BLOCK_SIZE 9
+
+static efi_handle_t image_handle;
+static struct efi_boot_services *boottime;
+
+/* One 8 byte block of the compressed disk image */
+struct line {
+	size_t addr;
+	char *line;
+};
+
+/* Compressed file image */
+struct compressed_file_image {
+	size_t length;
+	struct line lines[];
+};
+
+static struct compressed_file_image img = EFI_ST_DISK_IMG;
+
+/* Decompressed file image */
+static u8 *image;
+
+/*
+ * Decompress the disk image.
+ *
+ * @image	decompressed disk image
+ * @return	status code
+ */
+static efi_status_t decompress(u8 **image)
+{
+	u8 *buf;
+	size_t i;
+	size_t addr;
+	size_t len;
+	efi_status_t ret;
+
+	ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
+				      (void **)&buf);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Out of memory\n");
+		return ret;
+	}
+	boottime->set_mem(buf, img.length, 0);
+
+	for (i = 0; ; ++i) {
+		if (!img.lines[i].line)
+			break;
+		addr = img.lines[i].addr;
+		len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
+		if (addr + len > img.length)
+			len = img.length - addr;
+		boottime->copy_mem(buf + addr, img.lines[i].line, len);
+	}
+	*image = buf;
+	return ret;
+}
+
+/*
+ * Setup unit test.
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+		 const struct efi_system_table *systable)
+{
+	image_handle = handle;
+	boottime = systable->boottime;
+
+	/* Load the application image into memory */
+	decompress(&image);
+
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+	efi_status_t r = EFI_ST_SUCCESS;
+
+	if (image) {
+		r = efi_free_pool(image);
+		if (r != EFI_SUCCESS) {
+			efi_st_error("Failed to free image\n");
+			return EFI_ST_FAILURE;
+		}
+	}
+	return r;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Load and start the application image.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+	efi_status_t ret;
+	efi_handle_t handle;
+
+	ret = boottime->load_image(false, image_handle, NULL, image,
+				   img.length, &handle);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to load image\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->start_image(handle, NULL, NULL);
+	if (ret != EFI_INCOMPATIBLE_VERSION) {
+		efi_st_error("Wrong return value from application\n");
+		return EFI_ST_FAILURE;
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(startimage) = {
+	.name = "start image return",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+	.teardown = teardown,
+};
diff --git a/lib/efi_selftest/efi_selftest_tpl.c b/lib/efi_selftest/efi_selftest_tpl.c
index 6ea0bb7..8243fae 100644
--- a/lib/efi_selftest/efi_selftest_tpl.c
+++ b/lib/efi_selftest/efi_selftest_tpl.c
@@ -144,9 +144,10 @@
 		efi_st_error("WaitForEvent returned wrong index\n");
 		return EFI_ST_FAILURE;
 	}
-	efi_st_printf("Notification count with TPL level TPL_APPLICATION: %u\n",
-		      notification_count);
 	if (notification_count < 8 || notification_count > 12) {
+		efi_st_printf(
+		    "Notification count with TPL level TPL_APPLICATION: %u\n",
+		    notification_count);
 		efi_st_error("Incorrect timing of events\n");
 		return EFI_ST_FAILURE;
 	}
@@ -181,9 +182,10 @@
 		efi_st_error("Could not check event\n");
 		return EFI_ST_FAILURE;
 	}
-	efi_st_printf("Notification count with TPL level TPL_CALLBACK: %u\n",
-		      notification_count);
 	if (notification_count != 0) {
+		efi_st_printf(
+			"Notification count with TPL level TPL_CALLBACK: %u\n",
+			notification_count);
 		efi_st_error("Suppressed timer fired\n");
 		return EFI_ST_FAILURE;
 	}
@@ -200,9 +202,10 @@
 		efi_st_error("Could not wait for event\n");
 		return EFI_ST_FAILURE;
 	}
-	efi_st_printf("Notification count with TPL level TPL_APPLICATION: %u\n",
-		      notification_count);
 	if (notification_count < 1) {
+		efi_st_printf(
+		    "Notification count with TPL level TPL_APPLICATION: %u\n",
+		    notification_count);
 		efi_st_error("Queued timer event did not fire\n");
 		return EFI_ST_FAILURE;
 	}
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 6b138fa..df9d9ae 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -83,8 +83,9 @@
 }
 
 fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
-		const char *prop_name, int index, int na, int ns,
-		fdt_size_t *sizep, bool translate)
+				      const char *prop_name, int index, int na,
+				      int ns, fdt_size_t *sizep,
+				      bool translate)
 {
 	const fdt32_t *prop, *prop_end;
 	const fdt32_t *prop_addr, *prop_size, *prop_after_size;
@@ -138,8 +139,9 @@
 }
 
 fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent,
-		int node, const char *prop_name, int index, fdt_size_t *sizep,
-		bool translate)
+					    int node, const char *prop_name,
+					    int index, fdt_size_t *sizep,
+					    bool translate)
 {
 	int na, ns;
 
@@ -164,8 +166,9 @@
 }
 
 fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node,
-		const char *prop_name, int index, fdt_size_t *sizep,
-		bool translate)
+					      const char *prop_name, int index,
+					      fdt_size_t *sizep,
+					      bool translate)
 {
 	int parent;
 
@@ -182,7 +185,7 @@
 }
 
 fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
-		const char *prop_name, fdt_size_t *sizep)
+				const char *prop_name, fdt_size_t *sizep)
 {
 	int ns = sizep ? (sizeof(fdt_size_t) / sizeof(fdt32_t)) : 0;
 
@@ -191,15 +194,14 @@
 					  ns, sizep, false);
 }
 
-fdt_addr_t fdtdec_get_addr(const void *blob, int node,
-		const char *prop_name)
+fdt_addr_t fdtdec_get_addr(const void *blob, int node, const char *prop_name)
 {
 	return fdtdec_get_addr_size(blob, node, prop_name, NULL);
 }
 
 #if defined(CONFIG_PCI) && defined(CONFIG_DM_PCI)
 int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type,
-		const char *prop_name, struct fdt_pci_addr *addr)
+			const char *prop_name, struct fdt_pci_addr *addr)
 {
 	const u32 *cell;
 	int len;
@@ -231,10 +233,10 @@
 				addr->phys_mid = fdt32_to_cpu(cell[1]);
 				addr->phys_lo = fdt32_to_cpu(cell[1]);
 				break;
-			} else {
-				cell += (FDT_PCI_ADDR_CELLS +
-					 FDT_PCI_SIZE_CELLS);
 			}
+
+			cell += (FDT_PCI_ADDR_CELLS +
+				 FDT_PCI_SIZE_CELLS);
 		}
 
 		if (i == num) {
@@ -243,10 +245,10 @@
 		}
 
 		return 0;
-	} else {
-		ret = -EINVAL;
 	}
 
+	ret = -EINVAL;
+
 fail:
 	debug("(not found)\n");
 	return ret;
@@ -263,11 +265,9 @@
 
 	end = list + len;
 	while (list < end) {
-		char *s;
-
 		len = strlen(list);
 		if (len >= strlen("pciVVVV,DDDD")) {
-			s = strstr(list, "pci");
+			char *s = strstr(list, "pci");
 
 			/*
 			 * check if the string is something like pciVVVV,DDDD.RR
@@ -297,7 +297,7 @@
 
 	/* extract the bar number from fdt_pci_addr */
 	barnum = addr->phys_hi & 0xff;
-	if ((barnum < PCI_BASE_ADDRESS_0) || (barnum > PCI_CARDBUS_CIS))
+	if (barnum < PCI_BASE_ADDRESS_0 || barnum > PCI_CARDBUS_CIS)
 		return -EINVAL;
 
 	barnum = (barnum - PCI_BASE_ADDRESS_0) / 4;
@@ -308,7 +308,7 @@
 #endif
 
 uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
-		uint64_t default_val)
+			   uint64_t default_val)
 {
 	const uint64_t *cell64;
 	int length;
@@ -333,7 +333,7 @@
 	 */
 	cell = fdt_getprop(blob, node, "status", NULL);
 	if (cell)
-		return 0 == strcmp(cell, "okay");
+		return strcmp(cell, "okay") == 0;
 	return 1;
 }
 
@@ -343,20 +343,19 @@
 
 	/* Search our drivers */
 	for (id = COMPAT_UNKNOWN; id < COMPAT_COUNT; id++)
-		if (0 == fdt_node_check_compatible(blob, node,
-				compat_names[id]))
+		if (fdt_node_check_compatible(blob, node,
+					      compat_names[id]) == 0)
 			return id;
 	return COMPAT_UNKNOWN;
 }
 
-int fdtdec_next_compatible(const void *blob, int node,
-		enum fdt_compat_id id)
+int fdtdec_next_compatible(const void *blob, int node, enum fdt_compat_id id)
 {
 	return fdt_node_offset_by_compatible(blob, node, compat_names[id]);
 }
 
 int fdtdec_next_compatible_subnode(const void *blob, int node,
-		enum fdt_compat_id id, int *depthp)
+				   enum fdt_compat_id id, int *depthp)
 {
 	do {
 		node = fdt_next_node(blob, node, depthp);
@@ -370,8 +369,8 @@
 	return -FDT_ERR_NOTFOUND;
 }
 
-int fdtdec_next_alias(const void *blob, const char *name,
-		enum fdt_compat_id id, int *upto)
+int fdtdec_next_alias(const void *blob, const char *name, enum fdt_compat_id id,
+		      int *upto)
 {
 #define MAX_STR_LEN 20
 	char str[MAX_STR_LEN + 20];
@@ -393,7 +392,8 @@
 }
 
 int fdtdec_find_aliases_for_id(const void *blob, const char *name,
-			enum fdt_compat_id id, int *node_list, int maxcount)
+			       enum fdt_compat_id id, int *node_list,
+			       int maxcount)
 {
 	memset(node_list, '\0', sizeof(*node_list) * maxcount);
 
@@ -402,7 +402,8 @@
 
 /* TODO: Can we tighten this code up a little? */
 int fdtdec_add_aliases_for_id(const void *blob, const char *name,
-			enum fdt_compat_id id, int *node_list, int maxcount)
+			      enum fdt_compat_id id, int *node_list,
+			      int maxcount)
 {
 	int name_len = strlen(name);
 	int nodes[maxcount];
@@ -429,7 +430,7 @@
 	}
 	if (node >= 0)
 		debug("%s: warning: maxcount exceeded with alias '%s'\n",
-		       __func__, name);
+		      __func__, name);
 
 	/* Now find all the aliases */
 	for (offset = fdt_first_property_offset(blob, alias_node);
@@ -452,7 +453,7 @@
 		number = simple_strtoul(path + name_len, NULL, 10);
 		if (number < 0 || number >= maxcount) {
 			debug("%s: warning: alias '%s' is out of range\n",
-			       __func__, path);
+			      __func__, path);
 			continue;
 		}
 
@@ -498,7 +499,7 @@
 		if (!node_list[i]) {
 			for (; j < maxcount; j++)
 				if (nodes[j] &&
-					fdtdec_get_is_enabled(blob, nodes[j]))
+				    fdtdec_get_is_enabled(blob, nodes[j]))
 					break;
 
 			/* Have we run out of nodes to add? */
@@ -641,7 +642,8 @@
  * @return pointer to cell, which is only valid if err == 0
  */
 static const void *get_prop_check_min_len(const void *blob, int node,
-		const char *prop_name, int min_len, int *err)
+					  const char *prop_name, int min_len,
+					  int *err)
 {
 	const void *cell;
 	int len;
@@ -658,15 +660,17 @@
 }
 
 int fdtdec_get_int_array(const void *blob, int node, const char *prop_name,
-		u32 *array, int count)
+			 u32 *array, int count)
 {
 	const u32 *cell;
-	int i, err = 0;
+	int err = 0;
 
 	debug("%s: %s\n", __func__, prop_name);
 	cell = get_prop_check_min_len(blob, node, prop_name,
 				      sizeof(u32) * count, &err);
 	if (!err) {
+		int i;
+
 		for (i = 0; i < count; i++)
 			array[i] = fdt32_to_cpu(cell[i]);
 	}
@@ -850,7 +854,7 @@
 }
 
 int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name,
-		u8 *array, int count)
+			  u8 *array, int count)
 {
 	const u8 *cell;
 	int err;
@@ -862,7 +866,7 @@
 }
 
 const u8 *fdtdec_locate_byte_array(const void *blob, int node,
-			     const char *prop_name, int count)
+				   const char *prop_name, int count)
 {
 	const u8 *cell;
 	int err;
@@ -874,7 +878,7 @@
 }
 
 int fdtdec_get_config_int(const void *blob, const char *prop_name,
-		int default_val)
+			  int default_val)
 {
 	int config_node;
 
@@ -971,7 +975,8 @@
 
 	while (ptr + na + ns <= end) {
 		if (i == index) {
-			res->start = res->end = fdtdec_get_number(ptr, na);
+			res->start = fdtdec_get_number(ptr, na);
+			res->end = res->start;
 			res->end += fdtdec_get_number(&ptr[na], ns) - 1;
 			return 0;
 		}
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index dd572d2..226f4eb 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -11,16 +11,17 @@
  * from hush: simple_itoa() was lifted from boa-0.93.15
  */
 
-#include <stdarg.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-
 #include <common.h>
 #include <charset.h>
+#include <efi_loader.h>
+#include <div64.h>
 #include <uuid.h>
+#include <stdarg.h>
+#include <linux/ctype.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/string.h>
 
-#include <div64.h>
 #define noinline __attribute__((noinline))
 
 /* we use this so that we can do without the ctype library */
@@ -291,6 +292,26 @@
 		ADDCH(buf, ' ');
 	return buf;
 }
+
+#if defined(CONFIG_EFI_LOADER) && \
+	!defined(CONFIG_SPL_BUILD) && !defined(API_BUILD)
+static char *device_path_string(char *buf, char *end, void *dp, int field_width,
+				int precision, int flags)
+{
+	u16 *str;
+
+	if (!dp)
+		return "<NULL>";
+
+	str = efi_dp_str((struct efi_device_path *)dp);
+	if (!str)
+		return ERR_PTR(-ENOMEM);
+
+	buf = string16(buf, end, str, field_width, precision, flags);
+	efi_free_pool(str);
+	return buf;
+}
+#endif
 
 #ifdef CONFIG_CMD_NET
 static const char hex_asc[] = "0123456789abcdef";
@@ -435,6 +456,12 @@
 #endif
 
 	switch (*fmt) {
+#if defined(CONFIG_EFI_LOADER) && \
+	!defined(CONFIG_SPL_BUILD) && !defined(API_BUILD)
+	case 'D':
+		return device_path_string(buf, end, ptr, field_width,
+					  precision, flags);
+#endif
 #ifdef CONFIG_CMD_NET
 	case 'a':
 		flags |= SPECIAL | ZEROPAD;
@@ -604,6 +631,8 @@
 			str = pointer(fmt + 1, str, end,
 					va_arg(args, void *),
 					field_width, precision, flags);
+			if (IS_ERR(str))
+				return PTR_ERR(str);
 			/* Skip all alphanumeric pointer suffixes */
 			while (isalnum(fmt[1]))
 				fmt++;
@@ -768,6 +797,9 @@
 	i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
 	va_end(args);
 
+	/* Handle error */
+	if (i <= 0)
+		return i;
 	/* Print the string */
 	puts(printbuffer);
 	return i;
@@ -784,6 +816,9 @@
 	 */
 	i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
 
+	/* Handle error */
+	if (i <= 0)
+		return i;
 	/* Print the string */
 	puts(printbuffer);
 	return i;
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index c98f262..6be4a76 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -344,9 +344,7 @@
 CONFIG_D2NET_V2
 CONFIG_DA850_AM18X_EVM
 CONFIG_DA850_EVM_MAX_CPU_CLK
-CONFIG_DA850_LOWLEVEL
 CONFIG_DA8XX_GPIO
-CONFIG_DAVINCI_SPI
 CONFIG_DBAU1000
 CONFIG_DBAU1X00
 CONFIG_DBGU
@@ -602,7 +600,6 @@
 CONFIG_ETHPRIME
 CONFIG_ETH_BUFSIZE
 CONFIG_ETH_RXSIZE
-CONFIG_EXT4_WRITE
 CONFIG_EXTRA_BOOTARGS
 CONFIG_EXTRA_CLOCK
 CONFIG_EXTRA_ENV
@@ -752,7 +749,6 @@
 CONFIG_FSMC_NAND_BASE
 CONFIG_FSMTDBLK
 CONFIG_FSNOTIFY
-CONFIG_FS_EXT4
 CONFIG_FS_POSIX_ACL
 CONFIG_FTAHBC020S
 CONFIG_FTAHBC020S_BASE
@@ -1279,7 +1275,6 @@
 CONFIG_MACB2_PHY
 CONFIG_MACB3_PHY
 CONFIG_MACB_SEARCH_PHY
-CONFIG_MACH_DAVINCI_DA850_EVM
 CONFIG_MACH_OMAPL138_LCDK
 CONFIG_MACH_SPECIFIC
 CONFIG_MACH_TYPE
@@ -1528,7 +1523,6 @@
 CONFIG_OMAP_EHCI_PHY3_RESET_GPIO
 CONFIG_OMAP_USB2PHY2_HOST
 CONFIG_OMAP_USB3PHY1_HOST
-CONFIG_OMAP_USB_PHY
 CONFIG_ORIGEN
 CONFIG_OS1_ENV_ADDR
 CONFIG_OS2_ENV_ADDR
@@ -1795,7 +1789,6 @@
 CONFIG_ROCKCHIP_CHIP_TAG
 CONFIG_ROCKCHIP_MAX_INIT_SIZE
 CONFIG_ROCKCHIP_SDHCI_MAX_FREQ
-CONFIG_ROCKCHIP_USB2_PHY
 CONFIG_ROM_STUBS
 CONFIG_ROOTFS_OFFSET
 CONFIG_ROOTPATH
@@ -1974,8 +1967,6 @@
 CONFIG_SOC_AU1500
 CONFIG_SOC_AU1550
 CONFIG_SOC_AU1X00
-CONFIG_SOC_DA850
-CONFIG_SOC_DA8XX
 CONFIG_SOC_DM355
 CONFIG_SOC_DM365
 CONFIG_SOC_DM644X
@@ -2168,7 +2159,6 @@
 CONFIG_SUPPORT_EMMC_BOOT
 CONFIG_SUPPORT_EMMC_RPMB
 CONFIG_SUPPORT_RAW_INITRD
-CONFIG_SUPPORT_VFAT
 CONFIG_SUVD3
 CONFIG_SXNI855T
 CONFIG_SYSFLAGS_ADDR
@@ -4748,7 +4738,6 @@
 CONFIG_TWL4030_INPUT
 CONFIG_TWL4030_KEYPAD
 CONFIG_TWL4030_LED
-CONFIG_TWL4030_USB
 CONFIG_TWL6030_INPUT
 CONFIG_TWL6030_POWER
 CONFIG_TWR
@@ -4817,7 +4806,6 @@
 CONFIG_USBID_ADDR
 CONFIG_USBNET_DEV_ADDR
 CONFIG_USBTTY
-CONFIG_USB_AM35X
 CONFIG_USB_ATMEL
 CONFIG_USB_ATMEL_CLK_SEL_PLLB
 CONFIG_USB_ATMEL_CLK_SEL_UPLL
@@ -4877,21 +4865,14 @@
 CONFIG_USB_INVENTRA_DMA
 CONFIG_USB_ISP1301_I2C_ADDR
 CONFIG_USB_MAX_CONTROLLER_COUNT
-CONFIG_USB_MUSB_AM35X
 CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT
-CONFIG_USB_MUSB_DSPS
-CONFIG_USB_MUSB_HCD
-CONFIG_USB_MUSB_OMAP2PLUS
-CONFIG_USB_MUSB_PIO_ONLY
 CONFIG_USB_MUSB_TIMEOUT
 CONFIG_USB_MUSB_TUSB6010
-CONFIG_USB_MUSB_UDC
 CONFIG_USB_OHCI
 CONFIG_USB_OHCI_EP93XX
 CONFIG_USB_OHCI_LPC32XX
 CONFIG_USB_OHCI_NEW
 CONFIG_USB_OHCI_SUNXI
-CONFIG_USB_OMAP3
 CONFIG_USB_OTG
 CONFIG_USB_OTG_BLACKLIST_HUB
 CONFIG_USB_PHY_CFG_BASE
diff --git a/test/print_ut.c b/test/print_ut.c
index a42c554..1aa68be 100644
--- a/test/print_ut.c
+++ b/test/print_ut.c
@@ -7,12 +7,46 @@
 #define DEBUG
 
 #include <common.h>
+#if defined(CONFIG_EFI_LOADER) && \
+	!defined(CONFIG_SPL_BUILD) && !defined(API_BUILD)
+#include <efi_api.h>
+#endif
 #include <display_options.h>
 #include <version.h>
 
 #define FAKE_BUILD_TAG	"jenkins-u-boot-denx_uboot_dm-master-build-aarch64" \
 			"and a lot more text to come"
 
+/* Test efi_loader specific printing */
+static void efi_ut_print(void)
+{
+#if defined(CONFIG_EFI_LOADER) && \
+    !defined(CONFIG_SPL_BUILD) && !defined(API_BUILD)
+	char str[10];
+	u8 buf[sizeof(struct efi_device_path_sd_mmc_path) +
+	       sizeof(struct efi_device_path)];
+	u8 *pos = buf;
+	struct efi_device_path *dp_end;
+	struct efi_device_path_sd_mmc_path *dp_sd =
+			(struct efi_device_path_sd_mmc_path *)pos;
+
+	/* Create a device path for an SD card */
+	dp_sd->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+	dp_sd->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_SD;
+	dp_sd->dp.length = sizeof(struct efi_device_path_sd_mmc_path);
+	dp_sd->slot_number = 3;
+	pos += sizeof(struct efi_device_path_sd_mmc_path);
+	/* Append end node */
+	dp_end = (struct efi_device_path *)pos;
+	dp_end->type = DEVICE_PATH_TYPE_END;
+	dp_end->sub_type = DEVICE_PATH_SUB_TYPE_END;
+	dp_end->length = sizeof(struct efi_device_path);
+
+	snprintf(str, sizeof(str), "_%pD_", buf);
+	assert(!strcmp("_/SD(3)_", str));
+#endif
+}
+
 static int do_ut_print(cmd_tbl_t *cmdtp, int flag, int argc,
 		       char *const argv[])
 {
@@ -75,6 +109,9 @@
 	assert(!strncmp(FAKE_BUILD_TAG, s + 9 + len, 12));
 	assert(!strcmp("\n\n", s + big_str_len - 3));
 
+	/* Test efi_loader specific printing */
+	efi_ut_print();
+
 	printf("%s: Everything went swimmingly\n", __func__);
 	return 0;
 }
diff --git a/tools/.gitignore b/tools/.gitignore
index 6a487d2..c8cdaef 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -6,6 +6,7 @@
 /easylogo/easylogo
 /envcrc
 /fdtgrep
+/file2include
 /fit_check_sign
 /fit_info
 /gdb/gdbcont
diff --git a/tools/Makefile b/tools/Makefile
index 571f571..b7d7d41 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -57,6 +57,8 @@
 hostprogs-y += dumpimage mkimage
 hostprogs-$(CONFIG_FIT_SIGNATURE) += fit_info fit_check_sign
 
+hostprogs-$(CONFIG_CMD_BOOTEFI_SELFTEST) += file2include
+
 FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o
 
 # The following files are synced with upstream DTC.
@@ -118,6 +120,7 @@
 mkimage-objs   := $(dumpimage-mkimage-objs) mkimage.o
 fit_info-objs   := $(dumpimage-mkimage-objs) fit_info.o
 fit_check_sign-objs   := $(dumpimage-mkimage-objs) fit_check_sign.o
+file2include-objs := file2include.o
 
 ifneq ($(CONFIG_MX23)$(CONFIG_MX28),)
 # Add CONFIG_MXS into host CFLAGS, so we can check whether or not register
diff --git a/tools/file2include.c b/tools/file2include.c
new file mode 100644
index 0000000..9145f08
--- /dev/null
+++ b/tools/file2include.c
@@ -0,0 +1,106 @@
+/*
+ * Convert a file image to a C define
+ *
+ * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ *
+ * For testing EFI disk management we need an in memory image of
+ * a disk.
+ *
+ * The tool file2include converts a file to a C include. The file
+ * is separated into strings of 8 bytes. Only the non-zero strings
+ * are written to the include. The output format has been designed
+ * to maintain readability.
+ *
+ * As the disk image needed for testing contains mostly zeroes a high
+ * compression ratio can be attained.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <malloc.h>
+
+/* Size of the blocks written to the compressed file */
+#define BLOCK_SIZE 8
+
+int main(int argc, char *argv[])
+{
+	FILE *file;
+	int ret;
+	unsigned char *buf;
+	size_t count, i, j;
+
+	/* Provide usage help */
+	if (argc != 2) {
+		printf("Usage:\n%s FILENAME\n", argv[0]);
+		return EXIT_FAILURE;
+	}
+	/* Open file */
+	file = fopen(argv[1], "r");
+	if (!file) {
+		perror("fopen");
+		return EXIT_FAILURE;
+	}
+	/* Get file length */
+	ret = fseek(file, 0, SEEK_END);
+	if (ret < 0) {
+		perror("fseek");
+		return EXIT_FAILURE;
+	}
+	count = ftell(file);
+	if (!count) {
+		fprintf(stderr, "File %s has length 0\n", argv[1]);
+		return EXIT_FAILURE;
+	}
+	rewind(file);
+	/* Read file */
+	buf = malloc(count);
+	if (!buf) {
+		perror("calloc");
+		return EXIT_FAILURE;
+	}
+	count = fread(buf, 1, count, file);
+
+	/* Generate output */
+	printf("/*\n");
+	printf(" *  Non-zero %u byte strings of a disk image\n", BLOCK_SIZE);
+	printf(" *\n");
+	printf(" *  Generated with tools/file2include\n");
+	printf(" *\n");
+	printf(" *  SPDX-License-Identifier:	GPL-2.0+\n");
+	printf(" */\n\n");
+	printf("#define EFI_ST_DISK_IMG { 0x%08zx, { \\\n", count);
+
+	for (i = 0; i < count; i += BLOCK_SIZE) {
+		int c = 0;
+
+		for (j = i; j < i + BLOCK_SIZE && j < count; ++j) {
+			if (buf[j])
+				c = 1;
+		}
+		if (!c)
+			continue;
+		printf("\t{0x%08zx, \"", i);
+		for (j = i; j < i + BLOCK_SIZE && j < count; ++j)
+			printf("\\x%02x", buf[j]);
+		printf("\"}, /* ");
+		for (j = i; j < i + BLOCK_SIZE && j < count; ++j) {
+			if (buf[j] >= 0x20 && buf[j] <= 0x7e)
+				printf("%c", buf[j]);
+			else
+				printf(".");
+		}
+		printf(" */ \\\n");
+	}
+	printf("\t{0, NULL} } }\n");
+
+	/* Release resources */
+	free(buf);
+	ret = fclose(file);
+	if (ret) {
+		perror("fclose");
+		return EXIT_FAILURE;
+	}
+	return EXIT_SUCCESS;
+}
diff --git a/tools/patman/get_maintainer.py b/tools/patman/get_maintainer.py
index 2deb5db..22b0918 100644
--- a/tools/patman/get_maintainer.py
+++ b/tools/patman/get_maintainer.py
@@ -44,4 +44,5 @@
         return []
 
     stdout = command.Output(get_maintainer, '--norolestats', fname)
-    return stdout.splitlines()
+    lines = stdout.splitlines()
+    return [ x.replace('"', '') for x in lines ]