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

- Assorted gadget changes including:
  - dfu: Fix handling of UBI partitions in MTD backend
  - gadget: f_thor: fix wrong file size cast
  - Extend cmd: bcb
  - Fixes for fastboot and rockchip gadgets
  - dfu: Add SCRIPT and SKIP entities
  - dfu/thor: Add `dfu_alt_info` reinitialization from flashed script
  - u-boot: Reduce size of u-boot as usbd_device_* arrays are not exported
diff --git a/Kconfig b/Kconfig
index 6dc20ed..86f0a39 100644
--- a/Kconfig
+++ b/Kconfig
@@ -217,22 +217,25 @@
 	  TODO: Use for other architectures
 
 config SPL_SYS_MALLOC_F_LEN
-	hex "Size of malloc() pool in SPL before relocation"
+	hex "Size of malloc() pool in SPL"
 	depends on SYS_MALLOC_F && SPL
 	default 0x2800 if RCAR_GEN3
 	default SYS_MALLOC_F_LEN
 	help
-	  Before relocation, memory is very limited on many platforms. Still,
+	  In SPL memory is very limited on many platforms. Still,
 	  we can provide a small malloc() pool if needed. Driver model in
 	  particular needs this to operate, so that it can allocate the
 	  initial serial device and any others that are needed.
 
+	  It is possible to enable CONFIG_SYS_SPL_MALLOC_START to start a new
+	  malloc() region in SDRAM once it is inited.
+
 config TPL_SYS_MALLOC_F_LEN
-	hex "Size of malloc() pool in TPL before relocation"
+	hex "Size of malloc() pool in TPL"
 	depends on SYS_MALLOC_F && TPL
-	default SYS_MALLOC_F_LEN
+	default SPL_SYS_MALLOC_F_LEN
 	help
-	  Before relocation, memory is very limited on many platforms. Still,
+	  In TPL memory is very limited on many platforms. Still,
 	  we can provide a small malloc() pool if needed. Driver model in
 	  particular needs this to operate, so that it can allocate the
 	  initial serial device and any others that are needed.
diff --git a/arch/arm/dts/hihope-common.dtsi b/arch/arm/dts/hihope-common.dtsi
new file mode 100644
index 0000000..b1eb6a0
--- /dev/null
+++ b/arch/arm/dts/hihope-common.dtsi
@@ -0,0 +1,377 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the HiHope RZ/G2H Rev.4.0 and
+ * HiHope RZ/G2[MN] Rev.[2.0/3.0/4.0] main board common parts
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	aliases {
+		serial0 = &scif2;
+		serial1 = &hscif0;
+	};
+
+	chosen {
+		bootargs = "ignore_loglevel";
+		stdout-path = "serial0:115200n8";
+	};
+
+	hdmi0-out {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi0_con: endpoint {
+				remote-endpoint = <&rcar_dw_hdmi0_out>;
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led1 {
+			gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
+		};
+
+		led2 {
+			gpios = <&gpio6 13 GPIO_ACTIVE_HIGH>;
+		};
+
+		led3 {
+			gpios = <&gpio0  0 GPIO_ACTIVE_HIGH>;
+		};
+
+		led4 {
+			gpios = <&gpio6 11 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	reg_1p8v: regulator0 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator1 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	sound_card: sound {
+		compatible = "audio-graph-card";
+
+		label = "rcar-sound";
+
+		dais = <&rsnd_port>;
+	};
+
+	vbus0_usb2: regulator-vbus0-usb2 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "USB20_VBUS0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+
+		gpio = <&gpio6 16 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 = <&gpio6 30 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1>, <1800000 0>;
+	};
+
+	x302_clk: x302-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <33000000>;
+	};
+
+	x304_clk: x304-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+&audio_clk_a {
+	clock-frequency = <22579200>;
+};
+
+&du {
+	status = "okay";
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&extal_clk {
+	clock-frequency = <16666666>;
+};
+
+&extalr_clk {
+	clock-frequency = <32768>;
+};
+
+&gpio6 {
+	usb1-reset {
+		gpio-hog;
+		gpios = <10 GPIO_ACTIVE_LOW>;
+		output-low;
+		line-name = "usb1-reset";
+	};
+};
+
+&hdmi0 {
+	status = "okay";
+
+	ports {
+		port@1 {
+			reg = <1>;
+			rcar_dw_hdmi0_out: endpoint {
+				remote-endpoint = <&hdmi0_con>;
+			};
+		};
+		port@2 {
+			reg = <2>;
+			dw_hdmi0_snd_in: endpoint {
+				remote-endpoint = <&rsnd_endpoint>;
+			};
+		};
+	};
+};
+
+&hscif0 {
+	pinctrl-0 = <&hscif0_pins>;
+	pinctrl-names = "default";
+
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&hsusb {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&i2c4 {
+	clock-frequency = <400000>;
+	status = "okay";
+
+	versaclock5: clock-generator@6a {
+		compatible = "idt,5p49v5923";
+		reg = <0x6a>;
+		#clock-cells = <1>;
+		clocks = <&x304_clk>;
+		clock-names = "xin";
+	};
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&pcie_bus_clk {
+	clock-frequency = <100000000>;
+};
+
+&pfc {
+	pinctrl-0 = <&scif_clk_pins>;
+	pinctrl-names = "default";
+
+	hscif0_pins: hscif0 {
+		groups = "hscif0_data", "hscif0_ctrl";
+		function = "hscif0";
+	};
+
+	scif2_pins: scif2 {
+		groups = "scif2_data_a";
+		function = "scif2";
+	};
+
+	scif_clk_pins: scif_clk {
+		groups = "scif_clk_a";
+		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>;
+	};
+
+	sdhi2_pins: sd2 {
+		groups = "sdhi2_data4", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <1800>;
+	};
+
+	sdhi3_pins: sd3 {
+		groups = "sdhi3_data8", "sdhi3_ctrl", "sdhi3_ds";
+		function = "sdhi3";
+		power-source = <1800>;
+	};
+
+	usb0_pins: usb0 {
+		groups = "usb0";
+		function = "usb0";
+	};
+
+	usb1_pins: usb1 {
+		mux {
+			groups = "usb1";
+			function = "usb1";
+		};
+
+		ovc {
+			pins = "GP_6_27";
+			bias-pull-up;
+		};
+	};
+
+	usb30_pins: usb30 {
+		groups = "usb30";
+		function = "usb30";
+	};
+};
+
+&rwdt {
+	timeout-sec = <60>;
+	status = "okay";
+};
+
+&scif2 {
+	pinctrl-0 = <&scif2_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
+&scif_clk {
+	clock-frequency = <14745600>;
+};
+
+&sdhi0 {
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-1 = <&sdhi0_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
+
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&vccq_sdhi0>;
+	cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
+	bus-width = <4>;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
+	status = "okay";
+};
+
+&sdhi2 {
+	status = "okay";
+	pinctrl-0 = <&sdhi2_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&wlan_en_reg>;
+	bus-width = <4>;
+	non-removable;
+	cap-power-off-card;
+	keep-power-in-suspend;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1837";
+		reg = <2>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
+
+&sdhi3 {
+	pinctrl-0 = <&sdhi3_pins>;
+	pinctrl-1 = <&sdhi3_pins>;
+	pinctrl-names = "default", "state_uhs";
+
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_1p8v>;
+	bus-width = <8>;
+	mmc-hs200-1_8v;
+	non-removable;
+	fixed-emmc-driver-type = <1>;
+	status = "okay";
+};
+
+&usb_extal_clk {
+	clock-frequency = <50000000>;
+};
+
+&usb2_phy0 {
+	pinctrl-0 = <&usb0_pins>;
+	pinctrl-names = "default";
+
+	vbus-supply = <&vbus0_usb2>;
+	status = "okay";
+};
+
+&usb2_phy1 {
+	pinctrl-0 = <&usb1_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
+&usb3_peri0 {
+	phys = <&usb3_phy0>;
+	phy-names = "usb";
+
+	companion = <&xhci0>;
+
+	status = "okay";
+};
+
+&usb3_phy0 {
+	status = "okay";
+};
+
+&usb3s0_clk {
+	clock-frequency = <100000000>;
+};
+
+&xhci0 {
+	pinctrl-0 = <&usb30_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
diff --git a/arch/arm/dts/hihope-rev4.dtsi b/arch/arm/dts/hihope-rev4.dtsi
new file mode 100644
index 0000000..30e9299
--- /dev/null
+++ b/arch/arm/dts/hihope-rev4.dtsi
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the HiHope RZ/G2H Rev.4.0 and
+ * HiHope RZ/G2[MN] Rev.3.0/4.0 main board common parts
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include "hihope-common.dtsi"
+
+/ {
+	audio_clkout: audio-clkout {
+		/*
+		 * This is same as <&rcar_sound 0>
+		 * but needed to avoid cs2000/rcar_sound probe dead-lock
+		 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <12288000>;
+	};
+
+	wlan_en_reg: regulator-wlan_en {
+		compatible = "regulator-fixed";
+		regulator-name = "wlan-en-regulator";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		startup-delay-us = <70000>;
+
+		gpio = <&gpio4 6 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	x1801_clk: x1801-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24576000>;
+	};
+};
+
+&hscif0 {
+	bluetooth {
+		compatible = "ti,wl1837-st";
+		enable-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&i2c2 {
+	pinctrl-0 = <&i2c2_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	cs2000: clk_multiplier@4f {
+		#clock-cells = <0>;
+		compatible = "cirrus,cs2000-cp";
+		reg = <0x4f>;
+		clocks = <&audio_clkout>, <&x1801_clk>;
+		clock-names = "clk_in", "ref_clk";
+
+		assigned-clocks = <&cs2000>;
+		assigned-clock-rates = <24576000>; /* 1/1 divide */
+	};
+};
+
+&pfc {
+	i2c2_pins: i2c2 {
+		groups = "i2c2_a";
+		function = "i2c2";
+	};
+
+	sound_clk_pins: sound_clk {
+		groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clkout_a";
+		function = "audio_clk";
+	};
+
+	sound_pins: sound {
+		groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a";
+		function = "ssi";
+	};
+};
+
+&rcar_sound {
+	pinctrl-0 = <&sound_pins &sound_clk_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	/* Single DAI */
+	#sound-dai-cells = <0>;
+
+	/* audio_clkout0/1/2/3 */
+	#clock-cells = <1>;
+	clock-frequency = <12288000 11289600>;
+
+	/* update <audio_clk_b> to <cs2000> */
+	clocks = <&cpg CPG_MOD 1005>,
+		 <&cpg CPG_MOD 1006>, <&cpg CPG_MOD 1007>,
+		 <&cpg CPG_MOD 1008>, <&cpg CPG_MOD 1009>,
+		 <&cpg CPG_MOD 1010>, <&cpg CPG_MOD 1011>,
+		 <&cpg CPG_MOD 1012>, <&cpg CPG_MOD 1013>,
+		 <&cpg CPG_MOD 1014>, <&cpg CPG_MOD 1015>,
+		 <&cpg CPG_MOD 1022>, <&cpg CPG_MOD 1023>,
+		 <&cpg CPG_MOD 1024>, <&cpg CPG_MOD 1025>,
+		 <&cpg CPG_MOD 1026>, <&cpg CPG_MOD 1027>,
+		 <&cpg CPG_MOD 1028>, <&cpg CPG_MOD 1029>,
+		 <&cpg CPG_MOD 1030>, <&cpg CPG_MOD 1031>,
+		 <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
+		 <&cpg CPG_MOD 1020>, <&cpg CPG_MOD 1021>,
+		 <&cpg CPG_MOD 1019>, <&cpg CPG_MOD 1018>,
+		 <&audio_clk_a>, <&cs2000>,
+		 <&audio_clk_c>,
+		 <&cpg CPG_CORE CPG_AUDIO_CLK_I>;
+
+	rsnd_port: port {
+		rsnd_endpoint: endpoint {
+			remote-endpoint = <&dw_hdmi0_snd_in>;
+
+			dai-format = "i2s";
+			bitclock-master = <&rsnd_endpoint>;
+			frame-master = <&rsnd_endpoint>;
+
+			playback = <&ssi2>;
+		};
+	};
+};
diff --git a/arch/arm/dts/hihope-rzg2-ex.dtsi b/arch/arm/dts/hihope-rzg2-ex.dtsi
new file mode 100644
index 0000000..7745012
--- /dev/null
+++ b/arch/arm/dts/hihope-rzg2-ex.dtsi
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the RZ/G2[HMN] HiHope sub board common parts
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+/ {
+	aliases {
+		ethernet0 = &avb;
+	};
+
+	chosen {
+		bootargs = "ignore_loglevel rw root=/dev/nfs ip=on";
+	};
+};
+
+&avb {
+	pinctrl-0 = <&avb_pins>;
+	pinctrl-names = "default";
+	phy-handle = <&phy0>;
+	phy-mode = "rgmii-txid";
+	status = "okay";
+
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+		reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&can0 {
+	pinctrl-0 = <&can0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-0 = <&can1_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&pciec0 {
+	status = "okay";
+};
+
+&pfc {
+	pinctrl-0 = <&scif_clk_pins>;
+	pinctrl-names = "default";
+
+	avb_pins: avb {
+		mux {
+			groups = "avb_link", "avb_mdio", "avb_mii";
+			function = "avb";
+		};
+
+		pins_mdio {
+			groups = "avb_mdio";
+			drive-strength = <24>;
+		};
+
+		pins_mii_tx {
+			pins = "PIN_AVB_TX_CTL", "PIN_AVB_TXC", "PIN_AVB_TD0",
+			       "PIN_AVB_TD1", "PIN_AVB_TD2", "PIN_AVB_TD3";
+			drive-strength = <12>;
+		};
+	};
+
+	can0_pins: can0 {
+		groups = "can0_data_a";
+		function = "can0";
+	};
+
+	can1_pins: can1 {
+		groups = "can1_data";
+		function = "can1";
+	};
+
+	pwm0_pins: pwm0 {
+		groups = "pwm0";
+		function = "pwm0";
+	};
+};
+
+&pwm0 {
+	pinctrl-0 = <&pwm0_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
diff --git a/arch/arm/dts/r8a774a1-hihope-rzg2m-ex.dts b/arch/arm/dts/r8a774a1-hihope-rzg2m-ex.dts
new file mode 100644
index 0000000..f0e4a1f
--- /dev/null
+++ b/arch/arm/dts/r8a774a1-hihope-rzg2m-ex.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the HiHope RZ/G2M Rev.3.0/4.0 connected to
+ * sub board
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+#include "r8a774a1-hihope-rzg2m.dts"
+#include "hihope-rzg2-ex.dtsi"
+
+/ {
+	model = "HopeRun HiHope RZ/G2M with sub board";
+	compatible = "hoperun,hihope-rzg2-ex", "hoperun,hihope-rzg2m",
+		     "renesas,r8a774a1";
+};
+
+/* SW43 should be OFF, if in ON state SATA port will be activated */
+&pciec1 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/r8a774a1-hihope-rzg2m-u-boot.dts b/arch/arm/dts/r8a774a1-hihope-rzg2m-u-boot.dts
new file mode 100644
index 0000000..b735e97
--- /dev/null
+++ b/arch/arm/dts/r8a774a1-hihope-rzg2m-u-boot.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot for the Hihope RZ/G2M board
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation
+ */
+
+#include "r8a774a1-hihope-rzg2m-ex.dts"
+#include "r8a774a1-u-boot.dtsi"
+
+&gpio3 {
+	bt_reg_on{
+		gpio-hog;
+		gpios = <13 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "bt-reg-on";
+	};
+};
+
+&gpio4 {
+	wlan_reg_on{
+		gpio-hog;
+		gpios = <6 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "wlan-reg-on";
+	};
+};
diff --git a/arch/arm/dts/r8a774a1-hihope-rzg2m.dts b/arch/arm/dts/r8a774a1-hihope-rzg2m.dts
new file mode 100644
index 0000000..a574c85
--- /dev/null
+++ b/arch/arm/dts/r8a774a1-hihope-rzg2m.dts
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the HiHope RZ/G2M Rev.3.0/4.0 main board
+ *
+ * Copyright (C) 2021 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include "r8a774a1.dtsi"
+#include "hihope-rev4.dtsi"
+
+/ {
+	model = "HopeRun HiHope RZ/G2M main board based on r8a774a1";
+	compatible = "hoperun,hihope-rzg2m", "renesas,r8a774a1";
+
+	memory@48000000 {
+		device_type = "memory";
+		/* first 128MB is reserved for secure area. */
+		reg = <0x0 0x48000000 0x0 0x78000000>;
+	};
+
+	memory@600000000 {
+		device_type = "memory";
+		reg = <0x6 0x00000000 0x0 0x80000000>;
+	};
+};
+
+&du {
+	clocks = <&cpg CPG_MOD 724>,
+		 <&cpg CPG_MOD 723>,
+		 <&cpg CPG_MOD 722>,
+		 <&versaclock5 1>,
+		 <&x302_clk>,
+		 <&versaclock5 2>;
+	clock-names = "du.0", "du.1", "du.2",
+		      "dclkin.0", "dclkin.1", "dclkin.2";
+};
diff --git a/arch/arm/dts/r8a774a1-u-boot.dtsi b/arch/arm/dts/r8a774a1-u-boot.dtsi
new file mode 100644
index 0000000..f826c41
--- /dev/null
+++ b/arch/arm/dts/r8a774a1-u-boot.dtsi
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source extras for U-Boot on RZ/G2 R8A774A1 SoC
+ *
+ * Copyright (C) 2021 Renesas Electronics Corporation
+ */
+
+#include "r8a779x-u-boot.dtsi"
+
+&extalr_clk {
+	u-boot,dm-pre-reloc;
+};
+
+/delete-node/ &audma0;
+/delete-node/ &audma1;
+/delete-node/ &can0;
+/delete-node/ &can1;
+/delete-node/ &canfd;
+/delete-node/ &csi20;
+/delete-node/ &csi40;
+/delete-node/ &du;
+/delete-node/ &fcpf0;
+/delete-node/ &fcpvb0;
+/delete-node/ &fcpvd0;
+/delete-node/ &fcpvd1;
+/delete-node/ &fcpvd2;
+/delete-node/ &fcpvi0;
+/delete-node/ &hdmi0;
+/delete-node/ &lvds0;
+/delete-node/ &rcar_sound;
+/delete-node/ &sdhi2;
+/delete-node/ &sound_card;
+/delete-node/ &vin0;
+/delete-node/ &vin1;
+/delete-node/ &vin2;
+/delete-node/ &vin3;
+/delete-node/ &vin4;
+/delete-node/ &vin5;
+/delete-node/ &vin6;
+/delete-node/ &vin7;
+/delete-node/ &vspb;
+/delete-node/ &vspd0;
+/delete-node/ &vspd1;
+/delete-node/ &vspd2;
+/delete-node/ &vspi0;
+
+/ {
+	/delete-node/ hdmi0-out;
+};
+
+/ {
+	soc {
+		/delete-node/ fdp1@fe940000;
+	};
+};
diff --git a/arch/arm/lib/crt0_aarch64_efi.S b/arch/arm/lib/crt0_aarch64_efi.S
index 368933e..492195f 100644
--- a/arch/arm/lib/crt0_aarch64_efi.S
+++ b/arch/arm/lib/crt0_aarch64_efi.S
@@ -18,7 +18,8 @@
 	.globl	ImageBase
 ImageBase:
 	.short	IMAGE_DOS_SIGNATURE		/* 'MZ' */
-	.skip	58				/* 'MZ' + pad + offset == 64 */
+	.skip	54				/* 'MZ' + pad + offset == 64 */
+	.long   LINUX_ARM64_MAGIC		/* For GRUB's linux command */
 	.long	pe_header - ImageBase		/* Offset to the PE header */
 pe_header:
 	.long	IMAGE_NT_SIGNATURE		/* 'PE' */
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 80996a9..3d8af0a 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -32,6 +32,9 @@
 #include <os.h>
 #include <rtc_def.h>
 
+/* Environment variable for time offset */
+#define ENV_TIME_OFFSET "UBOOT_SB_TIME_OFFSET"
+
 /* Operating System Interface */
 
 struct os_mem_hdr {
@@ -798,6 +801,28 @@
 	return os_jump_to_file(fname);
 }
 
+long os_get_time_offset(void)
+{
+	const char *offset;
+
+	offset = getenv(ENV_TIME_OFFSET);
+	if (offset)
+		return strtol(offset, NULL, 0);
+	return 0;
+}
+
+void os_set_time_offset(long offset)
+{
+	char buf[21];
+	int ret;
+
+	snprintf(buf, sizeof(buf), "%ld", offset);
+	ret = setenv(ENV_TIME_OFFSET, buf, true);
+	if (ret)
+		printf("Could not set environment variable %s\n",
+		       ENV_TIME_OFFSET);
+}
+
 void os_localtime(struct rtc_time *rt)
 {
 	time_t t = time(NULL);
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 2d18d9d..2542580 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -215,7 +215,7 @@
 	if (!p)
 		p = fname + strlen(fname);
 	len -= p - fname;
-	snprintf(p, len, fmt, p);
+	snprintf(p, len, fmt);
 	state->fdt_fname = fname;
 
 	return 0;
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index d842f02..dc933f3 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -260,10 +260,14 @@
 		stringarray = "pre-proper";
 	};
 
-	spl-test7 {
+	test-bus {
+		compatible = "simple-bus";
 		u-boot,dm-spl;
-		compatible = "sandbox,spl-test";
-		stringarray = "spl";
+		spl-test7 {
+			u-boot,dm-spl;
+			compatible = "sandbox,spl-test";
+			stringarray = "spl";
+		};
 	};
 
 	square {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index f86cd0d..e95f463 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -90,6 +90,16 @@
 			wp-ro {
 				image-pos = <0xf000>;
 				size = <0x1000>;
+				used = <0x884>;
+				compress = "lz4";
+				uncomp-size = <0xcf8>;
+				hash {
+					algo = "sha256";
+					value = [00 01 02 03 04 05 06 07
+						08 09 0a 0b 0c 0d 0e 0f
+						10 11 12 13 14 15 16 17
+						18 19 1a 1b 1c 1d 1e 1f];
+				};
 			};
 			rw {
 				image-pos = <0x10000>;
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
index 05f66f7..1cb960a 100644
--- a/arch/sandbox/include/asm/test.h
+++ b/arch/sandbox/include/asm/test.h
@@ -58,6 +58,13 @@
 };
 
 /**
+ */
+enum cros_ec_test_t {
+	CROSECT_BREAK_HELLO	= BIT(1),
+	CROSECT_LID_OPEN	= BIT(2),
+};
+
+/**
  * sandbox_i2c_set_test_mode() - set test mode for running unit tests
  *
  * See sandbox_i2c_xfer() for the behaviour changes.
@@ -260,4 +267,12 @@
  */
 void sandbox_set_enable_memio(bool enable);
 
+/**
+ * sandbox_cros_ec_set_test_flags() - Set behaviour for testing purposes
+ *
+ * @dev: Device to check
+ * @flags: Flags to control behaviour (CROSECT_...)
+ */
+void sandbox_cros_ec_set_test_flags(struct udevice *dev, uint flags);
+
 #endif
diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c
index 7517b75..6fa0f4d 100644
--- a/arch/x86/cpu/i386/cpu.c
+++ b/arch/x86/cpu/i386/cpu.c
@@ -175,7 +175,7 @@
  * Per Intel FSP external architecture specification, before calling any FSP
  * APIs, we need make sure the system is in flat 32-bit mode and both the code
  * and data selectors should have full 4GB access range. Here we reuse the one
- * we used in arch/x86/cpu/start16.S, and reload the segement registers.
+ * we used in arch/x86/cpu/start16.S, and reload the segment registers.
  */
 void setup_fsp_gdt(void)
 {
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 3b6ed37..3d0d952 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -77,7 +77,7 @@
 	lgdt	gdt_ptr2
 #endif
 
-	/* Load the segement registers to match the GDT loaded in start16.S */
+	/* Load the segment registers to match the GDT loaded in start16.S */
 	movl	$(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax
 	movw	%ax, %fs
 	movw	%ax, %ds
diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts
index a846022..9319123 100644
--- a/arch/x86/dts/chromebook_coral.dts
+++ b/arch/x86/dts/chromebook_coral.dts
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /dts-v1/;
 
+#include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/gpio/x86-gpio.h>
 
 /include/ "skeleton.dtsi"
@@ -99,6 +100,7 @@
 	clk: clock {
 		compatible = "intel,apl-clk";
 		#clock-cells = <1>;
+		u-boot,dm-pre-reloc;
 	};
 
 	cpus {
@@ -139,6 +141,7 @@
 	};
 
 	acpi_gpe: general-purpose-events {
+		u-boot,dm-pre-reloc;
 		reg = <IOMAP_ACPI_BASE IOMAP_ACPI_SIZE>;
 		compatible = "intel,acpi-gpe";
 		interrupt-controller;
@@ -417,8 +420,10 @@
 		};
 
 		i2c_2: i2c2@16,2 {
-			compatible = "intel,apl-i2c";
+			compatible = "intel,apl-i2c", "snps,designware-i2c-pci";
 			reg = <0x0200b210 0 0 0 0>;
+			early-regs = <IOMAP_I2C2_BASE 0x1000>;
+			u-boot,dm-pre-reloc;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clock-frequency = <400000>;
@@ -429,6 +434,7 @@
 			tpm: tpm@50 {
 				reg = <0x50>;
 				compatible = "google,cr50";
+				u-boot,dm-pre-reloc;
 				u-boot,i2c-offset-len = <0>;
 				ready-gpios = <&gpio_n 28 GPIO_ACTIVE_LOW>;
 				interrupts-extended = <&acpi_gpe GPIO_28_IRQ
@@ -583,6 +589,7 @@
 				u-boot,dm-pre-reloc;
 				cros_ec: cros-ec {
 					u-boot,dm-pre-proper;
+					u-boot,dm-vpl;
 					compatible = "google,cros-ec-lpc";
 					reg = <0x204 1 0x200 1 0x880 0x80>;
 
@@ -637,6 +644,7 @@
 				PAD_CFG0_TX_DISABLE | PAD_CFG0_ROUTE_IOAPIC |
 				PAD_CFG0_TRIG_LEVEL | PAD_CFG0_RX_POL_INVERT)
 			(PAD_CFG1_PULL_NONE | PAD_CFG1_IOSSTATE_TXD_RXE)
+		PAD_CFG_GPI(GPIO_25, UP_20K, DEEP)	 /* unused */
 
 		/*
 		 * WLAN_PE_RST - default to deasserted just in case FSP
@@ -657,6 +665,11 @@
 		PAD_CFG_NF(LPC_AD3, UP_20K, DEEP, NF1)	 /* LPC_AD3 */
 		PAD_CFG_NF(LPC_CLKRUNB, UP_20K, DEEP, NF1) /* LPC_CLKRUN_N */
 		PAD_CFG_NF(LPC_FRAMEB, NATIVE, DEEP, NF1) /* LPC_FRAME_N */
+
+		PAD_CFG_GPI(GPIO_101, NONE, DEEP) /* FST_IO2 -- MEM_CONFIG0 */
+		PAD_CFG_GPI(GPIO_102, NONE, DEEP) /* FST_IO3 -- MEM_CONFIG1 */
+		PAD_CFG_GPI(GPIO_38, NONE, DEEP) /* LPSS_UART0_RXD - MEM_CONFIG2*/
+		PAD_CFG_GPI(GPIO_45, NONE, DEEP) /* LPSS_UART1_CTS - MEM_CONFIG3 */
 		>;
 };
 
@@ -1210,3 +1223,9 @@
 		PAD_CFG_GPI(GPIO_73, UP_20K, DEEP)	 /* GP_CAMERASB11 */
 	>;
 };
+
+&rtc {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/x86/include/asm/arch-apollolake/iomap.h b/arch/x86/include/asm/arch-apollolake/iomap.h
index 21c5f33..a4ea150 100644
--- a/arch/x86/include/asm/arch-apollolake/iomap.h
+++ b/arch/x86/include/asm/arch-apollolake/iomap.h
@@ -33,6 +33,9 @@
 #define SRAM_SIZE_2		(4 * KiB)
 #endif
 
+/* Early address for I2C port 2 */
+#define IOMAP_I2C2_BASE		(0xfe020000 + 2 * 0x1000)
+
 /*
  * Use UART2. To use UART1 you need to set '2' to '1', change device tree serial
  * node name and 'reg' property, and update CONFIG_DEBUG_UART_BASE.
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index c8eb5c3..81dd8e0 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -8,6 +8,7 @@
 #define LOG_CATEGORY LOGC_EFI
 
 #include <common.h>
+#include <bootm.h>
 #include <charset.h>
 #include <command.h>
 #include <dm.h>
@@ -338,6 +339,9 @@
 	efi_uintn_t exit_data_size = 0;
 	u16 *exit_data = NULL;
 
+	/* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
+	switch_to_non_secure_mode();
+
 	/* Call our payload! */
 	ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data));
 	if (ret != EFI_SUCCESS) {
diff --git a/cmd/cros_ec.c b/cmd/cros_ec.c
index ce1f59a..eb5053d 100644
--- a/cmd/cros_ec.c
+++ b/cmd/cros_ec.c
@@ -94,6 +94,169 @@
 	return 0;
 }
 
+static const char *const feat_name[64] = {
+	"limited",
+	"flash",
+	"pwm_fan",
+	"pwm_keyb",
+	"lightbar",
+	"led",
+	"motion_sense",
+	"keyb",
+	"pstore",
+	"port80",
+	"thermal",
+	"bklight_switch",
+	"wifi_switch",
+	"host_events",
+	"gpio",
+	"i2c",
+	"charger",
+	"battery",
+	"smart_battery",
+	"hang_detect",
+	"pmu",
+	"sub_mcu",
+	"usb_pd",
+	"usb_mux",
+	"motion_sense_fifo",
+	"vstore",
+	"usbc_ss_mux_virtual",
+	"rtc",
+	"fingerprint",
+	"touchpad",
+	"rwsig",
+	"device_event",
+	"unified_wake_masks",
+	"host_event64",
+	"exec_in_ram",
+	"cec",
+	"motion_sense_tight_timestamps",
+	"refined_tablet_mode_hysteresis",
+	"efs2",
+	"scp",
+	"ish",
+	"typec_cmd",
+	"typec_require_ap_mode_entry",
+	"typec_mux_require_ap_ack",
+};
+
+static int do_show_features(struct udevice *dev)
+{
+	u64 feat;
+	int ret;
+	uint i;
+
+	ret = cros_ec_get_features(dev, &feat);
+	if (ret)
+		return ret;
+	for (i = 0; i < ARRAY_SIZE(feat_name); i++) {
+		if (feat & (1ULL << i)) {
+			if (feat_name[i])
+				printf("%s\n", feat_name[i]);
+			else
+				printf("unknown %d\n", i);
+		}
+	}
+
+	return 0;
+}
+
+static const char *const switch_name[8] = {
+	"lid open",
+	"power button pressed",
+	"write-protect disabled",
+	NULL,
+	"dedicated recovery",
+	NULL,
+	NULL,
+	NULL,
+};
+
+static int do_show_switches(struct udevice *dev)
+{
+	uint switches;
+	int ret;
+	uint i;
+
+	ret = cros_ec_get_switches(dev);
+	if (ret < 0)
+		return log_msg_ret("get", ret);
+	switches = ret;
+	for (i = 0; i < ARRAY_SIZE(switch_name); i++) {
+		uint mask = 1 << i;
+
+		if (switches & mask) {
+			if (switch_name[i])
+				printf("%s\n", switch_name[i]);
+			else
+				printf("unknown %02x\n", mask);
+		}
+	}
+
+	return 0;
+}
+
+static const char *const event_name[] = {
+	"lid_closed",
+	"lid_open",
+	"power_button",
+	"ac_connected",
+	"ac_disconnected",
+	"battery_low",
+	"battery_critical",
+	"battery",
+	"thermal_threshold",
+	"device",
+	"thermal",
+	"usb_charger",
+	"key_pressed",
+	"interface_ready",
+	"keyboard_recovery",
+	"thermal_shutdown",
+	"battery_shutdown",
+	"throttle_start",
+	"throttle_stop",
+	"hang_detect",
+	"hang_reboot",
+	"pd_mcu",
+	"battery_status",
+	"panic",
+	"keyboard_fastboot",
+	"rtc",
+	"mkbp",
+	"usb_mux",
+	"mode_change",
+	"keyboard_recovery_hw_reinit",
+	"extended",
+	"invalid",
+};
+
+static int do_show_events(struct udevice *dev)
+{
+	u32 events;
+	int ret;
+	uint i;
+
+	ret = cros_ec_get_host_events(dev, &events);
+	if (ret)
+		return ret;
+	printf("%08x\n", events);
+	for (i = 0; i < ARRAY_SIZE(event_name); i++) {
+		enum host_event_code code = i + 1;
+		u64 mask = EC_HOST_EVENT_MASK(code);
+
+		if (events & mask) {
+			if (event_name[i])
+				printf("%s\n", event_name[i]);
+			else
+				printf("unknown code %#x\n", code);
+		}
+	}
+
+	return 0;
+}
+
 static int do_cros_ec(struct cmd_tbl *cmdtp, int flag, int argc,
 		      char *const argv[])
 {
@@ -140,6 +303,16 @@
 		}
 		printf("rows     = %u\n", info.rows);
 		printf("cols     = %u\n", info.cols);
+	} else if (!strcmp("features", cmd)) {
+		ret = do_show_features(dev);
+
+		if (ret)
+			printf("Error: %d\n", ret);
+	} else if (!strcmp("switches", cmd)) {
+		ret = do_show_switches(dev);
+
+		if (ret)
+			printf("Error: %d\n", ret);
 	} else if (0 == strcmp("curimage", cmd)) {
 		enum ec_current_image image;
 
@@ -190,13 +363,10 @@
 			return 1;
 		}
 	} else if (0 == strcmp("events", cmd)) {
-		uint32_t events;
+		ret = do_show_events(dev);
 
-		if (cros_ec_get_host_events(dev, &events)) {
-			debug("%s: Could not read host events\n", __func__);
-			return 1;
-		}
-		printf("0x%08x\n", events);
+		if (ret)
+			printf("Error: %d\n", ret);
 	} else if (0 == strcmp("clrevents", cmd)) {
 		uint32_t events = 0x7fffffff;
 
@@ -352,6 +522,15 @@
 			debug("%s: Could not access LDO%d\n", __func__, index);
 			return ret;
 		}
+	} else if (!strcmp("sku", cmd)) {
+		ret = cros_ec_get_sku_id(dev);
+
+		if (ret >= 0) {
+			printf("%d\n", ret);
+			ret = 0;
+		} else {
+			printf("Error: %d\n", ret);
+		}
 	} else {
 		return CMD_RET_USAGE;
 	}
@@ -370,10 +549,13 @@
 	"init                Re-init CROS-EC (done on startup automatically)\n"
 	"crosec id                  Read CROS-EC ID\n"
 	"crosec info                Read CROS-EC info\n"
+	"crosec features            Read CROS-EC features\n"
+	"crosec switches            Read CROS-EC switches\n"
 	"crosec curimage            Read CROS-EC current image\n"
 	"crosec hash                Read CROS-EC hash\n"
 	"crosec reboot [rw | ro | cold]  Reboot CROS-EC\n"
 	"crosec events              Read CROS-EC host events\n"
+	"crosec eventsb             Read CROS-EC host events_b\n"
 	"crosec clrevents [mask]    Clear CROS-EC host events\n"
 	"crosec regioninfo <ro|rw>  Read image info\n"
 	"crosec flashinfo           Read flash info\n"
@@ -382,6 +564,7 @@
 	"crosec write <ro|rw> <addr> [<size>]  Write EC image\n"
 	"crosec vbnvcontext [hexstring]        Read [write] VbNvContext from EC\n"
 	"crosec ldo <idx> [<state>] Switch/Read LDO state\n"
+	"crosec sku                 Read board SKU ID\n"
 	"crosec test                run tests on cros_ec\n"
 	"crosec version             Read CROS-EC version"
 );
diff --git a/configs/chromebook_coral_defconfig b/configs/chromebook_coral_defconfig
index 05e6ce6..ab73a0a 100644
--- a/configs/chromebook_coral_defconfig
+++ b/configs/chromebook_coral_defconfig
@@ -29,6 +29,7 @@
 CONFIG_SPL_BOOTSTAGE_RECORD_COUNT=10
 CONFIG_BOOTSTAGE_STASH=y
 CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS_SUBST=y
 CONFIG_SYS_CONSOLE_INFO_QUIET=y
 CONFIG_LOGF_FUNC=y
 CONFIG_SPL_LOG=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index d193b18..61dae34 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -101,7 +101,6 @@
 CONFIG_SPL_SYSCON=y
 CONFIG_DEVRES=y
 CONFIG_DEBUG_DEVRES=y
-# CONFIG_SPL_SIMPLE_BUS is not set
 CONFIG_ADC=y
 CONFIG_ADC_SANDBOX=y
 CONFIG_AXI=y
diff --git a/disk/part.c b/disk/part.c
index b69fd34..85b1af5 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -150,6 +150,7 @@
 	case IF_TYPE_USB:
 	case IF_TYPE_NVME:
 	case IF_TYPE_PVBLOCK:
+	case IF_TYPE_HOST:
 		printf ("Vendor: %s Rev: %s Prod: %s\n",
 			dev_desc->vendor,
 			dev_desc->revision,
diff --git a/disk/part_efi.c b/disk/part_efi.c
index 2f92266..7a24e33 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -867,6 +867,9 @@
 		return 1;
 	}
 
+	/* Update the partition table entries*/
+	part_init(dev_desc);
+
 	return 0;
 }
 #endif
diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst
index 4674c42..60ee1e0 100644
--- a/doc/arch/sandbox.rst
+++ b/doc/arch/sandbox.rst
@@ -99,37 +99,44 @@
 Various options are available, mostly for test purposes. Use -h to see
 available options. Some of these are described below:
 
-* -t, --terminal <arg>
-  - The terminal is normally in what is called 'raw-with-sigs' mode. This means
+-t, --terminal <arg>
+  The terminal is normally in what is called 'raw-with-sigs' mode. This means
   that you can use arrow keys for command editing and history, but if you
   press Ctrl-C, U-Boot will exit instead of handling this as a keypress.
   Other options are 'raw' (so Ctrl-C is handled within U-Boot) and 'cooked'
   (where the terminal is in cooked mode and cursor keys will not work, Ctrl-C
   will exit).
 
-* -l
-  - Show the LCD emulation window.
+-l
+  Show the LCD emulation window.
 
-* -d <device_tree>
-  - A device tree binary file can be provided with -d. If you edit the source
+-d <device_tree>
+  A device tree binary file can be provided with -d. If you edit the source
   (it is stored at arch/sandbox/dts/sandbox.dts) you must rebuild U-Boot to
   recreate the binary file.
 
-* -D
-  - To use the default device tree, use -D.
+-D
+  To use the default device tree, use -D.
 
-* -T
-  - To use the test device tree, use -T.
+-T
+  To use the test device tree, use -T.
 
-* -c [<cmd>;]<cmd>
-  - To execute commands directly, use the -c option. You can specify a single
+-c [<cmd>;]<cmd>
+  To execute commands directly, use the -c option. You can specify a single
   command, or multiple commands separated by a semicolon, as is normal in
   U-Boot. Be careful with quoting as the shell will normally process and
   swallow quotes. When -c is used, U-Boot exits after the command is complete,
   but you can force it to go to interactive mode instead with -i.
 
-* -i
-  - Go to interactive mode after executing the commands specified by -c.
+-i
+  Go to interactive mode after executing the commands specified by -c.
+
+Environment Variables
+---------------------
+
+UBOOT_SB_TIME_OFFSET
+    This environment variable stores the offset of the emulated real time clock
+    to the host's real time clock in seconds. The offset defaults to zero.
 
 Memory Emulation
 ----------------
diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c
index 34c26cd..f57f690 100644
--- a/drivers/block/sandbox.c
+++ b/drivers/block/sandbox.c
@@ -92,6 +92,7 @@
 {
 	struct host_block_dev *host_dev;
 	struct udevice *dev;
+	struct blk_desc *desc;
 	char dev_name[20], *str, *fname;
 	int ret, fd;
 
@@ -143,6 +144,12 @@
 		goto err_file;
 	}
 
+	desc = blk_get_devnum_by_type(IF_TYPE_HOST, devnum);
+	desc->removable = 1;
+	snprintf(desc->vendor, BLK_VEN_SIZE, "U-Boot");
+	snprintf(desc->product, BLK_PRD_SIZE, "hostfile");
+	snprintf(desc->revision, BLK_REV_SIZE, "1.0");
+
 	return 0;
 err_file:
 	os_close(fd);
@@ -187,6 +194,10 @@
 	blk_dev->block_write = host_block_write;
 	blk_dev->devnum = dev;
 	blk_dev->part_type = PART_TYPE_UNKNOWN;
+	blk_dev->removable = 1;
+	snprintf(blk_dev->vendor, BLK_VEN_SIZE, "U-Boot");
+	snprintf(blk_dev->product, BLK_PRD_SIZE, "hostfile");
+	snprintf(blk_dev->revision, BLK_REV_SIZE, "1.0");
 	part_init(blk_dev);
 
 	return 0;
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index b750567..d5c4e3c 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -83,7 +83,7 @@
 	if (ret) {
 		debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
 		      __func__, ret);
-		return ret;
+		return log_msg_ret("get", ret);
 	}
 
 	clk->dev = dev_clk;
@@ -96,14 +96,15 @@
 		ret = clk_of_xlate_default(clk, args);
 	if (ret) {
 		debug("of_xlate() failed: %d\n", ret);
-		return ret;
+		return log_msg_ret("xlate", ret);
 	}
 
 	return clk_request(dev_clk, clk);
 err:
 	debug("%s: Node '%s', property '%s', failed to request CLK index %d: %d\n",
 	      __func__, ofnode_get_name(node), list_name, index, ret);
-	return ret;
+
+	return log_msg_ret("prop", ret);
 }
 
 static int clk_get_by_indexed_prop(struct udevice *dev, const char *prop_name,
@@ -122,7 +123,7 @@
 	if (ret) {
 		debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
 		      __func__, ret);
-		return ret;
+		return log_ret(ret);
 	}
 
 
@@ -470,6 +471,7 @@
 ulong clk_get_rate(struct clk *clk)
 {
 	const struct clk_ops *ops;
+	int ret;
 
 	debug("%s(clk=%p)\n", __func__, clk);
 	if (!clk_valid(clk))
@@ -479,7 +481,11 @@
 	if (!ops->get_rate)
 		return -ENOSYS;
 
+	ret = ops->get_rate(clk);
+	if (ret)
+		return log_ret(ret);
+
-	return ops->get_rate(clk);
+	return 0;
 }
 
 struct clk *clk_get_parent(struct clk *clk)
diff --git a/drivers/clk/intel/clk_intel.c b/drivers/clk/intel/clk_intel.c
index b633934..46ccbb1 100644
--- a/drivers/clk/intel/clk_intel.c
+++ b/drivers/clk/intel/clk_intel.c
@@ -29,8 +29,8 @@
 	{ }
 };
 
-U_BOOT_DRIVER(clk_intel) = {
-	.name		= "clk_intel",
+U_BOOT_DRIVER(intel_apl_clk) = {
+	.name		= "intel_apl_clk",
 	.id		= UCLASS_CLK,
 	.of_match	= intel_clk_ids,
 	.ops		= &intel_clk_ops,
diff --git a/drivers/core/device.c b/drivers/core/device.c
index aeab383..8629df8 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -462,6 +462,15 @@
 	 * continue regardless of the result of pinctrl. Don't process pinctrl
 	 * settings for pinctrl devices since the device may not yet be
 	 * probed.
+	 *
+	 * This call can produce some non-intuitive results. For example, on an
+	 * x86 device where dev is the main PCI bus, the pinctrl device may be
+	 * child or grandchild of that bus, meaning that the child will be
+	 * probed here. If the child happens to be the P2SB and the pinctrl
+	 * device is a child of that, then both the pinctrl and P2SB will be
+	 * probed by this call. This works because the DM_FLAG_ACTIVATED flag
+	 * is set just above. However, the PCI bus' probe() method and
+	 * associated uclass methods have not yet been called.
 	 */
 	if (dev->parent && device_get_uclass_id(dev) != UCLASS_PINCTRL)
 		pinctrl_select_state(dev, "default");
diff --git a/drivers/core/of_extra.c b/drivers/core/of_extra.c
index 6420e6e..6533445 100644
--- a/drivers/core/of_extra.c
+++ b/drivers/core/of_extra.c
@@ -14,16 +14,17 @@
 int ofnode_read_fmap_entry(ofnode node, struct fmap_entry *entry)
 {
 	const char *prop;
+	ofnode subnode;
 
 	if (ofnode_read_u32(node, "image-pos", &entry->offset)) {
 		debug("Node '%s' has bad/missing 'image-pos' property\n",
 		      ofnode_get_name(node));
-		return log_ret(-ENOENT);
+		return log_msg_ret("image-pos", -ENOENT);
 	}
 	if (ofnode_read_u32(node, "size", &entry->length)) {
 		debug("Node '%s' has bad/missing 'size' property\n",
 		      ofnode_get_name(node));
-		return log_ret(-ENOENT);
+		return log_msg_ret("size", -ENOENT);
 	}
 	entry->used = ofnode_read_s32_default(node, "used", entry->length);
 	prop = ofnode_read_string(node, "compress");
@@ -31,18 +32,20 @@
 		if (!strcmp(prop, "lz4"))
 			entry->compress_algo = FMAP_COMPRESS_LZ4;
 		else
-			return log_msg_ret("Unknown compression algo",
-					   -EINVAL);
+			return log_msg_ret("compression algo", -EINVAL);
 	} else {
 		entry->compress_algo = FMAP_COMPRESS_NONE;
 	}
 	entry->unc_length = ofnode_read_s32_default(node, "uncomp-size",
 						    entry->length);
-	prop = ofnode_read_string(node, "hash");
-	if (prop)
-		entry->hash_size = strlen(prop);
-	entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE;
-	entry->hash = (uint8_t *)prop;
+	subnode = ofnode_find_subnode(node, "hash");
+	if (ofnode_valid(subnode)) {
+		prop = ofnode_read_prop(subnode, "value", &entry->hash_size);
+
+		/* Assume it is sha256 */
+		entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE;
+		entry->hash = (uint8_t *)prop;
+	}
 
 	return 0;
 }
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 1aac5c4..29aab0f 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -39,7 +39,9 @@
 obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o
 obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o
 obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o exynos_hs_i2c.o
+ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o
+endif
 obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o
 obj-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o
 obj-$(CONFIG_SYS_I2C_STM32F7) += stm32f7_i2c.o
diff --git a/drivers/i2c/designware_i2c_pci.c b/drivers/i2c/designware_i2c_pci.c
index ec0cdf6..9e38773 100644
--- a/drivers/i2c/designware_i2c_pci.c
+++ b/drivers/i2c/designware_i2c_pci.c
@@ -192,6 +192,8 @@
 	{ }
 };
 
+DM_DRIVER_ALIAS(i2c_designware_pci, intel_apl_i2c)
+
 U_BOOT_DRIVER(i2c_designware_pci) = {
 	.name	= "i2c_designware_pci",
 	.id	= UCLASS_I2C,
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c
index f03b7d5..ebfa7c4 100644
--- a/drivers/misc/cros_ec.c
+++ b/drivers/misc/cros_ec.c
@@ -44,6 +44,10 @@
 	CROS_EC_CMD_TIMEOUT_MS	= 5000,
 	/* Timeout waiting for a synchronous hash to be recomputed */
 	CROS_EC_CMD_HASH_TIMEOUT_MS = 2000,
+
+	/* Wait 10 ms between attempts to check if EC's hash is ready */
+	CROS_EC_HASH_CHECK_DELAY_MS = 10,
+
 };
 
 #define INVALID_HCMD 0xFF
@@ -400,6 +404,8 @@
 		 */
 		if (din && in_buffer) {
 			assert(len <= din_len);
+			if (len > din_len)
+				return -ENOSPC;
 			memmove(din, in_buffer, len);
 		}
 	}
@@ -502,9 +508,10 @@
 
 	start = get_timer(0);
 	while (hash->status == EC_VBOOT_HASH_STATUS_BUSY) {
-		mdelay(50);	/* Insert some reasonable delay */
+		mdelay(CROS_EC_HASH_CHECK_DELAY_MS);
 
 		p->cmd = EC_VBOOT_HASH_GET;
+
 		if (ec_command(dev, EC_CMD_VBOOT_HASH, 0, p, sizeof(*p), hash,
 			       sizeof(*hash)) < 0)
 			return -1;
@@ -591,6 +598,25 @@
 	return 0;
 }
 
+int cros_ec_hello(struct udevice *dev, uint *handshakep)
+{
+	struct ec_params_hello req;
+	struct ec_response_hello *resp;
+
+	req.in_data = 0x12345678;
+	if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
+			     (uint8_t **)&resp, sizeof(*resp)) < 0)
+		return -EIO;
+	if (resp->out_data != req.in_data + 0x01020304) {
+		printf("Received invalid handshake %x\n", resp->out_data);
+		if (handshakep)
+			*handshakep = req.in_data;
+		return -ENOTSYNC;
+	}
+
+	return 0;
+}
+
 int cros_ec_reboot(struct udevice *dev, enum ec_reboot_cmd cmd, uint8_t flags)
 {
 	struct ec_params_reboot_ec p;
@@ -603,18 +629,23 @@
 		return -1;
 
 	if (!(flags & EC_REBOOT_FLAG_ON_AP_SHUTDOWN)) {
+		ulong start;
+
 		/*
 		 * EC reboot will take place immediately so delay to allow it
 		 * to complete.  Note that some reboot types (EC_REBOOT_COLD)
 		 * will reboot the AP as well, in which case we won't actually
 		 * get to this point.
 		 */
-		/*
-		 * TODO(rspangler@chromium.org): Would be nice if we had a
-		 * better way to determine when the reboot is complete.  Could
-		 * we poll a memory-mapped LPC value?
-		 */
-		udelay(50000);
+		mdelay(50);
+		start = get_timer(0);
+		while (cros_ec_hello(dev, NULL)) {
+			if (get_timer(start) > 3000) {
+				log_err("EC did not return from reboot\n");
+				return -ETIMEDOUT;
+			}
+			mdelay(5);
+		}
 	}
 
 	return 0;
@@ -738,7 +769,6 @@
 {
 	struct cros_ec_dev *cdev = dev_get_uclass_priv(dev);
 	struct ec_params_hello req;
-	struct ec_response_hello *resp;
 
 	struct dm_cros_ec_ops *ops;
 	int ret;
@@ -767,14 +797,14 @@
 	/* Try sending a version 3 packet */
 	cdev->protocol_version = 3;
 	req.in_data = 0;
-	if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
-			     (uint8_t **)&resp, sizeof(*resp)) > 0)
+	ret = cros_ec_hello(dev, NULL);
+	if (!ret || ret == -ENOTSYNC)
 		return 0;
 
 	/* Try sending a version 2 packet */
 	cdev->protocol_version = 2;
-	if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
-			     (uint8_t **)&resp, sizeof(*resp)) > 0)
+	ret = cros_ec_hello(dev, NULL);
+	if (!ret || ret == -ENOTSYNC)
 		return 0;
 
 	/*
@@ -790,18 +820,16 @@
 
 int cros_ec_test(struct udevice *dev)
 {
-	struct ec_params_hello req;
-	struct ec_response_hello *resp;
+	uint out_data;
+	int ret;
 
-	req.in_data = 0x12345678;
-	if (ec_command_inptr(dev, EC_CMD_HELLO, 0, &req, sizeof(req),
-		       (uint8_t **)&resp, sizeof(*resp)) < sizeof(*resp)) {
+	ret = cros_ec_hello(dev, &out_data);
+	if (ret == -ENOTSYNC) {
+		printf("Received invalid handshake %x\n", out_data);
+		return ret;
+	} else if (ret) {
 		printf("ec_command_inptr() returned error\n");
-		return -1;
-	}
-	if (resp->out_data != req.in_data + 0x01020304) {
-		printf("Received invalid handshake %x\n", resp->out_data);
-		return -1;
+		return ret;
 	}
 
 	return 0;
@@ -1077,6 +1105,19 @@
 	return 0;
 }
 
+int cros_ec_get_sku_id(struct udevice *dev)
+{
+	struct ec_sku_id_info *r;
+	int ret;
+
+	ret = ec_command_inptr(dev, EC_CMD_GET_SKU_ID, 0, NULL, 0,
+			       (uint8_t **)&r, sizeof(*r));
+	if (ret != sizeof(*r))
+		return -ret;
+
+	return r->sku_id;
+}
+
 int cros_ec_read_nvdata(struct udevice *dev, uint8_t *block, int size)
 {
 	struct ec_params_vbnvcontext p;
@@ -1303,19 +1344,33 @@
 	return 0;
 }
 
-int cros_ec_check_feature(struct udevice *dev, int feature)
+int cros_ec_get_features(struct udevice *dev, u64 *featuresp)
 {
 	struct ec_response_get_features r;
 	int rv;
 
-	rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, &r, sizeof(r), NULL, 0);
-	if (rv)
-		return rv;
+	rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, NULL, 0, &r, sizeof(r));
+	if (rv != sizeof(r))
+		return -EIO;
+	*featuresp = r.flags[0] | (u64)r.flags[1] << 32;
+
+	return 0;
+}
+
+int cros_ec_check_feature(struct udevice *dev, uint feature)
+{
+	struct ec_response_get_features r;
+	int rv;
+
+	rv = ec_command(dev, EC_CMD_GET_FEATURES, 0, NULL, 0, &r, sizeof(r));
+	if (rv != sizeof(r))
+		return -EIO;
 
 	if (feature >= 8 * sizeof(r.flags))
-		return -1;
+		return -EINVAL;
 
-	return r.flags[feature / 32] & EC_FEATURE_MASK_0(feature);
+	return r.flags[feature / 32] & EC_FEATURE_MASK_0(feature) ? true :
+		 false;
 }
 
 /*
@@ -1502,10 +1557,99 @@
 	return 0;
 }
 
+int cros_ec_vstore_supported(struct udevice *dev)
+{
+	return cros_ec_check_feature(dev, EC_FEATURE_VSTORE);
+}
+
+int cros_ec_vstore_info(struct udevice *dev, u32 *lockedp)
+{
+	struct ec_response_vstore_info *resp;
+
+	if (ec_command_inptr(dev, EC_CMD_VSTORE_INFO, 0, NULL, 0,
+			     (uint8_t **)&resp, sizeof(*resp)) != sizeof(*resp))
+		return -EIO;
+
+	if (lockedp)
+		*lockedp = resp->slot_locked;
+
+	return resp->slot_count;
+}
+
+/*
+ * cros_ec_vstore_read - Read data from EC vstore slot
+ *
+ * @slot: vstore slot to read from
+ * @data: buffer to store read data, must be EC_VSTORE_SLOT_SIZE bytes
+ */
+int cros_ec_vstore_read(struct udevice *dev, int slot, uint8_t *data)
+{
+	struct ec_params_vstore_read req;
+	struct ec_response_vstore_read *resp;
+
+	req.slot = slot;
+	if (ec_command_inptr(dev, EC_CMD_VSTORE_READ, 0, &req, sizeof(req),
+			     (uint8_t **)&resp, sizeof(*resp)) != sizeof(*resp))
+		return -EIO;
+
+	if (!data || req.slot >= EC_VSTORE_SLOT_MAX)
+		return -EINVAL;
+
+	memcpy(data, resp->data, sizeof(resp->data));
+
+	return 0;
+}
+
+/*
+ * cros_ec_vstore_write - Save data into EC vstore slot
+ *
+ * @slot: vstore slot to write into
+ * @data: data to write
+ * @size: size of data in bytes
+ *
+ * Maximum size of data is EC_VSTORE_SLOT_SIZE.  It is the callers
+ * responsibility to check the number of implemented slots by
+ * querying the vstore info.
+ */
+int cros_ec_vstore_write(struct udevice *dev, int slot, const uint8_t *data,
+			 size_t size)
+{
+	struct ec_params_vstore_write req;
+
+	if (slot >= EC_VSTORE_SLOT_MAX || size > EC_VSTORE_SLOT_SIZE)
+		return -EINVAL;
+
+	req.slot = slot;
+	memcpy(req.data, data, size);
+
+	if (ec_command(dev, EC_CMD_VSTORE_WRITE, 0, &req, sizeof(req), NULL, 0))
+		return -EIO;
+
+	return 0;
+}
+
+int cros_ec_get_switches(struct udevice *dev)
+{
+	struct dm_cros_ec_ops *ops;
+	int ret;
+
+	ops = dm_cros_ec_get_ops(dev);
+	if (!ops->get_switches)
+		return -ENOSYS;
+
+	ret = ops->get_switches(dev);
+	if (ret < 0)
+		return log_msg_ret("get", ret);
+
+	return ret;
+}
+
 UCLASS_DRIVER(cros_ec) = {
 	.id		= UCLASS_CROS_EC,
 	.name		= "cros-ec",
 	.per_device_auto	= sizeof(struct cros_ec_dev),
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 	.post_bind	= dm_scan_fdt_dev,
+#endif
 	.flags		= DM_UC_FLAG_ALLOC_PRIV_DMA,
 };
diff --git a/drivers/misc/cros_ec_lpc.c b/drivers/misc/cros_ec_lpc.c
index e0002b9..f403759 100644
--- a/drivers/misc/cros_ec_lpc.c
+++ b/drivers/misc/cros_ec_lpc.c
@@ -207,6 +207,12 @@
 	return 0;
 }
 
+/* Return the byte of EC switch states */
+static int cros_ec_lpc_get_switches(struct udevice *dev)
+{
+	return inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES);
+}
+
 /*
  * Test if LPC command args are supported.
  *
@@ -239,6 +245,7 @@
 	.packet = cros_ec_lpc_packet,
 	.command = cros_ec_lpc_command,
 	.check_version = cros_ec_lpc_check_version,
+	.get_switches = cros_ec_lpc_get_switches,
 };
 
 static const struct udevice_id cros_ec_ids[] = {
diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c
index 9fd6cc2..cb8adc4 100644
--- a/drivers/misc/cros_ec_sandbox.c
+++ b/drivers/misc/cros_ec_sandbox.c
@@ -18,6 +18,7 @@
 #include <asm/malloc.h>
 #include <asm/state.h>
 #include <asm/sdl.h>
+#include <asm/test.h>
 #include <linux/input.h>
 
 /*
@@ -61,6 +62,15 @@
 	int keycode;	/* corresponding linux key code */
 };
 
+enum {
+	VSTORE_SLOT_COUNT	= 4,
+};
+
+struct vstore_slot {
+	bool locked;
+	u8 data[EC_VSTORE_SLOT_SIZE];
+};
+
 /**
  * struct ec_state - Information about the EC state
  *
@@ -73,6 +83,8 @@
  * @matrix: Information about keyboard matrix
  * @keyscan: Current keyscan information (bit set for each row/column pressed)
  * @recovery_req: Keyboard recovery requested
+ * @test_flags: Flags that control behaviour for tests
+ * @slot_locked: Locked vstore slots (mask)
  */
 struct ec_state {
 	u8 vbnv_context[EC_VBNV_BLOCK_SIZE_V2];
@@ -84,6 +96,8 @@
 	struct ec_keymatrix_entry *matrix;	/* the key matrix info */
 	uint8_t keyscan[KEYBOARD_COLS];
 	bool recovery_req;
+	uint test_flags;
+	struct vstore_slot slot[VSTORE_SLOT_COUNT];
 } s_state, *g_state;
 
 /**
@@ -295,6 +309,8 @@
 		struct ec_response_hello *resp = resp_data;
 
 		resp->out_data = req->in_data + 0x01020304;
+		if (ec->test_flags & CROSECT_BREAK_HELLO)
+			resp->out_data++;
 		len = sizeof(*resp);
 		break;
 	}
@@ -358,10 +374,20 @@
 			resp->mask |= EC_HOST_EVENT_MASK(
 					EC_HOST_EVENT_KEYBOARD_RECOVERY);
 		}
-
+		if (ec->test_flags & CROSECT_LID_OPEN)
+			resp->mask |=
+				EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN);
 		len = sizeof(*resp);
 		break;
 	}
+	case EC_CMD_HOST_EVENT_CLEAR_B: {
+		const struct ec_params_host_event_mask *req = req_data;
+
+		if (req->mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN))
+			ec->test_flags &= ~CROSECT_LID_OPEN;
+		len = 0;
+		break;
+		}
 	case EC_CMD_VBOOT_HASH: {
 		const struct ec_params_vboot_hash *req = req_data;
 		struct ec_response_vboot_hash *resp = resp_data;
@@ -468,6 +494,62 @@
 		len = sizeof(*resp);
 		break;
 	}
+	case EC_CMD_GET_SKU_ID: {
+		struct ec_sku_id_info *resp = resp_data;
+
+		resp->sku_id = 1234;
+		len = sizeof(*resp);
+		break;
+	}
+	case EC_CMD_GET_FEATURES: {
+		struct ec_response_get_features *resp = resp_data;
+
+		resp->flags[0] = EC_FEATURE_MASK_0(EC_FEATURE_FLASH) |
+			EC_FEATURE_MASK_0(EC_FEATURE_I2C) |
+			EC_FEATURE_MASK_0(EC_FEATURE_VSTORE);
+		resp->flags[1] =
+			EC_FEATURE_MASK_1(EC_FEATURE_UNIFIED_WAKE_MASKS) |
+			EC_FEATURE_MASK_1(EC_FEATURE_ISH);
+		len = sizeof(*resp);
+		break;
+	}
+	case EC_CMD_VSTORE_INFO: {
+		struct ec_response_vstore_info *resp = resp_data;
+		int i;
+
+		resp->slot_count = VSTORE_SLOT_COUNT;
+		resp->slot_locked = 0;
+		for (i = 0; i < VSTORE_SLOT_COUNT; i++) {
+			if (ec->slot[i].locked)
+				resp->slot_locked |= 1 << i;
+		}
+		len = sizeof(*resp);
+		break;
+	};
+	case EC_CMD_VSTORE_WRITE: {
+		const struct ec_params_vstore_write *req = req_data;
+		struct vstore_slot *slot;
+
+		if (req->slot >= EC_VSTORE_SLOT_MAX)
+			return -EINVAL;
+		slot = &ec->slot[req->slot];
+		slot->locked = true;
+		memcpy(slot->data, req->data, EC_VSTORE_SLOT_SIZE);
+		len = 0;
+		break;
+	}
+	case EC_CMD_VSTORE_READ: {
+		const struct ec_params_vstore_read *req = req_data;
+		struct ec_response_vstore_read *resp = resp_data;
+		struct vstore_slot *slot;
+
+		if (req->slot >= EC_VSTORE_SLOT_MAX)
+			return -EINVAL;
+		slot = &ec->slot[req->slot];
+		memcpy(resp->data, slot->data, EC_VSTORE_SLOT_SIZE);
+		len = sizeof(*resp);
+		break;
+	}
 	default:
 		printf("   ** Unknown EC command %#02x\n", req_hdr->command);
 		return -1;
@@ -518,6 +600,21 @@
 	}
 }
 
+/* Return the byte of EC switch states */
+static int cros_ec_sandbox_get_switches(struct udevice *dev)
+{
+	struct ec_state *ec = dev_get_priv(dev);
+
+	return ec->test_flags & CROSECT_LID_OPEN ? EC_SWITCH_LID_OPEN : 0;
+}
+
+void sandbox_cros_ec_set_test_flags(struct udevice *dev, uint flags)
+{
+	struct ec_state *ec = dev_get_priv(dev);
+
+	ec->test_flags = flags;
+}
+
 int cros_ec_probe(struct udevice *dev)
 {
 	struct ec_state *ec = dev_get_priv(dev);
@@ -573,6 +670,7 @@
 
 struct dm_cros_ec_ops cros_ec_ops = {
 	.packet = cros_ec_sandbox_packet,
+	.get_switches = cros_ec_sandbox_get_switches,
 };
 
 static const struct udevice_id cros_ec_ids[] = {
diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c
index 24130e6..2acb8c6 100644
--- a/drivers/mmc/renesas-sdhi.c
+++ b/drivers/mmc/renesas-sdhi.c
@@ -862,6 +862,9 @@
 	if (!(priv->caps & TMIO_SD_CAP_RCAR_GEN3))
 		return;
 
+	if (priv->caps & TMIO_SD_CAP_DMA_INTERNAL)
+		priv->idma_bus_width = TMIO_SD_DMA_MODE_BUS_WIDTH;
+
 #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
     CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
     CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c
index 2c52868..6c0c840 100644
--- a/drivers/mmc/tmio-common.c
+++ b/drivers/mmc/tmio-common.c
@@ -324,6 +324,8 @@
 
 	tmp = tmio_sd_readl(priv, TMIO_SD_DMA_MODE);
 
+	tmp |= priv->idma_bus_width;
+
 	if (data->flags & MMC_DATA_READ) {
 		buf = data->dest;
 		dir = DMA_FROM_DEVICE;
@@ -702,6 +704,7 @@
 	if (priv->caps & TMIO_SD_CAP_DMA_INTERNAL) {
 		tmp = tmio_sd_readl(priv, TMIO_SD_DMA_MODE);
 		tmp |= TMIO_SD_DMA_MODE_ADDR_INC;
+		tmp |= priv->idma_bus_width;
 		tmio_sd_writel(priv, tmp, TMIO_SD_DMA_MODE);
 	}
 }
diff --git a/drivers/mmc/tmio-common.h b/drivers/mmc/tmio-common.h
index 9062300..59d5a0e 100644
--- a/drivers/mmc/tmio-common.h
+++ b/drivers/mmc/tmio-common.h
@@ -90,6 +90,7 @@
 #define   TMIO_SD_VOLT_180		(2 << 0)/* 1.8V signal */
 #define TMIO_SD_DMA_MODE		0x410
 #define   TMIO_SD_DMA_MODE_DIR_RD	BIT(16)	/* 1: from device, 0: to dev */
+#define   TMIO_SD_DMA_MODE_BUS_WIDTH	(BIT(5) | BIT(4)) /* RCar, 64bit */
 #define   TMIO_SD_DMA_MODE_ADDR_INC	BIT(0)	/* 1: address inc, 0: fixed */
 #define TMIO_SD_DMA_CTL		0x414
 #define   TMIO_SD_DMA_CTL_START	BIT(0)	/* start DMA (auto cleared) */
@@ -121,6 +122,7 @@
 	unsigned int			version;
 	u32				caps;
 	u32				read_poll_flag;
+	u32				idma_bus_width;
 #define TMIO_SD_CAP_NONREMOVABLE	BIT(0)	/* Nonremovable e.g. eMMC */
 #define TMIO_SD_CAP_DMA_INTERNAL	BIT(1)	/* have internal DMA engine */
 #define TMIO_SD_CAP_DIV1024		BIT(2)	/* divisor 1024 is available */
diff --git a/drivers/rtc/i2c_rtc_emul.c b/drivers/rtc/i2c_rtc_emul.c
index 5a2a154..f25b976 100644
--- a/drivers/rtc/i2c_rtc_emul.c
+++ b/drivers/rtc/i2c_rtc_emul.c
@@ -57,6 +57,7 @@
 	plat->use_system_time = use_system_time;
 	if (offset != -1)
 		plat->offset = offset;
+	os_set_time_offset(plat->offset);
 
 	return old_offset;
 }
@@ -80,7 +81,7 @@
 
 	os_localtime(&now);
 	plat->base_time = rtc_mktime(&now);
-	plat->offset = 0;
+	plat->offset = os_get_time_offset();
 	plat->use_system_time = true;
 }
 
@@ -115,6 +116,7 @@
 		now = plat->base_time;
 	}
 	plat->offset = rtc_mktime(time) - now;
+	os_set_time_offset(plat->offset);
 
 	return 0;
 }
diff --git a/drivers/tpm/cr50_i2c.c b/drivers/tpm/cr50_i2c.c
index ce61b72..b103a6f 100644
--- a/drivers/tpm/cr50_i2c.c
+++ b/drivers/tpm/cr50_i2c.c
@@ -183,23 +183,31 @@
 	return cr50_i2c_wait_tpm_ready(dev);
 }
 
-static inline u8 tpm_access(u8 locality)
+static inline u8 tpm_access(int locality)
 {
+	if (locality == -1)
+		locality = 0;
 	return 0x0 | (locality << 4);
 }
 
-static inline u8 tpm_sts(u8 locality)
+static inline u8 tpm_sts(int locality)
 {
+	if (locality == -1)
+		locality = 0;
 	return 0x1 | (locality << 4);
 }
 
-static inline u8 tpm_data_fifo(u8 locality)
+static inline u8 tpm_data_fifo(int locality)
 {
+	if (locality == -1)
+		locality = 0;
 	return 0x5 | (locality << 4);
 }
 
-static inline u8 tpm_did_vid(u8 locality)
+static inline u8 tpm_did_vid(int locality)
 {
+	if (locality == -1)
+		locality = 0;
 	return 0x6 | (locality << 4);
 }
 
@@ -372,7 +380,6 @@
 static int cr50_i2c_send(struct udevice *dev, const u8 *buf, size_t len)
 {
 	struct cr50_priv *priv = dev_get_priv(dev);
-
 	int status;
 	size_t burstcnt, limit, sent = 0;
 	u8 tpm_go[4] = { TPM_STS_GO };
@@ -549,9 +556,23 @@
 {
 	struct dm_i2c_chip *chip = dev_get_parent_plat(dev);
 	struct cr50_priv *priv = dev_get_priv(dev);
+	int len;
+
+	len = snprintf(buf, size, "cr50 TPM 2.0 (i2c %02x id %x), ",
+		       chip->chip_addr, priv->vendor >> 16);
+	if (priv->use_irq) {
+		len += snprintf(buf + len, size - len, "irq=%s/%ld",
+				priv->irq.dev->name, priv->irq.id);
+	} else if (dm_gpio_is_valid(&priv->ready_gpio)) {
+		len += snprintf(buf + len, size - len, "gpio=%s/%u",
+				priv->ready_gpio.dev->name,
+				priv->ready_gpio.offset);
+	} else {
+		len += snprintf(buf + len, size - len, "delay=%d",
+				TIMEOUT_NO_IRQ_US);
+	}
 
-	return snprintf(buf, size, "cr50 TPM 2.0 (i2c %02x id %x) irq=%d",
-			chip->chip_addr, priv->vendor >> 16, priv->use_irq);
+	return len;
 }
 
 static int cr50_i2c_open(struct udevice *dev)
@@ -694,11 +715,12 @@
 		mdelay(10);
 	}
 	if (vendor != CR50_DID_VID) {
-		log_debug("DID_VID %08x not recognised\n", vendor);
+		log_warning("DID_VID %08x not recognised\n", vendor);
 		return log_msg_ret("vendor-id", -EXDEV);
 	}
 	priv->vendor = vendor;
 	priv->locality = -1;
+	log_debug("Cr50 ready\n");
 
 	return 0;
 }
@@ -720,8 +742,8 @@
 	{ }
 };
 
-U_BOOT_DRIVER(cr50_i2c) = {
-	.name   = "cr50_i2c",
+U_BOOT_DRIVER(google_cr50) = {
+	.name   = "google_cr50",
 	.id     = UCLASS_TPM,
 	.of_match = cr50_i2c_ids,
 	.ops    = &cr50_i2c_ops,
diff --git a/include/asm-generic/pe.h b/include/asm-generic/pe.h
index b247519..a1df747 100644
--- a/include/asm-generic/pe.h
+++ b/include/asm-generic/pe.h
@@ -51,4 +51,6 @@
 #define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER	12
 #define IMAGE_SUBSYSTEM_EFI_ROM			13
 
+#define LINUX_ARM64_MAGIC			0x644d5241
+
 #endif /* _ASM_PE_H */
diff --git a/include/cros_ec.h b/include/cros_ec.h
index f187bd0..eddc23d 100644
--- a/include/cros_ec.h
+++ b/include/cros_ec.h
@@ -234,11 +234,61 @@
 struct udevice *board_get_cros_ec_dev(void);
 
 struct dm_cros_ec_ops {
+	/**
+	 * check_version() - Check the protocol version being used (optional)
+	 *
+	 * If provided, this function should check that the EC can be supported
+	 * by the driver. If not provided, HELLO messages will be sent to try
+	 * to determine the protocol version.
+	 *
+	 * @dev: Device to check
+	 * @return 0 if the protocol is valid, -ve if not supported
+	 */
 	int (*check_version)(struct udevice *dev);
+
+	/**
+	 * command() - Old-style command interface
+	 *
+	 * This sends a command and receives a response (deprecated, use
+	 * packet())
+	 *
+	 * @dev: Device to use
+	 * @cmd: Command to send (only supports 0-0xff)
+	 * @cmd_version: Version of command to send (often 0)
+	 * @dout: Output data (may be NULL If dout_len=0)
+	 * @dout_len: Length of output data excluding 4-byte header
+	 * @dinp: On input, set to point to input data, often struct
+	 *	cros_ec_dev->din - typically this is left alone but may be
+	 *	updated by the driver
+	 * @din_len: Maximum length of response
+	 * @return number of bytes in response, or -ve on error
+	 */
 	int (*command)(struct udevice *dev, uint8_t cmd, int cmd_version,
 		       const uint8_t *dout, int dout_len,
 		       uint8_t **dinp, int din_len);
+
+	/**
+	 * packet() - New-style command interface
+	 *
+	 * This interface is preferred over command(), since it is typically
+	 * easier to implement.
+	 *
+	 * @dev: Device to use
+	 * @out_bytes: Number of bytes to send (from struct cros_ec_dev->dout)
+	 * @in_bytes: Maximum number of bytes to expect in response
+	 * @return number of bytes in response, or -ve on error
+	 */
 	int (*packet)(struct udevice *dev, int out_bytes, int in_bytes);
+
+	/**
+	 * get_switches() - Get value of EC switches
+	 *
+	 * This is currently supported on the LPC EC.
+	 *
+	 * @dev: Device to use
+	 * @return current switches value, or -ENOSYS if not supported
+	 */
+	int (*get_switches)(struct udevice *dev);
 };
 
 #define dm_cros_ec_get_ops(dev) \
@@ -330,6 +380,14 @@
 			 uint32_t *offset, uint32_t *size);
 
 /**
+ * cros_ec_get_sku_id() - Read the SKU ID
+ *
+ * @dev: CROS-EC device
+ * return SKU ID, or -ve on error
+ */
+int cros_ec_get_sku_id(struct udevice *dev);
+
+/**
  * Read/write non-volatile data from/to a CROS-EC device.
  *
  * @param dev		CROS-EC device
@@ -497,4 +555,88 @@
  */
 int cros_ec_set_lid_shutdown_mask(struct udevice *dev, int enable);
 
+/**
+ * cros_ec_hello() - Send a hello message
+ *
+ * Sends a message with a fixed input value and checks that the expected output
+ * value is received
+ *
+ * @dev: CROS-EC device
+ * @handshakep: If non-NULL, returns received handshake value on error
+ * @return 0 if OK, -ve on error
+ */
+int cros_ec_hello(struct udevice *dev, uint *handshakep);
+
+/**
+ * cros_ec_get_features() - Get the set of features provided by the EC
+ *
+ * See enum ec_feature_code for the list of available features
+ *
+ * @dev: CROS-EC device
+ * @featuresp: Returns a bitmask of supported features
+ * @return 0 if OK, -ve on error
+ */
+int cros_ec_get_features(struct udevice *dev, u64 *featuresp);
+
+/**
+ * cros_ec_check_feature() - Check if a feature is supported
+ *
+ * @dev: CROS-EC device
+ * @feature: Feature number to check (enum ec_feature_code)
+ * @return true if supported, false if not, -ve on error
+ */
+int cros_ec_check_feature(struct udevice *dev, uint feature);
+
+/**
+ * cros_ec_get_switches() - Get switches value
+ *
+ * @dev: CROS-EC device
+ * @return switches value, or -ENOSYS if not supported, or other -ve value on
+ *	other error
+ */
+int cros_ec_get_switches(struct udevice *dev);
+
+/**
+ * cros_ec_vstore_supported() - Check if vstore is supported
+ *
+ * @dev: CROS-EC device
+ * @return false if not supported, true if supported, -ve on error
+ */
+int cros_ec_vstore_supported(struct udevice *dev);
+
+/**
+ * cros_ec_vstore_info() - Get vstore information
+ *
+ * @dev: CROS-EC device
+ * @lockedp: mask of locked slots
+ * @return number of vstore slots supported by the EC,, -ve on error
+ */
+int cros_ec_vstore_info(struct udevice *dev, u32 *lockedp);
+
+/**
+ * cros_ec_vstore_read() - Read data from EC vstore slot
+ *
+ * @dev: CROS-EC device
+ * @slot: vstore slot to read from
+ * @data: buffer to store read data, must be EC_VSTORE_SLOT_SIZE bytes
+ * @return 0 if OK, -ve on error
+ */
+int cros_ec_vstore_read(struct udevice *dev, int slot, uint8_t *data);
+
+/**
+ * cros_ec_vstore_write() - Save data into EC vstore slot
+ *
+ * The maximum size of data is EC_VSTORE_SLOT_SIZE.  It is the caller's
+ * responsibility to check the number of implemented slots by querying the
+ * vstore info.
+ *
+ * @dev: CROS-EC device
+ * @slot: vstore slot to write into
+ * @data: data to write
+ * @size: size of data in bytes
+ * @return 0 if OK, -ve on error
+ */
+int cros_ec_vstore_write(struct udevice *dev, int slot, const uint8_t *data,
+			 size_t size);
+
 #endif
diff --git a/include/ctype.h b/include/ctype.h
new file mode 120000
index 0000000..9e43f9c
--- /dev/null
+++ b/include/ctype.h
@@ -0,0 +1 @@
+linux/ctype.h
\ No newline at end of file
diff --git a/include/dm/device.h b/include/dm/device.h
index f5b4cd6..e665558 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -111,7 +111,7 @@
  * probe method if the device has a device tree node.
  *
  * All three of plat, priv and uclass_priv can be allocated by the
- * driver, or you can use the auto_alloc_size members of struct driver and
+ * driver, or you can use the auto members of struct driver and
  * struct uclass_driver to have driver model do this automatically.
  *
  * @driver: The driver used by this device
diff --git a/include/dm/read.h b/include/dm/read.h
index c875e11..03ba982 100644
--- a/include/dm/read.h
+++ b/include/dm/read.h
@@ -30,8 +30,7 @@
 }
 #endif
 
-#ifndef CONFIG_DM_DEV_READ_INLINE
-
+#if !defined(CONFIG_DM_DEV_READ_INLINE) || CONFIG_IS_ENABLED(OF_PLATDATA)
 /**
  * dev_read_u32() - read a 32-bit integer from a device's DT property
  *
@@ -1007,7 +1006,7 @@
 
 static inline int dev_read_alias_highest_id(const char *stem)
 {
-	if (!CONFIG_IS_ENABLED(OF_LIBFDT))
+	if (!CONFIG_IS_ENABLED(OF_LIBFDT) || !gd->fdt_blob)
 		return -1;
 	return fdtdec_get_alias_highest_id(gd->fdt_blob, stem);
 }
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 444ba61..36f4a02 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1101,13 +1101,50 @@
 	EC_FEATURE_DEVICE_EVENT = 31,
 	/* EC supports the unified wake masks for LPC/eSPI systems */
 	EC_FEATURE_UNIFIED_WAKE_MASKS = 32,
+	/* EC supports 64-bit host events */
+	EC_FEATURE_HOST_EVENT64 = 33,
+	/* EC runs code in RAM (not in place, a.k.a. XIP) */
+	EC_FEATURE_EXEC_IN_RAM = 34,
+	/* EC supports CEC commands */
+	EC_FEATURE_CEC = 35,
+	/* EC supports tight sensor timestamping. */
+	EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS = 36,
+	/*
+	 * EC supports tablet mode detection aligned to Chrome and allows
+	 * setting of threshold by host command using
+	 * MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE.
+	 */
+	EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS = 37,
+	/*
+	 * Early Firmware Selection ver.2. Enabled by CONFIG_VBOOT_EFS2.
+	 * Note this is a RO feature. So, a query (EC_CMD_GET_FEATURES) should
+	 * be sent to RO to be precise.
+	 */
+	EC_FEATURE_EFS2 = 38,
+	/* The MCU is a System Companion Processor (SCP). */
+	EC_FEATURE_SCP = 39,
+	/* The MCU is an Integrated Sensor Hub */
+	EC_FEATURE_ISH = 40,
+	/* New TCPMv2 TYPEC_ prefaced commands supported */
+	EC_FEATURE_TYPEC_CMD = 41,
+	/*
+	 * The EC will wait for direction from the AP to enter Type-C alternate
+	 * modes or USB4.
+	 */
+	EC_FEATURE_TYPEC_REQUIRE_AP_MODE_ENTRY = 42,
+	/*
+	 * The EC will wait for an acknowledge from the AP after setting the
+	 * mux.
+	 */
+	EC_FEATURE_TYPEC_MUX_REQUIRE_AP_ACK = 43,
 };
 
-#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
-#define EC_FEATURE_MASK_1(event_code) (1UL << (event_code - 32))
-struct __ec_align4 ec_response_get_features {
+#define EC_FEATURE_MASK_0(event_code) BIT(event_code % 32)
+#define EC_FEATURE_MASK_1(event_code) BIT(event_code - 32)
+
+struct ec_response_get_features {
 	uint32_t flags[2];
-};
+} __ec_align4;
 
 /*****************************************************************************/
 /* Get the board's SKU ID from EC */
diff --git a/include/os.h b/include/os.h
index 0913b47..e192e32 100644
--- a/include/os.h
+++ b/include/os.h
@@ -424,4 +424,22 @@
  */
 void os_signal_action(int sig, unsigned long pc);
 
+/**
+ * os_get_time_offset() - get time offset
+ *
+ * Get the time offset from environment variable UBOOT_SB_TIME_OFFSET.
+ *
+ * Return:	offset in seconds
+ */
+long os_get_time_offset(void);
+
+/**
+ * os_set_time_offset() - set time offset
+ *
+ * Save the time offset in environment variable UBOOT_SB_TIME_OFFSET.
+ *
+ * @offset:	offset in seconds
+ */
+void os_set_time_offset(long offset);
+
 #endif
diff --git a/lib/binman.c b/lib/binman.c
index f415df3..6040ec8 100644
--- a/lib/binman.c
+++ b/lib/binman.c
@@ -145,6 +145,8 @@
 	if (ret)
 		return log_msg_ret("node", -ENOENT);
 	binman_set_rom_offset(ROM_OFFSET_NONE);
+	log_debug("binman: Selected image node '%s'\n",
+		  ofnode_get_name(binman->image));
 
 	return 0;
 }
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index c0804ef..d0aad02 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -142,8 +142,9 @@
 		return EFI_MEDIA_CHANGED;
 	if (!this->media->media_present)
 		return EFI_NO_MEDIA;
-	/* media->io_align is a power of 2 */
-	if ((uintptr_t)buffer & (this->media->io_align - 1))
+	/* media->io_align is a power of 2 or 0 */
+	if (this->media->io_align &&
+	    (uintptr_t)buffer & (this->media->io_align - 1))
 		return EFI_INVALID_PARAMETER;
 	if (lba * this->media->block_size + buffer_size >
 	    this->media->last_block * this->media->block_size)
@@ -209,8 +210,9 @@
 		return EFI_MEDIA_CHANGED;
 	if (!this->media->media_present)
 		return EFI_NO_MEDIA;
-	/* media->io_align is a power of 2 */
-	if ((uintptr_t)buffer & (this->media->io_align - 1))
+	/* media->io_align is a power of 2 or 0 */
+	if (this->media->io_align &&
+	    (uintptr_t)buffer & (this->media->io_align - 1))
 		return EFI_INVALID_PARAMETER;
 	if (lba * this->media->block_size + buffer_size >
 	    this->media->last_block * this->media->block_size)
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 5800cbf..b1c5125 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -6,7 +6,6 @@
  */
 
 #include <common.h>
-#include <bootm.h>
 #include <efi_loader.h>
 #include <efi_variable.h>
 
@@ -188,9 +187,6 @@
 	/* Allow unaligned memory access */
 	allow_unaligned();
 
-	/* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */
-	switch_to_non_secure_mode();
-
 	/* Initialize root node */
 	ret = efi_root_node_register();
 	if (ret != EFI_SUCCESS)
diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c
index 5eb297d..15f0375 100644
--- a/lib/efi_selftest/efi_selftest_block_device.c
+++ b/lib/efi_selftest/efi_selftest_block_device.c
@@ -194,7 +194,7 @@
 	decompress(&image);
 
 	block_io.media->block_size = 1 << LB_BLOCK_SIZE;
-	block_io.media->last_block = img.length >> LB_BLOCK_SIZE;
+	block_io.media->last_block = (img.length >> LB_BLOCK_SIZE) - 1;
 
 	ret = boottime->install_protocol_interface(
 				&disk_handle, &block_io_protocol_guid,
@@ -301,6 +301,7 @@
 	efi_handle_t *handles;
 	efi_handle_t handle_partition = NULL;
 	struct efi_device_path *dp_partition;
+	struct efi_block_io *block_io_protocol;
 	struct efi_simple_file_system_protocol *file_system;
 	struct efi_file_handle *root, *file;
 	struct {
@@ -309,6 +310,7 @@
 	} system_info;
 	efi_uintn_t buf_size;
 	char buf[16] __aligned(ARCH_DMA_MINALIGN);
+	u32 part1_size;
 	u64 pos;
 
 	/* Connect controller to virtual disk */
@@ -353,6 +355,23 @@
 		return EFI_ST_FAILURE;
 	}
 
+	/* Open the block_io_protocol */
+	ret = boottime->open_protocol(handle_partition,
+				      &block_io_protocol_guid,
+				      (void **)&block_io_protocol, NULL, NULL,
+				      EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to open block IO protocol\n");
+		return EFI_ST_FAILURE;
+	}
+	/* Get size of first MBR partition */
+	memcpy(&part1_size, image + 0x1ca, sizeof(u32));
+	if (block_io_protocol->media->last_block != part1_size - 1) {
+		efi_st_error("Last LBA of partition %x, expected %x\n",
+			     (unsigned int)block_io_protocol->media->last_block,
+			     part1_size - 1);
+		return EFI_ST_FAILURE;
+	}
 	/* Open the simple file system protocol */
 	ret = boottime->open_protocol(handle_partition,
 				      &guid_simple_file_system_protocol,
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 46e076e..e70e50f 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -24,6 +24,7 @@
 obj-$(CONFIG_BUTTON) += button.o
 obj-$(CONFIG_DM_BOOTCOUNT) += bootcount.o
 obj-$(CONFIG_CLK) += clk.o clk_ccf.o
+obj-$(CONFIG_CROS_EC) += cros_ec.o
 obj-$(CONFIG_DEVRES) += devres.o
 obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi_host.o
 obj-$(CONFIG_DM_ETH) += eth.o
@@ -41,6 +42,7 @@
 obj-$(CONFIG_UT_DM) += nop.o
 obj-y += ofnode.o
 obj-y += ofread.o
+obj-y += of_extra.o
 obj-$(CONFIG_OSD) += osd.o
 obj-$(CONFIG_DM_VIDEO) += panel.o
 obj-$(CONFIG_DM_PCI) += pci.o
diff --git a/test/dm/cros_ec.c b/test/dm/cros_ec.c
new file mode 100644
index 0000000..30cb70e
--- /dev/null
+++ b/test/dm/cros_ec.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2021 Google LLC
+ */
+
+#include <common.h>
+#include <cros_ec.h>
+#include <dm.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+static int dm_test_cros_ec_hello(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	uint val;
+
+	ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+
+	ut_assertok(cros_ec_hello(dev, NULL));
+
+	val = 0xdead1357;
+	ut_assertok(cros_ec_hello(dev, &val));
+	ut_asserteq(0xdead1357, val);
+
+	sandbox_cros_ec_set_test_flags(dev, CROSECT_BREAK_HELLO);
+	ut_asserteq(-ENOTSYNC, cros_ec_hello(dev, &val));
+	ut_asserteq(0x12345678, val);
+
+	return 0;
+}
+DM_TEST(dm_test_cros_ec_hello, UT_TESTF_SCAN_FDT);
+
+static int dm_test_cros_ec_sku_id(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+	ut_asserteq(1234, cros_ec_get_sku_id(dev));
+
+	/* try the command */
+	console_record_reset();
+	ut_assertok(run_command("crosec sku", 0));
+	ut_assert_nextline("1234");
+	ut_assert_console_end();
+
+	return 0;
+}
+DM_TEST(dm_test_cros_ec_sku_id, UT_TESTF_SCAN_FDT);
+
+static int dm_test_cros_ec_features(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	u64 feat;
+
+	ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+	ut_assertok(cros_ec_get_features(dev, &feat));
+	ut_asserteq_64(1U << EC_FEATURE_FLASH | 1U << EC_FEATURE_I2C |
+		1u << EC_FEATURE_VSTORE |
+		1ULL << EC_FEATURE_UNIFIED_WAKE_MASKS | 1ULL << EC_FEATURE_ISH,
+		feat);
+
+	ut_asserteq(true, cros_ec_check_feature(dev, EC_FEATURE_I2C));
+	ut_asserteq(false, cros_ec_check_feature(dev, EC_FEATURE_MOTION_SENSE));
+	ut_asserteq(true, cros_ec_check_feature(dev, EC_FEATURE_ISH));
+
+	/* try the command */
+	console_record_reset();
+	ut_assertok(run_command("crosec features", 0));
+	ut_assert_nextline("flash");
+	ut_assert_nextline("i2c");
+	ut_assert_nextline("vstore");
+	ut_assert_nextline("unified_wake_masks");
+	ut_assert_nextline("ish");
+	ut_assert_console_end();
+
+	return 0;
+}
+DM_TEST(dm_test_cros_ec_features, UT_TESTF_SCAN_FDT);
+
+static int dm_test_cros_ec_switches(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+	ut_asserteq(0, cros_ec_get_switches(dev));
+
+	/* try the command */
+	console_record_reset();
+	ut_assertok(run_command("crosec switches", 0));
+	ut_assert_console_end();
+
+	/* Open the lid and check the switch changes */
+	sandbox_cros_ec_set_test_flags(dev, CROSECT_LID_OPEN);
+	ut_asserteq(EC_SWITCH_LID_OPEN, cros_ec_get_switches(dev));
+
+	/* try the command */
+	console_record_reset();
+	ut_assertok(run_command("crosec switches", 0));
+	ut_assert_nextline("lid open");
+	ut_assert_console_end();
+
+	return 0;
+}
+DM_TEST(dm_test_cros_ec_switches, UT_TESTF_SCAN_FDT);
+
+static int dm_test_cros_ec_events(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+	u32 events;
+
+	ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+	ut_assertok(cros_ec_get_host_events(dev, &events));
+	ut_asserteq(0, events);
+
+	/* try the command */
+	console_record_reset();
+	ut_assertok(run_command("crosec events", 0));
+	ut_assert_nextline("00000000");
+	ut_assert_console_end();
+
+	/* Open the lid and check the event appears */
+	sandbox_cros_ec_set_test_flags(dev, CROSECT_LID_OPEN);
+	ut_assertok(cros_ec_get_host_events(dev, &events));
+	ut_asserteq(EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN), events);
+
+	/* try the command */
+	console_record_reset();
+	ut_assertok(run_command("crosec events", 0));
+	ut_assert_nextline("00000002");
+	ut_assert_nextline("lid_open");
+	ut_assert_console_end();
+
+	/* Clear the event */
+	ut_assertok(cros_ec_clear_host_events(dev,
+		EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN)));
+	ut_assertok(cros_ec_get_host_events(dev, &events));
+	ut_asserteq(0, events);
+
+	return 0;
+}
+DM_TEST(dm_test_cros_ec_events, UT_TESTF_SCAN_FDT);
+
+static int dm_test_cros_ec_vstore(struct unit_test_state *uts)
+{
+	const int size = EC_VSTORE_SLOT_SIZE;
+	u8 test_data[size], data[size];
+	struct udevice *dev;
+	u32 locked;
+	int i;
+
+	ut_assertok(uclass_first_device_err(UCLASS_CROS_EC, &dev));
+	ut_asserteq(true, cros_ec_vstore_supported(dev));
+
+	ut_asserteq(4, cros_ec_vstore_info(dev, &locked));
+	ut_asserteq(0, locked);
+
+	/* Write some data */
+	for (i = 0; i < size; i++)
+		test_data[i] = ' ' + i;
+	ut_assertok(cros_ec_vstore_write(dev, 2, test_data, size));
+
+	/* Check it is locked */
+	ut_asserteq(4, cros_ec_vstore_info(dev, &locked));
+	ut_asserteq(1 << 2, locked);
+
+	/* Read it back and compare */
+	ut_assertok(cros_ec_vstore_read(dev, 2, data));
+	ut_asserteq_mem(test_data, data, size);
+
+	/* Try another slot to make sure it is empty */
+	ut_assertok(cros_ec_vstore_read(dev, 0, data));
+	for (i = 0; i < size; i++)
+		ut_asserteq(0, data[i]);
+
+	return 0;
+}
+DM_TEST(dm_test_cros_ec_vstore, UT_TESTF_SCAN_FDT);
diff --git a/test/dm/of_extra.c b/test/dm/of_extra.c
new file mode 100644
index 0000000..b19cd37
--- /dev/null
+++ b/test/dm/of_extra.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/of_extra.h>
+#include <dm/test.h>
+#include <test/ut.h>
+#include <u-boot/sha256.h>
+
+static int dm_test_ofnode_read_fmap_entry(struct unit_test_state *uts)
+{
+	const char hash_expect[] = {
+		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+		0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	};
+	struct fmap_entry entry;
+	ofnode node;
+
+	node = ofnode_path("/cros-ec/flash/wp-ro");
+	ut_assertok(ofnode_read_fmap_entry(node, &entry));
+	ut_asserteq(0xf000, entry.offset);
+	ut_asserteq(0x1000, entry.length);
+	ut_asserteq(0x884, entry.used);
+	ut_asserteq(FMAP_COMPRESS_LZ4, entry.compress_algo);
+	ut_asserteq(0xcf8, entry.unc_length);
+	ut_asserteq(FMAP_HASH_SHA256, entry.hash_algo);
+	ut_asserteq(SHA256_SUM_LEN, entry.hash_size);
+	ut_asserteq_mem(hash_expect, entry.hash, SHA256_SUM_LEN);
+
+	return 0;
+}
+DM_TEST(dm_test_ofnode_read_fmap_entry, 0);
diff --git a/test/dm/of_platdata.c b/test/dm/of_platdata.c
index cfc43a5..26c5092 100644
--- a/test/dm/of_platdata.c
+++ b/test/dm/of_platdata.c
@@ -210,11 +210,11 @@
 /* Test that device parents are correctly set up */
 static int dm_test_of_plat_parent(struct unit_test_state *uts)
 {
-	struct udevice *rtc, *i2c;
+	struct udevice *dev, *bus;
 
-	ut_assertok(uclass_first_device_err(UCLASS_RTC, &rtc));
-	ut_assertok(uclass_first_device_err(UCLASS_I2C, &i2c));
-	ut_asserteq_ptr(i2c, dev_get_parent(rtc));
+	ut_assertok(uclass_first_device_err(UCLASS_SIMPLE_BUS, &bus));
+	ut_assertok(device_first_child_err(bus, &dev));
+	ut_asserteq_ptr(bus, dev_get_parent(dev));
 
 	return 0;
 }
diff --git a/tools/.gitignore b/tools/.gitignore
index a021ea9..a88453f 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -20,6 +20,7 @@
 /kwboot
 /lib/
 /mips-relocs
+/mkeficapsule
 /mkenvimage
 /mkexynosspl
 /mkimage
diff --git a/tools/binman/README b/tools/binman/README
index de1eedf..a00c902 100644
--- a/tools/binman/README
+++ b/tools/binman/README
@@ -1050,10 +1050,9 @@
 - Allow easy building of images by specifying just the board name
 - Support building an image for a board (-b) more completely, with a
   configurable build directory
-- Support adding FITs to an image
-- Support for ARM Trusted Firmware (ATF)
 - Detect invalid properties in nodes
 - Sort the fdtmap by offset
+- Output temporary files to a different directory
 
 --
 Simon Glass <sjg@chromium.org>
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 072417f..1952b2a 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -244,7 +244,8 @@
             if not os.path.exists(fname):
                 os.makedirs(fname)
             fname = os.path.join(fname, 'root')
-        tout.Notice("Write entry '%s' to '%s'" % (entry.GetPath(), fname))
+        tout.Notice("Write entry '%s' size %x to '%s'" %
+                    (entry.GetPath(), len(data), fname))
         tools.WriteFile(fname, data)
     return einfos
 
diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index 249074a..03b49d7 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -132,7 +132,8 @@
                                  (msg, sym.size))
 
             # Look up the symbol in our entry tables.
-            value = section.LookupSymbol(name, sym.weak, msg, base.address)
+            value = section.GetImage().LookupImageSymbol(name, sym.weak, msg,
+                                                         base.address)
             if value is None:
                 value = -1
                 pack_string = pack_string.lower()
diff --git a/tools/binman/elf_test.py b/tools/binman/elf_test.py
index e3d218a..7a12801 100644
--- a/tools/binman/elf_test.py
+++ b/tools/binman/elf_test.py
@@ -45,10 +45,12 @@
     def GetPath(self):
         return 'section_path'
 
-    def LookupSymbol(self, name, weak, msg, base_addr):
+    def LookupImageSymbol(self, name, weak, msg, base_addr):
         """Fake implementation which returns the same value for all symbols"""
         return self.sym_value
 
+    def GetImage(self):
+        return self
 
 def BuildElfTestFiles(target_dir):
     """Build ELF files used for testing in binman
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 2be0d8e..d58a730 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -434,8 +434,7 @@
                 missing.append(prop.name)
             values.append(value)
         if missing:
-            self.Raise('Missing required properties/entry args: %s' %
-                       (', '.join(missing)))
+            self.GetImage().MissingArgs(self, missing)
         return values
 
     def GetPath(self):
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
index 301ac55..81756c3 100644
--- a/tools/binman/etype/blob.py
+++ b/tools/binman/etype/blob.py
@@ -66,3 +66,7 @@
 
     def GetDefaultFilename(self):
         return self._filename
+
+    def ProcessContents(self):
+        # The blob may have changed due to WriteSymbols()
+        return self.ProcessContentsUpdate(self.data)
diff --git a/tools/binman/etype/files.py b/tools/binman/etype/files.py
index ce3832e..1feebd0 100644
--- a/tools/binman/etype/files.py
+++ b/tools/binman/etype/files.py
@@ -22,6 +22,7 @@
         - files-compress: Compression algorithm to use:
             none: No compression
             lz4: Use lz4 compression (via 'lz4' command-line utility)
+        - files-align: Align each file to the given alignment
 
     This entry reads a number of files and places each in a separate sub-entry
     within this entry. To access these you need to enable device-tree updates
@@ -38,6 +39,7 @@
             self.Raise("Missing 'pattern' property")
         self._files_compress = fdt_util.GetString(self._node, 'files-compress',
                                                   'none')
+        self._files_align = fdt_util.GetInt(self._node, 'files-align');
         self._require_matches = fdt_util.GetBool(self._node,
                                                 'require-matches')
 
@@ -55,6 +57,8 @@
             state.AddString(subnode, 'type', 'blob')
             state.AddString(subnode, 'filename', fname)
             state.AddString(subnode, 'compress', self._files_compress)
+            if self._files_align:
+                state.AddInt(subnode, 'align', self._files_align)
 
         # Read entries again, now that we have some
         self._ReadEntries()
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 3dd5f58..1ceadef 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -385,7 +385,7 @@
                 return entry.GetData()
         source_entry.Raise("Cannot find entry for node '%s'" % node.name)
 
-    def LookupSymbol(self, sym_name, optional, msg, base_addr):
+    def LookupSymbol(self, sym_name, optional, msg, base_addr, entries=None):
         """Look up a symbol in an ELF file
 
         Looks up a symbol in an ELF file. Only entry types which come from an
@@ -428,18 +428,20 @@
                              (msg, sym_name))
         entry_name, prop_name = m.groups()
         entry_name = entry_name.replace('_', '-')
-        entry = self._entries.get(entry_name)
+        if not entries:
+            entries = self._entries
+        entry = entries.get(entry_name)
         if not entry:
             if entry_name.endswith('-any'):
                 root = entry_name[:-4]
-                for name in self._entries:
+                for name in entries:
                     if name.startswith(root):
                         rest = name[len(root):]
                         if rest in ['', '-img', '-nodtb']:
-                            entry = self._entries[name]
+                            entry = entries[name]
         if not entry:
             err = ("%s: Entry '%s' not found in list (%s)" %
-                   (msg, entry_name, ','.join(self._entries.keys())))
+                   (msg, entry_name, ','.join(entries.keys())))
             if optional:
                 print('Warning: %s' % err, file=sys.stderr)
                 return None
@@ -603,10 +605,12 @@
     def ReadData(self, decomp=True):
         tout.Info("ReadData path='%s'" % self.GetPath())
         parent_data = self.section.ReadData(True)
-        tout.Info('%s: Reading data from offset %#x-%#x, size %#x' %
-                  (self.GetPath(), self.offset, self.offset + self.size,
-                   self.size))
-        data = parent_data[self.offset:self.offset + self.size]
+        offset = self.offset - self.section._skip_at_start
+        data = parent_data[offset:offset + self.size]
+        tout.Info(
+            '%s: Reading data from offset %#x-%#x (real %#x), size %#x, got %#x' %
+                  (self.GetPath(), self.offset, self.offset + self.size, offset,
+                   self.size, len(data)))
         return data
 
     def ReadChildData(self, child, decomp=True):
@@ -648,3 +652,47 @@
         """
         for entry in self._entries.values():
             entry.CheckMissing(missing_list)
+
+    def _CollectEntries(self, entries, entries_by_name, add_entry):
+        """Collect all the entries in an section
+
+        This builds up a dict of entries in this section and all subsections.
+        Entries are indexed by path and by name.
+
+        Since all paths are unique, entries will not have any conflicts. However
+        entries_by_name make have conflicts if two entries have the same name
+        (e.g. with different parent sections). In this case, an entry at a
+        higher level in the hierarchy will win over a lower-level entry.
+
+        Args:
+            entries: dict to put entries:
+                key: entry path
+                value: Entry object
+            entries_by_name: dict to put entries
+                key: entry name
+                value: Entry object
+            add_entry: Entry to add
+        """
+        entries[add_entry.GetPath()] = add_entry
+        to_add = add_entry.GetEntries()
+        if to_add:
+            for entry in to_add.values():
+                entries[entry.GetPath()] = entry
+            for entry in to_add.values():
+                self._CollectEntries(entries, entries_by_name, entry)
+        entries_by_name[add_entry.name] = add_entry
+
+    def MissingArgs(self, entry, missing):
+        """Report a missing argument, if enabled
+
+        For entries which require arguments, this reports an error if some are
+        missing. If missing entries are being ignored (e.g. because we read the
+        entry from an image rather than creating it), this function does
+        nothing.
+
+        Args:
+            missing: List of missing properties / entry args, each a string
+        """
+        if not self._ignore_missing:
+            entry.Raise('Missing required properties/entry args: %s' %
+                       (', '.join(missing)))
diff --git a/tools/binman/etype/u_boot_spl_bss_pad.py b/tools/binman/etype/u_boot_spl_bss_pad.py
index 596b2be..df15cd2 100644
--- a/tools/binman/etype/u_boot_spl_bss_pad.py
+++ b/tools/binman/etype/u_boot_spl_bss_pad.py
@@ -9,7 +9,6 @@
 
 from binman import elf
 from binman.entry import Entry
-from patman import command
 from binman.etype.blob import Entry_blob
 from patman import tools
 
diff --git a/tools/binman/etype/u_boot_spl_nodtb.py b/tools/binman/etype/u_boot_spl_nodtb.py
index 6f45293..c154cfd 100644
--- a/tools/binman/etype/u_boot_spl_nodtb.py
+++ b/tools/binman/etype/u_boot_spl_nodtb.py
@@ -2,7 +2,7 @@
 # Copyright (c) 2016 Google, Inc
 # Written by Simon Glass <sjg@chromium.org>
 #
-# Entry-type module for 'u-boot-nodtb.bin'
+# Entry-type module for 'u-boot-spl-nodtb.bin'
 #
 
 from binman.entry import Entry
diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py
index f734fba..eba5351 100644
--- a/tools/binman/etype/vblock.py
+++ b/tools/binman/etype/vblock.py
@@ -49,7 +49,7 @@
             EntryArg('kernelkey', str),
             EntryArg('preamble-flags', int)])
 
-    def ObtainContents(self):
+    def GetVblock(self):
         # Join up the data files to be signed
         input_data = b''
         for entry_phandle in self.content:
@@ -76,5 +76,16 @@
         ]
         #out.Notice("Sign '%s' into %s" % (', '.join(self.value), self.label))
         stdout = tools.Run('futility', *args)
-        self.SetContents(tools.ReadFile(output_fname))
+        return tools.ReadFile(output_fname)
+
+    def ObtainContents(self):
+        data = self.GetVblock()
+        if data is False:
+            return False
+        self.SetContents(data)
         return True
+
+    def ProcessContents(self):
+        # The blob may have changed due to WriteSymbols()
+        data = self.GetVblock()
+        return self.ProcessContentsUpdate(data)
diff --git a/tools/binman/fmap_util.py b/tools/binman/fmap_util.py
index b03fc28..8277619 100644
--- a/tools/binman/fmap_util.py
+++ b/tools/binman/fmap_util.py
@@ -53,8 +53,8 @@
 
 
 def NameToFmap(name):
-    if type(name) == bytes and sys.version_info[0] >= 3:
-        name = name.decode('utf-8')  # pragma: no cover (for Python 2)
+    if type(name) == bytes:
+        name = name.decode('utf-8')
     return name.replace('\0', '').replace('-', '_').upper()
 
 def ConvertName(field_names, fields):
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index e753a34..814e91d 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -1638,15 +1638,37 @@
                       str(e.exception))
 
     def _HandleVblockCommand(self, pipe_list):
-        """Fake calls to the futility utility"""
+        """Fake calls to the futility utility
+
+        The expected pipe is:
+
+           [('futility', 'vbutil_firmware', '--vblock',
+             'vblock.vblock', '--keyblock', 'devkeys/firmware.keyblock',
+             '--signprivate', 'devkeys/firmware_data_key.vbprivk',
+             '--version', '1', '--fv', 'input.vblock', '--kernelkey',
+             'devkeys/kernel_subkey.vbpubk', '--flags', '1')]
+
+        This writes to the output file (here, 'vblock.vblock'). If
+        self._hash_data is False, it writes VBLOCK_DATA, else it writes a hash
+        of the input data (here, 'input.vblock').
+        """
         if pipe_list[0][0] == 'futility':
             fname = pipe_list[0][3]
             with open(fname, 'wb') as fd:
-                fd.write(VBLOCK_DATA)
+                if self._hash_data:
+                    infile = pipe_list[0][11]
+                    m = hashlib.sha256()
+                    data = tools.ReadFile(infile)
+                    m.update(data)
+                    fd.write(m.digest())
+                else:
+                    fd.write(VBLOCK_DATA)
+
             return command.CommandResult()
 
     def testVblock(self):
         """Test for the Chromium OS Verified Boot Block"""
+        self._hash_data = False
         command.test_result = self._HandleVblockCommand
         entry_args = {
             'keydir': 'devkeys',
@@ -1677,6 +1699,29 @@
         self.assertIn("Node '/binman/vblock': Cannot find entry for node "
                       "'other'", str(e.exception))
 
+    def testVblockContent(self):
+        """Test that the vblock signs the right data"""
+        self._hash_data = True
+        command.test_result = self._HandleVblockCommand
+        entry_args = {
+            'keydir': 'devkeys',
+        }
+        data = self._DoReadFileDtb(
+            '189_vblock_content.dts', use_real_dtb=True, update_dtb=True,
+            entry_args=entry_args)[0]
+        hashlen = 32  # SHA256 hash is 32 bytes
+        self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
+        hashval = data[-hashlen:]
+        dtb = data[len(U_BOOT_DATA):-hashlen]
+
+        expected_data = U_BOOT_DATA + dtb
+
+        # The hashval should be a hash of the dtb
+        m = hashlib.sha256()
+        m.update(expected_data)
+        expected_hashval = m.digest()
+        self.assertEqual(expected_hashval, hashval)
+
     def testTpl(self):
         """Test that an image with TPL and its device tree can be created"""
         # ELF file with a '__bss_size' symbol
@@ -4139,6 +4184,67 @@
             }
         self.assertEqual(expected, props)
 
+    def testSymbolsSubsection(self):
+        """Test binman can assign symbols from a subsection"""
+        elf_fname = self.ElfTestFile('u_boot_binman_syms')
+        syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
+        addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
+        self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
+
+        self._SetupSplElf('u_boot_binman_syms')
+        data = self._DoReadFile('187_symbols_sub.dts')
+        sym_values = struct.pack('<LQLL', 0x00, 0x1c, 0x28, 0x04)
+        expected = (sym_values + U_BOOT_SPL_DATA[20:] +
+                    tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
+                    U_BOOT_SPL_DATA[20:])
+        self.assertEqual(expected, data)
+
+    def testReadImageEntryArg(self):
+        """Test reading an image that would need an entry arg to generate"""
+        entry_args = {
+            'cros-ec-rw-path': 'ecrw.bin',
+        }
+        data = self.data = self._DoReadFileDtb(
+            '188_image_entryarg.dts',use_real_dtb=True, update_dtb=True,
+            entry_args=entry_args)
+
+        image_fname = tools.GetOutputFilename('image.bin')
+        orig_image = control.images['image']
+
+        # This should not generate an error about the missing 'cros-ec-rw-path'
+        # since we are reading the image from a file. Compare with
+        # testEntryArgsRequired()
+        image = Image.FromFile(image_fname)
+        self.assertEqual(orig_image.GetEntries().keys(),
+                         image.GetEntries().keys())
+
+    def testFilesAlign(self):
+        """Test alignment with files"""
+        data = self._DoReadFile('190_files_align.dts')
+
+        # The first string is 15 bytes so will align to 16
+        expect = FILES_DATA[:15] + b'\0' + FILES_DATA[15:]
+        self.assertEqual(expect, data)
+
+    def testReadImageSkip(self):
+        """Test reading an image and accessing its FDT map"""
+        data = self.data = self._DoReadFileRealDtb('191_read_image_skip.dts')
+        image_fname = tools.GetOutputFilename('image.bin')
+        orig_image = control.images['image']
+        image = Image.FromFile(image_fname)
+        self.assertEqual(orig_image.GetEntries().keys(),
+                         image.GetEntries().keys())
+
+        orig_entry = orig_image.GetEntries()['fdtmap']
+        entry = image.GetEntries()['fdtmap']
+        self.assertEqual(orig_entry.offset, entry.offset)
+        self.assertEqual(orig_entry.size, entry.size)
+        self.assertEqual(16, entry.image_pos)
+
+        u_boot = image.GetEntries()['section'].GetEntries()['u-boot']
+
+        self.assertEquals(U_BOOT_DATA, u_boot.ReadData())
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/image.py b/tools/binman/image.py
index d65ab88..e949435 100644
--- a/tools/binman/image.py
+++ b/tools/binman/image.py
@@ -43,8 +43,13 @@
         test: True if this is being called from a test of Images. This this case
             there is no device tree defining the structure of the section, so
             we create a section manually.
+        ignore_missing: Ignore any missing entry arguments (i.e. don't raise an
+            exception). This should be used if the Image is being loaded from
+            a file rather than generated. In that case we obviously don't need
+            the entry arguments since the contents already exists.
     """
-    def __init__(self, name, node, copy_to_orig=True, test=False):
+    def __init__(self, name, node, copy_to_orig=True, test=False,
+                 ignore_missing=False):
         super().__init__(None, 'section', node, test=test)
         self.copy_to_orig = copy_to_orig
         self.name = 'main-section'
@@ -53,6 +58,7 @@
         self.fdtmap_dtb = None
         self.fdtmap_data = None
         self.allow_repack = False
+        self._ignore_missing = ignore_missing
         if not test:
             self.ReadNode()
 
@@ -100,7 +106,7 @@
 
         # Return an Image with the associated nodes
         root = dtb.GetRoot()
-        image = Image('image', root, copy_to_orig=False)
+        image = Image('image', root, copy_to_orig=False, ignore_missing=True)
 
         image.image_node = fdt_util.GetString(root, 'image-node', 'image')
         image.fdtmap_dtb = dtb
@@ -130,12 +136,7 @@
         Returns:
             True if the new data size is OK, False if expansion is needed
         """
-        sizes_ok = True
-        for entry in self._entries.values():
-            if not entry.ProcessContents():
-                sizes_ok = False
-                tout.Debug("Entry '%s' size change" % self._node.path)
-        return sizes_ok
+        return super().ProcessContents()
 
     def WriteSymbols(self):
         """Write symbol values into binary files for access at run time"""
@@ -324,3 +325,48 @@
             _DoLine(lines, _EntryToStrings(entry))
             selected_entries.append(entry)
         return selected_entries, lines, widths
+
+    def LookupImageSymbol(self, sym_name, optional, msg, base_addr):
+        """Look up a symbol in an ELF file
+
+        Looks up a symbol in an ELF file. Only entry types which come from an
+        ELF image can be used by this function.
+
+        This searches through this image including all of its subsections.
+
+        At present the only entry properties supported are:
+            offset
+            image_pos - 'base_addr' is added if this is not an end-at-4gb image
+            size
+
+        Args:
+            sym_name: Symbol name in the ELF file to look up in the format
+                _binman_<entry>_prop_<property> where <entry> is the name of
+                the entry and <property> is the property to find (e.g.
+                _binman_u_boot_prop_offset). As a special case, you can append
+                _any to <entry> to have it search for any matching entry. E.g.
+                _binman_u_boot_any_prop_offset will match entries called u-boot,
+                u-boot-img and u-boot-nodtb)
+            optional: True if the symbol is optional. If False this function
+                will raise if the symbol is not found
+            msg: Message to display if an error occurs
+            base_addr: Base address of image. This is added to the returned
+                image_pos in most cases so that the returned position indicates
+                where the targeted entry/binary has actually been loaded. But
+                if end-at-4gb is used, this is not done, since the binary is
+                already assumed to be linked to the ROM position and using
+                execute-in-place (XIP).
+
+        Returns:
+            Value that should be assigned to that symbol, or None if it was
+                optional and not found
+
+        Raises:
+            ValueError if the symbol is invalid or not found, or references a
+                property which is not supported
+        """
+        entries = OrderedDict()
+        entries_by_name = {}
+        self._CollectEntries(entries, entries_by_name, self)
+        return self.LookupSymbol(sym_name, optional, msg, base_addr,
+                                 entries_by_name)
diff --git a/tools/binman/state.py b/tools/binman/state.py
index 36bc513..bb3e36e 100644
--- a/tools/binman/state.py
+++ b/tools/binman/state.py
@@ -314,6 +314,16 @@
     for n in GetUpdateNodes(node):
         n.AddString(prop, value)
 
+def AddInt(node, prop, value):
+    """Add a new string property to affected device trees
+
+    Args:
+        prop_name: Name of property
+        val: Integer value of property
+    """
+    for n in GetUpdateNodes(node):
+        n.AddInt(prop, value)
+
 def SetInt(node, prop, value, for_repack=False):
     """Update an integer property in affected device trees with an integer value
 
diff --git a/tools/binman/test/084_files.dts b/tools/binman/test/084_files.dts
index 83ddb78..8f09afd 100644
--- a/tools/binman/test/084_files.dts
+++ b/tools/binman/test/084_files.dts
@@ -5,7 +5,7 @@
 	binman {
 		files {
 			pattern = "files/*.dat";
-			compress = "none";
+			files-compress = "none";
 		};
 	};
 };
diff --git a/tools/binman/test/187_symbols_sub.dts b/tools/binman/test/187_symbols_sub.dts
new file mode 100644
index 0000000..54511a7
--- /dev/null
+++ b/tools/binman/test/187_symbols_sub.dts
@@ -0,0 +1,22 @@
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		section {
+			pad-byte = <0xff>;
+			u-boot-spl {
+			};
+
+			u-boot {
+				offset = <24>;
+			};
+		};
+
+		u-boot-spl2 {
+			type = "u-boot-spl";
+		};
+	};
+};
diff --git a/tools/binman/test/188_image_entryarg.dts b/tools/binman/test/188_image_entryarg.dts
new file mode 100644
index 0000000..29d8149
--- /dev/null
+++ b/tools/binman/test/188_image_entryarg.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		size = <0xc00>;
+		u-boot {
+		};
+		cros-ec-rw {
+		};
+		fdtmap {
+		};
+		image-header {
+			location = "end";
+		};
+	};
+};
diff --git a/tools/binman/test/189_vblock_content.dts b/tools/binman/test/189_vblock_content.dts
new file mode 100644
index 0000000..dcc7444
--- /dev/null
+++ b/tools/binman/test/189_vblock_content.dts
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		u_boot: u-boot {
+		};
+
+		dtb: u-boot-dtb {
+		};
+
+		/*
+		 * Put the vblock after the dtb so that the dtb is updated
+		 * before the vblock reads its data. At present binman does not
+		 * understand dependencies between entries, but simply
+		 * iterates again when it thinks something needs to be
+		 * recalculated.
+		 */
+		vblock {
+			content = <&u_boot &dtb>;
+			keyblock = "firmware.keyblock";
+			signprivate = "firmware_data_key.vbprivk";
+			version = <1>;
+			kernelkey = "kernel_subkey.vbpubk";
+			preamble-flags = <1>;
+		};
+	};
+};
diff --git a/tools/binman/test/190_files_align.dts b/tools/binman/test/190_files_align.dts
new file mode 100644
index 0000000..213ba96
--- /dev/null
+++ b/tools/binman/test/190_files_align.dts
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	binman {
+		files {
+			pattern = "files/*.dat";
+			files-compress = "none";
+			files-align = <4>;
+		};
+	};
+};
diff --git a/tools/binman/test/191_read_image_skip.dts b/tools/binman/test/191_read_image_skip.dts
new file mode 100644
index 0000000..31df518
--- /dev/null
+++ b/tools/binman/test/191_read_image_skip.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		end-at-4gb;
+		size = <0x400>;
+		section {
+			size = <0x10>;
+			u-boot {
+			};
+		};
+		fdtmap {
+		};
+		image-header {
+			location = "end";
+		};
+	};
+};
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index 4a78c73..25ce513 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -460,10 +460,21 @@
             prop_name: Name of property to add
             val: String value of property
         """
-        if sys.version_info[0] >= 3:  # pragma: no cover
-            val = bytes(val, 'utf-8')
+        val = bytes(val, 'utf-8')
         self.AddData(prop_name, val + b'\0')
 
+    def AddInt(self, prop_name, val):
+        """Add a new integer property to a node
+
+        The device tree is marked dirty so that the value will be written to
+        the blob on the next sync.
+
+        Args:
+            prop_name: Name of property to add
+            val: Integer value of property
+        """
+        self.AddData(prop_name, struct.pack('>I', val))
+
     def AddSubnode(self, name):
         """Add a new subnode to the node
 
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index dc6943f..e8fbbd5 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -397,6 +397,12 @@
         data = self.fdt.getprop(self.node.Offset(), 'one')
         self.assertEqual(1, fdt32_to_cpu(data))
 
+        val = 1234
+        self.node.AddInt('integer', val)
+        self.dtb.Sync(auto_resize=True)
+        data = self.fdt.getprop(self.node.Offset(), 'integer')
+        self.assertEqual(val, fdt32_to_cpu(data))
+
         val = '123' + chr(0) + '456'
         self.node.AddString('string', val)
         self.dtb.Sync(auto_resize=True)
diff --git a/tools/patman/tools.py b/tools/patman/tools.py
index d8e01a3..10997e4 100644
--- a/tools/patman/tools.py
+++ b/tools/patman/tools.py
@@ -476,7 +476,8 @@
     fname = GetOutputFilename('%s.comp.tmp' % algo)
     WriteFile(fname, indata)
     if algo == 'lz4':
-        data = Run('lz4', '--no-frame-crc', '-c', fname, binary=True)
+        data = Run('lz4', '--no-frame-crc', '-B4', '-5', '-c', fname,
+                   binary=True)
     # cbfstool uses a very old version of lzma
     elif algo == 'lzma':
         outfname = GetOutputFilename('%s.comp.otmp' % algo)