Merge branch 'master_tmio_fixes' of https://source.denx.de/u-boot/custodians/u-boot-sh

- MMC fixes for Renesas platforms
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 7007997..55aceb5 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -322,6 +322,7 @@
 dtb-$(CONFIG_ARCH_MVEBU) +=			\
 	armada-3720-db.dtb			\
 	armada-3720-espressobin.dtb		\
+	armada-3720-ripe-atlas.dtb		\
 	armada-3720-turris-mox.dtb		\
 	armada-3720-eDPU.dtb			\
 	armada-3720-uDPU.dtb			\
diff --git a/arch/arm/dts/armada-3720-ripe-atlas.dts b/arch/arm/dts/armada-3720-ripe-atlas.dts
new file mode 100644
index 0000000..4457845
--- /dev/null
+++ b/arch/arm/dts/armada-3720-ripe-atlas.dts
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+ or X11
+/*
+ * Device Tree file for CZ.NIC' RIPE Atlas Probe
+ * 2021 by Marek Behún <marek.behun@nic.cz>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include "armada-372x.dtsi"
+
+/ {
+	model = "CZ.NIC's RIPE Atlas Probe";
+	compatible = "cznic,ripe-atlas", "marvell,armada3720",
+		     "marvell,armada3710";
+
+	aliases {
+		ethernet0 = &eth0;
+		mmc0 = &sdhci0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led {
+			gpios = <&gpiosb 21 GPIO_ACTIVE_LOW>;
+			color = <LED_COLOR_ID_RED>;
+			function = LED_FUNCTION_ACTIVITY;
+		};
+	};
+
+	vsdc_reg: vsdc-reg {
+		compatible = "regulator-gpio";
+		regulator-name = "vsdc";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+
+		gpios = <&gpiosb 23 GPIO_ACTIVE_HIGH>;
+		gpios-states = <0>;
+		states = <1800000 0x1
+			  3300000 0x0>;
+		enable-active-high;
+	};
+};
+
+&comphy {
+	status = "disabled";
+};
+
+&mdio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&smi_pins>;
+	status = "okay";
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
+
+&eth0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	phy-mode = "rgmii";
+	phy-handle = <&phy1>;
+	status = "okay";
+};
+
+&sdhci0 {
+	bus-width = <8>;
+	non-removable;
+	vqmmc-supply = <&vsdc_reg>;
+	marvell,pad-type = "sd";
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "okay";
+};
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 5c7f4bf..c80d858 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -144,8 +144,12 @@
 	select ATSHA204A
 
 config TARGET_TURRIS_MOX
-	bool "Support Turris Mox"
+	bool "Support CZ.NIC's Turris Mox / RIPE Atlas Probe"
 	select ARMADA_3700
+	select BOARD_TYPES
+	select ENV_IS_IN_MMC
+	select ENV_IS_IN_SPI_FLASH
+	select MULTI_DTB_FIT
 
 config TARGET_MVEBU_ARMADA_8K
 	bool "Support Armada 7k/8k platforms"
diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c
index eaaa68a..79f8877 100644
--- a/arch/arm/mach-mvebu/spl.c
+++ b/arch/arm/mach-mvebu/spl.c
@@ -71,8 +71,9 @@
 #error CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR must be set to 0
 #endif
 #if !defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET) || \
-    CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET != 0
-#error CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET must be set to 0
+    (CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET != 0 && \
+     CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET != 4096)
+#error CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_DATA_PART_OFFSET must be set to either 0 or 4096
 #endif
 #endif
 
diff --git a/arch/powerpc/cpu/mpc85xx/start.S b/arch/powerpc/cpu/mpc85xx/start.S
index e9c3042..b737d5d 100644
--- a/arch/powerpc/cpu/mpc85xx/start.S
+++ b/arch/powerpc/cpu/mpc85xx/start.S
@@ -1617,7 +1617,7 @@
 	mr	r10,r5		/* Save copy of Destination Address	*/
 
 	GET_GOT
-#ifndef CONFIG_SPL_SKIP_RELOCATE
+#if !defined(CONFIG_SPL_SKIP_RELOCATE) || !defined(CONFIG_SPL_BUILD)
 	mr	r3,r5				/* Destination Address	*/
 	lis	r4,CONFIG_VAL(SYS_MONITOR_BASE)@h		/* Source      Address	*/
 	ori	r4,r4,CONFIG_VAL(SYS_MONITOR_BASE)@l
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index ff7e558..241f397 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,11 +4,23 @@
  * and sandbox64 builds.
  */
 
+#include <config.h>
 #include <dt-bindings/input/input.h>
 
 #define USB_CLASS_HUB			9
 
 / {
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		event_log: tcg_event_log {
+			no-map;
+			reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+		};
+	};
+
 	binman {
 	};
 
@@ -342,6 +354,7 @@
 
 	tpm2 {
 		compatible = "sandbox,tpm2";
+		memory-region = <&event_log>;
 	};
 
 	triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 5b54651..2887f6c 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 
+#include <config.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/gpio/sandbox-gpio.h>
 #include <dt-bindings/input/input.h>
@@ -69,6 +70,17 @@
 		osd0 = "/osd";
 	};
 
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		event_log: tcg_event_log {
+			no-map;
+			reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+		};
+	};
+
 	binman: binman {
 	};
 
@@ -1436,6 +1448,7 @@
 
 	tpm2 {
 		compatible = "sandbox,tpm2";
+		memory-region = <&event_log>;
 	};
 
 	tpm {
diff --git a/board/CZ.NIC/turris_mox/mox_sp.c b/board/CZ.NIC/turris_mox/mox_sp.c
index 87f6751..11d8756 100644
--- a/board/CZ.NIC/turris_mox/mox_sp.c
+++ b/board/CZ.NIC/turris_mox/mox_sp.c
@@ -10,6 +10,8 @@
 #include <linux/delay.h>
 #include <mach/mbox.h>
 
+#include "mox_sp.h"
+
 const char *mox_sp_get_ecdsa_public_key(void)
 {
 	static char public_key[135];
@@ -42,12 +44,13 @@
 	mac[5] = t2;
 }
 
-int mbox_sp_get_board_info(u64 *sn, u8 *mac1, u8 *mac2, int *bv, int *ram)
+int mbox_sp_get_board_info(u64 *sn, u8 *mac1, u8 *mac2, int *bv, int *ram,
+			   enum cznic_a3720_board *board)
 {
-	u32 out[8];
+	u32 out[9];
 	int res;
 
-	res = mbox_do_cmd(MBOX_CMD_BOARD_INFO, NULL, 0, out, 8);
+	res = mbox_do_cmd(MBOX_CMD_BOARD_INFO, NULL, 0, out, 9);
 	if (res < 0)
 		return res;
 
@@ -69,5 +72,8 @@
 	if (mac2)
 		res_to_mac(mac2, out[6], out[7]);
 
+	if (board)
+		*board = out[8] + 1;
+
 	return 0;
 }
diff --git a/board/CZ.NIC/turris_mox/mox_sp.h b/board/CZ.NIC/turris_mox/mox_sp.h
index 83b6037..720880d 100644
--- a/board/CZ.NIC/turris_mox/mox_sp.h
+++ b/board/CZ.NIC/turris_mox/mox_sp.h
@@ -8,8 +8,14 @@
 
 #include <common.h>
 
+enum cznic_a3720_board {
+	BOARD_UNDEFINED		= 0x0,
+	BOARD_TURRIS_MOX	= 0x1,
+	BOARD_RIPE_ATLAS	= 0x3,
+};
+
 const char *mox_sp_get_ecdsa_public_key(void);
 int mbox_sp_get_board_info(u64 *sn, u8 *mac1, u8 *mac2, int *bv,
-			   int *ram);
+			   int *ram, enum cznic_a3720_board *board);
 
 #endif /* _BOARD_CZNIC_TURRIS_MOX_MOX_SP_H_ */
diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c
index 370c266..63b8699 100644
--- a/board/CZ.NIC/turris_mox/turris_mox.c
+++ b/board/CZ.NIC/turris_mox/turris_mox.c
@@ -15,6 +15,7 @@
 #include <dm.h>
 #include <dm/of_extra.h>
 #include <env.h>
+#include <env_internal.h>
 #include <event.h>
 #include <fdt_support.h>
 #include <init.h>
@@ -45,6 +46,26 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+int board_fit_config_name_match(const char *name)
+{
+	if (!gd->board_type) {
+		enum cznic_a3720_board board;
+
+		if (mbox_sp_get_board_info(NULL, NULL, NULL, NULL, NULL,
+					   &board) < 0) {
+			printf("Cannot determine board, defaulting to Turris MOX!\n");
+			board = BOARD_TURRIS_MOX;
+		}
+
+		gd->board_type = board;
+	}
+
+	return !((gd->board_type == BOARD_TURRIS_MOX &&
+		  !strcmp(name, "armada-3720-turris-mox")) ||
+		 (gd->board_type == BOARD_RIPE_ATLAS &&
+		  !strcmp(name, "armada-3720-ripe-atlas")));
+}
+
 #if defined(CONFIG_OF_BOARD_FIXUP)
 int board_fix_fdt(void *blob)
 {
@@ -53,6 +74,9 @@
 	int i, size, ret;
 	bool eth1_sgmii;
 
+	if (gd->board_type != BOARD_TURRIS_MOX)
+		return 0;
+
 	/*
 	 * SPI driver is not loaded in driver model yet, but we have to find out
 	 * if pcie should be enabled in U-Boot's device tree. Therefore we have
@@ -388,16 +412,23 @@
 
 int misc_init_r(void)
 {
+	int i, ret, addrcnt;
 	u8 mac[2][6];
-	int i, ret;
 
-	ret = mbox_sp_get_board_info(NULL, mac[0], mac[1], NULL, NULL);
+	ret = mbox_sp_get_board_info(NULL, mac[0], mac[1], NULL, NULL, NULL);
 	if (ret < 0) {
 		printf("Cannot read data from OTP!\n");
 		return 0;
 	}
 
+	if (gd->board_type == BOARD_TURRIS_MOX)
+		addrcnt = 2;
+	else if (gd->board_type == BOARD_RIPE_ATLAS)
+		addrcnt = 1;
+	else
+		addrcnt = 0;
+
-	for (i = 0; i < 2; ++i) {
+	for (i = 0; i < addrcnt; ++i) {
 		u8 oldmac[6];
 
 		if (is_valid_ethaddr(mac[i]) &&
@@ -405,7 +436,13 @@
 			eth_env_set_enetaddr_by_index("eth", i, mac[i]);
 	}
 
-	load_spi_dtb();
+	if (gd->board_type == BOARD_RIPE_ATLAS) {
+		env_set("board", "ripe_atlas");
+		env_set("board_name", "ripe_atlas");
+		env_set("fdtfile", "marvell/armada-3720-ripe-atlas.dtb");
+	} else {
+		load_spi_dtb();
+	}
 
 	return 0;
 }
@@ -528,14 +565,15 @@
 int show_board_info(void)
 {
 	int i, ret, board_version, ram_size, is_sd;
-	const char *pub_key;
+	const char *pub_key, *model;
 	const u8 *topology;
 	u64 serial_number;
 
-	printf("Model: CZ.NIC Turris Mox Board\n");
+	model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+	printf("Model: %s\n", model);
 
 	ret = mbox_sp_get_board_info(&serial_number, NULL, NULL, &board_version,
-				     &ram_size);
+				     &ram_size, NULL);
 	if (ret < 0) {
 		printf("  Cannot read board info: %i\n", ret);
 	} else {
@@ -550,6 +588,9 @@
 	else
 		printf("  Cannot read ECDSA Public Key\n");
 
+	if (gd->board_type != BOARD_TURRIS_MOX)
+		return 0;
+
 	ret = mox_get_topology(&topology, &module_count, &is_sd);
 	if (ret)
 		printf("Cannot read module topology!\n");
@@ -668,10 +709,24 @@
 	return NULL;
 }
 
+enum env_location env_get_location(enum env_operation op, int prio)
+{
+	if (prio > 0)
+		return ENVL_UNKNOWN;
+
+	if (gd->board_type == BOARD_RIPE_ATLAS)
+		return ENVL_MMC;
+
+	return ENVL_SPI_FLASH;
+}
+
 static int last_stage_init(void)
 {
 	struct gpio_desc reset_gpio = {};
 
+	if (gd->board_type != BOARD_TURRIS_MOX)
+		return 0;
+
 	/* configure modules */
 	if (get_reset_gpio(&reset_gpio) < 0)
 		goto handle_reset_btn;
@@ -801,6 +856,9 @@
 {
 	int res;
 
+	if (gd->board_type != BOARD_TURRIS_MOX)
+		return 0;
+
 	/*
 	 * If MOX B (PCI), MOX F (USB) or MOX G (Passthrough PCI) modules are
 	 * connected, enable the PCIe node.
diff --git a/board/siemens/iot2050/board.c b/board/siemens/iot2050/board.c
index e35e55f..0b0686e 100644
--- a/board/siemens/iot2050/board.c
+++ b/board/siemens/iot2050/board.c
@@ -155,19 +155,20 @@
 		strstr((char *)info->name, "IOT2050-ADVANCED") != NULL;
 }
 
-static bool board_is_sr1(void)
+static bool board_is_pg1(void)
 {
 	struct iot2050_info *info = IOT2050_INFO_DATA;
 
 	return info->magic == IOT2050_INFO_MAGIC &&
-		strstr((char *)info->name, "-PG2") == NULL;
+		(strcmp((char *)info->name, "IOT2050-BASIC") == 0 ||
+		 strcmp((char *)info->name, "IOT2050-ADVANCED") == 0);
 }
 
 static bool board_is_m2(void)
 {
 	struct iot2050_info *info = IOT2050_INFO_DATA;
 
-	return !board_is_sr1() && info->magic == IOT2050_INFO_MAGIC &&
+	return info->magic == IOT2050_INFO_MAGIC &&
 		strcmp((char *)info->name, "IOT2050-ADVANCED-M2") == 0;
 }
 
@@ -217,14 +218,14 @@
 	}
 
 	if (board_is_advanced()) {
-		if (board_is_sr1())
+		if (board_is_pg1())
 			fdtfile = "ti/k3-am6548-iot2050-advanced.dtb";
 		else if(board_is_m2())
 			fdtfile = "ti/k3-am6548-iot2050-advanced-m2.dtb";
 		else
 			fdtfile = "ti/k3-am6548-iot2050-advanced-pg2.dtb";
 	} else {
-		if (board_is_sr1())
+		if (board_is_pg1())
 			fdtfile = "ti/k3-am6528-iot2050-basic.dtb";
 		else
 			fdtfile = "ti/k3-am6528-iot2050-basic-pg2.dtb";
diff --git a/board/socionext/developerbox/developerbox.c b/board/socionext/developerbox/developerbox.c
index 9585944..ac4415f 100644
--- a/board/socionext/developerbox/developerbox.c
+++ b/board/socionext/developerbox/developerbox.c
@@ -20,39 +20,18 @@
 
 #if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
 struct efi_fw_image fw_images[] = {
-#if CONFIG_IS_ENABLED(FWU_MULTI_BANK_UPDATE)
 	{
 		.image_type_id = DEVELOPERBOX_FIP_IMAGE_GUID,
 		.fw_name = u"DEVELOPERBOX-FIP",
 		.image_index = 1,
 	},
-#else
-	{
-		.image_type_id = DEVELOPERBOX_UBOOT_IMAGE_GUID,
-		.fw_name = u"DEVELOPERBOX-UBOOT",
-		.image_index = 1,
-	},
-	{
-		.image_type_id = DEVELOPERBOX_FIP_IMAGE_GUID,
-		.fw_name = u"DEVELOPERBOX-FIP",
-		.image_index = 2,
-	},
-	{
-		.image_type_id = DEVELOPERBOX_OPTEE_IMAGE_GUID,
-		.fw_name = u"DEVELOPERBOX-OPTEE",
-		.image_index = 3,
-	},
-#endif
 };
 
 struct efi_capsule_update_info update_info = {
-	.dfu_string = "mtd nor1=u-boot.bin raw 200000 100000;"
-			"fip.bin raw 180000 78000;"
-			"optee.bin raw 500000 100000",
+	.dfu_string = "mtd nor1=fip.bin raw 600000 400000",
 	.num_images = ARRAY_SIZE(fw_images),
 	.images = fw_images,
 };
-
 #endif /* EFI_HAVE_CAPSULE_SUPPORT */
 
 static struct mm_region sc2a11_mem_map[] = {
diff --git a/boot/Kconfig b/boot/Kconfig
index a01e6cb..fbc49c5 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -685,6 +685,38 @@
 	  loaded. If a board needs the legacy image format support in this
 	  case, enable it here.
 
+config MEASURED_BOOT
+	bool "Measure boot images and configuration when booting without EFI"
+	depends on HASH && TPM_V2
+	help
+	  This option enables measurement of the boot process when booting
+	  without UEFI . Measurement involves creating cryptographic hashes
+	  of the binary images that are booting and storing them in the TPM.
+	  In addition, a log of these hashes is stored in memory for the OS
+	  to verify the booted images and configuration. Enable this if the
+	  OS has configured some memory area for the event log and you intend
+	  to use some attestation tools on your system.
+
+if MEASURED_BOOT
+	config MEASURE_DEVICETREE
+	bool "Measure the devicetree image"
+	default y if MEASURED_BOOT
+	help
+	  On some platforms, the devicetree is not static as it may contain
+	  random MAC addresses or other such data that changes each boot.
+	  Therefore, it should not be measured into the TPM. In that case,
+	  disable the measurement here.
+
+	config MEASURE_IGNORE_LOG
+	bool "Ignore the existing event log"
+	default n
+	help
+	  On platforms that use an event log memory region that persists
+	  through system resets and are the first stage bootloader, then
+	  this option should be enabled to ignore any existing data in the
+	  event log memory region.
+endif # MEASURED_BOOT
+
 config SUPPORT_RAW_INITRD
 	bool "Enable raw initrd images"
 	help
diff --git a/boot/bootm.c b/boot/bootm.c
index 8f96a80..cb61485 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -23,6 +23,7 @@
 #include <asm/global_data.h>
 #include <asm/io.h>
 #include <linux/sizes.h>
+#include <tpm-v2.h>
 #if defined(CONFIG_CMD_USB)
 #include <usb.h>
 #endif
@@ -673,6 +674,75 @@
 	return 0;
 }
 
+int bootm_measure(struct bootm_headers *images)
+{
+	int ret = 0;
+
+	/* Skip measurement if EFI is going to do it */
+	if (images->os.os == IH_OS_EFI &&
+	    IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) &&
+	    IS_ENABLED(CONFIG_BOOTM_EFI))
+		return ret;
+
+	if (IS_ENABLED(CONFIG_MEASURED_BOOT)) {
+		struct tcg2_event_log elog;
+		struct udevice *dev;
+		void *initrd_buf;
+		void *image_buf;
+		const char *s;
+		u32 rd_len;
+		bool ign;
+
+		elog.log_size = 0;
+		ign = IS_ENABLED(CONFIG_MEASURE_IGNORE_LOG);
+		ret = tcg2_measurement_init(&dev, &elog, ign);
+		if (ret)
+			return ret;
+
+		image_buf = map_sysmem(images->os.image_start,
+				       images->os.image_len);
+		ret = tcg2_measure_data(dev, &elog, 8, images->os.image_len,
+					image_buf, EV_COMPACT_HASH,
+					strlen("linux") + 1, (u8 *)"linux");
+		if (ret)
+			goto unmap_image;
+
+		rd_len = images->rd_end - images->rd_start;
+		initrd_buf = map_sysmem(images->rd_start, rd_len);
+		ret = tcg2_measure_data(dev, &elog, 9, rd_len, initrd_buf,
+					EV_COMPACT_HASH, strlen("initrd") + 1,
+					(u8 *)"initrd");
+		if (ret)
+			goto unmap_initrd;
+
+		if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) {
+			ret = tcg2_measure_data(dev, &elog, 0, images->ft_len,
+						(u8 *)images->ft_addr,
+						EV_TABLE_OF_DEVICES,
+						strlen("dts") + 1,
+						(u8 *)"dts");
+			if (ret)
+				goto unmap_initrd;
+		}
+
+		s = env_get("bootargs");
+		if (!s)
+			s = "";
+		ret = tcg2_measure_data(dev, &elog, 1, strlen(s) + 1, (u8 *)s,
+					EV_PLATFORM_CONFIG_FLAGS,
+					strlen(s) + 1, (u8 *)s);
+
+unmap_initrd:
+		unmap_sysmem(initrd_buf);
+
+unmap_image:
+		unmap_sysmem(image_buf);
+		tcg2_measurement_term(dev, &elog, ret != 0);
+	}
+
+	return ret;
+}
+
 /**
  * Execute selected states of the bootm command.
  *
@@ -724,6 +794,10 @@
 	if (!ret && (states & BOOTM_STATE_FINDOTHER))
 		ret = bootm_find_other(cmdtp, flag, argc, argv);
 
+	if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !ret &&
+	    (states & BOOTM_STATE_MEASURE))
+		bootm_measure(images);
+
 	/* Load the OS */
 	if (!ret && (states & BOOTM_STATE_LOADOS)) {
 		iflag = bootm_disable_interrupts();
diff --git a/cmd/booti.c b/cmd/booti.c
index 1d531bd..a6c7db2 100644
--- a/cmd/booti.c
+++ b/cmd/booti.c
@@ -127,6 +127,7 @@
 #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
 			      BOOTM_STATE_RAMDISK |
 #endif
+			      BOOTM_STATE_MEASURE |
 			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
 			      BOOTM_STATE_OS_GO,
 			      &images, 1);
diff --git a/cmd/bootm.c b/cmd/bootm.c
index 3e504cc..6ded091 100644
--- a/cmd/bootm.c
+++ b/cmd/bootm.c
@@ -147,6 +147,8 @@
 		BOOTM_STATE_OS_GO;
 	if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
 		states |= BOOTM_STATE_RAMDISK;
+	if (IS_ENABLED(CONFIG_MEASURED_BOOT))
+		states |= BOOTM_STATE_MEASURE;
 	if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS))
 		states |= BOOTM_STATE_OS_CMDLINE;
 	ret = do_bootm_states(cmdtp, flag, argc, argv, states, &images, 1);
diff --git a/cmd/bootz.c b/cmd/bootz.c
index 742889f..dd6fe49 100644
--- a/cmd/bootz.c
+++ b/cmd/bootz.c
@@ -81,6 +81,7 @@
 #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
 			      BOOTM_STATE_RAMDISK |
 #endif
+			      BOOTM_STATE_MEASURE |
 			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
 			      BOOTM_STATE_OS_GO,
 			      &images, 1);
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c
index ca24a5c..744b1c2 100644
--- a/cmd/mvebu/bubt.c
+++ b/cmd/mvebu/bubt.c
@@ -240,9 +240,16 @@
 #endif
 
 	/* SD reserves LBA-0 for MBR and boots from LBA-1,
-	 * MMC/eMMC boots from LBA-0
+	 * MMC/eMMC boots from LBA-0 and LBA-4096
 	 */
-	start_lba = IS_SD(mmc) ? 1 : 0;
+	if (IS_SD(mmc))
+		start_lba = 1;
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+	else if (part)
+		start_lba = 0;
+#endif
+	else
+		start_lba = 4096;
 #ifdef CONFIG_BLK
 	blk_count = image_size / mmc->write_bl_len;
 	if (image_size % mmc->write_bl_len)
diff --git a/configs/ad401_defconfig b/configs/ad401_defconfig
index b9aca3a..b44b9c6 100644
--- a/configs/ad401_defconfig
+++ b/configs/ad401_defconfig
@@ -51,6 +51,7 @@
 CONFIG_MESON_SERIAL=y
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
+CONFIG_MESON_SPIFC_A1=y
 CONFIG_USB=y
 CONFIG_DM_USB_GADGET=y
 CONFIG_USB_GADGET=y
diff --git a/configs/bananapi-cm4-cm4io_defconfig b/configs/bananapi-cm4-cm4io_defconfig
index bb43cc4..116147f 100644
--- a/configs/bananapi-cm4-cm4io_defconfig
+++ b/configs/bananapi-cm4-cm4io_defconfig
@@ -17,12 +17,17 @@
 CONFIG_PCI=y
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -37,6 +42,7 @@
 CONFIG_SARADC_MESON=y
 CONFIG_BUTTON=y
 CONFIG_BUTTON_ADC=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_MDIO=y
diff --git a/configs/bananapi-m2-pro_defconfig b/configs/bananapi-m2-pro_defconfig
index 4f8cec9..2a3958b 100644
--- a/configs/bananapi-m2-pro_defconfig
+++ b/configs/bananapi-m2-pro_defconfig
@@ -16,12 +16,17 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -33,6 +38,7 @@
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ADC=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_MDIO=y
diff --git a/configs/bananapi-m2s_defconfig b/configs/bananapi-m2s_defconfig
index 3dd8ddc..405ce3a 100644
--- a/configs/bananapi-m2s_defconfig
+++ b/configs/bananapi-m2s_defconfig
@@ -18,12 +18,17 @@
 CONFIG_DEBUG_UART=y
 CONFIG_AHCI=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -36,6 +41,7 @@
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ADC=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_MDIO=y
diff --git a/configs/bananapi-m5_defconfig b/configs/bananapi-m5_defconfig
index 696d2fc..6de5d5f 100644
--- a/configs/bananapi-m5_defconfig
+++ b/configs/bananapi-m5_defconfig
@@ -16,12 +16,17 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -33,6 +38,7 @@
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ADC=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_MDIO=y
diff --git a/configs/beelink-gsking-x_defconfig b/configs/beelink-gsking-x_defconfig
index c022097..99e36e9 100644
--- a/configs/beelink-gsking-x_defconfig
+++ b/configs/beelink-gsking-x_defconfig
@@ -17,12 +17,17 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -32,6 +37,7 @@
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
diff --git a/configs/beelink-gt1-ultimate_defconfig b/configs/beelink-gt1-ultimate_defconfig
index c0d22c4..1313dde 100644
--- a/configs/beelink-gt1-ultimate_defconfig
+++ b/configs/beelink-gt1-ultimate_defconfig
@@ -16,6 +16,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
@@ -23,6 +27,7 @@
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_ADC=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -33,6 +38,7 @@
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
diff --git a/configs/beelink-gtking_defconfig b/configs/beelink-gtking_defconfig
index 42e1ba6..5c21d8e 100644
--- a/configs/beelink-gtking_defconfig
+++ b/configs/beelink-gtking_defconfig
@@ -17,12 +17,17 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -32,6 +37,7 @@
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
diff --git a/configs/beelink-gtkingpro_defconfig b/configs/beelink-gtkingpro_defconfig
index a371332..37bb4cd 100644
--- a/configs/beelink-gtkingpro_defconfig
+++ b/configs/beelink-gtkingpro_defconfig
@@ -17,12 +17,17 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -32,6 +37,7 @@
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
diff --git a/configs/jethub_j100_defconfig b/configs/jethub_j100_defconfig
index 549d551..1e6d5c7 100644
--- a/configs/jethub_j100_defconfig
+++ b/configs/jethub_j100_defconfig
@@ -18,6 +18,10 @@
 CONFIG_SYS_LOAD_ADDR=0x01000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
@@ -26,6 +30,7 @@
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_EEPROM=y
 CONFIG_CMD_ADC=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 CONFIG_RANDOM_UUID=y
 CONFIG_CMD_I2C=y
@@ -39,6 +44,7 @@
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_MESON=y
 CONFIG_MMC_MESON_GX=y
diff --git a/configs/jethub_j80_defconfig b/configs/jethub_j80_defconfig
index df9b8f3..b370e5d 100644
--- a/configs/jethub_j80_defconfig
+++ b/configs/jethub_j80_defconfig
@@ -18,6 +18,10 @@
 CONFIG_SYS_LOAD_ADDR=0x01000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_CONSOLE_MUX=y
 # CONFIG_DISPLAY_CPUINFO is not set
@@ -27,6 +31,7 @@
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_EEPROM=y
 CONFIG_CMD_ADC=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 CONFIG_RANDOM_UUID=y
 CONFIG_CMD_I2C=y
@@ -40,6 +45,7 @@
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_MESON=y
 CONFIG_MMC_MESON_GX=y
diff --git a/configs/khadas-vim2_defconfig b/configs/khadas-vim2_defconfig
index 38b9b2b..28e9052 100644
--- a/configs/khadas-vim2_defconfig
+++ b/configs/khadas-vim2_defconfig
@@ -16,6 +16,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_CONSOLE_MUX=y
 # CONFIG_DISPLAY_CPUINFO is not set
@@ -24,6 +28,7 @@
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_ADC=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -36,6 +41,7 @@
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
diff --git a/configs/khadas-vim3_android_ab_defconfig b/configs/khadas-vim3_android_ab_defconfig
index ccd6f6f..b41c266 100644
--- a/configs/khadas-vim3_android_ab_defconfig
+++ b/configs/khadas-vim3_android_ab_defconfig
@@ -7,6 +7,7 @@
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x20000000
 CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x0
 CONFIG_DM_GPIO=y
 CONFIG_DEFAULT_DEVICE_TREE="meson-g12b-a311d-khadas-vim3"
 CONFIG_OF_LIBFDT_OVERLAY=y
@@ -19,6 +20,10 @@
 CONFIG_PCI=y
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
@@ -45,7 +50,10 @@
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_AVB=y
 CONFIG_OF_CONTROL=y
+CONFIG_ENV_IS_IN_MMC=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_SYS_MMC_ENV_DEV=2
+CONFIG_SYS_MMC_ENV_PART=2
 CONFIG_ADC=y
 CONFIG_SARADC_MESON=y
 CONFIG_BUTTON=y
diff --git a/configs/khadas-vim3_android_defconfig b/configs/khadas-vim3_android_defconfig
index 5c3d565..88197f5 100644
--- a/configs/khadas-vim3_android_defconfig
+++ b/configs/khadas-vim3_android_defconfig
@@ -7,6 +7,7 @@
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x20000000
 CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x0
 CONFIG_DM_GPIO=y
 CONFIG_DEFAULT_DEVICE_TREE="meson-g12b-a311d-khadas-vim3"
 CONFIG_OF_LIBFDT_OVERLAY=y
@@ -19,6 +20,10 @@
 CONFIG_PCI=y
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
@@ -43,7 +48,10 @@
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_AVB=y
 CONFIG_OF_CONTROL=y
+CONFIG_ENV_IS_IN_MMC=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_SYS_MMC_ENV_DEV=2
+CONFIG_SYS_MMC_ENV_PART=2
 CONFIG_ADC=y
 CONFIG_SARADC_MESON=y
 CONFIG_BUTTON=y
diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig
index d611124..5df4b92 100644
--- a/configs/khadas-vim3_defconfig
+++ b/configs/khadas-vim3_defconfig
@@ -18,12 +18,17 @@
 CONFIG_PCI=y
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 # CONFIG_CMD_LOADS is not set
@@ -41,6 +46,7 @@
 CONFIG_SARADC_MESON=y
 CONFIG_BUTTON=y
 CONFIG_BUTTON_ADC=y
+CONFIG_DFU_RAM=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_MESON=y
 CONFIG_MMC_MESON_GX=y
diff --git a/configs/khadas-vim3l_android_ab_defconfig b/configs/khadas-vim3l_android_ab_defconfig
index 0d6de80..3381d2e 100644
--- a/configs/khadas-vim3l_android_ab_defconfig
+++ b/configs/khadas-vim3l_android_ab_defconfig
@@ -7,6 +7,7 @@
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x20000000
 CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x0
 CONFIG_DM_GPIO=y
 CONFIG_DEFAULT_DEVICE_TREE="meson-sm1-khadas-vim3l"
 CONFIG_OF_LIBFDT_OVERLAY=y
@@ -19,6 +20,10 @@
 CONFIG_PCI=y
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
@@ -45,7 +50,10 @@
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_AVB=y
 CONFIG_OF_CONTROL=y
+CONFIG_ENV_IS_IN_MMC=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_SYS_MMC_ENV_DEV=2
+CONFIG_SYS_MMC_ENV_PART=2
 CONFIG_ADC=y
 CONFIG_SARADC_MESON=y
 CONFIG_BUTTON=y
diff --git a/configs/khadas-vim3l_android_defconfig b/configs/khadas-vim3l_android_defconfig
index 827752f..3fa587e 100644
--- a/configs/khadas-vim3l_android_defconfig
+++ b/configs/khadas-vim3l_android_defconfig
@@ -7,6 +7,7 @@
 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
 CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x20000000
 CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x0
 CONFIG_DM_GPIO=y
 CONFIG_DEFAULT_DEVICE_TREE="meson-sm1-khadas-vim3l"
 CONFIG_OF_LIBFDT_OVERLAY=y
@@ -19,6 +20,10 @@
 CONFIG_PCI=y
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
@@ -43,7 +48,10 @@
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_AVB=y
 CONFIG_OF_CONTROL=y
+CONFIG_ENV_IS_IN_MMC=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_SYS_MMC_ENV_DEV=2
+CONFIG_SYS_MMC_ENV_PART=2
 CONFIG_ADC=y
 CONFIG_SARADC_MESON=y
 CONFIG_BUTTON=y
diff --git a/configs/khadas-vim3l_defconfig b/configs/khadas-vim3l_defconfig
index f959d33..de8fdd8 100644
--- a/configs/khadas-vim3l_defconfig
+++ b/configs/khadas-vim3l_defconfig
@@ -18,12 +18,17 @@
 CONFIG_PCI=y
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 # CONFIG_CMD_LOADS is not set
@@ -41,6 +46,7 @@
 CONFIG_SARADC_MESON=y
 CONFIG_BUTTON=y
 CONFIG_BUTTON_ADC=y
+CONFIG_DFU_RAM=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_MESON=y
 CONFIG_MMC_MESON_GX=y
diff --git a/configs/khadas-vim_defconfig b/configs/khadas-vim_defconfig
index 6a9e851..d27ab6f 100644
--- a/configs/khadas-vim_defconfig
+++ b/configs/khadas-vim_defconfig
@@ -16,6 +16,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_CONSOLE_MUX=y
 # CONFIG_DISPLAY_CPUINFO is not set
@@ -24,6 +28,7 @@
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_ADC=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -34,6 +39,7 @@
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_MESON_GXL=y
 CONFIG_DM_MDIO=y
diff --git a/configs/libretech-ac_defconfig b/configs/libretech-ac_defconfig
index 0fa7f3d..bc17b42 100644
--- a/configs/libretech-ac_defconfig
+++ b/configs/libretech-ac_defconfig
@@ -19,6 +19,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_USE_PREBOOT=y
 # CONFIG_DISPLAY_CPUINFO is not set
@@ -28,6 +32,7 @@
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_ADC=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -41,6 +46,7 @@
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
diff --git a/configs/libretech-cc_defconfig b/configs/libretech-cc_defconfig
index dee03b3..baa9b1b 100644
--- a/configs/libretech-cc_defconfig
+++ b/configs/libretech-cc_defconfig
@@ -16,6 +16,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
@@ -23,6 +27,7 @@
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_ADC=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -33,6 +38,7 @@
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_MESON_GXL=y
 CONFIG_DM_MDIO=y
diff --git a/configs/libretech-cc_v2_defconfig b/configs/libretech-cc_v2_defconfig
index 628c6ba..ba74b24 100644
--- a/configs/libretech-cc_v2_defconfig
+++ b/configs/libretech-cc_v2_defconfig
@@ -18,6 +18,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_USE_PREBOOT=y
 # CONFIG_DISPLAY_CPUINFO is not set
@@ -26,6 +30,7 @@
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -37,6 +42,7 @@
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
diff --git a/configs/libretech-s905d-pc_defconfig b/configs/libretech-s905d-pc_defconfig
index 1c8787c..cd138d6 100644
--- a/configs/libretech-s905d-pc_defconfig
+++ b/configs/libretech-s905d-pc_defconfig
@@ -19,6 +19,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_USE_PREBOOT=y
 # CONFIG_DISPLAY_CPUINFO is not set
@@ -27,6 +31,7 @@
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_ADC=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -39,6 +44,7 @@
 CONFIG_OF_CONTROL=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_SPI_FLASH=y
diff --git a/configs/libretech-s912-pc_defconfig b/configs/libretech-s912-pc_defconfig
index 170492e..dabb4ca 100644
--- a/configs/libretech-s912-pc_defconfig
+++ b/configs/libretech-s912-pc_defconfig
@@ -18,6 +18,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_USE_PREBOOT=y
 # CONFIG_DISPLAY_CPUINFO is not set
@@ -26,6 +30,7 @@
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_ADC=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -38,6 +43,7 @@
 CONFIG_OF_CONTROL=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_SPI_FLASH=y
diff --git a/configs/nanopi-k2_defconfig b/configs/nanopi-k2_defconfig
index ef101cf..41dbf79 100644
--- a/configs/nanopi-k2_defconfig
+++ b/configs/nanopi-k2_defconfig
@@ -15,6 +15,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
diff --git a/configs/nsa310s_defconfig b/configs/nsa310s_defconfig
index ff489562..038ef42 100644
--- a/configs/nsa310s_defconfig
+++ b/configs/nsa310s_defconfig
@@ -19,7 +19,8 @@
 CONFIG_IDENT_STRING="\nZyXEL NSA310S/320S 1/2-Bay Power Media Server"
 CONFIG_SYS_LOAD_ADDR=0x800000
 CONFIG_DEBUG_UART=y
-CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTSTD_FULL=y
+CONFIG_BOOTSTD_DEFAULTS=y
 CONFIG_BOOTDELAY=3
 CONFIG_USE_PREBOOT=y
 # CONFIG_DISPLAY_BOARDINFO is not set
diff --git a/configs/odroid-c2_defconfig b/configs/odroid-c2_defconfig
index 9481cbc..5f9f323e 100644
--- a/configs/odroid-c2_defconfig
+++ b/configs/odroid-c2_defconfig
@@ -15,6 +15,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
diff --git a/configs/odroid-c4_defconfig b/configs/odroid-c4_defconfig
index 315dc5c..fe1f861 100644
--- a/configs/odroid-c4_defconfig
+++ b/configs/odroid-c4_defconfig
@@ -17,12 +17,17 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -34,6 +39,7 @@
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ADC=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_MDIO=y
diff --git a/configs/odroid-go-ultra_defconfig b/configs/odroid-go-ultra_defconfig
index fb8ce5c..bc0bf9b 100644
--- a/configs/odroid-go-ultra_defconfig
+++ b/configs/odroid-go-ultra_defconfig
@@ -17,11 +17,16 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -37,6 +42,7 @@
 CONFIG_BUTTON=y
 CONFIG_BUTTON_ADC=y
 CONFIG_BUTTON_GPIO=y
+CONFIG_DFU_RAM=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_MESON=y
 CONFIG_MMC_MESON_GX=y
diff --git a/configs/odroid-hc4_defconfig b/configs/odroid-hc4_defconfig
index b250715..4316811 100644
--- a/configs/odroid-hc4_defconfig
+++ b/configs/odroid-hc4_defconfig
@@ -19,12 +19,17 @@
 CONFIG_DEBUG_UART=y
 CONFIG_AHCI=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -41,6 +46,7 @@
 CONFIG_SATA=y
 CONFIG_SCSI_AHCI=y
 CONFIG_AHCI_PCI=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
diff --git a/configs/odroid-n2_defconfig b/configs/odroid-n2_defconfig
index e55de38..9694f04 100644
--- a/configs/odroid-n2_defconfig
+++ b/configs/odroid-n2_defconfig
@@ -17,12 +17,17 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -34,6 +39,7 @@
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ADC=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_MDIO=y
diff --git a/configs/odroid-n2l_defconfig b/configs/odroid-n2l_defconfig
index 983ac88..673e0cf 100644
--- a/configs/odroid-n2l_defconfig
+++ b/configs/odroid-n2l_defconfig
@@ -17,12 +17,17 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -34,6 +39,7 @@
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_ADC=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MESON_G12A_USB_PHY=y
 CONFIG_PINCTRL=y
diff --git a/configs/p200_defconfig b/configs/p200_defconfig
index 42e7eb8..cd579ef 100644
--- a/configs/p200_defconfig
+++ b/configs/p200_defconfig
@@ -15,6 +15,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
diff --git a/configs/p201_defconfig b/configs/p201_defconfig
index 5c98375..b2f0a0c 100644
--- a/configs/p201_defconfig
+++ b/configs/p201_defconfig
@@ -16,6 +16,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
diff --git a/configs/p212_defconfig b/configs/p212_defconfig
index 2fcf3b3..b90391d 100644
--- a/configs/p212_defconfig
+++ b/configs/p212_defconfig
@@ -16,6 +16,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_CONSOLE_MUX=y
 # CONFIG_DISPLAY_CPUINFO is not set
diff --git a/configs/pogo_v4_defconfig b/configs/pogo_v4_defconfig
index 2747c3c..ff6411d 100644
--- a/configs/pogo_v4_defconfig
+++ b/configs/pogo_v4_defconfig
@@ -17,7 +17,8 @@
 CONFIG_SYS_LOAD_ADDR=0x800000
 CONFIG_PCI=y
 CONFIG_LTO=y
-CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTSTD_FULL=y
+CONFIG_BOOTSTD_DEFAULTS=y
 CONFIG_BOOTSTAGE=y
 CONFIG_SHOW_BOOT_PROGRESS=y
 CONFIG_BOOTDELAY=10
diff --git a/configs/qemu-ppce500_defconfig b/configs/qemu-ppce500_defconfig
index fbe84d5..de7267e 100644
--- a/configs/qemu-ppce500_defconfig
+++ b/configs/qemu-ppce500_defconfig
@@ -21,7 +21,6 @@
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_LAST_STAGE_INIT=y
 CONFIG_HUSH_PARSER=y
-CONFIG_SYS_PBSIZE=276
 CONFIG_CMD_REGINFO=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_GREPENV=y
diff --git a/configs/qemu-riscv32_defconfig b/configs/qemu-riscv32_defconfig
index 9ace68e..cf74a48 100644
--- a/configs/qemu-riscv32_defconfig
+++ b/configs/qemu-riscv32_defconfig
@@ -12,8 +12,6 @@
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DISPLAY_BOARDINFO=y
-CONFIG_SYS_CBSIZE=256
-CONFIG_SYS_PBSIZE=276
 CONFIG_SYS_BOOTM_LEN=0x4000000
 CONFIG_CMD_BOOTEFI_SELFTEST=y
 CONFIG_CMD_NVEDIT_EFI=y
diff --git a/configs/qemu-riscv32_smode_defconfig b/configs/qemu-riscv32_smode_defconfig
index 0c7389e..aeef2f3 100644
--- a/configs/qemu-riscv32_smode_defconfig
+++ b/configs/qemu-riscv32_smode_defconfig
@@ -13,8 +13,6 @@
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DISPLAY_BOARDINFO=y
-CONFIG_SYS_CBSIZE=256
-CONFIG_SYS_PBSIZE=276
 CONFIG_SYS_BOOTM_LEN=0x4000000
 CONFIG_CMD_BOOTEFI_SELFTEST=y
 CONFIG_CMD_NVEDIT_EFI=y
diff --git a/configs/qemu-riscv32_spl_defconfig b/configs/qemu-riscv32_spl_defconfig
index e63d6fd..db9c971 100644
--- a/configs/qemu-riscv32_spl_defconfig
+++ b/configs/qemu-riscv32_spl_defconfig
@@ -19,8 +19,6 @@
 CONFIG_SPL_MAX_SIZE=0x100000
 CONFIG_SPL_BSS_START_ADDR=0x84000000
 CONFIG_SPL_SYS_MALLOC=y
-CONFIG_SYS_CBSIZE=256
-CONFIG_SYS_PBSIZE=276
 CONFIG_SYS_BOOTM_LEN=0x4000000
 # CONFIG_CMD_MII is not set
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
diff --git a/configs/qemu-riscv64_defconfig b/configs/qemu-riscv64_defconfig
index 9a8bbef..9fb40b2 100644
--- a/configs/qemu-riscv64_defconfig
+++ b/configs/qemu-riscv64_defconfig
@@ -12,8 +12,6 @@
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DISPLAY_BOARDINFO=y
-CONFIG_SYS_CBSIZE=256
-CONFIG_SYS_PBSIZE=276
 CONFIG_SYS_BOOTM_LEN=0x4000000
 CONFIG_CMD_BOOTEFI_SELFTEST=y
 CONFIG_CMD_NVEDIT_EFI=y
diff --git a/configs/qemu-riscv64_smode_defconfig b/configs/qemu-riscv64_smode_defconfig
index 1d0f021..e3b123c 100644
--- a/configs/qemu-riscv64_smode_defconfig
+++ b/configs/qemu-riscv64_smode_defconfig
@@ -15,8 +15,6 @@
 CONFIG_PREBOOT="setenv fdt_addr ${fdtcontroladdr}; fdt addr ${fdtcontroladdr};"
 CONFIG_DISPLAY_CPUINFO=y
 CONFIG_DISPLAY_BOARDINFO=y
-CONFIG_SYS_CBSIZE=256
-CONFIG_SYS_PBSIZE=276
 CONFIG_SYS_BOOTM_LEN=0x4000000
 CONFIG_CMD_BOOTEFI_SELFTEST=y
 CONFIG_CMD_NVEDIT_EFI=y
diff --git a/configs/qemu-riscv64_spl_defconfig b/configs/qemu-riscv64_spl_defconfig
index b048bb8..d6bf313 100644
--- a/configs/qemu-riscv64_spl_defconfig
+++ b/configs/qemu-riscv64_spl_defconfig
@@ -18,8 +18,6 @@
 CONFIG_SPL_MAX_SIZE=0x100000
 CONFIG_SPL_BSS_START_ADDR=0x84000000
 CONFIG_SPL_SYS_MALLOC=y
-CONFIG_SYS_CBSIZE=256
-CONFIG_SYS_PBSIZE=276
 CONFIG_SYS_BOOTM_LEN=0x4000000
 # CONFIG_CMD_MII is not set
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig
index f02e912..2ff49fb 100644
--- a/configs/qemu-x86_64_defconfig
+++ b/configs/qemu-x86_64_defconfig
@@ -46,7 +46,6 @@
 CONFIG_SPL_PCI=y
 CONFIG_SPL_PCH=y
 CONFIG_SPL_RTC=y
-CONFIG_SYS_PBSIZE=532
 CONFIG_CMD_CPU=y
 CONFIG_CMD_BOOTEFI_SELFTEST=y
 CONFIG_CMD_NVEDIT_EFI=y
diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig
index 4b2787d..246ac6b 100644
--- a/configs/qemu-x86_defconfig
+++ b/configs/qemu-x86_defconfig
@@ -24,7 +24,6 @@
 CONFIG_LOGF_FUNC=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_PCI_INIT_R=y
-CONFIG_SYS_PBSIZE=532
 CONFIG_CMD_CPU=y
 CONFIG_CMD_BOOTEFI_SELFTEST=y
 CONFIG_CMD_NVEDIT_EFI=y
diff --git a/configs/qemu_arm64_defconfig b/configs/qemu_arm64_defconfig
index 5fdf496..c010c25 100644
--- a/configs/qemu_arm64_defconfig
+++ b/configs/qemu_arm64_defconfig
@@ -27,8 +27,6 @@
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_PCI_INIT_R=y
-CONFIG_SYS_CBSIZE=512
-CONFIG_SYS_PBSIZE=532
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_BOOTEFI_SELFTEST=y
 CONFIG_CMD_NVEDIT_EFI=y
diff --git a/configs/qemu_arm_defconfig b/configs/qemu_arm_defconfig
index 1347b86..9cc1f5f 100644
--- a/configs/qemu_arm_defconfig
+++ b/configs/qemu_arm_defconfig
@@ -28,8 +28,6 @@
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
 CONFIG_PCI_INIT_R=y
-CONFIG_SYS_CBSIZE=512
-CONFIG_SYS_PBSIZE=532
 CONFIG_SYS_BOOTM_LEN=0x4000000
 CONFIG_CMD_BOOTEFI_SELFTEST=y
 CONFIG_CMD_NVEDIT_EFI=y
diff --git a/configs/radxa-zero2_defconfig b/configs/radxa-zero2_defconfig
index b1aa3c2..e941576 100644
--- a/configs/radxa-zero2_defconfig
+++ b/configs/radxa-zero2_defconfig
@@ -16,12 +16,17 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -32,6 +37,7 @@
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
diff --git a/configs/radxa-zero_defconfig b/configs/radxa-zero_defconfig
index 23f30f6..103ff8a 100644
--- a/configs/radxa-zero_defconfig
+++ b/configs/radxa-zero_defconfig
@@ -16,12 +16,17 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -32,6 +37,7 @@
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
diff --git a/configs/s400_defconfig b/configs/s400_defconfig
index 9a7d520..8e22c95 100644
--- a/configs/s400_defconfig
+++ b/configs/s400_defconfig
@@ -16,12 +16,17 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -31,6 +36,7 @@
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_REALTEK=y
 CONFIG_ETH_DESIGNWARE_MESON8B=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index e3a2f9e..c8a4669 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -14,6 +14,7 @@
 CONFIG_FIT_CIPHER=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_LEGACY_IMAGE_FORMAT=y
+CONFIG_MEASURED_BOOT=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTSTAGE=y
 CONFIG_BOOTSTAGE_REPORT=y
diff --git a/configs/sei510_defconfig b/configs/sei510_defconfig
index 63e4ebe..c4a49fb 100644
--- a/configs/sei510_defconfig
+++ b/configs/sei510_defconfig
@@ -21,6 +21,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_USE_PREBOOT=y
 CONFIG_PREBOOT="run load_logo"
@@ -34,6 +38,7 @@
 CONFIG_CMD_ABOOTIMG=y
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_BCB=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPT=y
 # CONFIG_CMD_LOADS is not set
@@ -49,6 +54,7 @@
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SYS_MMC_ENV_DEV=2
 CONFIG_SYS_MMC_ENV_PART=1
+CONFIG_DFU_RAM=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x6000000
 CONFIG_FASTBOOT_FLASH=y
diff --git a/configs/sei610_defconfig b/configs/sei610_defconfig
index ff7bcb3..ae254c6 100644
--- a/configs/sei610_defconfig
+++ b/configs/sei610_defconfig
@@ -21,6 +21,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_USE_PREBOOT=y
 CONFIG_PREBOOT="run load_logo"
@@ -34,6 +38,7 @@
 CONFIG_CMD_ABOOTIMG=y
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_BCB=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPT=y
 # CONFIG_CMD_LOADS is not set
@@ -49,6 +54,7 @@
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SYS_MMC_ENV_DEV=2
 CONFIG_SYS_MMC_ENV_PART=1
+CONFIG_DFU_RAM=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0x6000000
 CONFIG_FASTBOOT_FLASH=y
diff --git a/configs/turris_mox_defconfig b/configs/turris_mox_defconfig
index e0ca633..c9815b6 100644
--- a/configs/turris_mox_defconfig
+++ b/configs/turris_mox_defconfig
@@ -52,9 +52,10 @@
 CONFIG_CMD_BTRFS=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_MAC_PARTITION=y
+CONFIG_OF_LIST="armada-3720-turris-mox armada-3720-ripe-atlas"
 CONFIG_ENV_OVERWRITE=y
-CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_SYS_MMC_ENV_PART=2
 CONFIG_ARP_TIMEOUT=200
 CONFIG_NET_RETRY_COUNT=50
 CONFIG_NETCONSOLE=y
diff --git a/configs/u200_defconfig b/configs/u200_defconfig
index a841a66..21c90e7 100644
--- a/configs/u200_defconfig
+++ b/configs/u200_defconfig
@@ -16,12 +16,17 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
 CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -31,6 +36,7 @@
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_DM_MDIO=y
 CONFIG_DM_MDIO_MUX=y
diff --git a/configs/verdin-imx8mp_defconfig b/configs/verdin-imx8mp_defconfig
index bb20a22..eec1d96 100644
--- a/configs/verdin-imx8mp_defconfig
+++ b/configs/verdin-imx8mp_defconfig
@@ -79,6 +79,7 @@
 CONFIG_CMD_MMC=y
 CONFIG_CMD_READ=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_BOOTCOUNT=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
@@ -108,6 +109,12 @@
 CONFIG_CLK_COMPOSITE_CCF=y
 CONFIG_CLK_IMX8MP=y
 CONFIG_FSL_CAAM=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x42800000
+CONFIG_FASTBOOT_BUF_SIZE=0x40000000
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_UUU_SUPPORT=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
 CONFIG_GPIO_HOG=y
 CONFIG_SPL_GPIO_HOG=y
 CONFIG_MXC_GPIO=y
@@ -138,6 +145,7 @@
 CONFIG_FEC_MXC=y
 CONFIG_RGMII=y
 CONFIG_MII=y
+CONFIG_PHY=y
 CONFIG_PHY_IMX8MQ_USB=y
 CONFIG_PINCTRL=y
 CONFIG_SPL_PINCTRL=y
@@ -160,14 +168,20 @@
 CONFIG_DM_THERMAL=y
 CONFIG_IMX_TMU=y
 CONFIG_USB=y
+# CONFIG_SPL_DM_USB is not set
+CONFIG_DM_USB_GADGET=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_EHCI_HCD=y
-CONFIG_MXC_USB_OTG_HACTIVE=y
+# CONFIG_USB_EHCI_MX7 is not set
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GENERIC=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Toradex"
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
+CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_IMX_WATCHDOG=y
 CONFIG_HEXDUMP=y
diff --git a/configs/videostrong-kii-pro_defconfig b/configs/videostrong-kii-pro_defconfig
index 4a2ff34..3eda8f1 100644
--- a/configs/videostrong-kii-pro_defconfig
+++ b/configs/videostrong-kii-pro_defconfig
@@ -14,6 +14,10 @@
 CONFIG_IDENT_STRING=" kii-pro"
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
diff --git a/configs/wetek-core2_defconfig b/configs/wetek-core2_defconfig
index 324062e..9bf3de9 100644
--- a/configs/wetek-core2_defconfig
+++ b/configs/wetek-core2_defconfig
@@ -16,6 +16,10 @@
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
 CONFIG_REMAKE_ELF=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
@@ -23,6 +27,7 @@
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_ADC=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -33,6 +38,7 @@
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SARADC_MESON=y
+CONFIG_DFU_RAM=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
diff --git a/configs/wetek-hub_defconfig b/configs/wetek-hub_defconfig
index 4091a19..fd92b04 100644
--- a/configs/wetek-hub_defconfig
+++ b/configs/wetek-hub_defconfig
@@ -14,6 +14,10 @@
 CONFIG_IDENT_STRING=" wetek-hub"
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
diff --git a/configs/wetek-play2_defconfig b/configs/wetek-play2_defconfig
index 3ef4390..b887419 100644
--- a/configs/wetek-play2_defconfig
+++ b/configs/wetek-play2_defconfig
@@ -14,6 +14,10 @@
 CONFIG_IDENT_STRING=" wetek-play2"
 CONFIG_SYS_LOAD_ADDR=0x1000000
 CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_OF_BOARD_SETUP=y
 # CONFIG_DISPLAY_CPUINFO is not set
 CONFIG_MISC_INIT_R=y
diff --git a/doc/build/gcc.rst b/doc/build/gcc.rst
index a0650a5..23501de 100644
--- a/doc/build/gcc.rst
+++ b/doc/build/gcc.rst
@@ -60,8 +60,14 @@
 
 .. code-block:: bash
 
-    apk add alpine-sdk bc bison dtc flex linux-headers ncurses-dev \
-      openssl-dev perl python3 py3-setuptools python3-dev sdl2-dev
+    apk add alpine-sdk bc bison dtc flex gnutls-dev linux-headers ncurses-dev \
+      openssl-dev py3-elftools py3-setuptools python3-dev swig util-linux-dev
+
+Depending on the build target further packages may be needed:
+
+* sandbox with lcd: sdl2-dev
+* riscv64 S-mode targests: opensbi
+* some arm64 targets: arm-trusted-firmware
 
 Prerequisites
 -------------
diff --git a/doc/develop/driver-model/debugging.rst b/doc/develop/driver-model/debugging.rst
index bbb2794..e13abdd 100644
--- a/doc/develop/driver-model/debugging.rst
+++ b/doc/develop/driver-model/debugging.rst
@@ -49,7 +49,7 @@
      of_to_plat() method in the driver.
 
 If there is no error, you should check if the device is actually bound. Call
-dm_dump_all() just before you locate the device to make sure it exists.
+dm_dump_tree() just before you locate the device to make sure it exists.
 
 If it does not exist, check your device tree compatible strings match up with
 what the driver expects (in the struct udevice_id array).
diff --git a/doc/sphinx/requirements.txt b/doc/sphinx/requirements.txt
index 6d45a3f..39ececb 100644
--- a/doc/sphinx/requirements.txt
+++ b/doc/sphinx/requirements.txt
@@ -23,4 +23,4 @@
 sphinxcontrib-jsmath==1.0.1
 sphinxcontrib-qthelp==1.0.3
 sphinxcontrib-serializinghtml==1.1.5
-urllib3==2.0.6
+urllib3==2.0.7
diff --git a/doc/usage/cmd/gpt.rst b/doc/usage/cmd/gpt.rst
index f6115ec..cbbe44a 100644
--- a/doc/usage/cmd/gpt.rst
+++ b/doc/usage/cmd/gpt.rst
@@ -156,6 +156,7 @@
 
 Examples
 ~~~~~~~~
+
 Create 6 partitions on a disk::
 
     => setenv gpt_parts 'uuid_disk=bec9fc2a-86c1-483d-8a0e-0109732277d7;
@@ -192,10 +193,9 @@
 Get the list of partition names on the disk::
 
     => gpt enumerate
-    => echo gpt_partition_list
+    => echo ${gpt_partition_list}
     boot rootfs system-data [ext] user modules ramdisk
 
-
 Get the GUID for a disk::
 
     => gpt guid mmc 0
@@ -209,6 +209,7 @@
     => gpt set-bootable mmc 0 boot
 
 Swap the order of the 'boot' and 'rootfs' partition table entries::
+
     => gpt setenv mmc 0 rootfs
     => echo ${gpt_partition_entry}
     2
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 98b4719..d8e23fc 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -14,6 +14,7 @@
    partitions
    cmdline
    semihosting
+   measured_boot
 
 Shell commands
 --------------
@@ -37,8 +38,8 @@
    cmd/bootm
    cmd/bootmenu
    cmd/bootmeth
-   cmd/button
    cmd/bootz
+   cmd/button
    cmd/cat
    cmd/cbsysinfo
    cmd/cedit
@@ -56,8 +57,8 @@
    cmd/env
    cmd/event
    cmd/exception
-   cmd/extension
    cmd/exit
+   cmd/extension
    cmd/false
    cmd/fatinfo
    cmd/fatload
@@ -93,15 +94,15 @@
    cmd/rng
    cmd/saves
    cmd/sbi
-   cmd/sf
    cmd/scp03
    cmd/seama
    cmd/setexpr
+   cmd/sf
    cmd/size
    cmd/sleep
+   cmd/sm
    cmd/sound
    cmd/source
-   cmd/sm
    cmd/temperature
    cmd/tftpput
    cmd/trace
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 0000000..0aad590
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,31 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=====================
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+By default, U-Boot will measure the operating system (linux) image, the
+initrd image, and the "bootargs" environment variable. By enabling
+CONFIG_MEASURE_DEVICETREE, U-Boot will also measure the devicetree image.
+
+The operating system typically would verify that the hashes found in the
+TPM PCRs match the contents of the event log. This can further be checked
+against the hash results of previous boots.
+
+Requirements
+---------------------
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.
diff --git a/drivers/misc/k3_avs.c b/drivers/misc/k3_avs.c
index acfc731..9a08824 100644
--- a/drivers/misc/k3_avs.c
+++ b/drivers/misc/k3_avs.c
@@ -15,6 +15,7 @@
 #include <k3-avs.h>
 #include <dm/device_compat.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 #include <power/regulator.h>
 
 #define AM6_VTM_DEVINFO(i)	(priv->base + 0x100 + 0x20 * (i))
@@ -25,11 +26,28 @@
 #define AM6_VTM_OPP_SHIFT(opp)	(8 * (opp))
 #define AM6_VTM_OPP_MASK	0xff
 
+#define K3_VTM_DEVINFO_PWR0_OFFSET		0x4
+#define K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK	0xf0
+#define K3_VTM_TMPSENS0_CTRL_OFFSET		0x300
+#define K3_VTM_TMPSENS_STAT_OFFSET		0x8
+#define K3_VTM_ANYMAXT_OUTRG_ALERT_EN		0x1
+#define K3_VTM_LOW_TEMP_OFFSET			0x10
+#define K3_VTM_MISC_CTRL2_OFFSET		0x10
+#define K3_VTM_MISC_CTRL1_OFFSET		0xc
+#define K3_VTM_TMPSENS_CTRL1_SOC		BIT(5)
+#define K3_VTM_TMPSENS_CTRL_CLRZ		BIT(6)
+#define K3_VTM_TMPSENS_CTRL_MAXT_OUTRG_EN	BIT(11)
+#define K3_VTM_ADC_COUNT_FOR_123C		0x2f8
+#define K3_VTM_ADC_COUNT_FOR_105C		0x288
+#define K3_VTM_ADC_WA_VALUE			0x2c
+#define K3_VTM_FUSE_MASK			0xc0000000
+
 #define VD_FLAG_INIT_DONE	BIT(0)
 
 struct k3_avs_privdata {
 	void *base;
 	struct vd_config *vd_config;
+	struct udevice *dev;
 };
 
 struct opp {
@@ -237,6 +255,88 @@
 	return 0;
 }
 
+/* k3_avs_program_tshut : Program thermal shutdown value for SOC
+ * set the values corresponding to thresholds to ~123C and 105C
+ * This is optional feature, Few times OS driver takes care of
+ * tshut programing.
+ */
+
+static void k3_avs_program_tshut(struct k3_avs_privdata *priv)
+{
+	int cnt, id, val;
+	int workaround_needed = 0;
+	u32 ctrl_offset;
+	void __iomem *cfg2_base;
+	void __iomem *fuse_base;
+
+	cfg2_base = (void __iomem *)devfdt_get_addr_index(priv->dev, 1);
+	if (IS_ERR(cfg2_base)) {
+		dev_err(priv->dev, "cfg base is not defined\n");
+		return;
+	}
+
+	/*
+	 * Some of TI's J721E SoCs require a software trimming procedure
+	 * for the temperature monitors to function properly. To determine
+	 * if this particular SoC is NOT affected, both bits in the
+	 * WKUP_SPARE_FUSE0[31:30] will be set (0xC0000000) indicating
+	 * when software trimming should NOT be applied.
+	 *
+	 * https://www.ti.com/lit/er/sprz455c/sprz455c.pdf
+	 * This routine checks if workaround_needed to be applied or not
+	 * based upon workaround_needed, adjust fixed value of tshut high and low
+	 */
+
+	if (device_is_compatible(priv->dev, "ti,j721e-vtm")) {
+		fuse_base = (void __iomem *)devfdt_get_addr_index(priv->dev, 2);
+		if (IS_ERR(fuse_base)) {
+			dev_err(priv->dev, "fuse-base is not defined for J721E Soc\n");
+			return;
+		}
+
+		if (!((readl(fuse_base) & K3_VTM_FUSE_MASK) == K3_VTM_FUSE_MASK))
+			workaround_needed = 1;
+	}
+
+	dev_dbg(priv->dev, "Work around %sneeded\n", workaround_needed ? "" : "not ");
+
+	/* Get the sensor count in the VTM */
+	val = readl(priv->base + K3_VTM_DEVINFO_PWR0_OFFSET);
+	cnt = val & K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK;
+	cnt >>= __ffs(K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK);
+
+	/* Program the thermal sensors */
+	for (id = 0; id < cnt; id++) {
+		ctrl_offset = K3_VTM_TMPSENS0_CTRL_OFFSET + id * 0x20;
+
+		val = readl(cfg2_base + ctrl_offset);
+		val |= (K3_VTM_TMPSENS_CTRL_MAXT_OUTRG_EN |
+			K3_VTM_TMPSENS_CTRL1_SOC |
+			K3_VTM_TMPSENS_CTRL_CLRZ | BIT(4));
+		writel(val, cfg2_base + ctrl_offset);
+	}
+
+	/*
+	 * Program TSHUT thresholds
+	 * Step 1: set the thresholds to ~123C and 105C WKUP_VTM_MISC_CTRL2
+	 * Step 2: WKUP_VTM_TMPSENS_CTRL_j set the MAXT_OUTRG_EN  bit
+	 *         This is already taken care as per of init
+	 * Step 3: WKUP_VTM_MISC_CTRL set the ANYMAXT_OUTRG_ALERT_EN  bit
+	 */
+
+	/* Low thresholds for tshut*/
+	val = (K3_VTM_ADC_COUNT_FOR_105C - workaround_needed * K3_VTM_ADC_WA_VALUE)
+		<< K3_VTM_LOW_TEMP_OFFSET;
+	/* high thresholds */
+	val |= K3_VTM_ADC_COUNT_FOR_123C - workaround_needed * K3_VTM_ADC_WA_VALUE;
+
+	writel(val, cfg2_base + K3_VTM_MISC_CTRL2_OFFSET);
+	/* ramp-up delay from Linux code */
+	mdelay(100);
+	val = readl(cfg2_base + K3_VTM_MISC_CTRL1_OFFSET) | K3_VTM_ANYMAXT_OUTRG_ALERT_EN;
+	writel(val, cfg2_base + K3_VTM_MISC_CTRL1_OFFSET);
+}
+
 /**
  * k3_avs_probe: parses VD info from VTM, and re-configures the OPP data
  *
@@ -255,6 +355,7 @@
 	int ret;
 
 	priv = dev_get_priv(dev);
+	priv->dev = dev;
 
 	k3_avs_priv = priv;
 
@@ -294,6 +395,9 @@
 		k3_avs_program_voltage(priv, vd, vd->opp);
 	}
 
+	if (!device_is_compatible(priv->dev, "ti,am654-avs"))
+		k3_avs_program_tshut(priv);
+
 	return 0;
 }
 
diff --git a/drivers/misc/vexpress_config.c b/drivers/misc/vexpress_config.c
index 2baca48..99aad14 100644
--- a/drivers/misc/vexpress_config.c
+++ b/drivers/misc/vexpress_config.c
@@ -92,7 +92,7 @@
 static int vexpress_config_probe(struct udevice *dev)
 {
 	struct ofnode_phandle_args args;
-	struct vexpress_config_sysreg *priv;
+	struct vexpress_config_sysreg *priv = dev_get_priv(dev);
 	const char *prop;
 	int err, prop_size;
 
@@ -105,11 +105,9 @@
 	if (!prop || (strncmp(prop, "arm,vexpress-sysreg", 19) != 0))
 		return -ENOENT;
 
-	priv = calloc(1, sizeof(*priv));
 	if (!priv)
 		return -ENOMEM;
 
-	dev_get_uclass_priv(dev) = priv;
 	priv->addr = ofnode_get_addr(args.node);
 
 	return dev_read_u32(dev, "arm,vexpress,site", &priv->site);
@@ -127,4 +125,5 @@
 	.bind = dm_scan_fdt_dev,
 	.probe = vexpress_config_probe,
 	.ops = &vexpress_config_ops,
+	.priv_auto = sizeof(struct vexpress_config_sysreg),
 };
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 854b8b8..66cf727 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -251,6 +251,15 @@
 	  Enable the QSPI driver for Microchip FPGA QSPI controllers.
 	  This driver can be used on Polarfire SoC.
 
+config MESON_SPIFC_A1
+	bool "Amlogic Meson A1 SPI Flash Controller driver"
+	depends on ARCH_MESON
+	help
+	  Enable the Amlogic A1 SPI Flash Controller (SPIFC) driver.
+	  This driver can be used to access the SPI NOR/NAND flash chips
+	  with STR mode frequency up to 98MHz. Dual and quad modes are
+	  supported by controller.
+
 config MPC8XX_SPI
 	bool "MPC8XX SPI Driver"
 	depends on MPC8xx
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index c27b332..14bdb97 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -41,6 +41,7 @@
 obj-$(CONFIG_IPROC_QSPI) += iproc_qspi.o
 obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
 obj-$(CONFIG_MESON_SPIFC) += meson_spifc.o
+obj-$(CONFIG_MESON_SPIFC_A1) += meson_spifc_a1.o
 obj-$(CONFIG_MICROCHIP_COREQSPI) += microchip_coreqspi.o
 obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
 obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
diff --git a/drivers/spi/meson_spifc_a1.c b/drivers/spi/meson_spifc_a1.c
new file mode 100644
index 0000000..099c4c0
--- /dev/null
+++ b/drivers/spi/meson_spifc_a1.c
@@ -0,0 +1,383 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for Amlogic A1 SPI flash controller (SPIFC)
+ *
+ * Copyright (c) 2023, SberDevices. All Rights Reserved.
+ *
+ * Author: Martin Kurbanov <mmkurbanov@sberdevices.ru>
+ *
+ * Ported to u-boot:
+ * Author: Igor Prusov <ivprusov@sberdevices.ru>
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <spi.h>
+#include <spi-mem.h>
+#include <asm/io.h>
+#include <linux/log2.h>
+#include <linux/iopoll.h>
+#include <linux/bitfield.h>
+
+#define SPIFC_A1_AHB_CTRL_REG		0x0
+#define SPIFC_A1_AHB_BUS_EN		BIT(31)
+
+#define SPIFC_A1_USER_CTRL0_REG		0x200
+#define SPIFC_A1_USER_REQUEST_ENABLE	BIT(31)
+#define SPIFC_A1_USER_REQUEST_FINISH	BIT(30)
+#define SPIFC_A1_USER_DATA_UPDATED	BIT(0)
+
+#define SPIFC_A1_USER_CTRL1_REG		0x204
+#define SPIFC_A1_USER_CMD_ENABLE	BIT(30)
+#define SPIFC_A1_USER_CMD_MODE		GENMASK(29, 28)
+#define SPIFC_A1_USER_CMD_CODE		GENMASK(27, 20)
+#define SPIFC_A1_USER_ADDR_ENABLE	BIT(19)
+#define SPIFC_A1_USER_ADDR_MODE		GENMASK(18, 17)
+#define SPIFC_A1_USER_ADDR_BYTES	GENMASK(16, 15)
+#define SPIFC_A1_USER_DOUT_ENABLE	BIT(14)
+#define SPIFC_A1_USER_DOUT_MODE		GENMASK(11, 10)
+#define SPIFC_A1_USER_DOUT_BYTES	GENMASK(9, 0)
+
+#define SPIFC_A1_USER_CTRL2_REG		0x208
+#define SPIFC_A1_USER_DUMMY_ENABLE	BIT(31)
+#define SPIFC_A1_USER_DUMMY_MODE	GENMASK(30, 29)
+#define SPIFC_A1_USER_DUMMY_CLK_SYCLES	GENMASK(28, 23)
+
+#define SPIFC_A1_USER_CTRL3_REG		0x20c
+#define SPIFC_A1_USER_DIN_ENABLE	BIT(31)
+#define SPIFC_A1_USER_DIN_MODE		GENMASK(28, 27)
+#define SPIFC_A1_USER_DIN_BYTES		GENMASK(25, 16)
+
+#define SPIFC_A1_USER_ADDR_REG		0x210
+
+#define SPIFC_A1_AHB_REQ_CTRL_REG	0x214
+#define SPIFC_A1_AHB_REQ_ENABLE		BIT(31)
+
+#define SPIFC_A1_ACTIMING0_REG		(0x0088 << 2)
+#define SPIFC_A1_TSLCH			GENMASK(31, 30)
+#define SPIFC_A1_TCLSH			GENMASK(29, 28)
+#define SPIFC_A1_TSHWL			GENMASK(20, 16)
+#define SPIFC_A1_TSHSL2			GENMASK(15, 12)
+#define SPIFC_A1_TSHSL1			GENMASK(11, 8)
+#define SPIFC_A1_TWHSL			GENMASK(7, 0)
+
+#define SPIFC_A1_DBUF_CTRL_REG		0x240
+#define SPIFC_A1_DBUF_DIR		BIT(31)
+#define SPIFC_A1_DBUF_AUTO_UPDATE_ADDR	BIT(30)
+#define SPIFC_A1_DBUF_ADDR		GENMASK(7, 0)
+
+#define SPIFC_A1_DBUF_DATA_REG		0x244
+
+#define SPIFC_A1_USER_DBUF_ADDR_REG	0x248
+
+#define SPIFC_A1_BUFFER_SIZE		512U
+
+#define SPIFC_A1_MAX_HZ			200000000
+#define SPIFC_A1_MIN_HZ			1000000
+
+#define SPIFC_A1_USER_CMD(op) ( \
+	SPIFC_A1_USER_CMD_ENABLE | \
+	FIELD_PREP(SPIFC_A1_USER_CMD_CODE, (op)->cmd.opcode) | \
+	FIELD_PREP(SPIFC_A1_USER_CMD_MODE, ilog2((op)->cmd.buswidth)))
+
+#define SPIFC_A1_USER_ADDR(op) ( \
+	SPIFC_A1_USER_ADDR_ENABLE | \
+	FIELD_PREP(SPIFC_A1_USER_ADDR_MODE, ilog2((op)->addr.buswidth)) | \
+	FIELD_PREP(SPIFC_A1_USER_ADDR_BYTES, (op)->addr.nbytes - 1))
+
+#define SPIFC_A1_USER_DUMMY(op) ( \
+	SPIFC_A1_USER_DUMMY_ENABLE | \
+	FIELD_PREP(SPIFC_A1_USER_DUMMY_MODE, ilog2((op)->dummy.buswidth)) | \
+	FIELD_PREP(SPIFC_A1_USER_DUMMY_CLK_SYCLES, (op)->dummy.nbytes << 3))
+
+#define SPIFC_A1_TSLCH_VAL	FIELD_PREP(SPIFC_A1_TSLCH, 1)
+#define SPIFC_A1_TCLSH_VAL	FIELD_PREP(SPIFC_A1_TCLSH, 1)
+#define SPIFC_A1_TSHWL_VAL	FIELD_PREP(SPIFC_A1_TSHWL, 7)
+#define SPIFC_A1_TSHSL2_VAL	FIELD_PREP(SPIFC_A1_TSHSL2, 7)
+#define SPIFC_A1_TSHSL1_VAL	FIELD_PREP(SPIFC_A1_TSHSL1, 7)
+#define SPIFC_A1_TWHSL_VAL	FIELD_PREP(SPIFC_A1_TWHSL, 2)
+#define SPIFC_A1_ACTIMING0_VAL	(SPIFC_A1_TSLCH_VAL | SPIFC_A1_TCLSH_VAL | \
+				 SPIFC_A1_TSHWL_VAL | SPIFC_A1_TSHSL2_VAL | \
+				 SPIFC_A1_TSHSL1_VAL | SPIFC_A1_TWHSL_VAL)
+
+struct amlogic_spifc_a1 {
+	struct clk clk;
+	void __iomem *base;
+	u32 curr_speed_hz;
+};
+
+static int amlogic_spifc_a1_request(struct amlogic_spifc_a1 *spifc, bool read)
+{
+	u32 mask = SPIFC_A1_USER_REQUEST_FINISH |
+		   (read ? SPIFC_A1_USER_DATA_UPDATED : 0);
+	u32 val;
+
+	writel(SPIFC_A1_USER_REQUEST_ENABLE,
+	       spifc->base + SPIFC_A1_USER_CTRL0_REG);
+
+	return readl_poll_timeout(spifc->base + SPIFC_A1_USER_CTRL0_REG,
+				  val, (val & mask) == mask,
+				  200 * 1000);
+}
+
+static void amlogic_spifc_a1_drain_buffer(struct amlogic_spifc_a1 *spifc,
+					  char *buf, u32 len)
+{
+	u32 data;
+	const u32 count = len / sizeof(data);
+	const u32 pad = len % sizeof(data);
+
+	writel(SPIFC_A1_DBUF_AUTO_UPDATE_ADDR,
+	       spifc->base + SPIFC_A1_DBUF_CTRL_REG);
+	readsl(spifc->base + SPIFC_A1_DBUF_DATA_REG, buf, count);
+
+	if (pad) {
+		data = readl(spifc->base + SPIFC_A1_DBUF_DATA_REG);
+		memcpy(buf + len - pad, &data, pad);
+	}
+}
+
+static void amlogic_spifc_a1_fill_buffer(struct amlogic_spifc_a1 *spifc,
+					 const char *buf, u32 len)
+{
+	u32 data;
+	const u32 count = len / sizeof(data);
+	const u32 pad = len % sizeof(data);
+
+	writel(SPIFC_A1_DBUF_DIR | SPIFC_A1_DBUF_AUTO_UPDATE_ADDR,
+	       spifc->base + SPIFC_A1_DBUF_CTRL_REG);
+	writesl(spifc->base + SPIFC_A1_DBUF_DATA_REG, buf, count);
+
+	if (pad) {
+		memcpy(&data, buf + len - pad, pad);
+		writel(data, spifc->base + SPIFC_A1_DBUF_DATA_REG);
+	}
+}
+
+static void amlogic_spifc_a1_user_init(struct amlogic_spifc_a1 *spifc)
+{
+	writel(0, spifc->base + SPIFC_A1_USER_CTRL0_REG);
+	writel(0, spifc->base + SPIFC_A1_USER_CTRL1_REG);
+	writel(0, spifc->base + SPIFC_A1_USER_CTRL2_REG);
+	writel(0, spifc->base + SPIFC_A1_USER_CTRL3_REG);
+}
+
+static void amlogic_spifc_a1_set_cmd(struct amlogic_spifc_a1 *spifc,
+				     u32 cmd_cfg)
+{
+	u32 val;
+
+	val = readl(spifc->base + SPIFC_A1_USER_CTRL1_REG);
+	val &= ~(SPIFC_A1_USER_CMD_MODE | SPIFC_A1_USER_CMD_CODE);
+	val |= cmd_cfg;
+	writel(val, spifc->base + SPIFC_A1_USER_CTRL1_REG);
+}
+
+static void amlogic_spifc_a1_set_addr(struct amlogic_spifc_a1 *spifc, u32 addr,
+				      u32 addr_cfg)
+{
+	u32 val;
+
+	writel(addr, spifc->base + SPIFC_A1_USER_ADDR_REG);
+
+	val = readl(spifc->base + SPIFC_A1_USER_CTRL1_REG);
+	val &= ~(SPIFC_A1_USER_ADDR_MODE | SPIFC_A1_USER_ADDR_BYTES);
+	val |= addr_cfg;
+	writel(val, spifc->base + SPIFC_A1_USER_CTRL1_REG);
+}
+
+static void amlogic_spifc_a1_set_dummy(struct amlogic_spifc_a1 *spifc,
+				       u32 dummy_cfg)
+{
+	u32 val = readl(spifc->base + SPIFC_A1_USER_CTRL2_REG);
+
+	val &= ~(SPIFC_A1_USER_DUMMY_MODE | SPIFC_A1_USER_DUMMY_CLK_SYCLES);
+	val |= dummy_cfg;
+	writel(val, spifc->base + SPIFC_A1_USER_CTRL2_REG);
+}
+
+static int amlogic_spifc_a1_read(struct amlogic_spifc_a1 *spifc, void *buf,
+				 u32 size, u32 mode)
+{
+	u32 val = readl(spifc->base + SPIFC_A1_USER_CTRL3_REG);
+	int ret;
+
+	val &= ~(SPIFC_A1_USER_DIN_MODE | SPIFC_A1_USER_DIN_BYTES);
+	val |= SPIFC_A1_USER_DIN_ENABLE;
+	val |= FIELD_PREP(SPIFC_A1_USER_DIN_MODE, mode);
+	val |= FIELD_PREP(SPIFC_A1_USER_DIN_BYTES, size);
+	writel(val, spifc->base + SPIFC_A1_USER_CTRL3_REG);
+
+	ret = amlogic_spifc_a1_request(spifc, true);
+	if (!ret)
+		amlogic_spifc_a1_drain_buffer(spifc, buf, size);
+
+	return ret;
+}
+
+static int amlogic_spifc_a1_write(struct amlogic_spifc_a1 *spifc,
+				  const void *buf, u32 size, u32 mode)
+{
+	u32 val;
+
+	amlogic_spifc_a1_fill_buffer(spifc, buf, size);
+
+	val = readl(spifc->base + SPIFC_A1_USER_CTRL1_REG);
+	val &= ~(SPIFC_A1_USER_DOUT_MODE | SPIFC_A1_USER_DOUT_BYTES);
+	val |= FIELD_PREP(SPIFC_A1_USER_DOUT_MODE, mode);
+	val |= FIELD_PREP(SPIFC_A1_USER_DOUT_BYTES, size);
+	val |= SPIFC_A1_USER_DOUT_ENABLE;
+	writel(val, spifc->base + SPIFC_A1_USER_CTRL1_REG);
+
+	return amlogic_spifc_a1_request(spifc, false);
+}
+
+static int amlogic_spifc_a1_set_freq(struct amlogic_spifc_a1 *spifc, u32 freq)
+{
+	int ret;
+
+	if (freq == spifc->curr_speed_hz)
+		return 0;
+
+	ret = clk_set_rate(&spifc->clk, freq);
+	if (ret)
+		return ret;
+
+	spifc->curr_speed_hz = freq;
+	return 0;
+}
+
+static int amlogic_spifc_a1_exec_op(struct spi_slave *slave,
+				    const struct spi_mem_op *op)
+{
+	struct amlogic_spifc_a1 *spifc = dev_get_priv(slave->dev->parent);
+	size_t data_size = op->data.nbytes;
+	int ret;
+
+	ret = amlogic_spifc_a1_set_freq(spifc, slave->max_hz);
+	if (ret)
+		return ret;
+
+	amlogic_spifc_a1_user_init(spifc);
+	amlogic_spifc_a1_set_cmd(spifc, SPIFC_A1_USER_CMD(op));
+
+	if (op->addr.nbytes)
+		amlogic_spifc_a1_set_addr(spifc, op->addr.val,
+					  SPIFC_A1_USER_ADDR(op));
+
+	if (op->dummy.nbytes)
+		amlogic_spifc_a1_set_dummy(spifc, SPIFC_A1_USER_DUMMY(op));
+
+	if (data_size) {
+		u32 mode = ilog2(op->data.buswidth);
+
+		writel(0, spifc->base + SPIFC_A1_USER_DBUF_ADDR_REG);
+
+		if (op->data.dir == SPI_MEM_DATA_IN)
+			ret = amlogic_spifc_a1_read(spifc, op->data.buf.in,
+						    data_size, mode);
+		else
+			ret = amlogic_spifc_a1_write(spifc, op->data.buf.out,
+						     data_size, mode);
+	} else {
+		ret = amlogic_spifc_a1_request(spifc, false);
+	}
+
+	return ret;
+}
+
+static int amlogic_spifc_a1_adjust_op_size(struct spi_slave *slave,
+					   struct spi_mem_op *op)
+{
+	op->data.nbytes = min(op->data.nbytes, SPIFC_A1_BUFFER_SIZE);
+	return 0;
+}
+
+static void amlogic_spifc_a1_hw_init(struct amlogic_spifc_a1 *spifc)
+{
+	u32 regv;
+
+	regv = readl(spifc->base + SPIFC_A1_AHB_REQ_CTRL_REG);
+	regv &= ~(SPIFC_A1_AHB_REQ_ENABLE);
+	writel(regv, spifc->base + SPIFC_A1_AHB_REQ_CTRL_REG);
+
+	regv = readl(spifc->base + SPIFC_A1_AHB_CTRL_REG);
+	regv &= ~(SPIFC_A1_AHB_BUS_EN);
+	writel(regv, spifc->base + SPIFC_A1_AHB_CTRL_REG);
+
+	writel(SPIFC_A1_ACTIMING0_VAL, spifc->base + SPIFC_A1_ACTIMING0_REG);
+
+	writel(0, spifc->base + SPIFC_A1_USER_DBUF_ADDR_REG);
+}
+
+static const struct spi_controller_mem_ops amlogic_spifc_a1_mem_ops = {
+	.exec_op = amlogic_spifc_a1_exec_op,
+	.adjust_op_size = amlogic_spifc_a1_adjust_op_size,
+};
+
+static int amlogic_spifc_a1_probe(struct udevice *dev)
+{
+	struct amlogic_spifc_a1 *spifc = dev_get_priv(dev);
+	int ret;
+	struct udevice *bus = dev;
+
+	spifc->base = dev_read_addr_ptr(dev);
+	if (!spifc->base)
+		return -EINVAL;
+
+	ret = clk_get_by_index(bus, 0, &spifc->clk);
+	if (ret) {
+		pr_err("can't get clk spifc_gate!\n");
+		return ret;
+	}
+
+	ret = clk_enable(&spifc->clk);
+	if (ret) {
+		pr_err("enable clk fail\n");
+		return ret;
+	}
+
+	amlogic_spifc_a1_hw_init(spifc);
+
+	return 0;
+}
+
+static int amlogic_spifc_a1_remove(struct udevice *dev)
+{
+	struct amlogic_spifc_a1 *spifc = dev_get_priv(dev);
+
+	clk_free(&spifc->clk);
+
+	return 0;
+}
+
+static const struct udevice_id meson_spifc_ids[] = {
+	{ .compatible = "amlogic,a1-spifc", },
+	{ }
+};
+
+int amlogic_spifc_a1_set_speed(struct udevice *bus, uint hz)
+{
+	return 0;
+}
+
+int amlogic_spifc_a1_set_mode(struct udevice *bus, uint mode)
+{
+	return 0;
+}
+
+static const struct dm_spi_ops amlogic_spifc_a1_ops = {
+	.mem_ops = &amlogic_spifc_a1_mem_ops,
+	.set_speed = amlogic_spifc_a1_set_speed,
+	.set_mode = amlogic_spifc_a1_set_mode,
+};
+
+U_BOOT_DRIVER(meson_spifc_a1) = {
+	.name		= "meson_spifc_a1",
+	.id		= UCLASS_SPI,
+	.of_match	= meson_spifc_ids,
+	.ops		= &amlogic_spifc_a1_ops,
+	.probe		= amlogic_spifc_a1_probe,
+	.remove		= amlogic_spifc_a1_remove,
+	.priv_auto	= sizeof(struct amlogic_spifc_a1),
+};
diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index e4004cf..d15a28d 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -22,11 +22,6 @@
 	TPM2_HIERARCHY_NB,
 };
 
-/* Subset of supported capabilities */
-enum tpm2_capability {
-	TPM_CAP_TPM_PROPERTIES = 0x6,
-};
-
 /* Subset of supported properties */
 #define TPM2_PROPERTIES_OFFSET 0x0000020E
 
@@ -38,7 +33,8 @@
 	TPM2_PROPERTY_NB,
 };
 
-#define SANDBOX_TPM_PCR_NB 1
+#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
+#define SANDBOX_TPM_PCR_SELECT_MAX	((SANDBOX_TPM_PCR_NB + 7) / 8)
 
 /*
  * Information about our TPM emulation. This is preserved in the sandbox
@@ -433,7 +429,7 @@
 	int i, j;
 
 	/* TPM2_GetProperty */
-	u32 capability, property, property_count;
+	u32 capability, property, property_count, val;
 
 	/* TPM2_PCR_Read/Extend variables */
 	int pcr_index = 0;
@@ -542,19 +538,32 @@
 	case TPM2_CC_GET_CAPABILITY:
 		capability = get_unaligned_be32(sent);
 		sent += sizeof(capability);
-		if (capability != TPM_CAP_TPM_PROPERTIES) {
-			printf("Sandbox TPM only support TPM_CAPABILITIES\n");
-			return TPM2_RC_HANDLE;
-		}
-
 		property = get_unaligned_be32(sent);
 		sent += sizeof(property);
-		property -= TPM2_PROPERTIES_OFFSET;
-
 		property_count = get_unaligned_be32(sent);
 		sent += sizeof(property_count);
-		if (!property_count ||
-		    property + property_count > TPM2_PROPERTY_NB) {
+
+		switch (capability) {
+		case TPM2_CAP_PCRS:
+			break;
+		case TPM2_CAP_TPM_PROPERTIES:
+			if (!property_count) {
+				rc = TPM2_RC_HANDLE;
+				return sandbox_tpm2_fill_buf(recv, recv_len,
+							     tag, rc);
+			}
+
+			if (property >= TPM2_PROPERTIES_OFFSET &&
+			    ((property - TPM2_PROPERTIES_OFFSET) +
+			     property_count > TPM2_PROPERTY_NB)) {
+				rc = TPM2_RC_HANDLE;
+				return sandbox_tpm2_fill_buf(recv, recv_len,
+							     tag, rc);
+			}
+			break;
+		default:
+			printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
+			       "TPM2_CAP_TPM_PROPERTIES\n");
 			rc = TPM2_RC_HANDLE;
 			return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
 		}
@@ -578,18 +587,53 @@
 		put_unaligned_be32(capability, recv);
 		recv += sizeof(capability);
 
+		switch (capability) {
+		case TPM2_CAP_PCRS:
+			/* Give the number of algorithms supported - just SHA256 */
+			put_unaligned_be32(1, recv);
+			recv += sizeof(u32);
+
+			/* Give SHA256 algorithm */
+			put_unaligned_be16(TPM2_ALG_SHA256, recv);
+			recv += sizeof(u16);
+
+			/* Select the PCRs supported */
+			*recv = SANDBOX_TPM_PCR_SELECT_MAX;
+			recv++;
+
-		/* Give the number of properties that follow */
-		put_unaligned_be32(property_count, recv);
-		recv += sizeof(property_count);
+			/* Activate all the PCR bits */
+			for (i = 0; i < SANDBOX_TPM_PCR_SELECT_MAX; ++i) {
+				*recv = 0xff;
+				recv++;
+			}
+			break;
+		case TPM2_CAP_TPM_PROPERTIES:
+			/* Give the number of properties that follow */
+			put_unaligned_be32(property_count, recv);
+			recv += sizeof(property_count);
+
+			/* Fill with the properties */
+			for (i = 0; i < property_count; i++) {
+				put_unaligned_be32(property + i, recv);
+				recv += sizeof(property);
+				if (property >= TPM2_PROPERTIES_OFFSET) {
+					val = tpm->properties[(property -
+						TPM2_PROPERTIES_OFFSET) + i];
+				} else {
+					switch (property) {
+					case TPM2_PT_PCR_COUNT:
+						val = SANDBOX_TPM_PCR_NB;
+						break;
+					default:
+						val = 0xffffffff;
+						break;
+					}
+				}
 
-		/* Fill with the properties */
-		for (i = 0; i < property_count; i++) {
-			put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
-					   i, recv);
-			recv += sizeof(property);
-			put_unaligned_be32(tpm->properties[property + i],
-					   recv);
-			recv += sizeof(property);
+				put_unaligned_be32(val, recv);
+				recv += sizeof(property);
+			}
+			break;
 		}
 
 		/* Add trailing \0 */
diff --git a/include/bootm.h b/include/bootm.h
index c3c7336..10a1bd6 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -56,6 +56,17 @@
 int bootm_find_images(int flag, int argc, char *const argv[], ulong start,
 		      ulong size);
 
+/*
+ * Measure the boot images. Measurement is the process of hashing some binary
+ * data and storing it into secure memory, i.e. TPM PCRs. In addition, each
+ * measurement is logged into the platform event log such that the operating
+ * system can access it and perform attestation of the boot.
+ *
+ * @images:	The structure containing the various images to boot (linux,
+ *		initrd, dts, etc.)
+ */
+int bootm_measure(struct bootm_headers *images);
+
 int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
 		    char *const argv[], int states, struct bootm_headers *images,
 		    int boot_progress);
diff --git a/include/configs/iot2050.h b/include/configs/iot2050.h
index 4968722..94a9c76 100644
--- a/include/configs/iot2050.h
+++ b/include/configs/iot2050.h
@@ -15,6 +15,15 @@
 
 #include <configs/ti_armv7_common.h>
 
+/* allow up to 3 USB storage devices */
+#ifdef CONFIG_CMD_USB
+#undef BOOT_TARGET_USB
+#define BOOT_TARGET_USB(func) \
+	func(USB, usb, 0) \
+	func(USB, usb, 1) \
+	func(USB, usb, 2)
+#endif
+
 /*
  * This defines all MMC devices, even if the basic variant has no mmc1.
  * The non-supported device will be removed from the boot targets during
diff --git a/include/configs/meson64.h b/include/configs/meson64.h
index 801cdae..efab9a6 100644
--- a/include/configs/meson64.h
+++ b/include/configs/meson64.h
@@ -53,6 +53,30 @@
 #define BOOTENV_DEV_NAME_ROMUSB(devtypeu, devtypel, instance)	\
 		"romusb "
 
+/*
+ * Fallback to "USB DFU" boot if script is not at scriptaddr
+ *
+ * DFU will expose the kernel_addr_r memory range as DFU entry,
+ * then with `dfu-util --detach`, booting the uploaded image
+ * will be attempted:
+ * $ dfu-util -a 0 -D fitImage
+ * $ dfu-util -a 0 -e
+ */
+#if CONFIG_IS_ENABLED(USB_GADGET) && CONFIG_IS_ENABLED(DFU_RAM)
+	#define BOOTENV_DEV_USB_DFU(devtypeu, devtypel, instance) \
+		"bootcmd_usbdfu=" \
+			"if test \"${boot_source}\" = \"usb\"; then " \
+				"dfu 0 ram 0 60;" \
+				"bootm ${kernel_addr_r};" \
+			"fi\0"
+
+	#define BOOTENV_DEV_NAME_USB_DFU(devtypeu, devtypel, instance) \
+		"usbdfu "
+#else
+	#define BOOTENV_DEV_USB_DFU(devtypeu, devtypel, instance)
+	#define BOOTENV_DEV_NAME_USB_DFU(devtypeu, devtypel, instance)
+#endif
+
 #ifdef CONFIG_CMD_USB
 #define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0)
 #else
@@ -74,6 +98,7 @@
 #ifndef BOOT_TARGET_DEVICES
 #define BOOT_TARGET_DEVICES(func) \
 	func(ROMUSB, romusb, na)  \
+	func(USB_DFU, usbdfu, na)  \
 	func(MMC, mmc, 0) \
 	func(MMC, mmc, 1) \
 	func(MMC, mmc, 2) \
@@ -84,6 +109,15 @@
 	func(DHCP, dhcp, na)
 #endif
 
+#define BOOTM_SIZE		__stringify(0x1700000)
+#define KERNEL_ADDR_R		__stringify(0x08080000)
+#define KERNEL_COMP_ADDR_R	__stringify(0x0d080000)
+#define FDT_ADDR_R		__stringify(0x08008000)
+#define SCRIPT_ADDR_R		__stringify(0x08000000)
+#define PXEFILE_ADDR_R		__stringify(0x01080000)
+#define FDTOVERLAY_ADDR_R	__stringify(0x01000000)
+#define RAMDISK_ADDR_R		__stringify(0x13000000)
+
 #include <config_distro_bootcmd.h>
 
 #ifndef CFG_EXTRA_ENV_SETTINGS
@@ -91,15 +125,16 @@
 	"stdin=" STDIN_CFG "\0" \
 	"stdout=" STDOUT_CFG "\0" \
 	"stderr=" STDOUT_CFG "\0" \
-	"kernel_comp_addr_r=0x0d080000\0" \
+	"kernel_comp_addr_r=" KERNEL_COMP_ADDR_R "\0" \
 	"kernel_comp_size=0x2000000\0" \
-	"fdt_addr_r=0x08008000\0" \
-	"scriptaddr=0x08000000\0" \
-	"kernel_addr_r=0x08080000\0" \
-	"pxefile_addr_r=0x01080000\0" \
-	"fdtoverlay_addr_r=0x01000000\0" \
-	"ramdisk_addr_r=0x13000000\0" \
+	"fdt_addr_r=" FDT_ADDR_R "\0" \
+	"scriptaddr=" SCRIPT_ADDR_R "\0" \
+	"kernel_addr_r=" KERNEL_ADDR_R "\0" \
+	"pxefile_addr_r=" PXEFILE_ADDR_R "\0" \
+	"fdtoverlay_addr_r=" FDTOVERLAY_ADDR_R "\0" \
+	"ramdisk_addr_r=" RAMDISK_ADDR_R "\0" \
 	"fdtfile=amlogic/" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
+	"dfu_alt_info=fitimage ram " KERNEL_ADDR_R " 0x4000000 \0" \
 	BOOTENV
 #endif
 
diff --git a/include/configs/nsa310s.h b/include/configs/nsa310s.h
index fa029a1..8c4d035 100644
--- a/include/configs/nsa310s.h
+++ b/include/configs/nsa310s.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * Copyright (C) 2015, 2021-2022 Tony Dinh <mibodhi@gmail.com>
+ * Copyright (C) 2015, 2021-2023 Tony Dinh <mibodhi@gmail.com>
  * Copyright (C) 2015
  * Gerald Kerma <dreagle@doukki.net>
  * Luka Perkov <luka.perkov@sartura.hr>
@@ -15,14 +15,6 @@
  */
 #include "mv-common.h"
 
-/* Include the common distro boot environment */
-#ifndef CONFIG_SPL_BUILD
-
-#define BOOT_TARGET_DEVICES(func) \
-	func(USB, usb, 0) \
-	func(SATA, sata, 0) \
-	func(DHCP, dhcp, na)
-
 #define KERNEL_ADDR_R	__stringify(0x800000)
 #define FDT_ADDR_R	__stringify(0x2c00000)
 #define RAMDISK_ADDR_R	__stringify(0x01100000)
@@ -34,16 +26,11 @@
 	"ramdisk_addr_r=" RAMDISK_ADDR_R "\0" \
 	"scriptaddr=" SCRIPT_ADDR_R "\0"
 
-#include <config_distro_bootcmd.h>
-
 #define CFG_EXTRA_ENV_SETTINGS \
 	"console=console=ttyS0,115200\0" \
 	"kernel=/boot/zImage\0" \
 	"fdt=/boot/nsa310s.dtb\0" \
 	"bootargs_root=ubi.mtd=3 root=ubi0:rootfs rootfstype=ubifs rw\0" \
-	LOAD_ADDRESS_ENV_SETTINGS \
-	BOOTENV
-
-#endif /* CONFIG_SPL_BUILD */
+	LOAD_ADDRESS_ENV_SETTINGS
 
 #endif /* _CONFIG_NSA310S_H */
diff --git a/include/configs/pogo_v4.h b/include/configs/pogo_v4.h
index 3371579..d500353 100644
--- a/include/configs/pogo_v4.h
+++ b/include/configs/pogo_v4.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- * Copyright (C) 2014-2022 Tony Dinh <mibodhi@gmail.com>
+ * Copyright (C) 2014-2023 Tony Dinh <mibodhi@gmail.com>
  *
  * Based on
  * Copyright (C) 2012
@@ -21,33 +21,6 @@
  */
 #include "mv-common.h"
 
-/* Include the common distro boot environment */
-#ifndef CONFIG_SPL_BUILD
-
-#ifdef CONFIG_MMC
-#define BOOT_TARGET_DEVICES_MMC(func) func(MMC, mmc, 0)
-#else
-#define BOOT_TARGET_DEVICES_MMC(func)
-#endif
-
-#ifdef CONFIG_SATA
-#define BOOT_TARGET_DEVICES_SATA(func) func(SATA, sata, 0)
-#else
-#define BOOT_TARGET_DEVICES_SATA(func)
-#endif
-
-#ifdef CONFIG_USB_STORAGE
-#define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0)
-#else
-#define BOOT_TARGET_DEVICES_USB(func)
-#endif
-
-#define BOOT_TARGET_DEVICES(func) \
-	BOOT_TARGET_DEVICES_MMC(func) \
-	BOOT_TARGET_DEVICES_USB(func) \
-	BOOT_TARGET_DEVICES_SATA(func) \
-	func(DHCP, dhcp, na)
-
 #define KERNEL_ADDR_R	__stringify(0x800000)
 #define FDT_ADDR_R	__stringify(0x2c00000)
 #define RAMDISK_ADDR_R	__stringify(0x01100000)
@@ -59,14 +32,10 @@
 	"ramdisk_addr_r=" RAMDISK_ADDR_R "\0" \
 	"scriptaddr=" SCRIPT_ADDR_R "\0"
 
-#include <config_distro_bootcmd.h>
-
 #define CFG_EXTRA_ENV_SETTINGS \
 	LOAD_ADDRESS_ENV_SETTINGS \
 	"fdtfile=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
 	"mtdparts=" CONFIG_MTDPARTS_DEFAULT "\0" \
-	"console=ttyS0,115200\0" \
-	BOOTENV
-#endif /* CONFIG_SPL_BUILD */
+	"console=ttyS0,115200\0"
 
 #endif /* _CONFIG_POGO_V4_H */
diff --git a/include/configs/vexpress_aemv8.h b/include/configs/vexpress_aemv8.h
index 43f7e45..24d8ca0 100644
--- a/include/configs/vexpress_aemv8.h
+++ b/include/configs/vexpress_aemv8.h
@@ -148,6 +148,12 @@
 #define FUNC_VIRTIO(func)
 #endif
 
+#ifdef CONFIG_CMD_MMC
+#define FUNC_MMC(func)	func(MMC, mmc, 0)
+#else
+#define FUNC_MMC(func)
+#endif
+
 /*
  * Boot by loading an Android image, or kernel, initrd and FDT through
  * semihosting into DRAM.
@@ -204,6 +210,7 @@
 	func(SMH, smh, na)		\
 	func(MEM, mem, na)		\
 	FUNC_VIRTIO(func)		\
+	FUNC_MMC(func)			\
 	func(PXE, pxe, na)		\
 	func(DHCP, dhcp, na)
 
diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd..b21c5cb 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@
 #define BOOT_SERVICE_CAPABILITY_MIN \
 	offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
 
-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id:	algorithm defined in enum tpm2_algorithms
- *  @digest_size:	size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-	u16      algorithm_id;
-	u16      digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature:			signature, set to Spec ID Event03
- * @platform_class:		class defined in TCG ACPI Specification
- *				Client  Common Header.
- * @spec_version_minor:		minor version
- * @spec_version_major:		major version
- * @spec_version_errata:	major version
- * @uintn_size:			size of the efi_uintn_t fields used in various
- *				data structures used in this specification.
- *				0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:	hashing algorithms used in this event log
- * @digest_sizes:		array of number_of_algorithms pairs
- *				1st member defines the algorithm id
- *				2nd member defines the algorithm size
- */
-struct tcg_efi_spec_id_event {
-	u8 signature[16];
-	u32 platform_class;
-	u8 spec_version_minor;
-	u8 spec_version_major;
-	u8 spec_errata;
-	u8 uintn_size;
-	u32 number_of_algorithms;
-	struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
-} __packed;
-
 /**
  * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log
  * @version:		version number for this structure
diff --git a/include/image.h b/include/image.h
index 5f85bf8..2e3cf83 100644
--- a/include/image.h
+++ b/include/image.h
@@ -409,6 +409,7 @@
 #define BOOTM_STATE_OS_FAKE_GO	0x00000200	/* 'Almost' run the OS */
 #define BOOTM_STATE_OS_GO	0x00000400
 #define BOOTM_STATE_PRE_LOAD	0x00000800
+#define BOOTM_STATE_MEASURE	0x00001000
 	int		state;
 
 #if defined(CONFIG_LMB) && !defined(USE_HOSTCC)
diff --git a/include/test/suites.h b/include/test/suites.h
index 51acbe4..ad4fc92 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -46,6 +46,7 @@
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_mbr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 2b6980e..33dd103 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -169,7 +169,7 @@
 /**
  * Definition of TPMU_HA Union
  */
-union tmpu_ha {
+union tpmu_ha {
 	u8 sha1[TPM2_SHA1_DIGEST_SIZE];
 	u8 sha256[TPM2_SHA256_DIGEST_SIZE];
 	u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE];
@@ -185,7 +185,7 @@
  */
 struct tpmt_ha {
 	u16 hash_alg;
-	union tmpu_ha digest;
+	union tpmu_ha digest;
 } __packed;
 
 /**
@@ -217,6 +217,50 @@
 } __packed;
 
 /**
+ *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
+ *
+ *  @algorithm_id:	algorithm defined in enum tpm2_algorithms
+ *  @digest_size:	size of the algorithm
+ */
+struct tcg_efi_spec_id_event_algorithm_size {
+	u16      algorithm_id;
+	u16      digest_size;
+} __packed;
+
+#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
+#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
+#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
+#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
+
+/**
+ * struct TCG_EfiSpecIDEventStruct - content of the event log header
+ *
+ * @signature:			signature, set to Spec ID Event03
+ * @platform_class:		class defined in TCG ACPI Specification
+ *				Client  Common Header.
+ * @spec_version_minor:		minor version
+ * @spec_version_major:		major version
+ * @spec_version_errata:	major version
+ * @uintn_size:			size of the efi_uintn_t fields used in various
+ *				data structures used in this specification.
+ *				0x01 indicates u32  and 0x02  indicates u64
+ * @number_of_algorithms:	hashing algorithms used in this event log
+ * @digest_sizes:		array of number_of_algorithms pairs
+ *				1st member defines the algorithm id
+ *				2nd member defines the algorithm size
+ */
+struct tcg_efi_spec_id_event {
+	u8 signature[16];
+	u32 platform_class;
+	u8 spec_version_minor;
+	u8 spec_version_major;
+	u8 spec_errata;
+	u8 uintn_size;
+	u32 number_of_algorithms;
+	struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
+} __packed;
+
+/**
  * TPM2 Structure Tags for command/response buffers.
  *
  * @TPM2_ST_NO_SESSIONS: the command does not need an authentication.
@@ -342,6 +386,26 @@
 	TPM2_ALG_SM3_256	= 0x12,
 };
 
+extern const enum tpm2_algorithms tpm2_supported_algorithms[4];
+
+static inline u16 tpm2_algorithm_to_len(enum tpm2_algorithms a)
+{
+	switch (a) {
+	case TPM2_ALG_SHA1:
+		return TPM2_SHA1_DIGEST_SIZE;
+	case TPM2_ALG_SHA256:
+		return TPM2_SHA256_DIGEST_SIZE;
+	case TPM2_ALG_SHA384:
+		return TPM2_SHA384_DIGEST_SIZE;
+	case TPM2_ALG_SHA512:
+		return TPM2_SHA512_DIGEST_SIZE;
+	default:
+		return 0;
+	}
+}
+
+#define tpm2_algorithm_to_mask(a)	(1 << (a))
+
 /* NV index attributes */
 enum tpm_index_attrs {
 	TPMA_NV_PPWRITE		= 1UL << 0,
@@ -422,6 +486,188 @@
 };
 
 /**
+ * struct tcg2_event_log - Container for managing the platform event log
+ *
+ * @log:		Address of the log
+ * @log_position:	Current entry position
+ * @log_size:		Log space available
+ * @found:		Boolean indicating if an existing log was discovered
+ */
+struct tcg2_event_log {
+	u8 *log;
+	u32 log_position;
+	u32 log_size;
+	bool found;
+};
+
+/**
+ * Create a list of digests of the supported PCR banks for a given input data
+ *
+ * @dev		TPM device
+ * @input	Data
+ * @length	Length of the data to calculate the digest
+ * @digest_list	List of digests to fill in
+ *
+ * Return: zero on success, negative errno otherwise
+ */
+int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length,
+		       struct tpml_digest_values *digest_list);
+
+/**
+ * Get the event size of the specified digests
+ *
+ * @digest_list	List of digests for the event
+ *
+ * Return: Size in bytes of the event
+ */
+u32 tcg2_event_get_size(struct tpml_digest_values *digest_list);
+
+/**
+ * tcg2_get_active_pcr_banks
+ *
+ * @dev			TPM device
+ * @active_pcr_banks	Bitmask of PCR algorithms supported
+ *
+ * Return: zero on success, negative errno otherwise
+ */
+int tcg2_get_active_pcr_banks(struct udevice *dev, u32 *active_pcr_banks);
+
+/**
+ * tcg2_log_append - Append an event to an event log
+ *
+ * @pcr_index	Index of the PCR
+ * @event_type	Type of event
+ * @digest_list List of digests to add
+ * @size	Size of event
+ * @event	Event data
+ * @log		Log buffer to append the event to
+ */
+void tcg2_log_append(u32 pcr_index, u32 event_type,
+		     struct tpml_digest_values *digest_list, u32 size,
+		     const u8 *event, u8 *log);
+
+/**
+ * Extend the PCR with specified digests
+ *
+ * @dev		TPM device
+ * @pcr_index	Index of the PCR
+ * @digest_list	List of digests to extend
+ *
+ * Return: zero on success, negative errno otherwise
+ */
+int tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
+		    struct tpml_digest_values *digest_list);
+
+/**
+ * Read the PCR into a list of digests
+ *
+ * @dev		TPM device
+ * @pcr_index	Index of the PCR
+ * @digest_list	List of digests to extend
+ *
+ * Return: zero on success, negative errno otherwise
+ */
+int tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
+		  struct tpml_digest_values *digest_list);
+
+/**
+ * Measure data into the TPM PCRs and the platform event log.
+ *
+ * @dev		TPM device
+ * @log		Platform event log
+ * @pcr_index	Index of the PCR
+ * @size	Size of the data or 0 for event only
+ * @data	Pointer to the data or NULL for event only
+ * @event_type	Event log type
+ * @event_size	Size of the event
+ * @event	Pointer to the event
+ *
+ * Return: zero on success, negative errno otherwise
+ */
+int tcg2_measure_data(struct udevice *dev, struct tcg2_event_log *elog,
+		      u32 pcr_index, u32 size, const u8 *data, u32 event_type,
+		      u32 event_size, const u8 *event);
+
+#define tcg2_measure_event(dev, elog, pcr_index, event_type, size, event) \
+	tcg2_measure_data(dev, elog, pcr_index, 0, NULL, event_type, size, \
+			  event)
+
+/**
+ * Prepare the event log buffer. This function tries to discover an existing
+ * event log in memory from a previous bootloader stage. If such a log exists
+ * and the PCRs are not extended, the log is "replayed" to extend the PCRs.
+ * If no log is discovered, create the log header.
+ *
+ * @dev			TPM device
+ * @elog		Platform event log. The log pointer and log_size
+ *			members must be initialized to either 0 or to a valid
+ *			memory region, in which case any existing log
+ *			discovered will be copied to the specified memory
+ *			region.
+ * @ignore_existing_log	Boolean to indicate whether or not to ignore an
+ *			existing platform log in memory
+ *
+ * Return: zero on success, negative errno otherwise
+ */
+int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
+			    bool ignore_existing_log);
+
+/**
+ * Begin measurements.
+ *
+ * @dev			TPM device
+ * @elog		Platform event log. The log pointer and log_size
+ *			members must be initialized to either 0 or to a valid
+ *			memory region, in which case any existing log
+ *			discovered will be copied to the specified memory
+ *			region.
+ * @ignore_existing_log Boolean to indicate whether or not to ignore an
+ *			existing platform log in memory
+ *
+ * Return: zero on success, negative errno otherwise
+ */
+int tcg2_measurement_init(struct udevice **dev, struct tcg2_event_log *elog,
+			  bool ignore_existing_log);
+
+/**
+ * Stop measurements and record separator events.
+ *
+ * @dev		TPM device
+ * @elog	Platform event log
+ * @error	Boolean to indicate whether an error ocurred or not
+ */
+void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
+			   bool error);
+
+/**
+ * Get the platform event log address and size.
+ *
+ * @dev		TPM device
+ * @addr	Address of the log
+ * @size	Size of the log
+ *
+ * Return: zero on success, negative errno otherwise
+ */
+int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size);
+
+/**
+ * Get the first TPM2 device found.
+ *
+ * @dev		TPM device
+ *
+ * Return: zero on success, negative errno otherwise
+ */
+int tcg2_platform_get_tpm2(struct udevice **dev);
+
+/**
+ * Platform-specific function for handling TPM startup errors
+ *
+ * @dev		TPM device
+ * @rc		The TPM response code
+ */
+void tcg2_platform_startup_error(struct udevice *dev, int rc);
+
+/**
  * Issue a TPM2_Startup command.
  *
  * @dev		TPM device
@@ -541,6 +787,19 @@
 			void *buf, size_t prop_count);
 
 /**
+ * tpm2_get_pcr_info() - get the supported, active PCRs and number of banks
+ *
+ * @dev:		TPM device
+ * @supported_pcr:	bitmask with the algorithms supported
+ * @active_pcr:		bitmask with the active algorithms
+ * @pcr_banks:		number of PCR banks
+ *
+ * @return 0 on success, code of operation or negative errno on failure
+ */
+int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
+		      u32 *pcr_banks);
+
+/**
  * Issue a TPM2_DictionaryAttackLockReset command.
  *
  * @dev		TPM device
diff --git a/lib/Kconfig b/lib/Kconfig
index f6ca559..1964951 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -431,6 +431,10 @@
 	bool "Trusted Platform Module (TPM) Support"
 	depends on DM
 	imply DM_RNG
+	select SHA1
+	select SHA256
+	select SHA384
+	select SHA512
 	help
 	  This enables support for TPMs which can be used to provide security
 	  features for your board. The TPM can be connected via LPC or I2C
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index d20aaab..4ccd26f 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -379,8 +379,6 @@
 	bool "EFI_TCG2_PROTOCOL support"
 	default y
 	depends on TPM_V2
-	# Sandbox TPM currently fails on GetCapabilities needed for TCG2
-	depends on !SANDBOX
 	select SHA1
 	select SHA256
 	select SHA384
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 7b7926a..2eaa12b 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -66,35 +66,6 @@
 static const efi_guid_t efi_guid_tcg2_protocol = EFI_TCG2_PROTOCOL_GUID;
 static const efi_guid_t efi_guid_final_events = EFI_TCG2_FINAL_EVENTS_TABLE_GUID;
 
-struct digest_info {
-	u16 hash_alg;
-	u32 hash_mask;
-	u16 hash_len;
-};
-
-static const struct digest_info hash_algo_list[] = {
-	{
-		TPM2_ALG_SHA1,
-		EFI_TCG2_BOOT_HASH_ALG_SHA1,
-		TPM2_SHA1_DIGEST_SIZE,
-	},
-	{
-		TPM2_ALG_SHA256,
-		EFI_TCG2_BOOT_HASH_ALG_SHA256,
-		TPM2_SHA256_DIGEST_SIZE,
-	},
-	{
-		TPM2_ALG_SHA384,
-		EFI_TCG2_BOOT_HASH_ALG_SHA384,
-		TPM2_SHA384_DIGEST_SIZE,
-	},
-	{
-		TPM2_ALG_SHA512,
-		EFI_TCG2_BOOT_HASH_ALG_SHA512,
-		TPM2_SHA512_DIGEST_SIZE,
-	},
-};
-
 struct variable_info {
 	const u16	*name;
 	bool		accept_empty;
@@ -113,46 +84,6 @@
 	{u"AuditMode",		false,	1},
 };
 
-#define MAX_HASH_COUNT ARRAY_SIZE(hash_algo_list)
-
-/**
- * alg_to_mask - Get a TCG hash mask for algorithms
- *
- * @hash_alg: TCG defined algorithm
- *
- * @Return: TCG hashing algorithm bitmaps, 0 if the algorithm is not supported
- */
-static u32 alg_to_mask(u16 hash_alg)
-{
-	size_t i;
-
-	for (i = 0; i < MAX_HASH_COUNT; i++) {
-		if (hash_algo_list[i].hash_alg == hash_alg)
-			return hash_algo_list[i].hash_mask;
-	}
-
-	return 0;
-}
-
-/**
- * alg_to_len - Get a TCG hash len for algorithms
- *
- * @hash_alg: TCG defined algorithm
- *
- * @Return: len of chosen algorithm, 0 if the algorithm is not supported
- */
-static u16 alg_to_len(u16 hash_alg)
-{
-	size_t i;
-
-	for (i = 0; i < MAX_HASH_COUNT; i++) {
-		if (hash_algo_list[i].hash_alg == hash_alg)
-			return hash_algo_list[i].hash_len;
-	}
-
-	return 0;
-}
-
 static bool is_tcg2_protocol_installed(void)
 {
 	struct efi_handler *handler;
@@ -162,145 +93,6 @@
 	return ret == EFI_SUCCESS;
 }
 
-static u32 tcg_event_final_size(struct tpml_digest_values *digest_list)
-{
-	u32 len;
-	size_t i;
-
-	len = offsetof(struct tcg_pcr_event2, digests);
-	len += offsetof(struct tpml_digest_values, digests);
-	for (i = 0; i < digest_list->count; i++) {
-		u16 hash_alg = digest_list->digests[i].hash_alg;
-
-		len += offsetof(struct tpmt_ha, digest);
-		len += alg_to_len(hash_alg);
-	}
-	len += sizeof(u32); /* tcg_pcr_event2 event_size*/
-
-	return len;
-}
-
-/* tcg2_pcr_extend - Extend PCRs for a TPM2 device for a given tpml_digest_values
- *
- * @dev:		device
- * @digest_list:	list of digest algorithms to extend
- *
- * @Return: status code
- */
-static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
-				    struct tpml_digest_values *digest_list)
-{
-	u32 rc;
-	size_t i;
-
-	for (i = 0; i < digest_list->count; i++) {
-		u32 alg = digest_list->digests[i].hash_alg;
-
-		rc = tpm2_pcr_extend(dev, pcr_index, alg,
-				     (u8 *)&digest_list->digests[i].digest,
-				     alg_to_len(alg));
-		if (rc) {
-			EFI_PRINT("Failed to extend PCR\n");
-			return EFI_DEVICE_ERROR;
-		}
-	}
-
-	return EFI_SUCCESS;
-}
-
-/* tcg2_pcr_read - Read PCRs for a TPM2 device for a given tpml_digest_values
- *
- * @dev:		device
- * @pcr_index:		PCR index
- * @digest_list:	list of digest algorithms to extend
- *
- * @Return: status code
- */
-static efi_status_t tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
-				  struct tpml_digest_values *digest_list)
-{
-	struct tpm_chip_priv *priv;
-	unsigned int updates, pcr_select_min;
-	u32 rc;
-	size_t i;
-
-	priv = dev_get_uclass_priv(dev);
-	if (!priv)
-		return EFI_DEVICE_ERROR;
-
-	pcr_select_min = priv->pcr_select_min;
-
-	for (i = 0; i < digest_list->count; i++) {
-		u16 hash_alg = digest_list->digests[i].hash_alg;
-		u8 *digest = (u8 *)&digest_list->digests[i].digest;
-
-		rc = tpm2_pcr_read(dev, pcr_index, pcr_select_min,
-				   hash_alg, digest, alg_to_len(hash_alg),
-				   &updates);
-		if (rc) {
-			EFI_PRINT("Failed to read PCR\n");
-			return EFI_DEVICE_ERROR;
-		}
-	}
-
-	return EFI_SUCCESS;
-}
-
-/* put_event - Append an agile event to an eventlog
- *
- * @pcr_index:		PCR index
- * @event_type:		type of event added
- * @digest_list:	list of digest algorithms to add
- * @size:		size of event
- * @event:		event to add
- * @log:		log buffer to append the event
- *
- */
-static void put_event(u32 pcr_index, u32 event_type,
-		      struct tpml_digest_values *digest_list, u32 size,
-		      u8 event[], void *log)
-{
-	size_t pos;
-	size_t i;
-	u32 event_size;
-
-	/*
-	 * size refers to the length of event[] only, we need to check against
-	 * the final tcg_pcr_event2 size
-	 */
-	event_size = size + tcg_event_final_size(digest_list);
-
-	put_unaligned_le32(pcr_index, log);
-	pos = offsetof(struct tcg_pcr_event2, event_type);
-	put_unaligned_le32(event_type, (void *)((uintptr_t)log + pos));
-	pos = offsetof(struct tcg_pcr_event2, digests); /* count */
-	put_unaligned_le32(digest_list->count, (void *)((uintptr_t)log + pos));
-
-	pos += offsetof(struct tpml_digest_values, digests);
-	for (i = 0; i < digest_list->count; i++) {
-		u16 hash_alg = digest_list->digests[i].hash_alg;
-		u8 *digest = (u8 *)&digest_list->digests[i].digest;
-
-		put_unaligned_le16(hash_alg, (void *)((uintptr_t)log + pos));
-		pos += offsetof(struct tpmt_ha, digest);
-		memcpy((void *)((uintptr_t)log + pos), digest, alg_to_len(hash_alg));
-		pos += alg_to_len(hash_alg);
-	}
-
-	put_unaligned_le32(size, (void *)((uintptr_t)log + pos));
-	pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
-	memcpy((void *)((uintptr_t)log + pos), event, size);
-	pos += size;
-
-	/*
-	 * make sure the calculated buffer is what we checked against
-	 * This check should never fail.  It checks the code above is
-	 * calculating the right length for the event we are adding
-	 */
-	if (pos != event_size)
-		log_err("Appending to the EventLog failed\n");
-}
-
 /* tcg2_agile_log_append - Append an agile event to an eventlog
  *
  * @pcr_index:		PCR index
@@ -317,7 +109,7 @@
 					  u32 size, u8 event[])
 {
 	void *log = (void *)((uintptr_t)event_log.buffer + event_log.pos);
-	u32 event_size = size + tcg_event_final_size(digest_list);
+	u32 event_size = size + tcg2_event_get_size(digest_list);
 	struct efi_tcg2_final_events_table *final_event;
 	efi_status_t ret = EFI_SUCCESS;
 
@@ -328,7 +120,7 @@
 			event_log.truncated = true;
 			return EFI_VOLUME_FULL;
 		}
-		put_event(pcr_index, event_type, digest_list, size, event, log);
+		tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
 		event_log.pos += event_size;
 		event_log.last_event_size = event_size;
 	}
@@ -341,7 +133,7 @@
 		return EFI_VOLUME_FULL;
 
 	log = (void *)((uintptr_t)event_log.final_buffer + event_log.final_pos);
-	put_event(pcr_index, event_type, digest_list, size, event, log);
+	tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
 
 	final_event = event_log.final_buffer;
 	final_event->number_of_events++;
@@ -351,66 +143,6 @@
 }
 
 /**
- * platform_get_tpm_device() - retrieve TPM device
- *
- * This function retrieves the udevice implementing a TPM
- *
- * This function may be overridden if special initialization is needed.
- *
- * @dev:	udevice
- * Return:	status code
- */
-__weak efi_status_t platform_get_tpm2_device(struct udevice **dev)
-{
-	for_each_tpm_device(*dev) {
-		/* Only support TPMv2 devices */
-		if (tpm_get_version(*dev) == TPM_V2)
-			return EFI_SUCCESS;
-	}
-
-	return EFI_NOT_FOUND;
-}
-
-/**
- * platform_get_eventlog() - retrieve the eventlog address and size
- *
- * This function retrieves the eventlog address and size if the underlying
- * firmware has done some measurements and passed them.
- *
- * This function may be overridden based on platform specific method of
- * passing the eventlog address and size.
- *
- * @dev:	udevice
- * @addr:	eventlog address
- * @sz:		eventlog size
- * Return:	status code
- */
-__weak efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr,
-					  u32 *sz)
-{
-	const u64 *basep;
-	const u32 *sizep;
-
-	basep = dev_read_prop(dev, "tpm_event_log_addr", NULL);
-	if (!basep)
-		return EFI_NOT_FOUND;
-
-	*addr = be64_to_cpup((__force __be64 *)basep);
-
-	sizep = dev_read_prop(dev, "tpm_event_log_size", NULL);
-	if (!sizep)
-		return EFI_NOT_FOUND;
-
-	*sz = be32_to_cpup((__force __be32 *)sizep);
-	if (*sz == 0) {
-		log_debug("event log empty\n");
-		return EFI_NOT_FOUND;
-	}
-
-	return EFI_SUCCESS;
-}
-
-/**
  * tpm2_get_max_command_size() - get the supported max command size
  *
  * @dev:		TPM device
@@ -483,241 +215,9 @@
 	*manufacturer_id = get_unaligned_be32(response + properties_offset);
 
 	return 0;
-}
-
-/**
- * tpm2_get_num_pcr() - get the number of PCRs
- *
- * @dev:		TPM device
- * @manufacturer_id:	output buffer for the number
- *
- * Return: 0 on success, -1 on error
- */
-static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
-{
-	u8 response[TPM2_RESPONSE_BUFFER_SIZE];
-	u32 ret;
-
-	memset(response, 0, sizeof(response));
-	ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
-				  TPM2_PT_PCR_COUNT, response, 1);
-	if (ret)
-		return -1;
-
-	*num_pcr = get_unaligned_be32(response + properties_offset);
-	if (*num_pcr > TPM2_MAX_PCRS)
-		return -1;
-
-	return 0;
-}
-
-/**
- * is_active_pcr() - Check if a supported algorithm is active
- *
- * @dev:		TPM device
- * @selection:		struct of PCR information
- *
- * Return: true if PCR is active
- */
-static bool is_active_pcr(struct tpms_pcr_selection *selection)
-{
-	int i;
-	/*
-	 * check the pcr_select. If at least one of the PCRs supports the
-	 * algorithm add it on the active ones
-	 */
-	for (i = 0; i < selection->size_of_select; i++) {
-		if (selection->pcr_select[i])
-			return true;
-	}
-
-	return false;
-}
-
-/**
- * tpm2_get_pcr_info() - get the supported, active PCRs and number of banks
- *
- * @dev:		TPM device
- * @supported_pcr:	bitmask with the algorithms supported
- * @active_pcr:		bitmask with the active algorithms
- * @pcr_banks:		number of PCR banks
- *
- * Return: 0 on success, -1 on error
- */
-static int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr,
-			     u32 *active_pcr, u32 *pcr_banks)
-{
-	u8 response[TPM2_RESPONSE_BUFFER_SIZE];
-	struct tpml_pcr_selection pcrs;
-	u32 ret, num_pcr;
-	size_t i;
-	int tpm_ret;
-
-	*supported_pcr = 0;
-	*active_pcr = 0;
-	*pcr_banks = 0;
-	memset(response, 0, sizeof(response));
-	ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
-	if (ret)
-		goto out;
-
-	pcrs.count = get_unaligned_be32(response);
-	/*
-	 * We only support 5 algorithms for now so check against that
-	 * instead of TPM2_NUM_PCR_BANKS
-	 */
-	if (pcrs.count > MAX_HASH_COUNT || pcrs.count < 1)
-		goto out;
-
-	tpm_ret = tpm2_get_num_pcr(dev, &num_pcr);
-	if (tpm_ret)
-		goto out;
-
-	for (i = 0; i < pcrs.count; i++) {
-		/*
-		 * Definition of TPMS_PCR_SELECTION Structure
-		 * hash: u16
-		 * size_of_select: u8
-		 * pcr_select: u8 array
-		 *
-		 * The offsets depend on the number of the device PCRs
-		 * so we have to calculate them based on that
-		 */
-		u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
-			i * offsetof(struct tpms_pcr_selection, pcr_select) +
-			i * ((num_pcr + 7) / 8);
-		u32 size_select_offset =
-			hash_offset + offsetof(struct tpms_pcr_selection,
-					       size_of_select);
-		u32 pcr_select_offset =
-			hash_offset + offsetof(struct tpms_pcr_selection,
-					       pcr_select);
-
-		pcrs.selection[i].hash =
-			get_unaligned_be16(response + hash_offset);
-		pcrs.selection[i].size_of_select =
-			__get_unaligned_be(response + size_select_offset);
-		if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX)
-			goto out;
-		/* copy the array of pcr_select */
-		memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset,
-		       pcrs.selection[i].size_of_select);
-	}
-
-	for (i = 0; i < pcrs.count; i++) {
-		u32 hash_mask = alg_to_mask(pcrs.selection[i].hash);
-
-		if (hash_mask) {
-			*supported_pcr |= hash_mask;
-			if (is_active_pcr(&pcrs.selection[i]))
-				*active_pcr |= hash_mask;
-		} else {
-			EFI_PRINT("Unknown algorithm %x\n", pcrs.selection[i].hash);
-		}
-	}
-
-	*pcr_banks = pcrs.count;
-
-	return 0;
-out:
-	return -1;
 }
 
 /**
- * __get_active_pcr_banks() - returns the currently active PCR banks
- *
- * @active_pcr_banks:		pointer for receiving the bitmap of currently
- *				active PCR banks
- *
- * Return:	status code
- */
-static efi_status_t __get_active_pcr_banks(u32 *active_pcr_banks)
-{
-	struct udevice *dev;
-	u32 active = 0, supported = 0, pcr_banks = 0;
-	efi_status_t ret;
-	int err;
-
-	ret = platform_get_tpm2_device(&dev);
-	if (ret != EFI_SUCCESS)
-		goto out;
-
-	err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
-	if (err) {
-		ret = EFI_DEVICE_ERROR;
-		goto out;
-	}
-
-	*active_pcr_banks = active;
-
-out:
-	return ret;
-}
-
-/* tcg2_create_digest - create a list of digests of the supported PCR banks
- *			for a given memory range
- *
- * @input:		input memory
- * @length:		length of buffer to calculate the digest
- * @digest_list:	list of digests to fill in
- *
- * Return:		status code
- */
-static efi_status_t tcg2_create_digest(const u8 *input, u32 length,
-				       struct tpml_digest_values *digest_list)
-{
-	sha1_context ctx;
-	sha256_context ctx_256;
-	sha512_context ctx_512;
-	u8 final[TPM2_SHA512_DIGEST_SIZE];
-	efi_status_t ret;
-	u32 active;
-	size_t i;
-
-	ret = __get_active_pcr_banks(&active);
-	if (ret != EFI_SUCCESS)
-		return ret;
-
-	digest_list->count = 0;
-	for (i = 0; i < MAX_HASH_COUNT; i++) {
-		u16 hash_alg = hash_algo_list[i].hash_alg;
-
-		if (!(active & alg_to_mask(hash_alg)))
-			continue;
-		switch (hash_alg) {
-		case TPM2_ALG_SHA1:
-			sha1_starts(&ctx);
-			sha1_update(&ctx, input, length);
-			sha1_finish(&ctx, final);
-			break;
-		case TPM2_ALG_SHA256:
-			sha256_starts(&ctx_256);
-			sha256_update(&ctx_256, input, length);
-			sha256_finish(&ctx_256, final);
-			break;
-		case TPM2_ALG_SHA384:
-			sha384_starts(&ctx_512);
-			sha384_update(&ctx_512, input, length);
-			sha384_finish(&ctx_512, final);
-			break;
-		case TPM2_ALG_SHA512:
-			sha512_starts(&ctx_512);
-			sha512_update(&ctx_512, input, length);
-			sha512_finish(&ctx_512, final);
-			break;
-		default:
-			continue;
-		}
-		digest_list->digests[digest_list->count].hash_alg = hash_alg;
-		memcpy(&digest_list->digests[digest_list->count].digest, final,
-		       (u32)alg_to_len(hash_alg));
-		digest_list->count++;
-	}
-
-	return EFI_SUCCESS;
-}
-
-/**
  * efi_tcg2_get_capability() - protocol capability information and state information
  *
  * @this:		TCG2 protocol instance
@@ -758,7 +258,7 @@
 	capability->protocol_version.major = 1;
 	capability->protocol_version.minor = 1;
 
-	efi_ret = platform_get_tpm2_device(&dev);
+	efi_ret = tcg2_platform_get_tpm2(&dev);
 	if (efi_ret != EFI_SUCCESS) {
 		capability->supported_event_logs = 0;
 		capability->hash_algorithm_bitmap = 0;
@@ -854,7 +354,7 @@
 		goto out;
 	}
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS) {
 		event_log_location = NULL;
 		event_log_last_entry = NULL;
@@ -889,6 +389,7 @@
 	struct efi_image_regions *regs = NULL;
 	void *new_efi = NULL;
 	u8 hash[TPM2_SHA512_DIGEST_SIZE];
+	struct udevice *dev;
 	efi_status_t ret;
 	u32 active;
 	int i;
@@ -904,16 +405,20 @@
 		goto out;
 	}
 
-	ret = __get_active_pcr_banks(&active);
+	ret = tcg2_platform_get_tpm2(&dev);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	ret = tcg2_get_active_pcr_banks(dev, &active);
 	if (ret != EFI_SUCCESS) {
 		goto out;
 	}
 
 	digest_list->count = 0;
-	for (i = 0; i < MAX_HASH_COUNT; i++) {
-		u16 hash_alg = hash_algo_list[i].hash_alg;
+	for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); i++) {
+		u16 hash_alg = tpm2_supported_algorithms[i];
 
-		if (!(active & alg_to_mask(hash_alg)))
+		if (!(active & tpm2_algorithm_to_mask(hash_alg)))
 			continue;
 		switch (hash_alg) {
 		case TPM2_ALG_SHA1:
@@ -933,7 +438,7 @@
 		}
 		digest_list->digests[digest_list->count].hash_alg = hash_alg;
 		memcpy(&digest_list->digests[digest_list->count].digest, hash,
-		       (u32)alg_to_len(hash_alg));
+		       (u32)tpm2_algorithm_to_len(hash_alg));
 		digest_list->count++;
 	}
 
@@ -973,7 +478,7 @@
 	if (!is_tcg2_protocol_installed())
 		return EFI_SUCCESS;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		return EFI_SECURITY_VIOLATION;
 
@@ -1082,7 +587,7 @@
 		goto out;
 	}
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
@@ -1117,7 +622,7 @@
 		ret = tcg2_hash_pe_image((void *)(uintptr_t)data_to_hash,
 					 data_to_hash_len, &digest_list);
 	} else {
-		ret = tcg2_create_digest((u8 *)(uintptr_t)data_to_hash,
+		ret = tcg2_create_digest(dev, (u8 *)(uintptr_t)data_to_hash,
 					 data_to_hash_len, &digest_list);
 	}
 
@@ -1180,7 +685,7 @@
 		goto out;
 	}
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
@@ -1209,15 +714,20 @@
 efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this,
 			      u32 *active_pcr_banks)
 {
+	struct udevice *dev;
 	efi_status_t ret;
 
+	EFI_ENTRY("%p, %p", this, active_pcr_banks);
+
 	if (!this || !active_pcr_banks) {
 		ret = EFI_INVALID_PARAMETER;
 		goto out;
 	}
+	ret = tcg2_platform_get_tpm2(&dev);
+	if (ret != EFI_SUCCESS)
+		goto out;
 
-	EFI_ENTRY("%p, %p", this, active_pcr_banks);
-	ret = __get_active_pcr_banks(active_pcr_banks);
+	ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks);
 
 out:
 	return EFI_EXIT(ret);
@@ -1269,397 +779,6 @@
 };
 
 /**
- * parse_event_log_header() -  Parse and verify the event log header fields
- *
- * @buffer:			Pointer to the start of the eventlog
- * @size:			Size of the eventlog
- * @pos:			Return offset of the next event in buffer right
- *				after the event header i.e specID
- *
- * Return:	status code
- */
-static efi_status_t parse_event_log_header(void *buffer, u32 size, u32 *pos)
-{
-	struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
-	int i = 0;
-
-	if (size < sizeof(*event_header))
-		return EFI_COMPROMISED_DATA;
-
-	if (get_unaligned_le32(&event_header->pcr_index) != 0 ||
-	    get_unaligned_le32(&event_header->event_type) != EV_NO_ACTION)
-		return EFI_COMPROMISED_DATA;
-
-	for (i = 0; i < sizeof(event_header->digest); i++) {
-		if (event_header->digest[i])
-			return EFI_COMPROMISED_DATA;
-	}
-
-	*pos += sizeof(*event_header);
-
-	return EFI_SUCCESS;
-}
-
-/**
- * parse_specid_event() -  Parse and verify the specID Event in the eventlog
- *
- * @dev:		udevice
- * @buffer:		Pointer to the start of the eventlog
- * @log_size:		Size of the eventlog
- * @pos:		[in] Offset of specID event in the eventlog buffer
- *			[out] Return offset of the next event in the buffer
- *			after the specID
- * @digest_list:	list of digests in the event
- *
- * Return:		status code
- * @pos			Offset in the eventlog where the specID event ends
- * @digest_list:	list of digests in the event
- */
-static efi_status_t parse_specid_event(struct udevice *dev, void *buffer,
-				       u32 log_size, u32 *pos,
-				       struct tpml_digest_values *digest_list)
-{
-	struct tcg_efi_spec_id_event *spec_event;
-	struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
-	size_t spec_event_size;
-	u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
-	u32 spec_active = 0;
-	u16 hash_alg;
-	u8 vendor_sz;
-	int err, i;
-
-	if (*pos >= log_size || (*pos + sizeof(*spec_event)) > log_size)
-		return EFI_COMPROMISED_DATA;
-
-	/* Check specID event data */
-	spec_event = (struct tcg_efi_spec_id_event *)((uintptr_t)buffer + *pos);
-	/* Check for signature */
-	if (memcmp(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
-		   sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03))) {
-		log_err("specID Event: Signature mismatch\n");
-		return EFI_COMPROMISED_DATA;
-	}
-
-	if (spec_event->spec_version_minor !=
-			TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
-	    spec_event->spec_version_major !=
-			TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
-		return EFI_COMPROMISED_DATA;
-
-	if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
-	    spec_event->number_of_algorithms < 1) {
-		log_err("specID Event: Number of algorithms incorrect\n");
-		return EFI_COMPROMISED_DATA;
-	}
-
-	alg_count = spec_event->number_of_algorithms;
-
-	err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
-	if (err)
-		return EFI_DEVICE_ERROR;
-
-	digest_list->count = 0;
-	/*
-	 * We have to take care that the sequence of algorithms that we record
-	 * in digest_list matches the sequence in eventlog.
-	 */
-	for (i = 0; i < alg_count; i++) {
-		hash_alg =
-		  get_unaligned_le16(&spec_event->digest_sizes[i].algorithm_id);
-
-		if (!(supported & alg_to_mask(hash_alg))) {
-			log_err("specID Event: Unsupported algorithm\n");
-			return EFI_COMPROMISED_DATA;
-		}
-		digest_list->digests[digest_list->count++].hash_alg = hash_alg;
-
-		spec_active |= alg_to_mask(hash_alg);
-	}
-
-	/*
-	 * TCG specification expects the event log to have hashes for all
-	 * active PCR's
-	 */
-	if (spec_active != active) {
-		/*
-		 * Previous stage bootloader should know all the active PCR's
-		 * and use them in the Eventlog.
-		 */
-		log_err("specID Event: All active hash alg not present\n");
-		return EFI_COMPROMISED_DATA;
-	}
-
-	/*
-	 * the size of the spec event and placement of vendor_info_size
-	 * depends on supported algoriths
-	 */
-	spec_event_size =
-		offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
-		alg_count * sizeof(spec_event->digest_sizes[0]);
-
-	if (*pos + spec_event_size >= log_size)
-		return EFI_COMPROMISED_DATA;
-
-	vendor_sz = *(uint8_t *)((uintptr_t)buffer + *pos + spec_event_size);
-
-	spec_event_size += sizeof(vendor_sz) + vendor_sz;
-	*pos += spec_event_size;
-
-	if (get_unaligned_le32(&event_header->event_size) != spec_event_size) {
-		log_err("specID event: header event size mismatch\n");
-		/* Right way to handle this can be to call SetActive PCR's */
-		return EFI_COMPROMISED_DATA;
-	}
-
-	return EFI_SUCCESS;
-}
-
-/**
- * tcg2_parse_event() -  Parse the event in the eventlog
- *
- * @dev:		udevice
- * @buffer:		Pointer to the start of the eventlog
- * @log_size:		Size of the eventlog
- * @offset:		[in] Offset of the event in the eventlog buffer
- *			[out] Return offset of the next event in the buffer
- * @digest_list:	list of digests in the event
- * @pcr			Index of the PCR in the event
- *
- * Return:		status code
- */
-static efi_status_t tcg2_parse_event(struct udevice *dev, void *buffer,
-				     u32 log_size, u32 *offset,
-				     struct tpml_digest_values *digest_list,
-				     u32 *pcr)
-{
-	struct tcg_pcr_event2 *event = NULL;
-	u32 count, size, event_size;
-	size_t pos;
-
-	event_size = tcg_event_final_size(digest_list);
-	if (*offset >= log_size || *offset + event_size > log_size) {
-		log_err("Event exceeds log size\n");
-		return EFI_COMPROMISED_DATA;
-	}
-
-	event = (struct tcg_pcr_event2 *)((uintptr_t)buffer + *offset);
-	*pcr = get_unaligned_le32(&event->pcr_index);
-
-	/* get the count */
-	count = get_unaligned_le32(&event->digests.count);
-	if (count != digest_list->count)
-		return EFI_COMPROMISED_DATA;
-
-	pos = offsetof(struct tcg_pcr_event2, digests);
-	pos += offsetof(struct tpml_digest_values, digests);
-
-	for (int i = 0; i < digest_list->count; i++) {
-		u16 alg;
-		u16 hash_alg = digest_list->digests[i].hash_alg;
-		u8 *digest = (u8 *)&digest_list->digests[i].digest;
-
-		alg = get_unaligned_le16((void *)((uintptr_t)event + pos));
-
-		if (alg != hash_alg)
-			return EFI_COMPROMISED_DATA;
-
-		pos += offsetof(struct tpmt_ha, digest);
-		memcpy(digest, (void *)((uintptr_t)event + pos), alg_to_len(hash_alg));
-		pos += alg_to_len(hash_alg);
-	}
-
-	size = get_unaligned_le32((void *)((uintptr_t)event + pos));
-	event_size += size;
-	pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
-	pos += size;
-
-	/* make sure the calculated buffer is what we checked against */
-	if (pos != event_size)
-		return EFI_COMPROMISED_DATA;
-
-	if (pos > log_size)
-		return EFI_COMPROMISED_DATA;
-
-	*offset += pos;
-
-	return EFI_SUCCESS;
-}
-
-/**
- * tcg2_get_fw_eventlog() -  Get the eventlog address and size
- *
- * If the previous firmware has passed some eventlog, this function get it's
- * location and check for it's validity.
- *
- * @dev:		udevice
- * @log_buffer:		eventlog address
- * @log_sz:		eventlog size
- *
- * Return:	status code
- */
-static efi_status_t tcg2_get_fw_eventlog(struct udevice *dev, void *log_buffer,
-					 size_t *log_sz)
-{
-	struct tpml_digest_values digest_list;
-	void *buffer;
-	efi_status_t ret;
-	u32 pcr, pos;
-	u64 base;
-	u32 sz;
-	bool extend_pcr = false;
-	int i;
-
-	ret = platform_get_eventlog(dev, &base, &sz);
-	if (ret != EFI_SUCCESS)
-		return ret;
-
-	if (sz > TPM2_EVENT_LOG_SIZE)
-		return EFI_VOLUME_FULL;
-
-	buffer = (void *)(uintptr_t)base;
-	pos = 0;
-	/* Parse the eventlog to check for its validity */
-	ret = parse_event_log_header(buffer, sz, &pos);
-	if (ret)
-		return ret;
-
-	ret = parse_specid_event(dev, buffer, sz, &pos, &digest_list);
-	if (ret) {
-		log_err("Error parsing SPEC ID Event\n");
-		return ret;
-	}
-
-	ret = tcg2_pcr_read(dev, 0, &digest_list);
-	if (ret) {
-		log_err("Error reading PCR 0\n");
-		return ret;
-	}
-
-	/*
-	 * If PCR0 is 0, previous firmware didn't have the capability
-	 * to extend the PCR. In this scenario, extend the PCR as
-	 * the eventlog is parsed.
-	 */
-	for (i = 0; i < digest_list.count; i++) {
-		u8 hash_buf[TPM2_SHA512_DIGEST_SIZE] = { 0 };
-		u16 hash_alg = digest_list.digests[i].hash_alg;
-
-		if (!memcmp((u8 *)&digest_list.digests[i].digest, hash_buf,
-			    alg_to_len(hash_alg)))
-			extend_pcr = true;
-	}
-
-	while (pos < sz) {
-		ret = tcg2_parse_event(dev, buffer, sz, &pos, &digest_list,
-				       &pcr);
-		if (ret) {
-			log_err("Error parsing event\n");
-			return ret;
-		}
-		if (extend_pcr) {
-			ret = tcg2_pcr_extend(dev, pcr, &digest_list);
-			if (ret != EFI_SUCCESS) {
-				log_err("Error in extending PCR\n");
-				return ret;
-			}
-
-			/* Clear the digest for next event */
-			for (i = 0; i < digest_list.count; i++) {
-				u16 hash_alg = digest_list.digests[i].hash_alg;
-				u8 *digest =
-				   (u8 *)&digest_list.digests[i].digest;
-
-				memset(digest, 0, alg_to_len(hash_alg));
-			}
-		}
-	}
-
-	memcpy(log_buffer, buffer, sz);
-	*log_sz = sz;
-
-	return ret;
-}
-
-/**
- * create_specid_event() - Create the first event in the eventlog
- *
- * @dev:			tpm device
- * @event_header:		Pointer to the final event header
- * @event_size:			final spec event size
- *
- * Return:	status code
- */
-static efi_status_t create_specid_event(struct udevice *dev, void *buffer,
-					size_t *event_size)
-{
-	struct tcg_efi_spec_id_event *spec_event;
-	size_t spec_event_size;
-	efi_status_t ret = EFI_DEVICE_ERROR;
-	u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
-	int err;
-	size_t i;
-
-	/*
-	 * Create Spec event. This needs to be the first event in the log
-	 * according to the TCG EFI protocol spec
-	 */
-
-	/* Setup specID event data */
-	spec_event = (struct tcg_efi_spec_id_event *)buffer;
-	memcpy(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
-	       sizeof(spec_event->signature));
-	put_unaligned_le32(0, &spec_event->platform_class); /* type client */
-	spec_event->spec_version_minor =
-		TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
-	spec_event->spec_version_major =
-		TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
-	spec_event->spec_errata =
-		TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
-	spec_event->uintn_size = sizeof(efi_uintn_t) / sizeof(u32);
-
-	err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
-
-	if (err)
-		goto out;
-
-	for (i = 0; i < pcr_count; i++) {
-		u16 hash_alg = hash_algo_list[i].hash_alg;
-		u16 hash_len = hash_algo_list[i].hash_len;
-
-		if (active & alg_to_mask(hash_alg)) {
-			put_unaligned_le16(hash_alg,
-					   &spec_event->digest_sizes[alg_count].algorithm_id);
-			put_unaligned_le16(hash_len,
-					   &spec_event->digest_sizes[alg_count].digest_size);
-			alg_count++;
-		}
-	}
-
-	spec_event->number_of_algorithms = alg_count;
-	if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
-	    spec_event->number_of_algorithms < 1)
-		goto out;
-
-	/*
-	 * the size of the spec event and placement of vendor_info_size
-	 * depends on supported algoriths
-	 */
-	spec_event_size =
-		offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
-		spec_event->number_of_algorithms * sizeof(spec_event->digest_sizes[0]);
-	/* no vendor info for us */
-	memset(buffer + spec_event_size, 0, 1);
-	/* add a byte for vendor_info_size in the spec event */
-	spec_event_size += 1;
-	*event_size = spec_event_size;
-
-	return EFI_SUCCESS;
-
-out:
-	return ret;
-}
-
-/**
  * tcg2_uninit - remove the final event table and free efi memory on failures
  */
 void tcg2_uninit(void)
@@ -1720,7 +839,7 @@
 }
 
 /**
- * tcg2_measure_event() - common function to add event log and extend PCR
+ * measure_event() - common function to add event log and extend PCR
  *
  * @dev:		TPM device
  * @pcr_index:		PCR index
@@ -1730,14 +849,13 @@
  *
  * Return:	status code
  */
-static efi_status_t
-tcg2_measure_event(struct udevice *dev, u32 pcr_index, u32 event_type,
-		   u32 size, u8 event[])
+static efi_status_t measure_event(struct udevice *dev, u32 pcr_index,
+				  u32 event_type, u32 size, u8 event[])
 {
 	struct tpml_digest_values digest_list;
 	efi_status_t ret;
 
-	ret = tcg2_create_digest(event, size, &digest_list);
+	ret = tcg2_create_digest(dev, event, size, &digest_list);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
@@ -1764,9 +882,8 @@
 {
 	efi_status_t ret;
 
-	ret = tcg2_measure_event(dev, 0, EV_S_CRTM_VERSION,
-				 strlen(version_string) + 1,
-				 (u8 *)version_string);
+	ret = measure_event(dev, 0, EV_S_CRTM_VERSION,
+			    strlen(version_string) + 1, (u8 *)version_string);
 
 	return ret;
 }
@@ -1782,12 +899,11 @@
 	 * vendor_info_size is currently set to 0, we need to change the length
 	 * and allocate the flexible array member if this changes
 	 */
-	struct tcg_pcr_event *event_header = NULL;
+	struct tcg2_event_log elog;
 	struct udevice *dev;
-	size_t spec_event_size;
 	efi_status_t ret;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		return ret;
 
@@ -1806,7 +922,6 @@
 	 * The log header is defined to be in SHA1 event log entry format.
 	 * Setup event header
 	 */
-	event_header =  (struct tcg_pcr_event *)event_log.buffer;
 	event_log.pos = 0;
 	event_log.last_event_size = 0;
 	event_log.get_event_called = false;
@@ -1817,34 +932,20 @@
 	 * Check if earlier firmware have passed any eventlog. Different
 	 * platforms can use different ways to do so.
 	 */
-	ret = tcg2_get_fw_eventlog(dev, event_log.buffer, &event_log.pos);
+	elog.log = event_log.buffer;
+	elog.log_size = TPM2_EVENT_LOG_SIZE;
+	ret = tcg2_log_prepare_buffer(dev, &elog, false);
+	if (ret != EFI_SUCCESS)
+		goto free_pool;
+
+	event_log.pos = elog.log_position;
+
 	/*
-	 * If earlier firmware hasn't passed any eventlog, go ahead and
-	 * create the eventlog header.
+	 * Add SCRTM version to the log if previous firmmware
+	 * doesn't pass an eventlog.
 	 */
-	if (ret == EFI_NOT_FOUND) {
-		put_unaligned_le32(0, &event_header->pcr_index);
-		put_unaligned_le32(EV_NO_ACTION, &event_header->event_type);
-		memset(&event_header->digest, 0, sizeof(event_header->digest));
-		ret = create_specid_event(dev,
-					  (void *)((uintptr_t)event_log.buffer +
-						   sizeof(*event_header)),
-					  &spec_event_size);
-		if (ret != EFI_SUCCESS)
-			goto free_pool;
-		put_unaligned_le32(spec_event_size, &event_header->event_size);
-		event_log.pos = spec_event_size + sizeof(*event_header);
-		event_log.last_event_size = event_log.pos;
-
-		/*
-		 * Add SCRTM version to the log if previous firmmware
-		 * doesn't pass an eventlog.
-		 */
+	if (!elog.found)
 		ret = efi_append_scrtm_version(dev);
-	}
-
-	if (ret != EFI_SUCCESS)
-		goto free_pool;
 
 	ret = create_final_event();
 	if (ret != EFI_SUCCESS)
@@ -1897,8 +998,8 @@
 		memcpy((u16 *)event->unicode_name + event->unicode_name_length,
 		       data, data_size);
 	}
-	ret = tcg2_measure_event(dev, pcr_index, event_type, event_size,
-				 (u8 *)event);
+	ret = measure_event(dev, pcr_index, event_type, event_size,
+			    (u8 *)event);
 	free(event);
 	return ret;
 }
@@ -2009,8 +1110,8 @@
 
 	smbios_prepare_measurement(entry, smbios_copy);
 
-	ret = tcg2_measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
-				 (u8 *)event);
+	ret = measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
+			    (u8 *)event);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
@@ -2161,7 +1262,7 @@
 		gpt_e = (gpt_entry *)((u8 *)gpt_e + gpt_h->sizeof_partition_entry);
 	}
 
-	ret = tcg2_measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8 *)event);
+	ret = measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8 *)event);
 
 out2:
 	free(gpt_h);
@@ -2215,7 +1316,7 @@
 	if (!is_tcg2_protocol_installed())
 		return EFI_SUCCESS;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		return EFI_SECURITY_VIOLATION;
 
@@ -2240,7 +1341,7 @@
 	sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_mem_rsvmap(dtb), rsvmap_size);
 	sha256_finish(&hash_ctx, blob->data + blob->blob_description_size);
 
-	ret = tcg2_measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob);
+	ret = measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob);
 
 	free(blob);
 	return ret;
@@ -2265,7 +1366,7 @@
 	if (tcg2_efi_app_invoked)
 		return EFI_SUCCESS;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		return EFI_SECURITY_VIOLATION;
 
@@ -2273,9 +1374,9 @@
 	if (ret != EFI_SUCCESS)
 		goto out;
 
-	ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION,
-				 strlen(EFI_CALLING_EFI_APPLICATION),
-				 (u8 *)EFI_CALLING_EFI_APPLICATION);
+	ret = measure_event(dev, 4, EV_EFI_ACTION,
+			    strlen(EFI_CALLING_EFI_APPLICATION),
+			    (u8 *)EFI_CALLING_EFI_APPLICATION);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
@@ -2291,8 +1392,8 @@
 		goto out;
 
 	for (pcr_index = 0; pcr_index <= 7; pcr_index++) {
-		ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR,
-					 sizeof(event), (u8 *)&event);
+		ret = measure_event(dev, pcr_index, EV_SEPARATOR,
+				    sizeof(event), (u8 *)&event);
 		if (ret != EFI_SUCCESS)
 			goto out;
 	}
@@ -2315,13 +1416,13 @@
 	if (!is_tcg2_protocol_installed())
 		return EFI_SUCCESS;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		return ret;
 
-	ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION,
-				 strlen(EFI_RETURNING_FROM_EFI_APPLICATION),
-				 (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION);
+	ret = measure_event(dev, 4, EV_EFI_ACTION,
+			    strlen(EFI_RETURNING_FROM_EFI_APPLICATION),
+			    (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION);
 	return ret;
 }
 
@@ -2346,19 +1447,19 @@
 		goto out;
 	}
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
-	ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
-				 strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
-				 (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
+	ret = measure_event(dev, 5, EV_EFI_ACTION,
+			    strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
+			    (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
-	ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
-				 strlen(EFI_EXIT_BOOT_SERVICES_SUCCEEDED),
-				 (u8 *)EFI_EXIT_BOOT_SERVICES_SUCCEEDED);
+	ret = measure_event(dev, 5, EV_EFI_ACTION,
+			    strlen(EFI_EXIT_BOOT_SERVICES_SUCCEEDED),
+			    (u8 *)EFI_EXIT_BOOT_SERVICES_SUCCEEDED);
 
 out:
 	EFI_EXIT(ret);
@@ -2378,19 +1479,19 @@
 	if (!is_tcg2_protocol_installed())
 		return EFI_SUCCESS;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
-	ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
-				 strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
-				 (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
+	ret = measure_event(dev, 5, EV_EFI_ACTION,
+			    strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
+			    (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
-	ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
-				 strlen(EFI_EXIT_BOOT_SERVICES_FAILED),
-				 (u8 *)EFI_EXIT_BOOT_SERVICES_FAILED);
+	ret = measure_event(dev, 5, EV_EFI_ACTION,
+			    strlen(EFI_EXIT_BOOT_SERVICES_FAILED),
+			    (u8 *)EFI_EXIT_BOOT_SERVICES_FAILED);
 
 out:
 	return ret;
@@ -2460,7 +1561,7 @@
 	if (!is_tcg2_protocol_installed())
 		return EFI_SUCCESS;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		return EFI_SECURITY_VIOLATION;
 
@@ -2486,7 +1587,7 @@
 	struct efi_event *event;
 	u32 err;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS) {
 		log_warning("Missing TPMv2 device for EFI_TCG_PROTOCOL\n");
 		return EFI_SUCCESS;
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index 9ab5b46..bd0fb07 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -1,16 +1,705 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
+ * Copyright (c) 2023 Linaro Limited
  * Copyright (c) 2018 Bootlin
  * Author: Miquel Raynal <miquel.raynal@bootlin.com>
  */
 
 #include <common.h>
 #include <dm.h>
+#include <dm/of_access.h>
+#include <tpm_api.h>
 #include <tpm-common.h>
 #include <tpm-v2.h>
+#include <u-boot/sha1.h>
+#include <u-boot/sha256.h>
+#include <u-boot/sha512.h>
+#include <version_string.h>
+#include <asm/io.h>
 #include <linux/bitops.h>
+#include <linux/unaligned/be_byteshift.h>
+#include <linux/unaligned/generic.h>
+#include <linux/unaligned/le_byteshift.h>
+
 #include "tpm-utils.h"
 
+const enum tpm2_algorithms tpm2_supported_algorithms[4] = {
+	TPM2_ALG_SHA1,
+	TPM2_ALG_SHA256,
+	TPM2_ALG_SHA384,
+	TPM2_ALG_SHA512,
+};
+
+int tcg2_get_active_pcr_banks(struct udevice *dev, u32 *active_pcr_banks)
+{
+	u32 supported = 0;
+	u32 pcr_banks = 0;
+	u32 active = 0;
+	int rc;
+
+	rc = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
+	if (rc)
+		return rc;
+
+	*active_pcr_banks = active;
+
+	return 0;
+}
+
+u32 tcg2_event_get_size(struct tpml_digest_values *digest_list)
+{
+	u32 len;
+	size_t i;
+
+	len = offsetof(struct tcg_pcr_event2, digests);
+	len += offsetof(struct tpml_digest_values, digests);
+	for (i = 0; i < digest_list->count; ++i) {
+		u16 l = tpm2_algorithm_to_len(digest_list->digests[i].hash_alg);
+
+		if (!l)
+			continue;
+
+		len += l + offsetof(struct tpmt_ha, digest);
+	}
+	len += sizeof(u32);
+
+	return len;
+}
+
+int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length,
+		       struct tpml_digest_values *digest_list)
+{
+	u8 final[sizeof(union tpmu_ha)];
+	sha256_context ctx_256;
+	sha512_context ctx_512;
+	sha1_context ctx;
+	u32 active;
+	size_t i;
+	u32 len;
+	int rc;
+
+	rc = tcg2_get_active_pcr_banks(dev, &active);
+	if (rc)
+		return rc;
+
+	digest_list->count = 0;
+	for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
+		u32 mask =
+			tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
+
+		if (!(active & mask))
+			continue;
+
+		switch (tpm2_supported_algorithms[i]) {
+		case TPM2_ALG_SHA1:
+			sha1_starts(&ctx);
+			sha1_update(&ctx, input, length);
+			sha1_finish(&ctx, final);
+			len = TPM2_SHA1_DIGEST_SIZE;
+			break;
+		case TPM2_ALG_SHA256:
+			sha256_starts(&ctx_256);
+			sha256_update(&ctx_256, input, length);
+			sha256_finish(&ctx_256, final);
+			len = TPM2_SHA256_DIGEST_SIZE;
+			break;
+		case TPM2_ALG_SHA384:
+			sha384_starts(&ctx_512);
+			sha384_update(&ctx_512, input, length);
+			sha384_finish(&ctx_512, final);
+			len = TPM2_SHA384_DIGEST_SIZE;
+			break;
+		case TPM2_ALG_SHA512:
+			sha512_starts(&ctx_512);
+			sha512_update(&ctx_512, input, length);
+			sha512_finish(&ctx_512, final);
+			len = TPM2_SHA512_DIGEST_SIZE;
+			break;
+		default:
+			printf("%s: unsupported algorithm %x\n", __func__,
+			       tpm2_supported_algorithms[i]);
+			continue;
+		}
+
+		digest_list->digests[digest_list->count].hash_alg =
+			tpm2_supported_algorithms[i];
+		memcpy(&digest_list->digests[digest_list->count].digest, final,
+		       len);
+		digest_list->count++;
+	}
+
+	return 0;
+}
+
+void tcg2_log_append(u32 pcr_index, u32 event_type,
+		     struct tpml_digest_values *digest_list, u32 size,
+		     const u8 *event, u8 *log)
+{
+	size_t len;
+	size_t pos;
+	u32 i;
+
+	pos = offsetof(struct tcg_pcr_event2, pcr_index);
+	put_unaligned_le32(pcr_index, log);
+	pos = offsetof(struct tcg_pcr_event2, event_type);
+	put_unaligned_le32(event_type, log + pos);
+	pos = offsetof(struct tcg_pcr_event2, digests) +
+		offsetof(struct tpml_digest_values, count);
+	put_unaligned_le32(digest_list->count, log + pos);
+
+	pos = offsetof(struct tcg_pcr_event2, digests) +
+		offsetof(struct tpml_digest_values, digests);
+	for (i = 0; i < digest_list->count; ++i) {
+		u16 hash_alg = digest_list->digests[i].hash_alg;
+
+		len = tpm2_algorithm_to_len(hash_alg);
+		if (!len)
+			continue;
+
+		pos += offsetof(struct tpmt_ha, hash_alg);
+		put_unaligned_le16(hash_alg, log + pos);
+		pos += offsetof(struct tpmt_ha, digest);
+		memcpy(log + pos, (u8 *)&digest_list->digests[i].digest, len);
+		pos += len;
+	}
+
+	put_unaligned_le32(size, log + pos);
+	pos += sizeof(u32);
+	memcpy(log + pos, event, size);
+}
+
+static int tcg2_log_append_check(struct tcg2_event_log *elog, u32 pcr_index,
+				 u32 event_type,
+				 struct tpml_digest_values *digest_list,
+				 u32 size, const u8 *event)
+{
+	u32 event_size;
+	u8 *log;
+
+	event_size = size + tcg2_event_get_size(digest_list);
+	if (elog->log_position + event_size > elog->log_size) {
+		printf("%s: log too large: %u + %u > %u\n", __func__,
+		       elog->log_position, event_size, elog->log_size);
+		return -ENOBUFS;
+	}
+
+	log = elog->log + elog->log_position;
+	elog->log_position += event_size;
+
+	tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
+
+	return 0;
+}
+
+static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog)
+{
+	struct tcg_efi_spec_id_event *ev;
+	struct tcg_pcr_event *log;
+	u32 event_size;
+	u32 count = 0;
+	u32 log_size;
+	u32 active;
+	u32 mask;
+	size_t i;
+	u16 len;
+	int rc;
+
+	rc = tcg2_get_active_pcr_banks(dev, &active);
+	if (rc)
+		return rc;
+
+	event_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes);
+	for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
+		mask = tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
+
+		if (!(active & mask))
+			continue;
+
+		switch (tpm2_supported_algorithms[i]) {
+		case TPM2_ALG_SHA1:
+		case TPM2_ALG_SHA256:
+		case TPM2_ALG_SHA384:
+		case TPM2_ALG_SHA512:
+			count++;
+			break;
+		default:
+			continue;
+		}
+	}
+
+	event_size += 1 +
+		(sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count);
+	log_size = offsetof(struct tcg_pcr_event, event) + event_size;
+
+	if (log_size > elog->log_size) {
+		printf("%s: log too large: %u > %u\n", __func__, log_size,
+		       elog->log_size);
+		return -ENOBUFS;
+	}
+
+	log = (struct tcg_pcr_event *)elog->log;
+	put_unaligned_le32(0, &log->pcr_index);
+	put_unaligned_le32(EV_NO_ACTION, &log->event_type);
+	memset(&log->digest, 0, sizeof(log->digest));
+	put_unaligned_le32(event_size, &log->event_size);
+
+	ev = (struct tcg_efi_spec_id_event *)log->event;
+	strlcpy((char *)ev->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
+		sizeof(ev->signature));
+	put_unaligned_le32(0, &ev->platform_class);
+	ev->spec_version_minor = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
+	ev->spec_version_major = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
+	ev->spec_errata = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
+	ev->uintn_size = sizeof(size_t) / sizeof(u32);
+	put_unaligned_le32(count, &ev->number_of_algorithms);
+
+	count = 0;
+	for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
+		mask = tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
+
+		if (!(active & mask))
+			continue;
+
+		len = tpm2_algorithm_to_len(tpm2_supported_algorithms[i]);
+		if (!len)
+			continue;
+
+		put_unaligned_le16(tpm2_supported_algorithms[i],
+				   &ev->digest_sizes[count].algorithm_id);
+		put_unaligned_le16(len, &ev->digest_sizes[count].digest_size);
+		count++;
+	}
+
+	*((u8 *)ev + (event_size - 1)) = 0;
+	elog->log_position = log_size;
+
+	return 0;
+}
+
+static int tcg2_replay_eventlog(struct tcg2_event_log *elog,
+				struct udevice *dev,
+				struct tpml_digest_values *digest_list,
+				u32 log_position)
+{
+	const u32 offset = offsetof(struct tcg_pcr_event2, digests) +
+		offsetof(struct tpml_digest_values, digests);
+	u32 event_size;
+	u32 count;
+	u16 algo;
+	u32 pcr;
+	u32 pos;
+	u16 len;
+	u8 *log;
+	int rc;
+	u32 i;
+
+	while (log_position + offset < elog->log_size) {
+		log = elog->log + log_position;
+
+		pos = offsetof(struct tcg_pcr_event2, pcr_index);
+		pcr = get_unaligned_le32(log + pos);
+		pos = offsetof(struct tcg_pcr_event2, event_type);
+		if (!get_unaligned_le32(log + pos))
+			return 0;
+
+		pos = offsetof(struct tcg_pcr_event2, digests) +
+			offsetof(struct tpml_digest_values, count);
+		count = get_unaligned_le32(log + pos);
+		if (count > ARRAY_SIZE(tpm2_supported_algorithms) ||
+		    (digest_list->count && digest_list->count != count))
+			return 0;
+
+		pos = offsetof(struct tcg_pcr_event2, digests) +
+			offsetof(struct tpml_digest_values, digests);
+		for (i = 0; i < count; ++i) {
+			pos += offsetof(struct tpmt_ha, hash_alg);
+			if (log_position + pos + sizeof(u16) >= elog->log_size)
+				return 0;
+
+			algo = get_unaligned_le16(log + pos);
+			pos += offsetof(struct tpmt_ha, digest);
+			switch (algo) {
+			case TPM2_ALG_SHA1:
+			case TPM2_ALG_SHA256:
+			case TPM2_ALG_SHA384:
+			case TPM2_ALG_SHA512:
+				len = tpm2_algorithm_to_len(algo);
+				break;
+			default:
+				return 0;
+			}
+
+			if (digest_list->count) {
+				if (algo != digest_list->digests[i].hash_alg ||
+				    log_position + pos + len >= elog->log_size)
+					return 0;
+
+				memcpy(digest_list->digests[i].digest.sha512,
+				       log + pos, len);
+			}
+
+			pos += len;
+		}
+
+		if (log_position + pos + sizeof(u32) >= elog->log_size)
+			return 0;
+
+		event_size = get_unaligned_le32(log + pos);
+		pos += event_size + sizeof(u32);
+		if (log_position + pos > elog->log_size)
+			return 0;
+
+		if (digest_list->count) {
+			rc = tcg2_pcr_extend(dev, pcr, digest_list);
+			if (rc)
+				return rc;
+		}
+
+		log_position += pos;
+	}
+
+	elog->log_position = log_position;
+	elog->found = true;
+	return 0;
+}
+
+static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
+{
+	struct tpml_digest_values digest_list;
+	struct tcg_efi_spec_id_event *event;
+	struct tcg_pcr_event *log;
+	u32 log_active;
+	u32 calc_size;
+	u32 active;
+	u32 count;
+	u32 evsz;
+	u32 mask;
+	u16 algo;
+	u16 len;
+	int rc;
+	u32 i;
+	u16 j;
+
+	if (elog->log_size <= offsetof(struct tcg_pcr_event, event))
+		return 0;
+
+	log = (struct tcg_pcr_event *)elog->log;
+	if (get_unaligned_le32(&log->pcr_index) != 0 ||
+	    get_unaligned_le32(&log->event_type) != EV_NO_ACTION)
+		return 0;
+
+	for (i = 0; i < sizeof(log->digest); i++) {
+		if (log->digest[i])
+			return 0;
+	}
+
+	evsz = get_unaligned_le32(&log->event_size);
+	if (evsz < offsetof(struct tcg_efi_spec_id_event, digest_sizes) ||
+	    evsz + offsetof(struct tcg_pcr_event, event) > elog->log_size)
+		return 0;
+
+	event = (struct tcg_efi_spec_id_event *)log->event;
+	if (memcmp(event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
+		   sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03)))
+		return 0;
+
+	if (event->spec_version_minor != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
+	    event->spec_version_major != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
+		return 0;
+
+	count = get_unaligned_le32(&event->number_of_algorithms);
+	if (count > ARRAY_SIZE(tpm2_supported_algorithms))
+		return 0;
+
+	calc_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
+		(sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count) +
+		1;
+	if (evsz != calc_size)
+		return 0;
+
+	rc = tcg2_get_active_pcr_banks(dev, &active);
+	if (rc)
+		return rc;
+
+	digest_list.count = 0;
+	log_active = 0;
+
+	for (i = 0; i < count; ++i) {
+		algo = get_unaligned_le16(&event->digest_sizes[i].algorithm_id);
+		mask = tpm2_algorithm_to_mask(algo);
+
+		if (!(active & mask))
+			return 0;
+
+		switch (algo) {
+		case TPM2_ALG_SHA1:
+		case TPM2_ALG_SHA256:
+		case TPM2_ALG_SHA384:
+		case TPM2_ALG_SHA512:
+			len = get_unaligned_le16(&event->digest_sizes[i].digest_size);
+			if (tpm2_algorithm_to_len(algo) != len)
+				return 0;
+			digest_list.digests[digest_list.count++].hash_alg = algo;
+			break;
+		default:
+			return 0;
+		}
+
+		log_active |= mask;
+	}
+
+	/* Ensure the previous firmware extended all the PCRs. */
+	if (log_active != active)
+		return 0;
+
+	/* Read PCR0 to check if previous firmware extended the PCRs or not. */
+	rc = tcg2_pcr_read(dev, 0, &digest_list);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < digest_list.count; ++i) {
+		len = tpm2_algorithm_to_len(digest_list.digests[i].hash_alg);
+		for (j = 0; j < len; ++j) {
+			if (digest_list.digests[i].digest.sha512[j])
+				break;
+		}
+
+		/* PCR is non-zero; it has been extended, so skip extending. */
+		if (j != len) {
+			digest_list.count = 0;
+			break;
+		}
+	}
+
+	return tcg2_replay_eventlog(elog, dev, &digest_list,
+				    offsetof(struct tcg_pcr_event, event) +
+				    evsz);
+}
+
+int tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
+		    struct tpml_digest_values *digest_list)
+{
+	u32 rc;
+	u32 i;
+
+	for (i = 0; i < digest_list->count; i++) {
+		u32 alg = digest_list->digests[i].hash_alg;
+
+		rc = tpm2_pcr_extend(dev, pcr_index, alg,
+				     (u8 *)&digest_list->digests[i].digest,
+				     tpm2_algorithm_to_len(alg));
+		if (rc) {
+			printf("%s: error pcr:%u alg:%08x\n", __func__,
+			       pcr_index, alg);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+int tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
+		  struct tpml_digest_values *digest_list)
+{
+	struct tpm_chip_priv *priv;
+	u32 rc;
+	u32 i;
+
+	priv = dev_get_uclass_priv(dev);
+	if (!priv)
+		return -ENODEV;
+
+	for (i = 0; i < digest_list->count; i++) {
+		u32 alg = digest_list->digests[i].hash_alg;
+		u8 *digest = (u8 *)&digest_list->digests[i].digest;
+
+		rc = tpm2_pcr_read(dev, pcr_index, priv->pcr_select_min, alg,
+				   digest, tpm2_algorithm_to_len(alg), NULL);
+		if (rc) {
+			printf("%s: error pcr:%u alg:%08x\n", __func__,
+			       pcr_index, alg);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+int tcg2_measure_data(struct udevice *dev, struct tcg2_event_log *elog,
+		      u32 pcr_index, u32 size, const u8 *data, u32 event_type,
+		      u32 event_size, const u8 *event)
+{
+	struct tpml_digest_values digest_list;
+	int rc;
+
+	if (data)
+		rc = tcg2_create_digest(dev, data, size, &digest_list);
+	else
+		rc = tcg2_create_digest(dev, event, event_size, &digest_list);
+	if (rc)
+		return rc;
+
+	rc = tcg2_pcr_extend(dev, pcr_index, &digest_list);
+	if (rc)
+		return rc;
+
+	return tcg2_log_append_check(elog, pcr_index, event_type, &digest_list,
+				     event_size, event);
+}
+
+int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
+			    bool ignore_existing_log)
+{
+	struct tcg2_event_log log;
+	int rc;
+
+	elog->log_position = 0;
+	elog->found = false;
+
+	rc = tcg2_platform_get_log(dev, (void **)&log.log, &log.log_size);
+	if (!rc) {
+		log.log_position = 0;
+		log.found = false;
+
+		if (!ignore_existing_log) {
+			rc = tcg2_log_parse(dev, &log);
+			if (rc)
+				return rc;
+		}
+
+		if (elog->log_size) {
+			if (log.found) {
+				if (elog->log_size < log.log_position)
+					return -ENOSPC;
+
+				/*
+				 * Copy the discovered log into the user buffer
+				 * if there's enough space.
+				 */
+				memcpy(elog->log, log.log, log.log_position);
+			}
+
+			unmap_physmem(log.log, MAP_NOCACHE);
+		} else {
+			elog->log = log.log;
+			elog->log_size = log.log_size;
+		}
+
+		elog->log_position = log.log_position;
+		elog->found = log.found;
+	}
+
+	/*
+	 * Initialize the log buffer if no log was discovered and the buffer is
+	 * valid. User's can pass in their own buffer as a fallback if no
+	 * memory region is found.
+	 */
+	if (!elog->found && elog->log_size)
+		rc = tcg2_log_init(dev, elog);
+
+	return rc;
+}
+
+int tcg2_measurement_init(struct udevice **dev, struct tcg2_event_log *elog,
+			  bool ignore_existing_log)
+{
+	int rc;
+
+	rc = tcg2_platform_get_tpm2(dev);
+	if (rc)
+		return rc;
+
+	rc = tpm_auto_start(*dev);
+	if (rc)
+		return rc;
+
+	rc = tcg2_log_prepare_buffer(*dev, elog, ignore_existing_log);
+	if (rc) {
+		tcg2_measurement_term(*dev, elog, true);
+		return rc;
+	}
+
+	rc = tcg2_measure_event(*dev, elog, 0, EV_S_CRTM_VERSION,
+				strlen(version_string) + 1,
+				(u8 *)version_string);
+	if (rc) {
+		tcg2_measurement_term(*dev, elog, true);
+		return rc;
+	}
+
+	return 0;
+}
+
+void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
+			   bool error)
+{
+	u32 event = error ? 0x1 : 0xffffffff;
+	int i;
+
+	for (i = 0; i < 8; ++i)
+		tcg2_measure_event(dev, elog, i, EV_SEPARATOR, sizeof(event),
+				   (const u8 *)&event);
+
+	if (elog->log)
+		unmap_physmem(elog->log, MAP_NOCACHE);
+}
+
+__weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size)
+{
+	const __be32 *addr_prop;
+	const __be32 *size_prop;
+	int asize;
+	int ssize;
+
+	*addr = NULL;
+	*size = 0;
+
+	addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize);
+	if (!addr_prop)
+		addr_prop = dev_read_prop(dev, "linux,sml-base", &asize);
+
+	size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize);
+	if (!size_prop)
+		size_prop = dev_read_prop(dev, "linux,sml-size", &ssize);
+
+	if (addr_prop && size_prop) {
+		u64 a = of_read_number(addr_prop, asize / sizeof(__be32));
+		u64 s = of_read_number(size_prop, ssize / sizeof(__be32));
+
+		*addr = map_physmem(a, s, MAP_NOCACHE);
+		*size = (u32)s;
+	} else {
+		struct ofnode_phandle_args args;
+		phys_addr_t a;
+		fdt_size_t s;
+
+		if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
+					       0, &args))
+			return -ENODEV;
+
+		a = ofnode_get_addr_size(args.node, "reg", &s);
+		if (a == FDT_ADDR_T_NONE)
+			return -ENOMEM;
+
+		*addr = map_physmem(a, s, MAP_NOCACHE);
+		*size = (u32)s;
+	}
+
+	return 0;
+}
+
+__weak int tcg2_platform_get_tpm2(struct udevice **dev)
+{
+	for_each_tpm_device(*dev) {
+		if (tpm_get_version(*dev) == TPM_V2)
+			return 0;
+	}
+
+	return -ENODEV;
+}
+
+__weak void tcg2_platform_startup_error(struct udevice *dev, int rc) {}
+
 u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
 {
 	const u8 command_v2[12] = {
@@ -359,6 +1048,131 @@
 	return 0;
 }
 
+static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
+{
+	u8 response[(sizeof(struct tpms_capability_data) -
+		offsetof(struct tpms_capability_data, data))];
+	u32 properties_offset =
+		offsetof(struct tpml_tagged_tpm_property, tpm_property) +
+		offsetof(struct tpms_tagged_property, value);
+	u32 ret;
+
+	memset(response, 0, sizeof(response));
+	ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
+				  TPM2_PT_PCR_COUNT, response, 1);
+	if (ret)
+		return ret;
+
+	*num_pcr = get_unaligned_be32(response + properties_offset);
+	if (*num_pcr > TPM2_MAX_PCRS) {
+		printf("%s: too many pcrs: %u\n", __func__, *num_pcr);
+		return -E2BIG;
+	}
+
+	return 0;
+}
+
+static bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection)
+{
+	int i;
+
+	/*
+	 * check the pcr_select. If at least one of the PCRs supports the
+	 * algorithm add it on the active ones
+	 */
+	for (i = 0; i < selection->size_of_select; i++) {
+		if (selection->pcr_select[i])
+			return true;
+	}
+
+	return false;
+}
+
+int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
+		      u32 *pcr_banks)
+{
+	u8 response[(sizeof(struct tpms_capability_data) -
+		offsetof(struct tpms_capability_data, data))];
+	struct tpml_pcr_selection pcrs;
+	u32 num_pcr;
+	size_t i;
+	u32 ret;
+
+	*supported_pcr = 0;
+	*active_pcr = 0;
+	*pcr_banks = 0;
+	memset(response, 0, sizeof(response));
+	ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
+	if (ret)
+		return ret;
+
+	pcrs.count = get_unaligned_be32(response);
+	/*
+	 * We only support 5 algorithms for now so check against that
+	 * instead of TPM2_NUM_PCR_BANKS
+	 */
+	if (pcrs.count > ARRAY_SIZE(tpm2_supported_algorithms) ||
+	    pcrs.count < 1) {
+		printf("%s: too many pcrs: %u\n", __func__, pcrs.count);
+		return -EMSGSIZE;
+	}
+
+	ret = tpm2_get_num_pcr(dev, &num_pcr);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < pcrs.count; i++) {
+		/*
+		 * Definition of TPMS_PCR_SELECTION Structure
+		 * hash: u16
+		 * size_of_select: u8
+		 * pcr_select: u8 array
+		 *
+		 * The offsets depend on the number of the device PCRs
+		 * so we have to calculate them based on that
+		 */
+		u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
+			i * offsetof(struct tpms_pcr_selection, pcr_select) +
+			i * ((num_pcr + 7) / 8);
+		u32 size_select_offset =
+			hash_offset + offsetof(struct tpms_pcr_selection,
+					       size_of_select);
+		u32 pcr_select_offset =
+			hash_offset + offsetof(struct tpms_pcr_selection,
+					       pcr_select);
+
+		pcrs.selection[i].hash =
+			get_unaligned_be16(response + hash_offset);
+		pcrs.selection[i].size_of_select =
+			__get_unaligned_be(response + size_select_offset);
+		if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX) {
+			printf("%s: pcrs selection too large: %u\n", __func__,
+			       pcrs.selection[i].size_of_select);
+			return -ENOBUFS;
+		}
+		/* copy the array of pcr_select */
+		memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset,
+		       pcrs.selection[i].size_of_select);
+	}
+
+	for (i = 0; i < pcrs.count; i++) {
+		u32 hash_mask = tpm2_algorithm_to_mask(pcrs.selection[i].hash);
+
+		if (hash_mask) {
+			*supported_pcr |= hash_mask;
+			if (tpm2_is_active_pcr(&pcrs.selection[i]))
+				*active_pcr |= hash_mask;
+		} else {
+			printf("%s: unknown algorithm %x\n", __func__,
+			       pcrs.selection[i].hash);
+		}
+	}
+
+	*pcr_banks = pcrs.count;
+
+	return 0;
+}
+
 u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
 {
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 5294758..068522c 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
 obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
 
 obj-$(CONFIG_EXPO) += expo.o
 obj-$(CONFIG_CEDIT) += cedit.o
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 0000000..9db2ed3
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James <eajames@linux.ibm.com>
+ */
+
+#include <common.h>
+#include <bootm.h>
+#include <malloc.h>
+#include <test/suites.h>
+#include <test/test.h>
+#include <test/ut.h>
+#include <asm/io.h>
+
+#define MEASUREMENT_TEST(_name, _flags)	\
+	UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+	struct bootm_headers images;
+	const size_t size = 1024;
+	u8 *kernel;
+	u8 *initrd;
+	size_t i;
+
+	kernel = malloc(size);
+	initrd = malloc(size);
+
+	images.os.image_start = map_to_sysmem(kernel);
+	images.os.image_len = size;
+
+	images.rd_start = map_to_sysmem(initrd);
+	images.rd_end = images.rd_start + size;
+
+	images.ft_addr = malloc(size);
+	images.ft_len = size;
+
+	env_set("bootargs", "measurement testing");
+
+	for (i = 0; i < size; ++i) {
+		kernel[i] = 0xf0 | (i & 0xf);
+		initrd[i] = (i & 0xf0) | 0xf;
+		images.ft_addr[i] = i & 0xff;
+	}
+
+	ut_assertok(bootm_measure(&images));
+
+	free(images.ft_addr);
+	free(initrd);
+	free(kernel);
+
+	return 0;
+}
+MEASUREMENT_TEST(measure, 0);
+
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc,
+		      char *const argv[])
+{
+	struct unit_test *tests = UNIT_TEST_SUITE_START(measurement_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(measurement_test);
+
+	return cmd_ut_category("measurement", "measurement_test_", tests,
+			       n_ents, argc, argv);
+}
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 0343d47..2d5b80f 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -103,6 +103,10 @@
 #if CONFIG_IS_ENABLED(UT_UNICODE) && !defined(API_BUILD)
 	U_BOOT_CMD_MKENT(unicode, CONFIG_SYS_MAXARGS, 1, do_ut_unicode, "", ""),
 #endif
+#ifdef CONFIG_MEASURED_BOOT
+	U_BOOT_CMD_MKENT(measurement, CONFIG_SYS_MAXARGS, 1, do_ut_measurement,
+			 "", ""),
+#endif
 #ifdef CONFIG_SANDBOX
 	U_BOOT_CMD_MKENT(compression, CONFIG_SYS_MAXARGS, 1, do_ut_compression,
 			 "", ""),
diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py
index c2579fa..1d654cd 100644
--- a/test/py/tests/test_tpm2.py
+++ b/test/py/tests/test_tpm2.py
@@ -61,7 +61,7 @@
     skip_test = u_boot_console.config.env.get('env__tpm_device_test_skip', False)
     if skip_test:
         pytest.skip('skip TPM device test')
-    u_boot_console.run_command('tpm2 init')
+    u_boot_console.run_command('tpm2 autostart')
     output = u_boot_console.run_command('echo $?')
     assert output.endswith('0')
 
@@ -100,7 +100,7 @@
     """
     if is_sandbox(u_boot_console):
         u_boot_console.restart_uboot()
-        u_boot_console.run_command('tpm2 init')
+        u_boot_console.run_command('tpm2 autostart')
         output = u_boot_console.run_command('echo $?')
         assert output.endswith('0')
 
@@ -239,7 +239,7 @@
 def test_tpm2_pcr_read(u_boot_console):
     """Execute a TPM2_PCR_Read command.
 
-    Perform a PCR read of the 0th PCR. Must be zero.
+    Perform a PCR read of the 10th PCR. Must be zero.
     """
     if is_sandbox(u_boot_console):
         tpm2_sandbox_init(u_boot_console)
@@ -247,7 +247,7 @@
     force_init(u_boot_console)
     ram = u_boot_utils.find_ram_base(u_boot_console)
 
-    read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % ram)
+    read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % ram)
     output = u_boot_console.run_command('echo $?')
     assert output.endswith('0')
 
@@ -257,7 +257,7 @@
     updates = int(re.findall(r'\d+', str)[0])
 
     # Check the output value
-    assert 'PCR #0 content' in read_pcr
+    assert 'PCR #10 content' in read_pcr
     assert '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' in read_pcr
 
 @pytest.mark.buildconfigspec('cmd_tpm_v2')
@@ -275,19 +275,19 @@
     force_init(u_boot_console)
     ram = u_boot_utils.find_ram_base(u_boot_console)
 
-    read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20))
+    read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20))
     output = u_boot_console.run_command('echo $?')
     assert output.endswith('0')
     str = re.findall(r'\d+ known updates', read_pcr)[0]
     updates = int(re.findall(r'\d+', str)[0])
 
-    u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+    u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
     output = u_boot_console.run_command('echo $?')
     assert output.endswith('0')
 
     # Read the value back into a different place so we can still use 'ram' as
     # our zero bytes
-    read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20))
+    read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20))
     output = u_boot_console.run_command('echo $?')
     assert output.endswith('0')
     assert 'f5 a5 fd 42 d1 6a 20 30 27 98 ef 6e d3 09 97 9b' in read_pcr
@@ -297,11 +297,11 @@
     new_updates = int(re.findall(r'\d+', str)[0])
     assert (updates + 1) == new_updates
 
-    u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+    u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
     output = u_boot_console.run_command('echo $?')
     assert output.endswith('0')
 
-    read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20))
+    read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20))
     output = u_boot_console.run_command('echo $?')
     assert output.endswith('0')
     assert '7a 05 01 f5 95 7b df 9c b3 a8 ff 49 66 f0 22 65' in read_pcr