Merge tag 'u-boot-amlogic-20240701' of https://source.denx.de/u-boot/custodians/u-boot-amlogic into next

- Switch meson dwc3/usb PHY to set_mode callback for switching USB mode
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 27f6958..c43bb51 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -8,6 +8,17 @@
   # since our $(ci_runner_image) user is not root.
   container_option: -u 0
   work_dir: /u
+  # We define all of these as variables so we can easily reference them twice
+  am33xx_kirkwood_ls1_mvebu_omap: "am33xx kirkwood ls1 mvebu omap -x siemens,freescale"
+  amlogic_bcm_boundary_engicam_siemens_technexion_oradex: "amlogic bcm boundary engicam siemens technexion toradex -x mips"
+  arm_nxp_minus_imx_and_at91: "at91 freescale -x powerpc,m68k,imx,mx"
+  imx: "mx imx -x boundary,engicam,technexion,toradex"
+  rk: "rk"
+  sunxi: "sunxi"
+  powerpc: "powerpc"
+  arm_catch_all: "arm -x aarch64,am33xx,at91,bcm,ls1,kirkwood,mvebu,omap,rk,siemens,mx,sunxi,technexion,toradex"
+  aarch64_catch_all: "aarch64 -x amlogic,bcm,engicam,imx,ls1,ls2,lx216,mvebu,rk,siemens,sunxi,toradex"
+  everything_but_arm_and_powerpc: "arc m68k microblaze mips nios2 riscv sandbox sh x86 xtensa -x arm,powerpc"
 
 stages:
 - stage: testsuites
@@ -185,6 +196,34 @@
     steps:
       - script: make pip
 
+  - job: count_built_machines
+    displayName: 'Ensure we build all possible machines'
+    pool:
+      vmImage: $(ubuntu_vm)
+    container:
+      image: $(ci_runner_image)
+      options: $(container_option)
+    steps:
+      - script: |
+          BMANARGS="-o /tmp --dry-run -v"
+          # First get the total number of boards
+          total=$(tools/buildman/buildman ${BMANARGS} | grep "Total boards to build for each commit" | cut -d ' ' -f 8)
+          # Now build up the list of what each job built.
+          built="$(tools/buildman/buildman ${BMANARGS} $(am33xx_kirkwood_ls1_mvebu_omap) | grep '^   ')"
+          built="$built $(tools/buildman/buildman ${BMANARGS} $(amlogic_bcm_boundary_engicam_siemens_technexion_oradex) | grep '^   ')"
+          built="$built $(tools/buildman/buildman ${BMANARGS} $(arm_nxp_minus_imx_and_at91) | grep '^   ')"
+          built="$built $(tools/buildman/buildman ${BMANARGS} $(imx) | grep '^   ')"
+          built="$built $(tools/buildman/buildman ${BMANARGS} $(rk) | grep '^   ')"
+          built="$built $(tools/buildman/buildman ${BMANARGS} $(sunxi) | grep '^   ')"
+          built="$built $(tools/buildman/buildman ${BMANARGS} $(powerpc) | grep '^   ')"
+          built="$built $(tools/buildman/buildman ${BMANARGS} $(arm_catch_all) | grep '^   ')"
+          built="$built $(tools/buildman/buildman ${BMANARGS} $(aarch64_catch_all) | grep '^   ')"
+          built="$built $(tools/buildman/buildman ${BMANARGS} $(everything_but_arm_and_powerpc) | grep '^   ')"
+          # Finally see how many machines that is.
+          actual=$(tools/buildman/buildman ${BMANARGS} $built | grep "Total boards to build for each commit" | cut -d ' ' -f 8)
+          echo We would build a total of $actual out of $total platforms this CI run
+          [ $actual -eq $total ] && exit 0 || exit 1
+
   - job: create_test_py_wrapper_script
     displayName: 'Create and stage a wrapper for test.py runs'
     pool:
@@ -473,29 +512,29 @@
     pool:
       vmImage: $(ubuntu_vm)
     strategy:
-      # Use almost the same target division in .travis.yml, only merged
-      # 3 small build jobs (arc/microblaze/xtensa) into one.
+      # We split the world up in to 10 jobs as we can have at most 10
+      # parallel jobs going on the free tier of Azure.
       matrix:
-        am33xx_at91_kirkwood_mvebu_omap:
-          BUILDMAN: "am33xx at91_kirkwood mvebu omap -x siemens"
+        am33xx_kirkwood_ls1_mvebu_omap:
+          BUILDMAN: $(am33xx_kirkwood_ls1_mvebu_omap)
         amlogic_bcm_boundary_engicam_siemens_technexion_oradex:
-          BUILDMAN: "amlogic bcm boundary engicam siemens technexion toradex -x mips"
-        arm_nxp_minus_imx:
-          BUILDMAN: "freescale -x powerpc,m68k,imx,mx"
+          BUILDMAN: $(amlogic_bcm_boundary_engicam_siemens_technexion_oradex)
+        arm_nxp_minus_imx_and_at91:
+          BUILDMAN: $(arm_nxp_minus_imx_and_at91)
         imx:
-          BUILDMAN: "mx imx -x boundary,engicam,technexion,toradex"
+          BUILDMAN: $(imx)
         rk:
-          BUILDMAN: "rk"
+          BUILDMAN: $(rk)
         sunxi:
-          BUILDMAN: "sunxi"
+          BUILDMAN: $(sunxi)
         powerpc:
-          BUILDMAN: "powerpc"
+          BUILDMAN: $(powerpc)
         arm_catch_all:
-          BUILDMAN: "arm -x aarch64,am33xx,at91,bcm,ls1,kirkwood,mvebu,omap,rk,siemens,mx,sunxi,technexion,toradex"
+          BUILDMAN: $(arm_catch_all)
         aarch64_catch_all:
-          BUILDMAN: "aarch64 -x amlogic,bcm,engicam,imx,ls1,ls2,lx216,mvebu,rk,siemens,sunxi,toradex"
+          BUILDMAN: $(aarch64_catch_all)
         everything_but_arm_and_powerpc:
-          BUILDMAN: "-x arm,powerpc"
+          BUILDMAN: $(everything_but_arm_and_powerpc)
     steps:
       - script: |
           cat << EOF > build.sh
diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index d4c64f2..c3f8dac 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -396,6 +396,251 @@
 	return count;
 }
 
+#define ALL_ATTRS (3 << 8 | PMD_ATTRINDX_MASK)
+#define PTE_IS_TABLE(pte, level) (pte_type(&(pte)) == PTE_TYPE_TABLE && (level) < 3)
+
+enum walker_state {
+	WALKER_STATE_START = 0,
+	WALKER_STATE_TABLE,
+	WALKER_STATE_REGION, /* block or page, depending on level */
+};
+
+
+/**
+ * __pagetable_walk() - Walk through the pagetable and call cb() for each memory region
+ *
+ * This is a software implementation of the ARMv8-A MMU translation table walk. As per
+ * section D5.4 of the ARMv8-A Architecture Reference Manual. It recursively walks the
+ * 4 or 3 levels of the page table and calls the callback function for each discrete
+ * region of memory (that being the discovery of a new table, a collection of blocks
+ * with the same attributes, or of pages with the same attributes).
+ *
+ * U-Boot picks the smallest number of virtual address (VA) bits that it can based on the
+ * memory map configured by the board. If this is less than 39 then the MMU will only use
+ * 3 levels of translation instead of 3 - skipping level 0.
+ *
+ * Each level has 512 entries of 64-bits each. Each entry includes attribute bits and
+ * an address. When the attribute bits indicate a table, the address is the physical
+ * address of the table, so we can recursively call _pagetable_walk() on it (after calling
+ * @cb). If instead they indicate a block or page, we record the start address and attributes
+ * and continue walking until we find a region with different attributes, or the end of the
+ * table, in either case we call @cb with the start and end address of the region.
+ *
+ * This approach can be used to fully emulate the MMU's translation table walk, as per
+ * Figure D5-25 of the ARMv8-A Architecture Reference Manual.
+ *
+ * @addr:		The address of the table to walk
+ * @tcr:		The TCR register value
+ * @level:		The current level of the table
+ * @cb:			The callback function to call for each region
+ * @priv:		Private data to pass to the callback function
+ */
+static void __pagetable_walk(u64 addr, u64 tcr, int level, pte_walker_cb_t cb, void *priv)
+{
+	u64 *table = (u64 *)addr;
+	u64 attrs, last_attrs = 0, last_addr = 0, entry_start = 0;
+	int i;
+	u64 va_bits = 64 - (tcr & (BIT(6) - 1));
+	static enum walker_state state[4] = { 0 };
+	static bool exit;
+
+	if (!level) {
+		exit = false;
+		if (va_bits < 39)
+			level = 1;
+	}
+
+	state[level] = WALKER_STATE_START;
+
+	/* Walk through the table entries */
+	for (i = 0; i < MAX_PTE_ENTRIES; i++) {
+		u64 pte = table[i];
+		u64 _addr = pte & GENMASK_ULL(va_bits, PAGE_SHIFT);
+
+		if (exit)
+			return;
+
+		if (pte_type(&pte) == PTE_TYPE_FAULT)
+			continue;
+
+		attrs = pte & ALL_ATTRS;
+		/* If we're currently inside a block or set of pages */
+		if (state[level] > WALKER_STATE_START && state[level] != WALKER_STATE_TABLE) {
+			/*
+			 * Continue walking if this entry has the same attributes as the last and
+			 * is one page/block away -- it's a contiguous region.
+			 */
+			if (attrs == last_attrs && _addr == last_addr + (1 << level2shift(level))) {
+				last_attrs = attrs;
+				last_addr = _addr;
+				continue;
+			} else {
+				/* We either hit a table or a new region */
+				exit = cb(entry_start, last_addr + (1 << level2shift(level)),
+					  va_bits, level, priv);
+				if (exit)
+					return;
+				state[level] = WALKER_STATE_START;
+			}
+		}
+		last_attrs = attrs;
+		last_addr = _addr;
+
+		if (PTE_IS_TABLE(pte, level)) {
+			/* After the end of the table might be corrupted data */
+			if (!_addr || (pte & 0xfff) > 0x3ff)
+				return;
+			state[level] = WALKER_STATE_TABLE;
+			/* Signify the start of a table */
+			exit = cb(pte, 0, va_bits, level, priv);
+			if (exit)
+				return;
+
+			/* Go down a level */
+			__pagetable_walk(_addr, tcr, level + 1, cb, priv);
+			state[level] = WALKER_STATE_START;
+		} else if (pte_type(&pte) == PTE_TYPE_BLOCK || pte_type(&pte) == PTE_TYPE_PAGE) {
+			/* We foud a block or page, start walking */
+			entry_start = pte;
+			state[level] = WALKER_STATE_REGION;
+		}
+	}
+
+	if (state[level] > WALKER_STATE_START)
+		exit = cb(entry_start, last_addr + (1 << level2shift(level)), va_bits, level, priv);
+}
+
+static void pretty_print_pte_type(u64 pte)
+{
+	switch (pte_type(&pte)) {
+	case PTE_TYPE_FAULT:
+		printf(" %-5s", "Fault");
+		break;
+	case PTE_TYPE_BLOCK:
+		printf(" %-5s", "Block");
+		break;
+	case PTE_TYPE_PAGE:
+		printf(" %-5s", "Pages");
+		break;
+	default:
+		printf(" %-5s", "Unk");
+	}
+}
+
+static void pretty_print_table_attrs(u64 pte)
+{
+	int ap = (pte & PTE_TABLE_AP) >> 61;
+
+	printf(" | %2s %10s",
+	       (ap & 2) ? "RO" : "",
+	       (ap & 1) ? "!EL0" : "");
+	printf(" | %3s %2s %2s",
+	       (pte & PTE_TABLE_PXN) ? "PXN" : "",
+	       (pte & PTE_TABLE_XN) ? "XN" : "",
+	       (pte & PTE_TABLE_NS) ? "NS" : "");
+}
+
+static void pretty_print_block_attrs(u64 pte)
+{
+	u64 attrs = pte & PMD_ATTRINDX_MASK;
+
+	switch (attrs) {
+	case PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE):
+		printf(" | %-13s", "Device-nGnRnE");
+		break;
+	case PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE):
+		printf(" | %-13s", "Device-nGnRE");
+		break;
+	case PTE_BLOCK_MEMTYPE(MT_DEVICE_GRE):
+		printf(" | %-13s", "Device-GRE");
+		break;
+	case PTE_BLOCK_MEMTYPE(MT_NORMAL_NC):
+		printf(" | %-13s", "Normal-NC");
+		break;
+	case PTE_BLOCK_MEMTYPE(MT_NORMAL):
+		printf(" | %-13s", "Normal");
+		break;
+	default:
+		printf(" | %-13s", "Unknown");
+	}
+}
+
+static void pretty_print_block_memtype(u64 pte)
+{
+	u64 share = pte & (3 << 8);
+
+	switch (share) {
+	case PTE_BLOCK_NON_SHARE:
+		printf(" | %-16s", "Non-shareable");
+		break;
+	case PTE_BLOCK_OUTER_SHARE:
+		printf(" | %-16s", "Outer-shareable");
+		break;
+	case PTE_BLOCK_INNER_SHARE:
+		printf(" | %-16s", "Inner-shareable");
+		break;
+	default:
+		printf(" | %-16s", "Unknown");
+	}
+}
+
+static void print_pte(u64 pte, int level)
+{
+	if (PTE_IS_TABLE(pte, level)) {
+		printf(" %-5s", "Table");
+		pretty_print_table_attrs(pte);
+	} else {
+		pretty_print_pte_type(pte);
+		pretty_print_block_attrs(pte);
+		pretty_print_block_memtype(pte);
+	}
+	printf("\n");
+}
+
+/**
+ * pagetable_print_entry() - Callback function to print a single pagetable region
+ *
+ * This is the default callback used by @dump_pagetable(). It does some basic pretty
+ * printing (see example in the U-Boot arm64 documentation). It can be replaced by
+ * a custom callback function if more detailed information is needed.
+ *
+ * @start_attrs:	The start address and attributes of the region (or table address)
+ * @end:		The end address of the region (or 0 if it's a table)
+ * @va_bits:		The number of bits used for the virtual address
+ * @level:		The level of the region
+ * @priv:		Private data for the callback (unused)
+ */
+static bool pagetable_print_entry(u64 start_attrs, u64 end, int va_bits, int level, void *priv)
+{
+	u64 _addr = start_attrs & GENMASK_ULL(va_bits, PAGE_SHIFT);
+	int indent = va_bits < 39 ? level - 1 : level;
+
+	printf("%*s", indent * 2, "");
+	if (PTE_IS_TABLE(start_attrs, level))
+		printf("[%#011llx]%14s", _addr, "");
+	else
+		printf("[%#011llx - %#011llx]", _addr, end);
+
+	printf("%*s | ", (3 - level) * 2, "");
+	print_pte(start_attrs, level);
+
+	return false;
+}
+
+void walk_pagetable(u64 ttbr, u64 tcr, pte_walker_cb_t cb, void *priv)
+{
+	__pagetable_walk(ttbr, tcr, 0, cb, priv);
+}
+
+void dump_pagetable(u64 ttbr, u64 tcr)
+{
+	u64 va_bits = 64 - (tcr & (BIT(6) - 1));
+
+	printf("Walking pagetable at %p, va_bits: %lld. Using %d levels\n", (void *)ttbr,
+	       va_bits, va_bits < 39 ? 3 : 4);
+	walk_pagetable(ttbr, tcr, pagetable_print_entry, NULL);
+}
+
 /* Returns the estimated required size of all page tables */
 __weak u64 get_page_table_size(void)
 {
diff --git a/arch/arm/dts/k3-am625-beagleplay-u-boot.dtsi b/arch/arm/dts/k3-am625-beagleplay-u-boot.dtsi
index 1766adc..467cac6 100644
--- a/arch/arm/dts/k3-am625-beagleplay-u-boot.dtsi
+++ b/arch/arm/dts/k3-am625-beagleplay-u-boot.dtsi
@@ -80,6 +80,7 @@
 
 	ti-spl_unsigned {
 		filename = "tispl.bin_unsigned";
+		symlink = "tispl.bin";
 		pad-byte = <0xff>;
 
 		fit {
diff --git a/arch/arm/dts/k3-am625-r5-beagleplay.dts b/arch/arm/dts/k3-am625-r5-beagleplay.dts
index 162d480..f0b66f0 100644
--- a/arch/arm/dts/k3-am625-r5-beagleplay.dts
+++ b/arch/arm/dts/k3-am625-r5-beagleplay.dts
@@ -79,6 +79,7 @@
 &binman {
 	tiboot3-am62x-gp-evm.bin {
 		filename = "tiboot3-am62x-gp-evm.bin";
+		symlink = "tiboot3.bin";
 		ti-secure-rom {
 			content = <&u_boot_spl_unsigned>, <&ti_fs_gp>,
 				<&combined_tifs_cfg_gp>, <&combined_dm_cfg_gp>;
diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h
index ce655ce..0ab681c 100644
--- a/arch/arm/include/asm/armv8/mmu.h
+++ b/arch/arm/include/asm/armv8/mmu.h
@@ -51,7 +51,7 @@
 
 #define PTE_TABLE_PXN		(1UL << 59)
 #define PTE_TABLE_XN		(1UL << 60)
-#define PTE_TABLE_AP		(1UL << 61)
+#define PTE_TABLE_AP		(3UL << 61)
 #define PTE_TABLE_NS		(1UL << 63)
 
 /*
@@ -129,6 +129,62 @@
 	asm volatile("isb");
 }
 
+static inline void get_ttbr_tcr_mair(int el, u64 *table, u64 *tcr, u64 *attr)
+{
+	if (el == 1) {
+		asm volatile("mrs %0, ttbr0_el1" : "=r" (*table));
+		asm volatile("mrs %0, tcr_el1" : "=r" (*tcr));
+		asm volatile("mrs %0, mair_el1" : "=r" (*attr));
+	} else if (el == 2) {
+		asm volatile("mrs %0, ttbr0_el2" : "=r" (*table));
+		asm volatile("mrs %0, tcr_el2" : "=r" (*tcr));
+		asm volatile("mrs %0, mair_el2" : "=r" (*attr));
+	} else if (el == 3) {
+		asm volatile("mrs %0, ttbr0_el3" : "=r" (*table));
+		asm volatile("mrs %0, tcr_el3" : "=r" (*tcr));
+		asm volatile("mrs %0, mair_el3" : "=r" (*attr));
+	} else {
+		hang();
+	}
+}
+
+/**
+ * typedef pte_walker_cb_t - callback function for walk_pagetable.
+ *
+ * This function is called when the walker finds a table entry
+ * or after parsing a block or pages. For a table the @end address
+ * is 0, and @addr is the address of the table. Otherwise, they
+ * are the start and end physical addresses of the block or page.
+ *
+ * @addr: PTE start address (PA), or address of table. Includes attributes.
+ * @end: End address of the region (or 0 for a table)
+ * @va_bits: Number of bits in the virtual address
+ * @level: Table level
+ * @priv: Private data for the callback
+ *
+ * Return: true to stop walking, false to continue
+ */
+typedef bool (*pte_walker_cb_t)(u64 addr, u64 end, int va_bits, int level, void *priv);
+
+/**
+ * walk_pagetable() - Walk the pagetable at ttbr and call @cb for each region
+ *
+ * @ttbr: Address of the pagetable to dump
+ * @tcr: TCR value to use
+ * @cb: Callback function to call for each entry
+ * @priv: Private data for the callback
+ */
+void walk_pagetable(u64 ttbr, u64 tcr, pte_walker_cb_t cb, void *priv);
+
+/**
+ * dump_pagetable() - Dump the pagetable at ttbr, printing each region and
+ * level.
+ *
+ * @ttbr: Address of the pagetable to dump
+ * @tcr: TCR value to use
+ */
+void dump_pagetable(u64 ttbr, u64 tcr);
+
 struct mm_region {
 	u64 virt;
 	u64 phys;
diff --git a/arch/arm/mach-davinci/include/mach/timer_defs.h b/arch/arm/mach-davinci/include/mach/timer_defs.h
index 110e67e..a25f6d1 100644
--- a/arch/arm/mach-davinci/include/mach/timer_defs.h
+++ b/arch/arm/mach-davinci/include/mach/timer_defs.h
@@ -20,24 +20,4 @@
 	u_int32_t	wdtcr;
 };
 
-#define DV_TIMER_TCR_ENAMODE_MASK		3
-
-#define DV_TIMER_TCR_ENAMODE12_SHIFT		6
-#define DV_TIMER_TCR_CLKSRC12_SHIFT		8
-#define DV_TIMER_TCR_READRSTMODE12_SHIFT	10
-#define DV_TIMER_TCR_CAPMODE12_SHIFT		11
-#define DV_TIMER_TCR_CAPVTMODE12_SHIFT		12
-#define DV_TIMER_TCR_ENAMODE34_SHIFT		22
-#define DV_TIMER_TCR_CLKSRC34_SHIFT		24
-#define DV_TIMER_TCR_READRSTMODE34_SHIFT	26
-#define DV_TIMER_TCR_CAPMODE34_SHIFT		27
-#define DV_TIMER_TCR_CAPEVTMODE12_SHIFT		28
-
-#define DV_WDT_ENABLE_SYS_RESET		0x00020000
-#define DV_WDT_TRIGGER_SYS_RESET	0x00020002
-
-#ifdef CONFIG_HW_WATCHDOG
-void davinci_hw_watchdog_enable(void);
-void davinci_hw_watchdog_reset(void);
-#endif
 #endif /* _TIMER_DEFS_H_ */
diff --git a/arch/arm/mach-davinci/timer.c b/arch/arm/mach-davinci/timer.c
index f2990f7..474dc6b 100644
--- a/arch/arm/mach-davinci/timer.c
+++ b/arch/arm/mach-davinci/timer.c
@@ -98,34 +98,3 @@
 {
 	return gd->arch.timer_rate_hz;
 }
-
-#ifdef CONFIG_HW_WATCHDOG
-static struct davinci_timer * const wdttimer =
-	(struct davinci_timer *)CONFIG_SYS_WDTTIMERBASE;
-
-/*
- * See prufw2.pdf for using Timer as a WDT
- */
-void davinci_hw_watchdog_enable(void)
-{
-	writel(0x0, &wdttimer->tcr);
-	writel(0x0, &wdttimer->tgcr);
-	/* TIMMODE = 2h */
-	writel(0x08 | 0x03 | ((TIM_CLK_DIV - 1) << 8), &wdttimer->tgcr);
-	writel(CONFIG_SYS_WDT_PERIOD_LOW, &wdttimer->prd12);
-	writel(CONFIG_SYS_WDT_PERIOD_HIGH, &wdttimer->prd34);
-	writel(2 << 22, &wdttimer->tcr);
-	writel(0x0, &wdttimer->tim12);
-	writel(0x0, &wdttimer->tim34);
-	/* set WDEN bit, WDKEY 0xa5c6 */
-	writel(0xa5c64000, &wdttimer->wdtcr);
-	/* clear counter register */
-	writel(0xda7e4000, &wdttimer->wdtcr);
-}
-
-void davinci_hw_watchdog_reset(void)
-{
-	writel(0xa5c64000, &wdttimer->wdtcr);
-	writel(0xda7e4000, &wdttimer->wdtcr);
-}
-#endif
diff --git a/arch/arm/mach-imx/cmd_dek.c b/arch/arm/mach-imx/cmd_dek.c
index c7962ea..56e1a8f 100644
--- a/arch/arm/mach-imx/cmd_dek.c
+++ b/arch/arm/mach-imx/cmd_dek.c
@@ -395,10 +395,10 @@
 }
 
 /***************************************************/
-static char dek_blob_help_text[] =
+U_BOOT_LONGHELP(dek_blob,
 	"src dst len            - Encapsulate and create blob of data\n"
 	"                         $len bits long at address $src and\n"
-	"                         store the result at address $dst.\n";
+	"                         store the result at address $dst.\n");
 
 U_BOOT_CMD(
 	dek_blob, 4, 1, do_dek_blob,
diff --git a/arch/arm/mach-imx/cmd_mfgprot.c b/arch/arm/mach-imx/cmd_mfgprot.c
index 9925c99..9f37e61 100644
--- a/arch/arm/mach-imx/cmd_mfgprot.c
+++ b/arch/arm/mach-imx/cmd_mfgprot.c
@@ -134,12 +134,12 @@
 }
 
 /***************************************************/
-static char mfgprot_help_text[] =
+U_BOOT_LONGHELP(mfgprot,
 	"Usage:\n"
 	 "Print the public key for Manufacturing Protection\n"
 	 "\tmfgprot pubk\n"
 	 "Generates a Manufacturing Protection signature\n"
-	 "\tmfgprot sign <data_addr> <size>";
+	 "\tmfgprot sign <data_addr> <size>\n");
 
 U_BOOT_CMD(
 	mfgprot, 4, 1, do_mfgprot,
diff --git a/arch/arm/mach-imx/imx8/snvs_security_sc.c b/arch/arm/mach-imx/imx8/snvs_security_sc.c
index f13dfc1..df8c22b 100644
--- a/arch/arm/mach-imx/imx8/snvs_security_sc.c
+++ b/arch/arm/mach-imx/imx8/snvs_security_sc.c
@@ -597,7 +597,7 @@
 }
 #endif /* CONFIG_IMX_SNVS_SEC_SC_AUTO */
 
-static char snvs_cfg_help_text[] =
+U_BOOT_LONGHELP(snvs_cfg,
 	"snvs_cfg\n"
 	"\thp.lock\n"
 	"\thp.secvio_ctl\n"
@@ -618,7 +618,7 @@
 	"\tlp.act_tamper_routing_ctl1\n"
 	"\tlp.act_tamper_routing_ctl2\n"
 	"\n"
-	"ALL values should be in hexadecimal format";
+	"ALL values should be in hexadecimal format\n");
 
 #define NB_REGISTERS 18
 static int do_snvs_cfg(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -662,7 +662,7 @@
 	   snvs_cfg_help_text
 );
 
-static char snvs_dgo_cfg_help_text[] =
+U_BOOT_LONGHELP(snvs_dgo_cfg,
 	"snvs_dgo_cfg\n"
 	"\ttamper_offset_ctl\n"
 	"\ttamper_pull_ctl\n"
@@ -671,7 +671,7 @@
 	"\ttamper_misc_ctl\n"
 	"\ttamper_core_volt_mon_ctl\n"
 	"\n"
-	"ALL values should be in hexadecimal format";
+	"ALL values should be in hexadecimal format\n");
 
 static int do_snvs_dgo_cfg(struct cmd_tbl *cmdtp, int flag, int argc,
 			   char *const argv[])
@@ -702,12 +702,12 @@
 	   snvs_dgo_cfg_help_text
 );
 
-static char tamper_pin_cfg_help_text[] =
+U_BOOT_LONGHELP(tamper_pin_cfg,
 	"snvs_dgo_cfg\n"
 	"\tpad\n"
 	"\tvalue\n"
 	"\n"
-	"ALL values should be in hexadecimal format";
+	"ALL values should be in hexadecimal format\n");
 
 static int do_tamper_pin_cfg(struct cmd_tbl *cmdtp, int flag, int argc,
 			     char *const argv[])
@@ -734,7 +734,7 @@
 	   tamper_pin_cfg_help_text
 );
 
-static char snvs_clear_status_help_text[] =
+U_BOOT_LONGHELP(snvs_clear_status,
 	"snvs_clear_status\n"
 	"\tHPSR\n"
 	"\tHPSVSR\n"
@@ -742,7 +742,7 @@
 	"\tLPTDSR\n"
 	"\n"
 	"Write the status registers with the value provided,"
-	" clearing the status";
+	" clearing the status\n");
 
 static int do_snvs_clear_status(struct cmd_tbl *cmdtp, int flag, int argc,
 				char *const argv[])
@@ -778,9 +778,9 @@
 	   snvs_clear_status_help_text
 );
 
-static char snvs_sec_status_help_text[] =
+U_BOOT_LONGHELP(snvs_sec_status,
 	"snvs_sec_status\n"
-	"Display information about the security related to tamper and secvio";
+	"Display information about the security related to tamper and secvio\n");
 
 static int do_snvs_sec_status(struct cmd_tbl *cmdtp, int flag, int argc,
 			      char *const argv[])
diff --git a/arch/arm/mach-k3/r5/j784s4/clk-data.c b/arch/arm/mach-k3/r5/j784s4/clk-data.c
index feaa13e..793bcac 100644
--- a/arch/arm/mach-k3/r5/j784s4/clk-data.c
+++ b/arch/arm/mach-k3/r5/j784s4/clk-data.c
@@ -134,7 +134,7 @@
 
 static const char * const mcu_clkout_mux_out0_parents[] = {
 	"hsdiv4_16fft_mcu_2_hsdivout0_clk",
-	"hsdiv4_16fft_mcu_2_hsdivout0_clk",
+	"hsdiv4_16fft_mcu_2_hsdivout1_clk",
 };
 
 static const char * const k3_pll_ctrl_wrap_main_0_sysclkout_clk_parents[] = {
@@ -338,7 +338,7 @@
 	DEV_CLK(149, 5, "k3_pll_ctrl_wrap_wkup_0_chip_div1_clk_clk"),
 	DEV_CLK(157, 174, "mcu_clkout_mux_out0"),
 	DEV_CLK(157, 175, "hsdiv4_16fft_mcu_2_hsdivout0_clk"),
-	DEV_CLK(157, 176, "hsdiv4_16fft_mcu_2_hsdivout0_clk"),
+	DEV_CLK(157, 176, "hsdiv4_16fft_mcu_2_hsdivout1_clk"),
 	DEV_CLK(157, 179, "fss_mcu_0_hyperbus1p0_0_hpb_out_clk_p"),
 	DEV_CLK(157, 180, "fss_mcu_0_hyperbus1p0_0_hpb_out_clk_n"),
 	DEV_CLK(157, 224, "fss_mcu_0_ospi_0_ospi_oclk_clk"),
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c
index 0cb3c7a..040a70f 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32key.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32key.c
@@ -419,12 +419,12 @@
 	return CMD_RET_SUCCESS;
 }
 
-static char stm32key_help_text[] =
+U_BOOT_LONGHELP(stm32key,
 	"list : list the supported key with description\n"
 	"stm32key select [<key>] : Select the key identified by <key> or display the key used for read/fuse command\n"
 	"stm32key read [<addr> | -a ] : Read the curent key at <addr> or current / all (-a) key in OTP\n"
 	"stm32key fuse [-y] <addr> : Fuse the current key at addr in OTP\n"
-	"stm32key close [-y] : Close the device\n";
+	"stm32key close [-y] : Close the device\n");
 
 U_BOOT_CMD_WITH_SUBCMDS(stm32key, "Manage key on STM32", stm32key_help_text,
 	U_BOOT_SUBCMD_MKENT(list, 1, 0, do_stm32key_list),
diff --git a/board/amd/versal2/cmds.c b/board/amd/versal2/cmds.c
index fbd9991..56ae39b 100644
--- a/board/amd/versal2/cmds.c
+++ b/board/amd/versal2/cmds.c
@@ -71,10 +71,9 @@
 	return cmd_process_error(cmdtp, ret);
 }
 
-static char versal2_help_text[] =
+U_BOOT_LONGHELP(versal2,
 	"loadpdi addr len - Load pdi image\n"
-	"load pdi image at ddr address 'addr' with pdi image size 'len'\n"
-;
+	"load pdi image at ddr address 'addr' with pdi image size 'len'\n");
 
 U_BOOT_CMD_WITH_SUBCMDS(versal2, "Versal Gen 2 sub-system", versal2_help_text,
 			U_BOOT_SUBCMD_MKENT(loadpdi, 3, 1,
diff --git a/board/beagle/beagleplay/beagleplay.env b/board/beagle/beagleplay/beagleplay.env
index 8dbfc2f..354bc98 100644
--- a/board/beagle/beagleplay/beagleplay.env
+++ b/board/beagle/beagleplay/beagleplay.env
@@ -12,7 +12,7 @@
 	led led-2 on; led led-3 off; led led-4 on
 boot=mmc
 mmcdev=1
-bootpart=1:1
+bootpart=1:2
 bootdir=/boot
 boot_targets=mmc1 mmc0
 bootmeths=script extlinux efi pxe
diff --git a/board/freescale/common/cmd_esbc_validate.c b/board/freescale/common/cmd_esbc_validate.c
index d4192e5..3344653 100644
--- a/board/freescale/common/cmd_esbc_validate.c
+++ b/board/freescale/common/cmd_esbc_validate.c
@@ -63,14 +63,14 @@
 }
 
 /***************************************************/
-static char esbc_validate_help_text[] =
+U_BOOT_LONGHELP(esbc_validate,
 	"esbc_validate hdr_addr <hash_val> - Validates signature using\n"
 	"                          RSA verification\n"
 	"                          $hdr_addr Address of header of the image\n"
 	"                          to be validated.\n"
 	"                          $hash_val -Optional\n"
 	"                          It provides Hash of public/srk key to be\n"
-	"                          used to verify signature.\n";
+	"                          used to verify signature.\n");
 
 U_BOOT_CMD(
 	esbc_validate,	3,	0,	do_esbc_validate,
diff --git a/board/kontron/sl28/cmds.c b/board/kontron/sl28/cmds.c
index 7851361..0751477 100644
--- a/board/kontron/sl28/cmds.c
+++ b/board/kontron/sl28/cmds.c
@@ -172,8 +172,8 @@
 	return CMD_RET_FAILURE;
 }
 
-static char sl28_help_text[] =
-	"nvm [<hex>] - display/set the 16 non-volatile bits\n";
+U_BOOT_LONGHELP(sl28,
+	"nvm [<hex>] - display/set the 16 non-volatile bits\n");
 
 U_BOOT_CMD_WITH_SUBCMDS(sl28, "SMARC-sAL28 specific", sl28_help_text,
 			U_BOOT_SUBCMD_MKENT(nvm, 2, 1, do_sl28_nvm));
diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index 30a8137..0b43407 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -701,11 +701,6 @@
 #define MAX_RAND_SIZE 8
 int ft_board_setup(void *blob, struct bd_info *bd)
 {
-	size_t n = MAX_RAND_SIZE;
-	struct udevice *dev;
-	u8 buf[MAX_RAND_SIZE];
-	int nodeoffset, ret;
-
 	static const struct node_info nodes[] = {
 		{ "arm,pl353-nand-r2p1", MTD_DEV_TYPE_NAND, },
 	};
@@ -713,41 +708,6 @@
 	if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
 		fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
 
-	if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
-		debug("No RNG device\n");
-		return 0;
-	}
-
-	if (dm_rng_read(dev, buf, n)) {
-		debug("Reading RNG failed\n");
-		return 0;
-	}
-
-	if (!blob) {
-		debug("No FDT memory address configured. Please configure\n"
-		      "the FDT address via \"fdt addr <address>\" command.\n"
-		      "Aborting!\n");
-		return 0;
-	}
-
-	ret = fdt_check_header(blob);
-	if (ret < 0) {
-		debug("fdt_chosen: %s\n", fdt_strerror(ret));
-		return ret;
-	}
-
-	nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
-	if (nodeoffset < 0) {
-		debug("Reading chosen node failed\n");
-		return nodeoffset;
-	}
-
-	ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
-	if (ret < 0) {
-		debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
-		return ret;
-	}
-
 	return 0;
 }
 #endif
diff --git a/board/xilinx/versal-net/cmds.c b/board/xilinx/versal-net/cmds.c
index 4d52084..e8b669f 100644
--- a/board/xilinx/versal-net/cmds.c
+++ b/board/xilinx/versal-net/cmds.c
@@ -71,10 +71,9 @@
 	return cmd_process_error(cmdtp, ret);
 }
 
-static char versalnet_help_text[] =
+U_BOOT_LONGHELP(versalnet,
 	"loadpdi addr len - Load pdi image\n"
-	"load pdi image at ddr address 'addr' with pdi image size 'len'\n"
-;
+	"load pdi image at ddr address 'addr' with pdi image size 'len'\n");
 
 U_BOOT_CMD_WITH_SUBCMDS(versalnet, "Versal NET sub-system", versalnet_help_text,
 			U_BOOT_SUBCMD_MKENT(loadpdi, 3, 1,
diff --git a/boot/Kconfig b/boot/Kconfig
index a212f26..11175fb 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -734,6 +734,10 @@
 config MEASURED_BOOT
 	bool "Measure boot images and configuration when booting without EFI"
 	depends on HASH && TPM_V2
+	select SHA1
+	select SHA256
+	select SHA384
+	select SHA512
 	help
 	  This option enables measurement of the boot process when booting
 	  without UEFI . Measurement involves creating cryptographic hashes
diff --git a/boot/bootm.c b/boot/bootm.c
index 3de87eb..376d63a 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <linux/sizes.h>
 #include <tpm-v2.h>
+#include <tpm_tcg2.h>
 #if defined(CONFIG_CMD_USB)
 #include <usb.h>
 #endif
diff --git a/boot/fdt_support.c b/boot/fdt_support.c
index 874ca4d..2392027 100644
--- a/boot/fdt_support.c
+++ b/boot/fdt_support.c
@@ -6,12 +6,15 @@
  * Copyright 2010-2011 Freescale Semiconductor, Inc.
  */
 
+#include <dm.h>
 #include <abuf.h>
 #include <env.h>
 #include <log.h>
 #include <mapmem.h>
 #include <net.h>
+#include <rng.h>
 #include <stdio_dev.h>
+#include <dm/device_compat.h>
 #include <dm/ofnode.h>
 #include <linux/ctype.h>
 #include <linux/types.h>
@@ -273,6 +276,47 @@
 	return 0;
 }
 
+int fdt_kaslrseed(void *fdt, bool overwrite)
+{
+	int len, err, nodeoffset;
+	struct udevice *dev;
+	const u64 *orig;
+	u64 data = 0;
+
+	err = fdt_check_header(fdt);
+	if (err < 0)
+		return err;
+
+	/* find or create "/chosen" node. */
+	nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
+	if (nodeoffset < 0)
+		return nodeoffset;
+
+	/* return without error if we are not overwriting and existing non-zero node */
+	orig = fdt_getprop(fdt, nodeoffset, "kaslr-seed", &len);
+	if (orig && len == sizeof(*orig))
+		data = fdt64_to_cpu(*orig);
+	if (data && !overwrite) {
+		debug("not overwriting existing kaslr-seed\n");
+		return 0;
+	}
+	err = uclass_get_device(UCLASS_RNG, 0, &dev);
+	if (err) {
+		printf("No RNG device\n");
+		return err;
+	}
+	err = dm_rng_read(dev, &data, sizeof(data));
+	if (err) {
+		dev_err(dev, "dm_rng_read failed: %d\n", err);
+		return err;
+	}
+	err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", &data, sizeof(data));
+	if (err < 0)
+		printf("WARNING: could not set kaslr-seed %s.\n", fdt_strerror(err));
+
+	return err;
+}
+
 /**
  * board_fdt_chosen_bootargs - boards may override this function to use
  *                             alternative kernel command line arguments
@@ -300,6 +344,15 @@
 	if (nodeoffset < 0)
 		return nodeoffset;
 
+	/* if DM_RNG enabled automatically inject kaslr-seed node unless:
+	 * CONFIG_MEASURED_BOOT enabled: as dt modifications break measured boot
+	 * CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT enabled: as that implementation does not use dm yet
+	 */
+	if (IS_ENABLED(CONFIG_DM_RNG) &&
+	    !IS_ENABLED(CONFIG_MEASURED_BOOT) &&
+	    !IS_ENABLED(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT))
+		fdt_kaslrseed(fdt, false);
+
 	if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) {
 		err = fdt_setprop(fdt, nodeoffset, "rng-seed",
 				  abuf_data(&buf), abuf_size(&buf));
diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c
index 4b22bb6..53d6cf7 100644
--- a/boot/pxe_utils.c
+++ b/boot/pxe_utils.c
@@ -4,6 +4,8 @@
  * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
  */
 
+#define LOG_CATEGORY	LOGC_BOOT
+
 #include <command.h>
 #include <dm.h>
 #include <env.h>
@@ -323,10 +325,6 @@
 #if CONFIG_IS_ENABLED(DM_RNG)
 	ulong fdt_addr;
 	struct fdt_header *working_fdt;
-	size_t n = 0x8;
-	struct udevice *dev;
-	u64 *buf;
-	int nodeoffset;
 	int err;
 
 	/* Get the main fdt and map it */
@@ -341,36 +339,8 @@
 	err = fdt_shrink_to_minimum(working_fdt, 512);
 	if (err <= 0)
 		return;
-
-	if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
-		printf("No RNG device\n");
-		return;
-	}
-
-	nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
-	if (nodeoffset < 0) {
-		printf("Reading chosen node failed\n");
-		return;
-	}
-
-	buf = malloc(n);
-	if (!buf) {
-		printf("Out of memory\n");
-		return;
-	}
 
-	if (dm_rng_read(dev, buf, n)) {
-		printf("Reading RNG failed\n");
-		goto err;
-	}
-
-	err = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
-	if (err < 0) {
-		printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(err));
-		goto err;
-	}
-err:
-	free(buf);
+	fdt_kaslrseed(working_fdt, true);
 #endif
 	return;
 }
@@ -762,17 +732,22 @@
 
 	/* Try bootm for legacy and FIT format image */
 	if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID &&
-            IS_ENABLED(CONFIG_CMD_BOOTM))
+	    IS_ENABLED(CONFIG_CMD_BOOTM)) {
+		log_debug("using bootm\n");
 		do_bootm(ctx->cmdtp, 0, bootm_argc, bootm_argv);
 	/* Try booting an AArch64 Linux kernel image */
-	else if (IS_ENABLED(CONFIG_CMD_BOOTI))
+	} else if (IS_ENABLED(CONFIG_CMD_BOOTI)) {
+		log_debug("using booti\n");
 		do_booti(ctx->cmdtp, 0, bootm_argc, bootm_argv);
 	/* Try booting a Image */
-	else if (IS_ENABLED(CONFIG_CMD_BOOTZ))
+	} else if (IS_ENABLED(CONFIG_CMD_BOOTZ)) {
+		log_debug("using bootz\n");
 		do_bootz(ctx->cmdtp, 0, bootm_argc, bootm_argv);
 	/* Try booting an x86_64 Linux kernel image */
-	else if (IS_ENABLED(CONFIG_CMD_ZBOOT))
+	} else if (IS_ENABLED(CONFIG_CMD_ZBOOT)) {
+		log_debug("using zboot\n");
 		do_zboot_parent(ctx->cmdtp, 0, zboot_argc, zboot_argv, NULL);
+	}
 
 	unmap_sysmem(buf);
 
diff --git a/cmd/adc.c b/cmd/adc.c
index f87f978..4d3b5b6 100644
--- a/cmd/adc.c
+++ b/cmd/adc.c
@@ -152,11 +152,11 @@
 	return CMD_RET_SUCCESS;
 }
 
-static char adc_help_text[] =
+U_BOOT_LONGHELP(adc,
 	"list - list ADC devices\n"
 	"adc info <name> - Get ADC device info\n"
 	"adc single <name> <channel> [varname] - Get Single data of ADC device channel\n"
-	"adc scan <name> [channel mask] - Scan all [or masked] ADC channels";
+	"adc scan <name> [channel mask] - Scan all [or masked] ADC channels\n");
 
 U_BOOT_CMD_WITH_SUBCMDS(adc, "ADC sub-system", adc_help_text,
 	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_adc_list),
diff --git a/cmd/arm/exception.c b/cmd/arm/exception.c
index 98a9795..8857f12 100644
--- a/cmd/arm/exception.c
+++ b/cmd/arm/exception.c
@@ -49,12 +49,11 @@
 			 "", ""),
 };
 
-static char exception_help_text[] =
+U_BOOT_LONGHELP(exception,
 	"<ex>\n"
 	"  The following exceptions are available:\n"
 	"  breakpoint - prefetch abort\n"
 	"  unaligned  - data abort\n"
-	"  undefined  - undefined instruction\n"
-	;
+	"  undefined  - undefined instruction\n");
 
 #include <exception.h>
diff --git a/cmd/arm/exception64.c b/cmd/arm/exception64.c
index 73d6c20..4c5b953 100644
--- a/cmd/arm/exception64.c
+++ b/cmd/arm/exception64.c
@@ -77,12 +77,11 @@
 			 "", ""),
 };
 
-static char exception_help_text[] =
+U_BOOT_LONGHELP(exception,
 	"<ex>\n"
 	"  The following exceptions are available:\n"
 	"  breakpoint - breakpoint instruction exception\n"
 	"  unaligned  - unaligned LDAR data abort\n"
-	"  undefined  - undefined instruction exception\n"
-	;
+	"  undefined  - undefined instruction exception\n");
 
 #include <exception.h>
diff --git a/cmd/blob.c b/cmd/blob.c
index a3c1dc4..b1c72e3 100644
--- a/cmd/blob.c
+++ b/cmd/blob.c
@@ -99,7 +99,7 @@
 }
 
 /***************************************************/
-static char blob_help_text[] =
+U_BOOT_LONGHELP(blob,
 	"enc src dst len km - Encapsulate and create blob of data\n"
 	"                          $len bytes long at address $src and\n"
 	"                          store the result at address $dst.\n"
@@ -115,7 +115,7 @@
 	"                          modifier is stored.\n"
 	"                          The modifier is required for generation\n"
 	"                          /use as key for cryptographic operation.\n"
-	"                          Key modifier should be 16 byte long.\n";
+	"                          Key modifier should be 16 byte long.\n");
 
 U_BOOT_CMD(
 	blob, 6, 1, do_blob,
diff --git a/cmd/cli.c b/cmd/cli.c
index be3bf7d..e0ddd0a 100644
--- a/cmd/cli.c
+++ b/cmd/cli.c
@@ -118,16 +118,11 @@
 	return CMD_RET_USAGE;
 }
 
-#if CONFIG_IS_ENABLED(SYS_LONGHELP)
-static char cli_help_text[] =
+U_BOOT_LONGHELP(cli,
 	"get - print current cli\n"
-	"set - set the current cli, possible value are: old, modern"
-	;
-#endif
+	"set - set the current cli, possible value are: old, modern\n");
 
 U_BOOT_CMD(cli, 3, 1, do_cli,
 	   "cli",
-#if CONFIG_IS_ENABLED(SYS_LONGHELP)
 	   cli_help_text
-#endif
 );
diff --git a/cmd/fwu_mdata.c b/cmd/fwu_mdata.c
index 3c8be57..9c048d6 100644
--- a/cmd/fwu_mdata.c
+++ b/cmd/fwu_mdata.c
@@ -22,6 +22,7 @@
 	printf("\tFWU Metadata\n");
 	printf("crc32: %#x\n", data->crc32);
 	printf("version: %#x\n", data->version);
+	printf("size: %#x\n", data->metadata_size);
 	printf("active_index: %#x\n", data->active_index);
 	printf("previous_active_index: %#x\n", data->previous_active_index);
 
diff --git a/cmd/gpt.c b/cmd/gpt.c
index 36b112d..aeabd19 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -682,7 +682,8 @@
 	free(str_disk_guid);
 	free(partitions);
  out:
-	free(gpt_pte);
+	if (!ret)
+		free(gpt_pte);
 	return ret;
 }
 
diff --git a/cmd/kaslrseed.c b/cmd/kaslrseed.c
index e0d3c7f..2ad983a 100644
--- a/cmd/kaslrseed.c
+++ b/cmd/kaslrseed.c
@@ -15,60 +15,25 @@
 
 static int do_kaslr_seed(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-	size_t n = 0x8;
-	struct udevice *dev;
-	u64 *buf;
-	int nodeoffset;
-	int ret = CMD_RET_SUCCESS;
+	int err = CMD_RET_SUCCESS;
 
-	if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
-		printf("No RNG device\n");
-		return CMD_RET_FAILURE;
-	}
-
-	buf = malloc(n);
-	if (!buf) {
-		printf("Out of memory\n");
-		return CMD_RET_FAILURE;
-	}
-
-	if (dm_rng_read(dev, buf, n)) {
-		printf("Reading RNG failed\n");
-		return CMD_RET_FAILURE;
-	}
+	printf("Notice: a /chosen/kaslr-seed is automatically added to the device-tree when booted via booti/bootm/bootz therefore using this command is likely no longer needed\n");
 
 	if (!working_fdt) {
 		printf("No FDT memory address configured. Please configure\n"
 		       "the FDT address via \"fdt addr <address>\" command.\n"
 		       "Aborting!\n");
-		return CMD_RET_FAILURE;
-	}
-
-	ret = fdt_check_header(working_fdt);
-	if (ret < 0) {
-		printf("fdt_chosen: %s\n", fdt_strerror(ret));
-		return CMD_RET_FAILURE;
-	}
-
-	nodeoffset = fdt_find_or_add_subnode(working_fdt, 0, "chosen");
-	if (nodeoffset < 0) {
-		printf("Reading chosen node failed\n");
-		return CMD_RET_FAILURE;
+		err = CMD_RET_FAILURE;
+	} else {
+		if (fdt_kaslrseed(working_fdt, true) < 0)
+			err = CMD_RET_FAILURE;
 	}
 
-	ret = fdt_setprop(working_fdt, nodeoffset, "kaslr-seed", buf, sizeof(buf));
-	if (ret < 0) {
-		printf("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
-		return CMD_RET_FAILURE;
-	}
-
-	free(buf);
-
-	return ret;
+	return cmd_process_error(cmdtp, err);
 }
 
 U_BOOT_LONGHELP(kaslrseed,
-	"[n]\n"
+	"\n"
 	"  - append random bytes to chosen kaslr-seed node\n");
 
 U_BOOT_CMD(
diff --git a/cmd/riscv/exception.c b/cmd/riscv/exception.c
index 14ad6c4..2b58b1c 100644
--- a/cmd/riscv/exception.c
+++ b/cmd/riscv/exception.c
@@ -68,14 +68,13 @@
 			 "", ""),
 };
 
-static char exception_help_text[] =
+U_BOOT_LONGHELP(exception,
 	"<ex>\n"
 	"  The following exceptions are available:\n"
 	"  compressed - compressed instruction\n"
 	"  ebreak     - breakpoint\n"
 	"  ialign16   - 16 bit aligned instruction\n"
 	"  undefined  - illegal instruction\n"
-	"  unaligned  - load address misaligned\n"
-	;
+	"  unaligned  - load address misaligned\n");
 
 #include <exception.h>
diff --git a/cmd/scmi.c b/cmd/scmi.c
index 664062c..cfbca63 100644
--- a/cmd/scmi.c
+++ b/cmd/scmi.c
@@ -369,7 +369,7 @@
 	return cp->cmd(cmdtp, flag, argc, argv);
 }
 
-static char scmi_help_text[] =
+U_BOOT_LONGHELP(scmi,
 	" - SCMI utility\n"
 	" info - get the info of SCMI services\n"
 	" perm_dev <agent-id in hex> <device-id in hex> <flags in hex>\n"
@@ -377,8 +377,7 @@
 	" perm_proto <agent-id in hex> <device-id in hex> <protocol-id in hex> <flags in hex>\n"
 	"   - set protocol permission to device\n"
 	" reset <agent-id in hex> <flags in hex>\n"
-	"   - reset platform resource settings\n"
-	"";
+	"   - reset platform resource settings\n");
 
 U_BOOT_CMD(scmi, CONFIG_SYS_MAXARGS, 0, do_scmi, "SCMI utility",
 	   scmi_help_text);
diff --git a/cmd/x86/exception.c b/cmd/x86/exception.c
index 14b6bd6..0273549 100644
--- a/cmd/x86/exception.c
+++ b/cmd/x86/exception.c
@@ -19,10 +19,9 @@
 			 "", ""),
 };
 
-static char exception_help_text[] =
+U_BOOT_LONGHELP(exception,
 	"<ex>\n"
 	"  The following exceptions are available:\n"
-	"  undefined  - undefined instruction\n"
-	;
+	"  undefined  - undefined instruction\n");
 
 #include <exception.h>
diff --git a/cmd/x86/zboot.c b/cmd/x86/zboot.c
index addf28c..94e602b8 100644
--- a/cmd/x86/zboot.c
+++ b/cmd/x86/zboot.c
@@ -5,6 +5,8 @@
  * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
  */
 
+#define LOG_CATEGORY	LOGC_BOOT
+
 #include <command.h>
 #include <mapmem.h>
 #include <vsprintf.h>
@@ -14,8 +16,14 @@
 			  char *const argv[])
 {
 	ulong bzimage_addr = 0, bzimage_size, initrd_addr, initrd_size;
-	ulong base_addr;
 	const char *s, *cmdline;
+	ulong base_addr;
+	int i;
+
+	log_debug("argc %d:", argc);
+	for (i = 0; i < argc; i++)
+		log_debug(" %s", argv[i]);
+	log_debug("\n");
 
 	/* argv[1] holds the address of the bzImage */
 	s = cmd_arg1(argc, argv) ? : env_get("fileaddr");
@@ -114,17 +122,18 @@
 int do_zboot_states(struct cmd_tbl *cmdtp, int flag, int argc,
 		    char *const argv[], int state_mask)
 {
-	int ret;
+	int ret = 0;
 
-	if (flag & ZBOOT_STATE_START)
+	log_debug("state_mask %x\n", state_mask);
+	if (state_mask & ZBOOT_STATE_START)
 		ret = do_zboot_start(cmdtp, flag, argc, argv);
-	if (!ret && (flag & ZBOOT_STATE_LOAD))
+	if (!ret && (state_mask & ZBOOT_STATE_LOAD))
 		ret = do_zboot_load(cmdtp, flag, argc, argv);
-	if (!ret && (flag & ZBOOT_STATE_SETUP))
+	if (!ret && (state_mask & ZBOOT_STATE_SETUP))
 		ret = do_zboot_setup(cmdtp, flag, argc, argv);
-	if (!ret && (flag & ZBOOT_STATE_INFO))
+	if (!ret && (state_mask & ZBOOT_STATE_INFO))
 		ret = do_zboot_info(cmdtp, flag, argc, argv);
-	if (!ret && (flag & ZBOOT_STATE_GO))
+	if (!ret && (state_mask & ZBOOT_STATE_GO))
 		ret = do_zboot_go(cmdtp, flag, argc, argv);
 	if (ret)
 		return ret;
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 988125b..2a097f4 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -587,7 +587,7 @@
 static void warn_deprecated(const char *msg)
 {
 	printf("DEPRECATED: %s\n", msg);
-	printf("\tSee doc/uImage.FIT/source_file_format.txt\n");
+	printf("\tSee https://fitspec.osfw.foundation/\n");
 }
 
 static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node,
diff --git a/doc/arch/arm64.rst b/doc/arch/arm64.rst
index 7c07135..19662be 100644
--- a/doc/arch/arm64.rst
+++ b/doc/arch/arm64.rst
@@ -48,6 +48,55 @@
 6. CONFIG_ARM64 instead of CONFIG_ARMV8 is used to distinguish aarch64 and
    aarch32 specific codes.
 
+MMU
+---
+
+U-Boot uses a simple page table for MMU setup. It uses the smallest number of bits
+possible for the virtual address based on the maximum memory address (see the logic
+in ``get_tcr()``). If this is less than 39 bits, the MMU will use only 3 levels for
+address translation.
+
+As with all platforms, U-Boot on ARM64 uses a 1:1 mapping of virtual to physical addresses.
+In general, the memory map is expected to remain static once the MMU is enabled.
+
+Software pagetable walker
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+It is possible to debug the pagetable generated by U-Boot with the built in
+``dump_pagetable()`` and ``walk_pagetable()`` functions (the former being a simple
+wrapper for the latter). For example the following can be added to ``setup_all_pgtables()``
+after the first call to ``setup_pgtables()``:
+
+.. code-block:: c
+
+    dump_pagetable(gd->arch.tlb_addr, get_tcr(NULL, NULL));
+
+.. kernel-doc:: arch/arm/cpu/armv8/cache_v8.c
+   :identifiers: __pagetable_walk pagetable_print_entry
+
+The pagetable walker can be used as follows:
+
+.. kernel-doc:: arch/arm/include/asm/armv8/mmu.h
+   :identifiers: pte_walker_cb_t walk_pagetable dump_pagetable
+
+This will result in a print like the following:
+
+.. code-block:: text
+
+    Walking pagetable at 000000017df90000, va_bits: 36. Using 3 levels
+    [0x17df91000]                   |  Table |               |
+      [0x17df92000]                 |  Table |               |
+        [0x000001000 - 0x000200000] |  Pages | Device-nGnRnE | Non-shareable
+      [0x000200000 - 0x040000000]   |  Block | Device-nGnRnE | Non-shareable
+    [0x040000000 - 0x080000000]     |  Block | Device-nGnRnE | Non-shareable
+    [0x080000000 - 0x140000000]     |  Block | Normal        | Inner-shareable
+    [0x17df93000]                   |  Table |               |
+      [0x140000000 - 0x17de00000]   |  Block | Normal        | Inner-shareable
+      [0x17df94000]                 |  Table |               |
+        [0x17de00000 - 0x17dfa0000] |  Pages | Normal        | Inner-shareable
+
+For more information, please refer to the additional function documentation in
+``arch/arm/include/asm/armv8/mmu.h``.
 
 Contributors
 ------------
diff --git a/doc/board/beagle/am62x_beagleplay.rst b/doc/board/beagle/am62x_beagleplay.rst
index cdc6102..01f04be 100644
--- a/doc/board/beagle/am62x_beagleplay.rst
+++ b/doc/board/beagle/am62x_beagleplay.rst
@@ -71,11 +71,10 @@
 
 Target Images
 -------------
-Copy the below images to an SD card and boot:
+Copy these images to an SD card and boot:
 
-* tiboot3-am62x-gp-evm.bin from R5 build as tiboot3.bin
-* tispl.bin_unsigned from Cortex-A build as tispl.bin
-* u-boot.img_unsigned from Cortex-A build as u-boot.img
+* tiboot3.bin from Cortex-R5 build.
+* tispl.bin and u-boot.img from Cortex-A build
 
 Image formats
 -------------
diff --git a/doc/develop/gdb.rst b/doc/develop/gdb.rst
new file mode 100644
index 0000000..4e359c7
--- /dev/null
+++ b/doc/develop/gdb.rst
@@ -0,0 +1,171 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright (c) 2024 Alexander Dahl
+
+Debugging U-Boot with GDB
+=========================
+
+Using a JTAG adapter it is possible to debug a running U-Boot with GDB.
+A common way is to connect a debug adapter to the JTAG connector of your
+board, run a GDB server, connect GDB to the GDB server, and use GDB as usual.
+
+Similarly QEMU can provide a GDB server.
+
+Preparing build
+---------------
+
+Building U-Boot with with reduced optimization (-Og) and without link time
+optimization is recommended for easier debugging::
+
+    CONFIG_CC_OPTIMIZE_FOR_DEBUG=y
+    CONFIG_LTO=n
+
+Otherwise build, install, and run U-Boot as usual.
+
+Using OpenOCD as GDB server
+---------------------------
+
+`OpenOCD <https://openocd.org/>`_ is an open source tool supporting hardware
+debug probes, and providing a GDB server. It is readily available in major Linux
+distributions or you can build it from source.
+
+Here is example of starting OpenOCD on Debian using a J-Link adapter and a
+board with an AT91 SAMA5D2 SoC:
+
+.. code-block:: console
+
+    $ openocd -f interface/jlink.cfg -f target/at91sama5d2.cfg -c 'adapter speed 4000'
+    Open On-Chip Debugger 0.12.0
+    Licensed under GNU GPL v2
+    For bug reports, read
+            http://openocd.org/doc/doxygen/bugs.html
+    Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
+    adapter speed: 4000 kHz
+
+    Info : Listening on port 6666 for tcl connections
+    Info : Listening on port 4444 for telnet connections
+    Info : J-Link V10 compiled Jan 30 2023 11:28:07
+    Info : Hardware version: 10.10
+    Info : VTarget = 3.244 V
+    Info : clock speed 4000 kHz
+    Info : JTAG tap: at91sama5d2.cpu tap/device found: 0x5ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x5)
+    Info : at91sama5d2.cpu_a5.0: hardware has 3 breakpoints, 2 watchpoints
+    Info : at91sama5d2.cpu_a5.0: MPIDR level2 0, cluster 0, core 0, mono core, no SMT
+    Info : starting gdb server for at91sama5d2.cpu_a5.0 on 3333
+    Info : Listening on port 3333 for gdb connections
+
+Notice that OpenOCD is listening on port 3333 for GDB connections.
+
+Using QEMU as GDB server
+------------------------
+
+When running U-Boot on QEMU you can used the '-gdb' parameter to provide a
+GDB server:
+
+     qemu-system-riscv64 -M virt -nographic -gdb tcp::3333 -kernel u-boot
+
+Running a GDB session
+----------------------
+
+You need a GDB suited for your target. This can be the GDB coming with your
+toolchain or *gdb-multiarch* available in your Linux distribution.
+
+.. prompt:: bash $
+
+    gdb-multiarch u-boot
+
+In the above command-line *u-boot* is the U-boot binary in your build
+directory. You may need to adjust the path when calling GDB.
+
+Connect to the GDB server like this:
+
+.. code-block:: console
+
+    (gdb) target extended-remote :3333
+    Remote debugging using :3333
+    0x27fa9ac6 in ?? ()
+    (gdb)
+
+This is fine for debugging before U-Boot relocates itself.
+
+For debugging U-Boot after relocation you need to indicate the relocation
+address to GDB. You can retrieve the relocation address from the U-Boot shell
+with the command *bdinfo*:
+
+.. code-block:: console
+
+    U-Boot> bdinfo
+    boot_params = 0x20000100
+    DRAM bank   = 0x00000000
+    -> start    = 0x20000000
+    -> size     = 0x08000000
+    flashstart  = 0x00000000
+    flashsize   = 0x00000000
+    flashoffset = 0x00000000
+    baudrate    = 115200 bps
+    relocaddr   = 0x27f7a000
+    reloc off   = 0x0607a000
+    Build       = 32-bit
+    current eth = ethernet@f8008000
+    ethaddr     = 00:50:c2:31:58:d4
+    IP addr     = <NULL>
+    fdt_blob    = 0x27b36060
+    new_fdt     = 0x27b36060
+    fdt_size    = 0x00003e40
+    lmb_dump_all:
+     memory.cnt = 0x1 / max = 0x10
+     memory[0]      [0x20000000-0x27ffffff], 0x08000000 bytes flags: 0
+     reserved.cnt = 0x1 / max = 0x10
+     reserved[0]    [0x27b31d00-0x27ffffff], 0x004ce300 bytes flags: 0
+    devicetree  = separate
+    arch_number = 0x00000000
+    TLB addr    = 0x27ff0000
+    irq_sp      = 0x27b36050
+    sp start    = 0x27b36040
+    Early malloc usage: cd8 / 2000
+
+Look out for the line starting with *relocaddr* which has the address
+you need, ``0x27f7a000`` in this case.
+
+On most architectures (not sandbox, x86, Xtensa) the global data pointer is
+stored in a fixed register:
+
+============ ========
+Architecture Register
+============ ========
+arc          r25
+arm          r9
+arm64        x18
+m68k         d7
+microblaze   r31
+mips         k0
+nios2        gp
+powerpc      r2
+riscv        gp
+sh           r13
+============ ========
+
+On these architecture the relocation address cat be determined by
+dereferencing the global data pointer stored in register, *r9* in the example:
+
+.. code-block:: console
+
+     (gdb) p/x (*(struct global_data*)$r9)->relocaddr
+     $1 = 0x27f7a000
+
+In the GDB shell discard the previously loaded symbol file and add it once
+again with the relocation address like this:
+
+.. code-block:: console
+
+    (gdb) symbol-file
+    Discard symbol table from `/home/adahl/build/u-boot/v2024.04.x/u-boot'? (y or n) y
+    No symbol file now.
+    (gdb) add-symbol-file u-boot 0x27f7a000
+    add symbol table from file "u-boot" at
+            .text_addr = 0x27f7a000
+    (y or n) y
+    Reading symbols from u-boot...
+    (gdb)
+
+You can now use GDB as usual, setting breakpoints, printing backtraces,
+inspecting variables, stepping through the code, etc.
diff --git a/doc/develop/index.rst b/doc/develop/index.rst
index f82e148..f9c4bf8 100644
--- a/doc/develop/index.rst
+++ b/doc/develop/index.rst
@@ -60,6 +60,7 @@
    :maxdepth: 1
 
    crash_dumps
+   gdb
    trace
 
 Packaging
diff --git a/doc/sphinx/requirements.txt b/doc/sphinx/requirements.txt
index 54eb70a..306b05a 100644
--- a/doc/sphinx/requirements.txt
+++ b/doc/sphinx/requirements.txt
@@ -1,18 +1,18 @@
 alabaster==0.7.16
-Babel==2.14.0
-certifi==2023.11.17
+Babel==2.15.0
+certifi==2024.6.2
 charset-normalizer==3.3.2
 docutils==0.20.1
 idna==3.7
 imagesize==1.4.1
 Jinja2==3.1.4
-MarkupSafe==2.1.3
-packaging==23.2
-Pygments==2.17.2
-requests==2.32.2
+MarkupSafe==2.1.5
+packaging==24.1
+Pygments==2.18.0
+requests==2.32.3
 six==1.16.0
 snowballstemmer==2.2.0
-Sphinx==7.2.6
+Sphinx==7.3.7
 sphinx-prompt==1.8.0
 sphinx-rtd-theme==2.0.0
 sphinxcontrib-applehelp==1.0.8
@@ -22,4 +22,4 @@
 sphinxcontrib-jsmath==1.0.1
 sphinxcontrib-qthelp==1.0.7
 sphinxcontrib-serializinghtml==1.1.10
-urllib3==2.1.0
+urllib3==2.2.1
diff --git a/doc/usage/fit/source_file_format.rst b/doc/usage/fit/source_file_format.rst
index 7727ab7..15990e3 100644
--- a/doc/usage/fit/source_file_format.rst
+++ b/doc/usage/fit/source_file_format.rst
@@ -254,9 +254,6 @@
     zstd                  zstd compressed
     ====================  ==================
 
-data-size
-    size of the data in bytes
-
 
 Conditionally mandatory property
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -276,6 +273,9 @@
     not relative to the loading of the FIT. This is mandatory if external data
     used with a fixed address.
 
+data-size
+    Size of the data in bytes. This is mandatory if external data is used.
+
 os
     OS name, mandatory for types "kernel". Valid OS names are:
 
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 4691612..3998ffc 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -640,7 +640,11 @@
 	extent_type = btrfs_file_extent_type(leaf, fi);
 	if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
 		ret = btrfs_read_extent_inline(path, fi, buf);
-		memcpy(dest, buf + page_off, min(page_len, ret));
+		if (ret < 0) {
+			free(buf);
+			return ret;
+		}
+		memcpy(dest, buf + page_off, min3(page_len, ret, len));
 		free(buf);
 		return len;
 	}
@@ -652,7 +656,7 @@
 		free(buf);
 		return ret;
 	}
-	memcpy(dest, buf + page_off, page_len);
+	memcpy(dest, buf + page_off, min(page_len, len));
 	free(buf);
 	return len;
 }
diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index a75b5a3..8dfb1bc 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -18,6 +18,7 @@
 
 #include <efi_api.h>
 #include <tpm-v2.h>
+#include <tpm_tcg2.h>
 
 /* TPMV2 only */
 #define TCG2_EVENT_LOG_FORMAT_TCG_2 0x00000002
@@ -25,14 +26,6 @@
 #define PE_COFF_IMAGE 0x0000000000000010
 
 #define EFI_TCG2_MAX_PCR_INDEX 23
-
-/* Algorithm Registry */
-#define EFI_TCG2_BOOT_HASH_ALG_SHA1    0x00000001
-#define EFI_TCG2_BOOT_HASH_ALG_SHA256  0x00000002
-#define EFI_TCG2_BOOT_HASH_ALG_SHA384  0x00000004
-#define EFI_TCG2_BOOT_HASH_ALG_SHA512  0x00000008
-#define EFI_TCG2_BOOT_HASH_ALG_SM3_256 0x00000010
-
 #define EFI_TCG2_FINAL_EVENTS_TABLE_VERSION 1
 
 #define TPM2_EVENT_LOG_SIZE CONFIG_EFI_TCG2_PROTOCOL_EVENTLOG_SIZE
diff --git a/include/fdt_support.h b/include/fdt_support.h
index 4b71b89..741e236 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -463,4 +463,14 @@
 #ifdef CONFIG_CMD_PSTORE
 void fdt_fixup_pstore(void *blob);
 #endif
+
+/**
+ * fdt_kaslrseed() - create a 'kaslr-seed' node in chosen
+ *
+ * @blob:	fdt blob
+ * @overwrite:	do not overwrite existing non-zero node unless true
+ * Return:	0 if OK, -ve on error
+ */
+int fdt_kaslrseed(void *blob, bool overwrite);
+
 #endif /* ifndef __FDT_SUPPORT_H */
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index c9d5cb6..4fd19c5 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -55,59 +55,6 @@
 #define TPM2_PT_MAX_COMMAND_SIZE	(u32)(TPM2_PT_FIXED + 30)
 #define TPM2_PT_MAX_RESPONSE_SIZE	(u32)(TPM2_PT_FIXED + 31)
 
-/*
- * event types, cf.
- * "TCG Server Management Domain Firmware Profile Specification",
- * rev 1.00, 2020-05-01
- */
-#define EV_POST_CODE			((u32)0x00000001)
-#define EV_NO_ACTION			((u32)0x00000003)
-#define EV_SEPARATOR			((u32)0x00000004)
-#define EV_ACTION			((u32)0x00000005)
-#define EV_TAG				((u32)0x00000006)
-#define EV_S_CRTM_CONTENTS		((u32)0x00000007)
-#define EV_S_CRTM_VERSION		((u32)0x00000008)
-#define EV_CPU_MICROCODE		((u32)0x00000009)
-#define EV_PLATFORM_CONFIG_FLAGS	((u32)0x0000000A)
-#define EV_TABLE_OF_DEVICES		((u32)0x0000000B)
-#define EV_COMPACT_HASH			((u32)0x0000000C)
-
-/*
- * event types, cf.
- * "TCG PC Client Platform Firmware Profile Specification", Family "2.0"
- * Level 00 Version 1.05 Revision 23, May 7, 2021
- */
-#define EV_EFI_EVENT_BASE			((u32)0x80000000)
-#define EV_EFI_VARIABLE_DRIVER_CONFIG		((u32)0x80000001)
-#define EV_EFI_VARIABLE_BOOT			((u32)0x80000002)
-#define EV_EFI_BOOT_SERVICES_APPLICATION	((u32)0x80000003)
-#define EV_EFI_BOOT_SERVICES_DRIVER		((u32)0x80000004)
-#define EV_EFI_RUNTIME_SERVICES_DRIVER		((u32)0x80000005)
-#define EV_EFI_GPT_EVENT			((u32)0x80000006)
-#define EV_EFI_ACTION				((u32)0x80000007)
-#define EV_EFI_PLATFORM_FIRMWARE_BLOB		((u32)0x80000008)
-#define EV_EFI_HANDOFF_TABLES			((u32)0x80000009)
-#define EV_EFI_PLATFORM_FIRMWARE_BLOB2		((u32)0x8000000A)
-#define EV_EFI_HANDOFF_TABLES2			((u32)0x8000000B)
-#define EV_EFI_VARIABLE_BOOT2			((u32)0x8000000C)
-#define EV_EFI_HCRTM_EVENT			((u32)0x80000010)
-#define EV_EFI_VARIABLE_AUTHORITY		((u32)0x800000E0)
-#define EV_EFI_SPDM_FIRMWARE_BLOB		((u32)0x800000E1)
-#define EV_EFI_SPDM_FIRMWARE_CONFIG		((u32)0x800000E2)
-
-#define EFI_CALLING_EFI_APPLICATION         \
-	"Calling EFI Application from Boot Option"
-#define EFI_RETURNING_FROM_EFI_APPLICATION  \
-	"Returning from EFI Application from Boot Option"
-#define EFI_EXIT_BOOT_SERVICES_INVOCATION   \
-	"Exit Boot Services Invocation"
-#define EFI_EXIT_BOOT_SERVICES_FAILED       \
-	"Exit Boot Services Returned with Failure"
-#define EFI_EXIT_BOOT_SERVICES_SUCCEEDED    \
-	"Exit Boot Services Returned with Success"
-#define EFI_DTB_EVENT_STRING \
-	"DTB DATA"
-
 /* TPMS_TAGGED_PROPERTY Structure */
 struct tpms_tagged_property {
 	u32 property;
@@ -150,23 +97,6 @@
 } __packed;
 
 /**
- * SHA1 Event Log Entry Format
- *
- * @pcr_index:	PCRIndex event extended to
- * @event_type:	Type of event (see EFI specs)
- * @digest:	Value extended into PCR index
- * @event_size:	Size of event
- * @event:	Event data
- */
-struct tcg_pcr_event {
-	u32 pcr_index;
-	u32 event_type;
-	u8 digest[TPM2_SHA1_DIGEST_SIZE];
-	u32 event_size;
-	u8 event[];
-} __packed;
-
-/**
  * Definition of TPMU_HA Union
  */
 union tpmu_ha {
@@ -200,67 +130,6 @@
 } __packed;
 
 /**
- * Crypto Agile Log Entry Format
- *
- * @pcr_index:	PCRIndex event extended to
- * @event_type:	Type of event
- * @digests:	List of digestsextended to PCR index
- * @event_size: Size of the event data
- * @event:	Event data
- */
-struct tcg_pcr_event2 {
-	u32 pcr_index;
-	u32 event_type;
-	struct tpml_digest_values digests;
-	u32 event_size;
-	u8 event[];
-} __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.
@@ -409,48 +278,40 @@
 #define TCG2_BOOT_HASH_ALG_SM3_256 0x00000010
 
 static const struct digest_info hash_algo_list[] = {
+#if IS_ENABLED(CONFIG_SHA1)
 	{
 		"sha1",
 		TPM2_ALG_SHA1,
 		TCG2_BOOT_HASH_ALG_SHA1,
 		TPM2_SHA1_DIGEST_SIZE,
 	},
+#endif
+#if IS_ENABLED(CONFIG_SHA256)
 	{
 		"sha256",
 		TPM2_ALG_SHA256,
 		TCG2_BOOT_HASH_ALG_SHA256,
 		TPM2_SHA256_DIGEST_SIZE,
 	},
+#endif
+#if IS_ENABLED(CONFIG_SHA384)
 	{
 		"sha384",
 		TPM2_ALG_SHA384,
 		TCG2_BOOT_HASH_ALG_SHA384,
 		TPM2_SHA384_DIGEST_SIZE,
 	},
+#endif
+#if IS_ENABLED(CONFIG_SHA512)
 	{
 		"sha512",
 		TPM2_ALG_SHA512,
 		TCG2_BOOT_HASH_ALG_SHA512,
 		TPM2_SHA512_DIGEST_SIZE,
 	},
+#endif
 };
 
-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;
-	}
-}
-
 /* NV index attributes */
 enum tpm_index_attrs {
 	TPMA_NV_PPWRITE		= 1UL << 0,
@@ -531,188 +392,6 @@
 };
 
 /**
- * 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
@@ -835,14 +514,11 @@
  * 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
+ * @pcrs:		struct tpml_pcr_selection of available PCRs
  *
  * @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);
+int tpm2_get_pcr_info(struct udevice *dev, struct tpml_pcr_selection *pcrs);
 
 /**
  * Issue a TPM2_DictionaryAttackLockReset command.
@@ -1029,11 +705,47 @@
 const char *tpm2_algorithm_name(enum tpm2_algorithms);
 
 /**
- * tpm2_algorithm_to_mask() - Get a TCG hash mask for algorithm
+ * tpm2_algorithm_to_len() - Return an algorithm length for supported algorithm id
  *
- * @hash_alg: TCG defined algorithm
- * Return: TCG hashing algorithm bitmaps (or 0 if algo not supported)
+ * @algorithm_id: algorithm defined in enum tpm2_algorithms
+ * Return: len or 0 if not supported
+ */
+u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo);
+
+/*
+ * When measured boot is enabled via EFI or bootX commands all the algorithms
+ * above are selected by our Kconfigs. Due to U-Boots nature of being small there
+ * are cases where we need some functionality from the TPM -- e.g storage or RNG
+ * but we don't want to support measurements.
+ *
+ * The choice of hash algorithms are determined by the platform and the TPM
+ * configuration. Failing to cap a PCR in a bank which the platform left
+ * active is a security vulnerability. It permits the unsealing of secrets
+ * if an attacker can replay a good set of measurements into an unused bank.
+ *
+ * On top of that a previous stage bootloader (e.g TF-A), migh pass an eventlog
+ * since it doesn't have a TPM driver, which U-Boot needs to replace. The algorit h
+ * choice is a compile time option in that case and we need to make sure we conform.
+ *
+ * Add a variable here that sums the supported algorithms U-Boot was compiled
+ * with so we can refuse to do measurements if we don't support all of them
+ */
+
+/**
+ * tpm2_allow_extend() - Check if extending PCRs is allowed and safe
+ *
+ * @dev: TPM device
+ * Return: true if allowed
+ */
+bool tpm2_allow_extend(struct udevice *dev);
+
+/**
+ * tpm2_is_active_pcr() - check the pcr_select. If at least one of the PCRs
+ *			  supports the algorithm add it on the active ones
+ *
+ * @selection: PCR selection structure
+ * Return: True if the algorithm is active
  */
-u32 tpm2_algorithm_to_mask(enum tpm2_algorithms);
+bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection);
 
 #endif /* __TPM_V2_H */
diff --git a/include/tpm_tcg2.h b/include/tpm_tcg2.h
new file mode 100644
index 0000000..6519004
--- /dev/null
+++ b/include/tpm_tcg2.h
@@ -0,0 +1,348 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Defines APIs and structures that adhere to
+ * https://trustedcomputinggroup.org/resource/pc-client-specific-platform-firmware-profile-specification/
+ * https://trustedcomputinggroup.org/resource/tcg-efi-protocol-specification/
+ *
+ * Copyright (c) 2020 Linaro Limited
+ */
+
+#ifndef __TPM_TCG_V2_H
+#define __TPM_TCG_V2_H
+
+#include <tpm-v2.h>
+
+/*
+ * event types, cf.
+ * "TCG Server Management Domain Firmware Profile Specification",
+ * rev 1.00, 2020-05-01
+ */
+#define EV_POST_CODE			((u32)0x00000001)
+#define EV_NO_ACTION			((u32)0x00000003)
+#define EV_SEPARATOR			((u32)0x00000004)
+#define EV_ACTION			((u32)0x00000005)
+#define EV_TAG				((u32)0x00000006)
+#define EV_S_CRTM_CONTENTS		((u32)0x00000007)
+#define EV_S_CRTM_VERSION		((u32)0x00000008)
+#define EV_CPU_MICROCODE		((u32)0x00000009)
+#define EV_PLATFORM_CONFIG_FLAGS	((u32)0x0000000A)
+#define EV_TABLE_OF_DEVICES		((u32)0x0000000B)
+#define EV_COMPACT_HASH			((u32)0x0000000C)
+
+/*
+ * event types, cf.
+ * "TCG PC Client Platform Firmware Profile Specification", Family "2.0"
+ * Level 00 Version 1.05 Revision 23, May 7, 2021
+ */
+#define EV_EFI_EVENT_BASE			((u32)0x80000000)
+#define EV_EFI_VARIABLE_DRIVER_CONFIG		((u32)0x80000001)
+#define EV_EFI_VARIABLE_BOOT			((u32)0x80000002)
+#define EV_EFI_BOOT_SERVICES_APPLICATION	((u32)0x80000003)
+#define EV_EFI_BOOT_SERVICES_DRIVER		((u32)0x80000004)
+#define EV_EFI_RUNTIME_SERVICES_DRIVER		((u32)0x80000005)
+#define EV_EFI_GPT_EVENT			((u32)0x80000006)
+#define EV_EFI_ACTION				((u32)0x80000007)
+#define EV_EFI_PLATFORM_FIRMWARE_BLOB		((u32)0x80000008)
+#define EV_EFI_HANDOFF_TABLES			((u32)0x80000009)
+#define EV_EFI_PLATFORM_FIRMWARE_BLOB2		((u32)0x8000000A)
+#define EV_EFI_HANDOFF_TABLES2			((u32)0x8000000B)
+#define EV_EFI_VARIABLE_BOOT2			((u32)0x8000000C)
+#define EV_EFI_HCRTM_EVENT			((u32)0x80000010)
+#define EV_EFI_VARIABLE_AUTHORITY		((u32)0x800000E0)
+#define EV_EFI_SPDM_FIRMWARE_BLOB		((u32)0x800000E1)
+#define EV_EFI_SPDM_FIRMWARE_CONFIG		((u32)0x800000E2)
+
+#define EFI_CALLING_EFI_APPLICATION         \
+	"Calling EFI Application from Boot Option"
+#define EFI_RETURNING_FROM_EFI_APPLICATION  \
+	"Returning from EFI Application from Boot Option"
+#define EFI_EXIT_BOOT_SERVICES_INVOCATION   \
+	"Exit Boot Services Invocation"
+#define EFI_EXIT_BOOT_SERVICES_FAILED       \
+	"Exit Boot Services Returned with Failure"
+#define EFI_EXIT_BOOT_SERVICES_SUCCEEDED    \
+	"Exit Boot Services Returned with Success"
+#define EFI_DTB_EVENT_STRING \
+	"DTB DATA"
+
+/**
+ *  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;
+
+/**
+ * SHA1 Event Log Entry Format
+ *
+ * @pcr_index:	PCRIndex event extended to
+ * @event_type:	Type of event (see EFI specs)
+ * @digest:	Value extended into PCR index
+ * @event_size:	Size of event
+ * @event:	Event data
+ */
+struct tcg_pcr_event {
+	u32 pcr_index;
+	u32 event_type;
+	u8 digest[TPM2_SHA1_DIGEST_SIZE];
+	u32 event_size;
+	u8 event[];
+} __packed;
+
+/**
+ * tcg2_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 tcg2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
+		      u32 *pcr_banks);
+
+/**
+ * Crypto Agile Log Entry Format
+ *
+ * @pcr_index:	PCRIndex event extended to
+ * @event_type:	Type of event
+ * @digests:	List of digestsextended to PCR index
+ * @event_size: Size of the event data
+ * @event:	Event data
+ */
+struct tcg_pcr_event2 {
+	u32 pcr_index;
+	u32 event_type;
+	struct tpml_digest_values digests;
+	u32 event_size;
+	u8 event[];
+} __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;
+
+#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 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);
+
+/**
+ * tcg2_algorithm_to_mask() - Get a TCG hash mask for algorithm
+ *
+ * @hash_alg: TCG defined algorithm
+ * Return: TCG hashing algorithm bitmaps (or 0 if algo not supported)
+ */
+u32 tcg2_algorithm_to_mask(enum tpm2_algorithms);
+
+#endif /* __TPM_TCG_V2_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 189e6eb..b3baa4b 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -439,9 +439,6 @@
 	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
@@ -449,6 +446,9 @@
 	  command to interactive the TPM. Driver model support is provided
 	  for the low-level TPM interface, but only one TPM is supported at
 	  a time by the TPM library.
+	  For size reasons only SHA1 is selected which is supported on TPM1.2.
+	  If you want a fully functional TPM enable all hashing algorithms.
+	  If you enabled measured boot all hashing algorithms are selected.
 
 config SPL_TPM
 	bool "Trusted Platform Module (TPM) Support in SPL"
diff --git a/lib/Makefile b/lib/Makefile
index 2a76acf..e389ad0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -61,6 +61,8 @@
 obj-$(CONFIG_TPM) += tpm_api.o
 obj-$(CONFIG_TPM_V1) += tpm-v1.o
 obj-$(CONFIG_TPM_V2) += tpm-v2.o
+obj-$(CONFIG_EFI_TCG2_PROTOCOL) += tpm_tcg2.o
+obj-$(CONFIG_MEASURED_BOOT) += tpm_tcg2.o
 endif
 
 obj-$(CONFIG_$(SPL_TPL_)CRC8) += crc8.o
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 1400e67..45f451e 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -16,7 +16,6 @@
 #include <malloc.h>
 #include <smbios.h>
 #include <version_string.h>
-#include <tpm-v2.h>
 #include <tpm_api.h>
 #include <u-boot/hash-checksum.h>
 #include <linux/unaligned/be_byteshift.h>
@@ -277,7 +276,7 @@
 	/* Supported and active PCRs */
 	capability->hash_algorithm_bitmap = 0;
 	capability->active_pcr_banks = 0;
-	ret = tpm2_get_pcr_info(dev, &capability->hash_algorithm_bitmap,
+	ret = tcg2_get_pcr_info(dev, &capability->hash_algorithm_bitmap,
 				&capability->active_pcr_banks,
 				&capability->number_of_pcr_banks);
 	if (ret) {
diff --git a/lib/efi_selftest/efi_selftest_fdt.c b/lib/efi_selftest/efi_selftest_fdt.c
index aa3b13a..a4b0cef 100644
--- a/lib/efi_selftest/efi_selftest_fdt.c
+++ b/lib/efi_selftest/efi_selftest_fdt.c
@@ -227,6 +227,13 @@
 			return EFI_ST_FAILURE;
 		}
 	}
+	if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL_MEASURE_DTB)) {
+		str = get_property(u"kaslr-seed", u"chosen");
+		if (str) {
+			efi_st_error("kaslr-seed with measured fdt\n");
+			return EFI_ST_FAILURE;
+		}
+	}
 	if (IS_ENABLED(CONFIG_RISCV)) {
 		u32 fdt_hartid;
 
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index 91526af..59e6cba 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -10,6 +10,7 @@
 #include <tpm_api.h>
 #include <tpm-common.h>
 #include <tpm-v2.h>
+#include <tpm_tcg2.h>
 #include <u-boot/sha1.h>
 #include <u-boot/sha256.h>
 #include <u-boot/sha512.h>
@@ -22,668 +23,6 @@
 
 #include "tpm-utils.h"
 
-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(hash_algo_list); ++i) {
-		if (!(active & hash_algo_list[i].hash_mask))
-			continue;
-
-		switch (hash_algo_list[i].hash_alg) {
-		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__,
-			       hash_algo_list[i].hash_alg);
-			continue;
-		}
-
-		digest_list->digests[digest_list->count].hash_alg =
-			hash_algo_list[i].hash_alg;
-		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;
-	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(hash_algo_list); ++i) {
-		if (!(active & hash_algo_list[i].hash_mask))
-			continue;
-
-		switch (hash_algo_list[i].hash_alg) {
-		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(hash_algo_list); ++i) {
-		if (!(active & hash_algo_list[i].hash_mask))
-			continue;
-
-		len = hash_algo_list[i].hash_len;
-		if (!len)
-			continue;
-
-		put_unaligned_le16(hash_algo_list[i].hash_alg,
-				   &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(hash_algo_list) ||
-		    (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(hash_algo_list))
-		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 -ENOBUFS;
-
-				/*
-				 * 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] = {
@@ -857,6 +196,11 @@
 
 	if (!digest)
 		return -EINVAL;
+
+	if (!tpm2_allow_extend(dev)) {
+		log_err("Cannot extend PCRs if all the TPM enabled algorithms are not supported\n");
+		return -EINVAL;
+	}
 	/*
 	 * Fill the command structure starting from the first buffer:
 	 *     - the digest
@@ -1056,48 +400,25 @@
 	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)
+int tpm2_get_pcr_info(struct udevice *dev, struct tpml_pcr_selection *pcrs)
 {
 	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);
+	pcrs->count = get_unaligned_be32(response);
 	/*
-	 * We only support 5 algorithms for now so check against that
+	 * We only support 4 algorithms for now so check against that
 	 * instead of TPM2_NUM_PCR_BANKS
 	 */
-	if (pcrs.count > ARRAY_SIZE(hash_algo_list) ||
-	    pcrs.count < 1) {
-		printf("%s: too many pcrs: %u\n", __func__, pcrs.count);
+	if (pcrs->count > 4 || pcrs->count < 1) {
+		printf("%s: too many pcrs: %u\n", __func__, pcrs->count);
 		return -EMSGSIZE;
 	}
 
@@ -1105,7 +426,7 @@
 	if (ret)
 		return ret;
 
-	for (i = 0; i < pcrs.count; i++) {
+	for (i = 0; i < pcrs->count; i++) {
 		/*
 		 * Definition of TPMS_PCR_SELECTION Structure
 		 * hash: u16
@@ -1125,35 +446,20 @@
 			hash_offset + offsetof(struct tpms_pcr_selection,
 					       pcr_select);
 
-		pcrs.selection[i].hash =
+		pcrs->selection[i].hash =
 			get_unaligned_be16(response + hash_offset);
-		pcrs.selection[i].size_of_select =
+		pcrs->selection[i].size_of_select =
 			__get_unaligned_be(response + size_select_offset);
-		if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX) {
+		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);
+			       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);
+		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;
 }
 
@@ -1541,6 +847,18 @@
 	return 0;
 }
 
+bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection)
+{
+	int i;
+
+	for (i = 0; i < selection->size_of_select; i++) {
+		if (selection->pcr_select[i])
+			return true;
+	}
+
+	return false;
+}
+
 enum tpm2_algorithms tpm2_name_to_algorithm(const char *name)
 {
 	size_t i;
@@ -1566,14 +884,33 @@
 	return "";
 }
 
-u32 tpm2_algorithm_to_mask(enum tpm2_algorithms algo)
+u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo)
 {
 	size_t i;
 
-	for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
+	for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
 		if (hash_algo_list[i].hash_alg == algo)
-			return hash_algo_list[i].hash_mask;
+			return hash_algo_list[i].hash_len;
 	}
 
 	return 0;
 }
+
+bool tpm2_allow_extend(struct udevice *dev)
+{
+	struct tpml_pcr_selection pcrs;
+	size_t i;
+	int rc;
+
+	rc = tpm2_get_pcr_info(dev, &pcrs);
+	if (rc)
+		return false;
+
+	for (i = 0; i < pcrs.count; i++) {
+		if (tpm2_is_active_pcr(&pcrs.selection[i]) &&
+		    !tpm2_algorithm_to_len(pcrs.selection[i].hash))
+			return false;
+	}
+
+	return true;
+}
diff --git a/lib/tpm_tcg2.c b/lib/tpm_tcg2.c
new file mode 100644
index 0000000..7f868cc
--- /dev/null
+++ b/lib/tpm_tcg2.c
@@ -0,0 +1,731 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 Linaro Limited
+ */
+
+#include <dm.h>
+#include <dm/of_access.h>
+#include <tpm_api.h>
+#include <tpm-common.h>
+#include <tpm-v2.h>
+#include <tpm_tcg2.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"
+
+int tcg2_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;
+	size_t i;
+	u32 ret;
+
+	*supported_pcr = 0;
+	*active_pcr = 0;
+	*pcr_banks = 0;
+	memset(response, 0, sizeof(response));
+
+	ret = tpm2_get_pcr_info(dev, &pcrs);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < pcrs.count; i++) {
+		u32 hash_mask = tcg2_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;
+}
+
+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 = tcg2_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(hash_algo_list); ++i) {
+		if (!(active & hash_algo_list[i].hash_mask))
+			continue;
+
+		switch (hash_algo_list[i].hash_alg) {
+		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__,
+			       hash_algo_list[i].hash_alg);
+			continue;
+		}
+
+		digest_list->digests[digest_list->count].hash_alg =
+			hash_algo_list[i].hash_alg;
+		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;
+	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(hash_algo_list); ++i) {
+		if (!(active & hash_algo_list[i].hash_mask))
+			continue;
+
+		switch (hash_algo_list[i].hash_alg) {
+		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(hash_algo_list); ++i) {
+		if (!(active & hash_algo_list[i].hash_mask))
+			continue;
+
+		len = hash_algo_list[i].hash_len;
+		if (!len)
+			continue;
+
+		put_unaligned_le16(hash_algo_list[i].hash_alg,
+				   &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(hash_algo_list) ||
+		    (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(hash_algo_list))
+		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 = tcg2_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 -ENOBUFS;
+
+				/*
+				 * 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;
+}
+
+u32 tcg2_algorithm_to_mask(enum tpm2_algorithms algo)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
+		if (hash_algo_list[i].hash_alg == algo)
+			return hash_algo_list[i].hash_mask;
+	}
+
+	return 0;
+}
+
+__weak void tcg2_platform_startup_error(struct udevice *dev, int rc) {}
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 62f8751..3e68d5a 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -673,7 +673,7 @@
 		-n /chosen -n /config -O dtb | \
 	$(objtree)/tools/fdtgrep -r -O dtb - -o $@ \
 		-P bootph-all -P bootph-pre-ram -P bootph-pre-sram \
-		-P bootph-verify \
+		-P bootph-verify -P bootph-some-ram \
 		$(migrate_all) \
 		$(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS)))
 
diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c
index a0faf5a..e09a929 100644
--- a/test/cmd/fdt.c
+++ b/test/cmd/fdt.c
@@ -1346,6 +1346,10 @@
 	ut_assert_nextlinen("\tu-boot,version = "); /* Ignore the version string */
 	if (env_bootargs)
 		ut_assert_nextline("\tbootargs = \"%s\";", env_bootargs);
+	if (IS_ENABLED(CONFIG_DM_RNG) &&
+	    !IS_ENABLED(CONFIG_MEASURED_BOOT) &&
+	    !IS_ENABLED(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT))
+		ut_assert_nextlinen("\tkaslr-seed = ");
 	ut_assert_nextline("};");
 	ut_assertok(ut_check_console_end(uts));
 
@@ -1362,6 +1366,10 @@
 	ut_assert_nextlinen("\tu-boot,version = "); /* Ignore the version string */
 	if (env_bootargs)
 		ut_assert_nextline("\tbootargs = \"%s\";", env_bootargs);
+	if (IS_ENABLED(CONFIG_DM_RNG) &&
+	    !IS_ENABLED(CONFIG_MEASURED_BOOT) &&
+	    !IS_ENABLED(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT))
+		ut_assert_nextlinen("\tkaslr-seed = ");
 	ut_assert_nextline("};");
 	ut_assertok(ut_check_console_end(uts));