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));