Merge tag 'signed-rpi-next' of git://github.com/agraf/u-boot

Patch queue for rpi - 2018-12-03

A few Raspberry Pi specific changes this time:

  - Allow 2nd MMC device
  - Support RPi 3 Model A+
  - Allow UUID to find filesystem
diff --git a/Kconfig b/Kconfig
index dca9bb4..42672a9 100644
--- a/Kconfig
+++ b/Kconfig
@@ -86,6 +86,7 @@
 	select SUPPORT_RAW_INITRD
 	select SYS_LONGHELP
 	imply CMD_MII if NET
+	imply USB_STORAGE
 	imply USE_BOOTCOMMAND
 	help
 	  Select this to enable various options and commands which are suitable
@@ -290,6 +291,14 @@
 	  device memory. Assure this size does not extend past expected storage
 	  space.
 
+config FIT_ENABLE_RSASSA_PSS_SUPPORT
+	bool "Support rsassa-pss signature scheme of FIT image contents"
+	depends on FIT_SIGNATURE
+	default n
+	help
+	  Enable this to support the pss padding algorithm as described
+	  in the rfc8017 (https://tools.ietf.org/html/rfc8017).
+
 config FIT_VERBOSE
 	bool "Show verbose messages when FIT images fail"
 	help
diff --git a/MAINTAINERS b/MAINTAINERS
index 214629e..8ea8ef9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2,6 +2,8 @@
 
 	P: Person (obsolete)
 	M: Mail patches to: FullName <address@domain>
+	R: Designated reviewer: FullName <address@domain>
+	   These reviewers should be CCed on patches.
 	L: Mailing list that is relevant to this area
 	W: Web-page with status/info
 	Q: Patchwork web based patch tracking system site
@@ -414,6 +416,7 @@
 
 EFI PAYLOAD
 M:	Alexander Graf <agraf@suse.de>
+R:	Heinrich Schuchardt <xypron.glpk@gmx.de>
 S:	Maintained
 T:	git git://github.com/agraf/u-boot.git
 F:	doc/README.uefi
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 9920d2e..fff6591 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -16,6 +16,20 @@
  * access: "lr"/"sr".
  */
 
+/*
+ * Typically 8 least significant bits of Build Configuration Register (BCR)
+ * describe version of the HW block in question. Moreover if decoded version
+ * is 0 this means given HW block is absent - this is especially useful because
+ * we may safely read BRC regardless HW block existence while an attempt to
+ * access any other AUX regs associated with this HW block lead to imediate
+ * "instruction error" exception.
+ *
+ * I.e. before using any cofigurable HW block it's required to make sure it
+ * exists at all, and for that we introduce a special macro below.
+ */
+#define ARC_BCR_VERSION_MASK	GENMASK(7, 0)
+#define ARC_FEATURE_EXISTS(bcr)	!!(__builtin_arc_lr(bcr) & ARC_BCR_VERSION_MASK)
+
 #define ARC_AUX_IDENTITY	0x04
 #define ARC_AUX_STATUS32	0x0a
 
@@ -73,7 +87,7 @@
 #define ARC_BCR_CLUSTER		0xcf
 
 /* MMU Management regs */
-#define ARC_AUX_MMU_BCR		0x06f
+#define ARC_AUX_MMU_BCR		0x6f
 
 /* IO coherency related auxiliary registers */
 #define ARC_AUX_IO_COH_ENABLE	0x500
@@ -81,6 +95,15 @@
 #define ARC_AUX_IO_COH_AP0_BASE	0x508
 #define ARC_AUX_IO_COH_AP0_SIZE	0x509
 
+/* XY-memory related */
+#define ARC_AUX_XY_BUILD	0x79
+
+/* DSP-extensions related auxiliary registers */
+#define ARC_AUX_DSP_BUILD	0x7A
+
+/* ARC Subsystems related auxiliary registers */
+#define ARC_AUX_SUBSYS_BUILD	0xF0
+
 #ifndef __ASSEMBLY__
 /* Accessors for auxiliary registers */
 #define read_aux_reg(reg)	__builtin_arc_lr(reg)
diff --git a/arch/arc/lib/cpu.c b/arch/arc/lib/cpu.c
index a969a16..07daaa8 100644
--- a/arch/arc/lib/cpu.c
+++ b/arch/arc/lib/cpu.c
@@ -4,6 +4,7 @@
  */
 
 #include <common.h>
+#include <malloc.h>
 #include <asm/arcregs.h>
 #include <asm/cache.h>
 
@@ -35,34 +36,193 @@
 }
 
 #ifdef CONFIG_DISPLAY_CPUINFO
-const char *decode_identity(void)
+const char *arc_700_version(int arcver, char *name, int name_len)
 {
-	int arcver = read_aux_reg(ARC_AUX_IDENTITY) & 0xff;
+	const char *arc_ver;
+
+	switch (arcver) {
+	case 0x32:
+		arc_ver = "v4.4-4.5";
+		break;
+	case 0x33:
+		arc_ver = "v4.6-v4.9";
+		break;
+	case 0x34:
+		arc_ver = "v4.10";
+		break;
+	case 0x35:
+		arc_ver = "v4.11";
+		break;
+	default:
+		arc_ver = "unknown version";
+	}
+
+	snprintf(name, name_len, "ARC 700 %s", arc_ver);
+
+	return name;
+}
+
+struct em_template_t {
+	const bool cache;
+	const bool dsp;
+	const bool xymem;
+	const char name[8];
+};
+
+static const struct em_template_t em_versions[] = {
+	{false,	false,	false,	"EM4"},
+	{true,	false,	false,	"EM6"},
+	{false,	true,	false,	"EM5D"},
+	{true,	true,	false,	"EM7D"},
+	{false,	true,	true,	"EM9D"},
+	{true,	true,	true,	"EM11D"},
+};
+
+const char *arc_em_version(int arcver, char *name, int name_len)
+{
+	const char *arc_name = "EM";
+	const char *arc_ver;
+	bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD);
+	bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD);
+	bool xymem = ARC_FEATURE_EXISTS(ARC_AUX_XY_BUILD);
+	int i;
+
+	for (i = 0; i++ < sizeof(em_versions) / sizeof(struct em_template_t);) {
+		if (em_versions[i].cache == cache &&
+		    em_versions[i].dsp == dsp &&
+		    em_versions[i].xymem == xymem) {
+			arc_name = em_versions[i].name;
+			break;
+		}
+	}
 
 	switch (arcver) {
-	/* ARCompact cores */
-	case 0x32: return "ARC 700 v4.4-4.5";
-	case 0x33: return "ARC 700 v4.6-v4.9";
-	case 0x34: return "ARC 700 v4.10";
-	case 0x35: return "ARC 700 v4.11";
+	case 0x41:
+		arc_ver = "v1.1a";
+		break;
+	case 0x42:
+		arc_ver = "v3.0";
+		break;
+	case 0x43:
+		arc_ver = "v4.0";
+		break;
+	case 0x44:
+		arc_ver = "v5.0";
+		break;
+	default:
+		arc_ver = "unknown version";
+	}
+
+	snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver);
+
+	return name;
+}
+
+struct hs_template_t {
+	const bool cache;
+	const bool mmu;
+	const bool dual_issue;
+	const bool dsp;
+	const char name[8];
+};
+
+static const struct hs_template_t hs_versions[] = {
+	{false,	false,	false,	false,	"HS34"},
+	{true,	false,	false,	false,	"HS36"},
+	{true,	true,	false,	false,	"HS38"},
+	{false,	false,	true,	false,	"HS44"},
+	{true,	false,	true,	false,	"HS46"},
+	{true,	true,	true,	false,	"HS48"},
+	{false,	false,	true,	true,	"HS45D"},
+	{true,	false,	true,	true,	"HS47D"},
+};
 
-	/* ARCv2 cores */
-	case 0x41: return "ARC EM v1.1a";
-	case 0x42: return "ARC EM v3.0";
-	case 0x43: return "ARC EM v4.0";
-	case 0x50: return "ARC HS v1.0";
-	case 0x51: return "ARC EM v2.0";
-	case 0x52: return "ARC EM v2.1";
-	case 0x53: return "ARC HS v3.0";
-	case 0x54: return "ARC HS v4.0";
+const char *arc_hs_version(int arcver, char *name, int name_len)
+{
+	const char *arc_name = "HS";
+	const char *arc_ver;
+	bool cache = ARC_FEATURE_EXISTS(ARC_BCR_IC_BUILD);
+	bool dsp = ARC_FEATURE_EXISTS(ARC_AUX_DSP_BUILD);
+	bool mmu = !!read_aux_reg(ARC_AUX_MMU_BCR);
+	bool dual_issue = arcver == 0x54 ? true : false;
+	int i;
 
-	default: return "Unknown ARC core";
+	for (i = 0; i++ < sizeof(hs_versions) / sizeof(struct hs_template_t);) {
+		if (hs_versions[i].cache == cache &&
+		    hs_versions[i].mmu == mmu &&
+		    hs_versions[i].dual_issue == dual_issue &&
+		    hs_versions[i].dsp == dsp) {
+			arc_name = hs_versions[i].name;
+			break;
+		}
 	}
+
+	switch (arcver) {
+	case 0x50:
+		arc_ver = "v1.0";
+		break;
+	case 0x51:
+		arc_ver = "v2.0";
+		break;
+	case 0x52:
+		arc_ver = "v2.1c";
+		break;
+	case 0x53:
+		arc_ver = "v3.0";
+		break;
+	case 0x54:
+		arc_ver = "v4.0";
+		break;
+	default:
+		arc_ver = "unknown version";
+	}
+
+	snprintf(name, name_len, "ARC %s %s", arc_name, arc_ver);
+
+	return name;
+}
+
+const char *decode_identity(void)
+{
+#define MAX_CPU_NAME_LEN	64
+
+	int arcver = read_aux_reg(ARC_AUX_IDENTITY) & 0xff;
+	char *name = malloc(MAX_CPU_NAME_LEN);
+
+	if (arcver >= 0x50)
+		return arc_hs_version(arcver, name, MAX_CPU_NAME_LEN);
+	else if (arcver >= 0x40)
+		return arc_em_version(arcver, name, MAX_CPU_NAME_LEN);
+	else if (arcver >= 0x30)
+		return arc_700_version(arcver, name, MAX_CPU_NAME_LEN);
+	else
+		return "Unknown ARC core";
+}
+
+const char *decode_subsystem(void)
+{
+	int subsys_type = read_aux_reg(ARC_AUX_SUBSYS_BUILD) & GENMASK(3, 0);
+
+	switch (subsys_type) {
+	case 0: return NULL;
+	case 2: return "ARC Sensor & Control IP Subsystem";
+	case 3: return "ARC Data Fusion IP Subsystem";
+	case 4: return "ARC Secure Subsystem";
+	default: return "Unknown subsystem";
+	};
 }
 
 __weak int print_cpuinfo(void)
 {
-	printf("CPU:   %s\n", decode_identity());
+	const char *subsys_name = decode_subsystem();
+	char mhz[8];
+
+	printf("CPU:   %s at %s MHz\n", decode_identity(),
+	       strmhz(mhz, gd->cpu_clk));
+
+	if (subsys_name)
+		printf("Subsys:%s\n", subsys_name);
+
 	return 0;
 }
 #endif /* CONFIG_DISPLAY_CPUINFO */
diff --git a/arch/arm/cpu/armv7/smccc-call.S b/arch/arm/cpu/armv7/smccc-call.S
index 0d8b59e..eae69e3 100644
--- a/arch/arm/cpu/armv7/smccc-call.S
+++ b/arch/arm/cpu/armv7/smccc-call.S
@@ -7,6 +7,8 @@
 #include <asm/opcodes-sec.h>
 #include <asm/opcodes-virt.h>
 
+	.section	.text.efi_runtime
+
 #define UNWIND(x...)
 	/*
 	 * Wrap c macros in asm macros to delay expansion until after the
diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig
index ff42791..1c12bbd 100644
--- a/arch/arm/cpu/armv8/Kconfig
+++ b/arch/arm/cpu/armv8/Kconfig
@@ -96,6 +96,7 @@
 config PSCI_RESET
 	bool "Use PSCI for reset and shutdown"
 	default y
+	select ARM_SMCCC if OF_CONTROL
 	depends on !ARCH_EXYNOS7 && !ARCH_BCM283X && \
 		   !TARGET_LS2080A_SIMU && !TARGET_LS2080AQDS && \
 		   !TARGET_LS2080ARDB && !TARGET_LS2080A_EMU && \
diff --git a/arch/arm/cpu/armv8/fwcall.c b/arch/arm/cpu/armv8/fwcall.c
index 0ba3dad..9957c29 100644
--- a/arch/arm/cpu/armv8/fwcall.c
+++ b/arch/arm/cpu/armv8/fwcall.c
@@ -7,7 +7,6 @@
 
 #include <asm-offsets.h>
 #include <config.h>
-#include <efi_loader.h>
 #include <version.h>
 #include <asm/macro.h>
 #include <asm/psci.h>
@@ -19,7 +18,7 @@
  * x0~x7: input arguments
  * x0~x3: output arguments
  */
-static void __efi_runtime hvc_call(struct pt_regs *args)
+static void hvc_call(struct pt_regs *args)
 {
 	asm volatile(
 		"ldr x0, %0\n"
@@ -53,7 +52,7 @@
  * x0~x3: output arguments
  */
 
-void __efi_runtime smc_call(struct pt_regs *args)
+void smc_call(struct pt_regs *args)
 {
 	asm volatile(
 		"ldr x0, %0\n"
@@ -83,9 +82,9 @@
  * use PSCI on U-Boot running below a hypervisor, please detect
  * this and set the flag accordingly.
  */
-static const __efi_runtime_data bool use_smc_for_psci = true;
+static const bool use_smc_for_psci = true;
 
-void __noreturn __efi_runtime psci_system_reset(void)
+void __noreturn psci_system_reset(void)
 {
 	struct pt_regs regs;
 
@@ -100,7 +99,7 @@
 		;
 }
 
-void __noreturn __efi_runtime psci_system_off(void)
+void __noreturn psci_system_off(void)
 {
 	struct pt_regs regs;
 
@@ -114,44 +113,3 @@
 	while (1)
 		;
 }
-
-#ifdef CONFIG_CMD_POWEROFF
-int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	puts("poweroff ...\n");
-
-	udelay(50000); /* wait 50 ms */
-
-	disable_interrupts();
-
-	psci_system_off();
-
-	/*NOTREACHED*/
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_PSCI_RESET
-void reset_misc(void)
-{
-	psci_system_reset();
-}
-
-#ifdef CONFIG_EFI_LOADER
-void __efi_runtime EFIAPI efi_reset_system(
-			enum efi_reset_type reset_type,
-			efi_status_t reset_status,
-			unsigned long data_size, void *reset_data)
-{
-	if (reset_type == EFI_RESET_COLD ||
-	    reset_type == EFI_RESET_WARM ||
-	    reset_type == EFI_RESET_PLATFORM_SPECIFIC) {
-		psci_system_reset();
-	} else if (reset_type == EFI_RESET_SHUTDOWN) {
-		psci_system_off();
-	}
-
-	while (1) { }
-}
-#endif /* CONFIG_EFI_LOADER */
-#endif /* CONFIG_PSCI_RESET */
diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S
index 16c9e29..86de4b4 100644
--- a/arch/arm/cpu/armv8/smccc-call.S
+++ b/arch/arm/cpu/armv8/smccc-call.S
@@ -6,6 +6,8 @@
 #include <linux/arm-smccc.h>
 #include <generated/asm-offsets.h>
 
+	.section	.text.efi_runtime
+
 	.macro SMCCC instr
 	.cfi_startproc
 	\instr	#0
diff --git a/arch/arm/dts/am335x-baltos.dts b/arch/arm/dts/am335x-baltos.dts
new file mode 100644
index 0000000..f939cf6
--- /dev/null
+++ b/arch/arm/dts/am335x-baltos.dts
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * VScom OnRISC
+ * http://www.vscom.de
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+	model = "OnRISC Baltos";
+	compatible = "vscom,onrisc", "ti,am33xx";
+
+	chosen {
+		stdout-path = &uart0;
+	};
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd1_reg>;
+		};
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+};
+
+&am33xx_pinmux {
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0xf0 (MUX_MODE0 | INPUT_EN | PULL_UP)	/* mmc0_dat3.mmc0_dat3 */
+			0xf4 (MUX_MODE0 | INPUT_EN | PULL_UP)	/* mmc0_dat2.mmc0_dat2 */
+			0xf8 (MUX_MODE0 | INPUT_EN | PULL_UP)	/* mmc0_dat1.mmc0_dat1 */
+			0xfc (MUX_MODE0 | INPUT_EN | PULL_UP)	/* mmc0_dat0.mmc0_dat0 */
+			0x100 (MUX_MODE0 | INPUT_EN | PULL_UP)	/* mmc0_clk.mmc0_clk */
+			0x104 (MUX_MODE0 | INPUT_EN | PULL_UP)	/* mmc0_cmd.mmc0_cmd */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			0x158 0x2a      /* spi0_d1.i2c1_sda_mux3, INPUT | MODE2 */
+			0x15c 0x2a      /* spi0_cs0.i2c1_scl_mux3, INPUT | MODE2 */
+		>;
+	};
+
+	tps65910_pins: pinmux_tps65910_pins {
+		pinctrl-single,pins = <
+			0x078 (PIN_INPUT_PULLUP | MUX_MODE7)      /* gpmc_ben1.gpio1[28] */
+		>;
+
+	};
+	tca6416_pins: pinmux_tca6416_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE7)      /* xdma_event_intr1.gpio0[20] tca6416 stuff */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)		/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE1)       /* mii1_crs.rmii1_crs_dv */
+			0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_tx_en.rmii1_txen */
+			0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_txd1.rmii1_txd1 */
+			0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_txd0.rmii1_txd0 */
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE1)      /* mii1_rxd1.rmii1_rxd1 */
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE1)      /* mii1_rxd0.rmii1_rxd0 */
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE0)      /* rmii1_ref_clk.rmii1_refclk */
+
+
+			/* Slave 2 */
+			0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a0.rgmii2_tctl */
+			0x44 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a1.rgmii2_rctl */
+			0x48 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a2.rgmii2_td3 */
+			0x4c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a3.rgmii2_td2 */
+			0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a4.rgmii2_td1 */
+			0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a5.rgmii2_td0 */
+			0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a6.rgmii2_tclk */
+			0x5c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a7.rgmii2_rclk */
+			0x60 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a8.rgmii2_rd3 */
+			0x64 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a9.rgmii2_rd2 */
+			0x68 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a10.rgmii2_rd1 */
+			0x6c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a11.rgmii2_rd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+
+			/* Slave 2 reset value*/
+			0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	nandflash_pins_s0: nandflash_pins_s0 {
+		pinctrl-single,pins = <
+			0x0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+			0x4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+			0x8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+			0xc (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+			0x10 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+			0x14 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+			0x18 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+			0x1c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+			0x70 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+			0x74 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
+			0x7c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0  */
+			0x90 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+			0x94 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+			0x98 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+			0x9c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
+		>;
+	};
+};
+
+&elm {
+	status = "okay";
+};
+
+&gpmc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&nandflash_pins_s0>;
+	ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
+	status = "okay";
+
+	nand@0,0 {
+		reg = <0 0 0>; /* CS0, offset 0 */
+		nand-bus-width = <8>;
+		ti,nand-ecc-opt = "bch8";
+		ti,nand-xfer-type = "polled";
+
+		gpmc,device-nand = "true";
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-on-ns = <0>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,wait-on-read = "true";
+		gpmc,wait-on-write = "true";
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		elm_id = <&elm>;
+
+		boot@0 {
+		       label = "SPL";
+		       reg = <0x0 0x20000>;
+		};
+		boot@20000{
+		       label = "SPL.backup1";
+		       reg = <0x20000 0x20000>;
+		};
+		boot@40000 {
+		       label = "SPL.backup2";
+		       reg = <0x40000 0x20000>;
+		};
+		boot@60000 {
+		       label = "SPL.backup3";
+		       reg = <0x60000 0x20000>;
+		};
+		boot@80000 {
+		       label = "u-boot";
+		       reg = <0x80000 0x1e0000>;
+		};
+		boot@260000 {
+		       label = "UBI";
+		       reg = <0x260000 0xfda0000>;
+		};
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+
+	status = "okay";
+	clock-frequency = <1000>;
+
+	tps: tps@2d {
+		reg = <0x2d>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <28 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&tps65910_pins>;
+	};
+
+	at24@50 {
+		compatible = "at24,24c02";
+		pagesize = <8>;
+		reg = <0x50>;
+	};
+
+	tca6416: gpio@20 {
+		compatible = "ti,tca6416";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <20 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&tca6416_pins>;
+	};
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+/include/ "tps65910.dtsi"
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	ti,en-ck32k-xtal = <1>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1312500>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	dual_emac = <1>;
+
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rmii";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <7>;
+	phy-mode = "rgmii-txid";
+	dual_emac_res_vlan = <2>;
+};
+
+&phy_sel {
+	rmii-clock-ext = <1>;
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	vmmc-supply = <&vmmc_reg>;
+	status = "okay";
+};
+
+&gpio0 {
+	ti,no-reset-on-init;
+};
diff --git a/arch/arm/dts/meson-gx.dtsi b/arch/arm/dts/meson-gx.dtsi
index 3c31e21..f1e5cdb 100644
--- a/arch/arm/dts/meson-gx.dtsi
+++ b/arch/arm/dts/meson-gx.dtsi
@@ -35,10 +35,16 @@
 			no-map;
 		};
 
+		/* Alternate 3 MiB reserved for ARM Trusted Firmware (BL31) */
+		secmon_reserved_alt: secmon@5000000 {
+			reg = <0x0 0x05000000 0x0 0x300000>;
+			no-map;
+		};
+
 		linux,cma {
 			compatible = "shared-dma-pool";
 			reusable;
-			size = <0x0 0xbc00000>;
+			size = <0x0 0x10000000>;
 			alignment = <0x0 0x400000>;
 			linux,cma-default;
 		};
@@ -338,7 +344,7 @@
 			ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
 
 			sysctrl_AO: sys-ctrl@0 {
-				compatible = "amlogic,meson-gx-ao-sysctrl", "syscon", "simple-mfd";
+				compatible = "amlogic,meson-gx-ao-sysctrl", "simple-mfd", "syscon";
 				reg =  <0x0 0x0 0x0 0x100>;
 
 				pwrc_vpu: power-controller-vpu {
@@ -417,6 +423,19 @@
 			};
 		};
 
+		dmcbus: bus@c8838000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc8838000 0x0 0x400>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc8838000 0x0 0x400>;
+
+			canvas: video-lut@48 {
+				compatible = "amlogic,canvas";
+				reg = <0x0 0x48 0x0 0x14>;
+			};
+		};
+
 		hiubus: bus@c883c000 {
 			compatible = "simple-bus";
 			reg = <0x0 0xc883c000 0x0 0x2000>;
@@ -425,7 +444,7 @@
 			ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>;
 
 			sysctrl: system-controller@0 {
-				compatible = "amlogic,meson-gx-hhi-sysctrl", "syscon", "simple-mfd";
+				compatible = "amlogic,meson-gx-hhi-sysctrl", "simple-mfd", "syscon";
 				reg = <0 0 0 0x400>;
 			};
 
@@ -457,21 +476,21 @@
 
 			sd_emmc_a: mmc@70000 {
 				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
-				reg = <0x0 0x70000 0x0 0x2000>;
+				reg = <0x0 0x70000 0x0 0x800>;
 				interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
 				status = "disabled";
 			};
 
 			sd_emmc_b: mmc@72000 {
 				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
-				reg = <0x0 0x72000 0x0 0x2000>;
+				reg = <0x0 0x72000 0x0 0x800>;
 				interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
 				status = "disabled";
 			};
 
 			sd_emmc_c: mmc@74000 {
 				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
-				reg = <0x0 0x74000 0x0 0x2000>;
+				reg = <0x0 0x74000 0x0 0x800>;
 				interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
 				status = "disabled";
 			};
diff --git a/arch/arm/dts/meson-gxbb-nanopi-k2.dts b/arch/arm/dts/meson-gxbb-nanopi-k2.dts
index 7d5709c..cbe99bd 100644
--- a/arch/arm/dts/meson-gxbb-nanopi-k2.dts
+++ b/arch/arm/dts/meson-gxbb-nanopi-k2.dts
@@ -106,6 +106,42 @@
 		compatible = "mmc-pwrseq-emmc";
 		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
 	};
+
+	/* CVBS is available on CON1 pin 36, disabled by default */
+	cvbs-connector {
+		compatible = "composite-video-connector";
+		status = "disabled";
+
+		port {
+			cvbs_connector_in: endpoint {
+				remote-endpoint = <&cvbs_vdac_out>;
+			};
+		};
+	};
+
+	hdmi-connector {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&hdmi_tx_tmds_out>;
+			};
+		};
+	};
+};
+
+&cec_AO {
+	status = "okay";
+	pinctrl-0 = <&ao_cec_pins>;
+	pinctrl-names = "default";
+	hdmi-phandle = <&hdmi_tx>;
+};
+
+&cvbs_vdac_port {
+	cvbs_vdac_out: endpoint {
+		remote-endpoint = <&cvbs_connector_in>;
+	};
 };
 
 &ethmac {
@@ -137,6 +173,18 @@
 	};
 };
 
+&hdmi_tx {
+	status = "okay";
+	pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
+	pinctrl-names = "default";
+};
+
+&hdmi_tx_tmds_port {
+	hdmi_tx_tmds_out: endpoint {
+		remote-endpoint = <&hdmi_connector_in>;
+	};
+};
+
 &ir {
 	status = "okay";
 	pinctrl-0 = <&remote_input_ao_pins>;
diff --git a/arch/arm/dts/meson-gxbb.dtsi b/arch/arm/dts/meson-gxbb.dtsi
index 562c26a..1ade7e4 100644
--- a/arch/arm/dts/meson-gxbb.dtsi
+++ b/arch/arm/dts/meson-gxbb.dtsi
@@ -307,11 +307,10 @@
 	clock-names = "isfr", "iahb", "venci";
 };
 
-&hiubus {
-	clkc: clock-controller@0 {
+&sysctrl {
+	clkc: clock-controller {
 		compatible = "amlogic,gxbb-clkc";
 		#clock-cells = <1>;
-		reg = <0x0 0x0 0x0 0x3db>;
 	};
 };
 
@@ -391,7 +390,7 @@
 			};
 		};
 
-		spi_pins: spi {
+		spi_pins: spi-pins {
 			mux {
 				groups = "spi_miso",
 					"spi_mosi",
@@ -716,6 +715,7 @@
 		 <&clkc CLKID_SD_EMMC_A_CLK0>,
 		 <&clkc CLKID_FCLK_DIV2>;
 	clock-names = "core", "clkin0", "clkin1";
+	resets = <&reset RESET_SD_EMMC_A>;
 };
 
 &sd_emmc_b {
@@ -723,6 +723,7 @@
 		 <&clkc CLKID_SD_EMMC_B_CLK0>,
 		 <&clkc CLKID_FCLK_DIV2>;
 	clock-names = "core", "clkin0", "clkin1";
+	resets = <&reset RESET_SD_EMMC_B>;
 };
 
 &sd_emmc_c {
@@ -730,6 +731,7 @@
 		 <&clkc CLKID_SD_EMMC_C_CLK0>,
 		 <&clkc CLKID_FCLK_DIV2>;
 	clock-names = "core", "clkin0", "clkin1";
+	resets = <&reset RESET_SD_EMMC_C>;
 };
 
 &spicc {
@@ -749,12 +751,12 @@
 };
 
 &uart_AO {
-	clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+	clocks = <&xtal>, <&clkc_AO CLKID_AO_UART1>, <&xtal>;
 	clock-names = "xtal", "pclk", "baud";
 };
 
 &uart_AO_B {
-	clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+	clocks = <&xtal>, <&clkc_AO CLKID_AO_UART2>, <&xtal>;
 	clock-names = "xtal", "pclk", "baud";
 };
 
diff --git a/arch/arm/dts/meson-gxl-mali.dtsi b/arch/arm/dts/meson-gxl-mali.dtsi
index eb32766..6aaafff 100644
--- a/arch/arm/dts/meson-gxl-mali.dtsi
+++ b/arch/arm/dts/meson-gxl-mali.dtsi
@@ -6,7 +6,7 @@
 
 &apb {
 	mali: gpu@c0000 {
-		compatible = "amlogic,meson-gxbb-mali", "arm,mali-450";
+		compatible = "amlogic,meson-gxl-mali", "arm,mali-450";
 		reg = <0x0 0xc0000 0x0 0x40000>;
 		interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/arch/arm/dts/meson-gxl-s905x-libretech-cc.dts b/arch/arm/dts/meson-gxl-s905x-libretech-cc.dts
index 3e3eb31..90a56af 100644
--- a/arch/arm/dts/meson-gxl-s905x-libretech-cc.dts
+++ b/arch/arm/dts/meson-gxl-s905x-libretech-cc.dts
@@ -13,7 +13,7 @@
 
 / {
 	compatible = "libretech,cc", "amlogic,s905x", "amlogic,meson-gxl";
-	model = "Libre Technology CC";
+	model = "Libre Computer Board AML-S905X-CC";
 
 	aliases {
 		serial0 = &uart_AO;
@@ -234,9 +234,6 @@
 
 	bus-width = <4>;
 	cap-sd-highspeed;
-	sd-uhs-sdr12;
-	sd-uhs-sdr25;
-	sd-uhs-sdr50;
 	max-frequency = <100000000>;
 	disable-wp;
 
diff --git a/arch/arm/dts/meson-gxl-s905x-p212.dtsi b/arch/arm/dts/meson-gxl-s905x-p212.dtsi
index 3bd4050..a1b3101 100644
--- a/arch/arm/dts/meson-gxl-s905x-p212.dtsi
+++ b/arch/arm/dts/meson-gxl-s905x-p212.dtsi
@@ -191,8 +191,8 @@
 };
 
 &usb2_phy0 {
-        /*
-         * HDMI_5V is also used as supply for the USB VBUS.
-         */
-        phy-supply = <&hdmi_5v>;
+	/*
+	 * HDMI_5V is also used as supply for the USB VBUS.
+	 */
+	phy-supply = <&hdmi_5v>;
 };
diff --git a/arch/arm/dts/meson-gxl.dtsi b/arch/arm/dts/meson-gxl.dtsi
index dba365e..8f0bb3c 100644
--- a/arch/arm/dts/meson-gxl.dtsi
+++ b/arch/arm/dts/meson-gxl.dtsi
@@ -13,14 +13,6 @@
 / {
 	compatible = "amlogic,meson-gxl";
 
-	reserved-memory {
-		/* Alternate 3 MiB reserved for ARM Trusted Firmware (BL31) */
-		secmon_reserved_alt: secmon@5000000 {
-			reg = <0x0 0x05000000 0x0 0x300000>;
-			no-map;
-		};
-	};
-
 	soc {
 		usb0: usb@c9000000 {
 			status = "disabled";
@@ -267,11 +259,10 @@
 	clock-names = "isfr", "iahb", "venci";
 };
 
-&hiubus {
-	clkc: clock-controller@0 {
-		compatible = "amlogic,gxl-clkc", "amlogic,gxbb-clkc";
+&sysctrl {
+	clkc: clock-controller {
+		compatible = "amlogic,gxl-clkc";
 		#clock-cells = <1>;
-		reg = <0x0 0x0 0x0 0x3db>;
 	};
 };
 
@@ -346,7 +337,7 @@
 			};
 		};
 
-		spi_pins: spi {
+		spi_pins: spi-pins {
 			mux {
 				groups = "spi_miso",
 					"spi_mosi",
@@ -725,13 +716,15 @@
 		 <&clkc CLKID_SD_EMMC_A_CLK0>,
 		 <&clkc CLKID_FCLK_DIV2>;
 	clock-names = "core", "clkin0", "clkin1";
+	resets = <&reset RESET_SD_EMMC_A>;
 };
 
 &sd_emmc_b {
 	clocks = <&clkc CLKID_SD_EMMC_B>,
 		 <&clkc CLKID_SD_EMMC_B_CLK0>,
 		 <&clkc CLKID_FCLK_DIV2>;
-       clock-names = "core", "clkin0", "clkin1";
+	clock-names = "core", "clkin0", "clkin1";
+	resets = <&reset RESET_SD_EMMC_B>;
 };
 
 &sd_emmc_c {
@@ -739,6 +732,7 @@
 		 <&clkc CLKID_SD_EMMC_C_CLK0>,
 		 <&clkc CLKID_FCLK_DIV2>;
 	clock-names = "core", "clkin0", "clkin1";
+	resets = <&reset RESET_SD_EMMC_C>;
 };
 
 &spicc {
@@ -758,12 +752,12 @@
 };
 
 &uart_AO {
-	clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+	clocks = <&xtal>, <&clkc_AO CLKID_AO_UART1>, <&xtal>;
 	clock-names = "xtal", "pclk", "baud";
 };
 
 &uart_AO_B {
-	clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+	clocks = <&xtal>, <&clkc_AO CLKID_AO_UART2>, <&xtal>;
 	clock-names = "xtal", "pclk", "baud";
 };
 
diff --git a/arch/arm/dts/meson-gxm-khadas-vim2.dts b/arch/arm/dts/meson-gxm-khadas-vim2.dts
index 0868da4..313f88f 100644
--- a/arch/arm/dts/meson-gxm-khadas-vim2.dts
+++ b/arch/arm/dts/meson-gxm-khadas-vim2.dts
@@ -209,10 +209,34 @@
 	#cooling-cells = <2>;
 };
 
+&cpu1 {
+	#cooling-cells = <2>;
+};
+
+&cpu2 {
+	#cooling-cells = <2>;
+};
+
+&cpu3 {
+	#cooling-cells = <2>;
+};
+
 &cpu4 {
 	#cooling-cells = <2>;
 };
 
+&cpu5 {
+	#cooling-cells = <2>;
+};
+
+&cpu6 {
+	#cooling-cells = <2>;
+};
+
+&cpu7 {
+	#cooling-cells = <2>;
+};
+
 &ethmac {
 	pinctrl-0 = <&eth_pins>;
 	pinctrl-names = "default";
diff --git a/arch/arm/dts/r8a77990-ebisu.dts b/arch/arm/dts/r8a77990-ebisu.dts
index 5e3c195..0f269d0 100644
--- a/arch/arm/dts/r8a77990-ebisu.dts
+++ b/arch/arm/dts/r8a77990-ebisu.dts
@@ -46,6 +46,54 @@
 		regulator-boot-on;
 		regulator-always-on;
 	};
+
+	vcc_sdhi0: regulator-vcc-sdhi0 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI0 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio5 17 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi0: regulator-vccq-sdhi0 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI0 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio5 18 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
+
+	vcc_sdhi1: regulator-vcc-sdhi1 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI1 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi1: regulator-vccq-sdhi1 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI1 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio3 15 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
 };
 
 &avb {
@@ -94,14 +142,38 @@
 		function = "scif_clk";
 	};
 
+	sdhi0_pins: sd0 {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <3300>;
+	};
+
+	sdhi0_pins_uhs: sd0_uhs {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <1800>;
+	};
+
+	sdhi1_pins: sd1 {
+		groups = "sdhi1_data4", "sdhi1_ctrl";
+		function = "sdhi1";
+		power-source = <3300>;
+	};
+
+	sdhi1_pins_uhs: sd1_uhs {
+		groups = "sdhi1_data4", "sdhi1_ctrl";
+		function = "sdhi1";
+		power-source = <1800>;
+	};
+
 	sdhi3_pins: sd2 {
-		groups = "sdhi3_data8", "sdhi3_ctrl";
+		groups = "sdhi3_data8", "sdhi3_ctrl", "sdhi3_ds";
 		function = "sdhi3";
 		power-source = <1800>;
 	};
 
 	sdhi3_pins_uhs: sd2_uhs {
-		groups = "sdhi3_data8", "sdhi3_ctrl";
+		groups = "sdhi3_data8", "sdhi3_ctrl", "sdhi3_ds";
 		function = "sdhi3";
 		power-source = <1800>;
 	};
@@ -120,11 +192,40 @@
 };
 
 &sdhi0 {
+	/* full size SD */
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-1 = <&sdhi0_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
+
+	vmmc-supply = <&vcc_sdhi0>;
+	vqmmc-supply = <&vccq_sdhi0>;
+	cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
+	bus-width = <4>;
+	sd-uhs-sdr12;
+	sd-uhs-sdr25;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
 	status = "okay";
+	max-frequency = <208000000>;
 };
 
 &sdhi1 {
+	/* microSD */
+	pinctrl-0 = <&sdhi1_pins>;
+	pinctrl-1 = <&sdhi1_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
+
+	vmmc-supply = <&vcc_sdhi1>;
+	vqmmc-supply = <&vccq_sdhi1>;
+	cd-gpios = <&gpio3 14 GPIO_ACTIVE_LOW>;
+	bus-width = <4>;
+	sd-uhs-sdr12;
+	sd-uhs-sdr25;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
 	status = "okay";
+	max-frequency = <208000000>;
 };
 
 &sdhi3 {
@@ -137,6 +238,7 @@
 	vqmmc-supply = <&reg_1p8v>;
 	bus-width = <8>;
 	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
 	non-removable;
 	status = "okay";
 };
diff --git a/arch/arm/dts/salvator-common.dtsi b/arch/arm/dts/salvator-common.dtsi
index a36e0eb..b036a71 100644
--- a/arch/arm/dts/salvator-common.dtsi
+++ b/arch/arm/dts/salvator-common.dtsi
@@ -480,13 +480,13 @@
 	};
 
 	sdhi2_pins: sd2 {
-		groups = "sdhi2_data8", "sdhi2_ctrl";
+		groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
 		function = "sdhi2";
 		power-source = <1800>;
 	};
 
 	sdhi2_pins_uhs: sd2_uhs {
-		groups = "sdhi2_data8", "sdhi2_ctrl";
+		groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
 		function = "sdhi2";
 		power-source = <1800>;
 	};
@@ -618,8 +618,13 @@
 	cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
 	wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
 	bus-width = <4>;
+	sd-uhs-sdr12;
+	sd-uhs-sdr25;
 	sd-uhs-sdr50;
+	sd-uhs-sdr104;
 	status = "okay";
+
+	max-frequency = <208000000>;
 };
 
 &sdhi2 {
@@ -632,9 +637,11 @@
 	vqmmc-supply = <&reg_1p8v>;
 	bus-width = <8>;
 	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
 	non-removable;
 	fixed-emmc-driver-type = <1>;
 	status = "okay";
+	max-frequency = <200000000>;
 };
 
 &sdhi3 {
@@ -647,8 +654,12 @@
 	cd-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>;
 	wp-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>;
 	bus-width = <4>;
+	sd-uhs-sdr12;
+	sd-uhs-sdr25;
 	sd-uhs-sdr50;
+	sd-uhs-sdr104;
 	status = "okay";
+	max-frequency = <208000000>;
 };
 
 &ssi1 {
diff --git a/arch/arm/dts/ulcb.dtsi b/arch/arm/dts/ulcb.dtsi
index ab88665..e16c7f2 100644
--- a/arch/arm/dts/ulcb.dtsi
+++ b/arch/arm/dts/ulcb.dtsi
@@ -308,13 +308,13 @@
 	};
 
 	sdhi2_pins: sd2 {
-		groups = "sdhi2_data8", "sdhi2_ctrl";
+		groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
 		function = "sdhi2";
 		power-source = <1800>;
 	};
 
 	sdhi2_pins_uhs: sd2_uhs {
-		groups = "sdhi2_data8", "sdhi2_ctrl";
+		groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
 		function = "sdhi2";
 		power-source = <1800>;
 	};
@@ -396,8 +396,12 @@
 	vqmmc-supply = <&vccq_sdhi0>;
 	cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
 	bus-width = <4>;
+	sd-uhs-sdr12;
+	sd-uhs-sdr25;
 	sd-uhs-sdr50;
+	sd-uhs-sdr104;
 	status = "okay";
+	max-frequency = <208000000>;
 };
 
 &sdhi2 {
@@ -410,8 +414,10 @@
 	vqmmc-supply = <&reg_1p8v>;
 	bus-width = <8>;
 	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
 	non-removable;
 	status = "okay";
+	max-frequency = <200000000>;
 };
 
 &ssi1 {
diff --git a/arch/arm/lib/crt0_aarch64_efi.S b/arch/arm/lib/crt0_aarch64_efi.S
index 0db4360..cb205fa 100644
--- a/arch/arm/lib/crt0_aarch64_efi.S
+++ b/arch/arm/lib/crt0_aarch64_efi.S
@@ -28,13 +28,13 @@
 	.short	2				/* nr_sections */
 	.long	0				/* TimeDateStamp */
 	.long	0				/* PointerToSymbolTable */
-	.long	1				/* NumberOfSymbols */
+	.long	0				/* NumberOfSymbols */
 	.short	section_table - optional_header	/* SizeOfOptionalHeader */
-	/*
-	 * Characteristics: IMAGE_FILE_DEBUG_STRIPPED |
-	 * IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LINE_NUMS_STRIPPED
-	 */
-	.short	0x206
+	/* Characteristics */
+	.short	(IMAGE_FILE_EXECUTABLE_IMAGE | \
+		 IMAGE_FILE_LINE_NUMS_STRIPPED | \
+		 IMAGE_FILE_LOCAL_SYMS_STRIPPED | \
+		 IMAGE_FILE_DEBUG_STRIPPED)
 optional_header:
 	.short	0x20b				/* PE32+ format */
 	.byte	0x02				/* MajorLinkerVersion */
diff --git a/arch/arm/lib/crt0_arm_efi.S b/arch/arm/lib/crt0_arm_efi.S
index 23db49f..5470e2f 100644
--- a/arch/arm/lib/crt0_arm_efi.S
+++ b/arch/arm/lib/crt0_arm_efi.S
@@ -27,16 +27,16 @@
 	.short	2				/* nr_sections */
 	.long	0				/* TimeDateStamp */
 	.long	0				/* PointerToSymbolTable */
-	.long	1				/* NumberOfSymbols */
+	.long	0				/* NumberOfSymbols */
 	.short	section_table - optional_header	/* SizeOfOptionalHeader */
-	/*
-	 * Characteristics: IMAGE_FILE_32BIT_MACHINE |
-	 * IMAGE_FILE_DEBUG_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE |
-	 * IMAGE_FILE_LINE_NUMS_STRIPPED
-	 */
-	.short	0x306
+	/* Characteristics */
+	.short	(IMAGE_FILE_EXECUTABLE_IMAGE | \
+		 IMAGE_FILE_LINE_NUMS_STRIPPED | \
+		 IMAGE_FILE_LOCAL_SYMS_STRIPPED | \
+		 IMAGE_FILE_32BIT_MACHINE | \
+		 IMAGE_FILE_DEBUG_STRIPPED)
 optional_header:
-	.short	0x10b				/* PE32+ format */
+	.short	0x10b				/* PE32 format */
 	.byte	0x02				/* MajorLinkerVersion */
 	.byte	0x14				/* MinorLinkerVersion */
 	.long	_edata - _start			/* SizeOfCode */
diff --git a/arch/powerpc/cpu/mpc8xx/start.S b/arch/powerpc/cpu/mpc8xx/start.S
index 8dde4be..b8bdaae 100644
--- a/arch/powerpc/cpu/mpc8xx/start.S
+++ b/arch/powerpc/cpu/mpc8xx/start.S
@@ -144,9 +144,11 @@
 	ori	r2, r2, CONFIG_SYS_DER@l
 	mtspr	DER, r2
 
-	/* set up the stack in internal DPRAM */
+	/* set up the stack on top of internal DPRAM */
 	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)@h
 	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)@l
+	stw	r0, -4(r3)
+	stw	r0, -8(r3)
 	addi	r1, r3, -8
 
 	bl	board_init_f_alloc_reserve
diff --git a/arch/powerpc/dts/Makefile b/arch/powerpc/dts/Makefile
index a19aa56..172bed4 100644
--- a/arch/powerpc/dts/Makefile
+++ b/arch/powerpc/dts/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0+
 
 dtb-$(CONFIG_TARGET_T2080QDS) += t2080qds.dtb
+dtb-$(CONFIG_MCR3000) += mcr3000.dtb
 
 targets += $(dtb-y)
 
diff --git a/arch/powerpc/dts/mcr3000.dts b/arch/powerpc/dts/mcr3000.dts
new file mode 100644
index 0000000..5abf111
--- /dev/null
+++ b/arch/powerpc/dts/mcr3000.dts
@@ -0,0 +1,22 @@
+/*
+ * MCR3000 Device Tree Source
+ *
+ * Copyright 2017 CS Systemes d'Information
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+/ {
+	WDT: watchdog@0 {
+		compatible = "fsl,pq1-wdt";
+	};
+	SERIAL: smc@0 {
+		compatible = "fsl,pq1-smc";
+	};
+
+	chosen {
+		stdout-path = &SERIAL;
+	};
+};
diff --git a/arch/riscv/lib/crt0_riscv_efi.S b/arch/riscv/lib/crt0_riscv_efi.S
index 18f61f5..b7b5329 100644
--- a/arch/riscv/lib/crt0_riscv_efi.S
+++ b/arch/riscv/lib/crt0_riscv_efi.S
@@ -41,13 +41,13 @@
 	.short	2				/* nr_sections */
 	.long	0				/* TimeDateStamp */
 	.long	0				/* PointerToSymbolTable */
-	.long	1				/* NumberOfSymbols */
+	.long	0				/* NumberOfSymbols */
 	.short	section_table - optional_header	/* SizeOfOptionalHeader */
-	/*
-	 * Characteristics: IMAGE_FILE_DEBUG_STRIPPED |
-	 * IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LINE_NUMS_STRIPPED
-	 */
-	.short	0x206
+	/* Characteristics */
+	.short	(IMAGE_FILE_EXECUTABLE_IMAGE | \
+		 IMAGE_FILE_LINE_NUMS_STRIPPED | \
+		 IMAGE_FILE_LOCAL_SYMS_STRIPPED | \
+		 IMAGE_FILE_DEBUG_STRIPPED)
 optional_header:
 	.short	0x20b				/* PE32+ format */
 	.byte	0x02				/* MajorLinkerVersion */
diff --git a/arch/x86/config.mk b/arch/x86/config.mk
index 8151e47..b5e8f46 100644
--- a/arch/x86/config.mk
+++ b/arch/x86/config.mk
@@ -34,7 +34,7 @@
 
 # This is used in the top-level Makefile which does not include
 # PLATFORM_LDFLAGS
-LDFLAGS_EFI_PAYLOAD := -Bsymbolic -Bsymbolic-functions -shared --no-undefined
+LDFLAGS_EFI_PAYLOAD := -Bsymbolic -Bsymbolic-functions -shared --no-undefined -s
 
 OBJCOPYFLAGS_EFI := -j .text -j .sdata -j .data -j .dynamic -j .dynsym \
 	-j .rel -j .rela -j .reloc
@@ -65,7 +65,7 @@
 ifeq ($(CONFIG_EFI_APP),y)
 
 PLATFORM_CPPFLAGS += $(CFLAGS_EFI)
-LDFLAGS_FINAL += -znocombreloc -shared
+LDFLAGS_FINAL += -znocombreloc -shared -s
 LDSCRIPT := $(LDSCRIPT_EFI)
 
 else
diff --git a/board/cssi/MCR3000/MCR3000.c b/board/cssi/MCR3000/MCR3000.c
index ffbeb14..d26ac35 100644
--- a/board/cssi/MCR3000/MCR3000.c
+++ b/board/cssi/MCR3000/MCR3000.c
@@ -12,6 +12,8 @@
 #include <mpc8xx.h>
 #include <fdt_support.h>
 #include <asm/io.h>
+#include <dm/uclass.h>
+#include <wdt.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -143,3 +145,17 @@
 
 	return 0;
 }
+
+int board_early_init_r(void)
+{
+	struct udevice *watchdog_dev = NULL;
+
+	if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
+		puts("Cannot find watchdog!\n");
+	} else {
+		puts("Enabling watchdog.\n");
+		wdt_start(watchdog_dev, 0xffff, 0);
+	}
+
+	return 0;
+}
diff --git a/board/cssi/MCR3000/u-boot.lds b/board/cssi/MCR3000/u-boot.lds
index a32c0e7..70aef32 100644
--- a/board/cssi/MCR3000/u-boot.lds
+++ b/board/cssi/MCR3000/u-boot.lds
@@ -19,7 +19,6 @@
 		arch/powerpc/cpu/mpc8xx/start.o	(.text)
 		arch/powerpc/cpu/mpc8xx/traps.o	(.text*)
 		arch/powerpc/lib/built-in.o		(.text*)
-		board/cssi/MCR3000/built-in.o	(.text*)
 		drivers/net/built-in.o		(.text*)
 
 		. = DEFINED(env_offset) ? env_offset : .;
@@ -69,6 +68,12 @@
 	__ex_table : { *(__ex_table) }
 	__stop___ex_table = .;
 
+	/*
+	 * _end - This is end of u-boot.bin image.
+	 * dtb will be appended here to make u-boot-dtb.bin
+	 */
+	_end = .;
+
 	. = ALIGN(4096);
 	__init_begin = .;
 	.text.init : { *(.text.init) }
diff --git a/board/synopsys/axs10x/axs10x.c b/board/synopsys/axs10x/axs10x.c
index c95f7af..ffa7c15 100644
--- a/board/synopsys/axs10x/axs10x.c
+++ b/board/synopsys/axs10x/axs10x.c
@@ -109,3 +109,11 @@
 	writel(cmd, (void __iomem *)AXC003_CREG_CPU_START);
 }
 #endif
+
+int checkboard(void)
+{
+	printf("Board: ARC Software Development Platform AXS%s\n",
+	     is_isa_arcv2() ? "103" : "101");
+
+	return 0;
+};
diff --git a/board/synopsys/emsdp/emsdp.c b/board/synopsys/emsdp/emsdp.c
index b5ec7f1..c0770b5 100644
--- a/board/synopsys/emsdp/emsdp.c
+++ b/board/synopsys/emsdp/emsdp.c
@@ -7,10 +7,46 @@
 #include <dwmmc.h>
 #include <malloc.h>
 
+#include <asm/arcregs.h>
+
 DECLARE_GLOBAL_DATA_PTR;
 
+#define ARC_PERIPHERAL_BASE		0xF0000000
+
+#define CGU_ARC_FMEAS_ARC		(void *)(ARC_PERIPHERAL_BASE + 0x84)
+#define CGU_ARC_FMEAS_ARC_START		BIT(31)
+#define CGU_ARC_FMEAS_ARC_DONE		BIT(30)
+#define CGU_ARC_FMEAS_ARC_CNT_MASK	GENMASK(14, 0)
+#define CGU_ARC_FMEAS_ARC_RCNT_OFFSET	0
+#define CGU_ARC_FMEAS_ARC_FCNT_OFFSET	15
+
+#define SDIO_BASE			(void *)(ARC_PERIPHERAL_BASE + 0x10000)
+
+int mach_cpu_init(void)
+{
+	int rcnt, fcnt;
+	u32 data;
+
+	/* Start frequency measurement */
+	writel(CGU_ARC_FMEAS_ARC_START, CGU_ARC_FMEAS_ARC);
+
+	/* Poll DONE bit */
+	do {
+		data = readl(CGU_ARC_FMEAS_ARC);
+	} while (!(data & CGU_ARC_FMEAS_ARC_DONE));
+
+	/* Amount of reference 100 MHz clocks */
+	rcnt = ((data >> CGU_ARC_FMEAS_ARC_RCNT_OFFSET) &
+	       CGU_ARC_FMEAS_ARC_CNT_MASK);
+
-#define ARC_PERIPHERAL_BASE	0xF0000000
-#define SDIO_BASE		(ARC_PERIPHERAL_BASE + 0x10000)
+	/* Amount of CPU clocks */
+	fcnt = ((data >> CGU_ARC_FMEAS_ARC_FCNT_OFFSET) &
+	       CGU_ARC_FMEAS_ARC_CNT_MASK);
+
+	gd->cpu_clk = ((100 * fcnt) / rcnt) * 1000000;
+
+	return 0;
+}
 
 int board_mmc_init(bd_t *bis)
 {
@@ -24,7 +60,7 @@
 
 	memset(host, 0, sizeof(struct dwmci_host));
 	host->name = "Synopsys Mobile storage";
-	host->ioaddr = (void *)SDIO_BASE;
+	host->ioaddr = SDIO_BASE;
 	host->buswidth = 4;
 	host->dev_index = 0;
 	host->bus_hz = 50000000;
@@ -42,31 +78,32 @@
 }
 
 #define CREG_BASE		0xF0001000
-#define CREG_BOOT_OFFSET	0
-#define CREG_BOOT_WP_OFFSET	8
+#define CREG_BOOT		(void *)(CREG_BASE + 0x0FF0)
+#define CREG_IP_SW_RESET	(void *)(CREG_BASE + 0x0FF0)
+#define CREG_IP_VERSION		(void *)(CREG_BASE + 0x0FF8)
 
-#define CGU_BASE		0xF0000000
-#define CGU_IP_SW_RESET		0x0FF0
+/* Bits in CREG_BOOT register */
+#define CREG_BOOT_WP_BIT	BIT(8)
 
 void reset_cpu(ulong addr)
 {
-	writel(1, (u32 *)(CGU_BASE + CGU_IP_SW_RESET));
+	writel(1, CREG_IP_SW_RESET);
 	while (1)
 		; /* loop forever till reset */
 }
 
 static int do_emsdp_rom(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 {
-	u32 creg_boot = readl((u32 *)(CREG_BASE + CREG_BOOT_OFFSET));
+	u32 creg_boot = readl(CREG_BOOT);
 
 	if (!strcmp(argv[1], "unlock"))
-		creg_boot &= ~BIT(CREG_BOOT_WP_OFFSET);
+		creg_boot &= ~CREG_BOOT_WP_BIT;
 	else if (!strcmp(argv[1], "lock"))
-		creg_boot |= BIT(CREG_BOOT_WP_OFFSET);
+		creg_boot |= CREG_BOOT_WP_BIT;
 	else
 		return CMD_RET_USAGE;
 
-	writel(creg_boot, (u32 *)(CREG_BASE + CREG_BOOT_OFFSET));
+	writel(creg_boot, CREG_BOOT);
 
 	return CMD_RET_SUCCESS;
 }
@@ -97,3 +134,12 @@
 	"rom unlock - Unlock non-volatile memory for writing\n"
 	"emsdp rom lock - Lock non-volatile memory to prevent writing\n"
 );
+
+int checkboard(void)
+{
+	int version = readl(CREG_IP_VERSION);
+
+	printf("Board: ARC EM Software Development Platform v%d.%d\n",
+	       (version >> 16) & 0xff, version & 0xff);
+	return 0;
+};
diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c
index b6aefdb..8a2c201 100644
--- a/board/synopsys/hsdk/hsdk.c
+++ b/board/synopsys/hsdk/hsdk.c
@@ -1054,10 +1054,8 @@
 	return 0;
 }
 
-#ifdef CONFIG_DISPLAY_CPUINFO
-int print_cpuinfo(void)
+int checkboard(void)
 {
-	printf("CPU:   ARC HS38 v2.1c\n");
+	puts("Board: Synopsys ARC HS Development Kit\n");
 	return 0;
-}
-#endif /* CONFIG_DISPLAY_CPUINFO */
+};
diff --git a/board/synopsys/iot_devkit/iot_devkit.c b/board/synopsys/iot_devkit/iot_devkit.c
index f8838fb..8424e09 100644
--- a/board/synopsys/iot_devkit/iot_devkit.c
+++ b/board/synopsys/iot_devkit/iot_devkit.c
@@ -189,13 +189,3 @@
 	puts("Board: Synopsys IoT Development Kit\n");
 	return 0;
 };
-
-#ifdef CONFIG_DISPLAY_CPUINFO
-int print_cpuinfo(void)
-{
-	char mhz[8];
-
-	printf("CPU:   ARC EM9D at %s MHz\n", strmhz(mhz, gd->cpu_clk));
-	return 0;
-}
-#endif /* CONFIG_DISPLAY_CPUINFO */
diff --git a/board/vscom/baltos/board.c b/board/vscom/baltos/board.c
index df0a2d2..c5949ad 100644
--- a/board/vscom/baltos/board.c
+++ b/board/vscom/baltos/board.c
@@ -27,7 +27,6 @@
 #include <i2c.h>
 #include <miiphy.h>
 #include <cpsw.h>
-#include <power/tps65217.h>
 #include <power/tps65910.h>
 #include <environment.h>
 #include <watchdog.h>
@@ -35,8 +34,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-/* GPIO that controls power to DDR on EVM-SK */
-#define GPIO_DDR_VTT_EN		7
+/* GPIO that controls DIP switch and mPCIe slot */
 #define DIP_S1			44
 #define MPCIE_SW		100
 
@@ -248,9 +246,6 @@
 
 void sdram_init(void)
 {
-	gpio_request(GPIO_DDR_VTT_EN, "ddr_vtt_en");
-	gpio_direction_output(GPIO_DDR_VTT_EN, 1);
-
 	config_ddr(400, &ioregs_baltos,
 		   &ddr3_baltos_data,
 		   &ddr3_baltos_cmd_ctrl_data,
diff --git a/board/vscom/baltos/mux.c b/board/vscom/baltos/mux.c
index 94410ae..9c5542e 100644
--- a/board/vscom/baltos/mux.c
+++ b/board/vscom/baltos/mux.c
@@ -34,7 +34,6 @@
 	{OFFSET(mmc0_dat0), (MODE(0) | RXACTIVE | PULLUP_EN)},	/* MMC0_DAT0 */
 	{OFFSET(mmc0_clk), (MODE(0) | RXACTIVE | PULLUP_EN)},	/* MMC0_CLK */
 	{OFFSET(mmc0_cmd), (MODE(0) | RXACTIVE | PULLUP_EN)},	/* MMC0_CMD */
-	//{OFFSET(spi0_cs1), (MODE(5) | RXACTIVE | PULLUP_EN)},	/* MMC0_CD */
 	{-1},
 };
 
@@ -46,11 +45,6 @@
 	{-1},
 };
 
-static struct module_pin_mux gpio0_7_pin_mux[] = {
-	{OFFSET(ecap0_in_pwm0_out), (MODE(7) | PULLUDEN)},	/* GPIO0_7 */
-	{-1},
-};
-
 static struct module_pin_mux rmii1_pin_mux[] = {
 	{OFFSET(mii1_crs), MODE(1) | RXACTIVE},			/* RGMII1_TCTL */
 	{OFFSET(mii1_txen), MODE(1)},			/* RGMII1_TCTL */
@@ -114,7 +108,6 @@
 void enable_board_pin_mux()
 {
 	configure_module_pin_mux(i2c1_pin_mux);
-	configure_module_pin_mux(gpio0_7_pin_mux);
 	configure_module_pin_mux(rgmii2_pin_mux);
 	configure_module_pin_mux(rmii1_pin_mux);
 	configure_module_pin_mux(mmc0_pin_mux);
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 4d68d80..38679ff 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -148,16 +148,16 @@
 /**
  * copy_fdt() - Copy the device tree to a new location available to EFI
  *
- * The FDT is relocated into a suitable location within the EFI memory map.
- * An additional 12KB is added to the space in case the device tree needs to be
+ * The FDT is copied to a suitable location within the EFI memory map.
+ * Additional 12 KiB are added to the space in case the device tree needs to be
  * expanded later with fdt_open_into().
  *
- * @fdt_addr: On entry, address of start of FDT. On exit, address of relocated
- *	FDT start
- * @fdt_sizep: Returns new size of FDT, including
- * @return new relocated address of FDT
+ * @fdtp:	On entry a pointer to the flattened device tree.
+ *		On exit a pointer to the copy of the flattened device tree.
+ *		FDT start
+ * Return:	status code
  */
-static efi_status_t copy_fdt(ulong *fdt_addrp, ulong *fdt_sizep)
+static efi_status_t copy_fdt(void **fdtp)
 {
 	unsigned long fdt_ram_start = -1L, fdt_pages;
 	efi_status_t ret = 0;
@@ -178,17 +178,19 @@
 	}
 
 	/*
-	 * Give us at least 4KB of breathing room in case the device tree needs
-	 * to be expanded later. Round up to the nearest EFI page boundary.
+	 * Give us at least 12 KiB of breathing room in case the device tree
+	 * needs to be expanded later.
 	 */
-	fdt = map_sysmem(*fdt_addrp, 0);
-	fdt_size = fdt_totalsize(fdt);
-	fdt_size += 4096 * 3;
-	fdt_size = ALIGN(fdt_size + EFI_PAGE_SIZE - 1, EFI_PAGE_SIZE);
-	fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
+	fdt = *fdtp;
+	fdt_pages = efi_size_in_pages(fdt_totalsize(fdt) + 0x3000);
+	fdt_size = fdt_pages << EFI_PAGE_SHIFT;
 
-	/* Safe fdt location is at 127MB */
-	new_fdt_addr = fdt_ram_start + (127 * 1024 * 1024) + fdt_size;
+	/*
+	 * Safe fdt location is at 127 MiB.
+	 * On the sandbox convert from the sandbox address space.
+	 */
+	new_fdt_addr = (uintptr_t)map_sysmem(fdt_ram_start + 0x7f00000 +
+					     fdt_size, 0);
 	ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
 				 EFI_RUNTIME_SERVICES_DATA, fdt_pages,
 				 &new_fdt_addr);
@@ -203,13 +205,11 @@
 			goto done;
 		}
 	}
-
-	new_fdt = map_sysmem(new_fdt_addr, fdt_size);
+	new_fdt = (void *)(uintptr_t)new_fdt_addr;
 	memcpy(new_fdt, fdt, fdt_totalsize(fdt));
 	fdt_set_totalsize(new_fdt, fdt_size);
 
-	*fdt_addrp = new_fdt_addr;
-	*fdt_sizep = fdt_size;
+	*fdtp = (void *)(uintptr_t)new_fdt_addr;
 done:
 	return ret;
 }
@@ -277,7 +277,11 @@
 		if (fdt_get_mem_rsv(fdt, i, &addr, &size) != 0)
 			continue;
 
-		pages = ALIGN(size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT;
+		/* Convert from sandbox address space. */
+		addr = (uintptr_t)map_sysmem(addr, 0);
+
+		pages = efi_size_in_pages(size + (addr & EFI_PAGE_MASK));
+		addr &= ~EFI_PAGE_MASK;
 		if (!efi_add_memory_map(addr, pages, EFI_RESERVED_MEMORY_TYPE,
 					false))
 			printf("FDT memrsv map %d: Failed to add to map\n", i);
@@ -287,7 +291,6 @@
 static efi_status_t efi_install_fdt(ulong fdt_addr)
 {
 	bootm_headers_t img = { 0 };
-	ulong fdt_pages, fdt_size, fdt_start;
 	efi_status_t ret;
 	void *fdt;
 
@@ -297,37 +300,61 @@
 		return EFI_INVALID_PARAMETER;
 	}
 
+	/* Create memory reservation as indicated by the device tree */
+	efi_carve_out_dt_rsv(fdt);
+
 	/* Prepare fdt for payload */
-	ret = copy_fdt(&fdt_addr, &fdt_size);
+	ret = copy_fdt(&fdt);
 	if (ret)
 		return ret;
 
-	unmap_sysmem(fdt);
-	fdt = map_sysmem(fdt_addr, 0);
-	fdt_size = fdt_totalsize(fdt);
 	if (image_setup_libfdt(&img, fdt, 0, NULL)) {
 		printf("ERROR: failed to process device tree\n");
 		return EFI_LOAD_ERROR;
 	}
 
-	efi_carve_out_dt_rsv(fdt);
-
 	/* Link to it in the efi tables */
 	ret = efi_install_configuration_table(&efi_guid_fdt, fdt);
 	if (ret != EFI_SUCCESS)
 		return EFI_OUT_OF_RESOURCES;
 
-	/* And reserve the space in the memory map */
-	fdt_start = fdt_addr;
-	fdt_pages = fdt_size >> EFI_PAGE_SHIFT;
+	return ret;
+}
 
-	ret = efi_add_memory_map(fdt_start, fdt_pages,
-				 EFI_BOOT_SERVICES_DATA, true);
+static efi_status_t bootefi_run_prepare(const char *load_options_path,
+		struct efi_device_path *device_path,
+		struct efi_device_path *image_path,
+		struct efi_loaded_image_obj **image_objp,
+		struct efi_loaded_image **loaded_image_infop)
+{
+	efi_status_t ret;
 
-	return ret;
+	ret = efi_setup_loaded_image(device_path, image_path, image_objp,
+				     loaded_image_infop);
+	if (ret != EFI_SUCCESS)
+		return ret;
+
+	/* Transfer environment variable as load options */
+	set_load_options(*loaded_image_infop, load_options_path);
+
+	return 0;
 }
 
 /**
+ * bootefi_run_finish() - finish up after running an EFI test
+ *
+ * @loaded_image_info: Pointer to a struct which holds the loaded image info
+ * @image_objj: Pointer to a struct which holds the loaded image object
+ */
+static void bootefi_run_finish(struct efi_loaded_image_obj *image_obj,
+			       struct efi_loaded_image *loaded_image_info)
+{
+	efi_restore_gd();
+	free(loaded_image_info->load_options);
+	efi_delete_handle(&image_obj->header);
+}
+
+/**
  * do_bootefi_exec() - execute EFI binary
  *
  * @efi:		address of the binary
@@ -345,7 +372,7 @@
 	efi_handle_t mem_handle = NULL;
 	struct efi_device_path *memdp = NULL;
 	efi_status_t ret;
-	struct efi_loaded_image_obj *image_handle = NULL;
+	struct efi_loaded_image_obj *image_obj = NULL;
 	struct efi_loaded_image *loaded_image_info = NULL;
 
 	EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
@@ -354,7 +381,7 @@
 	/*
 	 * Special case for efi payload not loaded from disk, such as
 	 * 'bootefi hello' or for example payload loaded directly into
-	 * memory via jtag, etc:
+	 * memory via JTAG, etc:
 	 */
 	if (!device_path && !image_path) {
 		printf("WARNING: using memory device/image path, this may confuse some payloads!\n");
@@ -367,27 +394,25 @@
 		 */
 		ret = efi_create_handle(&mem_handle);
 		if (ret != EFI_SUCCESS)
-			goto exit;
+			return ret; /* TODO: leaks device_path */
 		ret = efi_add_protocol(mem_handle, &efi_guid_device_path,
 				       device_path);
 		if (ret != EFI_SUCCESS)
-			goto exit;
+			goto err_add_protocol;
 	} else {
 		assert(device_path && image_path);
 	}
 
-	ret = efi_setup_loaded_image(device_path, image_path, &image_handle,
-				     &loaded_image_info);
-	if (ret != EFI_SUCCESS)
-		goto exit;
+	ret = bootefi_run_prepare("bootargs", device_path, image_path,
+				  &image_obj, &loaded_image_info);
+	if (ret)
+		goto err_prepare;
 
-	/* Transfer environment variable bootargs as load options */
-	set_load_options(loaded_image_info, "bootargs");
 	/* Load the EFI payload */
-	entry = efi_load_pe(image_handle, efi, loaded_image_info);
+	entry = efi_load_pe(image_obj, efi, loaded_image_info);
 	if (!entry) {
 		ret = EFI_LOAD_ERROR;
-		goto exit;
+		goto err_prepare;
 	}
 
 	if (memdp) {
@@ -405,9 +430,9 @@
 	/* Call our payload! */
 	debug("%s:%d Jumping to 0x%lx\n", __func__, __LINE__, (long)entry);
 
-	if (setjmp(&image_handle->exit_jmp)) {
-		ret = image_handle->exit_status;
-		goto exit;
+	if (setjmp(&image_obj->exit_jmp)) {
+		ret = image_obj->exit_status;
+		goto err_prepare;
 	}
 
 #ifdef CONFIG_ARM64
@@ -418,7 +443,7 @@
 
 		/* Move into EL2 and keep running there */
 		armv8_switch_to_el2((ulong)entry,
-				    (ulong)image_handle,
+				    (ulong)&image_obj->header,
 				    (ulong)&systab, 0, (ulong)efi_run_in_el2,
 				    ES_TO_AARCH64);
 
@@ -435,7 +460,7 @@
 		secure_ram_addr(_do_nonsec_entry)(
 					efi_run_in_hyp,
 					(uintptr_t)entry,
-					(uintptr_t)image_handle,
+					(uintptr_t)&image_obj->header,
 					(uintptr_t)&systab);
 
 		/* Should never reach here, efi exits with longjmp */
@@ -443,18 +468,59 @@
 	}
 #endif
 
-	ret = efi_do_enter(image_handle, &systab, entry);
+	ret = efi_do_enter(&image_obj->header, &systab, entry);
 
-exit:
+err_prepare:
 	/* image has returned, loaded-image obj goes *poof*: */
-	if (image_handle)
-		efi_delete_handle(&image_handle->parent);
+	bootefi_run_finish(image_obj, loaded_image_info);
+
+err_add_protocol:
 	if (mem_handle)
 		efi_delete_handle(mem_handle);
 
 	return ret;
 }
 
+#ifdef CONFIG_CMD_BOOTEFI_SELFTEST
+/**
+ * bootefi_test_prepare() - prepare to run an EFI test
+ *
+ * This sets things up so we can call EFI functions. This involves preparing
+ * the 'gd' pointer and setting up the load ed image data structures.
+ *
+ * @image_objp: loaded_image_infop: Pointer to a struct which will hold the
+ *    loaded image object. This struct will be inited by this function before
+ *    use.
+ * @loaded_image_infop: Pointer to a struct which will hold the loaded image
+ *    info. This struct will be inited by this function before use.
+ * @path: File path to the test being run (often just the test name with a
+ *    backslash before it
+ * @test_func: Address of the test function that is being run
+ * @load_options_path: U-Boot environment variable to use as load options
+ * @return 0 if OK, -ve on error
+ */
+static efi_status_t bootefi_test_prepare
+		(struct efi_loaded_image_obj **image_objp,
+		struct efi_loaded_image **loaded_image_infop, const char *path,
+		ulong test_func, const char *load_options_path)
+{
+	/* Construct a dummy device path */
+	bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
+					      (uintptr_t)test_func,
+					      (uintptr_t)test_func);
+	if (!bootefi_device_path)
+		return EFI_OUT_OF_RESOURCES;
+	bootefi_image_path = efi_dp_from_file(NULL, 0, path);
+	if (!bootefi_image_path)
+		return EFI_OUT_OF_RESOURCES;
+
+	return bootefi_run_prepare(load_options_path, bootefi_device_path,
+				   bootefi_image_path, image_objp,
+				   loaded_image_infop);
+}
+
+#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */
+
 static int do_bootefi_bootmgr_exec(void)
 {
 	struct efi_device_path *device_path, *file_path;
@@ -527,29 +593,17 @@
 #endif
 #ifdef CONFIG_CMD_BOOTEFI_SELFTEST
 	if (!strcmp(argv[1], "selftest")) {
-		struct efi_loaded_image_obj *image_handle;
+		struct efi_loaded_image_obj *image_obj;
 		struct efi_loaded_image *loaded_image_info;
 
-		/* Construct a dummy device path. */
-		bootefi_device_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
-						      (uintptr_t)&efi_selftest,
-						      (uintptr_t)&efi_selftest);
-		bootefi_image_path = efi_dp_from_file(NULL, 0, "\\selftest");
-
-		r = efi_setup_loaded_image(bootefi_device_path,
-					   bootefi_image_path, &image_handle,
-					   &loaded_image_info);
-		if (r != EFI_SUCCESS)
+		if (bootefi_test_prepare(&image_obj, &loaded_image_info,
+					 "\\selftest", (uintptr_t)&efi_selftest,
+					 "efi_selftest"))
 			return CMD_RET_FAILURE;
 
-		efi_save_gd();
-		/* Transfer environment variable efi_selftest as load options */
-		set_load_options(loaded_image_info, "efi_selftest");
 		/* Execute the test */
-		r = efi_selftest(image_handle, &systab);
-		efi_restore_gd();
-		free(loaded_image_info->load_options);
-		efi_delete_handle(&image_handle->parent);
+		r = efi_selftest(&image_obj->header, &systab);
+		bootefi_run_finish(image_obj, loaded_image_info);
 		return r != EFI_SUCCESS;
 	} else
 #endif
@@ -608,45 +662,19 @@
 
 void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
 {
-	char filename[32] = { 0 }; /* dp->str is u16[32] long */
-	char *s;
+	struct efi_device_path *device, *image;
+	efi_status_t ret;
 
 	/* efi_set_bootdev is typically called repeatedly, recover memory */
 	efi_free_pool(bootefi_device_path);
 	efi_free_pool(bootefi_image_path);
-	/* If blk_get_device_part_str fails, avoid duplicate free. */
-	bootefi_device_path = NULL;
-	bootefi_image_path = NULL;
-
-	if (strcmp(dev, "Net")) {
-		struct blk_desc *desc;
-		disk_partition_t fs_partition;
-		int part;
 
-		part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
-					       1);
-		if (part < 0)
-			return;
-
-		bootefi_device_path = efi_dp_from_part(desc, part);
-	} else {
-#ifdef CONFIG_NET
-		bootefi_device_path = efi_dp_from_eth();
-#endif
-	}
-
-	if (!path)
-		return;
-
-	if (strcmp(dev, "Net")) {
-		/* Add leading / to fs paths, because they're absolute */
-		snprintf(filename, sizeof(filename), "/%s", path);
+	ret = efi_dp_from_name(dev, devnr, path, &device, &image);
+	if (ret == EFI_SUCCESS) {
+		bootefi_device_path = device;
+		bootefi_image_path = image;
 	} else {
-		snprintf(filename, sizeof(filename), "%s", path);
+		bootefi_device_path = NULL;
+		bootefi_image_path = NULL;
 	}
-	/* DOS style file path: */
-	s = filename;
-	while ((s = strchr(s, '/')))
-		*s++ = '\\';
-	bootefi_image_path = efi_dp_from_file(NULL, 0, filename);
 }
diff --git a/cmd/eeprom.c b/cmd/eeprom.c
index 4052cf4..e88cb13 100644
--- a/cmd/eeprom.c
+++ b/cmd/eeprom.c
@@ -137,6 +137,23 @@
 		spi_write(addr, alen, buffer, len);
 #else	/* I2C */
 
+#if defined(CONFIG_DM_I2C) && defined(CONFIG_SYS_I2C_EEPROM_BUS)
+	struct udevice *dev;
+
+	ret = i2c_get_chip_for_busnum(CONFIG_SYS_I2C_EEPROM_BUS, addr[0],
+				      alen - 1, &dev);
+	if (ret) {
+		printf("%s: Cannot find udev for a bus %d\n", __func__,
+		       CONFIG_SYS_I2C_EEPROM_BUS);
+		return CMD_RET_FAILURE;
+	}
+
+	if (read)
+		ret = dm_i2c_read(dev, offset, buffer, len);
+	else
+		ret = dm_i2c_write(dev, offset, buffer, len);
+
+#else /* Non DM I2C support - will be removed */
 #if defined(CONFIG_SYS_I2C_EEPROM_BUS)
 	i2c_set_bus_num(CONFIG_SYS_I2C_EEPROM_BUS);
 #endif
@@ -145,10 +162,11 @@
 		ret = i2c_read(addr[0], offset, alen - 1, buffer, len);
 	else
 		ret = i2c_write(addr[0], offset, alen - 1, buffer, len);
-
-	if (ret)
-		ret = 1;
 #endif
+#endif /* CONFIG_DM_I2C && CONFIG_SYS_I2C_EEPROM_BUS */
+	if (ret)
+		ret = CMD_RET_FAILURE;
+
 	return ret;
 }
 
diff --git a/common/board_r.c b/common/board_r.c
index c55e33e..21d3b3c 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -453,7 +453,8 @@
 	else
 		set_default_env(NULL, 0);
 #ifdef CONFIG_OF_CONTROL
-	env_set_addr("fdtcontroladdr", gd->fdt_blob);
+	env_set_hex("fdtcontroladdr",
+		    (unsigned long)map_to_sysmem(gd->fdt_blob));
 #endif
 
 	/* Initialize from environment */
@@ -743,7 +744,7 @@
 	/* initialize higher level parts of CPU like time base and timers */
 	cpu_init_r,
 #endif
-#ifdef CONFIG_PPC
+#if defined(CONFIG_PPC) && !defined(CONFIG_DM_SPI)
 	initr_spi,
 #endif
 #ifdef CONFIG_CMD_NAND
diff --git a/common/fdt_support.c b/common/fdt_support.c
index e6daa67..3440e42 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -7,6 +7,7 @@
  */
 
 #include <common.h>
+#include <mapmem.h>
 #include <stdio_dev.h>
 #include <linux/ctype.h>
 #include <linux/types.h>
@@ -633,7 +634,7 @@
 	fdt_set_totalsize(blob, actualsize);
 
 	/* Add the new reservation */
-	ret = fdt_add_mem_rsv(blob, (uintptr_t)blob, actualsize);
+	ret = fdt_add_mem_rsv(blob, map_to_sysmem(blob), actualsize);
 	if (ret < 0)
 		return ret;
 
diff --git a/common/image-fit.c b/common/image-fit.c
index 8d39a24..ac901e1 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -165,6 +165,7 @@
 	uint8_t *value;
 	int value_len;
 	char *algo;
+	const char *padding;
 	int required;
 	int ret, i;
 
@@ -184,6 +185,10 @@
 		printf(" (required)");
 	printf("\n");
 
+	padding = fdt_getprop(fit, noffset, "padding", NULL);
+	if (padding)
+		printf("%s  %s padding: %s\n", p, type, padding);
+
 	ret = fit_image_hash_get_value(fit, noffset, &value,
 				       &value_len);
 	printf("%s  %s value:   ", p, type);
diff --git a/common/image-sig.c b/common/image-sig.c
index 5d860e1..4f6b4ec 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -71,6 +71,19 @@
 
 };
 
+struct padding_algo padding_algos[] = {
+	{
+		.name = "pkcs-1.5",
+		.verify = padding_pkcs_15_verify,
+	},
+#ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
+	{
+		.name = "pss",
+		.verify = padding_pss_verify,
+	}
+#endif /* CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT */
+};
+
 struct checksum_algo *image_get_checksum_algo(const char *full_name)
 {
 	int i;
@@ -106,6 +119,21 @@
 	return NULL;
 }
 
+struct padding_algo *image_get_padding_algo(const char *name)
+{
+	int i;
+
+	if (!name)
+		return NULL;
+
+	for (i = 0; i < ARRAY_SIZE(padding_algos); i++) {
+		if (!strcmp(padding_algos[i].name, name))
+			return &padding_algos[i];
+	}
+
+	return NULL;
+}
+
 /**
  * fit_region_make_list() - Make a list of image regions
  *
@@ -155,6 +183,7 @@
 		char **err_msgp)
 {
 	char *algo_name;
+	const char *padding_name;
 
 	if (fdt_totalsize(fit) > CONFIG_FIT_SIGNATURE_MAX_SIZE) {
 		*err_msgp = "Total size too large";
@@ -165,6 +194,11 @@
 		*err_msgp = "Can't get hash algo property";
 		return -1;
 	}
+
+	padding_name = fdt_getprop(fit, noffset, "padding", NULL);
+	if (!padding_name)
+		padding_name = RSA_DEFAULT_PADDING_NAME;
+
 	memset(info, '\0', sizeof(*info));
 	info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
 	info->fit = (void *)fit;
@@ -172,6 +206,7 @@
 	info->name = algo_name;
 	info->checksum = image_get_checksum_algo(algo_name);
 	info->crypto = image_get_crypto_algo(algo_name);
+	info->padding = image_get_padding_algo(padding_name);
 	info->fdt_blob = gd_fdt_blob();
 	info->required_keynode = required_keynode;
 	printf("%s:%s", algo_name, info->keyname);
diff --git a/configs/MCR3000_defconfig b/configs/MCR3000_defconfig
index 29a60e3..33c6073 100644
--- a/configs/MCR3000_defconfig
+++ b/configs/MCR3000_defconfig
@@ -42,6 +42,7 @@
 CONFIG_USE_BOOTCOMMAND=y
 CONFIG_BOOTCOMMAND="run flashboot"
 CONFIG_MISC_INIT_R=y
+CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_HUSH_PARSER=y
 # CONFIG_AUTO_COMPLETE is not set
 CONFIG_SYS_PROMPT="S3K> "
@@ -73,3 +74,9 @@
 CONFIG_SHA256=y
 CONFIG_LZMA=y
 CONFIG_OF_LIBFDT=y
+CONFIG_DM=y
+CONFIG_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="mcr3000"
+CONFIG_WDT=y
+CONFIG_WDT_MPC8xx=y
+CONFIG_DM_SERIAL=y
diff --git a/configs/am335x_baltos_defconfig b/configs/am335x_baltos_defconfig
index a61b13b..05d41ae 100644
--- a/configs/am335x_baltos_defconfig
+++ b/configs/am335x_baltos_defconfig
@@ -1,6 +1,5 @@
 CONFIG_ARM=y
 CONFIG_ARCH_OMAP2PLUS=y
-CONFIG_SPL_GPIO_SUPPORT=y
 CONFIG_SPL_LIBCOMMON_SUPPORT=y
 CONFIG_SPL_LIBGENERIC_SUPPORT=y
 CONFIG_AM33XX=y
@@ -39,17 +38,26 @@
 CONFIG_MTDIDS_DEFAULT="nand0=omap2-nand.0"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=omap2-nand.0:128k(SPL),128k(SPL.backup1),128k(SPL.backup2),128k(SPL.backup3),1920k(u-boot),-(UBI)"
 CONFIG_CMD_UBI=y
+CONFIG_OF_CONTROL=y
+CONFIG_DEFAULT_DEVICE_TREE="am335x-baltos"
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
 CONFIG_BOOTCOUNT_LIMIT=y
 CONFIG_SYS_OMAP24_I2C_SPEED=1000
+CONFIG_DM_MMC=y
 CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_OMAP_HS_ADMA=y
 CONFIG_NAND=y
+CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y
+CONFIG_SYS_NAND_U_BOOT_OFFS=0x00080000
 CONFIG_PHY_ADDR_ENABLE=y
-CONFIG_DRIVER_TI_CPSW=y
+CONFIG_PHY_ATHEROS=y
+CONFIG_PHY_SMSC=y
 CONFIG_MII=y
+CONFIG_DRIVER_TI_CPSW=y
 CONFIG_SPI=y
 CONFIG_OMAP3_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_MUSB_DSPS=y
@@ -59,7 +67,7 @@
 CONFIG_USB_GADGET_VENDOR_NUM=0x0403
 CONFIG_USB_GADGET_PRODUCT_NUM=0xbd00
 CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_FUNCTION_MASS_STORAGE=y
 CONFIG_USB_ETHER=y
 CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00"
 CONFIG_FAT_WRITE=y
-CONFIG_OF_LIBFDT=y
diff --git a/configs/bk4r1_defconfig b/configs/bk4r1_defconfig
index cf1fd0b..9e31b4a 100644
--- a/configs/bk4r1_defconfig
+++ b/configs/bk4r1_defconfig
@@ -40,6 +40,7 @@
 CONFIG_PHYLIB=y
 CONFIG_PHY_MICREL=y
 CONFIG_MII=y
+CONFIG_RTC_M41T62=y
 CONFIG_DM_SERIAL=y
 CONFIG_FSL_LPUART=y
 CONFIG_SPI=y
diff --git a/configs/m53menlo_defconfig b/configs/m53menlo_defconfig
index 795f8a3..dd7aed3 100644
--- a/configs/m53menlo_defconfig
+++ b/configs/m53menlo_defconfig
@@ -49,6 +49,7 @@
 CONFIG_NAND_MXC=y
 CONFIG_PHYLIB=y
 CONFIG_PHY_MICREL=y
+CONFIG_RTC_M41T62=y
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_HOST_ETHER=y
diff --git a/configs/pcm052_defconfig b/configs/pcm052_defconfig
index 0c8e31a..e207df5 100644
--- a/configs/pcm052_defconfig
+++ b/configs/pcm052_defconfig
@@ -35,5 +35,6 @@
 CONFIG_PHYLIB=y
 CONFIG_PHY_MICREL=y
 CONFIG_MII=y
+CONFIG_RTC_M41T62=y
 CONFIG_DM_SERIAL=y
 CONFIG_FSL_LPUART=y
diff --git a/configs/r8a7795_salvator-x_defconfig b/configs/r8a7795_salvator-x_defconfig
index 40712a4..149d627 100644
--- a/configs/r8a7795_salvator-x_defconfig
+++ b/configs/r8a7795_salvator-x_defconfig
@@ -41,6 +41,7 @@
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_MMC_UHS_SUPPORT=y
 CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_RENESAS_SDHI=y
 CONFIG_PHY_MICREL=y
 CONFIG_PHY_MICREL_KSZ90X1=y
diff --git a/configs/r8a7795_ulcb_defconfig b/configs/r8a7795_ulcb_defconfig
index f1d150b..8d765e2 100644
--- a/configs/r8a7795_ulcb_defconfig
+++ b/configs/r8a7795_ulcb_defconfig
@@ -41,6 +41,7 @@
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_MMC_UHS_SUPPORT=y
 CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_RENESAS_SDHI=y
 CONFIG_PHY_MICREL=y
 CONFIG_PHY_MICREL_KSZ90X1=y
diff --git a/configs/r8a77965_salvator-x_defconfig b/configs/r8a77965_salvator-x_defconfig
index 72549e2..2d6b86f 100644
--- a/configs/r8a77965_salvator-x_defconfig
+++ b/configs/r8a77965_salvator-x_defconfig
@@ -42,6 +42,7 @@
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_MMC_UHS_SUPPORT=y
 CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_RENESAS_SDHI=y
 CONFIG_PHY_MICREL=y
 CONFIG_PHY_MICREL_KSZ90X1=y
diff --git a/configs/r8a7796_salvator-x_defconfig b/configs/r8a7796_salvator-x_defconfig
index 7c39268..3525045 100644
--- a/configs/r8a7796_salvator-x_defconfig
+++ b/configs/r8a7796_salvator-x_defconfig
@@ -42,6 +42,7 @@
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_MMC_UHS_SUPPORT=y
 CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_RENESAS_SDHI=y
 CONFIG_PHY_MICREL=y
 CONFIG_PHY_MICREL_KSZ90X1=y
diff --git a/configs/r8a7796_ulcb_defconfig b/configs/r8a7796_ulcb_defconfig
index ef5c944..b68bb7c 100644
--- a/configs/r8a7796_ulcb_defconfig
+++ b/configs/r8a7796_ulcb_defconfig
@@ -42,6 +42,7 @@
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_MMC_UHS_SUPPORT=y
 CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_RENESAS_SDHI=y
 CONFIG_PHY_MICREL=y
 CONFIG_PHY_MICREL_KSZ90X1=y
diff --git a/configs/r8a77990_ebisu_defconfig b/configs/r8a77990_ebisu_defconfig
index 7363310..5a8fc04 100644
--- a/configs/r8a77990_ebisu_defconfig
+++ b/configs/r8a77990_ebisu_defconfig
@@ -42,6 +42,7 @@
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_MMC_UHS_SUPPORT=y
 CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_RENESAS_SDHI=y
 CONFIG_PHY_MICREL=y
 CONFIG_PHY_MICREL_KSZ90X1=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 5a744f4..1a76785 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -5,6 +5,7 @@
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_BOOTSTAGE=y
 CONFIG_BOOTSTAGE_REPORT=y
diff --git a/configs/vf610twr_defconfig b/configs/vf610twr_defconfig
index a928cd4..504eebb 100644
--- a/configs/vf610twr_defconfig
+++ b/configs/vf610twr_defconfig
@@ -41,4 +41,4 @@
 CONFIG_MII=y
 CONFIG_DM_SERIAL=y
 CONFIG_FSL_LPUART=y
-# CONFIG_EFI_UNICODE_CAPITALIZATION is not set
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/vf610twr_nand_defconfig b/configs/vf610twr_nand_defconfig
index 560776f..0a1e28e 100644
--- a/configs/vf610twr_nand_defconfig
+++ b/configs/vf610twr_nand_defconfig
@@ -41,4 +41,4 @@
 CONFIG_MII=y
 CONFIG_DM_SERIAL=y
 CONFIG_FSL_LPUART=y
-# CONFIG_EFI_UNICODE_CAPITALIZATION is not set
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/x600_defconfig b/configs/x600_defconfig
index c8f5f66..a96f54c 100644
--- a/configs/x600_defconfig
+++ b/configs/x600_defconfig
@@ -52,6 +52,7 @@
 CONFIG_PHY_MICREL_KSZ90X1=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_MII=y
+CONFIG_RTC_M41T62=y
 CONFIG_CONS_INDEX=0
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/doc/README.iscsi b/doc/README.iscsi
index faee636..3a12438 100644
--- a/doc/README.iscsi
+++ b/doc/README.iscsi
@@ -1,8 +1,6 @@
-iSCSI booting with U-Boot and iPXE
-==================================
+# iSCSI booting with U-Boot and iPXE
 
-Motivation
-----------
+## Motivation
 
 U-Boot has only a reduced set of supported network protocols. The focus for
 network booting has been on UDP based protocols. A TCP stack and HTTP support
@@ -41,8 +39,7 @@
 iPXE can be built as an EFI application (named snp.efi) which can be loaded and
 run by U-Boot.
 
-Boot sequence
--------------
+## Boot sequence
 
 U-Boot loads the EFI application iPXE snp.efi using the bootefi command. This
 application has network access via the simple network protocol offered by
@@ -106,19 +103,16 @@
                                                                       |        |
                                                                       | ~ ~ ~ ~|
 
-Security
---------
+## Security
 
 The iSCSI protocol is not encrypted. The traffic could be secured using IPsec
 but neither U-Boot nor iPXE does support this. So we should at least separate
 the iSCSI traffic from all other network traffic. This can be achieved using a
 virtual local area network (VLAN).
 
-Configuration
--------------
+## Configuration
 
-iPXE
-^^^^
+### iPXE
 
 For running iPXE on arm64 the bin-arm64-efi/snp.efi build target is needed::
 
@@ -157,9 +151,20 @@
     #define DOWNLOAD_PROTO_NFS      /* Network File System Protocol */
     #define DOWNLOAD_PROTO_FILE     /* Local file system access */
 
-Links
------
+### Open-iSCSI
+
+When the root file system is on an iSCSI drive you should disable pings and set
+the replacement timer to a high value [3]:
+
+    node.conn[0].timeo.noop_out_interval = 0
+    node.conn[0].timeo.noop_out_timeout = 0
+    node.session.timeo.replacement_timeout = 86400
+
+## Links
 
 * [1](https://ipxe.org) https://ipxe.org - iPXE open source boot firmware
 * [2](https://www.gnu.org/software/grub/) https://www.gnu.org/software/grub/ -
-  GNU GRUB (Grand Unified Bootloader)
+     GNU GRUB (Grand Unified Bootloader)
+* [3](https://github.com/open-iscsi/open-iscsi/blob/master/README)
+     https://github.com/open-iscsi/open-iscsi/blob/master/README -
+     Open-iSCSI README
diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt
index a765722..bfff6fd 100644
--- a/doc/uImage.FIT/signature.txt
+++ b/doc/uImage.FIT/signature.txt
@@ -106,6 +106,9 @@
 
 - comment: Additional information about the signer or image
 
+- padding: The padding algorithm, it may be pkcs-1.5 or pss,
+	if no value is provided we assume pkcs-1.5
+
 For config bindings (see Signed Configurations below), the following
 additional properties are optional:
 
diff --git a/drivers/clk/clk_meson.c b/drivers/clk/clk_meson.c
index 0df8b91..2cb53fb 100644
--- a/drivers/clk/clk_meson.c
+++ b/drivers/clk/clk_meson.c
@@ -11,6 +11,8 @@
 #include <clk-uclass.h>
 #include <div64.h>
 #include <dm.h>
+#include <regmap.h>
+#include <syscon.h>
 #include <dt-bindings/clock/gxbb-clkc.h>
 #include "clk_meson.h"
 
@@ -65,7 +67,7 @@
 #define XTAL_RATE 24000000
 
 struct meson_clk {
-	void __iomem *addr;
+	struct regmap *map;
 };
 
 static ulong meson_div_get_rate(struct clk *clk, unsigned long id);
@@ -217,8 +219,8 @@
 
 	debug("%s: really %sabling %ld\n", __func__, on ? "en" : "dis", id);
 
-	clrsetbits_le32(priv->addr + gate->reg,
-			BIT(gate->bit), on ? BIT(gate->bit) : 0);
+	regmap_update_bits(priv->map, gate->reg,
+			   BIT(gate->bit), on ? BIT(gate->bit) : 0);
 
 	/* Propagate to next gate(s) */
 	switch (id) {
@@ -269,7 +271,7 @@
 	unsigned int rate, parent_rate;
 	struct parm *parm;
 	int parent;
-	u32 reg;
+	uint reg;
 
 	switch (id) {
 	case CLKID_VPU_0_DIV:
@@ -292,7 +294,7 @@
 		return -ENOENT;
 	}
 
-	reg = readl(priv->addr + parm->reg_off);
+	regmap_read(priv->map, parm->reg_off, &reg);
 	reg = PARM_GET(parm->width, parm->shift, reg);
 
 	debug("%s: div of %ld is %d\n", __func__, id, reg + 1);
@@ -318,7 +320,6 @@
 	unsigned long parent_rate;
 	struct parm *parm;
 	int parent;
-	u32 reg;
 	int ret;
 
 	if (current_rate == rate)
@@ -383,9 +384,8 @@
 
 	debug("%s: setting div of %ld to %d\n", __func__, id, new_div);
 
-	reg = readl(priv->addr + parm->reg_off);
-	writel(PARM_SET(parm->width, parm->shift, reg, new_div - 1),
-	       priv->addr + parm->reg_off);
+	regmap_update_bits(priv->map, parm->reg_off, SETPMASK(parm->width, parm->shift),
+			   (new_div - 1) << parm->shift);
 
 	debug("%s: new rate of %ld is %ld\n",
 	      __func__, id, meson_div_get_rate(clk, id));
@@ -446,7 +446,7 @@
 	struct meson_clk *priv = dev_get_priv(clk->dev);
 	struct parm *parm;
 	int *parents;
-	u32 reg;
+	uint reg;
 
 	switch (id) {
 	case CLKID_VPU:
@@ -477,7 +477,7 @@
 		return -ENOENT;
 	}
 
-	reg = readl(priv->addr + parm->reg_off);
+	regmap_read(priv->map, parm->reg_off, &reg);
 	reg = PARM_GET(parm->width, parm->shift, reg);
 
 	debug("%s: parent of %ld is %d (%d)\n",
@@ -494,7 +494,6 @@
 	unsigned int new_index = -EINVAL;
 	struct parm *parm;
 	int *parents;
-	u32 reg;
 	int i;
 
 	if (IS_ERR_VALUE(cur_parent))
@@ -546,9 +545,8 @@
 
 	debug("%s: new index of %ld is %d\n", __func__, id, new_index);
 
-	reg = readl(priv->addr + parm->reg_off);
-	writel(PARM_SET(parm->width, parm->shift, reg, new_index),
-	       priv->addr + parm->reg_off);
+	regmap_update_bits(priv->map, parm->reg_off, SETPMASK(parm->width, parm->shift),
+			   new_index << parm->shift);
 
 	debug("%s: new parent of %ld is %ld\n",
 	      __func__, id, meson_mux_get_parent(clk, id));
@@ -570,7 +568,7 @@
 {
 	struct meson_clk *priv = dev_get_priv(clk->dev);
 	unsigned long parent_rate;
-	u32 reg;
+	uint reg;
 	int parents[] = {
 		-1,
 		-1,
@@ -583,7 +581,7 @@
 	};
 
 	/* mux */
-	reg = readl(priv->addr + HHI_MPEG_CLK_CNTL);
+	regmap_read(priv->map, HHI_MPEG_CLK_CNTL, &reg);
 	reg = (reg >> 12) & 7;
 
 	switch (reg) {
@@ -597,7 +595,7 @@
 	}
 
 	/* divider */
-	reg = readl(priv->addr + HHI_MPEG_CLK_CNTL);
+	regmap_read(priv->map, HHI_MPEG_CLK_CNTL, &reg);
 	reg = reg & ((1 << 7) - 1);
 
 	/* clk81 divider is zero based */
@@ -641,8 +639,9 @@
 {
 	struct meson_clk *priv = dev_get_priv(clk->dev);
 	struct parm *psdm, *pn2;
-	unsigned long reg, sdm, n2;
+	unsigned long sdm, n2;
 	unsigned long parent_rate;
+	uint reg;
 
 	switch (id) {
 	case CLKID_MPLL0:
@@ -665,10 +664,10 @@
 	if (IS_ERR_VALUE(parent_rate))
 		return parent_rate;
 
-	reg = readl(priv->addr + psdm->reg_off);
+	regmap_read(priv->map, psdm->reg_off, &reg);
 	sdm = PARM_GET(psdm->width, psdm->shift, reg);
 
-	reg = readl(priv->addr + pn2->reg_off);
+	regmap_read(priv->map, pn2->reg_off, &reg);
 	n2 = PARM_GET(pn2->width, pn2->shift, reg);
 
 	return mpll_rate_from_params(parent_rate, sdm, n2);
@@ -692,7 +691,7 @@
 	struct parm *pm, *pn, *pod;
 	unsigned long parent_rate_mhz = XTAL_RATE / 1000000;
 	u16 n, m, od;
-	u32 reg;
+	uint reg;
 
 	switch (id) {
 	case CLKID_FIXED_PLL:
@@ -709,13 +708,13 @@
 		return -ENOENT;
 	}
 
-	reg = readl(priv->addr + pn->reg_off);
+	regmap_read(priv->map, pn->reg_off, &reg);
 	n = PARM_GET(pn->width, pn->shift, reg);
 
-	reg = readl(priv->addr + pm->reg_off);
+	regmap_read(priv->map, pm->reg_off, &reg);
 	m = PARM_GET(pm->width, pm->shift, reg);
 
-	reg = readl(priv->addr + pod->reg_off);
+	regmap_read(priv->map, pod->reg_off, &reg);
 	od = PARM_GET(pod->width, pod->shift, reg);
 
 	return ((parent_rate_mhz * m / n) >> od) * 1000000;
@@ -876,8 +875,8 @@
 	if (IS_ERR_VALUE(ret))
 		return ret;
 
-	printf("clock %lu has new rate %lu\n", clk->id,
-	       meson_clk_get_rate_by_id(clk, clk->id));
+	debug("clock %lu has new rate %lu\n", clk->id,
+	      meson_clk_get_rate_by_id(clk, clk->id));
 
 	return 0;
 }
@@ -886,9 +885,11 @@
 {
 	struct meson_clk *priv = dev_get_priv(dev);
 
-	priv->addr = dev_read_addr_ptr(dev);
+	priv->map = syscon_node_to_regmap(dev_get_parent(dev)->node);
+	if (IS_ERR(priv->map))
+		return PTR_ERR(priv->map);
 
-	debug("meson-clk: probed at addr %p\n", priv->addr);
+	debug("meson-clk: probed\n");
 
 	return 0;
 }
diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c
index 99698b1..0529fc8 100644
--- a/drivers/clk/renesas/clk-rcar-gen3.c
+++ b/drivers/clk/renesas/clk-rcar-gen3.c
@@ -107,7 +107,7 @@
 	return renesas_clk_get_parent(clk, info, parent);
 }
 
-static int gen3_clk_setup_sdif_div(struct clk *clk)
+static int gen3_clk_setup_sdif_div(struct clk *clk, ulong rate)
 {
 	struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
 	struct cpg_mssr_info *info = priv->info;
@@ -133,7 +133,7 @@
 
 	debug("%s[%i] SDIF offset=%x\n", __func__, __LINE__, core->offset);
 
-	writel(1, priv->base + core->offset);
+	writel((rate == 400000000) ? 0x4 : 0x1, priv->base + core->offset);
 
 	return 0;
 }
@@ -141,10 +141,6 @@
 static int gen3_clk_enable(struct clk *clk)
 {
 	struct gen3_clk_priv *priv = dev_get_priv(clk->dev);
-	int ret = gen3_clk_setup_sdif_div(clk);
-
-	if (ret)
-		return ret;
 
 	return renesas_clk_endisable(clk, priv->base, true);
 }
@@ -328,7 +324,7 @@
 static ulong gen3_clk_set_rate(struct clk *clk, ulong rate)
 {
 	/* Force correct SD-IF divider configuration if applicable */
-	gen3_clk_setup_sdif_div(clk);
+	gen3_clk_setup_sdif_div(clk, rate);
 	return gen3_clk_get_rate64(clk);
 }
 
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 2cb35f3..c8c47ac 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -9,31 +9,38 @@
 #include <common.h>
 #include <dm.h>
 #include <dm/lists.h>
+#include <efi_loader.h>
 #include <linux/libfdt.h>
 #include <linux/arm-smccc.h>
 #include <linux/errno.h>
 #include <linux/printk.h>
 #include <linux/psci.h>
 
-psci_fn *invoke_psci_fn;
+#define DRIVER_NAME "psci"
 
-static unsigned long __invoke_psci_fn_hvc(unsigned long function_id,
-			unsigned long arg0, unsigned long arg1,
-			unsigned long arg2)
-{
-	struct arm_smccc_res res;
+#define PSCI_METHOD_HVC 1
+#define PSCI_METHOD_SMC 2
 
-	arm_smccc_hvc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
-	return res.a0;
-}
+int __efi_runtime_data psci_method;
 
-static unsigned long __invoke_psci_fn_smc(unsigned long function_id,
-			unsigned long arg0, unsigned long arg1,
-			unsigned long arg2)
+unsigned long __efi_runtime invoke_psci_fn
+		(unsigned long function_id, unsigned long arg0,
+		 unsigned long arg1, unsigned long arg2)
 {
 	struct arm_smccc_res res;
 
-	arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+	/*
+	 * In the __efi_runtime we need to avoid the switch statement. In some
+	 * cases the compiler creates lookup tables to implement switch. These
+	 * tables are not correctly relocated when SetVirtualAddressMap is
+	 * called.
+	 */
+	if (psci_method == PSCI_METHOD_SMC)
+		arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+	else if (psci_method == PSCI_METHOD_HVC)
+		arm_smccc_hvc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
+	else
+		res.a0 = PSCI_RET_DISABLED;
 	return res.a0;
 }
 
@@ -67,9 +74,9 @@
 	}
 
 	if (!strcmp("hvc", method)) {
-		invoke_psci_fn = __invoke_psci_fn_hvc;
+		psci_method = PSCI_METHOD_HVC;
 	} else if (!strcmp("smc", method)) {
-		invoke_psci_fn = __invoke_psci_fn_smc;
+		psci_method = PSCI_METHOD_SMC;
 	} else {
 		pr_warn("invalid \"method\" property: %s\n", method);
 		return -EINVAL;
@@ -77,6 +84,67 @@
 
 	return 0;
 }
+
+/**
+ * void do_psci_probe() - probe PSCI firmware driver
+ *
+ * Ensure that psci_method is initialized.
+ */
+static void __maybe_unused do_psci_probe(void)
+{
+	struct udevice *dev;
+
+	uclass_get_device_by_name(UCLASS_FIRMWARE, DRIVER_NAME, &dev);
+}
+
+#if IS_ENABLED(CONFIG_EFI_LOADER) && IS_ENABLED(CONFIG_PSCI_RESET)
+efi_status_t efi_reset_system_init(void)
+{
+	do_psci_probe();
+	return EFI_SUCCESS;
+}
+
+void __efi_runtime EFIAPI efi_reset_system(enum efi_reset_type reset_type,
+					   efi_status_t reset_status,
+					   unsigned long data_size,
+					   void *reset_data)
+{
+	if (reset_type == EFI_RESET_COLD ||
+	    reset_type == EFI_RESET_WARM ||
+	    reset_type == EFI_RESET_PLATFORM_SPECIFIC) {
+		invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
+	} else if (reset_type == EFI_RESET_SHUTDOWN) {
+		invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
+	}
+	while (1)
+		;
+}
+#endif /* IS_ENABLED(CONFIG_EFI_LOADER) && IS_ENABLED(CONFIG_PSCI_RESET) */
+
+#ifdef CONFIG_PSCI_RESET
+void reset_misc(void)
+{
+	do_psci_probe();
+	invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
+}
+#endif /* CONFIG_PSCI_RESET */
+
+#ifdef CONFIG_CMD_POWEROFF
+int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	do_psci_probe();
+
+	puts("poweroff ...\n");
+	udelay(50000); /* wait 50 ms */
+
+	disable_interrupts();
+	invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
+	enable_interrupts();
+
+	log_err("Power off not supported on this platform\n");
+	return CMD_RET_FAILURE;
+}
+#endif
 
 static const struct udevice_id psci_of_match[] = {
 	{ .compatible = "arm,psci" },
@@ -86,7 +154,7 @@
 };
 
 U_BOOT_DRIVER(psci) = {
-	.name = "psci",
+	.name = DRIVER_NAME,
 	.id = UCLASS_FIRMWARE,
 	.of_match = psci_of_match,
 	.bind = psci_bind,
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index f73f072..76225b7 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -166,6 +166,10 @@
 		cfg->host_caps |= MMC_CAP(MMC_HS_200);
 	if (dev_read_bool(dev, "mmc-hs200-1_2v"))
 		cfg->host_caps |= MMC_CAP(MMC_HS_200);
+	if (dev_read_bool(dev, "mmc-hs400-1_8v"))
+		cfg->host_caps |= MMC_CAP(MMC_HS_400);
+	if (dev_read_bool(dev, "mmc-hs400-1_2v"))
+		cfg->host_caps |= MMC_CAP(MMC_HS_400);
 
 	return 0;
 }
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index e7f96f8..733b6d6 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -17,7 +17,9 @@
 
 #include "tmio-common.h"
 
-#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
 
 /* SCC registers */
 #define RENESAS_SDHI_SCC_DTCNTL			0x800
@@ -107,6 +109,56 @@
 	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL);
 }
 
+static int renesas_sdhi_hs400(struct udevice *dev)
+{
+	struct tmio_sd_priv *priv = dev_get_priv(dev);
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	bool hs400 = (mmc->selected_mode == MMC_HS_400);
+	int ret, taps = hs400 ? priv->nrtaps : 8;
+	u32 reg;
+
+	if (taps == 4)	/* HS400 on 4tap SoC needs different clock */
+		ret = clk_set_rate(&priv->clk, 400000000);
+	else
+		ret = clk_set_rate(&priv->clk, 200000000);
+	if (ret < 0)
+		return ret;
+
+	tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_RVSREQ);
+
+	reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_TMPPORT2);
+	if (hs400) {
+		reg |= RENESAS_SDHI_SCC_TMPPORT2_HS400EN |
+		       RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL;
+	} else {
+		reg &= ~(RENESAS_SDHI_SCC_TMPPORT2_HS400EN |
+		       RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL);
+	}
+
+	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_TMPPORT2);
+
+	tmio_sd_writel(priv, (taps << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) |
+			     RENESAS_SDHI_SCC_DTCNTL_TAPEN,
+			     RENESAS_SDHI_SCC_DTCNTL);
+
+	if (taps == 4) {
+		tmio_sd_writel(priv, priv->tap_set >> 1,
+			       RENESAS_SDHI_SCC_TAPSET);
+	} else {
+		tmio_sd_writel(priv, priv->tap_set, RENESAS_SDHI_SCC_TAPSET);
+	}
+
+	reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_CKSEL);
+	reg |= RENESAS_SDHI_SCC_CKSEL_DTSEL;
+	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_CKSEL);
+
+	reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL);
+	reg |= RENESAS_SDHI_SCC_RVSCNTL_RVSEN;
+	tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL);
+
+	return 0;
+}
+
 static void renesas_sdhi_prepare_tuning(struct tmio_sd_priv *priv,
 				       unsigned long tap)
 {
@@ -125,7 +177,6 @@
 				     unsigned int smpcmp)
 {
 	unsigned long tap_cnt;  /* counter of tuning success */
-	unsigned long tap_set;  /* tap position */
 	unsigned long tap_start;/* start position of tuning success */
 	unsigned long tap_end;  /* end position of tuning success */
 	unsigned long ntap;     /* temporary counter of tuning success */
@@ -209,12 +260,12 @@
 		select = true;
 
 	if (select)
-		tap_set = ((tap_start + tap_end) / 2) % tap_num;
+		priv->tap_set = ((tap_start + tap_end) / 2) % tap_num;
 	else
 		return -EIO;
 
 	/* Set SCC */
-	tmio_sd_writel(priv, tap_set, RENESAS_SDHI_SCC_TAPSET);
+	tmio_sd_writel(priv, priv->tap_set, RENESAS_SDHI_SCC_TAPSET);
 
 	/* Enable auto re-tuning */
 	reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL);
@@ -240,6 +291,7 @@
 
 	/* clock tuning is not needed for upto 52MHz */
 	if (!((mmc->selected_mode == MMC_HS_200) ||
+	      (mmc->selected_mode == MMC_HS_400) ||
 	      (mmc->selected_mode == UHS_SDR104) ||
 	      (mmc->selected_mode == UHS_SDR50)))
 		return 0;
@@ -287,19 +339,42 @@
 
 	return ret;
 }
+#else
+static int renesas_sdhi_hs400(struct udevice *dev)
+{
+	return 0;
+}
 #endif
 
 static int renesas_sdhi_set_ios(struct udevice *dev)
 {
-	int ret = tmio_sd_set_ios(dev);
+	struct tmio_sd_priv *priv = dev_get_priv(dev);
+	u32 tmp;
+	int ret;
 
-	mdelay(10);
+	/* Stop the clock before changing its rate to avoid a glitch signal */
+	tmp = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
+	tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+	tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
 
-#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
-	struct tmio_sd_priv *priv = dev_get_priv(dev);
+	ret = renesas_sdhi_hs400(dev);
+	if (ret)
+		return ret;
+
+	ret = tmio_sd_set_ios(dev);
+
+	mdelay(10);
 
-	if (priv->caps & TMIO_SD_CAP_RCAR_UHS)
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+	struct mmc *mmc = mmc_get_mmc_dev(dev);
+	if ((priv->caps & TMIO_SD_CAP_RCAR_UHS) &&
+	    (mmc->selected_mode != UHS_SDR104) &&
+	    (mmc->selected_mode != MMC_HS_200) &&
+	    (mmc->selected_mode != MMC_HS_400)) {
 		renesas_sdhi_reset_tuning(priv);
+	}
 #endif
 
 	return ret;
@@ -331,7 +406,9 @@
 	.send_cmd = tmio_sd_send_cmd,
 	.set_ios = renesas_sdhi_set_ios,
 	.get_cd = tmio_sd_get_cd,
-#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
 	.execute_tuning = renesas_sdhi_execute_tuning,
 #endif
 #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
@@ -358,15 +435,45 @@
 	{ /* sentinel */ }
 };
 
+static ulong renesas_sdhi_clk_get_rate(struct tmio_sd_priv *priv)
+{
+	return clk_get_rate(&priv->clk);
+}
+
+static void renesas_sdhi_filter_caps(struct udevice *dev)
+{
+	struct tmio_sd_plat *plat = dev_get_platdata(dev);
+	struct tmio_sd_priv *priv = dev_get_priv(dev);
+
+	if (!(priv->caps & TMIO_SD_CAP_RCAR_GEN3))
+		return;
+
+	/* HS400 is not supported on H3 ES1.x and M3W ES1.0,ES1.1 */
+	if (((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7795) &&
+	    (rmobile_get_cpu_rev_integer() <= 1)) ||
+	    ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7796) &&
+	    (rmobile_get_cpu_rev_integer() == 1) &&
+	    (rmobile_get_cpu_rev_fraction() <= 1)))
+		plat->cfg.host_caps &= ~MMC_MODE_HS400;
+
+	/* H3 ES2.0 uses 4 tuning taps */
+	if ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7795) &&
+	    (rmobile_get_cpu_rev_integer() == 2))
+		priv->nrtaps = 4;
+	else
+		priv->nrtaps = 8;
+}
+
 static int renesas_sdhi_probe(struct udevice *dev)
 {
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
 	u32 quirks = dev_get_driver_data(dev);
 	struct fdt_resource reg_res;
-	struct clk clk;
 	DECLARE_GLOBAL_DATA_PTR;
 	int ret;
 
+	priv->clk_get_rate = renesas_sdhi_clk_get_rate;
+
 	if (quirks == RENESAS_GEN2_QUIRKS) {
 		ret = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev),
 				       "reg", 0, &reg_res);
@@ -380,29 +487,33 @@
 			quirks |= TMIO_SD_CAP_16BIT;
 	}
 
-	ret = clk_get_by_index(dev, 0, &clk);
+	ret = clk_get_by_index(dev, 0, &priv->clk);
 	if (ret < 0) {
 		dev_err(dev, "failed to get host clock\n");
 		return ret;
 	}
 
 	/* set to max rate */
-	priv->mclk = clk_set_rate(&clk, ULONG_MAX);
-	if (IS_ERR_VALUE(priv->mclk)) {
+	ret = clk_set_rate(&priv->clk, 200000000);
+	if (ret < 0) {
 		dev_err(dev, "failed to set rate for host clock\n");
-		clk_free(&clk);
-		return priv->mclk;
+		clk_free(&priv->clk);
+		return ret;
 	}
 
-	ret = clk_enable(&clk);
-	clk_free(&clk);
+	ret = clk_enable(&priv->clk);
 	if (ret) {
 		dev_err(dev, "failed to enable host clock\n");
 		return ret;
 	}
 
 	ret = tmio_sd_probe(dev, quirks);
-#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
+
+	renesas_sdhi_filter_caps(dev);
+
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
 	if (!ret && (priv->caps & TMIO_SD_CAP_RCAR_UHS))
 		renesas_sdhi_reset_tuning(priv);
 #endif
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 0eca83a..2014920 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -555,55 +555,76 @@
 	tmio_sd_writel(priv, tmp, TMIO_SD_IF_MODE);
 }
 
-static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv,
-				     struct mmc *mmc)
+static ulong tmio_sd_clk_get_rate(struct tmio_sd_priv *priv)
+{
+	return priv->clk_get_rate(priv);
+}
+
+static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv, struct mmc *mmc)
 {
 	unsigned int divisor;
-	u32 val, tmp;
+	u32 tmp, val = 0;
+	ulong mclk;
 
-	if (!mmc->clock)
-		return;
+	if (mmc->clock) {
+		mclk = tmio_sd_clk_get_rate(priv);
 
-	divisor = DIV_ROUND_UP(priv->mclk, mmc->clock);
+		divisor = DIV_ROUND_UP(mclk, mmc->clock);
 
-	if (divisor <= 1)
-		val = (priv->caps & TMIO_SD_CAP_RCAR) ?
-		      TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
-	else if (divisor <= 2)
-		val = TMIO_SD_CLKCTL_DIV2;
-	else if (divisor <= 4)
-		val = TMIO_SD_CLKCTL_DIV4;
-	else if (divisor <= 8)
-		val = TMIO_SD_CLKCTL_DIV8;
-	else if (divisor <= 16)
-		val = TMIO_SD_CLKCTL_DIV16;
-	else if (divisor <= 32)
-		val = TMIO_SD_CLKCTL_DIV32;
-	else if (divisor <= 64)
-		val = TMIO_SD_CLKCTL_DIV64;
-	else if (divisor <= 128)
-		val = TMIO_SD_CLKCTL_DIV128;
-	else if (divisor <= 256)
-		val = TMIO_SD_CLKCTL_DIV256;
-	else if (divisor <= 512 || !(priv->caps & TMIO_SD_CAP_DIV1024))
-		val = TMIO_SD_CLKCTL_DIV512;
-	else
-		val = TMIO_SD_CLKCTL_DIV1024;
+		/* Do not set divider to 0xff in DDR mode */
+		if (mmc->ddr_mode && (divisor == 1))
+			divisor = 2;
+
+		if (divisor <= 1)
+			val = (priv->caps & TMIO_SD_CAP_RCAR) ?
+			      TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
+		else if (divisor <= 2)
+			val = TMIO_SD_CLKCTL_DIV2;
+		else if (divisor <= 4)
+			val = TMIO_SD_CLKCTL_DIV4;
+		else if (divisor <= 8)
+			val = TMIO_SD_CLKCTL_DIV8;
+		else if (divisor <= 16)
+			val = TMIO_SD_CLKCTL_DIV16;
+		else if (divisor <= 32)
+			val = TMIO_SD_CLKCTL_DIV32;
+		else if (divisor <= 64)
+			val = TMIO_SD_CLKCTL_DIV64;
+		else if (divisor <= 128)
+			val = TMIO_SD_CLKCTL_DIV128;
+		else if (divisor <= 256)
+			val = TMIO_SD_CLKCTL_DIV256;
+		else if (divisor <= 512 || !(priv->caps & TMIO_SD_CAP_DIV1024))
+			val = TMIO_SD_CLKCTL_DIV512;
+		else
+			val = TMIO_SD_CLKCTL_DIV1024;
+	}
 
 	tmp = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
-	if (tmp & TMIO_SD_CLKCTL_SCLKEN &&
-	    (tmp & TMIO_SD_CLKCTL_DIV_MASK) == val)
-		return;
+	if (mmc->clock &&
+	    !((tmp & TMIO_SD_CLKCTL_SCLKEN) &&
+	      ((tmp & TMIO_SD_CLKCTL_DIV_MASK) == val))) {
+		/*
+		 * Stop the clock before changing its rate
+		 * to avoid a glitch signal
+		 */
+		tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+		tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
 
-	/* stop the clock before changing its rate to avoid a glitch signal */
-	tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
-	tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
+		/* Change the clock rate. */
+		tmp &= ~TMIO_SD_CLKCTL_DIV_MASK;
+		tmp |= val;
+	}
 
-	tmp &= ~TMIO_SD_CLKCTL_DIV_MASK;
-	tmp |= val | TMIO_SD_CLKCTL_OFFEN;
-	tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
+	/* Enable or Disable the clock */
+	if (mmc->clk_disable) {
+		tmp |= TMIO_SD_CLKCTL_OFFEN;
+		tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+	} else {
+		tmp &= ~TMIO_SD_CLKCTL_OFFEN;
+		tmp |= TMIO_SD_CLKCTL_SCLKEN;
+	}
 
-	tmp |= TMIO_SD_CLKCTL_SCLKEN;
 	tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
 
 	udelay(1000);
@@ -708,6 +729,7 @@
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 	fdt_addr_t base;
+	ulong mclk;
 	int ret;
 
 	base = devfdt_get_addr(dev);
@@ -750,10 +772,12 @@
 
 	tmio_sd_host_init(priv);
 
+	mclk = tmio_sd_clk_get_rate(priv);
+
 	plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
-	plat->cfg.f_min = priv->mclk /
+	plat->cfg.f_min = mclk /
 			(priv->caps & TMIO_SD_CAP_DIV1024 ? 1024 : 512);
-	plat->cfg.f_max = priv->mclk;
+	plat->cfg.f_max = mclk;
 	plat->cfg.b_max = U32_MAX; /* max value of TMIO_SD_SECCNT */
 
 	upriv->mmc = &plat->mmc;
diff --git a/drivers/mmc/tmio-common.h b/drivers/mmc/tmio-common.h
index 792b1ba..192026c 100644
--- a/drivers/mmc/tmio-common.h
+++ b/drivers/mmc/tmio-common.h
@@ -117,7 +117,6 @@
 
 struct tmio_sd_priv {
 	void __iomem			*regbase;
-	unsigned long			mclk;
 	unsigned int			version;
 	u32				caps;
 #define TMIO_SD_CAP_NONREMOVABLE	BIT(0)	/* Nonremovable e.g. eMMC */
@@ -133,6 +132,14 @@
 #ifdef CONFIG_DM_REGULATOR
 	struct udevice *vqmmc_dev;
 #endif
+#if CONFIG_IS_ENABLED(CLK)
+	struct clk			clk;
+#endif
+#if CONFIG_IS_ENABLED(RENESAS_SDHI)
+	u8				tap_set;
+	u8				nrtaps;
+#endif
+	ulong (*clk_get_rate)(struct tmio_sd_priv *);
 };
 
 int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
index 813c284..6539880 100644
--- a/drivers/mmc/uniphier-sd.c
+++ b/drivers/mmc/uniphier-sd.c
@@ -31,35 +31,45 @@
 	{ /* sentinel */ }
 };
 
+static ulong uniphier_sd_clk_get_rate(struct tmio_sd_priv *priv)
+{
+#if CONFIG_IS_ENABLED(CLK)
+	return clk_get_rate(&priv->clk);
+#elif CONFIG_SPL_BUILD
+	return 100000000;
+#else
+	return 0;
+#endif
+}
+
 static int uniphier_sd_probe(struct udevice *dev)
 {
 	struct tmio_sd_priv *priv = dev_get_priv(dev);
+
+	priv->clk_get_rate = uniphier_sd_clk_get_rate;
+
 #ifndef CONFIG_SPL_BUILD
-	struct clk clk;
 	int ret;
 
-	ret = clk_get_by_index(dev, 0, &clk);
+	ret = clk_get_by_index(dev, 0, &priv->clk);
 	if (ret < 0) {
 		dev_err(dev, "failed to get host clock\n");
 		return ret;
 	}
 
 	/* set to max rate */
-	priv->mclk = clk_set_rate(&clk, ULONG_MAX);
-	if (IS_ERR_VALUE(priv->mclk)) {
+	ret = clk_set_rate(&priv->clk, ULONG_MAX);
+	if (ret < 0) {
 		dev_err(dev, "failed to set rate for host clock\n");
-		clk_free(&clk);
-		return priv->mclk;
+		clk_free(&priv->clk);
+		return ret;
 	}
 
-	ret = clk_enable(&clk);
-	clk_free(&clk);
+	ret = clk_enable(&priv->clk);
 	if (ret) {
 		dev_err(dev, "failed to enable host clock\n");
 		return ret;
 	}
-#else
-	priv->mclk = 100000000;
 #endif
 
 	return tmio_sd_probe(dev, 0);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 6038b43..fd0009b 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -104,4 +104,10 @@
 	  clock with a wide array of features and 50 bytes of general-purpose,
 	  battery-backed RAM. The driver supports access to the clock and RAM.
 
+config RTC_M41T62
+	bool "Enable M41T62 driver"
+	help
+	  Enable driver for ST's M41T62 compatible RTC devices (like RV-4162).
+	  It is a serial (I2C) real-time clock (RTC) with alarm.
+
 endmenu
diff --git a/drivers/rtc/m41t62.c b/drivers/rtc/m41t62.c
index 1374383..2ee7e00 100644
--- a/drivers/rtc/m41t62.c
+++ b/drivers/rtc/m41t62.c
@@ -1,5 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
+ * (C) Copyright 2018
+ * Lukasz Majewski, DENX Software Engineering, lukma@denx.de.
+ *
  * (C) Copyright 2008
  * Stefan Roese, DENX Software Engineering, sr@denx.de.
  *
@@ -15,6 +18,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <rtc.h>
 #include <i2c.h>
 
@@ -49,12 +53,8 @@
 
 #define M41T80_ALHOUR_HT	(1 << 6)	/* HT: Halt Update Bit */
 
-int rtc_get(struct rtc_time *tm)
+static void m41t62_update_rtc_time(struct rtc_time *tm, u8 *buf)
 {
-	u8 buf[M41T62_DATETIME_REG_SIZE];
-
-	i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE);
-
 	debug("%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
 	      "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
 	      __FUNCTION__,
@@ -77,20 +77,14 @@
 	      __FUNCTION__,
 	      tm->tm_sec, tm->tm_min, tm->tm_hour,
 	      tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
-
-	return 0;
 }
 
-int rtc_set(struct rtc_time *tm)
+static void m41t62_set_rtc_buf(const struct rtc_time *tm, u8 *buf)
 {
-	u8 buf[M41T62_DATETIME_REG_SIZE];
-
 	debug("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 	      tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
 	      tm->tm_hour, tm->tm_min, tm->tm_sec);
 
-	i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE);
-
 	/* Merge time-data and register flags into buf[0..7] */
 	buf[M41T62_REG_SSEC] = 0;
 	buf[M41T62_REG_SEC] =
@@ -107,8 +101,99 @@
 		bin2bcd(tm->tm_mon) | (buf[M41T62_REG_MON] & ~0x1f);
 	/* assume 20YY not 19YY */
 	buf[M41T62_REG_YEAR] = bin2bcd(tm->tm_year % 100);
+}
+
+#ifdef CONFIG_DM_RTC
+static int m41t62_rtc_get(struct udevice *dev, struct rtc_time *tm)
+{
+	u8 buf[M41T62_DATETIME_REG_SIZE];
+	int ret;
+
+	ret = dm_i2c_read(dev, 0, buf, sizeof(buf));
+	if (ret)
+		return ret;
+
+	m41t62_update_rtc_time(tm, buf);
+
+	return 0;
+}
+
+static int m41t62_rtc_set(struct udevice *dev, const struct rtc_time *tm)
+{
+	u8 buf[M41T62_DATETIME_REG_SIZE];
+	int ret;
+
+	ret = dm_i2c_read(dev, 0, buf, sizeof(buf));
+	if (ret)
+		return ret;
+
+	m41t62_set_rtc_buf(tm, buf);
+
+	ret = dm_i2c_write(dev, 0, buf, sizeof(buf));
+	if (ret) {
+		printf("I2C write failed in %s()\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int m41t62_rtc_reset(struct udevice *dev)
+{
+	u8 val;
+
+	/*
+	 * M41T82: Make sure HT (Halt Update) bit is cleared.
+	 * This bit is 0 in M41T62 so its save to clear it always.
+	 */
+
+	int ret = dm_i2c_read(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val));
+
+	val &= ~M41T80_ALHOUR_HT;
+	ret |= dm_i2c_write(dev, M41T62_REG_ALARM_HOUR, &val, sizeof(val));
+
+	return ret;
+}
+
+static const struct rtc_ops m41t62_rtc_ops = {
+	.get = m41t62_rtc_get,
+	.set = m41t62_rtc_set,
+	.reset = m41t62_rtc_reset,
+};
+
+static const struct udevice_id m41t62_rtc_ids[] = {
+	{ .compatible = "st,m41t62" },
+	{ .compatible = "microcrystal,rv4162" },
+	{ }
+};
+
+U_BOOT_DRIVER(rtc_m41t62) = {
+	.name	= "rtc-m41t62",
+	.id	= UCLASS_RTC,
+	.of_match = m41t62_rtc_ids,
+	.ops	= &m41t62_rtc_ops,
+};
+
+#else /* NON DM RTC code - will be removed */
+int rtc_get(struct rtc_time *tm)
+{
+	u8 buf[M41T62_DATETIME_REG_SIZE];
+
+	i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE);
+	m41t62_update_rtc_time(tm, buf);
+
+	return 0;
+}
+
+int rtc_set(struct rtc_time *tm)
+{
+	u8 buf[M41T62_DATETIME_REG_SIZE];
+
+	i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE);
+	m41t62_set_rtc_buf(tm, buf);
 
-	if (i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf, M41T62_DATETIME_REG_SIZE)) {
+	if (i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, buf,
+		      M41T62_DATETIME_REG_SIZE)) {
 		printf("I2C write failed in %s()\n", __func__);
 		return -1;
 	}
@@ -128,3 +213,4 @@
 	val &= ~M41T80_ALHOUR_HT;
 	i2c_write(CONFIG_SYS_I2C_RTC_ADDR, M41T62_REG_ALARM_HOUR, 1, &val, 1);
 }
+#endif /* CONFIG_DM_RTC */
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index c499601..09365ba 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -119,7 +119,6 @@
 serial_initfunc(atmel_serial_initialize);
 serial_initfunc(mcf_serial_initialize);
 serial_initfunc(mpc85xx_serial_initialize);
-serial_initfunc(mpc8xx_serial_initialize);
 serial_initfunc(mxc_serial_initialize);
 serial_initfunc(ns16550_serial_initialize);
 serial_initfunc(pl01x_serial_initialize);
@@ -173,7 +172,6 @@
 	atmel_serial_initialize();
 	mcf_serial_initialize();
 	mpc85xx_serial_initialize();
-	mpc8xx_serial_initialize();
 	mxc_serial_initialize();
 	ns16550_serial_initialize();
 	pl01x_serial_initialize();
diff --git a/drivers/serial/serial_mpc8xx.c b/drivers/serial/serial_mpc8xx.c
index 292912b..50d6e70 100644
--- a/drivers/serial/serial_mpc8xx.c
+++ b/drivers/serial/serial_mpc8xx.c
@@ -6,6 +6,7 @@
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
 #include <serial.h>
 #include <watchdog.h>
 #include <asm/cpm_8xx.h>
@@ -35,9 +36,9 @@
 	uchar	txbuf;	/* tx buffers */
 };
 
-static void serial_setdivisor(cpm8xx_t __iomem *cp)
+static void serial_setdivisor(cpm8xx_t __iomem *cp, int baudrate)
 {
-	int divisor = (gd->cpu_clk + 8 * gd->baudrate) / 16 / gd->baudrate;
+	int divisor = (gd->cpu_clk + 8 * baudrate) / 16 / baudrate;
 
 	if (divisor / 16 > 0x1000) {
 		/* bad divisor, assume 50MHz clock and 9600 baud */
@@ -58,7 +59,7 @@
  * as serial console interface.
  */
 
-static void smc_setbrg(void)
+static int serial_mpc8xx_setbrg(struct udevice *dev, int baudrate)
 {
 	immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
 	cpm8xx_t __iomem *cp = &(im->im_cpm);
@@ -71,10 +72,12 @@
 
 	out_be32(&cp->cp_simode, 0);
 
-	serial_setdivisor(cp);
+	serial_setdivisor(cp, baudrate);
+
+	return 0;
 }
 
-static int smc_init(void)
+static int serial_mpc8xx_probe(struct udevice *dev)
 {
 	immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
 	smc_t __iomem *sp;
@@ -139,7 +142,7 @@
 	out_8(&sp->smc_smce, 0xff);
 
 	/* Set up the baud rate generator */
-	smc_setbrg();
+	serial_mpc8xx_setbrg(dev, gd->baudrate);
 
 	/* Make the first buffer the only buffer. */
 	setbits_be16(&rtx->txbd.cbd_sc, BD_SC_WRAP);
@@ -166,14 +169,14 @@
 	return 0;
 }
 
-static void smc_putc(const char c)
+static int serial_mpc8xx_putc(struct udevice *dev, const char c)
 {
 	immap_t	__iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
 	cpm8xx_t	__iomem *cpmp = &(im->im_cpm);
 	struct serialbuffer	__iomem *rtx;
 
 	if (c == '\n')
-		smc_putc('\r');
+		serial_mpc8xx_putc(dev, '\r');
 
 	rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE];
 
@@ -184,15 +187,11 @@
 
 	while (in_be16(&rtx->txbd.cbd_sc) & BD_SC_READY)
 		WATCHDOG_RESET();
-}
 
-static void smc_puts(const char *s)
-{
-	while (*s)
-		smc_putc(*s++);
+	return 0;
 }
 
-static int smc_getc(void)
+static int serial_mpc8xx_getc(struct udevice *dev)
 {
 	immap_t	__iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
 	cpm8xx_t	__iomem *cpmp = &(im->im_cpm);
@@ -222,34 +221,37 @@
 	return c;
 }
 
-static int smc_tstc(void)
+static int serial_mpc8xx_pending(struct udevice *dev, bool input)
 {
 	immap_t	__iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
 	cpm8xx_t	__iomem *cpmp = &(im->im_cpm);
 	struct serialbuffer	__iomem *rtx;
 
+	if (!input)
+		return 0;
+
 	rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE];
 
 	return !(in_be16(&rtx->rxbd.cbd_sc) & BD_SC_EMPTY);
 }
 
-struct serial_device serial_smc_device = {
-	.name	= "serial_smc",
-	.start	= smc_init,
-	.stop	= NULL,
-	.setbrg	= smc_setbrg,
-	.getc	= smc_getc,
-	.tstc	= smc_tstc,
-	.putc	= smc_putc,
-	.puts	= smc_puts,
+static const struct dm_serial_ops serial_mpc8xx_ops = {
+	.putc = serial_mpc8xx_putc,
+	.pending = serial_mpc8xx_pending,
+	.getc = serial_mpc8xx_getc,
+	.setbrg = serial_mpc8xx_setbrg,
 };
 
-__weak struct serial_device *default_serial_console(void)
-{
-	return &serial_smc_device;
-}
+static const struct udevice_id serial_mpc8xx_ids[] = {
+	{ .compatible = "fsl,pq1-smc" },
+	{ }
+};
 
-void mpc8xx_serial_initialize(void)
-{
-	serial_register(&serial_smc_device);
-}
+U_BOOT_DRIVER(serial_mpc8xx) = {
+	.name	= "serial_mpc8xx",
+	.id	= UCLASS_SERIAL,
+	.of_match = serial_mpc8xx_ids,
+	.probe = serial_mpc8xx_probe,
+	.ops	= &serial_mpc8xx_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/spi/mpc8xx_spi.c b/drivers/spi/mpc8xx_spi.c
index 285fd4d..b020ce2 100644
--- a/drivers/spi/mpc8xx_spi.c
+++ b/drivers/spi/mpc8xx_spi.c
@@ -17,64 +17,19 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <mpc8xx.h>
-#include <asm/cpm_8xx.h>
-#include <linux/ctype.h>
-#include <malloc.h>
-#include <post.h>
-#include <serial.h>
-
-#define SPI_EEPROM_WREN		0x06
-#define SPI_EEPROM_RDSR		0x05
-#define SPI_EEPROM_READ		0x03
-#define SPI_EEPROM_WRITE	0x02
+#include <spi.h>
 
-/* ---------------------------------------------------------------
- * Offset for initial SPI buffers in DPRAM:
- * We need a 520 byte scratch DPRAM area to use at an early stage.
- * It is used between the two initialization calls (spi_init_f()
- * and spi_init_r()).
- * The value 0xb00 makes it far enough from the start of the data
- * area (as well as from the stack pointer).
- * --------------------------------------------------------------- */
-#ifndef	CONFIG_SYS_SPI_INIT_OFFSET
-#define	CONFIG_SYS_SPI_INIT_OFFSET	0xB00
-#endif
+#include <asm/cpm_8xx.h>
+#include <asm/io.h>
 
 #define CPM_SPI_BASE_RX	CPM_SPI_BASE
 #define CPM_SPI_BASE_TX	(CPM_SPI_BASE + sizeof(cbd_t))
 
-/* -------------------
- * Function prototypes
- * ------------------- */
-ssize_t spi_xfer(size_t);
-
-/* -------------------
- * Variables
- * ------------------- */
-
 #define MAX_BUFFER	0x104
 
-/* ----------------------------------------------------------------------
- * Initially we place the RX and TX buffers at a fixed location in DPRAM!
- * ---------------------------------------------------------------------- */
-static uchar *rxbuf =
-	(uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem
-			[CONFIG_SYS_SPI_INIT_OFFSET];
-static uchar *txbuf =
-	(uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem
-			[CONFIG_SYS_SPI_INIT_OFFSET+MAX_BUFFER];
-
-/* **************************************************************************
- *
- *  Function:    spi_init_f
- *
- *  Description: Init SPI-Controller (ROM part)
- *
- *  return:      ---
- *
- * *********************************************************************** */
-void spi_init_f(void)
+static int mpc8xx_spi_probe(struct udevice *dev)
 {
 	immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
 	cpm8xx_t __iomem *cp = &immr->im_cpm;
@@ -180,117 +135,24 @@
 	clrbits_be16(&tbdf->cbd_sc, BD_SC_READY);
 	clrbits_be16(&rbdf->cbd_sc, BD_SC_EMPTY);
 
-	/* Set the bd's rx and tx buffer address pointers */
-	out_be32(&rbdf->cbd_bufaddr, (ulong)rxbuf);
-	out_be32(&tbdf->cbd_bufaddr, (ulong)txbuf);
-
 /* 10 + 11 */
 	out_8(&cp->cp_spim, 0);			/* Mask  all SPI events */
 	out_8(&cp->cp_spie, SPI_EMASK);		/* Clear all SPI events	*/
 
-	return;
+	return 0;
 }
 
-/* **************************************************************************
- *
- *  Function:    spi_init_r
- *
- *  Description: Init SPI-Controller (RAM part) -
- *		 The malloc engine is ready and we can move our buffers to
- *		 normal RAM
- *
- *  return:      ---
- *
- * *********************************************************************** */
-void spi_init_r(void)
+static int mpc8xx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			    const void *dout, void *din, unsigned long flags)
 {
 	immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
 	cpm8xx_t __iomem *cp = &immr->im_cpm;
-	spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dparam[PROFF_SPI];
-	cbd_t __iomem *tbdf, *rbdf;
-
-	/* Disable relocation */
-	out_be16(&spi->spi_rpbase, 0);
-
-	/* tx and rx buffer descriptors */
-	tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX];
-	rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX];
-
-	/* Allocate memory for RX and TX buffers */
-	rxbuf = (uchar *)malloc(MAX_BUFFER);
-	txbuf = (uchar *)malloc(MAX_BUFFER);
-
-	out_be32(&rbdf->cbd_bufaddr, (ulong)rxbuf);
-	out_be32(&tbdf->cbd_bufaddr, (ulong)txbuf);
-
-	return;
-}
-
-/****************************************************************************
- *  Function:    spi_write
- **************************************************************************** */
-ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len)
-{
-	int i;
-
-	memset(rxbuf, 0, MAX_BUFFER);
-	memset(txbuf, 0, MAX_BUFFER);
-	*txbuf = SPI_EEPROM_WREN;		/* write enable		*/
-	spi_xfer(1);
-	memcpy(txbuf, addr, alen);
-	*txbuf = SPI_EEPROM_WRITE;		/* WRITE memory array	*/
-	memcpy(alen + txbuf, buffer, len);
-	spi_xfer(alen + len);
-						/* ignore received data	*/
-	for (i = 0; i < 1000; i++) {
-		*txbuf = SPI_EEPROM_RDSR;	/* read status		*/
-		txbuf[1] = 0;
-		spi_xfer(2);
-		if (!(rxbuf[1] & 1))
-			break;
-		udelay(1000);
-	}
-	if (i >= 1000)
-		printf("*** spi_write: Time out while writing!\n");
-
-	return len;
-}
-
-/****************************************************************************
- *  Function:    spi_read
- **************************************************************************** */
-ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len)
-{
-	memset(rxbuf, 0, MAX_BUFFER);
-	memset(txbuf, 0, MAX_BUFFER);
-	memcpy(txbuf, addr, alen);
-	*txbuf = SPI_EEPROM_READ;		/* READ memory array	*/
-
-	/*
-	 * There is a bug in 860T (?) that cuts the last byte of input
-	 * if we're reading into DPRAM. The solution we choose here is
-	 * to always read len+1 bytes (we have one extra byte at the
-	 * end of the buffer).
-	 */
-	spi_xfer(alen + len + 1);
-	memcpy(buffer, alen + rxbuf, len);
-
-	return len;
-}
-
-/****************************************************************************
- *  Function:    spi_xfer
- **************************************************************************** */
-ssize_t spi_xfer(size_t count)
-{
-	immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR;
-	cpm8xx_t __iomem *cp = &immr->im_cpm;
-	spi_t __iomem *spi = (spi_t __iomem *)&cp->cp_dparam[PROFF_SPI];
 	cbd_t __iomem *tbdf, *rbdf;
 	int tm;
+	size_t count = (bitlen + 7) / 8;
 
-	/* Disable relocation */
-	out_be16(&spi->spi_rpbase, 0);
+	if (count > MAX_BUFFER)
+		return -EINVAL;
 
 	tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX];
 	rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX];
@@ -299,10 +161,12 @@
 	clrbits_be32(&cp->cp_pbdat, 0x0001);
 
 	/* Setting tx bd status and data length */
+	out_be32(&tbdf->cbd_bufaddr, (ulong)dout);
 	out_be16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_LAST | BD_SC_WRAP);
 	out_be16(&tbdf->cbd_datlen, count);
 
 	/* Setting rx bd status and data length */
+	out_be32(&rbdf->cbd_bufaddr, (ulong)din);
 	out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_WRAP);
 	out_be16(&rbdf->cbd_datlen, 0);	 /* rx length has no significance */
 
@@ -333,3 +197,20 @@
 
 	return count;
 }
+
+static const struct dm_spi_ops mpc8xx_spi_ops = {
+	.xfer		= mpc8xx_spi_xfer,
+};
+
+static const struct udevice_id mpc8xx_spi_ids[] = {
+	{ .compatible = "fsl,mpc8xx-spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(mpc8xx_spi) = {
+	.name	= "mpc8xx_spi",
+	.id	= UCLASS_SPI,
+	.of_match = mpc8xx_spi_ids,
+	.ops	= &mpc8xx_spi_ops,
+	.probe	= mpc8xx_spi_probe,
+};
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 03746dd..d456beb 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -70,6 +70,7 @@
 
 config USB_STORAGE
 	bool "USB Mass Storage support"
+	depends on !(BLK && !DM_USB)
 	---help---
 	  Say Y here if you want to connect USB mass storage devices to your
 	  board's USB port.
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 4a9ebb6..b6974ad 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -144,4 +144,11 @@
 	   Select this to enable Ralink / Mediatek watchdog timer,
 	   which can be found on some MediaTek chips.
 
+config WDT_MPC8xx
+	bool "MPC8xx watchdog timer support"
+	depends on WDT && MPC8xx
+	select CONFIG_MPC8xx_WATCHDOG
+	help
+	   Select this to enable mpc8xx watchdog timer
+
 endmenu
diff --git a/drivers/watchdog/mpc8xx_wdt.c b/drivers/watchdog/mpc8xx_wdt.c
index ccb06ac..c24c2a9 100644
--- a/drivers/watchdog/mpc8xx_wdt.c
+++ b/drivers/watchdog/mpc8xx_wdt.c
@@ -4,6 +4,8 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <wdt.h>
 #include <mpc8xx.h>
 #include <asm/cpm_8xx.h>
 #include <asm/io.h>
@@ -16,3 +18,52 @@
 	out_be16(&immap->im_siu_conf.sc_swsr, 0xaa39);	/* write magic2 */
 }
 
+#ifdef CONFIG_WDT_MPC8xx
+static int mpc8xx_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+
+	out_be32(&immap->im_siu_conf.sc_sypcr, CONFIG_SYS_SYPCR);
+
+	if (!(in_be32(&immap->im_siu_conf.sc_sypcr) & SYPCR_SWE))
+		return -EBUSY;
+	return 0;
+
+}
+
+static int mpc8xx_wdt_stop(struct udevice *dev)
+{
+	immap_t __iomem *immap = (immap_t __iomem *)CONFIG_SYS_IMMR;
+
+	out_be32(&immap->im_siu_conf.sc_sypcr, CONFIG_SYS_SYPCR & ~SYPCR_SWE);
+
+	if (in_be32(&immap->im_siu_conf.sc_sypcr) & SYPCR_SWE)
+		return -EBUSY;
+	return 0;
+}
+
+static int mpc8xx_wdt_reset(struct udevice *dev)
+{
+	hw_watchdog_reset();
+
+	return 0;
+}
+
+static const struct wdt_ops mpc8xx_wdt_ops = {
+	.start = mpc8xx_wdt_start,
+	.reset = mpc8xx_wdt_reset,
+	.stop = mpc8xx_wdt_stop,
+};
+
+static const struct udevice_id mpc8xx_wdt_ids[] = {
+	{ .compatible = "fsl,pq1-wdt" },
+	{}
+};
+
+U_BOOT_DRIVER(wdt_mpc8xx) = {
+	.name = "wdt_mpc8xx",
+	.id = UCLASS_WDT,
+	.of_match = mpc8xx_wdt_ids,
+	.ops = &mpc8xx_wdt_ops,
+};
+#endif /* CONFIG_WDT_MPC8xx */
diff --git a/fs/fs.c b/fs/fs.c
index adae98d..cb26517 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -365,6 +365,7 @@
 	for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
 		if (!info->probe(fs_dev_desc, &fs_partition)) {
 			fs_type = info->fstype;
+			fs_dev_part = part;
 			return 0;
 		}
 	}
diff --git a/include/asm-generic/pe.h b/include/asm-generic/pe.h
index 9a8b5e8..faae534 100644
--- a/include/asm-generic/pe.h
+++ b/include/asm-generic/pe.h
@@ -11,6 +11,24 @@
 #ifndef _ASM_PE_H
 #define _ASM_PE_H
 
+/* Characteristics */
+#define IMAGE_FILE_RELOCS_STRIPPED		0x0001
+#define IMAGE_FILE_EXECUTABLE_IMAGE		0x0002
+#define IMAGE_FILE_LINE_NUMS_STRIPPED		0x0004
+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED		0x0008
+#define IMAGE_FILE_AGGRESSIVE_WS_TRIM		0x0010
+#define IMAGE_FILE_LARGE_ADDRESS_AWARE		0x0020
+/* Reserved					0x0040 */
+#define IMAGE_FILE_BYTES_REVERSED_LO		0x0080
+#define IMAGE_FILE_32BIT_MACHINE		0x0100
+#define IMAGE_FILE_DEBUG_STRIPPED		0x0200
+#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP	0x0400
+#define IMAGE_FILE_NET_RUN_FROM_SWAP		0x0800
+#define IMAGE_FILE_SYSTEM			0x1000
+#define IMAGE_FILE_DLL				0x2000
+#define IMAGE_FILE_UP_SYSTEM_ONLY		0x4000
+#define IMAGE_FILE_BYTES_REVERSED_HI		0x8000
+
 /* Subsystem type */
 #define IMAGE_SUBSYSTEM_EFI_APPLICATION		10
 #define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER	11
diff --git a/include/common.h b/include/common.h
index 8b56137..a8e879e 100644
--- a/include/common.h
+++ b/include/common.h
@@ -106,6 +106,17 @@
 void board_show_dram(phys_size_t size);
 
 /**
+ * Get the uppermost pointer that is valid to access
+ *
+ * Some systems may not map all of their address space. This function allows
+ * boards to indicate what their highest support pointer value is for DRAM
+ * access.
+ *
+ * @param total_size	Size of U-Boot (unused?)
+ */
+ulong board_get_usable_ram_top(ulong total_size);
+
+/**
  * arch_fixup_fdt() - Write arch-specific information to fdt
  *
  * Defined in arch/$(ARCH)/lib/bootm-fdt.c
diff --git a/include/configs/baltos.h b/include/configs/baltos.h
index 006b049..ccbdc0a 100644
--- a/include/configs/baltos.h
+++ b/include/configs/baltos.h
@@ -34,15 +34,8 @@
 /* FIT support */
 #define CONFIG_SYS_BOOTM_LEN         SZ_64M
 
-/* UBI Support */
-
-/* I2C configuration */
-
 #ifdef CONFIG_NAND
-#define CONFIG_SYS_NAND_U_BOOT_OFFS	0x00080000
-#ifdef CONFIG_SPL_OS_BOOT
-#define CONFIG_SYS_NAND_SPL_KERNEL_OFFS 0x00200000 /* kernel offset */
-#endif
+
 #define NANDARGS \
 	"mtdids=" CONFIG_MTDIDS_DEFAULT "\0" \
 	"mtdparts=" CONFIG_MTDPARTS_DEFAULT "\0" \
@@ -264,10 +257,6 @@
 #define CONFIG_AM335X_USB1
 #define CONFIG_AM335X_USB1_MODE MUSB_OTG
 
-/* Network. */
-#define CONFIG_PHY_SMSC
-#define CONFIG_PHY_ATHEROS
-
 /* NAND support */
 #ifdef CONFIG_NAND
 #define GPMC_NAND_ECC_LP_x8_LAYOUT	1
diff --git a/include/configs/emsdp.h b/include/configs/emsdp.h
index 385d59e..9a205ed 100644
--- a/include/configs/emsdp.h
+++ b/include/configs/emsdp.h
@@ -11,7 +11,7 @@
 #define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
 
 #define CONFIG_SYS_SDRAM_BASE		0x10000000
-#define CONFIG_SYS_SDRAM_SIZE		SZ_8M
+#define CONFIG_SYS_SDRAM_SIZE		SZ_16M
 
 #define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_SDRAM_BASE + SZ_1M)
 
diff --git a/include/configs/m53menlo.h b/include/configs/m53menlo.h
index 94214b1..3fca28d 100644
--- a/include/configs/m53menlo.h
+++ b/include/configs/m53menlo.h
@@ -110,7 +110,6 @@
  * RTC
  */
 #ifdef CONFIG_CMD_DATE
-#define CONFIG_RTC_M41T62
 #define CONFIG_SYS_I2C_RTC_ADDR		0x68
 #define CONFIG_SYS_M41T11_BASE_YEAR	2000
 #endif
diff --git a/include/configs/pcm052.h b/include/configs/pcm052.h
index 9997795..e125a38 100644
--- a/include/configs/pcm052.h
+++ b/include/configs/pcm052.h
@@ -58,7 +58,6 @@
 #define CONFIG_SYS_I2C_MXC
 
 /* RTC (actually an RV-4162 but M41T62-compatible) */
-#define CONFIG_RTC_M41T62
 #define CONFIG_SYS_I2C_RTC_ADDR 0x68
 #define CONFIG_SYS_RTC_BUS_NUM 2
 
diff --git a/include/configs/x600.h b/include/configs/x600.h
index a6835eb..639da80 100644
--- a/include/configs/x600.h
+++ b/include/configs/x600.h
@@ -75,7 +75,6 @@
 #define CONFIG_SYS_I2C_SLAVE			0x02
 #define CONFIG_I2C_CHIPADDRESS			0x50
 
-#define CONFIG_RTC_M41T62	1
 #define CONFIG_SYS_I2C_RTC_ADDR	0x68
 
 /* FPGA config options */
diff --git a/include/efi.h b/include/efi.h
index b1deb60..b5e2c64 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -96,7 +96,7 @@
 typedef unsigned long efi_status_t;
 typedef u64 efi_physical_addr_t;
 typedef u64 efi_virtual_addr_t;
-typedef void *efi_handle_t;
+typedef struct efi_object *efi_handle_t;
 
 #define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
 	{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, \
diff --git a/include/efi_api.h b/include/efi_api.h
index e850b95..aef77b6 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -85,10 +85,10 @@
 	efi_status_t (EFIAPI *check_event)(struct efi_event *event);
 #define EFI_NATIVE_INTERFACE	0x00000000
 	efi_status_t (EFIAPI *install_protocol_interface)(
-			void **handle, const efi_guid_t *protocol,
+			efi_handle_t *handle, const efi_guid_t *protocol,
 			int protocol_interface_type, void *protocol_interface);
 	efi_status_t (EFIAPI *reinstall_protocol_interface)(
-			void *handle, const efi_guid_t *protocol,
+			efi_handle_t handle, const efi_guid_t *protocol,
 			void *old_interface, void *new_interface);
 	efi_status_t (EFIAPI *uninstall_protocol_interface)(
 			efi_handle_t handle, const efi_guid_t *protocol,
@@ -164,9 +164,9 @@
 	efi_status_t (EFIAPI *locate_protocol)(const efi_guid_t *protocol,
 			void *registration, void **protocol_interface);
 	efi_status_t (EFIAPI *install_multiple_protocol_interfaces)(
-			void **handle, ...);
+			efi_handle_t *handle, ...);
 	efi_status_t (EFIAPI *uninstall_multiple_protocol_interfaces)(
-			void *handle, ...);
+			efi_handle_t handle, ...);
 	efi_status_t (EFIAPI *calculate_crc32)(const void *data,
 					       efi_uintn_t data_size,
 					       u32 *crc32);
@@ -241,8 +241,8 @@
 	efi_status_t (EFIAPI *query_capsule_caps)(
 			struct efi_capsule_header **capsule_header_array,
 			efi_uintn_t capsule_count,
-			u64 maximum_capsule_size,
-			u32 reset_type);
+			u64 *maximum_capsule_size,
+			u32 *reset_type);
 	efi_status_t (EFIAPI *query_variable_info)(
 			u32 attributes,
 			u64 *maximum_variable_storage_size,
@@ -965,7 +965,7 @@
 	struct efi_time last_access_time;
 	struct efi_time modification_time;
 	u64 attribute;
-	s16 file_name[0];
+	u16 file_name[0];
 };
 
 struct efi_file_system_info {
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 1417c35..53f0816 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -167,28 +167,41 @@
 	struct list_head open_infos;
 };
 
-/*
- * UEFI has a poor man's OO model where one "object" can be polymorphic and have
- * multiple different protocols (classes) attached to it.
+/**
+ * struct efi_object - dereferenced EFI handle
+ *
+ * @link:	pointers to put the handle into a linked list
+ * @protocols:	linked list with the protocol interfaces installed on this
+ *		handle
+ *
+ * UEFI offers a flexible and expandable object model. The objects in the UEFI
+ * API are devices, drivers, and loaded images. struct efi_object is our storage
+ * structure for these objects.
  *
- * This struct is the parent struct for all of our actual implementation objects
- * that can include it to make themselves an EFI object
+ * When including this structure into a larger structure always put it first so
+ * that when deleting a handle the whole encompassing structure can be freed.
+ *
+ * A pointer to this structure is referred to as a handle. Typedef efi_handle_t
+ * has been created for such pointers.
  */
 struct efi_object {
 	/* Every UEFI object is part of a global object list */
 	struct list_head link;
 	/* The list of protocols */
 	struct list_head protocols;
-	/* The object spawner can either use this for data or as identifier */
-	void *handle;
 };
 
 /**
  * struct efi_loaded_image_obj - handle of a loaded image
+ *
+ * @header:		EFI object header
+ * @reloc_base:		base address for the relocated image
+ * @reloc_size:		size of the relocated image
+ * @exit_jmp:		long jump buffer for returning form started image
+ * @entry:		entry address of the relocated image
  */
 struct efi_loaded_image_obj {
-	/* Generic EFI object parent class data */
-	struct efi_object parent;
+	struct efi_object header;
 	void *reloc_base;
 	aligned_u64 reloc_size;
 	efi_status_t exit_status;
@@ -290,11 +303,11 @@
 /* Call this to set the current device name */
 void efi_set_bootdev(const char *dev, const char *devnr, const char *path);
 /* Add a new object to the object list. */
-void efi_add_handle(struct efi_object *obj);
+void efi_add_handle(efi_handle_t obj);
 /* Create handle */
 efi_status_t efi_create_handle(efi_handle_t *handle);
 /* Delete handle */
-void efi_delete_handle(struct efi_object *obj);
+void efi_delete_handle(efi_handle_t obj);
 /* Call this to validate a handle and find the EFI object for it */
 struct efi_object *efi_search_obj(const efi_handle_t handle);
 /* Find a protocol on a handle */
@@ -331,7 +344,16 @@
 /* open file from device-path: */
 struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp);
 
-
+/**
+ * efi_size_in_pages() - convert size in bytes to size in pages
+ *
+ * This macro returns the number of EFI memory pages required to hold 'size'
+ * bytes.
+ *
+ * @size:	size in bytes
+ * Return:	size in pages
+ */
+#define efi_size_in_pages(size) ((size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT)
 /* Generic EFI memory allocator, call this to get memory */
 void *efi_alloc(uint64_t len, int memory_type);
 /* More specific EFI memory allocator, called by EFI payloads */
@@ -419,6 +441,10 @@
 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);
+efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
+			      const char *path,
+			      struct efi_device_path **device,
+			      struct efi_device_path **file);
 
 #define EFI_DP_TYPE(_dp, _type, _subtype) \
 	(((_dp)->type == DEVICE_PATH_TYPE_##_type) && \
@@ -492,6 +518,29 @@
 				     u32 attributes, efi_uintn_t data_size,
 				     void *data);
 
+/*
+ * See section 3.1.3 in the v2.7 UEFI spec for more details on
+ * the layout of EFI_LOAD_OPTION.  In short it is:
+ *
+ *    typedef struct _EFI_LOAD_OPTION {
+ *        UINT32 Attributes;
+ *        UINT16 FilePathListLength;
+ *        // CHAR16 Description[];   <-- variable length, NULL terminated
+ *        // EFI_DEVICE_PATH_PROTOCOL FilePathList[];
+ *						 <-- FilePathListLength bytes
+ *        // UINT8 OptionalData[];
+ *    } EFI_LOAD_OPTION;
+ */
+struct efi_load_option {
+	u32 attributes;
+	u16 file_path_length;
+	u16 *label;
+	struct efi_device_path *file_path;
+	u8 *optional_data;
+};
+
+void efi_deserialize_load_option(struct efi_load_option *lo, u8 *data);
+unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data);
 void *efi_bootmgr_load(struct efi_device_path **device_path,
 		       struct efi_device_path **file_path);
 
diff --git a/include/efi_selftest.h b/include/efi_selftest.h
index 56beac3..49d3d6d 100644
--- a/include/efi_selftest.h
+++ b/include/efi_selftest.h
@@ -129,7 +129,6 @@
  * @setup:	set up the unit test
  * @teardown:	tear down the unit test
  * @execute:	execute the unit test
- * @setup_ok:	setup was successful (set at runtime)
  * @on_request:	test is only executed on request
  */
 struct efi_unit_test {
@@ -139,7 +138,6 @@
 		     const struct efi_system_table *systable);
 	int (*execute)(void);
 	int (*teardown)(void);
-	int setup_ok;
 	bool on_request;
 };
 
diff --git a/include/image.h b/include/image.h
index f67502e..83a2d41 100644
--- a/include/image.h
+++ b/include/image.h
@@ -30,6 +30,7 @@
 #define IMAGE_ENABLE_FIT	1
 #define IMAGE_ENABLE_OF_LIBFDT	1
 #define CONFIG_FIT_VERBOSE	1 /* enable fit_format_{error,warning}() */
+#define CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT 1
 #define CONFIG_FIT_ENABLE_SHA256_SUPPORT
 #define CONFIG_SHA1
 #define CONFIG_SHA256
@@ -1101,6 +1102,7 @@
 	int node_offset;		/* Offset of signature node */
 	const char *name;		/* Algorithm name */
 	struct checksum_algo *checksum;	/* Checksum algorithm information */
+	struct padding_algo *padding;	/* Padding algorithm information */
 	struct crypto_algo *crypto;	/* Crypto algorithm information */
 	const void *fdt_blob;		/* FDT containing public keys */
 	int required_keynode;		/* Node offset of key to use: -1=any */
@@ -1186,6 +1188,13 @@
 		      uint8_t *sig, uint sig_len);
 };
 
+struct padding_algo {
+	const char *name;
+	int (*verify)(struct image_sign_info *info,
+		      uint8_t *pad, int pad_len,
+		      const uint8_t *hash, int hash_len);
+};
+
 /**
  * image_get_checksum_algo() - Look up a checksum algorithm
  *
@@ -1203,6 +1212,14 @@
 struct crypto_algo *image_get_crypto_algo(const char *full_name);
 
 /**
+ * image_get_padding_algo() - Look up a padding algorithm
+ *
+ * @param name		Name of padding algorithm
+ * @return pointer to algorithm information, or NULL if not found
+ */
+struct padding_algo *image_get_padding_algo(const char *name);
+
+/**
  * fit_image_verify_required_sigs() - Verify signatures marked as 'required'
  *
  * @fit:		FIT to check
diff --git a/include/linux/psci.h b/include/linux/psci.h
index 8d13bd2..9433df8 100644
--- a/include/linux/psci.h
+++ b/include/linux/psci.h
@@ -88,10 +88,8 @@
 #define PSCI_RET_DISABLED			-8
 
 #ifdef CONFIG_ARM_PSCI_FW
-typedef unsigned long (psci_fn)(unsigned long, unsigned long,
-				unsigned long, unsigned long);
-
-extern psci_fn *invoke_psci_fn;
+unsigned long invoke_psci_fn(unsigned long a0, unsigned long a1,
+			     unsigned long a2, unsigned long a3);
 #else
 unsigned long invoke_psci_fn(unsigned long a0, unsigned long a1,
 			     unsigned long a2, unsigned long a3)
diff --git a/include/serial.h b/include/serial.h
index ec25db6..9133d07 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -224,7 +224,6 @@
 void atmel_serial_initialize(void);
 void mcf_serial_initialize(void);
 void mpc85xx_serial_initialize(void);
-void mpc8xx_serial_initialize(void);
 void mxc_serial_initialize(void);
 void ns16550_serial_initialize(void);
 void pl01x_serial_initialize(void);
diff --git a/include/u-boot/rsa.h b/include/u-boot/rsa.h
index 68bcb14..2d3024d 100644
--- a/include/u-boot/rsa.h
+++ b/include/u-boot/rsa.h
@@ -97,6 +97,16 @@
 int rsa_verify(struct image_sign_info *info,
 	       const struct image_region region[], int region_count,
 	       uint8_t *sig, uint sig_len);
+
+int padding_pkcs_15_verify(struct image_sign_info *info,
+			   uint8_t *msg, int msg_len,
+			   const uint8_t *hash, int hash_len);
+
+#ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
+int padding_pss_verify(struct image_sign_info *info,
+		       uint8_t *msg, int msg_len,
+		       const uint8_t *hash, int hash_len);
+#endif /* CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT */
 #else
 static inline int rsa_verify(struct image_sign_info *info,
 		const struct image_region region[], int region_count,
@@ -104,8 +114,26 @@
 {
 	return -ENXIO;
 }
+
+static inline int padding_pkcs_15_verify(struct image_sign_info *info,
+					 uint8_t *msg, int msg_len,
+					 const uint8_t *hash, int hash_len)
+{
+	return -ENXIO;
+}
+
+#ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
+static inline int padding_pss_verify(struct image_sign_info *info,
+				     uint8_t *msg, int msg_len,
+				     const uint8_t *hash, int hash_len)
+{
+	return -ENXIO;
+}
+#endif /* CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT */
 #endif
 
+#define RSA_DEFAULT_PADDING_NAME		"pkcs-1.5"
+
 #define RSA2048_BYTES	(2048 / 8)
 #define RSA4096_BYTES	(4096 / 8)
 
diff --git a/lib/Makefile b/lib/Makefile
index 4d2e220..8321355 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -8,7 +8,7 @@
 obj-$(CONFIG_EFI) += efi/
 obj-$(CONFIG_EFI_LOADER) += efi_driver/
 obj-$(CONFIG_EFI_LOADER) += efi_loader/
-obj-$(CONFIG_EFI_LOADER) += efi_selftest/
+obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/
 obj-$(CONFIG_LZMA) += lzma/
 obj-$(CONFIG_BZIP2) += bzip2/
 obj-$(CONFIG_TIZEN) += tizen/
diff --git a/lib/efi/efi.c b/lib/efi/efi.c
index c6639f9..2c6a508 100644
--- a/lib/efi/efi.c
+++ b/lib/efi/efi.c
@@ -69,7 +69,7 @@
 	efi_putc(priv, ' ');
 
 	ret = boot->open_protocol(priv->parent_image, &loaded_image_guid,
-				  (void **)&loaded_image, &priv->parent_image,
+				  (void **)&loaded_image, priv->parent_image,
 				  NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
 	if (ret) {
 		efi_puts(priv, "Failed to get loaded image protocol\n");
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index 0c5764d..a095df3 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- *  EFI utils
+ *  EFI boot manager
  *
  *  Copyright (c) 2017 Rob Clark
  */
@@ -9,6 +9,7 @@
 #include <charset.h>
 #include <malloc.h>
 #include <efi_loader.h>
+#include <asm/unaligned.h>
 
 static const struct efi_boot_services *bs;
 static const struct efi_runtime_services *rs;
@@ -30,42 +31,68 @@
  */
 
 
+/* Parse serialized data and transform it into efi_load_option structure */
+void efi_deserialize_load_option(struct efi_load_option *lo, u8 *data)
+{
+	lo->attributes = get_unaligned_le32(data);
+	data += sizeof(u32);
+
+	lo->file_path_length = get_unaligned_le16(data);
+	data += sizeof(u16);
+
+	/* FIXME */
+	lo->label = (u16 *)data;
+	data += (u16_strlen(lo->label) + 1) * sizeof(u16);
+
+	/* FIXME */
+	lo->file_path = (struct efi_device_path *)data;
+	data += lo->file_path_length;
+
+	lo->optional_data = data;
+}
+
 /*
- * See section 3.1.3 in the v2.7 UEFI spec for more details on
- * the layout of EFI_LOAD_OPTION.  In short it is:
- *
- *    typedef struct _EFI_LOAD_OPTION {
- *        UINT32 Attributes;
- *        UINT16 FilePathListLength;
- *        // CHAR16 Description[];   <-- variable length, NULL terminated
- *        // EFI_DEVICE_PATH_PROTOCOL FilePathList[];  <-- FilePathListLength bytes
- *        // UINT8 OptionalData[];
- *    } EFI_LOAD_OPTION;
+ * Serialize efi_load_option structure into byte stream for BootXXXX.
+ * Return a size of allocated data.
  */
-struct load_option {
-	u32 attributes;
-	u16 file_path_length;
-	u16 *label;
-	struct efi_device_path *file_path;
-	u8 *optional_data;
-};
-
-/* parse an EFI_LOAD_OPTION, as described above */
-static void parse_load_option(struct load_option *lo, void *ptr)
+unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data)
 {
-	lo->attributes = *(u32 *)ptr;
-	ptr += sizeof(u32);
+	unsigned long label_len, option_len;
+	unsigned long size;
+	u8 *p;
+
+	label_len = (u16_strlen(lo->label) + 1) * sizeof(u16);
+	option_len = strlen((char *)lo->optional_data);
 
-	lo->file_path_length = *(u16 *)ptr;
-	ptr += sizeof(u16);
+	/* total size */
+	size = sizeof(lo->attributes);
+	size += sizeof(lo->file_path_length);
+	size += label_len;
+	size += lo->file_path_length;
+	size += option_len + 1;
+	p = malloc(size);
+	if (!p)
+		return 0;
 
-	lo->label = ptr;
-	ptr += (u16_strlen(lo->label) + 1) * 2;
+	/* copy data */
+	*data = p;
+	memcpy(p, &lo->attributes, sizeof(lo->attributes));
+	p += sizeof(lo->attributes);
 
-	lo->file_path = ptr;
-	ptr += lo->file_path_length;
+	memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length));
+	p += sizeof(lo->file_path_length);
 
-	lo->optional_data = ptr;
+	memcpy(p, lo->label, label_len);
+	p += label_len;
+
+	memcpy(p, lo->file_path, lo->file_path_length);
+	p += lo->file_path_length;
+
+	memcpy(p, lo->optional_data, option_len);
+	p += option_len;
+	*(char *)p = '\0';
+
+	return size;
 }
 
 /* free() the result */
@@ -100,7 +127,7 @@
 static void *try_load_entry(uint16_t n, struct efi_device_path **device_path,
 			    struct efi_device_path **file_path)
 {
-	struct load_option lo;
+	struct efi_load_option lo;
 	u16 varname[] = L"Boot0000";
 	u16 hexmap[] = L"0123456789ABCDEF";
 	void *load_option, *image = NULL;
@@ -115,7 +142,7 @@
 	if (!load_option)
 		return NULL;
 
-	parse_load_option(&lo, load_option);
+	efi_deserialize_load_option(&lo, load_option);
 
 	if (lo.attributes & LOAD_OPTION_ACTIVE) {
 		efi_status_t ret;
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index da978d2..cc9efbb 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -26,6 +26,14 @@
 /* List of all events */
 LIST_HEAD(efi_events);
 
+/*
+ * If we're running on nasty systems (32bit ARM booting into non-EFI Linux)
+ * we need to do trickery with caches. Since we don't want to break the EFI
+ * aware boot path, only apply hacks when loading exiting directly (breaking
+ * direct Linux EFI booting along the way - oh well).
+ */
+static bool efi_is_direct_boot = true;
+
 #ifdef CONFIG_ARM
 /*
  * The "gd" pointer lives in a register on ARM and AArch64 that we declare
@@ -416,13 +424,12 @@
  *
  * The protocols list is initialized. The object handle is set.
  */
-void efi_add_handle(struct efi_object *obj)
+void efi_add_handle(efi_handle_t handle)
 {
-	if (!obj)
+	if (!handle)
 		return;
-	INIT_LIST_HEAD(&obj->protocols);
-	obj->handle = obj;
-	list_add_tail(&obj->link, &efi_obj_list);
+	INIT_LIST_HEAD(&handle->protocols);
+	list_add_tail(&handle->link, &efi_obj_list);
 }
 
 /**
@@ -440,7 +447,7 @@
 		return EFI_OUT_OF_RESOURCES;
 
 	efi_add_handle(obj);
-	*handle = obj->handle;
+	*handle = obj;
 
 	return EFI_SUCCESS;
 }
@@ -536,13 +543,13 @@
  *
  * @obj: handle to delete
  */
-void efi_delete_handle(struct efi_object *obj)
+void efi_delete_handle(efi_handle_t handle)
 {
-	if (!obj)
+	if (!handle)
 		return;
-	efi_remove_all_protocols(obj->handle);
-	list_del(&obj->link);
-	free(obj);
+	efi_remove_all_protocols(handle);
+	list_del(&handle->link);
+	free(handle);
 }
 
 /**
@@ -927,7 +934,7 @@
 	struct efi_object *efiobj;
 
 	list_for_each_entry(efiobj, &efi_obj_list, link) {
-		if (efiobj->handle == handle)
+		if (efiobj == handle)
 			return efiobj;
 	}
 
@@ -1019,7 +1026,7 @@
  * Return: status code
  */
 static efi_status_t EFIAPI efi_install_protocol_interface(
-			void **handle, const efi_guid_t *protocol,
+			efi_handle_t *handle, const efi_guid_t *protocol,
 			int protocol_interface_type, void *protocol_interface)
 {
 	efi_status_t r;
@@ -1052,7 +1059,7 @@
 
 /**
  * efi_get_drivers() - get all drivers associated to a controller
- * @efiobj:               handle of the controller
+ * @handle:               handle of the controller
  * @protocol:             protocol GUID (optional)
  * @number_of_drivers:    number of child controllers
  * @driver_handle_buffer: handles of the the drivers
@@ -1061,7 +1068,7 @@
  *
  * Return: status code
  */
-static efi_status_t efi_get_drivers(struct efi_object *efiobj,
+static efi_status_t efi_get_drivers(efi_handle_t handle,
 				    const efi_guid_t *protocol,
 				    efi_uintn_t *number_of_drivers,
 				    efi_handle_t **driver_handle_buffer)
@@ -1072,7 +1079,7 @@
 	bool duplicate;
 
 	/* Count all driver associations */
-	list_for_each_entry(handler, &efiobj->protocols, link) {
+	list_for_each_entry(handler, &handle->protocols, link) {
 		if (protocol && guidcmp(handler->guid, protocol))
 			continue;
 		list_for_each_entry(item, &handler->open_infos, link) {
@@ -1090,7 +1097,7 @@
 	if (!*driver_handle_buffer)
 		return EFI_OUT_OF_RESOURCES;
 	/* Collect unique driver handles */
-	list_for_each_entry(handler, &efiobj->protocols, link) {
+	list_for_each_entry(handler, &handle->protocols, link) {
 		if (protocol && guidcmp(handler->guid, protocol))
 			continue;
 		list_for_each_entry(item, &handler->open_infos, link) {
@@ -1117,7 +1124,7 @@
 
 /**
  * efi_disconnect_all_drivers() - disconnect all drivers from a controller
- * @efiobj:       handle of the controller
+ * @handle:       handle of the controller
  * @protocol:     protocol GUID (optional)
  * @child_handle: handle of the child to destroy
  *
@@ -1128,16 +1135,16 @@
  *
  * 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)
+static efi_status_t efi_disconnect_all_drivers
+				(efi_handle_t handle,
+				 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,
+	ret = efi_get_drivers(handle, protocol, &number_of_drivers,
 			      &driver_handle_buffer);
 	if (ret != EFI_SUCCESS)
 		return ret;
@@ -1145,7 +1152,7 @@
 	ret = EFI_NOT_FOUND;
 	while (number_of_drivers) {
 		r = EFI_CALL(efi_disconnect_controller(
-				efiobj->handle,
+				handle,
 				driver_handle_buffer[--number_of_drivers],
 				child_handle));
 		if (r == EFI_SUCCESS)
@@ -1156,21 +1163,19 @@
 }
 
 /**
- * efi_uninstall_protocol_interface() - uninstall protocol interface
+ * efi_uninstall_protocol() - uninstall protocol interface
+ *
  * @handle:             handle from which the protocol shall be removed
  * @protocol:           GUID of the protocol to be removed
  * @protocol_interface: interface to be removed
  *
- * This function implements the UninstallProtocolInterface service.
- *
- * See the Unified Extensible Firmware Interface (UEFI) specification for
- * details.
+ * This function DOES NOT delete a handle without installed protocol.
  *
  * Return: status code
  */
-static efi_status_t EFIAPI efi_uninstall_protocol_interface(
-				efi_handle_t handle, const efi_guid_t *protocol,
-				void *protocol_interface)
+static efi_status_t efi_uninstall_protocol
+			(efi_handle_t handle, const efi_guid_t *protocol,
+			 void *protocol_interface)
 {
 	struct efi_object *efiobj;
 	struct efi_handler *handler;
@@ -1178,8 +1183,6 @@
 	struct efi_open_protocol_info_item *pos;
 	efi_status_t r;
 
-	EFI_ENTRY("%p, %pUl, %p", handle, protocol, protocol_interface);
-
 	/* Check handle */
 	efiobj = efi_search_obj(handle);
 	if (!efiobj) {
@@ -1210,7 +1213,41 @@
 	}
 	r = efi_remove_protocol(handle, protocol, protocol_interface);
 out:
-	return EFI_EXIT(r);
+	return r;
+}
+
+/**
+ * efi_uninstall_protocol_interface() - uninstall protocol interface
+ * @handle:             handle from which the protocol shall be removed
+ * @protocol:           GUID of the protocol to be removed
+ * @protocol_interface: interface to be removed
+ *
+ * This function implements the UninstallProtocolInterface service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * Return: status code
+ */
+static efi_status_t EFIAPI efi_uninstall_protocol_interface
+			(efi_handle_t handle, const efi_guid_t *protocol,
+			 void *protocol_interface)
+{
+	efi_status_t ret;
+
+	EFI_ENTRY("%p, %pUl, %p", handle, protocol, protocol_interface);
+
+	ret = efi_uninstall_protocol(handle, protocol, protocol_interface);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	/* If the last protocol has been removed, delete the handle. */
+	if (list_empty(&handle->protocols)) {
+		list_del(&handle->link);
+		free(handle);
+	}
+out:
+	return EFI_EXIT(ret);
 }
 
 /**
@@ -1240,7 +1277,7 @@
  * @search_type: selection criterion
  * @protocol:    GUID of the protocol
  * @search_key:  registration key
- * @efiobj:      handle
+ * @handle:      handle
  *
  * See the documentation of the LocateHandle service in the UEFI specification.
  *
@@ -1248,7 +1285,7 @@
  */
 static int efi_search(enum efi_locate_search_type search_type,
 		      const efi_guid_t *protocol, void *search_key,
-		      struct efi_object *efiobj)
+		      efi_handle_t handle)
 {
 	efi_status_t ret;
 
@@ -1259,7 +1296,7 @@
 		/* TODO: RegisterProtocolNotify is not implemented yet */
 		return -1;
 	case BY_PROTOCOL:
-		ret = efi_search_protocol(efiobj->handle, protocol, NULL);
+		ret = efi_search_protocol(handle, protocol, NULL);
 		return (ret != EFI_SUCCESS);
 	default:
 		/* Invalid search type */
@@ -1331,7 +1368,7 @@
 	/* Then fill the array */
 	list_for_each_entry(efiobj, &efi_obj_list, link) {
 		if (!efi_search(search_type, protocol, search_key, efiobj))
-			*buffer++ = efiobj->handle;
+			*buffer++ = efiobj;
 	}
 
 	return EFI_SUCCESS;
@@ -1489,7 +1526,7 @@
 	}
 
 	/* Add internal object to object list */
-	efi_add_handle(&obj->parent);
+	efi_add_handle(&obj->header);
 
 	if (info_ptr)
 		*info_ptr = info;
@@ -1506,7 +1543,7 @@
 		 * When asking for the device path interface, return
 		 * bootefi_device_path
 		 */
-		ret = efi_add_protocol(obj->parent.handle,
+		ret = efi_add_protocol(&obj->header,
 				       &efi_guid_device_path, device_path);
 		if (ret != EFI_SUCCESS)
 			goto failure;
@@ -1516,7 +1553,7 @@
 	 * When asking for the loaded_image interface, just
 	 * return handle which points to loaded_image_info
 	 */
-	ret = efi_add_protocol(obj->parent.handle,
+	ret = efi_add_protocol(&obj->header,
 			       &efi_guid_loaded_image, info);
 	if (ret != EFI_SUCCESS)
 		goto failure;
@@ -1678,6 +1715,8 @@
 
 	EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
 
+	efi_is_direct_boot = false;
+
 	/* call the image! */
 	if (setjmp(&image_obj->exit_jmp)) {
 		/*
@@ -1786,6 +1825,21 @@
 }
 
 /**
+ * efi_exit_caches() - fix up caches for EFI payloads if necessary
+ */
+static void efi_exit_caches(void)
+{
+#if defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
+	/*
+	 * Grub on 32bit ARM needs to have caches disabled before jumping into
+	 * a zImage, but does not know of all cache layers. Give it a hand.
+	 */
+	if (efi_is_direct_boot)
+		cleanup_before_linux();
+#endif
+}
+
+/**
  * efi_exit_boot_services() - stop all boot services
  * @image_handle: handle of the loaded image
  * @map_key:      key of the memory map
@@ -1838,6 +1892,9 @@
 
 	board_quiesce_devices();
 
+	/* Fix up caches for EFI payloads if necessary */
+	efi_exit_caches();
+
 	/* This stops all lingering devices */
 	bootm_disable_interrupts();
 
@@ -2176,7 +2233,7 @@
 
 		efiobj = list_entry(lhandle, struct efi_object, link);
 
-		ret = efi_search_protocol(efiobj->handle, protocol, &handler);
+		ret = efi_search_protocol(efiobj, protocol, &handler);
 		if (ret == EFI_SUCCESS) {
 			*protocol_interface = handler->protocol_interface;
 			return EFI_EXIT(EFI_SUCCESS);
@@ -2279,8 +2336,8 @@
  *
  * Return: status code
  */
-static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(
-			void **handle, ...)
+static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces
+				(efi_handle_t *handle, ...)
 {
 	EFI_ENTRY("%p", handle);
 
@@ -2316,7 +2373,7 @@
 	for (; i; --i) {
 		protocol = efi_va_arg(argptr, efi_guid_t*);
 		protocol_interface = efi_va_arg(argptr, void*);
-		EFI_CALL(efi_uninstall_protocol_interface(handle, protocol,
+		EFI_CALL(efi_uninstall_protocol_interface(*handle, protocol,
 							  protocol_interface));
 	}
 	efi_va_end(argptr);
@@ -2339,7 +2396,7 @@
  * Return: status code
  */
 static efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(
-			void *handle, ...)
+			efi_handle_t handle, ...)
 {
 	EFI_ENTRY("%p", handle);
 
@@ -2358,16 +2415,21 @@
 		if (!protocol)
 			break;
 		protocol_interface = efi_va_arg(argptr, void*);
-		r = EFI_CALL(efi_uninstall_protocol_interface(
-						handle, protocol,
-						protocol_interface));
+		r = efi_uninstall_protocol(handle, protocol,
+					   protocol_interface);
 		if (r != EFI_SUCCESS)
 			break;
 		i++;
 	}
 	efi_va_end(argptr);
-	if (r == EFI_SUCCESS)
+	if (r == EFI_SUCCESS) {
+		/* If the last protocol has been removed, delete the handle. */
+		if (list_empty(&handle->protocols)) {
+			list_del(&handle->link);
+			free(handle);
+		}
 		return EFI_EXIT(r);
+	}
 
 	/* If an error occurred undo all changes. */
 	efi_va_start(argptr, handle);
@@ -2380,7 +2442,8 @@
 	}
 	efi_va_end(argptr);
 
-	return EFI_EXIT(r);
+	/* In case of an error always return EFI_INVALID_PARAMETER */
+	return EFI_EXIT(EFI_INVALID_PARAMETER);
 }
 
 /**
@@ -2553,10 +2616,10 @@
  *
  * Return: status code
  */
-static efi_status_t EFIAPI efi_open_protocol(
-			void *handle, const efi_guid_t *protocol,
-			void **protocol_interface, void *agent_handle,
-			void *controller_handle, uint32_t attributes)
+static efi_status_t EFIAPI efi_open_protocol
+			(efi_handle_t handle, const efi_guid_t *protocol,
+			 void **protocol_interface, efi_handle_t agent_handle,
+			 efi_handle_t controller_handle, uint32_t attributes)
 {
 	struct efi_handler *handler;
 	efi_status_t r = EFI_INVALID_PARAMETER;
@@ -2828,13 +2891,19 @@
 
 	EFI_ENTRY("%p, %pUl, %p, %p", handle, protocol, old_interface,
 		  new_interface);
-	ret = EFI_CALL(efi_uninstall_protocol_interface(handle, protocol,
-							old_interface));
+
+	/* Uninstall protocol but do not delete handle */
+	ret = efi_uninstall_protocol(handle, protocol, old_interface);
 	if (ret != EFI_SUCCESS)
 		goto out;
-	ret = EFI_CALL(efi_install_protocol_interface(&handle, protocol,
-						      EFI_NATIVE_INTERFACE,
-						      new_interface));
+
+	/* Install the new protocol */
+	ret = efi_add_protocol(handle, protocol, new_interface);
+	/*
+	 * The UEFI spec does not specify what should happen to the handle
+	 * if in case of an error no protocol interface remains on the handle.
+	 * So let's do nothing here.
+	 */
 	if (ret != EFI_SUCCESS)
 		goto out;
 	/*
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 0225222..66c33a5 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -205,7 +205,7 @@
 	/*
 	 * Not all terminals understand CSI [18t for querying the console size.
 	 * We should adhere to escape sequences documented in the console_codes
-	 * manpage and the ECMA-48 standard.
+	 * man page and the ECMA-48 standard.
 	 *
 	 * So here we follow a different approach. We position the cursor to the
 	 * bottom right and query its position. Before leaving the function we
@@ -480,7 +480,7 @@
  *
  * This gets called when we have already parsed CSI.
  *
- * @modifiers:  bitmask (shift, alt, ctrl)
+ * @modifiers:  bit mask (shift, alt, ctrl)
  * @return:	the unmodified code
  */
 static int analyze_modifiers(struct efi_key_state *key_state)
@@ -1051,34 +1051,34 @@
 efi_status_t efi_console_register(void)
 {
 	efi_status_t r;
-	struct efi_object *efi_console_output_obj;
-	struct efi_object *efi_console_input_obj;
+	efi_handle_t console_output_handle;
+	efi_handle_t console_input_handle;
 
 	/* Set up mode information */
 	query_console_size();
 
 	/* Create handles */
-	r = efi_create_handle((efi_handle_t *)&efi_console_output_obj);
+	r = efi_create_handle(&console_output_handle);
 	if (r != EFI_SUCCESS)
 		goto out_of_memory;
 
-	r = efi_add_protocol(efi_console_output_obj->handle,
+	r = efi_add_protocol(console_output_handle,
 			     &efi_guid_text_output_protocol, &efi_con_out);
 	if (r != EFI_SUCCESS)
 		goto out_of_memory;
-	systab.con_out_handle = efi_console_output_obj->handle;
-	systab.stderr_handle = efi_console_output_obj->handle;
+	systab.con_out_handle = console_output_handle;
+	systab.stderr_handle = console_output_handle;
 
-	r = efi_create_handle((efi_handle_t *)&efi_console_input_obj);
+	r = efi_create_handle(&console_input_handle);
 	if (r != EFI_SUCCESS)
 		goto out_of_memory;
 
-	r = efi_add_protocol(efi_console_input_obj->handle,
+	r = efi_add_protocol(console_input_handle,
 			     &efi_guid_text_input_protocol, &efi_con_in);
 	if (r != EFI_SUCCESS)
 		goto out_of_memory;
-	systab.con_in_handle = efi_console_input_obj->handle;
-	r = efi_add_protocol(efi_console_input_obj->handle,
+	systab.con_in_handle = console_input_handle;
+	r = efi_add_protocol(console_input_handle,
 			     &efi_guid_text_input_ex_protocol, &efi_con_in_ex);
 	if (r != EFI_SUCCESS)
 		goto out_of_memory;
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index 46a24f7..d949823 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -82,7 +82,7 @@
 
 /*
  * Compare two device-paths, stopping when the shorter of the two hits
- * an End* node.  This is useful to, for example, compare a device-path
+ * an End* node. This is useful to, for example, compare a device-path
  * representing a device with one representing a file on the device, or
  * a device with a parent device.
  */
@@ -109,16 +109,17 @@
 }
 
 /*
- * 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
- * or USB Class node, and a few other cases which don't encode
- * the full device path with bus hierarchy:
+ * We can have device paths that start with a USB WWID or a USB Class node,
+ * and a few other cases which don't encode the full device path with bus
+ * hierarchy:
  *
  *   - MESSAGING:USB_WWID
  *   - MESSAGING:USB_CLASS
  *   - MEDIA:FILE_PATH
  *   - MEDIA:HARD_DRIVE
  *   - MESSAGING:URI
+ *
+ * See UEFI spec (section 3.1.2, about short-form device-paths)
  */
 static struct efi_device_path *shorten_path(struct efi_device_path *dp)
 {
@@ -150,7 +151,7 @@
 		struct efi_device_path *obj_dp;
 		efi_status_t ret;
 
-		ret = efi_search_protocol(efiobj->handle,
+		ret = efi_search_protocol(efiobj,
 					  &efi_guid_device_path, &handler);
 		if (ret != EFI_SUCCESS)
 			continue;
@@ -644,7 +645,7 @@
 /*
  * Create a device node for a block device partition.
  *
- * @buf		buffer to which the device path is wirtten
+ * @buf		buffer to which the device path is written
  * @desc	block device descriptor
  * @part	partition number, 0 identifies a block device
  */
@@ -709,7 +710,7 @@
 /*
  * Create a device path for a block device or one of its partitions.
  *
- * @buf		buffer to which the device path is wirtten
+ * @buf		buffer to which the device path is written
  * @desc	block device descriptor
  * @part	partition number, 0 identifies a block device
  */
@@ -728,7 +729,7 @@
 	/*
 	 * 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
+	 * legacy (i.e. 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.
 	 */
@@ -752,7 +753,7 @@
 	return dp_part_node(buf, desc, part);
 }
 
-/* Construct a device-path from a partition on a blk device: */
+/* Construct a device-path from a partition on a block device: */
 struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part)
 {
 	void *buf, *start;
@@ -771,7 +772,7 @@
 /*
  * Create a device node for a block device partition.
  *
- * @buf		buffer to which the device path is wirtten
+ * @buf		buffer to which the device path is written
  * @desc	block device descriptor
  * @part	partition number, 0 identifies a block device
  */
@@ -791,7 +792,7 @@
 	return buf;
 }
 
-/* convert path to an UEFI style path (ie. DOS style backslashes and utf16) */
+/* convert path to an UEFI style path (i.e. DOS style backslashes and UTF-16) */
 static void path_to_uefi(u16 *uefi, const char *path)
 {
 	while (*path) {
@@ -941,3 +942,53 @@
 	*file_path = fp;
 	return EFI_SUCCESS;
 }
+
+efi_status_t efi_dp_from_name(const char *dev, const char *devnr,
+			      const char *path,
+			      struct efi_device_path **device,
+			      struct efi_device_path **file)
+{
+	int is_net;
+	struct blk_desc *desc = NULL;
+	disk_partition_t fs_partition;
+	int part = 0;
+	char filename[32] = { 0 }; /* dp->str is u16[32] long */
+	char *s;
+
+	if (path && !file)
+		return EFI_INVALID_PARAMETER;
+
+	is_net = !strcmp(dev, "Net");
+	if (!is_net) {
+		part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
+					       1);
+		if (part < 0)
+			return EFI_INVALID_PARAMETER;
+
+		if (device)
+			*device = efi_dp_from_part(desc, part);
+	} else {
+#ifdef CONFIG_NET
+		if (device)
+			*device = efi_dp_from_eth();
+#endif
+	}
+
+	if (!path)
+		return EFI_SUCCESS;
+
+	if (!is_net) {
+		/* Add leading / to fs paths, because they're absolute */
+		snprintf(filename, sizeof(filename), "/%s", path);
+	} else {
+		snprintf(filename, sizeof(filename), "%s", path);
+	}
+	/* DOS style file path: */
+	s = filename;
+	while ((s = strchr(s, '/')))
+		*s++ = '\\';
+	*file = efi_dp_from_file(((!is_net && device) ? desc : NULL),
+				 part, filename);
+
+	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 0082236..e219f84 100644
--- a/lib/efi_loader/efi_device_path_to_text.c
+++ b/lib/efi_loader/efi_device_path_to_text.c
@@ -269,9 +269,9 @@
  * for details.
  *
  * device_node		device node to be converted
- * display_only		true if the shorter text represenation shall be used
+ * display_only		true if the shorter text representation shall be used
  * allow_shortcuts	true if shortcut forms may be used
- * @return		text represenation of the device path
+ * @return		text representation of the device path
  *			NULL if out of memory of device_path is NULL
  */
 static uint16_t EFIAPI *efi_convert_device_node_to_text(
@@ -302,9 +302,9 @@
  * for details.
  *
  * device_path		device path to be converted
- * display_only		true if the shorter text represenation shall be used
+ * display_only		true if the shorter text representation shall be used
  * allow_shortcuts	true if shortcut forms may be used
- * @return		text represenation of the device path
+ * @return		text representation of the device path
  *			NULL if out of memory of device_path is NULL
  */
 static uint16_t EFIAPI *efi_convert_device_path_to_text(
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 13fcc1b..c037526 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -14,26 +14,30 @@
 
 const efi_guid_t efi_block_io_guid = BLOCK_IO_GUID;
 
+/**
+ * struct efi_disk_obj - EFI disk object
+ *
+ * @header:	EFI object header
+ * @ops:	EFI disk I/O protocol interface
+ * @ifname:	interface name for block device
+ * @dev_index:	device index of block device
+ * @media:	block I/O media information
+ * @dp:		device path to the block device
+ * @part:	partition
+ * @volume:	simple file system protocol of the partition
+ * @offset:	offset into disk for simple partition
+ * @desc:	internal block device descriptor
+ */
 struct efi_disk_obj {
-	/* Generic EFI object parent class data */
-	struct efi_object parent;
-	/* EFI Interface callback struct for block I/O */
+	struct efi_object header;
 	struct efi_block_io ops;
-	/* U-Boot ifname for block device */
 	const char *ifname;
-	/* U-Boot dev_index for block device */
 	int dev_index;
-	/* EFI Interface Media descriptor struct, referenced by ops */
 	struct efi_block_io_media media;
-	/* EFI device path to this block device */
 	struct efi_device_path *dp;
-	/* partition # */
 	unsigned int part;
-	/* handle to filesys proto (for partition objects) */
 	struct efi_simple_file_system_protocol *volume;
-	/* Offset into disk for simple partitions */
 	lbaint_t offset;
-	/* Internal block device */
 	struct blk_desc *desc;
 };
 
@@ -246,7 +250,7 @@
 		return EFI_OUT_OF_RESOURCES;
 
 	/* Hook up to the device list */
-	efi_add_handle(&diskobj->parent);
+	efi_add_handle(&diskobj->header);
 
 	/* Fill in object data */
 	if (part) {
@@ -258,18 +262,18 @@
 		diskobj->dp = efi_dp_from_part(desc, part);
 	}
 	diskobj->part = part;
-	ret = efi_add_protocol(diskobj->parent.handle, &efi_block_io_guid,
+	ret = efi_add_protocol(&diskobj->header, &efi_block_io_guid,
 			       &diskobj->ops);
 	if (ret != EFI_SUCCESS)
 		return ret;
-	ret = efi_add_protocol(diskobj->parent.handle, &efi_guid_device_path,
+	ret = efi_add_protocol(&diskobj->header, &efi_guid_device_path,
 			       diskobj->dp);
 	if (ret != EFI_SUCCESS)
 		return ret;
 	if (part >= 1) {
 		diskobj->volume = efi_simple_file_system(desc, part,
 							 diskobj->dp);
-		ret = efi_add_protocol(diskobj->parent.handle,
+		ret = efi_add_protocol(&diskobj->header,
 				       &efi_simple_file_system_protocol_guid,
 				       diskobj->volume);
 		if (ret != EFI_SUCCESS)
@@ -381,7 +385,7 @@
 
 		/* Partitions show up as block devices in EFI */
 		disks += efi_disk_create_partitions(
-					disk->parent.handle, desc, if_typename,
+					&disk->header, desc, if_typename,
 					desc->devnum, dev->name);
 	}
 #else
@@ -426,9 +430,9 @@
 			disks++;
 
 			/* Partitions show up as block devices in EFI */
-			disks += efi_disk_create_partitions(
-						disk->parent.handle, desc,
-						if_typename, i, devname);
+			disks += efi_disk_create_partitions
+						(&disk->header, desc,
+						 if_typename, i, devname);
 		}
 	}
 #endif
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index beb4fba..128cb0a 100644
--- a/lib/efi_loader/efi_file.c
+++ b/lib/efi_loader/efi_file.c
@@ -563,7 +563,7 @@
 		if (fh->isdir)
 			info->attribute |= EFI_FILE_DIRECTORY;
 
-		ascii2unicode((u16 *)info->file_name, filename);
+		ascii2unicode(info->file_name, filename);
 	} else if (!guidcmp(info_type, &efi_file_system_info_guid)) {
 		struct efi_file_system_info *info = buffer;
 		disk_partition_t part;
diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c
index a4aa9bc..d62ce45 100644
--- a/lib/efi_loader/efi_gop.c
+++ b/lib/efi_loader/efi_gop.c
@@ -16,15 +16,22 @@
 
 static const efi_guid_t efi_gop_guid = EFI_GOP_GUID;
 
+/**
+ * struct efi_gop_obj - graphical output protocol object
+ *
+ * @header:	EFI object header
+ * @ops:	graphical output protocol interface
+ * @info:	graphical output mode information
+ * @mode:	graphical output mode
+ * @bpix:	bits per pixel
+ * @fb:		frame buffer
+ */
 struct efi_gop_obj {
-	/* Generic EFI object parent class data */
-	struct efi_object parent;
-	/* EFI Interface callback struct for gop */
+	struct efi_object header;
 	struct efi_gop ops;
-	/* The only mode we support */
 	struct efi_gop_mode_info info;
 	struct efi_gop_mode mode;
-	/* Fields we only have acces to during init */
+	/* Fields we only have access to during init */
 	u32 bpix;
 	void *fb;
 };
@@ -236,12 +243,12 @@
 }
 
 /*
- * Gcc can't optimize our BLT function well, but we need to make sure that
+ * GCC can't optimize our BLT function well, but we need to make sure that
  * our 2-dimensional loop gets executed very quickly, otherwise the system
  * will feel slow.
  *
  * By manually putting all obvious branch targets into functions which call
- * our generic blt function with constants, the compiler can successfully
+ * our generic BLT function with constants, the compiler can successfully
  * optimize for speed.
  */
 static efi_status_t gop_blt_video_fill(struct efi_gop *this,
@@ -439,13 +446,13 @@
 	}
 
 	/* Hook up to the device list */
-	efi_add_handle(&gopobj->parent);
+	efi_add_handle(&gopobj->header);
 
 	/* Fill in object data */
-	ret = efi_add_protocol(gopobj->parent.handle, &efi_gop_guid,
+	ret = efi_add_protocol(&gopobj->header, &efi_gop_guid,
 			       &gopobj->ops);
 	if (ret != EFI_SUCCESS) {
-		printf("ERROR: Failure adding gop protocol\n");
+		printf("ERROR: Failure adding GOP protocol\n");
 		return ret;
 	}
 	gopobj->ops.query_mode = gop_query_mode;
@@ -463,7 +470,10 @@
 	if (bpix == LCD_COLOR32)
 #endif
 	{
-		/* With 32bit color space we can directly expose the fb */
+		/*
+		 * With 32bit color space we can directly expose the frame
+		 * buffer
+		 */
 		gopobj->mode.fb_base = fb_base;
 		gopobj->mode.fb_size = fb_size;
 	}
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 5bd4f4d..4bb5174 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -11,6 +11,7 @@
 #include <mapmem.h>
 #include <watchdog.h>
 #include <linux/list_sort.h>
+#include <linux/sizes.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -294,6 +295,12 @@
 {
 	struct list_head *lhandle;
 
+	/*
+	 * Prealign input max address, so we simplify our matching
+	 * logic below and can just reuse it as return pointer.
+	 */
+	max_addr &= ~EFI_PAGE_MASK;
+
 	list_for_each(lhandle, &efi_mem) {
 		struct efi_mem_list *lmem = list_entry(lhandle,
 			struct efi_mem_list, link);
@@ -378,7 +385,7 @@
 		/* Reserve that map in our memory maps */
 		ret = efi_add_memory_map(addr, pages, memory_type, true);
 		if (ret == addr) {
-			*memory = (uintptr_t)map_sysmem(addr, len);
+			*memory = addr;
 		} else {
 			/* Map would overlap, bail out */
 			r = EFI_OUT_OF_RESOURCES;
@@ -391,7 +398,7 @@
 void *efi_alloc(uint64_t len, int memory_type)
 {
 	uint64_t ret = 0;
-	uint64_t pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+	uint64_t pages = efi_size_in_pages(len);
 	efi_status_t r;
 
 	r = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES, memory_type, pages,
@@ -412,12 +419,11 @@
 efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
 {
 	uint64_t r = 0;
-	uint64_t addr = map_to_sysmem((void *)(uintptr_t)memory);
 
-	r = efi_add_memory_map(addr, pages, EFI_CONVENTIONAL_MEMORY, false);
+	r = efi_add_memory_map(memory, pages, EFI_CONVENTIONAL_MEMORY, false);
 	/* Merging of adjacent free regions is missing */
 
-	if (r == addr)
+	if (r == memory)
 		return EFI_SUCCESS;
 
 	return EFI_NOT_FOUND;
@@ -435,8 +441,8 @@
 {
 	efi_status_t r;
 	struct efi_pool_allocation *alloc;
-	u64 num_pages = (size + sizeof(struct efi_pool_allocation) +
-			 EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+	u64 num_pages = efi_size_in_pages(size +
+					  sizeof(struct efi_pool_allocation));
 
 	if (!buffer)
 		return EFI_INVALID_PARAMETER;
@@ -545,17 +551,51 @@
 
 __weak void efi_add_known_memory(void)
 {
+	u64 ram_top = board_get_usable_ram_top(0) & ~EFI_PAGE_MASK;
 	int i;
 
+	/* Fix for 32bit targets with ram_top at 4G */
+	if (!ram_top)
+		ram_top = 0x100000000ULL;
+
 	/* Add RAM */
 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
-		u64 ram_start = gd->bd->bi_dram[i].start;
-		u64 ram_size = gd->bd->bi_dram[i].size;
-		u64 start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
-		u64 pages = (ram_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+		u64 ram_end, ram_start, pages;
+
+		ram_start = (uintptr_t)map_sysmem(gd->bd->bi_dram[i].start, 0);
+		ram_end = ram_start + gd->bd->bi_dram[i].size;
+
+		/* Remove partial pages */
+		ram_end &= ~EFI_PAGE_MASK;
+		ram_start = (ram_start + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
+
+		if (ram_end <= ram_start) {
+			/* Invalid mapping, keep going. */
+			continue;
+		}
+
+		pages = (ram_end - ram_start) >> EFI_PAGE_SHIFT;
+
+		efi_add_memory_map(ram_start, pages,
+				   EFI_CONVENTIONAL_MEMORY, false);
 
-		efi_add_memory_map(start, pages, EFI_CONVENTIONAL_MEMORY,
-				   false);
+		/*
+		 * Boards may indicate to the U-Boot memory core that they
+		 * can not support memory above ram_top. Let's honor this
+		 * in the efi_loader subsystem too by declaring any memory
+		 * above ram_top as "already occupied by firmware".
+		 */
+		if (ram_top < ram_start) {
+			/* ram_top is before this region, reserve all */
+			efi_add_memory_map(ram_start, pages,
+					   EFI_BOOT_SERVICES_DATA, true);
+		} else if ((ram_top >= ram_start) && (ram_top < ram_end)) {
+			/* ram_top is inside this region, reserve parts */
+			pages = (ram_end - ram_top) >> EFI_PAGE_SHIFT;
+
+			efi_add_memory_map(ram_top, pages,
+					   EFI_BOOT_SERVICES_DATA, true);
+		}
 	}
 }
 
@@ -563,6 +603,7 @@
 static void add_u_boot_and_runtime(void)
 {
 	unsigned long runtime_start, runtime_end, runtime_pages;
+	unsigned long runtime_mask = EFI_PAGE_MASK;
 	unsigned long uboot_start, uboot_pages;
 	unsigned long uboot_stack_size = 16 * 1024 * 1024;
 
@@ -571,10 +612,22 @@
 	uboot_pages = (gd->ram_top - uboot_start) >> EFI_PAGE_SHIFT;
 	efi_add_memory_map(uboot_start, uboot_pages, EFI_LOADER_DATA, false);
 
-	/* Add Runtime Services */
-	runtime_start = (ulong)&__efi_runtime_start & ~EFI_PAGE_MASK;
+#if defined(__aarch64__)
+	/*
+	 * Runtime Services must be 64KiB aligned according to the
+	 * "AArch64 Platforms" section in the UEFI spec (2.7+).
+	 */
+
+	runtime_mask = SZ_64K - 1;
+#endif
+
+	/*
+	 * Add Runtime Services. We mark surrounding boottime code as runtime as
+	 * well to fulfill the runtime alignment constraints but avoid padding.
+	 */
+	runtime_start = (ulong)&__efi_runtime_start & ~runtime_mask;
 	runtime_end = (ulong)&__efi_runtime_stop;
-	runtime_end = (runtime_end + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
+	runtime_end = (runtime_end + runtime_mask) & ~runtime_mask;
 	runtime_pages = (runtime_end - runtime_start) >> EFI_PAGE_SHIFT;
 	efi_add_memory_map(runtime_start, runtime_pages,
 			   EFI_RUNTIME_SERVICES_CODE, false);
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
index 4e8b2d5..c7d9da8 100644
--- a/lib/efi_loader/efi_net.c
+++ b/lib/efi_loader/efi_net.c
@@ -14,6 +14,8 @@
 static struct efi_pxe_packet *dhcp_ack;
 static bool new_rx_packet;
 static void *new_tx_packet;
+static void *transmit_buffer;
+
 /*
  * The notification function of this event is called in every timer cycle
  * to check if a new network packet has been received.
@@ -24,33 +26,85 @@
  */
 static struct efi_event *wait_for_packet;
 
+/**
+ * struct efi_net_obj - EFI object representing a network interface
+ *
+ * @header:	EFI object header
+ * @net:	simple network protocol interface
+ * @net_mode:	status of the network interface
+ * @pxe:	PXE base code protocol interface
+ * @pxe_mode:	status of the PXE base code protocol
+ */
 struct efi_net_obj {
-	/* Generic EFI object parent class data */
-	struct efi_object parent;
-	/* EFI Interface callback struct for network */
+	struct efi_object header;
 	struct efi_simple_network net;
 	struct efi_simple_network_mode net_mode;
-	/* PXE struct to transmit dhcp data */
 	struct efi_pxe pxe;
 	struct efi_pxe_mode pxe_mode;
 };
 
+/*
+ * efi_net_start() - start the network interface
+ *
+ * This function implements the Start service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this:	pointer to the protocol instance
+ * Return:	status code
+ */
 static efi_status_t EFIAPI efi_net_start(struct efi_simple_network *this)
 {
+	efi_status_t ret = EFI_SUCCESS;
+
 	EFI_ENTRY("%p", this);
 
+	/* Check parameters */
+	if (!this) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
-	return EFI_EXIT(EFI_SUCCESS);
+	if (this->mode->state != EFI_NETWORK_STOPPED)
+		ret = EFI_ALREADY_STARTED;
+	else
+		this->mode->state = EFI_NETWORK_STARTED;
+out:
+	return EFI_EXIT(ret);
 }
 
+/*
+ * efi_net_stop() - stop the network interface
+ *
+ * This function implements the Stop service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this:	pointer to the protocol instance
+ * Return:	status code
+ */
 static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this)
 {
+	efi_status_t ret = EFI_SUCCESS;
+
 	EFI_ENTRY("%p", this);
 
-	return EFI_EXIT(EFI_SUCCESS);
+	/* Check parameters */
+	if (!this) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	if (this->mode->state == EFI_NETWORK_STOPPED)
+		ret = EFI_NOT_STARTED;
+	else
+		this->mode->state = EFI_NETWORK_STOPPED;
+out:
+	return EFI_EXIT(ret);
 }
 
 /*
- * Initialize network adapter and allocate transmit and receive buffers.
+ * efi_net_initialize() - initialize the network interface
  *
  * This function implements the Initialize service of the
  * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
@@ -59,7 +113,7 @@
  * @this:	pointer to the protocol instance
  * @extra_rx:	extra receive buffer to be allocated
  * @extra_tx:	extra transmit buffer to be allocated
- * @return:	status code
+ * Return:	status code
  */
 static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this,
 					      ulong extra_rx, ulong extra_tx)
@@ -69,9 +123,10 @@
 
 	EFI_ENTRY("%p, %lx, %lx", this, extra_rx, extra_tx);
 
+	/* Check parameters */
 	if (!this) {
 		r = EFI_INVALID_PARAMETER;
-		goto error;
+		goto out;
 	}
 
 	/* Setup packet buffers */
@@ -84,32 +139,83 @@
 	ret = eth_init();
 	if (ret < 0) {
 		eth_halt();
+		this->mode->state = EFI_NETWORK_STOPPED;
 		r = EFI_DEVICE_ERROR;
+		goto out;
+	} else {
+		this->mode->state = EFI_NETWORK_INITIALIZED;
 	}
-
-error:
+out:
 	return EFI_EXIT(r);
 }
 
+/*
+ * efi_net_reset() - reinitialize the network interface
+ *
+ * This function implements the Reset service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this:			pointer to the protocol instance
+ * @extended_verification:	execute exhaustive verification
+ * Return:			status code
+ */
 static efi_status_t EFIAPI efi_net_reset(struct efi_simple_network *this,
 					 int extended_verification)
 {
 	EFI_ENTRY("%p, %x", this, extended_verification);
 
-	return EFI_EXIT(EFI_SUCCESS);
+	return EFI_EXIT(EFI_CALL(efi_net_initialize(this, 0, 0)));
 }
 
+/*
+ * efi_net_shutdown() - shut down the network interface
+ *
+ * This function implements the Shutdown service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this:	pointer to the protocol instance
+ * Return:	status code
+ */
 static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this)
 {
+	efi_status_t ret = EFI_SUCCESS;
+
 	EFI_ENTRY("%p", this);
 
+	/* Check parameters */
+	if (!this) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
-	return EFI_EXIT(EFI_SUCCESS);
+	eth_halt();
+	this->mode->state = EFI_NETWORK_STOPPED;
+
+out:
+	return EFI_EXIT(ret);
 }
 
-static efi_status_t EFIAPI efi_net_receive_filters(
-		struct efi_simple_network *this, u32 enable, u32 disable,
-		int reset_mcast_filter, ulong mcast_filter_count,
-		struct efi_mac_address *mcast_filter)
+/*
+ * efi_net_receive_filters() - mange multicast receive filters
+ *
+ * This function implements the ReceiveFilters service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this:		pointer to the protocol instance
+ * @enable:		bit mask of receive filters to enable
+ * @disable:		bit mask of receive filters to disable
+ * @reset_mcast_filter:	true resets contents of the filters
+ * @mcast_filter_count:	number of hardware MAC addresses in the new filters list
+ * @mcast_filter:	list of new filters
+ * Return:		status code
+ */
+static efi_status_t EFIAPI efi_net_receive_filters
+		(struct efi_simple_network *this, u32 enable, u32 disable,
+		 int reset_mcast_filter, ulong mcast_filter_count,
+		 struct efi_mac_address *mcast_filter)
 {
 	EFI_ENTRY("%p, %x, %x, %x, %lx, %p", this, enable, disable,
 		  reset_mcast_filter, mcast_filter_count, mcast_filter);
@@ -117,15 +223,40 @@
 	return EFI_EXIT(EFI_UNSUPPORTED);
 }
 
-static efi_status_t EFIAPI efi_net_station_address(
-		struct efi_simple_network *this, int reset,
-		struct efi_mac_address *new_mac)
+/*
+ * efi_net_station_address() - set the hardware MAC address
+ *
+ * This function implements the StationAddress service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this:	pointer to the protocol instance
+ * @reset:	if true reset the address to default
+ * @new_mac:	new MAC address
+ * Return:	status code
+ */
+static efi_status_t EFIAPI efi_net_station_address
+		(struct efi_simple_network *this, int reset,
+		 struct efi_mac_address *new_mac)
 {
 	EFI_ENTRY("%p, %x, %p", this, reset, new_mac);
 
 	return EFI_EXIT(EFI_UNSUPPORTED);
 }
 
+/*
+ * efi_net_statistics() - reset or collect statistics of the network interface
+ *
+ * This function implements the Statistics service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this:	pointer to the protocol instance
+ * @reset:	if true, the statistics are reset
+ * @stat_size:	size of the statistics table
+ * @stat_table:	table to receive the statistics
+ * Return:	status code
+ */
 static efi_status_t EFIAPI efi_net_statistics(struct efi_simple_network *this,
 					      int reset, ulong *stat_size,
 					      void *stat_table)
@@ -135,6 +266,19 @@
 	return EFI_EXIT(EFI_UNSUPPORTED);
 }
 
+/*
+ * efi_net_mcastiptomac() - translate multicast IP address to MAC address
+ *
+ * This function implements the Statistics service of the
+ * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
+ * (UEFI) specification for details.
+ *
+ * @this:	pointer to the protocol instance
+ * @ipv6:	true if the IP address is an IPv6 address
+ * @ip:		IP address
+ * @mac:	MAC address
+ * Return:	status code
+ */
 static efi_status_t EFIAPI efi_net_mcastiptomac(struct efi_simple_network *this,
 						int ipv6,
 						struct efi_ip_address *ip,
@@ -145,6 +289,19 @@
 	return EFI_EXIT(EFI_INVALID_PARAMETER);
 }
 
+/**
+ * efi_net_nvdata() - read or write NVRAM
+ *
+ * This function implements the GetStatus service of the Simple Network
+ * Protocol. See the UEFI spec for details.
+ *
+ * @this:		the instance of the Simple Network Protocol
+ * @readwrite:		true for read, false for write
+ * @offset:		offset in NVRAM
+ * @buffer_size:	size of buffer
+ * @buffer:		buffer
+ * Return:		status code
+ */
 static efi_status_t EFIAPI efi_net_nvdata(struct efi_simple_network *this,
 					  int read_write, ulong offset,
 					  ulong buffer_size, char *buffer)
@@ -155,13 +312,42 @@
 	return EFI_EXIT(EFI_UNSUPPORTED);
 }
 
+/**
+ * efi_net_get_status() - get interrupt status
+ *
+ * This function implements the GetStatus service of the Simple Network
+ * Protocol. See the UEFI spec for details.
+ *
+ * @this:		the instance of the Simple Network Protocol
+ * @int_status:		interface status
+ * @txbuf:		transmission buffer
+ */
 static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this,
 					      u32 *int_status, void **txbuf)
 {
+	efi_status_t ret = EFI_SUCCESS;
+
 	EFI_ENTRY("%p, %p, %p", this, int_status, txbuf);
 
 	efi_timer_check();
 
+	/* Check parameters */
+	if (!this) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	switch (this->mode->state) {
+	case EFI_NETWORK_STOPPED:
+		ret = EFI_NOT_STARTED;
+		goto out;
+	case EFI_NETWORK_STARTED:
+		ret = EFI_DEVICE_ERROR;
+		goto out;
+	default:
+		break;
+	}
+
 	if (int_status) {
 		/* We send packets synchronously, so nothing is outstanding */
 		*int_status = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
@@ -172,65 +358,103 @@
 		*txbuf = new_tx_packet;
 
 	new_tx_packet = NULL;
-
-	return EFI_EXIT(EFI_SUCCESS);
+out:
+	return EFI_EXIT(ret);
 }
 
-static efi_status_t EFIAPI efi_net_transmit(struct efi_simple_network *this,
-		size_t header_size, size_t buffer_size, void *buffer,
-		struct efi_mac_address *src_addr,
-		struct efi_mac_address *dest_addr, u16 *protocol)
+/**
+ * efi_net_transmit() - transmit a packet
+ *
+ * This function implements the Transmit service of the Simple Network Protocol.
+ * See the UEFI spec for details.
+ *
+ * @this:		the instance of the Simple Network Protocol
+ * @header_size:	size of the media header
+ * @buffer_size:	size of the buffer to receive the packet
+ * @buffer:		buffer to receive the packet
+ * @src_addr:		source hardware MAC address
+ * @dest_addr:		destination hardware MAC address
+ * @protocol:		type of header to build
+ * Return:		status code
+ */
+static efi_status_t EFIAPI efi_net_transmit
+		(struct efi_simple_network *this, size_t header_size,
+		 size_t buffer_size, void *buffer,
+		 struct efi_mac_address *src_addr,
+		 struct efi_mac_address *dest_addr, u16 *protocol)
 {
+	efi_status_t ret = EFI_SUCCESS;
+
 	EFI_ENTRY("%p, %lu, %lu, %p, %p, %p, %p", this,
 		  (unsigned long)header_size, (unsigned long)buffer_size,
 		  buffer, src_addr, dest_addr, protocol);
 
 	efi_timer_check();
 
+	/* Check parameters */
+	if (!this) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	/* We do not support jumbo packets */
+	if (buffer_size > PKTSIZE_ALIGN) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
 	if (header_size) {
-		/* We would need to create the header if header_size != 0 */
-		return EFI_EXIT(EFI_INVALID_PARAMETER);
+		/*
+		 * TODO: We would need to create the header
+		 * if header_size != 0
+		 */
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	switch (this->mode->state) {
+	case EFI_NETWORK_STOPPED:
+		ret = EFI_NOT_STARTED;
+		goto out;
+	case EFI_NETWORK_STARTED:
+		ret = EFI_DEVICE_ERROR;
+		goto out;
+	default:
+		break;
 	}
 
-#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
 	/* Ethernet packets always fit, just bounce */
-	memcpy(efi_bounce_buffer, buffer, buffer_size);
-	net_send_packet(efi_bounce_buffer, buffer_size);
-#else
-	net_send_packet(buffer, buffer_size);
-#endif
+	memcpy(transmit_buffer, buffer, buffer_size);
+	net_send_packet(transmit_buffer, buffer_size);
 
 	new_tx_packet = buffer;
 
-	return EFI_EXIT(EFI_SUCCESS);
-}
-
-static void efi_net_push(void *pkt, int len)
-{
-	new_rx_packet = true;
-	wait_for_packet->is_signaled = true;
+out:
+	return EFI_EXIT(ret);
 }
 
-/*
- * Receive a packet from a network interface.
+/**
+ * efi_net_receive() - receive a packet from a network interface
  *
  * This function implements the Receive service of the Simple Network Protocol.
  * See the UEFI spec for details.
  *
- * @this	the instance of the Simple Network Protocol
- * @header_size	size of the media header
- * @buffer_size	size of the buffer to receive the packet
- * @buffer	buffer to receive the packet
- * @src_addr	source MAC address
- * @dest_addr	destination MAC address
- * @protocol	protocol
- * @return	status code
+ * @this:		the instance of the Simple Network Protocol
+ * @header_size:	size of the media header
+ * @buffer_size:	size of the buffer to receive the packet
+ * @buffer:		buffer to receive the packet
+ * @src_addr:		source MAC address
+ * @dest_addr:		destination MAC address
+ * @protocol:		protocol
+ * Return:		status code
  */
-static efi_status_t EFIAPI efi_net_receive(struct efi_simple_network *this,
-		size_t *header_size, size_t *buffer_size, void *buffer,
-		struct efi_mac_address *src_addr,
-		struct efi_mac_address *dest_addr, u16 *protocol)
+static efi_status_t EFIAPI efi_net_receive
+		(struct efi_simple_network *this, size_t *header_size,
+		 size_t *buffer_size, void *buffer,
+		 struct efi_mac_address *src_addr,
+		 struct efi_mac_address *dest_addr, u16 *protocol)
 {
+	efi_status_t ret = EFI_SUCCESS;
 	struct ethernet_hdr *eth_hdr;
 	size_t hdr_size = sizeof(struct ethernet_hdr);
 	u16 protlen;
@@ -238,14 +462,35 @@
 	EFI_ENTRY("%p, %p, %p, %p, %p, %p, %p", this, header_size,
 		  buffer_size, buffer, src_addr, dest_addr, protocol);
 
+	/* Execute events */
 	efi_timer_check();
 
+	/* Check parameters */
+	if (!this) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
+
+	switch (this->mode->state) {
+	case EFI_NETWORK_STOPPED:
+		ret = EFI_NOT_STARTED;
+		goto out;
+	case EFI_NETWORK_STARTED:
+		ret = EFI_DEVICE_ERROR;
+		goto out;
+	default:
+		break;
+	}
+
-	if (!new_rx_packet)
-		return EFI_EXIT(EFI_NOT_READY);
+	if (!new_rx_packet) {
+		ret = EFI_NOT_READY;
+		goto out;
+	}
 	/* Check that we at least received an Ethernet header */
 	if (net_rx_packet_len < sizeof(struct ethernet_hdr)) {
 		new_rx_packet = false;
-		return EFI_EXIT(EFI_NOT_READY);
+		ret = EFI_NOT_READY;
+		goto out;
 	}
 	/* Fill export parameters */
 	eth_hdr = (struct ethernet_hdr *)net_rx_packet;
@@ -263,18 +508,24 @@
 	if (protocol)
 		*protocol = protlen;
 	if (*buffer_size < net_rx_packet_len) {
-		/* Packet doesn't fit, try again with bigger buf */
+		/* Packet doesn't fit, try again with bigger buffer */
 		*buffer_size = net_rx_packet_len;
-		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+		ret = EFI_BUFFER_TOO_SMALL;
+		goto out;
 	}
 	/* Copy packet */
 	memcpy(buffer, net_rx_packet, net_rx_packet_len);
 	*buffer_size = net_rx_packet_len;
 	new_rx_packet = false;
-
-	return EFI_EXIT(EFI_SUCCESS);
+out:
+	return EFI_EXIT(ret);
 }
 
+/**
+ * efi_net_set_dhcp_ack() - take note of a selected DHCP IP address
+ *
+ * This function is called by dhcp_handler().
+ */
 void efi_net_set_dhcp_ack(void *pkt, int len)
 {
 	int maxsize = sizeof(*dhcp_ack);
@@ -285,8 +536,22 @@
 	memcpy(dhcp_ack, pkt, min(len, maxsize));
 }
 
-/*
- * Check if a new network packet has been received.
+/**
+ * efi_net_push() - callback for received network packet
+ *
+ * This function is called when a network packet is received by eth_rx().
+ *
+ * @pkt:	network packet
+ * @len:	length
+ */
+static void efi_net_push(void *pkt, int len)
+{
+	new_rx_packet = true;
+	wait_for_packet->is_signaled = true;
+}
+
+/**
+ * efi_network_timer_notify() - check if a new network packet has been received
  *
  * This notification function is called in every timer cycle.
  *
@@ -296,47 +561,65 @@
 static void EFIAPI efi_network_timer_notify(struct efi_event *event,
 					    void *context)
 {
+	struct efi_simple_network *this = (struct efi_simple_network *)context;
+
 	EFI_ENTRY("%p, %p", event, context);
 
+	/*
+	 * Some network drivers do not support calling eth_rx() before
+	 * initialization.
+	 */
+	if (!this || this->mode->state != EFI_NETWORK_INITIALIZED)
+		goto out;
+
 	if (!new_rx_packet) {
 		push_packet = efi_net_push;
 		eth_rx();
 		push_packet = NULL;
 	}
+out:
 	EFI_EXIT(EFI_SUCCESS);
 }
 
-/* This gets called from do_bootefi_exec(). */
+/**
+ * efi_net_register() - register the simple network protocol
+ *
+ * This gets called from do_bootefi_exec().
+ */
 efi_status_t efi_net_register(void)
 {
-	struct efi_net_obj *netobj;
+	struct efi_net_obj *netobj = NULL;
 	efi_status_t r;
 
 	if (!eth_get_dev()) {
-		/* No eth device active, don't expose any */
+		/* No network device active, don't expose any */
 		return EFI_SUCCESS;
 	}
 
-	/* We only expose the "active" eth device, so one is enough */
+	/* We only expose the "active" network device, so one is enough */
 	netobj = calloc(1, sizeof(*netobj));
-	if (!netobj) {
-		printf("ERROR: Out of memory\n");
-		return EFI_OUT_OF_RESOURCES;
-	}
+	if (!netobj)
+		goto out_of_resources;
+
+	/* Allocate an aligned transmit buffer */
+	transmit_buffer = calloc(1, PKTSIZE_ALIGN + PKTALIGN);
+	if (!transmit_buffer)
+		goto out_of_resources;
+	transmit_buffer = (void *)ALIGN((uintptr_t)transmit_buffer, PKTALIGN);
 
 	/* Hook net up to the device list */
-	efi_add_handle(&netobj->parent);
+	efi_add_handle(&netobj->header);
 
 	/* Fill in object data */
-	r = efi_add_protocol(netobj->parent.handle, &efi_net_guid,
+	r = efi_add_protocol(&netobj->header, &efi_net_guid,
 			     &netobj->net);
 	if (r != EFI_SUCCESS)
 		goto failure_to_add_protocol;
-	r = efi_add_protocol(netobj->parent.handle, &efi_guid_device_path,
+	r = efi_add_protocol(&netobj->header, &efi_guid_device_path,
 			     efi_dp_from_eth());
 	if (r != EFI_SUCCESS)
 		goto failure_to_add_protocol;
-	r = efi_add_protocol(netobj->parent.handle, &efi_pxe_guid,
+	r = efi_add_protocol(&netobj->header, &efi_pxe_guid,
 			     &netobj->pxe);
 	if (r != EFI_SUCCESS)
 		goto failure_to_add_protocol;
@@ -385,13 +668,13 @@
 	 * iPXE is running at TPL_CALLBACK most of the time. Use a higher TPL.
 	 */
 	r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
-			     efi_network_timer_notify, NULL, NULL,
+			     efi_network_timer_notify, &netobj->net, NULL,
 			     &network_timer_event);
 	if (r != EFI_SUCCESS) {
 		printf("ERROR: Failed to register network event\n");
 		return r;
 	}
-	/* Network is time critical, create event in every timer cyle */
+	/* Network is time critical, create event in every timer cycle */
 	r = efi_set_timer(network_timer_event, EFI_TIMER_PERIODIC, 0);
 	if (r != EFI_SUCCESS) {
 		printf("ERROR: Failed to set network timer\n");
@@ -402,4 +685,9 @@
 failure_to_add_protocol:
 	printf("ERROR: Failure to add protocol\n");
 	return r;
+out_of_resources:
+	free(netobj);
+	/* free(transmit_buffer) not needed yet */
+	printf("ERROR: Out of memory\n");
+	return EFI_OUT_OF_RESOURCES;
 }
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index f059dc9..95844ef 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -141,7 +141,9 @@
 		do_reset(NULL, 0, 0, NULL);
 		break;
 	case EFI_RESET_SHUTDOWN:
-		/* We don't have anything to map this to */
+#ifdef CONFIG_CMD_POWEROFF
+		do_poweroff(NULL, 0, 0, NULL);
+#endif
 		break;
 	}
 
@@ -282,7 +284,7 @@
 	}, {
 		/* invalidate_*cache_all are gone */
 		.ptr = &efi_runtime_services.set_virtual_address_map,
-		.patchto = &efi_invalid_parameter,
+		.patchto = &efi_unimplemented,
 	}, {
 		/* RTC accessors are gone */
 		.ptr = &efi_runtime_services.get_time,
@@ -378,6 +380,9 @@
 			ulong symidx = rel->info >> SYM_INDEX;
 			extern struct dyn_sym __dyn_sym_start[];
 			newaddr = __dyn_sym_start[symidx].addr + offset;
+#ifdef IS_RELA
+			newaddr -= CONFIG_SYS_TEXT_BASE;
+#endif
 			break;
 		}
 #endif
@@ -623,8 +628,8 @@
 efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps(
 			struct efi_capsule_header **capsule_header_array,
 			efi_uintn_t capsule_count,
-			u64 maximum_capsule_size,
-			u32 reset_type)
+			u64 *maximum_capsule_size,
+			u32 *reset_type)
 {
 	return EFI_UNSUPPORTED;
 }
diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c
index 38e42fa..a814884 100644
--- a/lib/efi_loader/efi_smbios.c
+++ b/lib/efi_loader/efi_smbios.c
@@ -7,6 +7,7 @@
 
 #include <common.h>
 #include <efi_loader.h>
+#include <mapmem.h>
 #include <smbios.h>
 
 static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
@@ -19,17 +20,19 @@
 efi_status_t efi_smbios_register(void)
 {
 	/* Map within the low 32 bits, to allow for 32bit SMBIOS tables */
-	u64 dmi = U32_MAX;
+	u64 dmi_addr = U32_MAX;
 	efi_status_t ret;
+	void *dmi;
 
 	/* Reserve 4kiB page for SMBIOS */
 	ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
-				 EFI_RUNTIME_SERVICES_DATA, 1, &dmi);
+				 EFI_RUNTIME_SERVICES_DATA, 1, &dmi_addr);
 
 	if (ret != EFI_SUCCESS) {
 		/* Could not find space in lowmem, use highmem instead */
 		ret = efi_allocate_pages(EFI_ALLOCATE_ANY_PAGES,
-					 EFI_RUNTIME_SERVICES_DATA, 1, &dmi);
+					 EFI_RUNTIME_SERVICES_DATA, 1,
+					 &dmi_addr);
 
 		if (ret != EFI_SUCCESS)
 			return ret;
@@ -39,11 +42,14 @@
 	 * Generate SMBIOS tables - we know that efi_allocate_pages() returns
 	 * a 4k-aligned address, so it is safe to assume that
 	 * write_smbios_table() will write the table at that address.
+	 *
+	 * Note that on sandbox, efi_allocate_pages() unfortunately returns a
+	 * pointer even though it uses a uint64_t type. Convert it.
 	 */
-	assert(!(dmi & 0xf));
-	write_smbios_table(dmi);
+	assert(!(dmi_addr & 0xf));
+	dmi = (void *)(uintptr_t)dmi_addr;
+	write_smbios_table(map_to_sysmem(dmi));
 
 	/* And expose them to our EFI payload */
-	return efi_install_configuration_table(&smbios_guid,
-					       (void *)(uintptr_t)dmi);
+	return efi_install_configuration_table(&smbios_guid, dmi);
 }
diff --git a/lib/efi_loader/helloworld.c b/lib/efi_loader/helloworld.c
index 3b8de5b..2905479 100644
--- a/lib/efi_loader/helloworld.c
+++ b/lib/efi_loader/helloworld.c
@@ -17,6 +17,16 @@
 static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID;
 static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
 
+/**
+ * hw_memcmp() - compare memory areas
+ *
+ * @buf1:	pointer to first area
+ * @buf2:	pointer to second area
+ * @length:	number of bytes to compare
+ * Return:	0 if both memory areas are the same, otherwise the sign of the
+ *		result value is the same as the sign of ghe difference between
+ *		the first differing pair of bytes taken as u8.
+ */
 static int hw_memcmp(const void *buf1, const void *buf2, size_t length)
 {
 	const u8 *pos1 = buf1;
@@ -31,12 +41,12 @@
 	return 0;
 }
 
-/*
- * Entry point of the EFI application.
+/**
+ * efi_main() - entry point of the EFI application.
  *
- * @handle	handle of the loaded image
- * @systable	system table
- * @return	status code
+ * @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)
@@ -48,7 +58,8 @@
 	efi_uintn_t i;
 	u16 rev[] = L"0.0.0";
 
-	con_out->output_string(con_out, L"Hello, world!\n");
+	/* UEFI requires CR LF */
+	con_out->output_string(con_out, L"Hello, world!\r\n");
 
 	/* Print the revision number */
 	rev[0] = (systable->hdr.revision >> 16) + '0';
@@ -65,27 +76,30 @@
 
 	con_out->output_string(con_out, L"Running on UEFI ");
 	con_out->output_string(con_out, rev);
-	con_out->output_string(con_out, L"\n");
+	con_out->output_string(con_out, L"\r\n");
 
 	/* Get the loaded image protocol */
 	ret = boottime->handle_protocol(handle, &loaded_image_guid,
 					(void **)&loaded_image);
 	if (ret != EFI_SUCCESS) {
-		con_out->output_string(con_out,
-				       L"Cannot open loaded image protocol\n");
+		con_out->output_string
+			(con_out, L"Cannot open loaded image protocol\r\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");
+			con_out->output_string
+					(con_out, L"Have device tree\r\n");
 		if (!hw_memcmp(&systable->tables[i].guid, &acpi_guid,
 			       sizeof(efi_guid_t)))
-			con_out->output_string(con_out, L"Have ACPI 2.0 table\n");
+			con_out->output_string
+					(con_out, L"Have ACPI 2.0 table\r\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");
+			con_out->output_string
+					(con_out, L"Have SMBIOS table\r\n");
 	}
 	/* Output the load options */
 	con_out->output_string(con_out, L"Load options: ");
@@ -94,7 +108,7 @@
 				       (u16 *)loaded_image->load_options);
 	else
 		con_out->output_string(con_out, L"<none>");
-	con_out->output_string(con_out, L"\n");
+	con_out->output_string(con_out, L"\r\n");
 
 out:
 	boottime->exit(handle, ret, 0, NULL);
diff --git a/lib/efi_selftest/Kconfig b/lib/efi_selftest/Kconfig
index b526967..59f9f36 100644
--- a/lib/efi_selftest/Kconfig
+++ b/lib/efi_selftest/Kconfig
@@ -1,6 +1,6 @@
 config CMD_BOOTEFI_SELFTEST
 	bool "Allow booting an EFI efi_selftest"
-	depends on CMD_BOOTEFI && !SANDBOX
+	depends on CMD_BOOTEFI
 	imply FAT
 	imply FAT_WRITE
 	help
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 2f55d9d..743b482 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -10,7 +10,7 @@
 CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding
 CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI) -Os
 
-obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += \
+obj-y += \
 efi_selftest.o \
 efi_selftest_bitblt.o \
 efi_selftest_config_table.o \
@@ -21,11 +21,13 @@
 efi_selftest_devicepath_util.o \
 efi_selftest_events.o \
 efi_selftest_event_groups.o \
+efi_selftest_exception.o \
 efi_selftest_exitbootservices.o \
 efi_selftest_fdt.o \
 efi_selftest_gop.o \
 efi_selftest_loaded_image.o \
 efi_selftest_manageprotocols.o \
+efi_selftest_memory.o \
 efi_selftest_rtc.o \
 efi_selftest_snp.o \
 efi_selftest_textinput.o \
@@ -37,20 +39,16 @@
 efi_selftest_variables.o \
 efi_selftest_watchdog.o
 
-ifeq ($(CONFIG_CMD_BOOTEFI_SELFTEST),y)
 obj-$(CONFIG_CPU_V7) += efi_selftest_unaligned.o
-endif
 
 ifeq ($(CONFIG_BLK)$(CONFIG_PARTITIONS),yy)
-obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest_block_device.o
+obj-y += 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)$(CONFIG_SANDBOX),)
 
-ifneq ($(CONFIG_CMD_BOOTEFI_SELFTEST),)
-
 obj-y += \
 efi_selftest_startimage_exit.o \
 efi_selftest_startimage_return.o
@@ -74,5 +72,3 @@
 $(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 dd338db..5b01610 100644
--- a/lib/efi_selftest/efi_selftest.c
+++ b/lib/efi_selftest/efi_selftest.c
@@ -18,6 +18,7 @@
 static const struct efi_runtime_services *runtime;
 static efi_handle_t handle;
 static u16 reset_message[] = L"Selftest completed";
+static int *setup_status;
 
 /*
  * Exit the boot services.
@@ -74,20 +75,20 @@
  */
 static int setup(struct efi_unit_test *test, unsigned int *failures)
 {
-	if (!test->setup) {
-		test->setup_ok = EFI_ST_SUCCESS;
+	int ret;
+
+	if (!test->setup)
 		return EFI_ST_SUCCESS;
-	}
 	efi_st_printc(EFI_LIGHTBLUE, "\nSetting up '%s'\n", test->name);
-	test->setup_ok = test->setup(handle, systable);
-	if (test->setup_ok != EFI_ST_SUCCESS) {
+	ret = test->setup(handle, systable);
+	if (ret != EFI_ST_SUCCESS) {
 		efi_st_error("Setting up '%s' failed\n", test->name);
 		++*failures;
 	} else {
 		efi_st_printc(EFI_LIGHTGREEN,
 			      "Setting up '%s' succeeded\n", test->name);
 	}
-	return test->setup_ok;
+	return ret;
 }
 
 /*
@@ -186,18 +187,20 @@
 void efi_st_do_tests(const u16 *testname, unsigned int phase,
 		     unsigned int steps, unsigned int *failures)
 {
+	int i = 0;
 	struct efi_unit_test *test;
 
 	for (test = ll_entry_start(struct efi_unit_test, efi_unit_test);
-	     test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) {
+	     test < ll_entry_end(struct efi_unit_test, efi_unit_test);
+	     ++test, ++i) {
 		if (testname ?
 		    efi_st_strcmp_16_8(testname, test->name) : test->on_request)
 			continue;
 		if (test->phase != phase)
 			continue;
 		if (steps & EFI_ST_SETUP)
-			setup(test, failures);
-		if (steps & EFI_ST_EXECUTE && test->setup_ok == EFI_ST_SUCCESS)
+			setup_status[i] = setup(test, failures);
+		if (steps & EFI_ST_EXECUTE && setup_status[i] == EFI_ST_SUCCESS)
 			execute(test, failures);
 		if (steps & EFI_ST_TEARDOWN)
 			teardown(test, failures);
@@ -271,6 +274,16 @@
 			      ll_entry_count(struct efi_unit_test,
 					     efi_unit_test));
 
+	/* Allocate buffer for setup results */
+	ret = boottime->allocate_pool(EFI_RUNTIME_SERVICES_DATA, sizeof(int) *
+				      ll_entry_count(struct efi_unit_test,
+						     efi_unit_test),
+				      (void **)&setup_status);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Allocate pool failed\n");
+		return ret;
+	}
+
 	/* Execute boottime tests */
 	efi_st_do_tests(testname, EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
 			EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN,
diff --git a/lib/efi_selftest/efi_selftest_config_table.c b/lib/efi_selftest/efi_selftest_config_table.c
index 2aa3fc7..0bc5da6 100644
--- a/lib/efi_selftest/efi_selftest_config_table.c
+++ b/lib/efi_selftest/efi_selftest_config_table.c
@@ -18,7 +18,7 @@
 		 0x17, 0x2e, 0x51, 0x6b, 0x49, 0x75);
 
 /*
- * Notification function, increments the notfication count if parameter
+ * Notification function, increments the notification count if parameter
  * context is provided.
  *
  * @event	notified event
@@ -33,23 +33,23 @@
 }
 
 /*
- * Check crc32 of a table.
+ * Check CRC32 of a table.
  */
 static int check_table(const void *table)
 {
 	efi_status_t ret;
 	u32 crc32, res;
-	/* Casting from const to not const */
+	/* Casting from constant to not constant */
 	struct efi_table_hdr *hdr = (struct efi_table_hdr *)table;
 
 	crc32 = hdr->crc32;
 	/*
-	 * Setting the crc32 of the 'const' table to zero is easier than
+	 * Setting the CRC32 of the 'const' table to zero is easier than
 	 * copying
 	 */
 	hdr->crc32 = 0;
 	ret = boottime->calculate_crc32(table, hdr->headersize, &res);
-	/* Reset table crc32 so it stays constant */
+	/* Reset table CRC32 so it stays constant */
 	hdr->crc32 = crc32;
 	if (ret != EFI_ST_SUCCESS) {
 		efi_st_error("CalculateCrc32 failed\n");
@@ -203,7 +203,7 @@
 		return EFI_ST_FAILURE;
 	}
 	if (tabcnt > 1) {
-		efi_st_error("Duplicate table guid\n");
+		efi_st_error("Duplicate table GUID\n");
 		return EFI_ST_FAILURE;
 	}
 	if (table != &tables[1]) {
diff --git a/lib/efi_selftest/efi_selftest_controllers.c b/lib/efi_selftest/efi_selftest_controllers.c
index d08c377..38720bb 100644
--- a/lib/efi_selftest/efi_selftest_controllers.c
+++ b/lib/efi_selftest/efi_selftest_controllers.c
@@ -33,7 +33,7 @@
  * Count child controllers
  *
  * @handle	handle on which child controllers are installed
- * @protocol	protocol for which the child controlles where installed
+ * @protocol	protocol for which the child controllers were installed
  * @count	number of child controllers
  * @return	status code
  */
diff --git a/lib/efi_selftest/efi_selftest_crc32.c b/lib/efi_selftest/efi_selftest_crc32.c
index 8555b8f..4881e8a 100644
--- a/lib/efi_selftest/efi_selftest_crc32.c
+++ b/lib/efi_selftest/efi_selftest_crc32.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
  *
  * This unit test checks the CalculateCrc32 bootservice and checks the
- * headers of the system table, the boot services tablle, and the runtime
+ * headers of the system table, the boot services table, and the runtime
  * services table before and after ExitBootServices().
  */
 
@@ -19,7 +19,7 @@
 {
 	efi_status_t ret;
 	u32 crc32, res;
-	/* Casting from const to not const */
+	/* Casting from constant to not constant */
 	struct efi_table_hdr *hdr = (struct efi_table_hdr *)table;
 
 	if (!hdr->signature) {
diff --git a/lib/efi_selftest/efi_selftest_devicepath.c b/lib/efi_selftest/efi_selftest_devicepath.c
index adcf531..105ce2c 100644
--- a/lib/efi_selftest/efi_selftest_devicepath.c
+++ b/lib/efi_selftest/efi_selftest_devicepath.c
@@ -257,7 +257,7 @@
 static int execute(void)
 {
 	struct efi_device_path *remaining_dp;
-	void *handle;
+	efi_handle_t handle;
 	/*
 	 * This device path node ends with the letter 't' of 'u-boot'.
 	 * The following '.bin' does not belong to the node but is
diff --git a/lib/efi_selftest/efi_selftest_event_groups.c b/lib/efi_selftest/efi_selftest_event_groups.c
index 9b3c513..5a7980c 100644
--- a/lib/efi_selftest/efi_selftest_event_groups.c
+++ b/lib/efi_selftest/efi_selftest_event_groups.c
@@ -19,7 +19,7 @@
 		 0x0e, 0x5b, 0x45, 0xc0, 0x56, 0x91);
 
 /*
- * Notification function, increments the notfication count if parameter
+ * Notification function, increments the notification count if parameter
  * context is provided.
  *
  * @event	notified event
@@ -114,7 +114,7 @@
 					      (unsigned int)i, (unsigned int)j,
 					      (unsigned int)counter[j]);
 				efi_st_error(
-					"Nofification function not called\n");
+					"Notification function not called\n");
 				return EFI_ST_FAILURE;
 			}
 		}
diff --git a/lib/efi_selftest/efi_selftest_events.c b/lib/efi_selftest/efi_selftest_events.c
index 47f9f99..ed99a53 100644
--- a/lib/efi_selftest/efi_selftest_events.c
+++ b/lib/efi_selftest/efi_selftest_events.c
@@ -17,7 +17,7 @@
 static struct efi_boot_services *boottime;
 
 /*
- * Notification function, increments the notfication count if parameter
+ * Notification function, increments the notification count if parameter
  * context is provided.
  *
  * @event	notified event
diff --git a/lib/efi_selftest/efi_selftest_exception.c b/lib/efi_selftest/efi_selftest_exception.c
new file mode 100644
index 0000000..76cfb88
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_exception.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_exception
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Test the handling of exceptions by trying to execute an undefined
+ * instruction.
+ */
+
+#include <efi_selftest.h>
+
+/**
+ * undefined_instruction() - try to executed an undefined instruction
+ */
+static void undefined_instruction(void)
+{
+#if defined(CONFIG_ARM)
+	/*
+	 * 0xe7f...f.	is undefined in ARM mode
+	 * 0xde..	is undefined in Thumb mode
+	 */
+	asm volatile (".word 0xe7f7defb\n");
+#elif defined(CONFIG_RISCV)
+	asm volatile (".word 0xffffffff\n");
+#elif defined(CONFIG_X86)
+	asm volatile (".word 0xffff\n");
+#endif
+}
+
+/**
+ * execute() - execute unit test
+ *
+ * Return:	EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+	undefined_instruction();
+
+	efi_st_error("An undefined instruction exception was not raised\n");
+
+	return EFI_ST_FAILURE;
+}
+
+EFI_UNIT_TEST(exception) = {
+	.name = "exception",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.execute = execute,
+	.on_request = true,
+};
diff --git a/lib/efi_selftest/efi_selftest_fdt.c b/lib/efi_selftest/efi_selftest_fdt.c
index c7bc242..d545d51 100644
--- a/lib/efi_selftest/efi_selftest_fdt.c
+++ b/lib/efi_selftest/efi_selftest_fdt.c
@@ -16,7 +16,7 @@
 static struct efi_boot_services *boottime;
 static const char *fdt;
 
-/* This should be sufficent for */
+/* This should be sufficient for */
 #define BUFFERSIZE 0x100000
 
 static efi_guid_t fdt_guid = EFI_FDT_GUID;
diff --git a/lib/efi_selftest/efi_selftest_loaded_image.c b/lib/efi_selftest/efi_selftest_loaded_image.c
index f9b54ae..ea2b380 100644
--- a/lib/efi_selftest/efi_selftest_loaded_image.c
+++ b/lib/efi_selftest/efi_selftest_loaded_image.c
@@ -53,7 +53,7 @@
 		efi_st_error("ProtocolsPerHandle failed\n");
 		return EFI_ST_FAILURE;
 	}
-	if (!protocol_buffer_count | !protocol_buffer) {
+	if (!protocol_buffer_count || !protocol_buffer) {
 		efi_st_error("ProtocolsPerHandle returned no protocol\n");
 		return EFI_ST_FAILURE;
 	}
diff --git a/lib/efi_selftest/efi_selftest_manageprotocols.c b/lib/efi_selftest/efi_selftest_manageprotocols.c
index b09e4cd..0ff35ce 100644
--- a/lib/efi_selftest/efi_selftest_manageprotocols.c
+++ b/lib/efi_selftest/efi_selftest_manageprotocols.c
@@ -189,7 +189,14 @@
 	/*
 	 * Test error handling in UninstallMultipleProtocols
 	 *
-	 * Try to uninstall more protocols than there are installed.
+	 * These are the installed protocol interfaces on handle 2:
+	 *
+	 *   guid1 interface4
+	 *   guid2 interface2
+	 *
+	 * Try to uninstall more protocols than there are installed. This
+	 * should return an error EFI_INVALID_PARAMETER. All deleted protocols
+	 * should be reinstalled.
 	 */
 	ret = boottime->uninstall_multiple_protocol_interfaces(
 						handle2,
@@ -197,13 +204,18 @@
 						&guid2, &interface2,
 						&guid3, &interface3,
 						NULL);
-	if (ret == EFI_SUCCESS) {
+	if (ret != EFI_INVALID_PARAMETER) {
+		printf("%lx", ret);
 		efi_st_error("UninstallMultipleProtocolInterfaces did not catch error\n");
 		return EFI_ST_FAILURE;
 	}
 
 	/*
 	 * Test LocateHandleBuffer with ByProtocol
+	 *
+	 * These are the handles with a guid1 protocol interface installed:
+	 *
+	 *	handle1, handle2
 	 */
 	count = buffer_size;
 	ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL,
@@ -213,7 +225,7 @@
 		return EFI_ST_FAILURE;
 	}
 	if (count != 2) {
-		efi_st_error("LocateHandleBuffer failed to locate new handles\n");
+		efi_st_error("UninstallMultipleProtocolInterfaces deleted handle\n");
 		return EFI_ST_FAILURE;
 	}
 	ret = find_in_buffer(handle1, count, buffer);
diff --git a/lib/efi_selftest/efi_selftest_memory.c b/lib/efi_selftest/efi_selftest_memory.c
new file mode 100644
index 0000000..24b4438
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_memory.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_memory
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This unit test checks the following runtime services:
+ * AllocatePages, FreePages, GetMemoryMap
+ *
+ * The memory type used for the device tree is checked.
+ */
+
+#include <efi_selftest.h>
+
+#define EFI_ST_NUM_PAGES 8
+
+static const efi_guid_t fdt_guid = EFI_FDT_GUID;
+static struct efi_boot_services *boottime;
+static u64 fdt_addr;
+
+/**
+ * setup() - 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)
+{
+	size_t i;
+
+	boottime = systable->boottime;
+
+	for (i = 0; i < systable->nr_tables; ++i) {
+		if (!efi_st_memcmp(&systable->tables[i].guid, &fdt_guid,
+				   sizeof(efi_guid_t))) {
+			if (fdt_addr) {
+				efi_st_error("Duplicate device tree\n");
+				return EFI_ST_FAILURE;
+			}
+			fdt_addr = (uintptr_t)systable->tables[i].table;
+		}
+	}
+	return EFI_ST_SUCCESS;
+}
+
+/**
+ * find_in_memory_map() - check matching memory map entry exists
+ *
+ * @memory_map:		memory map
+ * @desc_size:		number of memory map entries
+ * @addr:		physical address to find in the map
+ * @type:		expected memory type
+ * Return:		EFI_ST_SUCCESS for success
+ */
+static int find_in_memory_map(efi_uintn_t map_size,
+			      struct efi_mem_desc *memory_map,
+			      efi_uintn_t desc_size,
+			      u64 addr, int memory_type)
+{
+	efi_uintn_t i;
+	bool found = false;
+
+	for (i = 0; map_size; ++i, map_size -= desc_size) {
+		struct efi_mem_desc *entry = &memory_map[i];
+
+		if (addr >= entry->physical_start &&
+		    addr < entry->physical_start +
+			    (entry->num_pages << EFI_PAGE_SHIFT)) {
+			if (found) {
+				efi_st_error("Duplicate memory map entry\n");
+				return EFI_ST_FAILURE;
+			}
+			found = true;
+			if (memory_type != entry->type) {
+				efi_st_error
+					("Wrong memory type %d, expected %d\n",
+					 entry->type, memory_type);
+				return EFI_ST_FAILURE;
+			}
+		}
+	}
+	if (!found) {
+		efi_st_error("Missing memory map entry\n");
+		return EFI_ST_FAILURE;
+	}
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * execute() - execute unit test
+ *
+ * Return:	EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+	u64 p1;
+	u64 p2;
+	efi_uintn_t map_size = 0;
+	efi_uintn_t map_key;
+	efi_uintn_t desc_size;
+	u32 desc_version;
+	struct efi_mem_desc *memory_map;
+	efi_status_t ret;
+
+	/* Allocate two page ranges with different memory type */
+	ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				       EFI_RUNTIME_SERVICES_CODE,
+				       EFI_ST_NUM_PAGES, &p1);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("AllocatePages did not return EFI_SUCCESS\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+				       EFI_RUNTIME_SERVICES_DATA,
+				       EFI_ST_NUM_PAGES, &p2);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("AllocatePages did not return EFI_SUCCESS\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* Load memory map */
+	ret = boottime->get_memory_map(&map_size, NULL, &map_key, &desc_size,
+				       &desc_version);
+	if (ret != EFI_BUFFER_TOO_SMALL) {
+		efi_st_error
+			("GetMemoryMap did not return EFI_BUFFER_TOO_SMALL\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Allocate extra space for newly allocated memory */
+	map_size += sizeof(struct efi_mem_desc);
+	ret = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, map_size,
+				      (void **)&memory_map);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("AllocatePool did not return EFI_SUCCESS\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->get_memory_map(&map_size, memory_map, &map_key,
+				       &desc_size, &desc_version);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("GetMemoryMap did not return EFI_SUCCESS\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* Check memory map entries */
+	if (find_in_memory_map(map_size, memory_map, desc_size, p1,
+			       EFI_RUNTIME_SERVICES_CODE) != EFI_ST_SUCCESS)
+		return EFI_ST_FAILURE;
+	if (find_in_memory_map(map_size, memory_map, desc_size, p2,
+			       EFI_RUNTIME_SERVICES_DATA) != EFI_ST_SUCCESS)
+		return EFI_ST_FAILURE;
+
+	/* Free memory */
+	ret = boottime->free_pages(p1, EFI_ST_NUM_PAGES);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("FreePages did not return EFI_SUCCESS\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->free_pages(p2, EFI_ST_NUM_PAGES);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("FreePages did not return EFI_SUCCESS\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->free_pool(memory_map);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("FreePool did not return EFI_SUCCESS\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* Check memory reservation for the device tree */
+	if (fdt_addr &&
+	    find_in_memory_map(map_size, memory_map, desc_size, fdt_addr,
+			       EFI_RUNTIME_SERVICES_DATA) != EFI_ST_SUCCESS) {
+		efi_st_error
+			("Device tree not marked as runtime services data\n");
+		return EFI_ST_FAILURE;
+	}
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(memory) = {
+	.name = "memory",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+};
diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c
index 09bd53d..e10a34b 100644
--- a/lib/efi_selftest/efi_selftest_snp.c
+++ b/lib/efi_selftest/efi_selftest_snp.c
@@ -103,7 +103,7 @@
 	struct dhcp p = {};
 
 	/*
-	 * Fill ethernet header
+	 * Fill Ethernet header
 	 */
 	boottime->copy_mem(p.eth_hdr.et_dest, (void *)BROADCAST_MAC, ARP_HLEN);
 	boottime->copy_mem(p.eth_hdr.et_src, &net->mode->current_address,
@@ -229,19 +229,19 @@
 		return EFI_ST_FAILURE;
 	}
 	/*
-	 * Initialize network adapter.
+	 * Start network adapter.
 	 */
-	ret = net->initialize(net, 0, 0);
-	if (ret != EFI_SUCCESS) {
-		efi_st_error("Failed to initialize network adapter\n");
+	ret = net->start(net);
+	if (ret != EFI_SUCCESS && ret != EFI_ALREADY_STARTED) {
+		efi_st_error("Failed to start network adapter\n");
 		return EFI_ST_FAILURE;
 	}
 	/*
-	 * Start network adapter.
+	 * Initialize network adapter.
 	 */
-	ret = net->start(net);
+	ret = net->initialize(net, 0, 0);
 	if (ret != EFI_SUCCESS) {
-		efi_st_error("Failed to start network adapter\n");
+		efi_st_error("Failed to initialize network adapter\n");
 		return EFI_ST_FAILURE;
 	}
 	return EFI_ST_SUCCESS;
diff --git a/lib/efi_selftest/efi_selftest_textinput.c b/lib/efi_selftest/efi_selftest_textinput.c
index 164fbff..b90671c 100644
--- a/lib/efi_selftest/efi_selftest_textinput.c
+++ b/lib/efi_selftest/efi_selftest_textinput.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
  *
  * Provides a unit test for the EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
- * The unicode character and the scan code are printed for text
+ * The Unicode character and the scan code are printed for text
  * input. To run the test:
  *
  *	setenv efi_selftest text input
diff --git a/lib/efi_selftest/efi_selftest_tpl.c b/lib/efi_selftest/efi_selftest_tpl.c
index 61ae46b..97d256a 100644
--- a/lib/efi_selftest/efi_selftest_tpl.c
+++ b/lib/efi_selftest/efi_selftest_tpl.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * efi_selftest_events
+ * efi_selftest_tpl
  *
  * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
  *
diff --git a/lib/efi_selftest/efi_selftest_unicode_collation.c b/lib/efi_selftest/efi_selftest_unicode_collation.c
index 9765bd3..7529430 100644
--- a/lib/efi_selftest/efi_selftest_unicode_collation.c
+++ b/lib/efi_selftest/efi_selftest_unicode_collation.c
@@ -52,7 +52,7 @@
 						    c1, c2);
 	if (ret) {
 		efi_st_error(
-			"stri_coll(\"%ps\", \"%ps\") = %zu\n", c1, c2, ret);
+			"stri_coll(\"%ps\", \"%ps\") = %d\n", c1, c2, (int)ret);
 		return EFI_ST_FAILURE;
 	}
 
@@ -60,7 +60,7 @@
 						    c1, c3);
 	if (ret >= 0) {
 		efi_st_error(
-			"stri_coll(\"%ps\", \"%ps\") = %zu\n", c1, c3, ret);
+			"stri_coll(\"%ps\", \"%ps\") = %d\n", c1, c3, (int)ret);
 		return EFI_ST_FAILURE;
 	}
 
@@ -68,7 +68,7 @@
 						    c3, c1);
 	if (ret <= 0) {
 		efi_st_error(
-			"stri_coll(\"%ps\", \"%ps\") = %zu\n", c3, c1, ret);
+			"stri_coll(\"%ps\", \"%ps\") = %d\n", c3, c1, (int)ret);
 		return EFI_ST_FAILURE;
 	}
 
diff --git a/lib/efi_selftest/efi_selftest_variables.c b/lib/efi_selftest/efi_selftest_variables.c
index 146378f..e4c389a 100644
--- a/lib/efi_selftest/efi_selftest_variables.c
+++ b/lib/efi_selftest/efi_selftest_variables.c
@@ -4,10 +4,8 @@
  *
  * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
  *
- * This unit test checks the following protocol services:
- * ConnectController, DisconnectController,
- * InstallProtocol, ReinstallProtocol, UninstallProtocol,
- * OpenProtocol, CloseProtcol, OpenProtocolInformation
+ * This unit test checks the runtime services for variables:
+ * GetVariable, GetNextVariableName, SetVariable, QueryVariableInfo.
  */
 
 #include <efi_selftest.h>
diff --git a/lib/efi_selftest/efi_selftest_watchdog.c b/lib/efi_selftest/efi_selftest_watchdog.c
index bff2330..cbc6761 100644
--- a/lib/efi_selftest/efi_selftest_watchdog.c
+++ b/lib/efi_selftest/efi_selftest_watchdog.c
@@ -35,7 +35,7 @@
 static bool watchdog_reset;
 
 /*
- * Notification function, increments the notfication count if parameter
+ * Notification function, increments the notification count if parameter
  * context is provided.
  *
  * @event	notified event
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index d28f2cb..cbdc077 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -11,6 +11,7 @@
 #include <errno.h>
 #include <fdtdec.h>
 #include <fdt_support.h>
+#include <mapmem.h>
 #include <linux/libfdt.h>
 #include <serial.h>
 #include <asm/sections.h>
@@ -1253,8 +1254,9 @@
 #  if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
 	gd->fdt_blob = (void *)prior_stage_fdt_address;
 #  else
-	gd->fdt_blob = (void *)env_get_ulong("fdtcontroladdr", 16,
-						(uintptr_t)gd->fdt_blob);
+	gd->fdt_blob = map_sysmem
+		(env_get_ulong("fdtcontroladdr", 16,
+			       (unsigned long)map_to_sysmem(gd->fdt_blob)), 0);
 #  endif
 # endif
 
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
index 05ac67b..fb5e07b 100644
--- a/lib/rsa/rsa-sign.c
+++ b/lib/rsa/rsa-sign.c
@@ -387,13 +387,16 @@
 	}
 }
 
-static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
+static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo,
+			     struct checksum_algo *checksum_algo,
 		const struct image_region region[], int region_count,
 		uint8_t **sigp, uint *sig_size)
 {
 	EVP_PKEY *key;
+	EVP_PKEY_CTX *ckey;
 	EVP_MD_CTX *context;
-	int size, ret = 0;
+	int ret = 0;
+	size_t size;
 	uint8_t *sig;
 	int i;
 
@@ -409,7 +412,7 @@
 	size = EVP_PKEY_size(key);
 	sig = malloc(size);
 	if (!sig) {
-		fprintf(stderr, "Out of memory for signature (%d bytes)\n",
+		fprintf(stderr, "Out of memory for signature (%zu bytes)\n",
 			size);
 		ret = -ENOMEM;
 		goto err_alloc;
@@ -421,22 +424,43 @@
 		goto err_create;
 	}
 	EVP_MD_CTX_init(context);
-	if (!EVP_SignInit(context, checksum_algo->calculate_sign())) {
+
+	ckey = EVP_PKEY_CTX_new(key, NULL);
+	if (!ckey) {
+		ret = rsa_err("EVP key context creation failed");
+		goto err_create;
+	}
+
+	if (EVP_DigestSignInit(context, &ckey,
+			       checksum_algo->calculate_sign(),
+			       NULL, key) <= 0) {
 		ret = rsa_err("Signer setup failed");
 		goto err_sign;
 	}
 
+#ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
+	if (padding_algo && !strcmp(padding_algo->name, "pss")) {
+		if (EVP_PKEY_CTX_set_rsa_padding(ckey,
+						 RSA_PKCS1_PSS_PADDING) <= 0) {
+			ret = rsa_err("Signer padding setup failed");
+			goto err_sign;
+		}
+	}
+#endif /* CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT */
+
 	for (i = 0; i < region_count; i++) {
-		if (!EVP_SignUpdate(context, region[i].data, region[i].size)) {
+		if (!EVP_DigestSignUpdate(context, region[i].data,
+					  region[i].size)) {
 			ret = rsa_err("Signing data failed");
 			goto err_sign;
 		}
 	}
 
-	if (!EVP_SignFinal(context, sig, sig_size, key)) {
+	if (!EVP_DigestSignFinal(context, sig, &size)) {
 		ret = rsa_err("Could not obtain signature");
 		goto err_sign;
 	}
+
 	#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
 		(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
 		EVP_MD_CTX_cleanup(context);
@@ -446,7 +470,7 @@
 	EVP_MD_CTX_destroy(context);
 	EVP_PKEY_free(key);
 
-	debug("Got signature: %d bytes, expected %d\n", *sig_size, size);
+	debug("Got signature: %d bytes, expected %zu\n", *sig_size, size);
 	*sigp = sig;
 	*sig_size = size;
 
@@ -483,7 +507,7 @@
 	ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa);
 	if (ret)
 		goto err_priv;
-	ret = rsa_sign_with_key(rsa, info->checksum, region,
+	ret = rsa_sign_with_key(rsa, info->padding, info->checksum, region,
 				region_count, sigp, sig_len);
 	if (ret)
 		goto err_sign;
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
index bc83354..9734f6d 100644
--- a/lib/rsa/rsa-verify.c
+++ b/lib/rsa/rsa-verify.c
@@ -57,31 +57,247 @@
 	return ret;
 }
 
+int padding_pkcs_15_verify(struct image_sign_info *info,
+			   uint8_t *msg, int msg_len,
+			   const uint8_t *hash, int hash_len)
+{
+	struct checksum_algo *checksum = info->checksum;
+	int ret, pad_len = msg_len - checksum->checksum_len;
+
+	/* Check pkcs1.5 padding bytes. */
+	ret = rsa_verify_padding(msg, pad_len, checksum);
+	if (ret) {
+		debug("In RSAVerify(): Padding check failed!\n");
+		return -EINVAL;
+	}
+
+	/* Check hash. */
+	if (memcmp((uint8_t *)msg + pad_len, hash, msg_len - pad_len)) {
+		debug("In RSAVerify(): Hash check failed!\n");
+		return -EACCES;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
+static void u32_i2osp(uint32_t val, uint8_t *buf)
+{
+	buf[0] = (uint8_t)((val >> 24) & 0xff);
+	buf[1] = (uint8_t)((val >> 16) & 0xff);
+	buf[2] = (uint8_t)((val >>  8) & 0xff);
+	buf[3] = (uint8_t)((val >>  0) & 0xff);
+}
+
+/**
+ * mask_generation_function1() - generate an octet string
+ *
+ * Generate an octet string used to check rsa signature.
+ * It use an input octet string and a hash function.
+ *
+ * @checksum:	A Hash function
+ * @seed:	Specifies an input variable octet string
+ * @seed_len:	Size of the input octet string
+ * @output:	Specifies the output octet string
+ * @output_len:	Size of the output octet string
+ * @return 0 if the octet string was correctly generated, others on error
+ */
+static int mask_generation_function1(struct checksum_algo *checksum,
+				     uint8_t *seed, int seed_len,
+				     uint8_t *output, int output_len)
+{
+	struct image_region region[2];
+	int ret = 0, i, i_output = 0, region_count = 2;
+	uint32_t counter = 0;
+	uint8_t buf_counter[4], *tmp;
+	int hash_len = checksum->checksum_len;
+
+	memset(output, 0, output_len);
+
+	region[0].data = seed;
+	region[0].size = seed_len;
+	region[1].data = &buf_counter[0];
+	region[1].size = 4;
+
+	tmp = malloc(hash_len);
+	if (!tmp) {
+		debug("%s: can't allocate array tmp\n", __func__);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	while (i_output < output_len) {
+		u32_i2osp(counter, &buf_counter[0]);
+
+		ret = checksum->calculate(checksum->name,
+					  region, region_count,
+					  tmp);
+		if (ret < 0) {
+			debug("%s: Error in checksum calculation\n", __func__);
+			goto out;
+		}
+
+		i = 0;
+		while ((i_output < output_len) && (i < hash_len)) {
+			output[i_output] = tmp[i];
+			i_output++;
+			i++;
+		}
+
+		counter++;
+	}
+
+out:
+	free(tmp);
+
+	return ret;
+}
+
+static int compute_hash_prime(struct checksum_algo *checksum,
+			      uint8_t *pad, int pad_len,
+			      uint8_t *hash, int hash_len,
+			      uint8_t *salt, int salt_len,
+			      uint8_t *hprime)
+{
+	struct image_region region[3];
+	int ret, region_count = 3;
+
+	region[0].data = pad;
+	region[0].size = pad_len;
+	region[1].data = hash;
+	region[1].size = hash_len;
+	region[2].data = salt;
+	region[2].size = salt_len;
+
+	ret = checksum->calculate(checksum->name, region, region_count, hprime);
+	if (ret < 0) {
+		debug("%s: Error in checksum calculation\n", __func__);
+		goto out;
+	}
+
+out:
+	return ret;
+}
+
+int padding_pss_verify(struct image_sign_info *info,
+		       uint8_t *msg, int msg_len,
+		       const uint8_t *hash, int hash_len)
+{
+	uint8_t *masked_db = NULL;
+	int masked_db_len = msg_len - hash_len - 1;
+	uint8_t *h = NULL, *hprime = NULL;
+	int h_len = hash_len;
+	uint8_t *db_mask = NULL;
+	int db_mask_len = masked_db_len;
+	uint8_t *db = NULL, *salt = NULL;
+	int db_len = masked_db_len, salt_len = msg_len - hash_len - 2;
+	uint8_t pad_zero[8] = { 0 };
+	int ret, i, leftmost_bits = 1;
+	uint8_t leftmost_mask;
+	struct checksum_algo *checksum = info->checksum;
+
+	/* first, allocate everything */
+	masked_db = malloc(masked_db_len);
+	h = malloc(h_len);
+	db_mask = malloc(db_mask_len);
+	db = malloc(db_len);
+	salt = malloc(salt_len);
+	hprime = malloc(hash_len);
+	if (!masked_db || !h || !db_mask || !db || !salt || !hprime) {
+		printf("%s: can't allocate some buffer\n", __func__);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* step 4: check if the last byte is 0xbc */
+	if (msg[msg_len - 1] != 0xbc) {
+		printf("%s: invalid pss padding (0xbc is missing)\n", __func__);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* step 5 */
+	memcpy(masked_db, msg, masked_db_len);
+	memcpy(h, msg + masked_db_len, h_len);
+
+	/* step 6 */
+	leftmost_mask = (0xff >> (8 - leftmost_bits)) << (8 - leftmost_bits);
+	if (masked_db[0] & leftmost_mask) {
+		printf("%s: invalid pss padding ", __func__);
+		printf("(leftmost bit of maskedDB not zero)\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* step 7 */
+	mask_generation_function1(checksum, h, h_len, db_mask, db_mask_len);
+
+	/* step 8 */
+	for (i = 0; i < db_len; i++)
+		db[i] = masked_db[i] ^ db_mask[i];
+
+	/* step 9 */
+	db[0] &= 0xff >> leftmost_bits;
+
+	/* step 10 */
+	if (db[0] != 0x01) {
+		printf("%s: invalid pss padding ", __func__);
+		printf("(leftmost byte of db isn't 0x01)\n");
+		ret = EINVAL;
+		goto out;
+	}
+
+	/* step 11 */
+	memcpy(salt, &db[1], salt_len);
+
+	/* step 12 & 13 */
+	compute_hash_prime(checksum, pad_zero, 8,
+			   (uint8_t *)hash, hash_len,
+			   salt, salt_len, hprime);
+
+	/* step 14 */
+	ret = memcmp(h, hprime, hash_len);
+
+out:
+	free(hprime);
+	free(salt);
+	free(db);
+	free(db_mask);
+	free(h);
+	free(masked_db);
+
+	return ret;
+}
+#endif
+
 /**
  * rsa_verify_key() - Verify a signature against some data using RSA Key
  *
  * Verify a RSA PKCS1.5 signature against an expected hash using
  * the RSA Key properties in prop structure.
  *
+ * @info:	Specifies key and FIT information
  * @prop:	Specifies key
  * @sig:	Signature
  * @sig_len:	Number of bytes in signature
  * @hash:	Pointer to the expected hash
  * @key_len:	Number of bytes in rsa key
- * @algo:	Checksum algo structure having information on DER encoding etc.
  * @return 0 if verified, -ve on error
  */
-static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig,
+static int rsa_verify_key(struct image_sign_info *info,
+			  struct key_prop *prop, const uint8_t *sig,
 			  const uint32_t sig_len, const uint8_t *hash,
-			  const uint32_t key_len, struct checksum_algo *algo)
+			  const uint32_t key_len)
 {
-	int pad_len;
 	int ret;
 #if !defined(USE_HOSTCC)
 	struct udevice *mod_exp_dev;
 #endif
+	struct checksum_algo *checksum = info->checksum;
+	struct padding_algo *padding = info->padding;
+	int hash_len = checksum->checksum_len;
 
-	if (!prop || !sig || !hash || !algo)
+	if (!prop || !sig || !hash || !checksum)
 		return -EIO;
 
 	if (sig_len != (prop->num_bits / 8)) {
@@ -89,7 +305,7 @@
 		return -EINVAL;
 	}
 
-	debug("Checksum algorithm: %s", algo->name);
+	debug("Checksum algorithm: %s", checksum->name);
 
 	/* Sanity check for stack size */
 	if (sig_len > RSA_MAX_SIG_BITS / 8) {
@@ -116,19 +332,10 @@
 		return ret;
 	}
 
-	pad_len = key_len - algo->checksum_len;
-
-	/* Check pkcs1.5 padding bytes. */
-	ret = rsa_verify_padding(buf, pad_len, algo);
+	ret = padding->verify(info, buf, key_len, hash, hash_len);
 	if (ret) {
-		debug("In RSAVerify(): Padding check failed!\n");
-		return -EINVAL;
-	}
-
-	/* Check hash. */
-	if (memcmp((uint8_t *)buf + pad_len, hash, sig_len - pad_len)) {
-		debug("In RSAVerify(): Hash check failed!\n");
-		return -EACCES;
+		debug("In RSAVerify(): padding check failed!\n");
+		return ret;
 	}
 
 	return 0;
@@ -182,8 +389,8 @@
 		return -EFAULT;
 	}
 
-	ret = rsa_verify_key(&prop, sig, sig_len, hash,
-			     info->crypto->key_len, info->checksum);
+	ret = rsa_verify_key(info, &prop, sig, sig_len, hash,
+			     info->crypto->key_len);
 
 	return ret;
 }
diff --git a/lib/smbios.c b/lib/smbios.c
index 326eb00..e8ee55c 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <mapmem.h>
 #include <smbios.h>
 #include <tables_csum.h>
 #include <version.h>
@@ -72,9 +73,10 @@
 
 static int smbios_write_type0(ulong *current, int handle)
 {
-	struct smbios_type0 *t = (struct smbios_type0 *)*current;
+	struct smbios_type0 *t;
 	int len = sizeof(struct smbios_type0);
 
+	t = map_sysmem(*current, len);
 	memset(t, 0, sizeof(struct smbios_type0));
 	fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle);
 	t->vendor = smbios_add_string(t->eos, "U-Boot");
@@ -101,16 +103,18 @@
 
 	len = t->length + smbios_string_table_len(t->eos);
 	*current += len;
+	unmap_sysmem(t);
 
 	return len;
 }
 
 static int smbios_write_type1(ulong *current, int handle)
 {
-	struct smbios_type1 *t = (struct smbios_type1 *)*current;
+	struct smbios_type1 *t;
 	int len = sizeof(struct smbios_type1);
 	char *serial_str = env_get("serial#");
 
+	t = map_sysmem(*current, len);
 	memset(t, 0, sizeof(struct smbios_type1));
 	fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
 	t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
@@ -122,15 +126,17 @@
 
 	len = t->length + smbios_string_table_len(t->eos);
 	*current += len;
+	unmap_sysmem(t);
 
 	return len;
 }
 
 static int smbios_write_type2(ulong *current, int handle)
 {
-	struct smbios_type2 *t = (struct smbios_type2 *)*current;
+	struct smbios_type2 *t;
 	int len = sizeof(struct smbios_type2);
 
+	t = map_sysmem(*current, len);
 	memset(t, 0, sizeof(struct smbios_type2));
 	fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
 	t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
@@ -140,15 +146,17 @@
 
 	len = t->length + smbios_string_table_len(t->eos);
 	*current += len;
+	unmap_sysmem(t);
 
 	return len;
 }
 
 static int smbios_write_type3(ulong *current, int handle)
 {
-	struct smbios_type3 *t = (struct smbios_type3 *)*current;
+	struct smbios_type3 *t;
 	int len = sizeof(struct smbios_type3);
 
+	t = map_sysmem(*current, len);
 	memset(t, 0, sizeof(struct smbios_type3));
 	fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle);
 	t->manufacturer = smbios_add_string(t->eos, CONFIG_SMBIOS_MANUFACTURER);
@@ -160,6 +168,7 @@
 
 	len = t->length + smbios_string_table_len(t->eos);
 	*current += len;
+	unmap_sysmem(t);
 
 	return len;
 }
@@ -198,9 +207,10 @@
 
 static int smbios_write_type4(ulong *current, int handle)
 {
-	struct smbios_type4 *t = (struct smbios_type4 *)*current;
+	struct smbios_type4 *t;
 	int len = sizeof(struct smbios_type4);
 
+	t = map_sysmem(*current, len);
 	memset(t, 0, sizeof(struct smbios_type4));
 	fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle);
 	t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
@@ -214,32 +224,37 @@
 
 	len = t->length + smbios_string_table_len(t->eos);
 	*current += len;
+	unmap_sysmem(t);
 
 	return len;
 }
 
 static int smbios_write_type32(ulong *current, int handle)
 {
-	struct smbios_type32 *t = (struct smbios_type32 *)*current;
+	struct smbios_type32 *t;
 	int len = sizeof(struct smbios_type32);
 
+	t = map_sysmem(*current, len);
 	memset(t, 0, sizeof(struct smbios_type32));
 	fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle);
 
 	*current += len;
+	unmap_sysmem(t);
 
 	return len;
 }
 
 static int smbios_write_type127(ulong *current, int handle)
 {
-	struct smbios_type127 *t = (struct smbios_type127 *)*current;
+	struct smbios_type127 *t;
 	int len = sizeof(struct smbios_type127);
 
+	t = map_sysmem(*current, len);
 	memset(t, 0, sizeof(struct smbios_type127));
 	fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle);
 
 	*current += len;
+	unmap_sysmem(t);
 
 	return len;
 }
@@ -257,6 +272,7 @@
 ulong write_smbios_table(ulong addr)
 {
 	struct smbios_entry *se;
+	ulong table_addr;
 	ulong tables;
 	int len = 0;
 	int max_struct_size = 0;
@@ -268,7 +284,7 @@
 	/* 16 byte align the table address */
 	addr = ALIGN(addr, 16);
 
-	se = (struct smbios_entry *)(uintptr_t)addr;
+	se = map_sysmem(addr, sizeof(struct smbios_entry));
 	memset(se, 0, sizeof(struct smbios_entry));
 
 	addr += sizeof(struct smbios_entry);
@@ -290,7 +306,24 @@
 	se->max_struct_size = max_struct_size;
 	memcpy(se->intermediate_anchor, "_DMI_", 5);
 	se->struct_table_length = len;
-	se->struct_table_address = tables;
+
+	/*
+	 * We must use a pointer here so things work correctly on sandbox. The
+	 * user of this table is not aware of the mapping of addresses to
+	 * sandbox's DRAM buffer.
+	 */
+	table_addr = (ulong)map_sysmem(tables, 0);
+	if (sizeof(table_addr) > sizeof(u32) && table_addr > (ulong)UINT_MAX) {
+		/*
+		 * We need to put this >32-bit pointer into the table but the
+		 * field is only 32 bits wide.
+		 */
+		printf("WARNING: SMBIOS table_address overflow %llx\n",
+		       (unsigned long long)table_addr);
+		table_addr = 0;
+	}
+	se->struct_table_address = table_addr;
+
 	se->struct_count = handle;
 
 	/* calculate checksums */
@@ -298,6 +331,7 @@
 	isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
 	se->intermediate_checksum = table_compute_checksum(istart, isize);
 	se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
+	unmap_sysmem(se);
 
 	return addr;
 }
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 4dceb6d..a4f16bb 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -381,7 +381,7 @@
 
 quiet_cmd_efi_ld = LD      $@
 cmd_efi_ld = $(LD) -nostdlib -znocombreloc -T $(EFI_LDS_PATH) -shared \
-		-Bsymbolic $^ -o $@
+		-Bsymbolic -s $^ -o $@
 
 EFI_LDS_PATH = $(srctree)/arch/$(ARCH)/lib/$(EFI_LDS)
 
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index b3f525f..bd14fe2 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -1661,7 +1661,6 @@
 CONFIG_RTC_FTRTC010
 CONFIG_RTC_IMXDI
 CONFIG_RTC_M41T11
-CONFIG_RTC_M41T62
 CONFIG_RTC_MC13XXX
 CONFIG_RTC_MCFRRTC
 CONFIG_RTC_MCP79411
diff --git a/test/py/tests/test_efi_selftest.py b/test/py/tests/test_efi_selftest.py
index e0833ff..36b35ee 100644
--- a/test/py/tests/test_efi_selftest.py
+++ b/test/py/tests/test_efi_selftest.py
@@ -8,12 +8,14 @@
 
 @pytest.mark.buildconfigspec('cmd_bootefi_selftest')
 def test_efi_selftest(u_boot_console):
-	"""
-	Run bootefi selftest
-	"""
+	"""Test the UEFI implementation
 
+	:param u_boot_console: U-Boot console
+
+	This function executes all selftests that are not marked as on request.
+	"""
 	u_boot_console.run_command(cmd='setenv efi_selftest')
-	u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False)
+	u_boot_console.run_command(cmd='bootefi selftest ${fdtcontroladdr}', wait_for_prompt=False)
 	m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
 	if m != 0:
 		raise Exception('Failures occurred during the EFI selftest')
diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py
index 92144d4..4627ceb 100644
--- a/test/py/tests/test_vboot.py
+++ b/test/py/tests/test_vboot.py
@@ -126,7 +126,7 @@
             handle.write(struct.pack(">I", size))
         return struct.unpack(">I", total_size)[0]
 
-    def test_with_algo(sha_algo):
+    def test_with_algo(sha_algo, padding):
         """Test verified boot with the given hash algorithm.
 
         This is the main part of the test code. The same procedure is followed
@@ -144,7 +144,7 @@
 
         # Build the FIT, but don't sign anything yet
         cons.log.action('%s: Test FIT with signed images' % sha_algo)
-        make_fit('sign-images-%s.its' % sha_algo)
+        make_fit('sign-images-%s%s.its' % (sha_algo , padding))
         run_bootm(sha_algo, 'unsigned images', 'dev-', True)
 
         # Sign images with our dev keys
@@ -155,7 +155,7 @@
         dtc('sandbox-u-boot.dts')
 
         cons.log.action('%s: Test FIT with signed configuration' % sha_algo)
-        make_fit('sign-configs-%s.its' % sha_algo)
+        make_fit('sign-configs-%s%s.its' % (sha_algo , padding))
         run_bootm(sha_algo, 'unsigned config', '%s+ OK' % sha_algo, True)
 
         # Sign images with our dev keys
@@ -204,7 +204,7 @@
     fit_check_sign = cons.config.build_dir + '/tools/fit_check_sign'
     dtc_args = '-I dts -O dtb -i %s' % tmpdir
     dtb = '%ssandbox-u-boot.dtb' % tmpdir
-    sig_node = '/configurations/conf@1/signature@1'
+    sig_node = '/configurations/conf-1/signature'
 
     # Create an RSA key pair
     public_exponent = 65537
@@ -226,8 +226,10 @@
         # afterwards.
         old_dtb = cons.config.dtb
         cons.config.dtb = dtb
-        test_with_algo('sha1')
-        test_with_algo('sha256')
+        test_with_algo('sha1','')
+        test_with_algo('sha1','-pss')
+        test_with_algo('sha256','')
+        test_with_algo('sha256','-pss')
     finally:
         # Go back to the original U-Boot with the correct dtb.
         cons.config.dtb = old_dtb
diff --git a/test/py/tests/vboot/sign-configs-sha1-pss.its b/test/py/tests/vboot/sign-configs-sha1-pss.its
new file mode 100644
index 0000000..72a5637
--- /dev/null
+++ b/test/py/tests/vboot/sign-configs-sha1-pss.its
@@ -0,0 +1,46 @@
+/dts-v1/;
+
+/ {
+	description = "Chrome OS kernel image with one or more FDT blobs";
+	#address-cells = <1>;
+
+	images {
+		kernel {
+			data = /incbin/("test-kernel.bin");
+			type = "kernel_noload";
+			arch = "sandbox";
+			os = "linux";
+			compression = "none";
+			load = <0x4>;
+			entry = <0x8>;
+			kernel-version = <1>;
+			hash-1 {
+				algo = "sha1";
+			};
+		};
+		fdt-1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			hash-1 {
+				algo = "sha1";
+			};
+		};
+	};
+	configurations {
+		default = "conf-1";
+		conf-1 {
+			kernel = "kernel";
+			fdt = "fdt-1";
+			signature {
+				algo = "sha1,rsa2048";
+				padding = "pss";
+				key-name-hint = "dev";
+				sign-images = "fdt", "kernel";
+			};
+		};
+	};
+};
diff --git a/test/py/tests/vboot/sign-configs-sha1.its b/test/py/tests/vboot/sign-configs-sha1.its
index db2ed79..d8bc1fa 100644
--- a/test/py/tests/vboot/sign-configs-sha1.its
+++ b/test/py/tests/vboot/sign-configs-sha1.its
@@ -5,7 +5,7 @@
 	#address-cells = <1>;
 
 	images {
-		kernel@1 {
+		kernel {
 			data = /incbin/("test-kernel.bin");
 			type = "kernel_noload";
 			arch = "sandbox";
@@ -14,28 +14,28 @@
 			load = <0x4>;
 			entry = <0x8>;
 			kernel-version = <1>;
-			hash@1 {
+			hash-1 {
 				algo = "sha1";
 			};
 		};
-		fdt@1 {
+		fdt-1 {
 			description = "snow";
 			data = /incbin/("sandbox-kernel.dtb");
 			type = "flat_dt";
 			arch = "sandbox";
 			compression = "none";
 			fdt-version = <1>;
-			hash@1 {
+			hash-1 {
 				algo = "sha1";
 			};
 		};
 	};
 	configurations {
-		default = "conf@1";
-		conf@1 {
-			kernel = "kernel@1";
-			fdt = "fdt@1";
-			signature@1 {
+		default = "conf-1";
+		conf-1 {
+			kernel = "kernel";
+			fdt = "fdt-1";
+			signature {
 				algo = "sha1,rsa2048";
 				key-name-hint = "dev";
 				sign-images = "fdt", "kernel";
diff --git a/test/py/tests/vboot/sign-configs-sha256-pss.its b/test/py/tests/vboot/sign-configs-sha256-pss.its
new file mode 100644
index 0000000..7bdcc7e
--- /dev/null
+++ b/test/py/tests/vboot/sign-configs-sha256-pss.its
@@ -0,0 +1,46 @@
+/dts-v1/;
+
+/ {
+	description = "Chrome OS kernel image with one or more FDT blobs";
+	#address-cells = <1>;
+
+	images {
+		kernel {
+			data = /incbin/("test-kernel.bin");
+			type = "kernel_noload";
+			arch = "sandbox";
+			os = "linux";
+			compression = "none";
+			load = <0x4>;
+			entry = <0x8>;
+			kernel-version = <1>;
+			hash-1 {
+				algo = "sha256";
+			};
+		};
+		fdt-1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			hash-1 {
+				algo = "sha256";
+			};
+		};
+	};
+	configurations {
+		default = "conf-1";
+		conf-1 {
+			kernel = "kernel";
+			fdt = "fdt-1";
+			signature {
+				algo = "sha256,rsa2048";
+				padding = "pss";
+				key-name-hint = "dev";
+				sign-images = "fdt", "kernel";
+			};
+		};
+	};
+};
diff --git a/test/py/tests/vboot/sign-configs-sha256.its b/test/py/tests/vboot/sign-configs-sha256.its
index 1b3432e..f5591aa 100644
--- a/test/py/tests/vboot/sign-configs-sha256.its
+++ b/test/py/tests/vboot/sign-configs-sha256.its
@@ -5,7 +5,7 @@
 	#address-cells = <1>;
 
 	images {
-		kernel@1 {
+		kernel {
 			data = /incbin/("test-kernel.bin");
 			type = "kernel_noload";
 			arch = "sandbox";
@@ -14,28 +14,28 @@
 			load = <0x4>;
 			entry = <0x8>;
 			kernel-version = <1>;
-			hash@1 {
+			hash-1 {
 				algo = "sha256";
 			};
 		};
-		fdt@1 {
+		fdt-1 {
 			description = "snow";
 			data = /incbin/("sandbox-kernel.dtb");
 			type = "flat_dt";
 			arch = "sandbox";
 			compression = "none";
 			fdt-version = <1>;
-			hash@1 {
+			hash-1 {
 				algo = "sha256";
 			};
 		};
 	};
 	configurations {
-		default = "conf@1";
-		conf@1 {
-			kernel = "kernel@1";
-			fdt = "fdt@1";
-			signature@1 {
+		default = "conf-1";
+		conf-1 {
+			kernel = "kernel";
+			fdt = "fdt-1";
+			signature {
 				algo = "sha256,rsa2048";
 				key-name-hint = "dev";
 				sign-images = "fdt", "kernel";
diff --git a/test/py/tests/vboot/sign-images-sha1-pss.its b/test/py/tests/vboot/sign-images-sha1-pss.its
new file mode 100644
index 0000000..ded7ae4
--- /dev/null
+++ b/test/py/tests/vboot/sign-images-sha1-pss.its
@@ -0,0 +1,44 @@
+/dts-v1/;
+
+/ {
+	description = "Chrome OS kernel image with one or more FDT blobs";
+	#address-cells = <1>;
+
+	images {
+		kernel {
+			data = /incbin/("test-kernel.bin");
+			type = "kernel_noload";
+			arch = "sandbox";
+			os = "linux";
+			compression = "none";
+			load = <0x4>;
+			entry = <0x8>;
+			kernel-version = <1>;
+			signature {
+				algo = "sha1,rsa2048";
+				padding = "pss";
+				key-name-hint = "dev";
+			};
+		};
+		fdt-1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			signature {
+				algo = "sha1,rsa2048";
+				padding = "pss";
+				key-name-hint = "dev";
+			};
+		};
+	};
+	configurations {
+		default = "conf-1";
+		conf-1 {
+			kernel = "kernel";
+			fdt = "fdt-1";
+		};
+	};
+};
diff --git a/test/py/tests/vboot/sign-images-sha1.its b/test/py/tests/vboot/sign-images-sha1.its
index f69326a..18c759e 100644
--- a/test/py/tests/vboot/sign-images-sha1.its
+++ b/test/py/tests/vboot/sign-images-sha1.its
@@ -5,7 +5,7 @@
 	#address-cells = <1>;
 
 	images {
-		kernel@1 {
+		kernel {
 			data = /incbin/("test-kernel.bin");
 			type = "kernel_noload";
 			arch = "sandbox";
@@ -14,29 +14,29 @@
 			load = <0x4>;
 			entry = <0x8>;
 			kernel-version = <1>;
-			signature@1 {
+			signature {
 				algo = "sha1,rsa2048";
 				key-name-hint = "dev";
 			};
 		};
-		fdt@1 {
+		fdt-1 {
 			description = "snow";
 			data = /incbin/("sandbox-kernel.dtb");
 			type = "flat_dt";
 			arch = "sandbox";
 			compression = "none";
 			fdt-version = <1>;
-			signature@1 {
+			signature {
 				algo = "sha1,rsa2048";
 				key-name-hint = "dev";
 			};
 		};
 	};
 	configurations {
-		default = "conf@1";
-		conf@1 {
-			kernel = "kernel@1";
-			fdt = "fdt@1";
+		default = "conf-1";
+		conf-1 {
+			kernel = "kernel";
+			fdt = "fdt-1";
 		};
 	};
 };
diff --git a/test/py/tests/vboot/sign-images-sha256-pss.its b/test/py/tests/vboot/sign-images-sha256-pss.its
new file mode 100644
index 0000000..34850cc
--- /dev/null
+++ b/test/py/tests/vboot/sign-images-sha256-pss.its
@@ -0,0 +1,44 @@
+/dts-v1/;
+
+/ {
+	description = "Chrome OS kernel image with one or more FDT blobs";
+	#address-cells = <1>;
+
+	images {
+		kernel {
+			data = /incbin/("test-kernel.bin");
+			type = "kernel_noload";
+			arch = "sandbox";
+			os = "linux";
+			compression = "none";
+			load = <0x4>;
+			entry = <0x8>;
+			kernel-version = <1>;
+			signature {
+				algo = "sha256,rsa2048";
+				padding = "pss";
+				key-name-hint = "dev";
+			};
+		};
+		fdt-1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			signature {
+				algo = "sha256,rsa2048";
+				padding = "pss";
+				key-name-hint = "dev";
+			};
+		};
+	};
+	configurations {
+		default = "conf-1";
+		conf-1 {
+			kernel = "kernel";
+			fdt = "fdt-1";
+		};
+	};
+};
diff --git a/test/py/tests/vboot/sign-images-sha256.its b/test/py/tests/vboot/sign-images-sha256.its
index e6aa9fc..bb0f8ee 100644
--- a/test/py/tests/vboot/sign-images-sha256.its
+++ b/test/py/tests/vboot/sign-images-sha256.its
@@ -5,7 +5,7 @@
 	#address-cells = <1>;
 
 	images {
-		kernel@1 {
+		kernel {
 			data = /incbin/("test-kernel.bin");
 			type = "kernel_noload";
 			arch = "sandbox";
@@ -14,29 +14,29 @@
 			load = <0x4>;
 			entry = <0x8>;
 			kernel-version = <1>;
-			signature@1 {
+			signature {
 				algo = "sha256,rsa2048";
 				key-name-hint = "dev";
 			};
 		};
-		fdt@1 {
+		fdt-1 {
 			description = "snow";
 			data = /incbin/("sandbox-kernel.dtb");
 			type = "flat_dt";
 			arch = "sandbox";
 			compression = "none";
 			fdt-version = <1>;
-			signature@1 {
+			signature {
 				algo = "sha256,rsa2048";
 				key-name-hint = "dev";
 			};
 		};
 	};
 	configurations {
-		default = "conf@1";
-		conf@1 {
-			kernel = "kernel@1";
-			fdt = "fdt@1";
+		default = "conf-1";
+		conf-1 {
+			kernel = "kernel";
+			fdt = "fdt-1";
 		};
 	};
 };
diff --git a/tools/image-host.c b/tools/image-host.c
index 09e4f47..88b3295 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -157,6 +157,7 @@
 {
 	const char *node_name;
 	char *algo_name;
+	const char *padding_name;
 
 	node_name = fit_get_name(fit, noffset, NULL);
 	if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
@@ -165,6 +166,8 @@
 		return -1;
 	}
 
+	padding_name = fdt_getprop(fit, noffset, "padding", NULL);
+
 	memset(info, '\0', sizeof(*info));
 	info->keydir = keydir;
 	info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
@@ -173,6 +176,7 @@
 	info->name = strdup(algo_name);
 	info->checksum = image_get_checksum_algo(algo_name);
 	info->crypto = image_get_crypto_algo(algo_name);
+	info->padding = image_get_padding_algo(padding_name);
 	info->require_keys = require_keys;
 	info->engine_id = engine_id;
 	if (!info->checksum || !info->crypto) {