All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v9 0/6] tpm: Support boot measurements
@ 2023-03-08 21:25 Eddie James
  2023-03-08 21:25 ` [PATCH v9 1/6] tpm: Fix spelling for tpmu_ha union Eddie James
                   ` (5 more replies)
  0 siblings, 6 replies; 16+ messages in thread
From: Eddie James @ 2023-03-08 21:25 UTC (permalink / raw)
  To: u-boot; +Cc: eajames, sjg, ilias.apalodimas, xypron.glpk, joel

This series adds support for measuring the boot images more generically
than the existing EFI support. Several EFI functions have been moved to
the TPM layer. The series includes optional measurement from the bootm 
command.
A new test case has been added for the bootm measurement to test the new
path, and the sandbox TPM2 driver has been updated to support this use
case.
This series is based on Ilias' auto-startup series and Simon's additions.

Changes since v8:
 - Fix a sandbox driver off-by-one error in checking the property type.
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log and a configuration option
   for systems to select that for the bootm measurement. This would only
   be selected for systems that know that U-Boot is the first stage
   bootloader. This is necessary because the reserved memory region may
   persist through resets and so U-Boot attempts to append to the
   previous boot's log.

Changes since v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Re-ordered the patches to put the sandbox TPM driver patch second
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs
 - Remove the !SANDBOX dependency for EFI TCG2
 - Only compile in the measurement u-boot command when CONFIG_MEASURED_BOOT
   is enabled

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
 - Change PCR indexes for initrd and dtb
 - Drop u8 casting in measurement test
 - Use bullets in documentation

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
    Removed digest_info structure and instead used the common alg_to_mask
      and alg_to_len
    Improved event log parsing in common code to get it equivalent to EFI
      Common code now extends PCR if previous bootloader stage couldn't
      No need to allocate memory in the common code, so EFI copies the
      discovered buffer like it did before
    Rename efi measure_event function

Changes since v2:
 - Add documentation.
 - Changed reserved memory address to the top of the RAM for sandbox dts.
 - Add measure state to booti and bootz.
 - Skip measurement for EFI images that should be measured

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions.
 - Add test case
 - Drop #ifdefs for bootm
 - Add devicetree measurement config option
 - Update sandbox TPM driver

Eddie James (6):
  tpm: Fix spelling for tpmu_ha union
  tpm: sandbox: Update for needed TPM2 capabilities
  tpm: Support boot measurements
  bootm: Support boot measurement
  test: Add sandbox TPM boot measurement
  doc: Add measured boot documentation

 arch/sandbox/dts/sandbox.dtsi  |   13 +
 arch/sandbox/dts/test.dts      |   13 +
 boot/Kconfig                   |   32 +
 boot/bootm.c                   |   74 +++
 cmd/booti.c                    |    1 +
 cmd/bootm.c                    |    2 +
 cmd/bootz.c                    |    1 +
 configs/sandbox_defconfig      |    1 +
 doc/usage/index.rst            |    1 +
 doc/usage/measured_boot.rst    |   23 +
 drivers/tpm/tpm2_tis_sandbox.c |  100 ++-
 include/bootm.h                |   11 +
 include/efi_tcg2.h             |   44 --
 include/image.h                |    1 +
 include/test/suites.h          |    1 +
 include/tpm-v2.h               |  263 +++++++-
 lib/Kconfig                    |    4 +
 lib/efi_loader/Kconfig         |    2 -
 lib/efi_loader/efi_tcg2.c      | 1054 +++-----------------------------
 lib/tpm-v2.c                   |  814 ++++++++++++++++++++++++
 test/boot/Makefile             |    1 +
 test/boot/measurement.c        |   66 ++
 test/cmd_ut.c                  |    4 +
 23 files changed, 1473 insertions(+), 1053 deletions(-)
 create mode 100644 doc/usage/measured_boot.rst
 create mode 100644 test/boot/measurement.c

-- 
2.31.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v9 1/6] tpm: Fix spelling for tpmu_ha union
  2023-03-08 21:25 [PATCH v9 0/6] tpm: Support boot measurements Eddie James
@ 2023-03-08 21:25 ` Eddie James
  2023-03-08 21:25 ` [PATCH v9 2/6] tpm: sandbox: Update for needed TPM2 capabilities Eddie James
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: Eddie James @ 2023-03-08 21:25 UTC (permalink / raw)
  To: u-boot; +Cc: eajames, sjg, ilias.apalodimas, xypron.glpk, joel

tmpu -> tpmu

Signed-off-by: Eddie James <eajames@linux.ibm.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
 include/tpm-v2.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 2b6980e441..6684033deb 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -169,7 +169,7 @@ struct tcg_pcr_event {
 /**
  * Definition of TPMU_HA Union
  */
-union tmpu_ha {
+union tpmu_ha {
 	u8 sha1[TPM2_SHA1_DIGEST_SIZE];
 	u8 sha256[TPM2_SHA256_DIGEST_SIZE];
 	u8 sm3_256[TPM2_SM3_256_DIGEST_SIZE];
@@ -185,7 +185,7 @@ union tmpu_ha {
  */
 struct tpmt_ha {
 	u16 hash_alg;
-	union tmpu_ha digest;
+	union tpmu_ha digest;
 } __packed;
 
 /**
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v9 2/6] tpm: sandbox: Update for needed TPM2 capabilities
  2023-03-08 21:25 [PATCH v9 0/6] tpm: Support boot measurements Eddie James
  2023-03-08 21:25 ` [PATCH v9 1/6] tpm: Fix spelling for tpmu_ha union Eddie James
@ 2023-03-08 21:25 ` Eddie James
  2023-03-16  8:32   ` Ilias Apalodimas
  2023-03-08 21:25 ` [PATCH v9 3/6] tpm: Support boot measurements Eddie James
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Eddie James @ 2023-03-08 21:25 UTC (permalink / raw)
  To: u-boot; +Cc: eajames, sjg, ilias.apalodimas, xypron.glpk, joel

The driver needs to support getting the PCRs in the capabilities
command. Fix various other things and support the max number
of PCRs for TPM2.
Remove the !SANDBOX dependency for EFI TCG2 as well.

Signed-off-by: Eddie James <eajames@linux.ibm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
Changes since v8:
 - Use >= for checking the property against TPM2_PROPERTIES_OFFSET

Changes since v5:
 - Remove the !SANDBOX dependency for EFI TCG2

 drivers/tpm/tpm2_tis_sandbox.c | 100 ++++++++++++++++++++++++---------
 lib/efi_loader/Kconfig         |   2 -
 2 files changed, 72 insertions(+), 30 deletions(-)

diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
index e4004cfcca..d15a28d9fc 100644
--- a/drivers/tpm/tpm2_tis_sandbox.c
+++ b/drivers/tpm/tpm2_tis_sandbox.c
@@ -22,11 +22,6 @@ enum tpm2_hierarchy {
 	TPM2_HIERARCHY_NB,
 };
 
-/* Subset of supported capabilities */
-enum tpm2_capability {
-	TPM_CAP_TPM_PROPERTIES = 0x6,
-};
-
 /* Subset of supported properties */
 #define TPM2_PROPERTIES_OFFSET 0x0000020E
 
@@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property {
 	TPM2_PROPERTY_NB,
 };
 
-#define SANDBOX_TPM_PCR_NB 1
+#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
+#define SANDBOX_TPM_PCR_SELECT_MAX	((SANDBOX_TPM_PCR_NB + 7) / 8)
 
 /*
  * Information about our TPM emulation. This is preserved in the sandbox
@@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
 	int i, j;
 
 	/* TPM2_GetProperty */
-	u32 capability, property, property_count;
+	u32 capability, property, property_count, val;
 
 	/* TPM2_PCR_Read/Extend variables */
 	int pcr_index = 0;
@@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
 	case TPM2_CC_GET_CAPABILITY:
 		capability = get_unaligned_be32(sent);
 		sent += sizeof(capability);
-		if (capability != TPM_CAP_TPM_PROPERTIES) {
-			printf("Sandbox TPM only support TPM_CAPABILITIES\n");
-			return TPM2_RC_HANDLE;
-		}
-
 		property = get_unaligned_be32(sent);
 		sent += sizeof(property);
-		property -= TPM2_PROPERTIES_OFFSET;
-
 		property_count = get_unaligned_be32(sent);
 		sent += sizeof(property_count);
-		if (!property_count ||
-		    property + property_count > TPM2_PROPERTY_NB) {
+
+		switch (capability) {
+		case TPM2_CAP_PCRS:
+			break;
+		case TPM2_CAP_TPM_PROPERTIES:
+			if (!property_count) {
+				rc = TPM2_RC_HANDLE;
+				return sandbox_tpm2_fill_buf(recv, recv_len,
+							     tag, rc);
+			}
+
+			if (property >= TPM2_PROPERTIES_OFFSET &&
+			    ((property - TPM2_PROPERTIES_OFFSET) +
+			     property_count > TPM2_PROPERTY_NB)) {
+				rc = TPM2_RC_HANDLE;
+				return sandbox_tpm2_fill_buf(recv, recv_len,
+							     tag, rc);
+			}
+			break;
+		default:
+			printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
+			       "TPM2_CAP_TPM_PROPERTIES\n");
 			rc = TPM2_RC_HANDLE;
 			return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
 		}
@@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
 		put_unaligned_be32(capability, recv);
 		recv += sizeof(capability);
 
-		/* Give the number of properties that follow */
-		put_unaligned_be32(property_count, recv);
-		recv += sizeof(property_count);
-
-		/* Fill with the properties */
-		for (i = 0; i < property_count; i++) {
-			put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
-					   i, recv);
-			recv += sizeof(property);
-			put_unaligned_be32(tpm->properties[property + i],
-					   recv);
-			recv += sizeof(property);
+		switch (capability) {
+		case TPM2_CAP_PCRS:
+			/* Give the number of algorithms supported - just SHA256 */
+			put_unaligned_be32(1, recv);
+			recv += sizeof(u32);
+
+			/* Give SHA256 algorithm */
+			put_unaligned_be16(TPM2_ALG_SHA256, recv);
+			recv += sizeof(u16);
+
+			/* Select the PCRs supported */
+			*recv = SANDBOX_TPM_PCR_SELECT_MAX;
+			recv++;
+
+			/* Activate all the PCR bits */
+			for (i = 0; i < SANDBOX_TPM_PCR_SELECT_MAX; ++i) {
+				*recv = 0xff;
+				recv++;
+			}
+			break;
+		case TPM2_CAP_TPM_PROPERTIES:
+			/* Give the number of properties that follow */
+			put_unaligned_be32(property_count, recv);
+			recv += sizeof(property_count);
+
+			/* Fill with the properties */
+			for (i = 0; i < property_count; i++) {
+				put_unaligned_be32(property + i, recv);
+				recv += sizeof(property);
+				if (property >= TPM2_PROPERTIES_OFFSET) {
+					val = tpm->properties[(property -
+						TPM2_PROPERTIES_OFFSET) + i];
+				} else {
+					switch (property) {
+					case TPM2_PT_PCR_COUNT:
+						val = SANDBOX_TPM_PCR_NB;
+						break;
+					default:
+						val = 0xffffffff;
+						break;
+					}
+				}
+
+				put_unaligned_be32(val, recv);
+				recv += sizeof(property);
+			}
+			break;
 		}
 
 		/* Add trailing \0 */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c5835e6ef6..605719d2b6 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -333,8 +333,6 @@ config EFI_TCG2_PROTOCOL
 	bool "EFI_TCG2_PROTOCOL support"
 	default y
 	depends on TPM_V2
-	# Sandbox TPM currently fails on GetCapabilities needed for TCG2
-	depends on !SANDBOX
 	select SHA1
 	select SHA256
 	select SHA384
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v9 3/6] tpm: Support boot measurements
  2023-03-08 21:25 [PATCH v9 0/6] tpm: Support boot measurements Eddie James
  2023-03-08 21:25 ` [PATCH v9 1/6] tpm: Fix spelling for tpmu_ha union Eddie James
  2023-03-08 21:25 ` [PATCH v9 2/6] tpm: sandbox: Update for needed TPM2 capabilities Eddie James
@ 2023-03-08 21:25 ` Eddie James
  2023-04-06  9:18   ` Ilias Apalodimas
  2023-03-08 21:25 ` [PATCH v9 4/6] bootm: Support boot measurement Eddie James
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Eddie James @ 2023-03-08 21:25 UTC (permalink / raw)
  To: u-boot; +Cc: eajames, sjg, ilias.apalodimas, xypron.glpk, joel

Add TPM2 functions to support boot measurement. This includes
starting up the TPM, initializing/appending the event log, and
measuring the U-Boot version. Much of the code was used in the
EFI subsystem, so remove it there and use the common functions.

Signed-off-by: Eddie James <eajames@linux.ibm.com>
---
Changes since v8:
 - Fix log parsing again - any data corruption seen while replaying the
   event log was failing the entire measurement.
 - Added an option to ignore the existing log. This should only be used
   for systems that know that U-Boot is the first stage bootloader. This
   is necessary because the reserved memory region may persist through
   resets and so U-Boot attempts to append to the previous boot's log.

Changes since v7:
 - Change name of tcg2_init_log and add more documentation
 - Add a check, when parsing the event log header, to ensure that the
   previous stage bootloader used all the active PCRs.
 - Change name of tcg2_log_find_end
 - Fix the greater than or equal to check to exit the log parsing
 - Make sure log_position is 0 if there is any error discovering the log
 - Return errors parsing the log if the data is corrupt so that we don't
   end up with half a log

Changes since v6:
 - Added Linaro copyright for all the EFI moved code
 - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
   copy any discovered event log to the user's log if passed in.

Changes since v5:
 - Remove unused platform_get_eventlog in efi_tcg2.c
 - First look for tpm_event_log_* properties instead of linux,sml-*
 - Fix efi_tcg2.c compilation
 - Select SHA* configs

Changes since v4:
 - Remove tcg2_measure_event function and check for NULL data in
   tcg2_measure_data
 - Use tpm_auto_startup
 - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function

Changes since v3:
 - Reordered headers
 - Refactored more of EFI code into common code
    Removed digest_info structure and instead used the common alg_to_mask
      and alg_to_len
    Improved event log parsing in common code to get it equivalent to EFI
      Common code now extends PCR if previous bootloader stage couldn't
      No need to allocate memory in the common code, so EFI copies the
      discovered buffer like it did before
    Rename efi measure_event function

Changes since v1:
 - Refactor TPM layer functions to allow EFI system to use them, and
   remove duplicate EFI functions

 include/efi_tcg2.h        |   44 --
 include/tpm-v2.h          |  259 +++++++++
 lib/Kconfig               |    4 +
 lib/efi_loader/efi_tcg2.c | 1054 +++----------------------------------
 lib/tpm-v2.c              |  814 ++++++++++++++++++++++++++++
 5 files changed, 1154 insertions(+), 1021 deletions(-)

diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index b1c3abd097..b21c5cb3dd 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
 #define BOOT_SERVICE_CAPABILITY_MIN \
 	offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
 
-#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
-#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
-
-/**
- *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
- *
- *  @algorithm_id:	algorithm defined in enum tpm2_algorithms
- *  @digest_size:	size of the algorithm
- */
-struct tcg_efi_spec_id_event_algorithm_size {
-	u16      algorithm_id;
-	u16      digest_size;
-} __packed;
-
-/**
- * struct TCG_EfiSpecIDEventStruct - content of the event log header
- *
- * @signature:			signature, set to Spec ID Event03
- * @platform_class:		class defined in TCG ACPI Specification
- *				Client  Common Header.
- * @spec_version_minor:		minor version
- * @spec_version_major:		major version
- * @spec_version_errata:	major version
- * @uintn_size:			size of the efi_uintn_t fields used in various
- *				data structures used in this specification.
- *				0x01 indicates u32  and 0x02  indicates u64
- * @number_of_algorithms:	hashing algorithms used in this event log
- * @digest_sizes:		array of number_of_algorithms pairs
- *				1st member defines the algorithm id
- *				2nd member defines the algorithm size
- */
-struct tcg_efi_spec_id_event {
-	u8 signature[16];
-	u32 platform_class;
-	u8 spec_version_minor;
-	u8 spec_version_major;
-	u8 spec_errata;
-	u8 uintn_size;
-	u32 number_of_algorithms;
-	struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
-} __packed;
-
 /**
  * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log
  * @version:		version number for this structure
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 6684033deb..33dd103767 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -216,6 +216,50 @@ struct tcg_pcr_event2 {
 	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.
  *
@@ -342,6 +386,26 @@ enum tpm2_algorithms {
 	TPM2_ALG_SM3_256	= 0x12,
 };
 
+extern const enum tpm2_algorithms tpm2_supported_algorithms[4];
+
+static inline u16 tpm2_algorithm_to_len(enum tpm2_algorithms a)
+{
+	switch (a) {
+	case TPM2_ALG_SHA1:
+		return TPM2_SHA1_DIGEST_SIZE;
+	case TPM2_ALG_SHA256:
+		return TPM2_SHA256_DIGEST_SIZE;
+	case TPM2_ALG_SHA384:
+		return TPM2_SHA384_DIGEST_SIZE;
+	case TPM2_ALG_SHA512:
+		return TPM2_SHA512_DIGEST_SIZE;
+	default:
+		return 0;
+	}
+}
+
+#define tpm2_algorithm_to_mask(a)	(1 << (a))
+
 /* NV index attributes */
 enum tpm_index_attrs {
 	TPMA_NV_PPWRITE		= 1UL << 0,
@@ -421,6 +485,188 @@ enum {
 	HR_NV_INDEX		= TPM_HT_NV_INDEX << HR_SHIFT,
 };
 
+/**
+ * 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.
  *
@@ -540,6 +786,19 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
 u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
 			void *buf, size_t prop_count);
 
+/**
+ * tpm2_get_pcr_info() - get the supported, active PCRs and number of banks
+ *
+ * @dev:		TPM device
+ * @supported_pcr:	bitmask with the algorithms supported
+ * @active_pcr:		bitmask with the active algorithms
+ * @pcr_banks:		number of PCR banks
+ *
+ * @return 0 on success, code of operation or negative errno on failure
+ */
+int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
+		      u32 *pcr_banks);
+
 /**
  * Issue a TPM2_DictionaryAttackLockReset command.
  *
diff --git a/lib/Kconfig b/lib/Kconfig
index 83e5edd73b..7a146c293f 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -411,6 +411,10 @@ config TPM
 	bool "Trusted Platform Module (TPM) Support"
 	depends on DM
 	imply DM_RNG
+	select SHA1
+	select SHA256
+	select SHA384
+	select SHA512
 	help
 	  This enables support for TPMs which can be used to provide security
 	  features for your board. The TPM can be connected via LPC or I2C
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index a83ae7a46c..5f0f4b5dd2 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -66,35 +66,6 @@ static bool tcg2_efi_app_invoked;
 static const efi_guid_t efi_guid_tcg2_protocol = EFI_TCG2_PROTOCOL_GUID;
 static const efi_guid_t efi_guid_final_events = EFI_TCG2_FINAL_EVENTS_TABLE_GUID;
 
-struct digest_info {
-	u16 hash_alg;
-	u32 hash_mask;
-	u16 hash_len;
-};
-
-static const struct digest_info hash_algo_list[] = {
-	{
-		TPM2_ALG_SHA1,
-		EFI_TCG2_BOOT_HASH_ALG_SHA1,
-		TPM2_SHA1_DIGEST_SIZE,
-	},
-	{
-		TPM2_ALG_SHA256,
-		EFI_TCG2_BOOT_HASH_ALG_SHA256,
-		TPM2_SHA256_DIGEST_SIZE,
-	},
-	{
-		TPM2_ALG_SHA384,
-		EFI_TCG2_BOOT_HASH_ALG_SHA384,
-		TPM2_SHA384_DIGEST_SIZE,
-	},
-	{
-		TPM2_ALG_SHA512,
-		EFI_TCG2_BOOT_HASH_ALG_SHA512,
-		TPM2_SHA512_DIGEST_SIZE,
-	},
-};
-
 struct variable_info {
 	const u16	*name;
 	bool		accept_empty;
@@ -113,46 +84,6 @@ static struct variable_info secure_variables[] = {
 	{u"AuditMode",		false,	1},
 };
 
-#define MAX_HASH_COUNT ARRAY_SIZE(hash_algo_list)
-
-/**
- * alg_to_mask - Get a TCG hash mask for algorithms
- *
- * @hash_alg: TCG defined algorithm
- *
- * @Return: TCG hashing algorithm bitmaps, 0 if the algorithm is not supported
- */
-static u32 alg_to_mask(u16 hash_alg)
-{
-	size_t i;
-
-	for (i = 0; i < MAX_HASH_COUNT; i++) {
-		if (hash_algo_list[i].hash_alg == hash_alg)
-			return hash_algo_list[i].hash_mask;
-	}
-
-	return 0;
-}
-
-/**
- * alg_to_len - Get a TCG hash len for algorithms
- *
- * @hash_alg: TCG defined algorithm
- *
- * @Return: len of chosen algorithm, 0 if the algorithm is not supported
- */
-static u16 alg_to_len(u16 hash_alg)
-{
-	size_t i;
-
-	for (i = 0; i < MAX_HASH_COUNT; i++) {
-		if (hash_algo_list[i].hash_alg == hash_alg)
-			return hash_algo_list[i].hash_len;
-	}
-
-	return 0;
-}
-
 static bool is_tcg2_protocol_installed(void)
 {
 	struct efi_handler *handler;
@@ -162,145 +93,6 @@ static bool is_tcg2_protocol_installed(void)
 	return ret == EFI_SUCCESS;
 }
 
-static u32 tcg_event_final_size(struct tpml_digest_values *digest_list)
-{
-	u32 len;
-	size_t i;
-
-	len = offsetof(struct tcg_pcr_event2, digests);
-	len += offsetof(struct tpml_digest_values, digests);
-	for (i = 0; i < digest_list->count; i++) {
-		u16 hash_alg = digest_list->digests[i].hash_alg;
-
-		len += offsetof(struct tpmt_ha, digest);
-		len += alg_to_len(hash_alg);
-	}
-	len += sizeof(u32); /* tcg_pcr_event2 event_size*/
-
-	return len;
-}
-
-/* tcg2_pcr_extend - Extend PCRs for a TPM2 device for a given tpml_digest_values
- *
- * @dev:		device
- * @digest_list:	list of digest algorithms to extend
- *
- * @Return: status code
- */
-static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
-				    struct tpml_digest_values *digest_list)
-{
-	u32 rc;
-	size_t i;
-
-	for (i = 0; i < digest_list->count; i++) {
-		u32 alg = digest_list->digests[i].hash_alg;
-
-		rc = tpm2_pcr_extend(dev, pcr_index, alg,
-				     (u8 *)&digest_list->digests[i].digest,
-				     alg_to_len(alg));
-		if (rc) {
-			EFI_PRINT("Failed to extend PCR\n");
-			return EFI_DEVICE_ERROR;
-		}
-	}
-
-	return EFI_SUCCESS;
-}
-
-/* tcg2_pcr_read - Read PCRs for a TPM2 device for a given tpml_digest_values
- *
- * @dev:		device
- * @pcr_index:		PCR index
- * @digest_list:	list of digest algorithms to extend
- *
- * @Return: status code
- */
-static efi_status_t tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
-				  struct tpml_digest_values *digest_list)
-{
-	struct tpm_chip_priv *priv;
-	unsigned int updates, pcr_select_min;
-	u32 rc;
-	size_t i;
-
-	priv = dev_get_uclass_priv(dev);
-	if (!priv)
-		return EFI_DEVICE_ERROR;
-
-	pcr_select_min = priv->pcr_select_min;
-
-	for (i = 0; i < digest_list->count; i++) {
-		u16 hash_alg = digest_list->digests[i].hash_alg;
-		u8 *digest = (u8 *)&digest_list->digests[i].digest;
-
-		rc = tpm2_pcr_read(dev, pcr_index, pcr_select_min,
-				   hash_alg, digest, alg_to_len(hash_alg),
-				   &updates);
-		if (rc) {
-			EFI_PRINT("Failed to read PCR\n");
-			return EFI_DEVICE_ERROR;
-		}
-	}
-
-	return EFI_SUCCESS;
-}
-
-/* put_event - Append an agile event to an eventlog
- *
- * @pcr_index:		PCR index
- * @event_type:		type of event added
- * @digest_list:	list of digest algorithms to add
- * @size:		size of event
- * @event:		event to add
- * @log:		log buffer to append the event
- *
- */
-static void put_event(u32 pcr_index, u32 event_type,
-		      struct tpml_digest_values *digest_list, u32 size,
-		      u8 event[], void *log)
-{
-	size_t pos;
-	size_t i;
-	u32 event_size;
-
-	/*
-	 * size refers to the length of event[] only, we need to check against
-	 * the final tcg_pcr_event2 size
-	 */
-	event_size = size + tcg_event_final_size(digest_list);
-
-	put_unaligned_le32(pcr_index, log);
-	pos = offsetof(struct tcg_pcr_event2, event_type);
-	put_unaligned_le32(event_type, (void *)((uintptr_t)log + pos));
-	pos = offsetof(struct tcg_pcr_event2, digests); /* count */
-	put_unaligned_le32(digest_list->count, (void *)((uintptr_t)log + pos));
-
-	pos += offsetof(struct tpml_digest_values, digests);
-	for (i = 0; i < digest_list->count; i++) {
-		u16 hash_alg = digest_list->digests[i].hash_alg;
-		u8 *digest = (u8 *)&digest_list->digests[i].digest;
-
-		put_unaligned_le16(hash_alg, (void *)((uintptr_t)log + pos));
-		pos += offsetof(struct tpmt_ha, digest);
-		memcpy((void *)((uintptr_t)log + pos), digest, alg_to_len(hash_alg));
-		pos += alg_to_len(hash_alg);
-	}
-
-	put_unaligned_le32(size, (void *)((uintptr_t)log + pos));
-	pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
-	memcpy((void *)((uintptr_t)log + pos), event, size);
-	pos += size;
-
-	/*
-	 * make sure the calculated buffer is what we checked against
-	 * This check should never fail.  It checks the code above is
-	 * calculating the right length for the event we are adding
-	 */
-	if (pos != event_size)
-		log_err("Appending to the EventLog failed\n");
-}
-
 /* tcg2_agile_log_append - Append an agile event to an eventlog
  *
  * @pcr_index:		PCR index
@@ -317,7 +109,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
 					  u32 size, u8 event[])
 {
 	void *log = (void *)((uintptr_t)event_log.buffer + event_log.pos);
-	u32 event_size = size + tcg_event_final_size(digest_list);
+	u32 event_size = size + tcg2_event_get_size(digest_list);
 	struct efi_tcg2_final_events_table *final_event;
 	efi_status_t ret = EFI_SUCCESS;
 
@@ -328,7 +120,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
 			event_log.truncated = true;
 			return EFI_VOLUME_FULL;
 		}
-		put_event(pcr_index, event_type, digest_list, size, event, log);
+		tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
 		event_log.pos += event_size;
 		event_log.last_event_size = event_size;
 	}
@@ -341,7 +133,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
 		return EFI_VOLUME_FULL;
 
 	log = (void *)((uintptr_t)event_log.final_buffer + event_log.final_pos);
-	put_event(pcr_index, event_type, digest_list, size, event, log);
+	tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
 
 	final_event = event_log.final_buffer;
 	final_event->number_of_events++;
@@ -350,66 +142,6 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
 	return ret;
 }
 
-/**
- * platform_get_tpm_device() - retrieve TPM device
- *
- * This function retrieves the udevice implementing a TPM
- *
- * This function may be overridden if special initialization is needed.
- *
- * @dev:	udevice
- * Return:	status code
- */
-__weak efi_status_t platform_get_tpm2_device(struct udevice **dev)
-{
-	for_each_tpm_device(*dev) {
-		/* Only support TPMv2 devices */
-		if (tpm_get_version(*dev) == TPM_V2)
-			return EFI_SUCCESS;
-	}
-
-	return EFI_NOT_FOUND;
-}
-
-/**
- * platform_get_eventlog() - retrieve the eventlog address and size
- *
- * This function retrieves the eventlog address and size if the underlying
- * firmware has done some measurements and passed them.
- *
- * This function may be overridden based on platform specific method of
- * passing the eventlog address and size.
- *
- * @dev:	udevice
- * @addr:	eventlog address
- * @sz:		eventlog size
- * Return:	status code
- */
-__weak efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr,
-					  u32 *sz)
-{
-	const u64 *basep;
-	const u32 *sizep;
-
-	basep = dev_read_prop(dev, "tpm_event_log_addr", NULL);
-	if (!basep)
-		return EFI_NOT_FOUND;
-
-	*addr = be64_to_cpup((__force __be64 *)basep);
-
-	sizep = dev_read_prop(dev, "tpm_event_log_size", NULL);
-	if (!sizep)
-		return EFI_NOT_FOUND;
-
-	*sz = be32_to_cpup((__force __be32 *)sizep);
-	if (*sz == 0) {
-		log_debug("event log empty\n");
-		return EFI_NOT_FOUND;
-	}
-
-	return EFI_SUCCESS;
-}
-
 /**
  * tpm2_get_max_command_size() - get the supported max command size
  *
@@ -485,239 +217,6 @@ static int tpm2_get_manufacturer_id(struct udevice *dev, u32 *manufacturer_id)
 	return 0;
 }
 
-/**
- * tpm2_get_num_pcr() - get the number of PCRs
- *
- * @dev:		TPM device
- * @manufacturer_id:	output buffer for the number
- *
- * Return: 0 on success, -1 on error
- */
-static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
-{
-	u8 response[TPM2_RESPONSE_BUFFER_SIZE];
-	u32 ret;
-
-	memset(response, 0, sizeof(response));
-	ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
-				  TPM2_PT_PCR_COUNT, response, 1);
-	if (ret)
-		return -1;
-
-	*num_pcr = get_unaligned_be32(response + properties_offset);
-	if (*num_pcr > TPM2_MAX_PCRS)
-		return -1;
-
-	return 0;
-}
-
-/**
- * is_active_pcr() - Check if a supported algorithm is active
- *
- * @dev:		TPM device
- * @selection:		struct of PCR information
- *
- * Return: true if PCR is active
- */
-static bool is_active_pcr(struct tpms_pcr_selection *selection)
-{
-	int i;
-	/*
-	 * check the pcr_select. If at least one of the PCRs supports the
-	 * algorithm add it on the active ones
-	 */
-	for (i = 0; i < selection->size_of_select; i++) {
-		if (selection->pcr_select[i])
-			return true;
-	}
-
-	return false;
-}
-
-/**
- * tpm2_get_pcr_info() - get the supported, active PCRs and number of banks
- *
- * @dev:		TPM device
- * @supported_pcr:	bitmask with the algorithms supported
- * @active_pcr:		bitmask with the active algorithms
- * @pcr_banks:		number of PCR banks
- *
- * Return: 0 on success, -1 on error
- */
-static int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr,
-			     u32 *active_pcr, u32 *pcr_banks)
-{
-	u8 response[TPM2_RESPONSE_BUFFER_SIZE];
-	struct tpml_pcr_selection pcrs;
-	u32 ret, num_pcr;
-	size_t i;
-	int tpm_ret;
-
-	*supported_pcr = 0;
-	*active_pcr = 0;
-	*pcr_banks = 0;
-	memset(response, 0, sizeof(response));
-	ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
-	if (ret)
-		goto out;
-
-	pcrs.count = get_unaligned_be32(response);
-	/*
-	 * We only support 5 algorithms for now so check against that
-	 * instead of TPM2_NUM_PCR_BANKS
-	 */
-	if (pcrs.count > MAX_HASH_COUNT || pcrs.count < 1)
-		goto out;
-
-	tpm_ret = tpm2_get_num_pcr(dev, &num_pcr);
-	if (tpm_ret)
-		goto out;
-
-	for (i = 0; i < pcrs.count; i++) {
-		/*
-		 * Definition of TPMS_PCR_SELECTION Structure
-		 * hash: u16
-		 * size_of_select: u8
-		 * pcr_select: u8 array
-		 *
-		 * The offsets depend on the number of the device PCRs
-		 * so we have to calculate them based on that
-		 */
-		u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
-			i * offsetof(struct tpms_pcr_selection, pcr_select) +
-			i * ((num_pcr + 7) / 8);
-		u32 size_select_offset =
-			hash_offset + offsetof(struct tpms_pcr_selection,
-					       size_of_select);
-		u32 pcr_select_offset =
-			hash_offset + offsetof(struct tpms_pcr_selection,
-					       pcr_select);
-
-		pcrs.selection[i].hash =
-			get_unaligned_be16(response + hash_offset);
-		pcrs.selection[i].size_of_select =
-			__get_unaligned_be(response + size_select_offset);
-		if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX)
-			goto out;
-		/* copy the array of pcr_select */
-		memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset,
-		       pcrs.selection[i].size_of_select);
-	}
-
-	for (i = 0; i < pcrs.count; i++) {
-		u32 hash_mask = alg_to_mask(pcrs.selection[i].hash);
-
-		if (hash_mask) {
-			*supported_pcr |= hash_mask;
-			if (is_active_pcr(&pcrs.selection[i]))
-				*active_pcr |= hash_mask;
-		} else {
-			EFI_PRINT("Unknown algorithm %x\n", pcrs.selection[i].hash);
-		}
-	}
-
-	*pcr_banks = pcrs.count;
-
-	return 0;
-out:
-	return -1;
-}
-
-/**
- * __get_active_pcr_banks() - returns the currently active PCR banks
- *
- * @active_pcr_banks:		pointer for receiving the bitmap of currently
- *				active PCR banks
- *
- * Return:	status code
- */
-static efi_status_t __get_active_pcr_banks(u32 *active_pcr_banks)
-{
-	struct udevice *dev;
-	u32 active = 0, supported = 0, pcr_banks = 0;
-	efi_status_t ret;
-	int err;
-
-	ret = platform_get_tpm2_device(&dev);
-	if (ret != EFI_SUCCESS)
-		goto out;
-
-	err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
-	if (err) {
-		ret = EFI_DEVICE_ERROR;
-		goto out;
-	}
-
-	*active_pcr_banks = active;
-
-out:
-	return ret;
-}
-
-/* tcg2_create_digest - create a list of digests of the supported PCR banks
- *			for a given memory range
- *
- * @input:		input memory
- * @length:		length of buffer to calculate the digest
- * @digest_list:	list of digests to fill in
- *
- * Return:		status code
- */
-static efi_status_t tcg2_create_digest(const u8 *input, u32 length,
-				       struct tpml_digest_values *digest_list)
-{
-	sha1_context ctx;
-	sha256_context ctx_256;
-	sha512_context ctx_512;
-	u8 final[TPM2_SHA512_DIGEST_SIZE];
-	efi_status_t ret;
-	u32 active;
-	size_t i;
-
-	ret = __get_active_pcr_banks(&active);
-	if (ret != EFI_SUCCESS)
-		return ret;
-
-	digest_list->count = 0;
-	for (i = 0; i < MAX_HASH_COUNT; i++) {
-		u16 hash_alg = hash_algo_list[i].hash_alg;
-
-		if (!(active & alg_to_mask(hash_alg)))
-			continue;
-		switch (hash_alg) {
-		case TPM2_ALG_SHA1:
-			sha1_starts(&ctx);
-			sha1_update(&ctx, input, length);
-			sha1_finish(&ctx, final);
-			break;
-		case TPM2_ALG_SHA256:
-			sha256_starts(&ctx_256);
-			sha256_update(&ctx_256, input, length);
-			sha256_finish(&ctx_256, final);
-			break;
-		case TPM2_ALG_SHA384:
-			sha384_starts(&ctx_512);
-			sha384_update(&ctx_512, input, length);
-			sha384_finish(&ctx_512, final);
-			break;
-		case TPM2_ALG_SHA512:
-			sha512_starts(&ctx_512);
-			sha512_update(&ctx_512, input, length);
-			sha512_finish(&ctx_512, final);
-			break;
-		default:
-			EFI_PRINT("Unsupported algorithm %x\n", hash_alg);
-			return EFI_INVALID_PARAMETER;
-		}
-		digest_list->digests[digest_list->count].hash_alg = hash_alg;
-		memcpy(&digest_list->digests[digest_list->count].digest, final,
-		       (u32)alg_to_len(hash_alg));
-		digest_list->count++;
-	}
-
-	return EFI_SUCCESS;
-}
-
 /**
  * efi_tcg2_get_capability() - protocol capability information and state information
  *
@@ -759,7 +258,7 @@ efi_tcg2_get_capability(struct efi_tcg2_protocol *this,
 	capability->protocol_version.major = 1;
 	capability->protocol_version.minor = 1;
 
-	efi_ret = platform_get_tpm2_device(&dev);
+	efi_ret = tcg2_platform_get_tpm2(&dev);
 	if (efi_ret != EFI_SUCCESS) {
 		capability->supported_event_logs = 0;
 		capability->hash_algorithm_bitmap = 0;
@@ -855,7 +354,7 @@ efi_tcg2_get_eventlog(struct efi_tcg2_protocol *this,
 		goto out;
 	}
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS) {
 		event_log_location = NULL;
 		event_log_last_entry = NULL;
@@ -890,6 +389,7 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size,
 	struct efi_image_regions *regs = NULL;
 	void *new_efi = NULL;
 	u8 hash[TPM2_SHA512_DIGEST_SIZE];
+	struct udevice *dev;
 	efi_status_t ret;
 	u32 active;
 	int i;
@@ -905,16 +405,20 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size,
 		goto out;
 	}
 
-	ret = __get_active_pcr_banks(&active);
+	ret = tcg2_platform_get_tpm2(&dev);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	ret = tcg2_get_active_pcr_banks(dev, &active);
 	if (ret != EFI_SUCCESS) {
 		goto out;
 	}
 
 	digest_list->count = 0;
-	for (i = 0; i < MAX_HASH_COUNT; i++) {
-		u16 hash_alg = hash_algo_list[i].hash_alg;
+	for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); i++) {
+		u16 hash_alg = tpm2_supported_algorithms[i];
 
-		if (!(active & alg_to_mask(hash_alg)))
+		if (!(active & tpm2_algorithm_to_mask(hash_alg)))
 			continue;
 		switch (hash_alg) {
 		case TPM2_ALG_SHA1:
@@ -935,7 +439,7 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size,
 		}
 		digest_list->digests[digest_list->count].hash_alg = hash_alg;
 		memcpy(&digest_list->digests[digest_list->count].digest, hash,
-		       (u32)alg_to_len(hash_alg));
+		       (u32)tpm2_algorithm_to_len(hash_alg));
 		digest_list->count++;
 	}
 
@@ -975,7 +479,7 @@ efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size,
 	if (!is_tcg2_protocol_installed())
 		return EFI_SUCCESS;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		return EFI_SECURITY_VIOLATION;
 
@@ -1084,7 +588,7 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags,
 		goto out;
 	}
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
@@ -1119,7 +623,7 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags,
 		ret = tcg2_hash_pe_image((void *)(uintptr_t)data_to_hash,
 					 data_to_hash_len, &digest_list);
 	} else {
-		ret = tcg2_create_digest((u8 *)(uintptr_t)data_to_hash,
+		ret = tcg2_create_digest(dev, (u8 *)(uintptr_t)data_to_hash,
 					 data_to_hash_len, &digest_list);
 	}
 
@@ -1182,7 +686,7 @@ efi_tcg2_submit_command(struct efi_tcg2_protocol *this,
 		goto out;
 	}
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
@@ -1211,6 +715,7 @@ static efi_status_t EFIAPI
 efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this,
 			      u32 *active_pcr_banks)
 {
+	struct udevice *dev;
 	efi_status_t ret;
 
 	if (!this || !active_pcr_banks) {
@@ -1218,8 +723,12 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this,
 		goto out;
 	}
 
+	ret = tcg2_platform_get_tpm2(&dev);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
 	EFI_ENTRY("%p, %p", this, active_pcr_banks);
-	ret = __get_active_pcr_banks(active_pcr_banks);
+	ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks);
 
 out:
 	return EFI_EXIT(ret);
@@ -1270,397 +779,6 @@ static const struct efi_tcg2_protocol efi_tcg2_protocol = {
 	.get_result_of_set_active_pcr_banks = efi_tcg2_get_result_of_set_active_pcr_banks,
 };
 
-/**
- * parse_event_log_header() -  Parse and verify the event log header fields
- *
- * @buffer:			Pointer to the start of the eventlog
- * @size:			Size of the eventlog
- * @pos:			Return offset of the next event in buffer right
- *				after the event header i.e specID
- *
- * Return:	status code
- */
-static efi_status_t parse_event_log_header(void *buffer, u32 size, u32 *pos)
-{
-	struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
-	int i = 0;
-
-	if (size < sizeof(*event_header))
-		return EFI_COMPROMISED_DATA;
-
-	if (get_unaligned_le32(&event_header->pcr_index) != 0 ||
-	    get_unaligned_le32(&event_header->event_type) != EV_NO_ACTION)
-		return EFI_COMPROMISED_DATA;
-
-	for (i = 0; i < sizeof(event_header->digest); i++) {
-		if (event_header->digest[i])
-			return EFI_COMPROMISED_DATA;
-	}
-
-	*pos += sizeof(*event_header);
-
-	return EFI_SUCCESS;
-}
-
-/**
- * parse_specid_event() -  Parse and verify the specID Event in the eventlog
- *
- * @dev:		udevice
- * @buffer:		Pointer to the start of the eventlog
- * @log_size:		Size of the eventlog
- * @pos:		[in] Offset of specID event in the eventlog buffer
- *			[out] Return offset of the next event in the buffer
- *			after the specID
- * @digest_list:	list of digests in the event
- *
- * Return:		status code
- * @pos			Offset in the eventlog where the specID event ends
- * @digest_list:	list of digests in the event
- */
-static efi_status_t parse_specid_event(struct udevice *dev, void *buffer,
-				       u32 log_size, u32 *pos,
-				       struct tpml_digest_values *digest_list)
-{
-	struct tcg_efi_spec_id_event *spec_event;
-	struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
-	size_t spec_event_size;
-	u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
-	u32 spec_active = 0;
-	u16 hash_alg;
-	u8 vendor_sz;
-	int err, i;
-
-	if (*pos >= log_size || (*pos + sizeof(*spec_event)) > log_size)
-		return EFI_COMPROMISED_DATA;
-
-	/* Check specID event data */
-	spec_event = (struct tcg_efi_spec_id_event *)((uintptr_t)buffer + *pos);
-	/* Check for signature */
-	if (memcmp(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
-		   sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03))) {
-		log_err("specID Event: Signature mismatch\n");
-		return EFI_COMPROMISED_DATA;
-	}
-
-	if (spec_event->spec_version_minor !=
-			TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
-	    spec_event->spec_version_major !=
-			TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
-		return EFI_COMPROMISED_DATA;
-
-	if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
-	    spec_event->number_of_algorithms < 1) {
-		log_err("specID Event: Number of algorithms incorrect\n");
-		return EFI_COMPROMISED_DATA;
-	}
-
-	alg_count = spec_event->number_of_algorithms;
-
-	err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
-	if (err)
-		return EFI_DEVICE_ERROR;
-
-	digest_list->count = 0;
-	/*
-	 * We have to take care that the sequence of algorithms that we record
-	 * in digest_list matches the sequence in eventlog.
-	 */
-	for (i = 0; i < alg_count; i++) {
-		hash_alg =
-		  get_unaligned_le16(&spec_event->digest_sizes[i].algorithm_id);
-
-		if (!(supported & alg_to_mask(hash_alg))) {
-			log_err("specID Event: Unsupported algorithm\n");
-			return EFI_COMPROMISED_DATA;
-		}
-		digest_list->digests[digest_list->count++].hash_alg = hash_alg;
-
-		spec_active |= alg_to_mask(hash_alg);
-	}
-
-	/*
-	 * TCG specification expects the event log to have hashes for all
-	 * active PCR's
-	 */
-	if (spec_active != active) {
-		/*
-		 * Previous stage bootloader should know all the active PCR's
-		 * and use them in the Eventlog.
-		 */
-		log_err("specID Event: All active hash alg not present\n");
-		return EFI_COMPROMISED_DATA;
-	}
-
-	/*
-	 * the size of the spec event and placement of vendor_info_size
-	 * depends on supported algoriths
-	 */
-	spec_event_size =
-		offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
-		alg_count * sizeof(spec_event->digest_sizes[0]);
-
-	if (*pos + spec_event_size >= log_size)
-		return EFI_COMPROMISED_DATA;
-
-	vendor_sz = *(uint8_t *)((uintptr_t)buffer + *pos + spec_event_size);
-
-	spec_event_size += sizeof(vendor_sz) + vendor_sz;
-	*pos += spec_event_size;
-
-	if (get_unaligned_le32(&event_header->event_size) != spec_event_size) {
-		log_err("specID event: header event size mismatch\n");
-		/* Right way to handle this can be to call SetActive PCR's */
-		return EFI_COMPROMISED_DATA;
-	}
-
-	return EFI_SUCCESS;
-}
-
-/**
- * tcg2_parse_event() -  Parse the event in the eventlog
- *
- * @dev:		udevice
- * @buffer:		Pointer to the start of the eventlog
- * @log_size:		Size of the eventlog
- * @offset:		[in] Offset of the event in the eventlog buffer
- *			[out] Return offset of the next event in the buffer
- * @digest_list:	list of digests in the event
- * @pcr			Index of the PCR in the event
- *
- * Return:		status code
- */
-static efi_status_t tcg2_parse_event(struct udevice *dev, void *buffer,
-				     u32 log_size, u32 *offset,
-				     struct tpml_digest_values *digest_list,
-				     u32 *pcr)
-{
-	struct tcg_pcr_event2 *event = NULL;
-	u32 count, size, event_size;
-	size_t pos;
-
-	event_size = tcg_event_final_size(digest_list);
-	if (*offset >= log_size || *offset + event_size > log_size) {
-		log_err("Event exceeds log size\n");
-		return EFI_COMPROMISED_DATA;
-	}
-
-	event = (struct tcg_pcr_event2 *)((uintptr_t)buffer + *offset);
-	*pcr = get_unaligned_le32(&event->pcr_index);
-
-	/* get the count */
-	count = get_unaligned_le32(&event->digests.count);
-	if (count != digest_list->count)
-		return EFI_COMPROMISED_DATA;
-
-	pos = offsetof(struct tcg_pcr_event2, digests);
-	pos += offsetof(struct tpml_digest_values, digests);
-
-	for (int i = 0; i < digest_list->count; i++) {
-		u16 alg;
-		u16 hash_alg = digest_list->digests[i].hash_alg;
-		u8 *digest = (u8 *)&digest_list->digests[i].digest;
-
-		alg = get_unaligned_le16((void *)((uintptr_t)event + pos));
-
-		if (alg != hash_alg)
-			return EFI_COMPROMISED_DATA;
-
-		pos += offsetof(struct tpmt_ha, digest);
-		memcpy(digest, (void *)((uintptr_t)event + pos), alg_to_len(hash_alg));
-		pos += alg_to_len(hash_alg);
-	}
-
-	size = get_unaligned_le32((void *)((uintptr_t)event + pos));
-	event_size += size;
-	pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
-	pos += size;
-
-	/* make sure the calculated buffer is what we checked against */
-	if (pos != event_size)
-		return EFI_COMPROMISED_DATA;
-
-	if (pos > log_size)
-		return EFI_COMPROMISED_DATA;
-
-	*offset += pos;
-
-	return EFI_SUCCESS;
-}
-
-/**
- * tcg2_get_fw_eventlog() -  Get the eventlog address and size
- *
- * If the previous firmware has passed some eventlog, this function get it's
- * location and check for it's validity.
- *
- * @dev:		udevice
- * @log_buffer:		eventlog address
- * @log_sz:		eventlog size
- *
- * Return:	status code
- */
-static efi_status_t tcg2_get_fw_eventlog(struct udevice *dev, void *log_buffer,
-					 size_t *log_sz)
-{
-	struct tpml_digest_values digest_list;
-	void *buffer;
-	efi_status_t ret;
-	u32 pcr, pos;
-	u64 base;
-	u32 sz;
-	bool extend_pcr = false;
-	int i;
-
-	ret = platform_get_eventlog(dev, &base, &sz);
-	if (ret != EFI_SUCCESS)
-		return ret;
-
-	if (sz > TPM2_EVENT_LOG_SIZE)
-		return EFI_VOLUME_FULL;
-
-	buffer = (void *)(uintptr_t)base;
-	pos = 0;
-	/* Parse the eventlog to check for its validity */
-	ret = parse_event_log_header(buffer, sz, &pos);
-	if (ret)
-		return ret;
-
-	ret = parse_specid_event(dev, buffer, sz, &pos, &digest_list);
-	if (ret) {
-		log_err("Error parsing SPEC ID Event\n");
-		return ret;
-	}
-
-	ret = tcg2_pcr_read(dev, 0, &digest_list);
-	if (ret) {
-		log_err("Error reading PCR 0\n");
-		return ret;
-	}
-
-	/*
-	 * If PCR0 is 0, previous firmware didn't have the capability
-	 * to extend the PCR. In this scenario, extend the PCR as
-	 * the eventlog is parsed.
-	 */
-	for (i = 0; i < digest_list.count; i++) {
-		u8 hash_buf[TPM2_SHA512_DIGEST_SIZE] = { 0 };
-		u16 hash_alg = digest_list.digests[i].hash_alg;
-
-		if (!memcmp((u8 *)&digest_list.digests[i].digest, hash_buf,
-			    alg_to_len(hash_alg)))
-			extend_pcr = true;
-	}
-
-	while (pos < sz) {
-		ret = tcg2_parse_event(dev, buffer, sz, &pos, &digest_list,
-				       &pcr);
-		if (ret) {
-			log_err("Error parsing event\n");
-			return ret;
-		}
-		if (extend_pcr) {
-			ret = tcg2_pcr_extend(dev, pcr, &digest_list);
-			if (ret != EFI_SUCCESS) {
-				log_err("Error in extending PCR\n");
-				return ret;
-			}
-
-			/* Clear the digest for next event */
-			for (i = 0; i < digest_list.count; i++) {
-				u16 hash_alg = digest_list.digests[i].hash_alg;
-				u8 *digest =
-				   (u8 *)&digest_list.digests[i].digest;
-
-				memset(digest, 0, alg_to_len(hash_alg));
-			}
-		}
-	}
-
-	memcpy(log_buffer, buffer, sz);
-	*log_sz = sz;
-
-	return ret;
-}
-
-/**
- * create_specid_event() - Create the first event in the eventlog
- *
- * @dev:			tpm device
- * @event_header:		Pointer to the final event header
- * @event_size:			final spec event size
- *
- * Return:	status code
- */
-static efi_status_t create_specid_event(struct udevice *dev, void *buffer,
-					size_t *event_size)
-{
-	struct tcg_efi_spec_id_event *spec_event;
-	size_t spec_event_size;
-	efi_status_t ret = EFI_DEVICE_ERROR;
-	u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
-	int err;
-	size_t i;
-
-	/*
-	 * Create Spec event. This needs to be the first event in the log
-	 * according to the TCG EFI protocol spec
-	 */
-
-	/* Setup specID event data */
-	spec_event = (struct tcg_efi_spec_id_event *)buffer;
-	memcpy(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
-	       sizeof(spec_event->signature));
-	put_unaligned_le32(0, &spec_event->platform_class); /* type client */
-	spec_event->spec_version_minor =
-		TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
-	spec_event->spec_version_major =
-		TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
-	spec_event->spec_errata =
-		TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
-	spec_event->uintn_size = sizeof(efi_uintn_t) / sizeof(u32);
-
-	err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
-
-	if (err)
-		goto out;
-
-	for (i = 0; i < pcr_count; i++) {
-		u16 hash_alg = hash_algo_list[i].hash_alg;
-		u16 hash_len = hash_algo_list[i].hash_len;
-
-		if (active & alg_to_mask(hash_alg)) {
-			put_unaligned_le16(hash_alg,
-					   &spec_event->digest_sizes[alg_count].algorithm_id);
-			put_unaligned_le16(hash_len,
-					   &spec_event->digest_sizes[alg_count].digest_size);
-			alg_count++;
-		}
-	}
-
-	spec_event->number_of_algorithms = alg_count;
-	if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
-	    spec_event->number_of_algorithms < 1)
-		goto out;
-
-	/*
-	 * the size of the spec event and placement of vendor_info_size
-	 * depends on supported algoriths
-	 */
-	spec_event_size =
-		offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
-		spec_event->number_of_algorithms * sizeof(spec_event->digest_sizes[0]);
-	/* no vendor info for us */
-	memset(buffer + spec_event_size, 0, 1);
-	/* add a byte for vendor_info_size in the spec event */
-	spec_event_size += 1;
-	*event_size = spec_event_size;
-
-	return EFI_SUCCESS;
-
-out:
-	return ret;
-}
-
 /**
  * tcg2_uninit - remove the final event table and free efi memory on failures
  */
@@ -1722,7 +840,7 @@ out:
 }
 
 /**
- * tcg2_measure_event() - common function to add event log and extend PCR
+ * measure_event() - common function to add event log and extend PCR
  *
  * @dev:		TPM device
  * @pcr_index:		PCR index
@@ -1732,14 +850,13 @@ out:
  *
  * Return:	status code
  */
-static efi_status_t
-tcg2_measure_event(struct udevice *dev, u32 pcr_index, u32 event_type,
-		   u32 size, u8 event[])
+static efi_status_t measure_event(struct udevice *dev, u32 pcr_index,
+				  u32 event_type, u32 size, u8 event[])
 {
 	struct tpml_digest_values digest_list;
 	efi_status_t ret;
 
-	ret = tcg2_create_digest(event, size, &digest_list);
+	ret = tcg2_create_digest(dev, event, size, &digest_list);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
@@ -1766,9 +883,8 @@ static efi_status_t efi_append_scrtm_version(struct udevice *dev)
 {
 	efi_status_t ret;
 
-	ret = tcg2_measure_event(dev, 0, EV_S_CRTM_VERSION,
-				 strlen(version_string) + 1,
-				 (u8 *)version_string);
+	ret = measure_event(dev, 0, EV_S_CRTM_VERSION,
+			    strlen(version_string) + 1, (u8 *)version_string);
 
 	return ret;
 }
@@ -1784,12 +900,11 @@ static efi_status_t efi_init_event_log(void)
 	 * vendor_info_size is currently set to 0, we need to change the length
 	 * and allocate the flexible array member if this changes
 	 */
-	struct tcg_pcr_event *event_header = NULL;
+	struct tcg2_event_log elog;
 	struct udevice *dev;
-	size_t spec_event_size;
 	efi_status_t ret;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		return ret;
 
@@ -1808,7 +923,6 @@ static efi_status_t efi_init_event_log(void)
 	 * The log header is defined to be in SHA1 event log entry format.
 	 * Setup event header
 	 */
-	event_header =  (struct tcg_pcr_event *)event_log.buffer;
 	event_log.pos = 0;
 	event_log.last_event_size = 0;
 	event_log.get_event_called = false;
@@ -1819,34 +933,20 @@ static efi_status_t efi_init_event_log(void)
 	 * Check if earlier firmware have passed any eventlog. Different
 	 * platforms can use different ways to do so.
 	 */
-	ret = tcg2_get_fw_eventlog(dev, event_log.buffer, &event_log.pos);
+	elog.log = event_log.buffer;
+	elog.log_size = TPM2_EVENT_LOG_SIZE;
+	ret = tcg2_log_prepare_buffer(dev, &elog, false);
+	if (ret != EFI_SUCCESS)
+		goto free_pool;
+
+	event_log.pos = elog.log_position;
+
 	/*
-	 * If earlier firmware hasn't passed any eventlog, go ahead and
-	 * create the eventlog header.
+	 * Add SCRTM version to the log if previous firmmware
+	 * doesn't pass an eventlog.
 	 */
-	if (ret == EFI_NOT_FOUND) {
-		put_unaligned_le32(0, &event_header->pcr_index);
-		put_unaligned_le32(EV_NO_ACTION, &event_header->event_type);
-		memset(&event_header->digest, 0, sizeof(event_header->digest));
-		ret = create_specid_event(dev,
-					  (void *)((uintptr_t)event_log.buffer +
-						   sizeof(*event_header)),
-					  &spec_event_size);
-		if (ret != EFI_SUCCESS)
-			goto free_pool;
-		put_unaligned_le32(spec_event_size, &event_header->event_size);
-		event_log.pos = spec_event_size + sizeof(*event_header);
-		event_log.last_event_size = event_log.pos;
-
-		/*
-		 * Add SCRTM version to the log if previous firmmware
-		 * doesn't pass an eventlog.
-		 */
+	if (!elog.found)
 		ret = efi_append_scrtm_version(dev);
-	}
-
-	if (ret != EFI_SUCCESS)
-		goto free_pool;
 
 	ret = create_final_event();
 	if (ret != EFI_SUCCESS)
@@ -1899,8 +999,8 @@ static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index,
 		memcpy((u16 *)event->unicode_name + event->unicode_name_length,
 		       data, data_size);
 	}
-	ret = tcg2_measure_event(dev, pcr_index, event_type, event_size,
-				 (u8 *)event);
+	ret = measure_event(dev, pcr_index, event_type, event_size,
+			    (u8 *)event);
 	free(event);
 	return ret;
 }
@@ -2011,8 +1111,8 @@ tcg2_measure_smbios(struct udevice *dev,
 
 	smbios_prepare_measurement(entry, smbios_copy);
 
-	ret = tcg2_measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
-				 (u8 *)event);
+	ret = measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
+			    (u8 *)event);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
@@ -2163,7 +1263,7 @@ tcg2_measure_gpt_data(struct udevice *dev,
 		gpt_e = (gpt_entry *)((u8 *)gpt_e + gpt_h->sizeof_partition_entry);
 	}
 
-	ret = tcg2_measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8 *)event);
+	ret = measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8 *)event);
 
 out2:
 	free(gpt_h);
@@ -2217,7 +1317,7 @@ efi_status_t efi_tcg2_measure_dtb(void *dtb)
 	if (!is_tcg2_protocol_installed())
 		return EFI_SUCCESS;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		return EFI_SECURITY_VIOLATION;
 
@@ -2242,7 +1342,7 @@ efi_status_t efi_tcg2_measure_dtb(void *dtb)
 	sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_mem_rsvmap(dtb), rsvmap_size);
 	sha256_finish(&hash_ctx, blob->data + blob->blob_description_size);
 
-	ret = tcg2_measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob);
+	ret = measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob);
 
 	free(blob);
 	return ret;
@@ -2267,7 +1367,7 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
 	if (tcg2_efi_app_invoked)
 		return EFI_SUCCESS;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		return EFI_SECURITY_VIOLATION;
 
@@ -2275,9 +1375,9 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
 	if (ret != EFI_SUCCESS)
 		goto out;
 
-	ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION,
-				 strlen(EFI_CALLING_EFI_APPLICATION),
-				 (u8 *)EFI_CALLING_EFI_APPLICATION);
+	ret = measure_event(dev, 4, EV_EFI_ACTION,
+			    strlen(EFI_CALLING_EFI_APPLICATION),
+			    (u8 *)EFI_CALLING_EFI_APPLICATION);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
@@ -2293,8 +1393,8 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
 		goto out;
 
 	for (pcr_index = 0; pcr_index <= 7; pcr_index++) {
-		ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR,
-					 sizeof(event), (u8 *)&event);
+		ret = measure_event(dev, pcr_index, EV_SEPARATOR,
+				    sizeof(event), (u8 *)&event);
 		if (ret != EFI_SUCCESS)
 			goto out;
 	}
@@ -2317,13 +1417,13 @@ efi_status_t efi_tcg2_measure_efi_app_exit(void)
 	if (!is_tcg2_protocol_installed())
 		return EFI_SUCCESS;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		return ret;
 
-	ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION,
-				 strlen(EFI_RETURNING_FROM_EFI_APPLICATION),
-				 (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION);
+	ret = measure_event(dev, 4, EV_EFI_ACTION,
+			    strlen(EFI_RETURNING_FROM_EFI_APPLICATION),
+			    (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION);
 	return ret;
 }
 
@@ -2348,19 +1448,19 @@ efi_tcg2_notify_exit_boot_services(struct efi_event *event, void *context)
 		goto out;
 	}
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
-	ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
-				 strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
-				 (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
+	ret = measure_event(dev, 5, EV_EFI_ACTION,
+			    strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
+			    (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
-	ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
-				 strlen(EFI_EXIT_BOOT_SERVICES_SUCCEEDED),
-				 (u8 *)EFI_EXIT_BOOT_SERVICES_SUCCEEDED);
+	ret = measure_event(dev, 5, EV_EFI_ACTION,
+			    strlen(EFI_EXIT_BOOT_SERVICES_SUCCEEDED),
+			    (u8 *)EFI_EXIT_BOOT_SERVICES_SUCCEEDED);
 
 out:
 	EFI_EXIT(ret);
@@ -2380,19 +1480,19 @@ efi_status_t efi_tcg2_notify_exit_boot_services_failed(void)
 	if (!is_tcg2_protocol_installed())
 		return EFI_SUCCESS;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
-	ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
-				 strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
-				 (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
+	ret = measure_event(dev, 5, EV_EFI_ACTION,
+			    strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
+			    (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
-	ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
-				 strlen(EFI_EXIT_BOOT_SERVICES_FAILED),
-				 (u8 *)EFI_EXIT_BOOT_SERVICES_FAILED);
+	ret = measure_event(dev, 5, EV_EFI_ACTION,
+			    strlen(EFI_EXIT_BOOT_SERVICES_FAILED),
+			    (u8 *)EFI_EXIT_BOOT_SERVICES_FAILED);
 
 out:
 	return ret;
@@ -2462,7 +1562,7 @@ efi_status_t efi_tcg2_do_initial_measurement(void)
 	if (!is_tcg2_protocol_installed())
 		return EFI_SUCCESS;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS)
 		return EFI_SECURITY_VIOLATION;
 
@@ -2488,7 +1588,7 @@ efi_status_t efi_tcg2_register(void)
 	struct efi_event *event;
 	u32 err;
 
-	ret = platform_get_tpm2_device(&dev);
+	ret = tcg2_platform_get_tpm2(&dev);
 	if (ret != EFI_SUCCESS) {
 		log_warning("Missing TPMv2 device for EFI_TCG_PROTOCOL\n");
 		return EFI_SUCCESS;
diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
index 9ab5b46df1..d22e21985b 100644
--- a/lib/tpm-v2.c
+++ b/lib/tpm-v2.c
@@ -1,16 +1,705 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
+ * Copyright (c) 2023 Linaro Limited
  * Copyright (c) 2018 Bootlin
  * Author: Miquel Raynal <miquel.raynal@bootlin.com>
  */
 
 #include <common.h>
 #include <dm.h>
+#include <dm/of_access.h>
+#include <tpm_api.h>
 #include <tpm-common.h>
 #include <tpm-v2.h>
+#include <u-boot/sha1.h>
+#include <u-boot/sha256.h>
+#include <u-boot/sha512.h>
+#include <version_string.h>
+#include <asm/io.h>
 #include <linux/bitops.h>
+#include <linux/unaligned/be_byteshift.h>
+#include <linux/unaligned/generic.h>
+#include <linux/unaligned/le_byteshift.h>
+
 #include "tpm-utils.h"
 
+const enum tpm2_algorithms tpm2_supported_algorithms[4] = {
+	TPM2_ALG_SHA1,
+	TPM2_ALG_SHA256,
+	TPM2_ALG_SHA384,
+	TPM2_ALG_SHA512,
+};
+
+int tcg2_get_active_pcr_banks(struct udevice *dev, u32 *active_pcr_banks)
+{
+	u32 supported = 0;
+	u32 pcr_banks = 0;
+	u32 active = 0;
+	int rc;
+
+	rc = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
+	if (rc)
+		return rc;
+
+	*active_pcr_banks = active;
+
+	return 0;
+}
+
+u32 tcg2_event_get_size(struct tpml_digest_values *digest_list)
+{
+	u32 len;
+	size_t i;
+
+	len = offsetof(struct tcg_pcr_event2, digests);
+	len += offsetof(struct tpml_digest_values, digests);
+	for (i = 0; i < digest_list->count; ++i) {
+		u16 l = tpm2_algorithm_to_len(digest_list->digests[i].hash_alg);
+
+		if (!l)
+			continue;
+
+		len += l + offsetof(struct tpmt_ha, digest);
+	}
+	len += sizeof(u32);
+
+	return len;
+}
+
+int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length,
+		       struct tpml_digest_values *digest_list)
+{
+	u8 final[sizeof(union tpmu_ha)];
+	sha256_context ctx_256;
+	sha512_context ctx_512;
+	sha1_context ctx;
+	u32 active;
+	size_t i;
+	u32 len;
+	int rc;
+
+	rc = tcg2_get_active_pcr_banks(dev, &active);
+	if (rc)
+		return rc;
+
+	digest_list->count = 0;
+	for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
+		u32 mask =
+			tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
+
+		if (!(active & mask))
+			continue;
+
+		switch (tpm2_supported_algorithms[i]) {
+		case TPM2_ALG_SHA1:
+			sha1_starts(&ctx);
+			sha1_update(&ctx, input, length);
+			sha1_finish(&ctx, final);
+			len = TPM2_SHA1_DIGEST_SIZE;
+			break;
+		case TPM2_ALG_SHA256:
+			sha256_starts(&ctx_256);
+			sha256_update(&ctx_256, input, length);
+			sha256_finish(&ctx_256, final);
+			len = TPM2_SHA256_DIGEST_SIZE;
+			break;
+		case TPM2_ALG_SHA384:
+			sha384_starts(&ctx_512);
+			sha384_update(&ctx_512, input, length);
+			sha384_finish(&ctx_512, final);
+			len = TPM2_SHA384_DIGEST_SIZE;
+			break;
+		case TPM2_ALG_SHA512:
+			sha512_starts(&ctx_512);
+			sha512_update(&ctx_512, input, length);
+			sha512_finish(&ctx_512, final);
+			len = TPM2_SHA512_DIGEST_SIZE;
+			break;
+		default:
+			printf("%s: unsupported algorithm %x\n", __func__,
+			       tpm2_supported_algorithms[i]);
+			continue;
+		}
+
+		digest_list->digests[digest_list->count].hash_alg =
+			tpm2_supported_algorithms[i];
+		memcpy(&digest_list->digests[digest_list->count].digest, final,
+		       len);
+		digest_list->count++;
+	}
+
+	return 0;
+}
+
+void tcg2_log_append(u32 pcr_index, u32 event_type,
+		     struct tpml_digest_values *digest_list, u32 size,
+		     const u8 *event, u8 *log)
+{
+	size_t len;
+	size_t pos;
+	u32 i;
+
+	pos = offsetof(struct tcg_pcr_event2, pcr_index);
+	put_unaligned_le32(pcr_index, log);
+	pos = offsetof(struct tcg_pcr_event2, event_type);
+	put_unaligned_le32(event_type, log + pos);
+	pos = offsetof(struct tcg_pcr_event2, digests) +
+		offsetof(struct tpml_digest_values, count);
+	put_unaligned_le32(digest_list->count, log + pos);
+
+	pos = offsetof(struct tcg_pcr_event2, digests) +
+		offsetof(struct tpml_digest_values, digests);
+	for (i = 0; i < digest_list->count; ++i) {
+		u16 hash_alg = digest_list->digests[i].hash_alg;
+
+		len = tpm2_algorithm_to_len(hash_alg);
+		if (!len)
+			continue;
+
+		pos += offsetof(struct tpmt_ha, hash_alg);
+		put_unaligned_le16(hash_alg, log + pos);
+		pos += offsetof(struct tpmt_ha, digest);
+		memcpy(log + pos, (u8 *)&digest_list->digests[i].digest, len);
+		pos += len;
+	}
+
+	put_unaligned_le32(size, log + pos);
+	pos += sizeof(u32);
+	memcpy(log + pos, event, size);
+}
+
+static int tcg2_log_append_check(struct tcg2_event_log *elog, u32 pcr_index,
+				 u32 event_type,
+				 struct tpml_digest_values *digest_list,
+				 u32 size, const u8 *event)
+{
+	u32 event_size;
+	u8 *log;
+
+	event_size = size + tcg2_event_get_size(digest_list);
+	if (elog->log_position + event_size > elog->log_size) {
+		printf("%s: log too large: %u + %u > %u\n", __func__,
+		       elog->log_position, event_size, elog->log_size);
+		return -ENOBUFS;
+	}
+
+	log = elog->log + elog->log_position;
+	elog->log_position += event_size;
+
+	tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
+
+	return 0;
+}
+
+static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog)
+{
+	struct tcg_efi_spec_id_event *ev;
+	struct tcg_pcr_event *log;
+	u32 event_size;
+	u32 count = 0;
+	u32 log_size;
+	u32 active;
+	u32 mask;
+	size_t i;
+	u16 len;
+	int rc;
+
+	rc = tcg2_get_active_pcr_banks(dev, &active);
+	if (rc)
+		return rc;
+
+	event_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes);
+	for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
+		mask = tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
+
+		if (!(active & mask))
+			continue;
+
+		switch (tpm2_supported_algorithms[i]) {
+		case TPM2_ALG_SHA1:
+		case TPM2_ALG_SHA256:
+		case TPM2_ALG_SHA384:
+		case TPM2_ALG_SHA512:
+			count++;
+			break;
+		default:
+			continue;
+		}
+	}
+
+	event_size += 1 +
+		(sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count);
+	log_size = offsetof(struct tcg_pcr_event, event) + event_size;
+
+	if (log_size > elog->log_size) {
+		printf("%s: log too large: %u > %u\n", __func__, log_size,
+		       elog->log_size);
+		return -ENOBUFS;
+	}
+
+	log = (struct tcg_pcr_event *)elog->log;
+	put_unaligned_le32(0, &log->pcr_index);
+	put_unaligned_le32(EV_NO_ACTION, &log->event_type);
+	memset(&log->digest, 0, sizeof(log->digest));
+	put_unaligned_le32(event_size, &log->event_size);
+
+	ev = (struct tcg_efi_spec_id_event *)log->event;
+	strlcpy((char *)ev->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
+		sizeof(ev->signature));
+	put_unaligned_le32(0, &ev->platform_class);
+	ev->spec_version_minor = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
+	ev->spec_version_major = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
+	ev->spec_errata = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
+	ev->uintn_size = sizeof(size_t) / sizeof(u32);
+	put_unaligned_le32(count, &ev->number_of_algorithms);
+
+	count = 0;
+	for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
+		mask = tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
+
+		if (!(active & mask))
+			continue;
+
+		len = tpm2_algorithm_to_len(tpm2_supported_algorithms[i]);
+		if (!len)
+			continue;
+
+		put_unaligned_le16(tpm2_supported_algorithms[i],
+				   &ev->digest_sizes[count].algorithm_id);
+		put_unaligned_le16(len, &ev->digest_sizes[count].digest_size);
+		count++;
+	}
+
+	*((u8 *)ev + (event_size - 1)) = 0;
+	elog->log_position = log_size;
+
+	return 0;
+}
+
+static int tcg2_replay_eventlog(struct tcg2_event_log *elog,
+				struct udevice *dev,
+				struct tpml_digest_values *digest_list,
+				u32 log_position)
+{
+	const u32 offset = offsetof(struct tcg_pcr_event2, digests) +
+		offsetof(struct tpml_digest_values, digests);
+	u32 event_size;
+	u32 count;
+	u16 algo;
+	u32 pcr;
+	u32 pos;
+	u16 len;
+	u8 *log;
+	int rc;
+	u32 i;
+
+	while (log_position + offset < elog->log_size) {
+		log = elog->log + log_position;
+
+		pos = offsetof(struct tcg_pcr_event2, pcr_index);
+		pcr = get_unaligned_le32(log + pos);
+		pos = offsetof(struct tcg_pcr_event2, event_type);
+		if (!get_unaligned_le32(log + pos))
+			return 0;
+
+		pos = offsetof(struct tcg_pcr_event2, digests) +
+			offsetof(struct tpml_digest_values, count);
+		count = get_unaligned_le32(log + pos);
+		if (count > ARRAY_SIZE(tpm2_supported_algorithms) ||
+		    (digest_list->count && digest_list->count != count))
+			return 0;
+
+		pos = offsetof(struct tcg_pcr_event2, digests) +
+			offsetof(struct tpml_digest_values, digests);
+		for (i = 0; i < count; ++i) {
+			pos += offsetof(struct tpmt_ha, hash_alg);
+			if (log_position + pos + sizeof(u16) >= elog->log_size)
+				return 0;
+
+			algo = get_unaligned_le16(log + pos);
+			pos += offsetof(struct tpmt_ha, digest);
+			switch (algo) {
+			case TPM2_ALG_SHA1:
+			case TPM2_ALG_SHA256:
+			case TPM2_ALG_SHA384:
+			case TPM2_ALG_SHA512:
+				len = tpm2_algorithm_to_len(algo);
+				break;
+			default:
+				return 0;
+			}
+
+			if (digest_list->count) {
+				if (algo != digest_list->digests[i].hash_alg ||
+				    log_position + pos + len >= elog->log_size)
+					return 0;
+
+				memcpy(digest_list->digests[i].digest.sha512,
+				       log + pos, len);
+			}
+
+			pos += len;
+		}
+
+		if (log_position + pos + sizeof(u32) >= elog->log_size)
+			return 0;
+
+		event_size = get_unaligned_le32(log + pos);
+		pos += event_size + sizeof(u32);
+		if (log_position + pos > elog->log_size)
+			return 0;
+
+		if (digest_list->count) {
+			rc = tcg2_pcr_extend(dev, pcr, digest_list);
+			if (rc)
+				return rc;
+		}
+
+		log_position += pos;
+	}
+
+	elog->log_position = log_position;
+	elog->found = true;
+	return 0;
+}
+
+static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
+{
+	struct tpml_digest_values digest_list;
+	struct tcg_efi_spec_id_event *event;
+	struct tcg_pcr_event *log;
+	u32 log_active;
+	u32 calc_size;
+	u32 active;
+	u32 count;
+	u32 evsz;
+	u32 mask;
+	u16 algo;
+	u16 len;
+	int rc;
+	u32 i;
+	u16 j;
+
+	if (elog->log_size <= offsetof(struct tcg_pcr_event, event))
+		return 0;
+
+	log = (struct tcg_pcr_event *)elog->log;
+	if (get_unaligned_le32(&log->pcr_index) != 0 ||
+	    get_unaligned_le32(&log->event_type) != EV_NO_ACTION)
+		return 0;
+
+	for (i = 0; i < sizeof(log->digest); i++) {
+		if (log->digest[i])
+			return 0;
+	}
+
+	evsz = get_unaligned_le32(&log->event_size);
+	if (evsz < offsetof(struct tcg_efi_spec_id_event, digest_sizes) ||
+	    evsz + offsetof(struct tcg_pcr_event, event) > elog->log_size)
+		return 0;
+
+	event = (struct tcg_efi_spec_id_event *)log->event;
+	if (memcmp(event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
+		   sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03)))
+		return 0;
+
+	if (event->spec_version_minor != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
+	    event->spec_version_major != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
+		return 0;
+
+	count = get_unaligned_le32(&event->number_of_algorithms);
+	if (count > ARRAY_SIZE(tpm2_supported_algorithms))
+		return 0;
+
+	calc_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
+		(sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count) +
+		1;
+	if (evsz != calc_size)
+		return 0;
+
+	rc = tcg2_get_active_pcr_banks(dev, &active);
+	if (rc)
+		return rc;
+
+	digest_list.count = 0;
+	log_active = 0;
+
+	for (i = 0; i < count; ++i) {
+		algo = get_unaligned_le16(&event->digest_sizes[i].algorithm_id);
+		mask = tpm2_algorithm_to_mask(algo);
+
+		if (!(active & mask))
+			return 0;
+
+		switch (algo) {
+		case TPM2_ALG_SHA1:
+		case TPM2_ALG_SHA256:
+		case TPM2_ALG_SHA384:
+		case TPM2_ALG_SHA512:
+			len = get_unaligned_le16(&event->digest_sizes[i].digest_size);
+			if (tpm2_algorithm_to_len(algo) != len)
+				return 0;
+			digest_list.digests[digest_list.count++].hash_alg = algo;
+			break;
+		default:
+			return 0;
+		}
+
+		log_active |= mask;
+	}
+
+	/* Ensure the previous firmware extended all the PCRs. */
+	if (log_active != active)
+		return 0;
+
+	/* Read PCR0 to check if previous firmware extended the PCRs or not. */
+	rc = tcg2_pcr_read(dev, 0, &digest_list);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < digest_list.count; ++i) {
+		len = tpm2_algorithm_to_len(digest_list.digests[i].hash_alg);
+		for (j = 0; j < len; ++j) {
+			if (digest_list.digests[i].digest.sha512[j])
+				break;
+		}
+
+		/* PCR is non-zero; it has been extended, so skip extending. */
+		if (j != len) {
+			digest_list.count = 0;
+			break;
+		}
+	}
+
+	return tcg2_replay_eventlog(elog, dev, &digest_list,
+				    offsetof(struct tcg_pcr_event, event) +
+				    evsz);
+}
+
+int tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
+		    struct tpml_digest_values *digest_list)
+{
+	u32 rc;
+	u32 i;
+
+	for (i = 0; i < digest_list->count; i++) {
+		u32 alg = digest_list->digests[i].hash_alg;
+
+		rc = tpm2_pcr_extend(dev, pcr_index, alg,
+				     (u8 *)&digest_list->digests[i].digest,
+				     tpm2_algorithm_to_len(alg));
+		if (rc) {
+			printf("%s: error pcr:%u alg:%08x\n", __func__,
+			       pcr_index, alg);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+int tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
+		  struct tpml_digest_values *digest_list)
+{
+	struct tpm_chip_priv *priv;
+	u32 rc;
+	u32 i;
+
+	priv = dev_get_uclass_priv(dev);
+	if (!priv)
+		return -ENODEV;
+
+	for (i = 0; i < digest_list->count; i++) {
+		u32 alg = digest_list->digests[i].hash_alg;
+		u8 *digest = (u8 *)&digest_list->digests[i].digest;
+
+		rc = tpm2_pcr_read(dev, pcr_index, priv->pcr_select_min, alg,
+				   digest, tpm2_algorithm_to_len(alg), NULL);
+		if (rc) {
+			printf("%s: error pcr:%u alg:%08x\n", __func__,
+			       pcr_index, alg);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+int tcg2_measure_data(struct udevice *dev, struct tcg2_event_log *elog,
+		      u32 pcr_index, u32 size, const u8 *data, u32 event_type,
+		      u32 event_size, const u8 *event)
+{
+	struct tpml_digest_values digest_list;
+	int rc;
+
+	if (data)
+		rc = tcg2_create_digest(dev, data, size, &digest_list);
+	else
+		rc = tcg2_create_digest(dev, event, event_size, &digest_list);
+	if (rc)
+		return rc;
+
+	rc = tcg2_pcr_extend(dev, pcr_index, &digest_list);
+	if (rc)
+		return rc;
+
+	return tcg2_log_append_check(elog, pcr_index, event_type, &digest_list,
+				     event_size, event);
+}
+
+int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
+			    bool ignore_existing_log)
+{
+	struct tcg2_event_log log;
+	int rc;
+
+	elog->log_position = 0;
+	elog->found = false;
+
+	rc = tcg2_platform_get_log(dev, (void **)&log.log, &log.log_size);
+	if (!rc) {
+		log.log_position = 0;
+		log.found = false;
+
+		if (!ignore_existing_log) {
+			rc = tcg2_log_parse(dev, &log);
+			if (rc)
+				return rc;
+		}
+
+		if (elog->log_size) {
+			if (log.found) {
+				if (elog->log_size < log.log_position)
+					return -ENOSPC;
+
+				/*
+				 * Copy the discovered log into the user buffer
+				 * if there's enough space.
+				 */
+				memcpy(elog->log, log.log, log.log_position);
+			}
+
+			unmap_physmem(log.log, MAP_NOCACHE);
+		} else {
+			elog->log = log.log;
+			elog->log_size = log.log_size;
+		}
+
+		elog->log_position = log.log_position;
+		elog->found = log.found;
+	}
+
+	/*
+	 * Initialize the log buffer if no log was discovered and the buffer is
+	 * valid. User's can pass in their own buffer as a fallback if no
+	 * memory region is found.
+	 */
+	if (!elog->found && elog->log_size)
+		rc = tcg2_log_init(dev, elog);
+
+	return rc;
+}
+
+int tcg2_measurement_init(struct udevice **dev, struct tcg2_event_log *elog,
+			  bool ignore_existing_log)
+{
+	int rc;
+
+	rc = tcg2_platform_get_tpm2(dev);
+	if (rc)
+		return rc;
+
+	rc = tpm_auto_start(*dev);
+	if (rc)
+		return rc;
+
+	rc = tcg2_log_prepare_buffer(*dev, elog, ignore_existing_log);
+	if (rc) {
+		tcg2_measurement_term(*dev, elog, true);
+		return rc;
+	}
+
+	rc = tcg2_measure_event(*dev, elog, 0, EV_S_CRTM_VERSION,
+				strlen(version_string) + 1,
+				(u8 *)version_string);
+	if (rc) {
+		tcg2_measurement_term(*dev, elog, true);
+		return rc;
+	}
+
+	return 0;
+}
+
+void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
+			   bool error)
+{
+	u32 event = error ? 0x1 : 0xffffffff;
+	int i;
+
+	for (i = 0; i < 8; ++i)
+		tcg2_measure_event(dev, elog, i, EV_SEPARATOR, sizeof(event),
+				   (const u8 *)&event);
+
+	if (elog->log)
+		unmap_physmem(elog->log, MAP_NOCACHE);
+}
+
+__weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size)
+{
+	const __be32 *addr_prop;
+	const __be32 *size_prop;
+	int asize;
+	int ssize;
+
+	*addr = NULL;
+	*size = 0;
+
+	addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize);
+	if (!addr_prop)
+		addr_prop = dev_read_prop(dev, "linux,sml-base", &asize);
+
+	size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize);
+	if (!size_prop)
+		size_prop = dev_read_prop(dev, "linux,sml-size", &ssize);
+
+	if (addr_prop && size_prop) {
+		u64 a = of_read_number(addr_prop, asize / sizeof(__be32));
+		u64 s = of_read_number(size_prop, ssize / sizeof(__be32));
+
+		*addr = map_physmem(a, s, MAP_NOCACHE);
+		*size = (u32)s;
+	} else {
+		struct ofnode_phandle_args args;
+		phys_addr_t a;
+		phys_size_t s;
+
+		if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
+					       0, &args))
+			return -ENODEV;
+
+		a = ofnode_get_addr_size(args.node, "reg", &s);
+		if (a == FDT_ADDR_T_NONE)
+			return -ENOMEM;
+
+		*addr = map_physmem(a, s, MAP_NOCACHE);
+		*size = (u32)s;
+	}
+
+	return 0;
+}
+
+__weak int tcg2_platform_get_tpm2(struct udevice **dev)
+{
+	for_each_tpm_device(*dev) {
+		if (tpm_get_version(*dev) == TPM_V2)
+			return 0;
+	}
+
+	return -ENODEV;
+}
+
+__weak void tcg2_platform_startup_error(struct udevice *dev, int rc) {}
+
 u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
 {
 	const u8 command_v2[12] = {
@@ -359,6 +1048,131 @@ u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
 	return 0;
 }
 
+static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
+{
+	u8 response[(sizeof(struct tpms_capability_data) -
+		offsetof(struct tpms_capability_data, data))];
+	u32 properties_offset =
+		offsetof(struct tpml_tagged_tpm_property, tpm_property) +
+		offsetof(struct tpms_tagged_property, value);
+	u32 ret;
+
+	memset(response, 0, sizeof(response));
+	ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
+				  TPM2_PT_PCR_COUNT, response, 1);
+	if (ret)
+		return ret;
+
+	*num_pcr = get_unaligned_be32(response + properties_offset);
+	if (*num_pcr > TPM2_MAX_PCRS) {
+		printf("%s: too many pcrs: %u\n", __func__, *num_pcr);
+		return -E2BIG;
+	}
+
+	return 0;
+}
+
+static bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection)
+{
+	int i;
+
+	/*
+	 * check the pcr_select. If at least one of the PCRs supports the
+	 * algorithm add it on the active ones
+	 */
+	for (i = 0; i < selection->size_of_select; i++) {
+		if (selection->pcr_select[i])
+			return true;
+	}
+
+	return false;
+}
+
+int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
+		      u32 *pcr_banks)
+{
+	u8 response[(sizeof(struct tpms_capability_data) -
+		offsetof(struct tpms_capability_data, data))];
+	struct tpml_pcr_selection pcrs;
+	u32 num_pcr;
+	size_t i;
+	u32 ret;
+
+	*supported_pcr = 0;
+	*active_pcr = 0;
+	*pcr_banks = 0;
+	memset(response, 0, sizeof(response));
+	ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
+	if (ret)
+		return ret;
+
+	pcrs.count = get_unaligned_be32(response);
+	/*
+	 * We only support 5 algorithms for now so check against that
+	 * instead of TPM2_NUM_PCR_BANKS
+	 */
+	if (pcrs.count > ARRAY_SIZE(tpm2_supported_algorithms) ||
+	    pcrs.count < 1) {
+		printf("%s: too many pcrs: %u\n", __func__, pcrs.count);
+		return -EMSGSIZE;
+	}
+
+	ret = tpm2_get_num_pcr(dev, &num_pcr);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < pcrs.count; i++) {
+		/*
+		 * Definition of TPMS_PCR_SELECTION Structure
+		 * hash: u16
+		 * size_of_select: u8
+		 * pcr_select: u8 array
+		 *
+		 * The offsets depend on the number of the device PCRs
+		 * so we have to calculate them based on that
+		 */
+		u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
+			i * offsetof(struct tpms_pcr_selection, pcr_select) +
+			i * ((num_pcr + 7) / 8);
+		u32 size_select_offset =
+			hash_offset + offsetof(struct tpms_pcr_selection,
+					       size_of_select);
+		u32 pcr_select_offset =
+			hash_offset + offsetof(struct tpms_pcr_selection,
+					       pcr_select);
+
+		pcrs.selection[i].hash =
+			get_unaligned_be16(response + hash_offset);
+		pcrs.selection[i].size_of_select =
+			__get_unaligned_be(response + size_select_offset);
+		if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX) {
+			printf("%s: pcrs selection too large: %u\n", __func__,
+			       pcrs.selection[i].size_of_select);
+			return -ENOBUFS;
+		}
+		/* copy the array of pcr_select */
+		memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset,
+		       pcrs.selection[i].size_of_select);
+	}
+
+	for (i = 0; i < pcrs.count; i++) {
+		u32 hash_mask = tpm2_algorithm_to_mask(pcrs.selection[i].hash);
+
+		if (hash_mask) {
+			*supported_pcr |= hash_mask;
+			if (tpm2_is_active_pcr(&pcrs.selection[i]))
+				*active_pcr |= hash_mask;
+		} else {
+			printf("%s: unknown algorithm %x\n", __func__,
+			       pcrs.selection[i].hash);
+		}
+	}
+
+	*pcr_banks = pcrs.count;
+
+	return 0;
+}
+
 u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
 {
 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v9 4/6] bootm: Support boot measurement
  2023-03-08 21:25 [PATCH v9 0/6] tpm: Support boot measurements Eddie James
                   ` (2 preceding siblings ...)
  2023-03-08 21:25 ` [PATCH v9 3/6] tpm: Support boot measurements Eddie James
@ 2023-03-08 21:25 ` Eddie James
  2023-08-04 18:10   ` Sean Edmond
  2023-03-08 21:25 ` [PATCH v9 5/6] test: Add sandbox TPM " Eddie James
  2023-03-08 21:25 ` [PATCH v9 6/6] doc: Add measured boot documentation Eddie James
  5 siblings, 1 reply; 16+ messages in thread
From: Eddie James @ 2023-03-08 21:25 UTC (permalink / raw)
  To: u-boot; +Cc: eajames, sjg, ilias.apalodimas, xypron.glpk, joel

Add a configuration option to measure the boot through the bootm
function. Add the measurement state to the booti and bootz paths
as well.

Signed-off-by: Eddie James <eajames@linux.ibm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes since v8:
 - Added a configuration option to select to ignore any existing
   event log. This would only be selected for systems that know
   that U-Boot is the first stage bootloader. This is necessary
   because the reserved memory region may persist through resets
   and so U-Boot attempts to append to the previous boot's log.

Changes since v6:
 - Added comment for bootm_measure
 - Fixed line length in bootm_measure

 boot/Kconfig    | 32 +++++++++++++++++++++
 boot/bootm.c    | 74 +++++++++++++++++++++++++++++++++++++++++++++++++
 cmd/booti.c     |  1 +
 cmd/bootm.c     |  2 ++
 cmd/bootz.c     |  1 +
 include/bootm.h | 11 ++++++++
 include/image.h |  1 +
 7 files changed, 122 insertions(+)

diff --git a/boot/Kconfig b/boot/Kconfig
index 5f491625c8..8119519c9f 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -629,6 +629,38 @@ config LEGACY_IMAGE_FORMAT
 	  loaded. If a board needs the legacy image format support in this
 	  case, enable it here.
 
+config MEASURED_BOOT
+	bool "Measure boot images and configuration to TPM and event log"
+	depends on HASH && TPM_V2
+	help
+	  This option enables measurement of the boot process. Measurement
+	  involves creating cryptographic hashes of the binary images that
+	  are booting and storing them in the TPM. In addition, a log of
+	  these hashes is stored in memory for the OS to verify the booted
+	  images and configuration. Enable this if the OS has configured
+	  some memory area for the event log and you intend to use some
+	  attestation tools on your system.
+
+if MEASURED_BOOT
+	config MEASURE_DEVICETREE
+	bool "Measure the devicetree image"
+	default y if MEASURED_BOOT
+	help
+	  On some platforms, the devicetree is not static as it may contain
+	  random MAC addresses or other such data that changes each boot.
+	  Therefore, it should not be measured into the TPM. In that case,
+	  disable the measurement here.
+
+	config MEASURE_IGNORE_LOG
+	bool "Ignore the existing event log"
+	default n
+	help
+	  On platforms that use an event log memory region that persists
+	  through system resets and are the first stage bootloader, then
+	  this option should be enabled to ignore any existing data in the
+	  event log memory region.
+endif # MEASURED_BOOT
+
 config SUPPORT_RAW_INITRD
 	bool "Enable raw initrd images"
 	help
diff --git a/boot/bootm.c b/boot/bootm.c
index 2eec60ec7b..2685bdbd74 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -22,6 +22,7 @@
 #include <asm/global_data.h>
 #include <asm/io.h>
 #include <linux/sizes.h>
+#include <tpm-v2.h>
 #if defined(CONFIG_CMD_USB)
 #include <usb.h>
 #endif
@@ -659,6 +660,75 @@ int bootm_process_cmdline_env(int flags)
 	return 0;
 }
 
+int bootm_measure(struct bootm_headers *images)
+{
+	int ret = 0;
+
+	/* Skip measurement if EFI is going to do it */
+	if (images->os.os == IH_OS_EFI &&
+	    IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) &&
+	    IS_ENABLED(CONFIG_BOOTM_EFI))
+		return ret;
+
+	if (IS_ENABLED(CONFIG_MEASURED_BOOT)) {
+		struct tcg2_event_log elog;
+		struct udevice *dev;
+		void *initrd_buf;
+		void *image_buf;
+		const char *s;
+		u32 rd_len;
+		bool ign;
+
+		elog.log_size = 0;
+		ign = IS_ENABLED(CONFIG_MEASURE_IGNORE_LOG);
+		ret = tcg2_measurement_init(&dev, &elog, ign);
+		if (ret)
+			return ret;
+
+		image_buf = map_sysmem(images->os.image_start,
+				       images->os.image_len);
+		ret = tcg2_measure_data(dev, &elog, 8, images->os.image_len,
+					image_buf, EV_COMPACT_HASH,
+					strlen("linux") + 1, (u8 *)"linux");
+		if (ret)
+			goto unmap_image;
+
+		rd_len = images->rd_end - images->rd_start;
+		initrd_buf = map_sysmem(images->rd_start, rd_len);
+		ret = tcg2_measure_data(dev, &elog, 9, rd_len, initrd_buf,
+					EV_COMPACT_HASH, strlen("initrd") + 1,
+					(u8 *)"initrd");
+		if (ret)
+			goto unmap_initrd;
+
+		if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) {
+			ret = tcg2_measure_data(dev, &elog, 0, images->ft_len,
+						(u8 *)images->ft_addr,
+						EV_TABLE_OF_DEVICES,
+						strlen("dts") + 1,
+						(u8 *)"dts");
+			if (ret)
+				goto unmap_initrd;
+		}
+
+		s = env_get("bootargs");
+		if (!s)
+			s = "";
+		ret = tcg2_measure_data(dev, &elog, 1, strlen(s) + 1, (u8 *)s,
+					EV_PLATFORM_CONFIG_FLAGS,
+					strlen(s) + 1, (u8 *)s);
+
+unmap_initrd:
+		unmap_sysmem(initrd_buf);
+
+unmap_image:
+		unmap_sysmem(image_buf);
+		tcg2_measurement_term(dev, &elog, ret != 0);
+	}
+
+	return ret;
+}
+
 /**
  * Execute selected states of the bootm command.
  *
@@ -710,6 +780,10 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
 	if (!ret && (states & BOOTM_STATE_FINDOTHER))
 		ret = bootm_find_other(cmdtp, flag, argc, argv);
 
+	if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !ret &&
+	    (states & BOOTM_STATE_MEASURE))
+		bootm_measure(images);
+
 	/* Load the OS */
 	if (!ret && (states & BOOTM_STATE_LOADOS)) {
 		iflag = bootm_disable_interrupts();
diff --git a/cmd/booti.c b/cmd/booti.c
index 6ac39193db..659bb10549 100644
--- a/cmd/booti.c
+++ b/cmd/booti.c
@@ -127,6 +127,7 @@ int do_booti(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
 			      BOOTM_STATE_RAMDISK |
 #endif
+			      BOOTM_STATE_MEASURE |
 			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
 			      BOOTM_STATE_OS_GO,
 			      &images, 1);
diff --git a/cmd/bootm.c b/cmd/bootm.c
index 37c2af96e0..0c4a713e02 100644
--- a/cmd/bootm.c
+++ b/cmd/bootm.c
@@ -161,6 +161,8 @@ int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 		BOOTM_STATE_OS_GO;
 	if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
 		states |= BOOTM_STATE_RAMDISK;
+	if (IS_ENABLED(CONFIG_MEASURED_BOOT))
+		states |= BOOTM_STATE_MEASURE;
 	if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS))
 		states |= BOOTM_STATE_OS_CMDLINE;
 	ret = do_bootm_states(cmdtp, flag, argc, argv, states, &images, 1);
diff --git a/cmd/bootz.c b/cmd/bootz.c
index f1423573d2..87922bfc3c 100644
--- a/cmd/bootz.c
+++ b/cmd/bootz.c
@@ -81,6 +81,7 @@ int do_bootz(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
 			      BOOTM_STATE_RAMDISK |
 #endif
+			      BOOTM_STATE_MEASURE |
 			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
 			      BOOTM_STATE_OS_GO,
 			      &images, 1);
diff --git a/include/bootm.h b/include/bootm.h
index 044a4797ed..76e8e38c82 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -55,6 +55,17 @@ ulong bootm_disable_interrupts(void);
 int bootm_find_images(int flag, int argc, char *const argv[], ulong start,
 		      ulong size);
 
+/*
+ * Measure the boot images. Measurement is the process of hashing some binary
+ * data and storing it into secure memory, i.e. TPM PCRs. In addition, each
+ * measurement is logged into the platform event log such that the operating
+ * system can access it and perform attestation of the boot.
+ *
+ * @images:	The structure containing the various images to boot (linux,
+ *		initrd, dts, etc.)
+ */
+int bootm_measure(struct bootm_headers *images);
+
 int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
 		    char *const argv[], int states, struct bootm_headers *images,
 		    int boot_progress);
diff --git a/include/image.h b/include/image.h
index 7717a4c13d..f7414b5338 100644
--- a/include/image.h
+++ b/include/image.h
@@ -407,6 +407,7 @@ struct bootm_headers {
 #define BOOTM_STATE_OS_FAKE_GO	0x00000200	/* 'Almost' run the OS */
 #define BOOTM_STATE_OS_GO	0x00000400
 #define BOOTM_STATE_PRE_LOAD	0x00000800
+#define BOOTM_STATE_MEASURE	0x00001000
 	int		state;
 
 #if defined(CONFIG_LMB) && !defined(USE_HOSTCC)
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v9 5/6] test: Add sandbox TPM boot measurement
  2023-03-08 21:25 [PATCH v9 0/6] tpm: Support boot measurements Eddie James
                   ` (3 preceding siblings ...)
  2023-03-08 21:25 ` [PATCH v9 4/6] bootm: Support boot measurement Eddie James
@ 2023-03-08 21:25 ` Eddie James
  2023-03-08 21:25 ` [PATCH v9 6/6] doc: Add measured boot documentation Eddie James
  5 siblings, 0 replies; 16+ messages in thread
From: Eddie James @ 2023-03-08 21:25 UTC (permalink / raw)
  To: u-boot; +Cc: eajames, sjg, ilias.apalodimas, xypron.glpk, joel

Use the sandbox TPM driver to measure some boot images in a unit
test case.

Signed-off-by: Eddie James <eajames@linux.ibm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
Changes since v5:
 - Only compile in the measurement u-boot command when
   CONFIG_MEASURED_BOOT is enabled.

 arch/sandbox/dts/sandbox.dtsi | 13 +++++++
 arch/sandbox/dts/test.dts     | 13 +++++++
 configs/sandbox_defconfig     |  1 +
 include/test/suites.h         |  1 +
 test/boot/Makefile            |  1 +
 test/boot/measurement.c       | 66 +++++++++++++++++++++++++++++++++++
 test/cmd_ut.c                 |  4 +++
 7 files changed, 99 insertions(+)
 create mode 100644 test/boot/measurement.c

diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index 7e7fcff6d2..3442be7634 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -4,11 +4,23 @@
  * and sandbox64 builds.
  */
 
+#include <config.h>
 #include <dt-bindings/input/input.h>
 
 #define USB_CLASS_HUB			9
 
 / {
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		event_log: tcg_event_log {
+			no-map;
+			reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+		};
+	};
+
 	binman {
 	};
 
@@ -336,6 +348,7 @@
 
 	tpm2 {
 		compatible = "sandbox,tpm2";
+		memory-region = <&event_log>;
 	};
 
 	triangle {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 9717103f10..7659effa71 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -9,6 +9,7 @@
 
 /dts-v1/;
 
+#include <config.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/gpio/sandbox-gpio.h>
 #include <dt-bindings/input/input.h>
@@ -66,6 +67,17 @@
 		osd0 = "/osd";
 	};
 
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		event_log: tcg_event_log {
+			no-map;
+			reg = <(CFG_SYS_SDRAM_SIZE - 0x2000) 0x2000>;
+		};
+	};
+
 	binman: binman {
 	};
 
@@ -1365,6 +1377,7 @@
 
 	tpm2 {
 		compatible = "sandbox,tpm2";
+		memory-region = <&event_log>;
 	};
 
 	tpm {
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 77ade1f1d8..43b15b8446 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -335,3 +335,4 @@ CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_MEASURED_BOOT=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 7c4960c004..b552fea9a9 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -44,6 +44,7 @@ int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_loadm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 22ed61c8fa..2dbb032a7e 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
 obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
 
 obj-$(CONFIG_EXPO) += expo.o
 
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 0000000000..9db2ed324c
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James <eajames@linux.ibm.com>
+ */
+
+#include <common.h>
+#include <bootm.h>
+#include <malloc.h>
+#include <test/suites.h>
+#include <test/test.h>
+#include <test/ut.h>
+#include <asm/io.h>
+
+#define MEASUREMENT_TEST(_name, _flags)	\
+	UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+	struct bootm_headers images;
+	const size_t size = 1024;
+	u8 *kernel;
+	u8 *initrd;
+	size_t i;
+
+	kernel = malloc(size);
+	initrd = malloc(size);
+
+	images.os.image_start = map_to_sysmem(kernel);
+	images.os.image_len = size;
+
+	images.rd_start = map_to_sysmem(initrd);
+	images.rd_end = images.rd_start + size;
+
+	images.ft_addr = malloc(size);
+	images.ft_len = size;
+
+	env_set("bootargs", "measurement testing");
+
+	for (i = 0; i < size; ++i) {
+		kernel[i] = 0xf0 | (i & 0xf);
+		initrd[i] = (i & 0xf0) | 0xf;
+		images.ft_addr[i] = i & 0xff;
+	}
+
+	ut_assertok(bootm_measure(&images));
+
+	free(images.ft_addr);
+	free(initrd);
+	free(kernel);
+
+	return 0;
+}
+MEASUREMENT_TEST(measure, 0);
+
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc,
+		      char *const argv[])
+{
+	struct unit_test *tests = UNIT_TEST_SUITE_START(measurement_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(measurement_test);
+
+	return cmd_ut_category("measurement", "measurement_test_", tests,
+			       n_ents, argc, argv);
+}
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 409c22bfd2..25b873d0ea 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -96,6 +96,10 @@ static struct cmd_tbl cmd_ut_sub[] = {
 #if CONFIG_IS_ENABLED(UT_UNICODE) && !defined(API_BUILD)
 	U_BOOT_CMD_MKENT(unicode, CONFIG_SYS_MAXARGS, 1, do_ut_unicode, "", ""),
 #endif
+#ifdef CONFIG_MEASURED_BOOT
+	U_BOOT_CMD_MKENT(measurement, CONFIG_SYS_MAXARGS, 1, do_ut_measurement,
+			 "", ""),
+#endif
 #ifdef CONFIG_SANDBOX
 	U_BOOT_CMD_MKENT(compression, CONFIG_SYS_MAXARGS, 1, do_ut_compression,
 			 "", ""),
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v9 6/6] doc: Add measured boot documentation
  2023-03-08 21:25 [PATCH v9 0/6] tpm: Support boot measurements Eddie James
                   ` (4 preceding siblings ...)
  2023-03-08 21:25 ` [PATCH v9 5/6] test: Add sandbox TPM " Eddie James
@ 2023-03-08 21:25 ` Eddie James
  5 siblings, 0 replies; 16+ messages in thread
From: Eddie James @ 2023-03-08 21:25 UTC (permalink / raw)
  To: u-boot; +Cc: eajames, sjg, ilias.apalodimas, xypron.glpk, joel

Briefly describe the feature and specify the requirements.

Signed-off-by: Eddie James <eajames@linux.ibm.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
 doc/usage/index.rst         |  1 +
 doc/usage/measured_boot.rst | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)
 create mode 100644 doc/usage/measured_boot.rst

diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 840c20c934..1cb6988d8a 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -12,6 +12,7 @@ Use U-Boot
    partitions
    cmdline
    semihosting
+   measured_boot
 
 Shell commands
 --------------
diff --git a/doc/usage/measured_boot.rst b/doc/usage/measured_boot.rst
new file mode 100644
index 0000000000..8357b1f480
--- /dev/null
+++ b/doc/usage/measured_boot.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Measured Boot
+=====================
+
+U-Boot can perform a measured boot, the process of hashing various components
+of the boot process, extending the results in the TPM and logging the
+component's measurement in memory for the operating system to consume.
+
+Requirements
+---------------------
+
+* A hardware TPM 2.0 supported by the U-Boot drivers
+* CONFIG_TPM=y
+* CONFIG_MEASURED_BOOT=y
+* Device-tree configuration of the TPM device to specify the memory area
+  for event logging. The TPM device node must either contain a phandle to
+  a reserved memory region or "linux,sml-base" and "linux,sml-size"
+  indicating the address and size of the memory region. An example can be
+  found in arch/sandbox/dts/test.dts
+* The operating system must also be configured to use the memory regions
+  specified in the U-Boot device-tree in order to make use of the event
+  log.
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v9 2/6] tpm: sandbox: Update for needed TPM2 capabilities
  2023-03-08 21:25 ` [PATCH v9 2/6] tpm: sandbox: Update for needed TPM2 capabilities Eddie James
@ 2023-03-16  8:32   ` Ilias Apalodimas
  2023-05-09 13:49     ` Ilias Apalodimas
  0 siblings, 1 reply; 16+ messages in thread
From: Ilias Apalodimas @ 2023-03-16  8:32 UTC (permalink / raw)
  To: Eddie James; +Cc: u-boot, sjg, xypron.glpk, joel

Hi Eddie,

Apologies for the late reply, I am now getting back on this.
There are some failures on the CI wrt to sandbox here [0].  Can you have a
look ?
Also I believe some of the existing tests are wrong because they are
using PCR0 (which is always going to be extended).  Can you also pick up
[1] with your series?


[0] https://source.denx.de/u-boot/custodians/u-boot-tpm/-/pipelines/15471
[1] https://source.denx.de/u-boot/custodians/u-boot-tpm/-/commit/0d28387cac5fafa59e4367d1548e021eeebe2004

Thanks
/Ilias

On Wed, Mar 08, 2023 at 03:25:33PM -0600, Eddie James wrote:
> The driver needs to support getting the PCRs in the capabilities
> command. Fix various other things and support the max number
> of PCRs for TPM2.
> Remove the !SANDBOX dependency for EFI TCG2 as well.
>
> Signed-off-by: Eddie James <eajames@linux.ibm.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> ---
> Changes since v8:
>  - Use >= for checking the property against TPM2_PROPERTIES_OFFSET
>
> Changes since v5:
>  - Remove the !SANDBOX dependency for EFI TCG2
>
>  drivers/tpm/tpm2_tis_sandbox.c | 100 ++++++++++++++++++++++++---------
>  lib/efi_loader/Kconfig         |   2 -
>  2 files changed, 72 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
> index e4004cfcca..d15a28d9fc 100644
> --- a/drivers/tpm/tpm2_tis_sandbox.c
> +++ b/drivers/tpm/tpm2_tis_sandbox.c
> @@ -22,11 +22,6 @@ enum tpm2_hierarchy {
>  	TPM2_HIERARCHY_NB,
>  };
>
> -/* Subset of supported capabilities */
> -enum tpm2_capability {
> -	TPM_CAP_TPM_PROPERTIES = 0x6,
> -};
> -
>  /* Subset of supported properties */
>  #define TPM2_PROPERTIES_OFFSET 0x0000020E
>
> @@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property {
>  	TPM2_PROPERTY_NB,
>  };
>
> -#define SANDBOX_TPM_PCR_NB 1
> +#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
> +#define SANDBOX_TPM_PCR_SELECT_MAX	((SANDBOX_TPM_PCR_NB + 7) / 8)
>
>  /*
>   * Information about our TPM emulation. This is preserved in the sandbox
> @@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
>  	int i, j;
>
>  	/* TPM2_GetProperty */
> -	u32 capability, property, property_count;
> +	u32 capability, property, property_count, val;
>
>  	/* TPM2_PCR_Read/Extend variables */
>  	int pcr_index = 0;
> @@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
>  	case TPM2_CC_GET_CAPABILITY:
>  		capability = get_unaligned_be32(sent);
>  		sent += sizeof(capability);
> -		if (capability != TPM_CAP_TPM_PROPERTIES) {
> -			printf("Sandbox TPM only support TPM_CAPABILITIES\n");
> -			return TPM2_RC_HANDLE;
> -		}
> -
>  		property = get_unaligned_be32(sent);
>  		sent += sizeof(property);
> -		property -= TPM2_PROPERTIES_OFFSET;
> -
>  		property_count = get_unaligned_be32(sent);
>  		sent += sizeof(property_count);
> -		if (!property_count ||
> -		    property + property_count > TPM2_PROPERTY_NB) {
> +
> +		switch (capability) {
> +		case TPM2_CAP_PCRS:
> +			break;
> +		case TPM2_CAP_TPM_PROPERTIES:
> +			if (!property_count) {
> +				rc = TPM2_RC_HANDLE;
> +				return sandbox_tpm2_fill_buf(recv, recv_len,
> +							     tag, rc);
> +			}
> +
> +			if (property >= TPM2_PROPERTIES_OFFSET &&
> +			    ((property - TPM2_PROPERTIES_OFFSET) +
> +			     property_count > TPM2_PROPERTY_NB)) {
> +				rc = TPM2_RC_HANDLE;
> +				return sandbox_tpm2_fill_buf(recv, recv_len,
> +							     tag, rc);
> +			}
> +			break;
> +		default:
> +			printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
> +			       "TPM2_CAP_TPM_PROPERTIES\n");
>  			rc = TPM2_RC_HANDLE;
>  			return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
>  		}
> @@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
>  		put_unaligned_be32(capability, recv);
>  		recv += sizeof(capability);
>
> -		/* Give the number of properties that follow */
> -		put_unaligned_be32(property_count, recv);
> -		recv += sizeof(property_count);
> -
> -		/* Fill with the properties */
> -		for (i = 0; i < property_count; i++) {
> -			put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
> -					   i, recv);
> -			recv += sizeof(property);
> -			put_unaligned_be32(tpm->properties[property + i],
> -					   recv);
> -			recv += sizeof(property);
> +		switch (capability) {
> +		case TPM2_CAP_PCRS:
> +			/* Give the number of algorithms supported - just SHA256 */
> +			put_unaligned_be32(1, recv);
> +			recv += sizeof(u32);
> +
> +			/* Give SHA256 algorithm */
> +			put_unaligned_be16(TPM2_ALG_SHA256, recv);
> +			recv += sizeof(u16);
> +
> +			/* Select the PCRs supported */
> +			*recv = SANDBOX_TPM_PCR_SELECT_MAX;
> +			recv++;
> +
> +			/* Activate all the PCR bits */
> +			for (i = 0; i < SANDBOX_TPM_PCR_SELECT_MAX; ++i) {
> +				*recv = 0xff;
> +				recv++;
> +			}
> +			break;
> +		case TPM2_CAP_TPM_PROPERTIES:
> +			/* Give the number of properties that follow */
> +			put_unaligned_be32(property_count, recv);
> +			recv += sizeof(property_count);
> +
> +			/* Fill with the properties */
> +			for (i = 0; i < property_count; i++) {
> +				put_unaligned_be32(property + i, recv);
> +				recv += sizeof(property);
> +				if (property >= TPM2_PROPERTIES_OFFSET) {
> +					val = tpm->properties[(property -
> +						TPM2_PROPERTIES_OFFSET) + i];
> +				} else {
> +					switch (property) {
> +					case TPM2_PT_PCR_COUNT:
> +						val = SANDBOX_TPM_PCR_NB;
> +						break;
> +					default:
> +						val = 0xffffffff;
> +						break;
> +					}
> +				}
> +
> +				put_unaligned_be32(val, recv);
> +				recv += sizeof(property);
> +			}
> +			break;
>  		}
>
>  		/* Add trailing \0 */
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index c5835e6ef6..605719d2b6 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -333,8 +333,6 @@ config EFI_TCG2_PROTOCOL
>  	bool "EFI_TCG2_PROTOCOL support"
>  	default y
>  	depends on TPM_V2
> -	# Sandbox TPM currently fails on GetCapabilities needed for TCG2
> -	depends on !SANDBOX
>  	select SHA1
>  	select SHA256
>  	select SHA384
> --
> 2.31.1
>



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v9 3/6] tpm: Support boot measurements
  2023-03-08 21:25 ` [PATCH v9 3/6] tpm: Support boot measurements Eddie James
@ 2023-04-06  9:18   ` Ilias Apalodimas
  2023-04-10 16:18     ` Eddie James
  0 siblings, 1 reply; 16+ messages in thread
From: Ilias Apalodimas @ 2023-04-06  9:18 UTC (permalink / raw)
  To: Eddie James; +Cc: u-boot, sjg, xypron.glpk, joel

Hi Eddie,

Do you plan on resending this?
If yes, I can spend some time trying to figure out the CI failures and
send you a patch.

Thanks
/Ilias


On Wed, 8 Mar 2023 at 23:25, Eddie James <eajames@linux.ibm.com> wrote:
>
> Add TPM2 functions to support boot measurement. This includes
> starting up the TPM, initializing/appending the event log, and
> measuring the U-Boot version. Much of the code was used in the
> EFI subsystem, so remove it there and use the common functions.
>
> Signed-off-by: Eddie James <eajames@linux.ibm.com>
> ---
> Changes since v8:
>  - Fix log parsing again - any data corruption seen while replaying the
>    event log was failing the entire measurement.
>  - Added an option to ignore the existing log. This should only be used
>    for systems that know that U-Boot is the first stage bootloader. This
>    is necessary because the reserved memory region may persist through
>    resets and so U-Boot attempts to append to the previous boot's log.
>
> Changes since v7:
>  - Change name of tcg2_init_log and add more documentation
>  - Add a check, when parsing the event log header, to ensure that the
>    previous stage bootloader used all the active PCRs.
>  - Change name of tcg2_log_find_end
>  - Fix the greater than or equal to check to exit the log parsing
>  - Make sure log_position is 0 if there is any error discovering the log
>  - Return errors parsing the log if the data is corrupt so that we don't
>    end up with half a log
>
> Changes since v6:
>  - Added Linaro copyright for all the EFI moved code
>  - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
>    copy any discovered event log to the user's log if passed in.
>
> Changes since v5:
>  - Remove unused platform_get_eventlog in efi_tcg2.c
>  - First look for tpm_event_log_* properties instead of linux,sml-*
>  - Fix efi_tcg2.c compilation
>  - Select SHA* configs
>
> Changes since v4:
>  - Remove tcg2_measure_event function and check for NULL data in
>    tcg2_measure_data
>  - Use tpm_auto_startup
>  - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
>
> Changes since v3:
>  - Reordered headers
>  - Refactored more of EFI code into common code
>     Removed digest_info structure and instead used the common alg_to_mask
>       and alg_to_len
>     Improved event log parsing in common code to get it equivalent to EFI
>       Common code now extends PCR if previous bootloader stage couldn't
>       No need to allocate memory in the common code, so EFI copies the
>       discovered buffer like it did before
>     Rename efi measure_event function
>
> Changes since v1:
>  - Refactor TPM layer functions to allow EFI system to use them, and
>    remove duplicate EFI functions
>
>  include/efi_tcg2.h        |   44 --
>  include/tpm-v2.h          |  259 +++++++++
>  lib/Kconfig               |    4 +
>  lib/efi_loader/efi_tcg2.c | 1054 +++----------------------------------
>  lib/tpm-v2.c              |  814 ++++++++++++++++++++++++++++
>  5 files changed, 1154 insertions(+), 1021 deletions(-)
>
> diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
> index b1c3abd097..b21c5cb3dd 100644
> --- a/include/efi_tcg2.h
> +++ b/include/efi_tcg2.h
> @@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
>  #define BOOT_SERVICE_CAPABILITY_MIN \
>         offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
>
> -#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
> -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
> -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
> -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
> -
> -/**
> - *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
> - *
> - *  @algorithm_id:     algorithm defined in enum tpm2_algorithms
> - *  @digest_size:      size of the algorithm
> - */
> -struct tcg_efi_spec_id_event_algorithm_size {
> -       u16      algorithm_id;
> -       u16      digest_size;
> -} __packed;
> -
> -/**
> - * struct TCG_EfiSpecIDEventStruct - content of the event log header
> - *
> - * @signature:                 signature, set to Spec ID Event03
> - * @platform_class:            class defined in TCG ACPI Specification
> - *                             Client  Common Header.
> - * @spec_version_minor:                minor version
> - * @spec_version_major:                major version
> - * @spec_version_errata:       major version
> - * @uintn_size:                        size of the efi_uintn_t fields used in various
> - *                             data structures used in this specification.
> - *                             0x01 indicates u32  and 0x02  indicates u64
> - * @number_of_algorithms:      hashing algorithms used in this event log
> - * @digest_sizes:              array of number_of_algorithms pairs
> - *                             1st member defines the algorithm id
> - *                             2nd member defines the algorithm size
> - */
> -struct tcg_efi_spec_id_event {
> -       u8 signature[16];
> -       u32 platform_class;
> -       u8 spec_version_minor;
> -       u8 spec_version_major;
> -       u8 spec_errata;
> -       u8 uintn_size;
> -       u32 number_of_algorithms;
> -       struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
> -} __packed;
> -
>  /**
>   * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log
>   * @version:           version number for this structure
> diff --git a/include/tpm-v2.h b/include/tpm-v2.h
> index 6684033deb..33dd103767 100644
> --- a/include/tpm-v2.h
> +++ b/include/tpm-v2.h
> @@ -216,6 +216,50 @@ struct tcg_pcr_event2 {
>         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.
>   *
> @@ -342,6 +386,26 @@ enum tpm2_algorithms {
>         TPM2_ALG_SM3_256        = 0x12,
>  };
>
> +extern const enum tpm2_algorithms tpm2_supported_algorithms[4];
> +
> +static inline u16 tpm2_algorithm_to_len(enum tpm2_algorithms a)
> +{
> +       switch (a) {
> +       case TPM2_ALG_SHA1:
> +               return TPM2_SHA1_DIGEST_SIZE;
> +       case TPM2_ALG_SHA256:
> +               return TPM2_SHA256_DIGEST_SIZE;
> +       case TPM2_ALG_SHA384:
> +               return TPM2_SHA384_DIGEST_SIZE;
> +       case TPM2_ALG_SHA512:
> +               return TPM2_SHA512_DIGEST_SIZE;
> +       default:
> +               return 0;
> +       }
> +}
> +
> +#define tpm2_algorithm_to_mask(a)      (1 << (a))
> +
>  /* NV index attributes */
>  enum tpm_index_attrs {
>         TPMA_NV_PPWRITE         = 1UL << 0,
> @@ -421,6 +485,188 @@ enum {
>         HR_NV_INDEX             = TPM_HT_NV_INDEX << HR_SHIFT,
>  };
>
> +/**
> + * 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.
>   *
> @@ -540,6 +786,19 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
>  u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
>                         void *buf, size_t prop_count);
>
> +/**
> + * tpm2_get_pcr_info() - get the supported, active PCRs and number of banks
> + *
> + * @dev:               TPM device
> + * @supported_pcr:     bitmask with the algorithms supported
> + * @active_pcr:                bitmask with the active algorithms
> + * @pcr_banks:         number of PCR banks
> + *
> + * @return 0 on success, code of operation or negative errno on failure
> + */
> +int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
> +                     u32 *pcr_banks);
> +
>  /**
>   * Issue a TPM2_DictionaryAttackLockReset command.
>   *
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 83e5edd73b..7a146c293f 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -411,6 +411,10 @@ config TPM
>         bool "Trusted Platform Module (TPM) Support"
>         depends on DM
>         imply DM_RNG
> +       select SHA1
> +       select SHA256
> +       select SHA384
> +       select SHA512
>         help
>           This enables support for TPMs which can be used to provide security
>           features for your board. The TPM can be connected via LPC or I2C
> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> index a83ae7a46c..5f0f4b5dd2 100644
> --- a/lib/efi_loader/efi_tcg2.c
> +++ b/lib/efi_loader/efi_tcg2.c
> @@ -66,35 +66,6 @@ static bool tcg2_efi_app_invoked;
>  static const efi_guid_t efi_guid_tcg2_protocol = EFI_TCG2_PROTOCOL_GUID;
>  static const efi_guid_t efi_guid_final_events = EFI_TCG2_FINAL_EVENTS_TABLE_GUID;
>
> -struct digest_info {
> -       u16 hash_alg;
> -       u32 hash_mask;
> -       u16 hash_len;
> -};
> -
> -static const struct digest_info hash_algo_list[] = {
> -       {
> -               TPM2_ALG_SHA1,
> -               EFI_TCG2_BOOT_HASH_ALG_SHA1,
> -               TPM2_SHA1_DIGEST_SIZE,
> -       },
> -       {
> -               TPM2_ALG_SHA256,
> -               EFI_TCG2_BOOT_HASH_ALG_SHA256,
> -               TPM2_SHA256_DIGEST_SIZE,
> -       },
> -       {
> -               TPM2_ALG_SHA384,
> -               EFI_TCG2_BOOT_HASH_ALG_SHA384,
> -               TPM2_SHA384_DIGEST_SIZE,
> -       },
> -       {
> -               TPM2_ALG_SHA512,
> -               EFI_TCG2_BOOT_HASH_ALG_SHA512,
> -               TPM2_SHA512_DIGEST_SIZE,
> -       },
> -};
> -
>  struct variable_info {
>         const u16       *name;
>         bool            accept_empty;
> @@ -113,46 +84,6 @@ static struct variable_info secure_variables[] = {
>         {u"AuditMode",          false,  1},
>  };
>
> -#define MAX_HASH_COUNT ARRAY_SIZE(hash_algo_list)
> -
> -/**
> - * alg_to_mask - Get a TCG hash mask for algorithms
> - *
> - * @hash_alg: TCG defined algorithm
> - *
> - * @Return: TCG hashing algorithm bitmaps, 0 if the algorithm is not supported
> - */
> -static u32 alg_to_mask(u16 hash_alg)
> -{
> -       size_t i;
> -
> -       for (i = 0; i < MAX_HASH_COUNT; i++) {
> -               if (hash_algo_list[i].hash_alg == hash_alg)
> -                       return hash_algo_list[i].hash_mask;
> -       }
> -
> -       return 0;
> -}
> -
> -/**
> - * alg_to_len - Get a TCG hash len for algorithms
> - *
> - * @hash_alg: TCG defined algorithm
> - *
> - * @Return: len of chosen algorithm, 0 if the algorithm is not supported
> - */
> -static u16 alg_to_len(u16 hash_alg)
> -{
> -       size_t i;
> -
> -       for (i = 0; i < MAX_HASH_COUNT; i++) {
> -               if (hash_algo_list[i].hash_alg == hash_alg)
> -                       return hash_algo_list[i].hash_len;
> -       }
> -
> -       return 0;
> -}
> -
>  static bool is_tcg2_protocol_installed(void)
>  {
>         struct efi_handler *handler;
> @@ -162,145 +93,6 @@ static bool is_tcg2_protocol_installed(void)
>         return ret == EFI_SUCCESS;
>  }
>
> -static u32 tcg_event_final_size(struct tpml_digest_values *digest_list)
> -{
> -       u32 len;
> -       size_t i;
> -
> -       len = offsetof(struct tcg_pcr_event2, digests);
> -       len += offsetof(struct tpml_digest_values, digests);
> -       for (i = 0; i < digest_list->count; i++) {
> -               u16 hash_alg = digest_list->digests[i].hash_alg;
> -
> -               len += offsetof(struct tpmt_ha, digest);
> -               len += alg_to_len(hash_alg);
> -       }
> -       len += sizeof(u32); /* tcg_pcr_event2 event_size*/
> -
> -       return len;
> -}
> -
> -/* tcg2_pcr_extend - Extend PCRs for a TPM2 device for a given tpml_digest_values
> - *
> - * @dev:               device
> - * @digest_list:       list of digest algorithms to extend
> - *
> - * @Return: status code
> - */
> -static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
> -                                   struct tpml_digest_values *digest_list)
> -{
> -       u32 rc;
> -       size_t i;
> -
> -       for (i = 0; i < digest_list->count; i++) {
> -               u32 alg = digest_list->digests[i].hash_alg;
> -
> -               rc = tpm2_pcr_extend(dev, pcr_index, alg,
> -                                    (u8 *)&digest_list->digests[i].digest,
> -                                    alg_to_len(alg));
> -               if (rc) {
> -                       EFI_PRINT("Failed to extend PCR\n");
> -                       return EFI_DEVICE_ERROR;
> -               }
> -       }
> -
> -       return EFI_SUCCESS;
> -}
> -
> -/* tcg2_pcr_read - Read PCRs for a TPM2 device for a given tpml_digest_values
> - *
> - * @dev:               device
> - * @pcr_index:         PCR index
> - * @digest_list:       list of digest algorithms to extend
> - *
> - * @Return: status code
> - */
> -static efi_status_t tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
> -                                 struct tpml_digest_values *digest_list)
> -{
> -       struct tpm_chip_priv *priv;
> -       unsigned int updates, pcr_select_min;
> -       u32 rc;
> -       size_t i;
> -
> -       priv = dev_get_uclass_priv(dev);
> -       if (!priv)
> -               return EFI_DEVICE_ERROR;
> -
> -       pcr_select_min = priv->pcr_select_min;
> -
> -       for (i = 0; i < digest_list->count; i++) {
> -               u16 hash_alg = digest_list->digests[i].hash_alg;
> -               u8 *digest = (u8 *)&digest_list->digests[i].digest;
> -
> -               rc = tpm2_pcr_read(dev, pcr_index, pcr_select_min,
> -                                  hash_alg, digest, alg_to_len(hash_alg),
> -                                  &updates);
> -               if (rc) {
> -                       EFI_PRINT("Failed to read PCR\n");
> -                       return EFI_DEVICE_ERROR;
> -               }
> -       }
> -
> -       return EFI_SUCCESS;
> -}
> -
> -/* put_event - Append an agile event to an eventlog
> - *
> - * @pcr_index:         PCR index
> - * @event_type:                type of event added
> - * @digest_list:       list of digest algorithms to add
> - * @size:              size of event
> - * @event:             event to add
> - * @log:               log buffer to append the event
> - *
> - */
> -static void put_event(u32 pcr_index, u32 event_type,
> -                     struct tpml_digest_values *digest_list, u32 size,
> -                     u8 event[], void *log)
> -{
> -       size_t pos;
> -       size_t i;
> -       u32 event_size;
> -
> -       /*
> -        * size refers to the length of event[] only, we need to check against
> -        * the final tcg_pcr_event2 size
> -        */
> -       event_size = size + tcg_event_final_size(digest_list);
> -
> -       put_unaligned_le32(pcr_index, log);
> -       pos = offsetof(struct tcg_pcr_event2, event_type);
> -       put_unaligned_le32(event_type, (void *)((uintptr_t)log + pos));
> -       pos = offsetof(struct tcg_pcr_event2, digests); /* count */
> -       put_unaligned_le32(digest_list->count, (void *)((uintptr_t)log + pos));
> -
> -       pos += offsetof(struct tpml_digest_values, digests);
> -       for (i = 0; i < digest_list->count; i++) {
> -               u16 hash_alg = digest_list->digests[i].hash_alg;
> -               u8 *digest = (u8 *)&digest_list->digests[i].digest;
> -
> -               put_unaligned_le16(hash_alg, (void *)((uintptr_t)log + pos));
> -               pos += offsetof(struct tpmt_ha, digest);
> -               memcpy((void *)((uintptr_t)log + pos), digest, alg_to_len(hash_alg));
> -               pos += alg_to_len(hash_alg);
> -       }
> -
> -       put_unaligned_le32(size, (void *)((uintptr_t)log + pos));
> -       pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
> -       memcpy((void *)((uintptr_t)log + pos), event, size);
> -       pos += size;
> -
> -       /*
> -        * make sure the calculated buffer is what we checked against
> -        * This check should never fail.  It checks the code above is
> -        * calculating the right length for the event we are adding
> -        */
> -       if (pos != event_size)
> -               log_err("Appending to the EventLog failed\n");
> -}
> -
>  /* tcg2_agile_log_append - Append an agile event to an eventlog
>   *
>   * @pcr_index:         PCR index
> @@ -317,7 +109,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
>                                           u32 size, u8 event[])
>  {
>         void *log = (void *)((uintptr_t)event_log.buffer + event_log.pos);
> -       u32 event_size = size + tcg_event_final_size(digest_list);
> +       u32 event_size = size + tcg2_event_get_size(digest_list);
>         struct efi_tcg2_final_events_table *final_event;
>         efi_status_t ret = EFI_SUCCESS;
>
> @@ -328,7 +120,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
>                         event_log.truncated = true;
>                         return EFI_VOLUME_FULL;
>                 }
> -               put_event(pcr_index, event_type, digest_list, size, event, log);
> +               tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
>                 event_log.pos += event_size;
>                 event_log.last_event_size = event_size;
>         }
> @@ -341,7 +133,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
>                 return EFI_VOLUME_FULL;
>
>         log = (void *)((uintptr_t)event_log.final_buffer + event_log.final_pos);
> -       put_event(pcr_index, event_type, digest_list, size, event, log);
> +       tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
>
>         final_event = event_log.final_buffer;
>         final_event->number_of_events++;
> @@ -350,66 +142,6 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
>         return ret;
>  }
>
> -/**
> - * platform_get_tpm_device() - retrieve TPM device
> - *
> - * This function retrieves the udevice implementing a TPM
> - *
> - * This function may be overridden if special initialization is needed.
> - *
> - * @dev:       udevice
> - * Return:     status code
> - */
> -__weak efi_status_t platform_get_tpm2_device(struct udevice **dev)
> -{
> -       for_each_tpm_device(*dev) {
> -               /* Only support TPMv2 devices */
> -               if (tpm_get_version(*dev) == TPM_V2)
> -                       return EFI_SUCCESS;
> -       }
> -
> -       return EFI_NOT_FOUND;
> -}
> -
> -/**
> - * platform_get_eventlog() - retrieve the eventlog address and size
> - *
> - * This function retrieves the eventlog address and size if the underlying
> - * firmware has done some measurements and passed them.
> - *
> - * This function may be overridden based on platform specific method of
> - * passing the eventlog address and size.
> - *
> - * @dev:       udevice
> - * @addr:      eventlog address
> - * @sz:                eventlog size
> - * Return:     status code
> - */
> -__weak efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr,
> -                                         u32 *sz)
> -{
> -       const u64 *basep;
> -       const u32 *sizep;
> -
> -       basep = dev_read_prop(dev, "tpm_event_log_addr", NULL);
> -       if (!basep)
> -               return EFI_NOT_FOUND;
> -
> -       *addr = be64_to_cpup((__force __be64 *)basep);
> -
> -       sizep = dev_read_prop(dev, "tpm_event_log_size", NULL);
> -       if (!sizep)
> -               return EFI_NOT_FOUND;
> -
> -       *sz = be32_to_cpup((__force __be32 *)sizep);
> -       if (*sz == 0) {
> -               log_debug("event log empty\n");
> -               return EFI_NOT_FOUND;
> -       }
> -
> -       return EFI_SUCCESS;
> -}
> -
>  /**
>   * tpm2_get_max_command_size() - get the supported max command size
>   *
> @@ -485,239 +217,6 @@ static int tpm2_get_manufacturer_id(struct udevice *dev, u32 *manufacturer_id)
>         return 0;
>  }
>
> -/**
> - * tpm2_get_num_pcr() - get the number of PCRs
> - *
> - * @dev:               TPM device
> - * @manufacturer_id:   output buffer for the number
> - *
> - * Return: 0 on success, -1 on error
> - */
> -static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
> -{
> -       u8 response[TPM2_RESPONSE_BUFFER_SIZE];
> -       u32 ret;
> -
> -       memset(response, 0, sizeof(response));
> -       ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
> -                                 TPM2_PT_PCR_COUNT, response, 1);
> -       if (ret)
> -               return -1;
> -
> -       *num_pcr = get_unaligned_be32(response + properties_offset);
> -       if (*num_pcr > TPM2_MAX_PCRS)
> -               return -1;
> -
> -       return 0;
> -}
> -
> -/**
> - * is_active_pcr() - Check if a supported algorithm is active
> - *
> - * @dev:               TPM device
> - * @selection:         struct of PCR information
> - *
> - * Return: true if PCR is active
> - */
> -static bool is_active_pcr(struct tpms_pcr_selection *selection)
> -{
> -       int i;
> -       /*
> -        * check the pcr_select. If at least one of the PCRs supports the
> -        * algorithm add it on the active ones
> -        */
> -       for (i = 0; i < selection->size_of_select; i++) {
> -               if (selection->pcr_select[i])
> -                       return true;
> -       }
> -
> -       return false;
> -}
> -
> -/**
> - * tpm2_get_pcr_info() - get the supported, active PCRs and number of banks
> - *
> - * @dev:               TPM device
> - * @supported_pcr:     bitmask with the algorithms supported
> - * @active_pcr:                bitmask with the active algorithms
> - * @pcr_banks:         number of PCR banks
> - *
> - * Return: 0 on success, -1 on error
> - */
> -static int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr,
> -                            u32 *active_pcr, u32 *pcr_banks)
> -{
> -       u8 response[TPM2_RESPONSE_BUFFER_SIZE];
> -       struct tpml_pcr_selection pcrs;
> -       u32 ret, num_pcr;
> -       size_t i;
> -       int tpm_ret;
> -
> -       *supported_pcr = 0;
> -       *active_pcr = 0;
> -       *pcr_banks = 0;
> -       memset(response, 0, sizeof(response));
> -       ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
> -       if (ret)
> -               goto out;
> -
> -       pcrs.count = get_unaligned_be32(response);
> -       /*
> -        * We only support 5 algorithms for now so check against that
> -        * instead of TPM2_NUM_PCR_BANKS
> -        */
> -       if (pcrs.count > MAX_HASH_COUNT || pcrs.count < 1)
> -               goto out;
> -
> -       tpm_ret = tpm2_get_num_pcr(dev, &num_pcr);
> -       if (tpm_ret)
> -               goto out;
> -
> -       for (i = 0; i < pcrs.count; i++) {
> -               /*
> -                * Definition of TPMS_PCR_SELECTION Structure
> -                * hash: u16
> -                * size_of_select: u8
> -                * pcr_select: u8 array
> -                *
> -                * The offsets depend on the number of the device PCRs
> -                * so we have to calculate them based on that
> -                */
> -               u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
> -                       i * offsetof(struct tpms_pcr_selection, pcr_select) +
> -                       i * ((num_pcr + 7) / 8);
> -               u32 size_select_offset =
> -                       hash_offset + offsetof(struct tpms_pcr_selection,
> -                                              size_of_select);
> -               u32 pcr_select_offset =
> -                       hash_offset + offsetof(struct tpms_pcr_selection,
> -                                              pcr_select);
> -
> -               pcrs.selection[i].hash =
> -                       get_unaligned_be16(response + hash_offset);
> -               pcrs.selection[i].size_of_select =
> -                       __get_unaligned_be(response + size_select_offset);
> -               if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX)
> -                       goto out;
> -               /* copy the array of pcr_select */
> -               memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset,
> -                      pcrs.selection[i].size_of_select);
> -       }
> -
> -       for (i = 0; i < pcrs.count; i++) {
> -               u32 hash_mask = alg_to_mask(pcrs.selection[i].hash);
> -
> -               if (hash_mask) {
> -                       *supported_pcr |= hash_mask;
> -                       if (is_active_pcr(&pcrs.selection[i]))
> -                               *active_pcr |= hash_mask;
> -               } else {
> -                       EFI_PRINT("Unknown algorithm %x\n", pcrs.selection[i].hash);
> -               }
> -       }
> -
> -       *pcr_banks = pcrs.count;
> -
> -       return 0;
> -out:
> -       return -1;
> -}
> -
> -/**
> - * __get_active_pcr_banks() - returns the currently active PCR banks
> - *
> - * @active_pcr_banks:          pointer for receiving the bitmap of currently
> - *                             active PCR banks
> - *
> - * Return:     status code
> - */
> -static efi_status_t __get_active_pcr_banks(u32 *active_pcr_banks)
> -{
> -       struct udevice *dev;
> -       u32 active = 0, supported = 0, pcr_banks = 0;
> -       efi_status_t ret;
> -       int err;
> -
> -       ret = platform_get_tpm2_device(&dev);
> -       if (ret != EFI_SUCCESS)
> -               goto out;
> -
> -       err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
> -       if (err) {
> -               ret = EFI_DEVICE_ERROR;
> -               goto out;
> -       }
> -
> -       *active_pcr_banks = active;
> -
> -out:
> -       return ret;
> -}
> -
> -/* tcg2_create_digest - create a list of digests of the supported PCR banks
> - *                     for a given memory range
> - *
> - * @input:             input memory
> - * @length:            length of buffer to calculate the digest
> - * @digest_list:       list of digests to fill in
> - *
> - * Return:             status code
> - */
> -static efi_status_t tcg2_create_digest(const u8 *input, u32 length,
> -                                      struct tpml_digest_values *digest_list)
> -{
> -       sha1_context ctx;
> -       sha256_context ctx_256;
> -       sha512_context ctx_512;
> -       u8 final[TPM2_SHA512_DIGEST_SIZE];
> -       efi_status_t ret;
> -       u32 active;
> -       size_t i;
> -
> -       ret = __get_active_pcr_banks(&active);
> -       if (ret != EFI_SUCCESS)
> -               return ret;
> -
> -       digest_list->count = 0;
> -       for (i = 0; i < MAX_HASH_COUNT; i++) {
> -               u16 hash_alg = hash_algo_list[i].hash_alg;
> -
> -               if (!(active & alg_to_mask(hash_alg)))
> -                       continue;
> -               switch (hash_alg) {
> -               case TPM2_ALG_SHA1:
> -                       sha1_starts(&ctx);
> -                       sha1_update(&ctx, input, length);
> -                       sha1_finish(&ctx, final);
> -                       break;
> -               case TPM2_ALG_SHA256:
> -                       sha256_starts(&ctx_256);
> -                       sha256_update(&ctx_256, input, length);
> -                       sha256_finish(&ctx_256, final);
> -                       break;
> -               case TPM2_ALG_SHA384:
> -                       sha384_starts(&ctx_512);
> -                       sha384_update(&ctx_512, input, length);
> -                       sha384_finish(&ctx_512, final);
> -                       break;
> -               case TPM2_ALG_SHA512:
> -                       sha512_starts(&ctx_512);
> -                       sha512_update(&ctx_512, input, length);
> -                       sha512_finish(&ctx_512, final);
> -                       break;
> -               default:
> -                       EFI_PRINT("Unsupported algorithm %x\n", hash_alg);
> -                       return EFI_INVALID_PARAMETER;
> -               }
> -               digest_list->digests[digest_list->count].hash_alg = hash_alg;
> -               memcpy(&digest_list->digests[digest_list->count].digest, final,
> -                      (u32)alg_to_len(hash_alg));
> -               digest_list->count++;
> -       }
> -
> -       return EFI_SUCCESS;
> -}
> -
>  /**
>   * efi_tcg2_get_capability() - protocol capability information and state information
>   *
> @@ -759,7 +258,7 @@ efi_tcg2_get_capability(struct efi_tcg2_protocol *this,
>         capability->protocol_version.major = 1;
>         capability->protocol_version.minor = 1;
>
> -       efi_ret = platform_get_tpm2_device(&dev);
> +       efi_ret = tcg2_platform_get_tpm2(&dev);
>         if (efi_ret != EFI_SUCCESS) {
>                 capability->supported_event_logs = 0;
>                 capability->hash_algorithm_bitmap = 0;
> @@ -855,7 +354,7 @@ efi_tcg2_get_eventlog(struct efi_tcg2_protocol *this,
>                 goto out;
>         }
>
> -       ret = platform_get_tpm2_device(&dev);
> +       ret = tcg2_platform_get_tpm2(&dev);
>         if (ret != EFI_SUCCESS) {
>                 event_log_location = NULL;
>                 event_log_last_entry = NULL;
> @@ -890,6 +389,7 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size,
>         struct efi_image_regions *regs = NULL;
>         void *new_efi = NULL;
>         u8 hash[TPM2_SHA512_DIGEST_SIZE];
> +       struct udevice *dev;
>         efi_status_t ret;
>         u32 active;
>         int i;
> @@ -905,16 +405,20 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size,
>                 goto out;
>         }
>
> -       ret = __get_active_pcr_banks(&active);
> +       ret = tcg2_platform_get_tpm2(&dev);
> +       if (ret != EFI_SUCCESS)
> +               goto out;
> +
> +       ret = tcg2_get_active_pcr_banks(dev, &active);
>         if (ret != EFI_SUCCESS) {
>                 goto out;
>         }
>
>         digest_list->count = 0;
> -       for (i = 0; i < MAX_HASH_COUNT; i++) {
> -               u16 hash_alg = hash_algo_list[i].hash_alg;
> +       for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); i++) {
> +               u16 hash_alg = tpm2_supported_algorithms[i];
>
> -               if (!(active & alg_to_mask(hash_alg)))
> +               if (!(active & tpm2_algorithm_to_mask(hash_alg)))
>                         continue;
>                 switch (hash_alg) {
>                 case TPM2_ALG_SHA1:
> @@ -935,7 +439,7 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size,
>                 }
>                 digest_list->digests[digest_list->count].hash_alg = hash_alg;
>                 memcpy(&digest_list->digests[digest_list->count].digest, hash,
> -                      (u32)alg_to_len(hash_alg));
> +                      (u32)tpm2_algorithm_to_len(hash_alg));
>                 digest_list->count++;
>         }
>
> @@ -975,7 +479,7 @@ efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size,
>         if (!is_tcg2_protocol_installed())
>                 return EFI_SUCCESS;
>
> -       ret = platform_get_tpm2_device(&dev);
> +       ret = tcg2_platform_get_tpm2(&dev);
>         if (ret != EFI_SUCCESS)
>                 return EFI_SECURITY_VIOLATION;
>
> @@ -1084,7 +588,7 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags,
>                 goto out;
>         }
>
> -       ret = platform_get_tpm2_device(&dev);
> +       ret = tcg2_platform_get_tpm2(&dev);
>         if (ret != EFI_SUCCESS)
>                 goto out;
>
> @@ -1119,7 +623,7 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags,
>                 ret = tcg2_hash_pe_image((void *)(uintptr_t)data_to_hash,
>                                          data_to_hash_len, &digest_list);
>         } else {
> -               ret = tcg2_create_digest((u8 *)(uintptr_t)data_to_hash,
> +               ret = tcg2_create_digest(dev, (u8 *)(uintptr_t)data_to_hash,
>                                          data_to_hash_len, &digest_list);
>         }
>
> @@ -1182,7 +686,7 @@ efi_tcg2_submit_command(struct efi_tcg2_protocol *this,
>                 goto out;
>         }
>
> -       ret = platform_get_tpm2_device(&dev);
> +       ret = tcg2_platform_get_tpm2(&dev);
>         if (ret != EFI_SUCCESS)
>                 goto out;
>
> @@ -1211,6 +715,7 @@ static efi_status_t EFIAPI
>  efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this,
>                               u32 *active_pcr_banks)
>  {
> +       struct udevice *dev;
>         efi_status_t ret;
>
>         if (!this || !active_pcr_banks) {
> @@ -1218,8 +723,12 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this,
>                 goto out;
>         }
>
> +       ret = tcg2_platform_get_tpm2(&dev);
> +       if (ret != EFI_SUCCESS)
> +               goto out;
> +
>         EFI_ENTRY("%p, %p", this, active_pcr_banks);
> -       ret = __get_active_pcr_banks(active_pcr_banks);
> +       ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks);
>
>  out:
>         return EFI_EXIT(ret);
> @@ -1270,397 +779,6 @@ static const struct efi_tcg2_protocol efi_tcg2_protocol = {
>         .get_result_of_set_active_pcr_banks = efi_tcg2_get_result_of_set_active_pcr_banks,
>  };
>
> -/**
> - * parse_event_log_header() -  Parse and verify the event log header fields
> - *
> - * @buffer:                    Pointer to the start of the eventlog
> - * @size:                      Size of the eventlog
> - * @pos:                       Return offset of the next event in buffer right
> - *                             after the event header i.e specID
> - *
> - * Return:     status code
> - */
> -static efi_status_t parse_event_log_header(void *buffer, u32 size, u32 *pos)
> -{
> -       struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
> -       int i = 0;
> -
> -       if (size < sizeof(*event_header))
> -               return EFI_COMPROMISED_DATA;
> -
> -       if (get_unaligned_le32(&event_header->pcr_index) != 0 ||
> -           get_unaligned_le32(&event_header->event_type) != EV_NO_ACTION)
> -               return EFI_COMPROMISED_DATA;
> -
> -       for (i = 0; i < sizeof(event_header->digest); i++) {
> -               if (event_header->digest[i])
> -                       return EFI_COMPROMISED_DATA;
> -       }
> -
> -       *pos += sizeof(*event_header);
> -
> -       return EFI_SUCCESS;
> -}
> -
> -/**
> - * parse_specid_event() -  Parse and verify the specID Event in the eventlog
> - *
> - * @dev:               udevice
> - * @buffer:            Pointer to the start of the eventlog
> - * @log_size:          Size of the eventlog
> - * @pos:               [in] Offset of specID event in the eventlog buffer
> - *                     [out] Return offset of the next event in the buffer
> - *                     after the specID
> - * @digest_list:       list of digests in the event
> - *
> - * Return:             status code
> - * @pos                        Offset in the eventlog where the specID event ends
> - * @digest_list:       list of digests in the event
> - */
> -static efi_status_t parse_specid_event(struct udevice *dev, void *buffer,
> -                                      u32 log_size, u32 *pos,
> -                                      struct tpml_digest_values *digest_list)
> -{
> -       struct tcg_efi_spec_id_event *spec_event;
> -       struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
> -       size_t spec_event_size;
> -       u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
> -       u32 spec_active = 0;
> -       u16 hash_alg;
> -       u8 vendor_sz;
> -       int err, i;
> -
> -       if (*pos >= log_size || (*pos + sizeof(*spec_event)) > log_size)
> -               return EFI_COMPROMISED_DATA;
> -
> -       /* Check specID event data */
> -       spec_event = (struct tcg_efi_spec_id_event *)((uintptr_t)buffer + *pos);
> -       /* Check for signature */
> -       if (memcmp(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
> -                  sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03))) {
> -               log_err("specID Event: Signature mismatch\n");
> -               return EFI_COMPROMISED_DATA;
> -       }
> -
> -       if (spec_event->spec_version_minor !=
> -                       TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
> -           spec_event->spec_version_major !=
> -                       TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
> -               return EFI_COMPROMISED_DATA;
> -
> -       if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
> -           spec_event->number_of_algorithms < 1) {
> -               log_err("specID Event: Number of algorithms incorrect\n");
> -               return EFI_COMPROMISED_DATA;
> -       }
> -
> -       alg_count = spec_event->number_of_algorithms;
> -
> -       err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
> -       if (err)
> -               return EFI_DEVICE_ERROR;
> -
> -       digest_list->count = 0;
> -       /*
> -        * We have to take care that the sequence of algorithms that we record
> -        * in digest_list matches the sequence in eventlog.
> -        */
> -       for (i = 0; i < alg_count; i++) {
> -               hash_alg =
> -                 get_unaligned_le16(&spec_event->digest_sizes[i].algorithm_id);
> -
> -               if (!(supported & alg_to_mask(hash_alg))) {
> -                       log_err("specID Event: Unsupported algorithm\n");
> -                       return EFI_COMPROMISED_DATA;
> -               }
> -               digest_list->digests[digest_list->count++].hash_alg = hash_alg;
> -
> -               spec_active |= alg_to_mask(hash_alg);
> -       }
> -
> -       /*
> -        * TCG specification expects the event log to have hashes for all
> -        * active PCR's
> -        */
> -       if (spec_active != active) {
> -               /*
> -                * Previous stage bootloader should know all the active PCR's
> -                * and use them in the Eventlog.
> -                */
> -               log_err("specID Event: All active hash alg not present\n");
> -               return EFI_COMPROMISED_DATA;
> -       }
> -
> -       /*
> -        * the size of the spec event and placement of vendor_info_size
> -        * depends on supported algoriths
> -        */
> -       spec_event_size =
> -               offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
> -               alg_count * sizeof(spec_event->digest_sizes[0]);
> -
> -       if (*pos + spec_event_size >= log_size)
> -               return EFI_COMPROMISED_DATA;
> -
> -       vendor_sz = *(uint8_t *)((uintptr_t)buffer + *pos + spec_event_size);
> -
> -       spec_event_size += sizeof(vendor_sz) + vendor_sz;
> -       *pos += spec_event_size;
> -
> -       if (get_unaligned_le32(&event_header->event_size) != spec_event_size) {
> -               log_err("specID event: header event size mismatch\n");
> -               /* Right way to handle this can be to call SetActive PCR's */
> -               return EFI_COMPROMISED_DATA;
> -       }
> -
> -       return EFI_SUCCESS;
> -}
> -
> -/**
> - * tcg2_parse_event() -  Parse the event in the eventlog
> - *
> - * @dev:               udevice
> - * @buffer:            Pointer to the start of the eventlog
> - * @log_size:          Size of the eventlog
> - * @offset:            [in] Offset of the event in the eventlog buffer
> - *                     [out] Return offset of the next event in the buffer
> - * @digest_list:       list of digests in the event
> - * @pcr                        Index of the PCR in the event
> - *
> - * Return:             status code
> - */
> -static efi_status_t tcg2_parse_event(struct udevice *dev, void *buffer,
> -                                    u32 log_size, u32 *offset,
> -                                    struct tpml_digest_values *digest_list,
> -                                    u32 *pcr)
> -{
> -       struct tcg_pcr_event2 *event = NULL;
> -       u32 count, size, event_size;
> -       size_t pos;
> -
> -       event_size = tcg_event_final_size(digest_list);
> -       if (*offset >= log_size || *offset + event_size > log_size) {
> -               log_err("Event exceeds log size\n");
> -               return EFI_COMPROMISED_DATA;
> -       }
> -
> -       event = (struct tcg_pcr_event2 *)((uintptr_t)buffer + *offset);
> -       *pcr = get_unaligned_le32(&event->pcr_index);
> -
> -       /* get the count */
> -       count = get_unaligned_le32(&event->digests.count);
> -       if (count != digest_list->count)
> -               return EFI_COMPROMISED_DATA;
> -
> -       pos = offsetof(struct tcg_pcr_event2, digests);
> -       pos += offsetof(struct tpml_digest_values, digests);
> -
> -       for (int i = 0; i < digest_list->count; i++) {
> -               u16 alg;
> -               u16 hash_alg = digest_list->digests[i].hash_alg;
> -               u8 *digest = (u8 *)&digest_list->digests[i].digest;
> -
> -               alg = get_unaligned_le16((void *)((uintptr_t)event + pos));
> -
> -               if (alg != hash_alg)
> -                       return EFI_COMPROMISED_DATA;
> -
> -               pos += offsetof(struct tpmt_ha, digest);
> -               memcpy(digest, (void *)((uintptr_t)event + pos), alg_to_len(hash_alg));
> -               pos += alg_to_len(hash_alg);
> -       }
> -
> -       size = get_unaligned_le32((void *)((uintptr_t)event + pos));
> -       event_size += size;
> -       pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
> -       pos += size;
> -
> -       /* make sure the calculated buffer is what we checked against */
> -       if (pos != event_size)
> -               return EFI_COMPROMISED_DATA;
> -
> -       if (pos > log_size)
> -               return EFI_COMPROMISED_DATA;
> -
> -       *offset += pos;
> -
> -       return EFI_SUCCESS;
> -}
> -
> -/**
> - * tcg2_get_fw_eventlog() -  Get the eventlog address and size
> - *
> - * If the previous firmware has passed some eventlog, this function get it's
> - * location and check for it's validity.
> - *
> - * @dev:               udevice
> - * @log_buffer:                eventlog address
> - * @log_sz:            eventlog size
> - *
> - * Return:     status code
> - */
> -static efi_status_t tcg2_get_fw_eventlog(struct udevice *dev, void *log_buffer,
> -                                        size_t *log_sz)
> -{
> -       struct tpml_digest_values digest_list;
> -       void *buffer;
> -       efi_status_t ret;
> -       u32 pcr, pos;
> -       u64 base;
> -       u32 sz;
> -       bool extend_pcr = false;
> -       int i;
> -
> -       ret = platform_get_eventlog(dev, &base, &sz);
> -       if (ret != EFI_SUCCESS)
> -               return ret;
> -
> -       if (sz > TPM2_EVENT_LOG_SIZE)
> -               return EFI_VOLUME_FULL;
> -
> -       buffer = (void *)(uintptr_t)base;
> -       pos = 0;
> -       /* Parse the eventlog to check for its validity */
> -       ret = parse_event_log_header(buffer, sz, &pos);
> -       if (ret)
> -               return ret;
> -
> -       ret = parse_specid_event(dev, buffer, sz, &pos, &digest_list);
> -       if (ret) {
> -               log_err("Error parsing SPEC ID Event\n");
> -               return ret;
> -       }
> -
> -       ret = tcg2_pcr_read(dev, 0, &digest_list);
> -       if (ret) {
> -               log_err("Error reading PCR 0\n");
> -               return ret;
> -       }
> -
> -       /*
> -        * If PCR0 is 0, previous firmware didn't have the capability
> -        * to extend the PCR. In this scenario, extend the PCR as
> -        * the eventlog is parsed.
> -        */
> -       for (i = 0; i < digest_list.count; i++) {
> -               u8 hash_buf[TPM2_SHA512_DIGEST_SIZE] = { 0 };
> -               u16 hash_alg = digest_list.digests[i].hash_alg;
> -
> -               if (!memcmp((u8 *)&digest_list.digests[i].digest, hash_buf,
> -                           alg_to_len(hash_alg)))
> -                       extend_pcr = true;
> -       }
> -
> -       while (pos < sz) {
> -               ret = tcg2_parse_event(dev, buffer, sz, &pos, &digest_list,
> -                                      &pcr);
> -               if (ret) {
> -                       log_err("Error parsing event\n");
> -                       return ret;
> -               }
> -               if (extend_pcr) {
> -                       ret = tcg2_pcr_extend(dev, pcr, &digest_list);
> -                       if (ret != EFI_SUCCESS) {
> -                               log_err("Error in extending PCR\n");
> -                               return ret;
> -                       }
> -
> -                       /* Clear the digest for next event */
> -                       for (i = 0; i < digest_list.count; i++) {
> -                               u16 hash_alg = digest_list.digests[i].hash_alg;
> -                               u8 *digest =
> -                                  (u8 *)&digest_list.digests[i].digest;
> -
> -                               memset(digest, 0, alg_to_len(hash_alg));
> -                       }
> -               }
> -       }
> -
> -       memcpy(log_buffer, buffer, sz);
> -       *log_sz = sz;
> -
> -       return ret;
> -}
> -
> -/**
> - * create_specid_event() - Create the first event in the eventlog
> - *
> - * @dev:                       tpm device
> - * @event_header:              Pointer to the final event header
> - * @event_size:                        final spec event size
> - *
> - * Return:     status code
> - */
> -static efi_status_t create_specid_event(struct udevice *dev, void *buffer,
> -                                       size_t *event_size)
> -{
> -       struct tcg_efi_spec_id_event *spec_event;
> -       size_t spec_event_size;
> -       efi_status_t ret = EFI_DEVICE_ERROR;
> -       u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
> -       int err;
> -       size_t i;
> -
> -       /*
> -        * Create Spec event. This needs to be the first event in the log
> -        * according to the TCG EFI protocol spec
> -        */
> -
> -       /* Setup specID event data */
> -       spec_event = (struct tcg_efi_spec_id_event *)buffer;
> -       memcpy(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
> -              sizeof(spec_event->signature));
> -       put_unaligned_le32(0, &spec_event->platform_class); /* type client */
> -       spec_event->spec_version_minor =
> -               TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
> -       spec_event->spec_version_major =
> -               TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
> -       spec_event->spec_errata =
> -               TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
> -       spec_event->uintn_size = sizeof(efi_uintn_t) / sizeof(u32);
> -
> -       err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
> -
> -       if (err)
> -               goto out;
> -
> -       for (i = 0; i < pcr_count; i++) {
> -               u16 hash_alg = hash_algo_list[i].hash_alg;
> -               u16 hash_len = hash_algo_list[i].hash_len;
> -
> -               if (active & alg_to_mask(hash_alg)) {
> -                       put_unaligned_le16(hash_alg,
> -                                          &spec_event->digest_sizes[alg_count].algorithm_id);
> -                       put_unaligned_le16(hash_len,
> -                                          &spec_event->digest_sizes[alg_count].digest_size);
> -                       alg_count++;
> -               }
> -       }
> -
> -       spec_event->number_of_algorithms = alg_count;
> -       if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
> -           spec_event->number_of_algorithms < 1)
> -               goto out;
> -
> -       /*
> -        * the size of the spec event and placement of vendor_info_size
> -        * depends on supported algoriths
> -        */
> -       spec_event_size =
> -               offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
> -               spec_event->number_of_algorithms * sizeof(spec_event->digest_sizes[0]);
> -       /* no vendor info for us */
> -       memset(buffer + spec_event_size, 0, 1);
> -       /* add a byte for vendor_info_size in the spec event */
> -       spec_event_size += 1;
> -       *event_size = spec_event_size;
> -
> -       return EFI_SUCCESS;
> -
> -out:
> -       return ret;
> -}
> -
>  /**
>   * tcg2_uninit - remove the final event table and free efi memory on failures
>   */
> @@ -1722,7 +840,7 @@ out:
>  }
>
>  /**
> - * tcg2_measure_event() - common function to add event log and extend PCR
> + * measure_event() - common function to add event log and extend PCR
>   *
>   * @dev:               TPM device
>   * @pcr_index:         PCR index
> @@ -1732,14 +850,13 @@ out:
>   *
>   * Return:     status code
>   */
> -static efi_status_t
> -tcg2_measure_event(struct udevice *dev, u32 pcr_index, u32 event_type,
> -                  u32 size, u8 event[])
> +static efi_status_t measure_event(struct udevice *dev, u32 pcr_index,
> +                                 u32 event_type, u32 size, u8 event[])
>  {
>         struct tpml_digest_values digest_list;
>         efi_status_t ret;
>
> -       ret = tcg2_create_digest(event, size, &digest_list);
> +       ret = tcg2_create_digest(dev, event, size, &digest_list);
>         if (ret != EFI_SUCCESS)
>                 goto out;
>
> @@ -1766,9 +883,8 @@ static efi_status_t efi_append_scrtm_version(struct udevice *dev)
>  {
>         efi_status_t ret;
>
> -       ret = tcg2_measure_event(dev, 0, EV_S_CRTM_VERSION,
> -                                strlen(version_string) + 1,
> -                                (u8 *)version_string);
> +       ret = measure_event(dev, 0, EV_S_CRTM_VERSION,
> +                           strlen(version_string) + 1, (u8 *)version_string);
>
>         return ret;
>  }
> @@ -1784,12 +900,11 @@ static efi_status_t efi_init_event_log(void)
>          * vendor_info_size is currently set to 0, we need to change the length
>          * and allocate the flexible array member if this changes
>          */
> -       struct tcg_pcr_event *event_header = NULL;
> +       struct tcg2_event_log elog;
>         struct udevice *dev;
> -       size_t spec_event_size;
>         efi_status_t ret;
>
> -       ret = platform_get_tpm2_device(&dev);
> +       ret = tcg2_platform_get_tpm2(&dev);
>         if (ret != EFI_SUCCESS)
>                 return ret;
>
> @@ -1808,7 +923,6 @@ static efi_status_t efi_init_event_log(void)
>          * The log header is defined to be in SHA1 event log entry format.
>          * Setup event header
>          */
> -       event_header =  (struct tcg_pcr_event *)event_log.buffer;
>         event_log.pos = 0;
>         event_log.last_event_size = 0;
>         event_log.get_event_called = false;
> @@ -1819,34 +933,20 @@ static efi_status_t efi_init_event_log(void)
>          * Check if earlier firmware have passed any eventlog. Different
>          * platforms can use different ways to do so.
>          */
> -       ret = tcg2_get_fw_eventlog(dev, event_log.buffer, &event_log.pos);
> +       elog.log = event_log.buffer;
> +       elog.log_size = TPM2_EVENT_LOG_SIZE;
> +       ret = tcg2_log_prepare_buffer(dev, &elog, false);
> +       if (ret != EFI_SUCCESS)
> +               goto free_pool;
> +
> +       event_log.pos = elog.log_position;
> +
>         /*
> -        * If earlier firmware hasn't passed any eventlog, go ahead and
> -        * create the eventlog header.
> +        * Add SCRTM version to the log if previous firmmware
> +        * doesn't pass an eventlog.
>          */
> -       if (ret == EFI_NOT_FOUND) {
> -               put_unaligned_le32(0, &event_header->pcr_index);
> -               put_unaligned_le32(EV_NO_ACTION, &event_header->event_type);
> -               memset(&event_header->digest, 0, sizeof(event_header->digest));
> -               ret = create_specid_event(dev,
> -                                         (void *)((uintptr_t)event_log.buffer +
> -                                                  sizeof(*event_header)),
> -                                         &spec_event_size);
> -               if (ret != EFI_SUCCESS)
> -                       goto free_pool;
> -               put_unaligned_le32(spec_event_size, &event_header->event_size);
> -               event_log.pos = spec_event_size + sizeof(*event_header);
> -               event_log.last_event_size = event_log.pos;
> -
> -               /*
> -                * Add SCRTM version to the log if previous firmmware
> -                * doesn't pass an eventlog.
> -                */
> +       if (!elog.found)
>                 ret = efi_append_scrtm_version(dev);
> -       }
> -
> -       if (ret != EFI_SUCCESS)
> -               goto free_pool;
>
>         ret = create_final_event();
>         if (ret != EFI_SUCCESS)
> @@ -1899,8 +999,8 @@ static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index,
>                 memcpy((u16 *)event->unicode_name + event->unicode_name_length,
>                        data, data_size);
>         }
> -       ret = tcg2_measure_event(dev, pcr_index, event_type, event_size,
> -                                (u8 *)event);
> +       ret = measure_event(dev, pcr_index, event_type, event_size,
> +                           (u8 *)event);
>         free(event);
>         return ret;
>  }
> @@ -2011,8 +1111,8 @@ tcg2_measure_smbios(struct udevice *dev,
>
>         smbios_prepare_measurement(entry, smbios_copy);
>
> -       ret = tcg2_measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
> -                                (u8 *)event);
> +       ret = measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
> +                           (u8 *)event);
>         if (ret != EFI_SUCCESS)
>                 goto out;
>
> @@ -2163,7 +1263,7 @@ tcg2_measure_gpt_data(struct udevice *dev,
>                 gpt_e = (gpt_entry *)((u8 *)gpt_e + gpt_h->sizeof_partition_entry);
>         }
>
> -       ret = tcg2_measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8 *)event);
> +       ret = measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8 *)event);
>
>  out2:
>         free(gpt_h);
> @@ -2217,7 +1317,7 @@ efi_status_t efi_tcg2_measure_dtb(void *dtb)
>         if (!is_tcg2_protocol_installed())
>                 return EFI_SUCCESS;
>
> -       ret = platform_get_tpm2_device(&dev);
> +       ret = tcg2_platform_get_tpm2(&dev);
>         if (ret != EFI_SUCCESS)
>                 return EFI_SECURITY_VIOLATION;
>
> @@ -2242,7 +1342,7 @@ efi_status_t efi_tcg2_measure_dtb(void *dtb)
>         sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_mem_rsvmap(dtb), rsvmap_size);
>         sha256_finish(&hash_ctx, blob->data + blob->blob_description_size);
>
> -       ret = tcg2_measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob);
> +       ret = measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob);
>
>         free(blob);
>         return ret;
> @@ -2267,7 +1367,7 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
>         if (tcg2_efi_app_invoked)
>                 return EFI_SUCCESS;
>
> -       ret = platform_get_tpm2_device(&dev);
> +       ret = tcg2_platform_get_tpm2(&dev);
>         if (ret != EFI_SUCCESS)
>                 return EFI_SECURITY_VIOLATION;
>
> @@ -2275,9 +1375,9 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
>         if (ret != EFI_SUCCESS)
>                 goto out;
>
> -       ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION,
> -                                strlen(EFI_CALLING_EFI_APPLICATION),
> -                                (u8 *)EFI_CALLING_EFI_APPLICATION);
> +       ret = measure_event(dev, 4, EV_EFI_ACTION,
> +                           strlen(EFI_CALLING_EFI_APPLICATION),
> +                           (u8 *)EFI_CALLING_EFI_APPLICATION);
>         if (ret != EFI_SUCCESS)
>                 goto out;
>
> @@ -2293,8 +1393,8 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
>                 goto out;
>
>         for (pcr_index = 0; pcr_index <= 7; pcr_index++) {
> -               ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR,
> -                                        sizeof(event), (u8 *)&event);
> +               ret = measure_event(dev, pcr_index, EV_SEPARATOR,
> +                                   sizeof(event), (u8 *)&event);
>                 if (ret != EFI_SUCCESS)
>                         goto out;
>         }
> @@ -2317,13 +1417,13 @@ efi_status_t efi_tcg2_measure_efi_app_exit(void)
>         if (!is_tcg2_protocol_installed())
>                 return EFI_SUCCESS;
>
> -       ret = platform_get_tpm2_device(&dev);
> +       ret = tcg2_platform_get_tpm2(&dev);
>         if (ret != EFI_SUCCESS)
>                 return ret;
>
> -       ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION,
> -                                strlen(EFI_RETURNING_FROM_EFI_APPLICATION),
> -                                (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION);
> +       ret = measure_event(dev, 4, EV_EFI_ACTION,
> +                           strlen(EFI_RETURNING_FROM_EFI_APPLICATION),
> +                           (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION);
>         return ret;
>  }
>
> @@ -2348,19 +1448,19 @@ efi_tcg2_notify_exit_boot_services(struct efi_event *event, void *context)
>                 goto out;
>         }
>
> -       ret = platform_get_tpm2_device(&dev);
> +       ret = tcg2_platform_get_tpm2(&dev);
>         if (ret != EFI_SUCCESS)
>                 goto out;
>
> -       ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
> -                                strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
> -                                (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
> +       ret = measure_event(dev, 5, EV_EFI_ACTION,
> +                           strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
> +                           (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
>         if (ret != EFI_SUCCESS)
>                 goto out;
>
> -       ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
> -                                strlen(EFI_EXIT_BOOT_SERVICES_SUCCEEDED),
> -                                (u8 *)EFI_EXIT_BOOT_SERVICES_SUCCEEDED);
> +       ret = measure_event(dev, 5, EV_EFI_ACTION,
> +                           strlen(EFI_EXIT_BOOT_SERVICES_SUCCEEDED),
> +                           (u8 *)EFI_EXIT_BOOT_SERVICES_SUCCEEDED);
>
>  out:
>         EFI_EXIT(ret);
> @@ -2380,19 +1480,19 @@ efi_status_t efi_tcg2_notify_exit_boot_services_failed(void)
>         if (!is_tcg2_protocol_installed())
>                 return EFI_SUCCESS;
>
> -       ret = platform_get_tpm2_device(&dev);
> +       ret = tcg2_platform_get_tpm2(&dev);
>         if (ret != EFI_SUCCESS)
>                 goto out;
>
> -       ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
> -                                strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
> -                                (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
> +       ret = measure_event(dev, 5, EV_EFI_ACTION,
> +                           strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
> +                           (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
>         if (ret != EFI_SUCCESS)
>                 goto out;
>
> -       ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
> -                                strlen(EFI_EXIT_BOOT_SERVICES_FAILED),
> -                                (u8 *)EFI_EXIT_BOOT_SERVICES_FAILED);
> +       ret = measure_event(dev, 5, EV_EFI_ACTION,
> +                           strlen(EFI_EXIT_BOOT_SERVICES_FAILED),
> +                           (u8 *)EFI_EXIT_BOOT_SERVICES_FAILED);
>
>  out:
>         return ret;
> @@ -2462,7 +1562,7 @@ efi_status_t efi_tcg2_do_initial_measurement(void)
>         if (!is_tcg2_protocol_installed())
>                 return EFI_SUCCESS;
>
> -       ret = platform_get_tpm2_device(&dev);
> +       ret = tcg2_platform_get_tpm2(&dev);
>         if (ret != EFI_SUCCESS)
>                 return EFI_SECURITY_VIOLATION;
>
> @@ -2488,7 +1588,7 @@ efi_status_t efi_tcg2_register(void)
>         struct efi_event *event;
>         u32 err;
>
> -       ret = platform_get_tpm2_device(&dev);
> +       ret = tcg2_platform_get_tpm2(&dev);
>         if (ret != EFI_SUCCESS) {
>                 log_warning("Missing TPMv2 device for EFI_TCG_PROTOCOL\n");
>                 return EFI_SUCCESS;
> diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> index 9ab5b46df1..d22e21985b 100644
> --- a/lib/tpm-v2.c
> +++ b/lib/tpm-v2.c
> @@ -1,16 +1,705 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  /*
> + * Copyright (c) 2023 Linaro Limited
>   * Copyright (c) 2018 Bootlin
>   * Author: Miquel Raynal <miquel.raynal@bootlin.com>
>   */
>
>  #include <common.h>
>  #include <dm.h>
> +#include <dm/of_access.h>
> +#include <tpm_api.h>
>  #include <tpm-common.h>
>  #include <tpm-v2.h>
> +#include <u-boot/sha1.h>
> +#include <u-boot/sha256.h>
> +#include <u-boot/sha512.h>
> +#include <version_string.h>
> +#include <asm/io.h>
>  #include <linux/bitops.h>
> +#include <linux/unaligned/be_byteshift.h>
> +#include <linux/unaligned/generic.h>
> +#include <linux/unaligned/le_byteshift.h>
> +
>  #include "tpm-utils.h"
>
> +const enum tpm2_algorithms tpm2_supported_algorithms[4] = {
> +       TPM2_ALG_SHA1,
> +       TPM2_ALG_SHA256,
> +       TPM2_ALG_SHA384,
> +       TPM2_ALG_SHA512,
> +};
> +
> +int tcg2_get_active_pcr_banks(struct udevice *dev, u32 *active_pcr_banks)
> +{
> +       u32 supported = 0;
> +       u32 pcr_banks = 0;
> +       u32 active = 0;
> +       int rc;
> +
> +       rc = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
> +       if (rc)
> +               return rc;
> +
> +       *active_pcr_banks = active;
> +
> +       return 0;
> +}
> +
> +u32 tcg2_event_get_size(struct tpml_digest_values *digest_list)
> +{
> +       u32 len;
> +       size_t i;
> +
> +       len = offsetof(struct tcg_pcr_event2, digests);
> +       len += offsetof(struct tpml_digest_values, digests);
> +       for (i = 0; i < digest_list->count; ++i) {
> +               u16 l = tpm2_algorithm_to_len(digest_list->digests[i].hash_alg);
> +
> +               if (!l)
> +                       continue;
> +
> +               len += l + offsetof(struct tpmt_ha, digest);
> +       }
> +       len += sizeof(u32);
> +
> +       return len;
> +}
> +
> +int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length,
> +                      struct tpml_digest_values *digest_list)
> +{
> +       u8 final[sizeof(union tpmu_ha)];
> +       sha256_context ctx_256;
> +       sha512_context ctx_512;
> +       sha1_context ctx;
> +       u32 active;
> +       size_t i;
> +       u32 len;
> +       int rc;
> +
> +       rc = tcg2_get_active_pcr_banks(dev, &active);
> +       if (rc)
> +               return rc;
> +
> +       digest_list->count = 0;
> +       for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
> +               u32 mask =
> +                       tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
> +
> +               if (!(active & mask))
> +                       continue;
> +
> +               switch (tpm2_supported_algorithms[i]) {
> +               case TPM2_ALG_SHA1:
> +                       sha1_starts(&ctx);
> +                       sha1_update(&ctx, input, length);
> +                       sha1_finish(&ctx, final);
> +                       len = TPM2_SHA1_DIGEST_SIZE;
> +                       break;
> +               case TPM2_ALG_SHA256:
> +                       sha256_starts(&ctx_256);
> +                       sha256_update(&ctx_256, input, length);
> +                       sha256_finish(&ctx_256, final);
> +                       len = TPM2_SHA256_DIGEST_SIZE;
> +                       break;
> +               case TPM2_ALG_SHA384:
> +                       sha384_starts(&ctx_512);
> +                       sha384_update(&ctx_512, input, length);
> +                       sha384_finish(&ctx_512, final);
> +                       len = TPM2_SHA384_DIGEST_SIZE;
> +                       break;
> +               case TPM2_ALG_SHA512:
> +                       sha512_starts(&ctx_512);
> +                       sha512_update(&ctx_512, input, length);
> +                       sha512_finish(&ctx_512, final);
> +                       len = TPM2_SHA512_DIGEST_SIZE;
> +                       break;
> +               default:
> +                       printf("%s: unsupported algorithm %x\n", __func__,
> +                              tpm2_supported_algorithms[i]);
> +                       continue;
> +               }
> +
> +               digest_list->digests[digest_list->count].hash_alg =
> +                       tpm2_supported_algorithms[i];
> +               memcpy(&digest_list->digests[digest_list->count].digest, final,
> +                      len);
> +               digest_list->count++;
> +       }
> +
> +       return 0;
> +}
> +
> +void tcg2_log_append(u32 pcr_index, u32 event_type,
> +                    struct tpml_digest_values *digest_list, u32 size,
> +                    const u8 *event, u8 *log)
> +{
> +       size_t len;
> +       size_t pos;
> +       u32 i;
> +
> +       pos = offsetof(struct tcg_pcr_event2, pcr_index);
> +       put_unaligned_le32(pcr_index, log);
> +       pos = offsetof(struct tcg_pcr_event2, event_type);
> +       put_unaligned_le32(event_type, log + pos);
> +       pos = offsetof(struct tcg_pcr_event2, digests) +
> +               offsetof(struct tpml_digest_values, count);
> +       put_unaligned_le32(digest_list->count, log + pos);
> +
> +       pos = offsetof(struct tcg_pcr_event2, digests) +
> +               offsetof(struct tpml_digest_values, digests);
> +       for (i = 0; i < digest_list->count; ++i) {
> +               u16 hash_alg = digest_list->digests[i].hash_alg;
> +
> +               len = tpm2_algorithm_to_len(hash_alg);
> +               if (!len)
> +                       continue;
> +
> +               pos += offsetof(struct tpmt_ha, hash_alg);
> +               put_unaligned_le16(hash_alg, log + pos);
> +               pos += offsetof(struct tpmt_ha, digest);
> +               memcpy(log + pos, (u8 *)&digest_list->digests[i].digest, len);
> +               pos += len;
> +       }
> +
> +       put_unaligned_le32(size, log + pos);
> +       pos += sizeof(u32);
> +       memcpy(log + pos, event, size);
> +}
> +
> +static int tcg2_log_append_check(struct tcg2_event_log *elog, u32 pcr_index,
> +                                u32 event_type,
> +                                struct tpml_digest_values *digest_list,
> +                                u32 size, const u8 *event)
> +{
> +       u32 event_size;
> +       u8 *log;
> +
> +       event_size = size + tcg2_event_get_size(digest_list);
> +       if (elog->log_position + event_size > elog->log_size) {
> +               printf("%s: log too large: %u + %u > %u\n", __func__,
> +                      elog->log_position, event_size, elog->log_size);
> +               return -ENOBUFS;
> +       }
> +
> +       log = elog->log + elog->log_position;
> +       elog->log_position += event_size;
> +
> +       tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
> +
> +       return 0;
> +}
> +
> +static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog)
> +{
> +       struct tcg_efi_spec_id_event *ev;
> +       struct tcg_pcr_event *log;
> +       u32 event_size;
> +       u32 count = 0;
> +       u32 log_size;
> +       u32 active;
> +       u32 mask;
> +       size_t i;
> +       u16 len;
> +       int rc;
> +
> +       rc = tcg2_get_active_pcr_banks(dev, &active);
> +       if (rc)
> +               return rc;
> +
> +       event_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes);
> +       for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
> +               mask = tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
> +
> +               if (!(active & mask))
> +                       continue;
> +
> +               switch (tpm2_supported_algorithms[i]) {
> +               case TPM2_ALG_SHA1:
> +               case TPM2_ALG_SHA256:
> +               case TPM2_ALG_SHA384:
> +               case TPM2_ALG_SHA512:
> +                       count++;
> +                       break;
> +               default:
> +                       continue;
> +               }
> +       }
> +
> +       event_size += 1 +
> +               (sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count);
> +       log_size = offsetof(struct tcg_pcr_event, event) + event_size;
> +
> +       if (log_size > elog->log_size) {
> +               printf("%s: log too large: %u > %u\n", __func__, log_size,
> +                      elog->log_size);
> +               return -ENOBUFS;
> +       }
> +
> +       log = (struct tcg_pcr_event *)elog->log;
> +       put_unaligned_le32(0, &log->pcr_index);
> +       put_unaligned_le32(EV_NO_ACTION, &log->event_type);
> +       memset(&log->digest, 0, sizeof(log->digest));
> +       put_unaligned_le32(event_size, &log->event_size);
> +
> +       ev = (struct tcg_efi_spec_id_event *)log->event;
> +       strlcpy((char *)ev->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
> +               sizeof(ev->signature));
> +       put_unaligned_le32(0, &ev->platform_class);
> +       ev->spec_version_minor = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
> +       ev->spec_version_major = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
> +       ev->spec_errata = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
> +       ev->uintn_size = sizeof(size_t) / sizeof(u32);
> +       put_unaligned_le32(count, &ev->number_of_algorithms);
> +
> +       count = 0;
> +       for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
> +               mask = tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
> +
> +               if (!(active & mask))
> +                       continue;
> +
> +               len = tpm2_algorithm_to_len(tpm2_supported_algorithms[i]);
> +               if (!len)
> +                       continue;
> +
> +               put_unaligned_le16(tpm2_supported_algorithms[i],
> +                                  &ev->digest_sizes[count].algorithm_id);
> +               put_unaligned_le16(len, &ev->digest_sizes[count].digest_size);
> +               count++;
> +       }
> +
> +       *((u8 *)ev + (event_size - 1)) = 0;
> +       elog->log_position = log_size;
> +
> +       return 0;
> +}
> +
> +static int tcg2_replay_eventlog(struct tcg2_event_log *elog,
> +                               struct udevice *dev,
> +                               struct tpml_digest_values *digest_list,
> +                               u32 log_position)
> +{
> +       const u32 offset = offsetof(struct tcg_pcr_event2, digests) +
> +               offsetof(struct tpml_digest_values, digests);
> +       u32 event_size;
> +       u32 count;
> +       u16 algo;
> +       u32 pcr;
> +       u32 pos;
> +       u16 len;
> +       u8 *log;
> +       int rc;
> +       u32 i;
> +
> +       while (log_position + offset < elog->log_size) {
> +               log = elog->log + log_position;
> +
> +               pos = offsetof(struct tcg_pcr_event2, pcr_index);
> +               pcr = get_unaligned_le32(log + pos);
> +               pos = offsetof(struct tcg_pcr_event2, event_type);
> +               if (!get_unaligned_le32(log + pos))
> +                       return 0;
> +
> +               pos = offsetof(struct tcg_pcr_event2, digests) +
> +                       offsetof(struct tpml_digest_values, count);
> +               count = get_unaligned_le32(log + pos);
> +               if (count > ARRAY_SIZE(tpm2_supported_algorithms) ||
> +                   (digest_list->count && digest_list->count != count))
> +                       return 0;
> +
> +               pos = offsetof(struct tcg_pcr_event2, digests) +
> +                       offsetof(struct tpml_digest_values, digests);
> +               for (i = 0; i < count; ++i) {
> +                       pos += offsetof(struct tpmt_ha, hash_alg);
> +                       if (log_position + pos + sizeof(u16) >= elog->log_size)
> +                               return 0;
> +
> +                       algo = get_unaligned_le16(log + pos);
> +                       pos += offsetof(struct tpmt_ha, digest);
> +                       switch (algo) {
> +                       case TPM2_ALG_SHA1:
> +                       case TPM2_ALG_SHA256:
> +                       case TPM2_ALG_SHA384:
> +                       case TPM2_ALG_SHA512:
> +                               len = tpm2_algorithm_to_len(algo);
> +                               break;
> +                       default:
> +                               return 0;
> +                       }
> +
> +                       if (digest_list->count) {
> +                               if (algo != digest_list->digests[i].hash_alg ||
> +                                   log_position + pos + len >= elog->log_size)
> +                                       return 0;
> +
> +                               memcpy(digest_list->digests[i].digest.sha512,
> +                                      log + pos, len);
> +                       }
> +
> +                       pos += len;
> +               }
> +
> +               if (log_position + pos + sizeof(u32) >= elog->log_size)
> +                       return 0;
> +
> +               event_size = get_unaligned_le32(log + pos);
> +               pos += event_size + sizeof(u32);
> +               if (log_position + pos > elog->log_size)
> +                       return 0;
> +
> +               if (digest_list->count) {
> +                       rc = tcg2_pcr_extend(dev, pcr, digest_list);
> +                       if (rc)
> +                               return rc;
> +               }
> +
> +               log_position += pos;
> +       }
> +
> +       elog->log_position = log_position;
> +       elog->found = true;
> +       return 0;
> +}
> +
> +static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
> +{
> +       struct tpml_digest_values digest_list;
> +       struct tcg_efi_spec_id_event *event;
> +       struct tcg_pcr_event *log;
> +       u32 log_active;
> +       u32 calc_size;
> +       u32 active;
> +       u32 count;
> +       u32 evsz;
> +       u32 mask;
> +       u16 algo;
> +       u16 len;
> +       int rc;
> +       u32 i;
> +       u16 j;
> +
> +       if (elog->log_size <= offsetof(struct tcg_pcr_event, event))
> +               return 0;
> +
> +       log = (struct tcg_pcr_event *)elog->log;
> +       if (get_unaligned_le32(&log->pcr_index) != 0 ||
> +           get_unaligned_le32(&log->event_type) != EV_NO_ACTION)
> +               return 0;
> +
> +       for (i = 0; i < sizeof(log->digest); i++) {
> +               if (log->digest[i])
> +                       return 0;
> +       }
> +
> +       evsz = get_unaligned_le32(&log->event_size);
> +       if (evsz < offsetof(struct tcg_efi_spec_id_event, digest_sizes) ||
> +           evsz + offsetof(struct tcg_pcr_event, event) > elog->log_size)
> +               return 0;
> +
> +       event = (struct tcg_efi_spec_id_event *)log->event;
> +       if (memcmp(event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
> +                  sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03)))
> +               return 0;
> +
> +       if (event->spec_version_minor != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
> +           event->spec_version_major != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
> +               return 0;
> +
> +       count = get_unaligned_le32(&event->number_of_algorithms);
> +       if (count > ARRAY_SIZE(tpm2_supported_algorithms))
> +               return 0;
> +
> +       calc_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
> +               (sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count) +
> +               1;
> +       if (evsz != calc_size)
> +               return 0;
> +
> +       rc = tcg2_get_active_pcr_banks(dev, &active);
> +       if (rc)
> +               return rc;
> +
> +       digest_list.count = 0;
> +       log_active = 0;
> +
> +       for (i = 0; i < count; ++i) {
> +               algo = get_unaligned_le16(&event->digest_sizes[i].algorithm_id);
> +               mask = tpm2_algorithm_to_mask(algo);
> +
> +               if (!(active & mask))
> +                       return 0;
> +
> +               switch (algo) {
> +               case TPM2_ALG_SHA1:
> +               case TPM2_ALG_SHA256:
> +               case TPM2_ALG_SHA384:
> +               case TPM2_ALG_SHA512:
> +                       len = get_unaligned_le16(&event->digest_sizes[i].digest_size);
> +                       if (tpm2_algorithm_to_len(algo) != len)
> +                               return 0;
> +                       digest_list.digests[digest_list.count++].hash_alg = algo;
> +                       break;
> +               default:
> +                       return 0;
> +               }
> +
> +               log_active |= mask;
> +       }
> +
> +       /* Ensure the previous firmware extended all the PCRs. */
> +       if (log_active != active)
> +               return 0;
> +
> +       /* Read PCR0 to check if previous firmware extended the PCRs or not. */
> +       rc = tcg2_pcr_read(dev, 0, &digest_list);
> +       if (rc)
> +               return rc;
> +
> +       for (i = 0; i < digest_list.count; ++i) {
> +               len = tpm2_algorithm_to_len(digest_list.digests[i].hash_alg);
> +               for (j = 0; j < len; ++j) {
> +                       if (digest_list.digests[i].digest.sha512[j])
> +                               break;
> +               }
> +
> +               /* PCR is non-zero; it has been extended, so skip extending. */
> +               if (j != len) {
> +                       digest_list.count = 0;
> +                       break;
> +               }
> +       }
> +
> +       return tcg2_replay_eventlog(elog, dev, &digest_list,
> +                                   offsetof(struct tcg_pcr_event, event) +
> +                                   evsz);
> +}
> +
> +int tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
> +                   struct tpml_digest_values *digest_list)
> +{
> +       u32 rc;
> +       u32 i;
> +
> +       for (i = 0; i < digest_list->count; i++) {
> +               u32 alg = digest_list->digests[i].hash_alg;
> +
> +               rc = tpm2_pcr_extend(dev, pcr_index, alg,
> +                                    (u8 *)&digest_list->digests[i].digest,
> +                                    tpm2_algorithm_to_len(alg));
> +               if (rc) {
> +                       printf("%s: error pcr:%u alg:%08x\n", __func__,
> +                              pcr_index, alg);
> +                       return rc;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +int tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
> +                 struct tpml_digest_values *digest_list)
> +{
> +       struct tpm_chip_priv *priv;
> +       u32 rc;
> +       u32 i;
> +
> +       priv = dev_get_uclass_priv(dev);
> +       if (!priv)
> +               return -ENODEV;
> +
> +       for (i = 0; i < digest_list->count; i++) {
> +               u32 alg = digest_list->digests[i].hash_alg;
> +               u8 *digest = (u8 *)&digest_list->digests[i].digest;
> +
> +               rc = tpm2_pcr_read(dev, pcr_index, priv->pcr_select_min, alg,
> +                                  digest, tpm2_algorithm_to_len(alg), NULL);
> +               if (rc) {
> +                       printf("%s: error pcr:%u alg:%08x\n", __func__,
> +                              pcr_index, alg);
> +                       return rc;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +int tcg2_measure_data(struct udevice *dev, struct tcg2_event_log *elog,
> +                     u32 pcr_index, u32 size, const u8 *data, u32 event_type,
> +                     u32 event_size, const u8 *event)
> +{
> +       struct tpml_digest_values digest_list;
> +       int rc;
> +
> +       if (data)
> +               rc = tcg2_create_digest(dev, data, size, &digest_list);
> +       else
> +               rc = tcg2_create_digest(dev, event, event_size, &digest_list);
> +       if (rc)
> +               return rc;
> +
> +       rc = tcg2_pcr_extend(dev, pcr_index, &digest_list);
> +       if (rc)
> +               return rc;
> +
> +       return tcg2_log_append_check(elog, pcr_index, event_type, &digest_list,
> +                                    event_size, event);
> +}
> +
> +int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
> +                           bool ignore_existing_log)
> +{
> +       struct tcg2_event_log log;
> +       int rc;
> +
> +       elog->log_position = 0;
> +       elog->found = false;
> +
> +       rc = tcg2_platform_get_log(dev, (void **)&log.log, &log.log_size);
> +       if (!rc) {
> +               log.log_position = 0;
> +               log.found = false;
> +
> +               if (!ignore_existing_log) {
> +                       rc = tcg2_log_parse(dev, &log);
> +                       if (rc)
> +                               return rc;
> +               }
> +
> +               if (elog->log_size) {
> +                       if (log.found) {
> +                               if (elog->log_size < log.log_position)
> +                                       return -ENOSPC;
> +
> +                               /*
> +                                * Copy the discovered log into the user buffer
> +                                * if there's enough space.
> +                                */
> +                               memcpy(elog->log, log.log, log.log_position);
> +                       }
> +
> +                       unmap_physmem(log.log, MAP_NOCACHE);
> +               } else {
> +                       elog->log = log.log;
> +                       elog->log_size = log.log_size;
> +               }
> +
> +               elog->log_position = log.log_position;
> +               elog->found = log.found;
> +       }
> +
> +       /*
> +        * Initialize the log buffer if no log was discovered and the buffer is
> +        * valid. User's can pass in their own buffer as a fallback if no
> +        * memory region is found.
> +        */
> +       if (!elog->found && elog->log_size)
> +               rc = tcg2_log_init(dev, elog);
> +
> +       return rc;
> +}
> +
> +int tcg2_measurement_init(struct udevice **dev, struct tcg2_event_log *elog,
> +                         bool ignore_existing_log)
> +{
> +       int rc;
> +
> +       rc = tcg2_platform_get_tpm2(dev);
> +       if (rc)
> +               return rc;
> +
> +       rc = tpm_auto_start(*dev);
> +       if (rc)
> +               return rc;
> +
> +       rc = tcg2_log_prepare_buffer(*dev, elog, ignore_existing_log);
> +       if (rc) {
> +               tcg2_measurement_term(*dev, elog, true);
> +               return rc;
> +       }
> +
> +       rc = tcg2_measure_event(*dev, elog, 0, EV_S_CRTM_VERSION,
> +                               strlen(version_string) + 1,
> +                               (u8 *)version_string);
> +       if (rc) {
> +               tcg2_measurement_term(*dev, elog, true);
> +               return rc;
> +       }
> +
> +       return 0;
> +}
> +
> +void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
> +                          bool error)
> +{
> +       u32 event = error ? 0x1 : 0xffffffff;
> +       int i;
> +
> +       for (i = 0; i < 8; ++i)
> +               tcg2_measure_event(dev, elog, i, EV_SEPARATOR, sizeof(event),
> +                                  (const u8 *)&event);
> +
> +       if (elog->log)
> +               unmap_physmem(elog->log, MAP_NOCACHE);
> +}
> +
> +__weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size)
> +{
> +       const __be32 *addr_prop;
> +       const __be32 *size_prop;
> +       int asize;
> +       int ssize;
> +
> +       *addr = NULL;
> +       *size = 0;
> +
> +       addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize);
> +       if (!addr_prop)
> +               addr_prop = dev_read_prop(dev, "linux,sml-base", &asize);
> +
> +       size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize);
> +       if (!size_prop)
> +               size_prop = dev_read_prop(dev, "linux,sml-size", &ssize);
> +
> +       if (addr_prop && size_prop) {
> +               u64 a = of_read_number(addr_prop, asize / sizeof(__be32));
> +               u64 s = of_read_number(size_prop, ssize / sizeof(__be32));
> +
> +               *addr = map_physmem(a, s, MAP_NOCACHE);
> +               *size = (u32)s;
> +       } else {
> +               struct ofnode_phandle_args args;
> +               phys_addr_t a;
> +               phys_size_t s;
> +
> +               if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
> +                                              0, &args))
> +                       return -ENODEV;
> +
> +               a = ofnode_get_addr_size(args.node, "reg", &s);
> +               if (a == FDT_ADDR_T_NONE)
> +                       return -ENOMEM;
> +
> +               *addr = map_physmem(a, s, MAP_NOCACHE);
> +               *size = (u32)s;
> +       }
> +
> +       return 0;
> +}
> +
> +__weak int tcg2_platform_get_tpm2(struct udevice **dev)
> +{
> +       for_each_tpm_device(*dev) {
> +               if (tpm_get_version(*dev) == TPM_V2)
> +                       return 0;
> +       }
> +
> +       return -ENODEV;
> +}
> +
> +__weak void tcg2_platform_startup_error(struct udevice *dev, int rc) {}
> +
>  u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
>  {
>         const u8 command_v2[12] = {
> @@ -359,6 +1048,131 @@ u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
>         return 0;
>  }
>
> +static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
> +{
> +       u8 response[(sizeof(struct tpms_capability_data) -
> +               offsetof(struct tpms_capability_data, data))];
> +       u32 properties_offset =
> +               offsetof(struct tpml_tagged_tpm_property, tpm_property) +
> +               offsetof(struct tpms_tagged_property, value);
> +       u32 ret;
> +
> +       memset(response, 0, sizeof(response));
> +       ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
> +                                 TPM2_PT_PCR_COUNT, response, 1);
> +       if (ret)
> +               return ret;
> +
> +       *num_pcr = get_unaligned_be32(response + properties_offset);
> +       if (*num_pcr > TPM2_MAX_PCRS) {
> +               printf("%s: too many pcrs: %u\n", __func__, *num_pcr);
> +               return -E2BIG;
> +       }
> +
> +       return 0;
> +}
> +
> +static bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection)
> +{
> +       int i;
> +
> +       /*
> +        * check the pcr_select. If at least one of the PCRs supports the
> +        * algorithm add it on the active ones
> +        */
> +       for (i = 0; i < selection->size_of_select; i++) {
> +               if (selection->pcr_select[i])
> +                       return true;
> +       }
> +
> +       return false;
> +}
> +
> +int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
> +                     u32 *pcr_banks)
> +{
> +       u8 response[(sizeof(struct tpms_capability_data) -
> +               offsetof(struct tpms_capability_data, data))];
> +       struct tpml_pcr_selection pcrs;
> +       u32 num_pcr;
> +       size_t i;
> +       u32 ret;
> +
> +       *supported_pcr = 0;
> +       *active_pcr = 0;
> +       *pcr_banks = 0;
> +       memset(response, 0, sizeof(response));
> +       ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
> +       if (ret)
> +               return ret;
> +
> +       pcrs.count = get_unaligned_be32(response);
> +       /*
> +        * We only support 5 algorithms for now so check against that
> +        * instead of TPM2_NUM_PCR_BANKS
> +        */
> +       if (pcrs.count > ARRAY_SIZE(tpm2_supported_algorithms) ||
> +           pcrs.count < 1) {
> +               printf("%s: too many pcrs: %u\n", __func__, pcrs.count);
> +               return -EMSGSIZE;
> +       }
> +
> +       ret = tpm2_get_num_pcr(dev, &num_pcr);
> +       if (ret)
> +               return ret;
> +
> +       for (i = 0; i < pcrs.count; i++) {
> +               /*
> +                * Definition of TPMS_PCR_SELECTION Structure
> +                * hash: u16
> +                * size_of_select: u8
> +                * pcr_select: u8 array
> +                *
> +                * The offsets depend on the number of the device PCRs
> +                * so we have to calculate them based on that
> +                */
> +               u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
> +                       i * offsetof(struct tpms_pcr_selection, pcr_select) +
> +                       i * ((num_pcr + 7) / 8);
> +               u32 size_select_offset =
> +                       hash_offset + offsetof(struct tpms_pcr_selection,
> +                                              size_of_select);
> +               u32 pcr_select_offset =
> +                       hash_offset + offsetof(struct tpms_pcr_selection,
> +                                              pcr_select);
> +
> +               pcrs.selection[i].hash =
> +                       get_unaligned_be16(response + hash_offset);
> +               pcrs.selection[i].size_of_select =
> +                       __get_unaligned_be(response + size_select_offset);
> +               if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX) {
> +                       printf("%s: pcrs selection too large: %u\n", __func__,
> +                              pcrs.selection[i].size_of_select);
> +                       return -ENOBUFS;
> +               }
> +               /* copy the array of pcr_select */
> +               memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset,
> +                      pcrs.selection[i].size_of_select);
> +       }
> +
> +       for (i = 0; i < pcrs.count; i++) {
> +               u32 hash_mask = tpm2_algorithm_to_mask(pcrs.selection[i].hash);
> +
> +               if (hash_mask) {
> +                       *supported_pcr |= hash_mask;
> +                       if (tpm2_is_active_pcr(&pcrs.selection[i]))
> +                               *active_pcr |= hash_mask;
> +               } else {
> +                       printf("%s: unknown algorithm %x\n", __func__,
> +                              pcrs.selection[i].hash);
> +               }
> +       }
> +
> +       *pcr_banks = pcrs.count;
> +
> +       return 0;
> +}
> +
>  u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
>  {
>         u8 command_v2[COMMAND_BUFFER_SIZE] = {
> --
> 2.31.1
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v9 3/6] tpm: Support boot measurements
  2023-04-06  9:18   ` Ilias Apalodimas
@ 2023-04-10 16:18     ` Eddie James
  2023-04-11  8:46       ` Ilias Apalodimas
  0 siblings, 1 reply; 16+ messages in thread
From: Eddie James @ 2023-04-10 16:18 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: u-boot, sjg, xypron.glpk, joel


On 4/6/23 04:18, Ilias Apalodimas wrote:
> Hi Eddie,
>
> Do you plan on resending this?
> If yes, I can spend some time trying to figure out the CI failures and
> send you a patch.


Hi,

Yes I do, I have been short on time. I was a bit confused by the CI, it 
didn't seem to run with the updated v9? I believed I had fixed at least 
some of the failures with patch 2 to update the sandbox driver. I also 
haven't figured out how to run the ci suite locally

Thanks,

Eddie

>
> Thanks
> /Ilias
>
>
> On Wed, 8 Mar 2023 at 23:25, Eddie James <eajames@linux.ibm.com> wrote:
>> Add TPM2 functions to support boot measurement. This includes
>> starting up the TPM, initializing/appending the event log, and
>> measuring the U-Boot version. Much of the code was used in the
>> EFI subsystem, so remove it there and use the common functions.
>>
>> Signed-off-by: Eddie James <eajames@linux.ibm.com>
>> ---
>> Changes since v8:
>>   - Fix log parsing again - any data corruption seen while replaying the
>>     event log was failing the entire measurement.
>>   - Added an option to ignore the existing log. This should only be used
>>     for systems that know that U-Boot is the first stage bootloader. This
>>     is necessary because the reserved memory region may persist through
>>     resets and so U-Boot attempts to append to the previous boot's log.
>>
>> Changes since v7:
>>   - Change name of tcg2_init_log and add more documentation
>>   - Add a check, when parsing the event log header, to ensure that the
>>     previous stage bootloader used all the active PCRs.
>>   - Change name of tcg2_log_find_end
>>   - Fix the greater than or equal to check to exit the log parsing
>>   - Make sure log_position is 0 if there is any error discovering the log
>>   - Return errors parsing the log if the data is corrupt so that we don't
>>     end up with half a log
>>
>> Changes since v6:
>>   - Added Linaro copyright for all the EFI moved code
>>   - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
>>     copy any discovered event log to the user's log if passed in.
>>
>> Changes since v5:
>>   - Remove unused platform_get_eventlog in efi_tcg2.c
>>   - First look for tpm_event_log_* properties instead of linux,sml-*
>>   - Fix efi_tcg2.c compilation
>>   - Select SHA* configs
>>
>> Changes since v4:
>>   - Remove tcg2_measure_event function and check for NULL data in
>>     tcg2_measure_data
>>   - Use tpm_auto_startup
>>   - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
>>
>> Changes since v3:
>>   - Reordered headers
>>   - Refactored more of EFI code into common code
>>      Removed digest_info structure and instead used the common alg_to_mask
>>        and alg_to_len
>>      Improved event log parsing in common code to get it equivalent to EFI
>>        Common code now extends PCR if previous bootloader stage couldn't
>>        No need to allocate memory in the common code, so EFI copies the
>>        discovered buffer like it did before
>>      Rename efi measure_event function
>>
>> Changes since v1:
>>   - Refactor TPM layer functions to allow EFI system to use them, and
>>     remove duplicate EFI functions
>>
>>   include/efi_tcg2.h        |   44 --
>>   include/tpm-v2.h          |  259 +++++++++
>>   lib/Kconfig               |    4 +
>>   lib/efi_loader/efi_tcg2.c | 1054 +++----------------------------------
>>   lib/tpm-v2.c              |  814 ++++++++++++++++++++++++++++
>>   5 files changed, 1154 insertions(+), 1021 deletions(-)
>>
>> diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
>> index b1c3abd097..b21c5cb3dd 100644
>> --- a/include/efi_tcg2.h
>> +++ b/include/efi_tcg2.h
>> @@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
>>   #define BOOT_SERVICE_CAPABILITY_MIN \
>>          offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks)
>>
>> -#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
>> -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
>> -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
>> -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
>> -
>> -/**
>> - *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm information
>> - *
>> - *  @algorithm_id:     algorithm defined in enum tpm2_algorithms
>> - *  @digest_size:      size of the algorithm
>> - */
>> -struct tcg_efi_spec_id_event_algorithm_size {
>> -       u16      algorithm_id;
>> -       u16      digest_size;
>> -} __packed;
>> -
>> -/**
>> - * struct TCG_EfiSpecIDEventStruct - content of the event log header
>> - *
>> - * @signature:                 signature, set to Spec ID Event03
>> - * @platform_class:            class defined in TCG ACPI Specification
>> - *                             Client  Common Header.
>> - * @spec_version_minor:                minor version
>> - * @spec_version_major:                major version
>> - * @spec_version_errata:       major version
>> - * @uintn_size:                        size of the efi_uintn_t fields used in various
>> - *                             data structures used in this specification.
>> - *                             0x01 indicates u32  and 0x02  indicates u64
>> - * @number_of_algorithms:      hashing algorithms used in this event log
>> - * @digest_sizes:              array of number_of_algorithms pairs
>> - *                             1st member defines the algorithm id
>> - *                             2nd member defines the algorithm size
>> - */
>> -struct tcg_efi_spec_id_event {
>> -       u8 signature[16];
>> -       u32 platform_class;
>> -       u8 spec_version_minor;
>> -       u8 spec_version_major;
>> -       u8 spec_errata;
>> -       u8 uintn_size;
>> -       u32 number_of_algorithms;
>> -       struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
>> -} __packed;
>> -
>>   /**
>>    * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event Log
>>    * @version:           version number for this structure
>> diff --git a/include/tpm-v2.h b/include/tpm-v2.h
>> index 6684033deb..33dd103767 100644
>> --- a/include/tpm-v2.h
>> +++ b/include/tpm-v2.h
>> @@ -216,6 +216,50 @@ struct tcg_pcr_event2 {
>>          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.
>>    *
>> @@ -342,6 +386,26 @@ enum tpm2_algorithms {
>>          TPM2_ALG_SM3_256        = 0x12,
>>   };
>>
>> +extern const enum tpm2_algorithms tpm2_supported_algorithms[4];
>> +
>> +static inline u16 tpm2_algorithm_to_len(enum tpm2_algorithms a)
>> +{
>> +       switch (a) {
>> +       case TPM2_ALG_SHA1:
>> +               return TPM2_SHA1_DIGEST_SIZE;
>> +       case TPM2_ALG_SHA256:
>> +               return TPM2_SHA256_DIGEST_SIZE;
>> +       case TPM2_ALG_SHA384:
>> +               return TPM2_SHA384_DIGEST_SIZE;
>> +       case TPM2_ALG_SHA512:
>> +               return TPM2_SHA512_DIGEST_SIZE;
>> +       default:
>> +               return 0;
>> +       }
>> +}
>> +
>> +#define tpm2_algorithm_to_mask(a)      (1 << (a))
>> +
>>   /* NV index attributes */
>>   enum tpm_index_attrs {
>>          TPMA_NV_PPWRITE         = 1UL << 0,
>> @@ -421,6 +485,188 @@ enum {
>>          HR_NV_INDEX             = TPM_HT_NV_INDEX << HR_SHIFT,
>>   };
>>
>> +/**
>> + * 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.
>>    *
>> @@ -540,6 +786,19 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
>>   u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
>>                          void *buf, size_t prop_count);
>>
>> +/**
>> + * tpm2_get_pcr_info() - get the supported, active PCRs and number of banks
>> + *
>> + * @dev:               TPM device
>> + * @supported_pcr:     bitmask with the algorithms supported
>> + * @active_pcr:                bitmask with the active algorithms
>> + * @pcr_banks:         number of PCR banks
>> + *
>> + * @return 0 on success, code of operation or negative errno on failure
>> + */
>> +int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
>> +                     u32 *pcr_banks);
>> +
>>   /**
>>    * Issue a TPM2_DictionaryAttackLockReset command.
>>    *
>> diff --git a/lib/Kconfig b/lib/Kconfig
>> index 83e5edd73b..7a146c293f 100644
>> --- a/lib/Kconfig
>> +++ b/lib/Kconfig
>> @@ -411,6 +411,10 @@ config TPM
>>          bool "Trusted Platform Module (TPM) Support"
>>          depends on DM
>>          imply DM_RNG
>> +       select SHA1
>> +       select SHA256
>> +       select SHA384
>> +       select SHA512
>>          help
>>            This enables support for TPMs which can be used to provide security
>>            features for your board. The TPM can be connected via LPC or I2C
>> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
>> index a83ae7a46c..5f0f4b5dd2 100644
>> --- a/lib/efi_loader/efi_tcg2.c
>> +++ b/lib/efi_loader/efi_tcg2.c
>> @@ -66,35 +66,6 @@ static bool tcg2_efi_app_invoked;
>>   static const efi_guid_t efi_guid_tcg2_protocol = EFI_TCG2_PROTOCOL_GUID;
>>   static const efi_guid_t efi_guid_final_events = EFI_TCG2_FINAL_EVENTS_TABLE_GUID;
>>
>> -struct digest_info {
>> -       u16 hash_alg;
>> -       u32 hash_mask;
>> -       u16 hash_len;
>> -};
>> -
>> -static const struct digest_info hash_algo_list[] = {
>> -       {
>> -               TPM2_ALG_SHA1,
>> -               EFI_TCG2_BOOT_HASH_ALG_SHA1,
>> -               TPM2_SHA1_DIGEST_SIZE,
>> -       },
>> -       {
>> -               TPM2_ALG_SHA256,
>> -               EFI_TCG2_BOOT_HASH_ALG_SHA256,
>> -               TPM2_SHA256_DIGEST_SIZE,
>> -       },
>> -       {
>> -               TPM2_ALG_SHA384,
>> -               EFI_TCG2_BOOT_HASH_ALG_SHA384,
>> -               TPM2_SHA384_DIGEST_SIZE,
>> -       },
>> -       {
>> -               TPM2_ALG_SHA512,
>> -               EFI_TCG2_BOOT_HASH_ALG_SHA512,
>> -               TPM2_SHA512_DIGEST_SIZE,
>> -       },
>> -};
>> -
>>   struct variable_info {
>>          const u16       *name;
>>          bool            accept_empty;
>> @@ -113,46 +84,6 @@ static struct variable_info secure_variables[] = {
>>          {u"AuditMode",          false,  1},
>>   };
>>
>> -#define MAX_HASH_COUNT ARRAY_SIZE(hash_algo_list)
>> -
>> -/**
>> - * alg_to_mask - Get a TCG hash mask for algorithms
>> - *
>> - * @hash_alg: TCG defined algorithm
>> - *
>> - * @Return: TCG hashing algorithm bitmaps, 0 if the algorithm is not supported
>> - */
>> -static u32 alg_to_mask(u16 hash_alg)
>> -{
>> -       size_t i;
>> -
>> -       for (i = 0; i < MAX_HASH_COUNT; i++) {
>> -               if (hash_algo_list[i].hash_alg == hash_alg)
>> -                       return hash_algo_list[i].hash_mask;
>> -       }
>> -
>> -       return 0;
>> -}
>> -
>> -/**
>> - * alg_to_len - Get a TCG hash len for algorithms
>> - *
>> - * @hash_alg: TCG defined algorithm
>> - *
>> - * @Return: len of chosen algorithm, 0 if the algorithm is not supported
>> - */
>> -static u16 alg_to_len(u16 hash_alg)
>> -{
>> -       size_t i;
>> -
>> -       for (i = 0; i < MAX_HASH_COUNT; i++) {
>> -               if (hash_algo_list[i].hash_alg == hash_alg)
>> -                       return hash_algo_list[i].hash_len;
>> -       }
>> -
>> -       return 0;
>> -}
>> -
>>   static bool is_tcg2_protocol_installed(void)
>>   {
>>          struct efi_handler *handler;
>> @@ -162,145 +93,6 @@ static bool is_tcg2_protocol_installed(void)
>>          return ret == EFI_SUCCESS;
>>   }
>>
>> -static u32 tcg_event_final_size(struct tpml_digest_values *digest_list)
>> -{
>> -       u32 len;
>> -       size_t i;
>> -
>> -       len = offsetof(struct tcg_pcr_event2, digests);
>> -       len += offsetof(struct tpml_digest_values, digests);
>> -       for (i = 0; i < digest_list->count; i++) {
>> -               u16 hash_alg = digest_list->digests[i].hash_alg;
>> -
>> -               len += offsetof(struct tpmt_ha, digest);
>> -               len += alg_to_len(hash_alg);
>> -       }
>> -       len += sizeof(u32); /* tcg_pcr_event2 event_size*/
>> -
>> -       return len;
>> -}
>> -
>> -/* tcg2_pcr_extend - Extend PCRs for a TPM2 device for a given tpml_digest_values
>> - *
>> - * @dev:               device
>> - * @digest_list:       list of digest algorithms to extend
>> - *
>> - * @Return: status code
>> - */
>> -static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
>> -                                   struct tpml_digest_values *digest_list)
>> -{
>> -       u32 rc;
>> -       size_t i;
>> -
>> -       for (i = 0; i < digest_list->count; i++) {
>> -               u32 alg = digest_list->digests[i].hash_alg;
>> -
>> -               rc = tpm2_pcr_extend(dev, pcr_index, alg,
>> -                                    (u8 *)&digest_list->digests[i].digest,
>> -                                    alg_to_len(alg));
>> -               if (rc) {
>> -                       EFI_PRINT("Failed to extend PCR\n");
>> -                       return EFI_DEVICE_ERROR;
>> -               }
>> -       }
>> -
>> -       return EFI_SUCCESS;
>> -}
>> -
>> -/* tcg2_pcr_read - Read PCRs for a TPM2 device for a given tpml_digest_values
>> - *
>> - * @dev:               device
>> - * @pcr_index:         PCR index
>> - * @digest_list:       list of digest algorithms to extend
>> - *
>> - * @Return: status code
>> - */
>> -static efi_status_t tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
>> -                                 struct tpml_digest_values *digest_list)
>> -{
>> -       struct tpm_chip_priv *priv;
>> -       unsigned int updates, pcr_select_min;
>> -       u32 rc;
>> -       size_t i;
>> -
>> -       priv = dev_get_uclass_priv(dev);
>> -       if (!priv)
>> -               return EFI_DEVICE_ERROR;
>> -
>> -       pcr_select_min = priv->pcr_select_min;
>> -
>> -       for (i = 0; i < digest_list->count; i++) {
>> -               u16 hash_alg = digest_list->digests[i].hash_alg;
>> -               u8 *digest = (u8 *)&digest_list->digests[i].digest;
>> -
>> -               rc = tpm2_pcr_read(dev, pcr_index, pcr_select_min,
>> -                                  hash_alg, digest, alg_to_len(hash_alg),
>> -                                  &updates);
>> -               if (rc) {
>> -                       EFI_PRINT("Failed to read PCR\n");
>> -                       return EFI_DEVICE_ERROR;
>> -               }
>> -       }
>> -
>> -       return EFI_SUCCESS;
>> -}
>> -
>> -/* put_event - Append an agile event to an eventlog
>> - *
>> - * @pcr_index:         PCR index
>> - * @event_type:                type of event added
>> - * @digest_list:       list of digest algorithms to add
>> - * @size:              size of event
>> - * @event:             event to add
>> - * @log:               log buffer to append the event
>> - *
>> - */
>> -static void put_event(u32 pcr_index, u32 event_type,
>> -                     struct tpml_digest_values *digest_list, u32 size,
>> -                     u8 event[], void *log)
>> -{
>> -       size_t pos;
>> -       size_t i;
>> -       u32 event_size;
>> -
>> -       /*
>> -        * size refers to the length of event[] only, we need to check against
>> -        * the final tcg_pcr_event2 size
>> -        */
>> -       event_size = size + tcg_event_final_size(digest_list);
>> -
>> -       put_unaligned_le32(pcr_index, log);
>> -       pos = offsetof(struct tcg_pcr_event2, event_type);
>> -       put_unaligned_le32(event_type, (void *)((uintptr_t)log + pos));
>> -       pos = offsetof(struct tcg_pcr_event2, digests); /* count */
>> -       put_unaligned_le32(digest_list->count, (void *)((uintptr_t)log + pos));
>> -
>> -       pos += offsetof(struct tpml_digest_values, digests);
>> -       for (i = 0; i < digest_list->count; i++) {
>> -               u16 hash_alg = digest_list->digests[i].hash_alg;
>> -               u8 *digest = (u8 *)&digest_list->digests[i].digest;
>> -
>> -               put_unaligned_le16(hash_alg, (void *)((uintptr_t)log + pos));
>> -               pos += offsetof(struct tpmt_ha, digest);
>> -               memcpy((void *)((uintptr_t)log + pos), digest, alg_to_len(hash_alg));
>> -               pos += alg_to_len(hash_alg);
>> -       }
>> -
>> -       put_unaligned_le32(size, (void *)((uintptr_t)log + pos));
>> -       pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
>> -       memcpy((void *)((uintptr_t)log + pos), event, size);
>> -       pos += size;
>> -
>> -       /*
>> -        * make sure the calculated buffer is what we checked against
>> -        * This check should never fail.  It checks the code above is
>> -        * calculating the right length for the event we are adding
>> -        */
>> -       if (pos != event_size)
>> -               log_err("Appending to the EventLog failed\n");
>> -}
>> -
>>   /* tcg2_agile_log_append - Append an agile event to an eventlog
>>    *
>>    * @pcr_index:         PCR index
>> @@ -317,7 +109,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
>>                                            u32 size, u8 event[])
>>   {
>>          void *log = (void *)((uintptr_t)event_log.buffer + event_log.pos);
>> -       u32 event_size = size + tcg_event_final_size(digest_list);
>> +       u32 event_size = size + tcg2_event_get_size(digest_list);
>>          struct efi_tcg2_final_events_table *final_event;
>>          efi_status_t ret = EFI_SUCCESS;
>>
>> @@ -328,7 +120,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
>>                          event_log.truncated = true;
>>                          return EFI_VOLUME_FULL;
>>                  }
>> -               put_event(pcr_index, event_type, digest_list, size, event, log);
>> +               tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
>>                  event_log.pos += event_size;
>>                  event_log.last_event_size = event_size;
>>          }
>> @@ -341,7 +133,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
>>                  return EFI_VOLUME_FULL;
>>
>>          log = (void *)((uintptr_t)event_log.final_buffer + event_log.final_pos);
>> -       put_event(pcr_index, event_type, digest_list, size, event, log);
>> +       tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
>>
>>          final_event = event_log.final_buffer;
>>          final_event->number_of_events++;
>> @@ -350,66 +142,6 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type,
>>          return ret;
>>   }
>>
>> -/**
>> - * platform_get_tpm_device() - retrieve TPM device
>> - *
>> - * This function retrieves the udevice implementing a TPM
>> - *
>> - * This function may be overridden if special initialization is needed.
>> - *
>> - * @dev:       udevice
>> - * Return:     status code
>> - */
>> -__weak efi_status_t platform_get_tpm2_device(struct udevice **dev)
>> -{
>> -       for_each_tpm_device(*dev) {
>> -               /* Only support TPMv2 devices */
>> -               if (tpm_get_version(*dev) == TPM_V2)
>> -                       return EFI_SUCCESS;
>> -       }
>> -
>> -       return EFI_NOT_FOUND;
>> -}
>> -
>> -/**
>> - * platform_get_eventlog() - retrieve the eventlog address and size
>> - *
>> - * This function retrieves the eventlog address and size if the underlying
>> - * firmware has done some measurements and passed them.
>> - *
>> - * This function may be overridden based on platform specific method of
>> - * passing the eventlog address and size.
>> - *
>> - * @dev:       udevice
>> - * @addr:      eventlog address
>> - * @sz:                eventlog size
>> - * Return:     status code
>> - */
>> -__weak efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr,
>> -                                         u32 *sz)
>> -{
>> -       const u64 *basep;
>> -       const u32 *sizep;
>> -
>> -       basep = dev_read_prop(dev, "tpm_event_log_addr", NULL);
>> -       if (!basep)
>> -               return EFI_NOT_FOUND;
>> -
>> -       *addr = be64_to_cpup((__force __be64 *)basep);
>> -
>> -       sizep = dev_read_prop(dev, "tpm_event_log_size", NULL);
>> -       if (!sizep)
>> -               return EFI_NOT_FOUND;
>> -
>> -       *sz = be32_to_cpup((__force __be32 *)sizep);
>> -       if (*sz == 0) {
>> -               log_debug("event log empty\n");
>> -               return EFI_NOT_FOUND;
>> -       }
>> -
>> -       return EFI_SUCCESS;
>> -}
>> -
>>   /**
>>    * tpm2_get_max_command_size() - get the supported max command size
>>    *
>> @@ -485,239 +217,6 @@ static int tpm2_get_manufacturer_id(struct udevice *dev, u32 *manufacturer_id)
>>          return 0;
>>   }
>>
>> -/**
>> - * tpm2_get_num_pcr() - get the number of PCRs
>> - *
>> - * @dev:               TPM device
>> - * @manufacturer_id:   output buffer for the number
>> - *
>> - * Return: 0 on success, -1 on error
>> - */
>> -static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
>> -{
>> -       u8 response[TPM2_RESPONSE_BUFFER_SIZE];
>> -       u32 ret;
>> -
>> -       memset(response, 0, sizeof(response));
>> -       ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
>> -                                 TPM2_PT_PCR_COUNT, response, 1);
>> -       if (ret)
>> -               return -1;
>> -
>> -       *num_pcr = get_unaligned_be32(response + properties_offset);
>> -       if (*num_pcr > TPM2_MAX_PCRS)
>> -               return -1;
>> -
>> -       return 0;
>> -}
>> -
>> -/**
>> - * is_active_pcr() - Check if a supported algorithm is active
>> - *
>> - * @dev:               TPM device
>> - * @selection:         struct of PCR information
>> - *
>> - * Return: true if PCR is active
>> - */
>> -static bool is_active_pcr(struct tpms_pcr_selection *selection)
>> -{
>> -       int i;
>> -       /*
>> -        * check the pcr_select. If at least one of the PCRs supports the
>> -        * algorithm add it on the active ones
>> -        */
>> -       for (i = 0; i < selection->size_of_select; i++) {
>> -               if (selection->pcr_select[i])
>> -                       return true;
>> -       }
>> -
>> -       return false;
>> -}
>> -
>> -/**
>> - * tpm2_get_pcr_info() - get the supported, active PCRs and number of banks
>> - *
>> - * @dev:               TPM device
>> - * @supported_pcr:     bitmask with the algorithms supported
>> - * @active_pcr:                bitmask with the active algorithms
>> - * @pcr_banks:         number of PCR banks
>> - *
>> - * Return: 0 on success, -1 on error
>> - */
>> -static int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr,
>> -                            u32 *active_pcr, u32 *pcr_banks)
>> -{
>> -       u8 response[TPM2_RESPONSE_BUFFER_SIZE];
>> -       struct tpml_pcr_selection pcrs;
>> -       u32 ret, num_pcr;
>> -       size_t i;
>> -       int tpm_ret;
>> -
>> -       *supported_pcr = 0;
>> -       *active_pcr = 0;
>> -       *pcr_banks = 0;
>> -       memset(response, 0, sizeof(response));
>> -       ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
>> -       if (ret)
>> -               goto out;
>> -
>> -       pcrs.count = get_unaligned_be32(response);
>> -       /*
>> -        * We only support 5 algorithms for now so check against that
>> -        * instead of TPM2_NUM_PCR_BANKS
>> -        */
>> -       if (pcrs.count > MAX_HASH_COUNT || pcrs.count < 1)
>> -               goto out;
>> -
>> -       tpm_ret = tpm2_get_num_pcr(dev, &num_pcr);
>> -       if (tpm_ret)
>> -               goto out;
>> -
>> -       for (i = 0; i < pcrs.count; i++) {
>> -               /*
>> -                * Definition of TPMS_PCR_SELECTION Structure
>> -                * hash: u16
>> -                * size_of_select: u8
>> -                * pcr_select: u8 array
>> -                *
>> -                * The offsets depend on the number of the device PCRs
>> -                * so we have to calculate them based on that
>> -                */
>> -               u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
>> -                       i * offsetof(struct tpms_pcr_selection, pcr_select) +
>> -                       i * ((num_pcr + 7) / 8);
>> -               u32 size_select_offset =
>> -                       hash_offset + offsetof(struct tpms_pcr_selection,
>> -                                              size_of_select);
>> -               u32 pcr_select_offset =
>> -                       hash_offset + offsetof(struct tpms_pcr_selection,
>> -                                              pcr_select);
>> -
>> -               pcrs.selection[i].hash =
>> -                       get_unaligned_be16(response + hash_offset);
>> -               pcrs.selection[i].size_of_select =
>> -                       __get_unaligned_be(response + size_select_offset);
>> -               if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX)
>> -                       goto out;
>> -               /* copy the array of pcr_select */
>> -               memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset,
>> -                      pcrs.selection[i].size_of_select);
>> -       }
>> -
>> -       for (i = 0; i < pcrs.count; i++) {
>> -               u32 hash_mask = alg_to_mask(pcrs.selection[i].hash);
>> -
>> -               if (hash_mask) {
>> -                       *supported_pcr |= hash_mask;
>> -                       if (is_active_pcr(&pcrs.selection[i]))
>> -                               *active_pcr |= hash_mask;
>> -               } else {
>> -                       EFI_PRINT("Unknown algorithm %x\n", pcrs.selection[i].hash);
>> -               }
>> -       }
>> -
>> -       *pcr_banks = pcrs.count;
>> -
>> -       return 0;
>> -out:
>> -       return -1;
>> -}
>> -
>> -/**
>> - * __get_active_pcr_banks() - returns the currently active PCR banks
>> - *
>> - * @active_pcr_banks:          pointer for receiving the bitmap of currently
>> - *                             active PCR banks
>> - *
>> - * Return:     status code
>> - */
>> -static efi_status_t __get_active_pcr_banks(u32 *active_pcr_banks)
>> -{
>> -       struct udevice *dev;
>> -       u32 active = 0, supported = 0, pcr_banks = 0;
>> -       efi_status_t ret;
>> -       int err;
>> -
>> -       ret = platform_get_tpm2_device(&dev);
>> -       if (ret != EFI_SUCCESS)
>> -               goto out;
>> -
>> -       err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
>> -       if (err) {
>> -               ret = EFI_DEVICE_ERROR;
>> -               goto out;
>> -       }
>> -
>> -       *active_pcr_banks = active;
>> -
>> -out:
>> -       return ret;
>> -}
>> -
>> -/* tcg2_create_digest - create a list of digests of the supported PCR banks
>> - *                     for a given memory range
>> - *
>> - * @input:             input memory
>> - * @length:            length of buffer to calculate the digest
>> - * @digest_list:       list of digests to fill in
>> - *
>> - * Return:             status code
>> - */
>> -static efi_status_t tcg2_create_digest(const u8 *input, u32 length,
>> -                                      struct tpml_digest_values *digest_list)
>> -{
>> -       sha1_context ctx;
>> -       sha256_context ctx_256;
>> -       sha512_context ctx_512;
>> -       u8 final[TPM2_SHA512_DIGEST_SIZE];
>> -       efi_status_t ret;
>> -       u32 active;
>> -       size_t i;
>> -
>> -       ret = __get_active_pcr_banks(&active);
>> -       if (ret != EFI_SUCCESS)
>> -               return ret;
>> -
>> -       digest_list->count = 0;
>> -       for (i = 0; i < MAX_HASH_COUNT; i++) {
>> -               u16 hash_alg = hash_algo_list[i].hash_alg;
>> -
>> -               if (!(active & alg_to_mask(hash_alg)))
>> -                       continue;
>> -               switch (hash_alg) {
>> -               case TPM2_ALG_SHA1:
>> -                       sha1_starts(&ctx);
>> -                       sha1_update(&ctx, input, length);
>> -                       sha1_finish(&ctx, final);
>> -                       break;
>> -               case TPM2_ALG_SHA256:
>> -                       sha256_starts(&ctx_256);
>> -                       sha256_update(&ctx_256, input, length);
>> -                       sha256_finish(&ctx_256, final);
>> -                       break;
>> -               case TPM2_ALG_SHA384:
>> -                       sha384_starts(&ctx_512);
>> -                       sha384_update(&ctx_512, input, length);
>> -                       sha384_finish(&ctx_512, final);
>> -                       break;
>> -               case TPM2_ALG_SHA512:
>> -                       sha512_starts(&ctx_512);
>> -                       sha512_update(&ctx_512, input, length);
>> -                       sha512_finish(&ctx_512, final);
>> -                       break;
>> -               default:
>> -                       EFI_PRINT("Unsupported algorithm %x\n", hash_alg);
>> -                       return EFI_INVALID_PARAMETER;
>> -               }
>> -               digest_list->digests[digest_list->count].hash_alg = hash_alg;
>> -               memcpy(&digest_list->digests[digest_list->count].digest, final,
>> -                      (u32)alg_to_len(hash_alg));
>> -               digest_list->count++;
>> -       }
>> -
>> -       return EFI_SUCCESS;
>> -}
>> -
>>   /**
>>    * efi_tcg2_get_capability() - protocol capability information and state information
>>    *
>> @@ -759,7 +258,7 @@ efi_tcg2_get_capability(struct efi_tcg2_protocol *this,
>>          capability->protocol_version.major = 1;
>>          capability->protocol_version.minor = 1;
>>
>> -       efi_ret = platform_get_tpm2_device(&dev);
>> +       efi_ret = tcg2_platform_get_tpm2(&dev);
>>          if (efi_ret != EFI_SUCCESS) {
>>                  capability->supported_event_logs = 0;
>>                  capability->hash_algorithm_bitmap = 0;
>> @@ -855,7 +354,7 @@ efi_tcg2_get_eventlog(struct efi_tcg2_protocol *this,
>>                  goto out;
>>          }
>>
>> -       ret = platform_get_tpm2_device(&dev);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>>          if (ret != EFI_SUCCESS) {
>>                  event_log_location = NULL;
>>                  event_log_last_entry = NULL;
>> @@ -890,6 +389,7 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size,
>>          struct efi_image_regions *regs = NULL;
>>          void *new_efi = NULL;
>>          u8 hash[TPM2_SHA512_DIGEST_SIZE];
>> +       struct udevice *dev;
>>          efi_status_t ret;
>>          u32 active;
>>          int i;
>> @@ -905,16 +405,20 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size,
>>                  goto out;
>>          }
>>
>> -       ret = __get_active_pcr_banks(&active);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>> +       if (ret != EFI_SUCCESS)
>> +               goto out;
>> +
>> +       ret = tcg2_get_active_pcr_banks(dev, &active);
>>          if (ret != EFI_SUCCESS) {
>>                  goto out;
>>          }
>>
>>          digest_list->count = 0;
>> -       for (i = 0; i < MAX_HASH_COUNT; i++) {
>> -               u16 hash_alg = hash_algo_list[i].hash_alg;
>> +       for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); i++) {
>> +               u16 hash_alg = tpm2_supported_algorithms[i];
>>
>> -               if (!(active & alg_to_mask(hash_alg)))
>> +               if (!(active & tpm2_algorithm_to_mask(hash_alg)))
>>                          continue;
>>                  switch (hash_alg) {
>>                  case TPM2_ALG_SHA1:
>> @@ -935,7 +439,7 @@ static efi_status_t tcg2_hash_pe_image(void *efi, u64 efi_size,
>>                  }
>>                  digest_list->digests[digest_list->count].hash_alg = hash_alg;
>>                  memcpy(&digest_list->digests[digest_list->count].digest, hash,
>> -                      (u32)alg_to_len(hash_alg));
>> +                      (u32)tpm2_algorithm_to_len(hash_alg));
>>                  digest_list->count++;
>>          }
>>
>> @@ -975,7 +479,7 @@ efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size,
>>          if (!is_tcg2_protocol_installed())
>>                  return EFI_SUCCESS;
>>
>> -       ret = platform_get_tpm2_device(&dev);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>>          if (ret != EFI_SUCCESS)
>>                  return EFI_SECURITY_VIOLATION;
>>
>> @@ -1084,7 +588,7 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags,
>>                  goto out;
>>          }
>>
>> -       ret = platform_get_tpm2_device(&dev);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>>          if (ret != EFI_SUCCESS)
>>                  goto out;
>>
>> @@ -1119,7 +623,7 @@ efi_tcg2_hash_log_extend_event(struct efi_tcg2_protocol *this, u64 flags,
>>                  ret = tcg2_hash_pe_image((void *)(uintptr_t)data_to_hash,
>>                                           data_to_hash_len, &digest_list);
>>          } else {
>> -               ret = tcg2_create_digest((u8 *)(uintptr_t)data_to_hash,
>> +               ret = tcg2_create_digest(dev, (u8 *)(uintptr_t)data_to_hash,
>>                                           data_to_hash_len, &digest_list);
>>          }
>>
>> @@ -1182,7 +686,7 @@ efi_tcg2_submit_command(struct efi_tcg2_protocol *this,
>>                  goto out;
>>          }
>>
>> -       ret = platform_get_tpm2_device(&dev);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>>          if (ret != EFI_SUCCESS)
>>                  goto out;
>>
>> @@ -1211,6 +715,7 @@ static efi_status_t EFIAPI
>>   efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this,
>>                                u32 *active_pcr_banks)
>>   {
>> +       struct udevice *dev;
>>          efi_status_t ret;
>>
>>          if (!this || !active_pcr_banks) {
>> @@ -1218,8 +723,12 @@ efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this,
>>                  goto out;
>>          }
>>
>> +       ret = tcg2_platform_get_tpm2(&dev);
>> +       if (ret != EFI_SUCCESS)
>> +               goto out;
>> +
>>          EFI_ENTRY("%p, %p", this, active_pcr_banks);
>> -       ret = __get_active_pcr_banks(active_pcr_banks);
>> +       ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks);
>>
>>   out:
>>          return EFI_EXIT(ret);
>> @@ -1270,397 +779,6 @@ static const struct efi_tcg2_protocol efi_tcg2_protocol = {
>>          .get_result_of_set_active_pcr_banks = efi_tcg2_get_result_of_set_active_pcr_banks,
>>   };
>>
>> -/**
>> - * parse_event_log_header() -  Parse and verify the event log header fields
>> - *
>> - * @buffer:                    Pointer to the start of the eventlog
>> - * @size:                      Size of the eventlog
>> - * @pos:                       Return offset of the next event in buffer right
>> - *                             after the event header i.e specID
>> - *
>> - * Return:     status code
>> - */
>> -static efi_status_t parse_event_log_header(void *buffer, u32 size, u32 *pos)
>> -{
>> -       struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
>> -       int i = 0;
>> -
>> -       if (size < sizeof(*event_header))
>> -               return EFI_COMPROMISED_DATA;
>> -
>> -       if (get_unaligned_le32(&event_header->pcr_index) != 0 ||
>> -           get_unaligned_le32(&event_header->event_type) != EV_NO_ACTION)
>> -               return EFI_COMPROMISED_DATA;
>> -
>> -       for (i = 0; i < sizeof(event_header->digest); i++) {
>> -               if (event_header->digest[i])
>> -                       return EFI_COMPROMISED_DATA;
>> -       }
>> -
>> -       *pos += sizeof(*event_header);
>> -
>> -       return EFI_SUCCESS;
>> -}
>> -
>> -/**
>> - * parse_specid_event() -  Parse and verify the specID Event in the eventlog
>> - *
>> - * @dev:               udevice
>> - * @buffer:            Pointer to the start of the eventlog
>> - * @log_size:          Size of the eventlog
>> - * @pos:               [in] Offset of specID event in the eventlog buffer
>> - *                     [out] Return offset of the next event in the buffer
>> - *                     after the specID
>> - * @digest_list:       list of digests in the event
>> - *
>> - * Return:             status code
>> - * @pos                        Offset in the eventlog where the specID event ends
>> - * @digest_list:       list of digests in the event
>> - */
>> -static efi_status_t parse_specid_event(struct udevice *dev, void *buffer,
>> -                                      u32 log_size, u32 *pos,
>> -                                      struct tpml_digest_values *digest_list)
>> -{
>> -       struct tcg_efi_spec_id_event *spec_event;
>> -       struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
>> -       size_t spec_event_size;
>> -       u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
>> -       u32 spec_active = 0;
>> -       u16 hash_alg;
>> -       u8 vendor_sz;
>> -       int err, i;
>> -
>> -       if (*pos >= log_size || (*pos + sizeof(*spec_event)) > log_size)
>> -               return EFI_COMPROMISED_DATA;
>> -
>> -       /* Check specID event data */
>> -       spec_event = (struct tcg_efi_spec_id_event *)((uintptr_t)buffer + *pos);
>> -       /* Check for signature */
>> -       if (memcmp(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
>> -                  sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03))) {
>> -               log_err("specID Event: Signature mismatch\n");
>> -               return EFI_COMPROMISED_DATA;
>> -       }
>> -
>> -       if (spec_event->spec_version_minor !=
>> -                       TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
>> -           spec_event->spec_version_major !=
>> -                       TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
>> -               return EFI_COMPROMISED_DATA;
>> -
>> -       if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
>> -           spec_event->number_of_algorithms < 1) {
>> -               log_err("specID Event: Number of algorithms incorrect\n");
>> -               return EFI_COMPROMISED_DATA;
>> -       }
>> -
>> -       alg_count = spec_event->number_of_algorithms;
>> -
>> -       err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
>> -       if (err)
>> -               return EFI_DEVICE_ERROR;
>> -
>> -       digest_list->count = 0;
>> -       /*
>> -        * We have to take care that the sequence of algorithms that we record
>> -        * in digest_list matches the sequence in eventlog.
>> -        */
>> -       for (i = 0; i < alg_count; i++) {
>> -               hash_alg =
>> -                 get_unaligned_le16(&spec_event->digest_sizes[i].algorithm_id);
>> -
>> -               if (!(supported & alg_to_mask(hash_alg))) {
>> -                       log_err("specID Event: Unsupported algorithm\n");
>> -                       return EFI_COMPROMISED_DATA;
>> -               }
>> -               digest_list->digests[digest_list->count++].hash_alg = hash_alg;
>> -
>> -               spec_active |= alg_to_mask(hash_alg);
>> -       }
>> -
>> -       /*
>> -        * TCG specification expects the event log to have hashes for all
>> -        * active PCR's
>> -        */
>> -       if (spec_active != active) {
>> -               /*
>> -                * Previous stage bootloader should know all the active PCR's
>> -                * and use them in the Eventlog.
>> -                */
>> -               log_err("specID Event: All active hash alg not present\n");
>> -               return EFI_COMPROMISED_DATA;
>> -       }
>> -
>> -       /*
>> -        * the size of the spec event and placement of vendor_info_size
>> -        * depends on supported algoriths
>> -        */
>> -       spec_event_size =
>> -               offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
>> -               alg_count * sizeof(spec_event->digest_sizes[0]);
>> -
>> -       if (*pos + spec_event_size >= log_size)
>> -               return EFI_COMPROMISED_DATA;
>> -
>> -       vendor_sz = *(uint8_t *)((uintptr_t)buffer + *pos + spec_event_size);
>> -
>> -       spec_event_size += sizeof(vendor_sz) + vendor_sz;
>> -       *pos += spec_event_size;
>> -
>> -       if (get_unaligned_le32(&event_header->event_size) != spec_event_size) {
>> -               log_err("specID event: header event size mismatch\n");
>> -               /* Right way to handle this can be to call SetActive PCR's */
>> -               return EFI_COMPROMISED_DATA;
>> -       }
>> -
>> -       return EFI_SUCCESS;
>> -}
>> -
>> -/**
>> - * tcg2_parse_event() -  Parse the event in the eventlog
>> - *
>> - * @dev:               udevice
>> - * @buffer:            Pointer to the start of the eventlog
>> - * @log_size:          Size of the eventlog
>> - * @offset:            [in] Offset of the event in the eventlog buffer
>> - *                     [out] Return offset of the next event in the buffer
>> - * @digest_list:       list of digests in the event
>> - * @pcr                        Index of the PCR in the event
>> - *
>> - * Return:             status code
>> - */
>> -static efi_status_t tcg2_parse_event(struct udevice *dev, void *buffer,
>> -                                    u32 log_size, u32 *offset,
>> -                                    struct tpml_digest_values *digest_list,
>> -                                    u32 *pcr)
>> -{
>> -       struct tcg_pcr_event2 *event = NULL;
>> -       u32 count, size, event_size;
>> -       size_t pos;
>> -
>> -       event_size = tcg_event_final_size(digest_list);
>> -       if (*offset >= log_size || *offset + event_size > log_size) {
>> -               log_err("Event exceeds log size\n");
>> -               return EFI_COMPROMISED_DATA;
>> -       }
>> -
>> -       event = (struct tcg_pcr_event2 *)((uintptr_t)buffer + *offset);
>> -       *pcr = get_unaligned_le32(&event->pcr_index);
>> -
>> -       /* get the count */
>> -       count = get_unaligned_le32(&event->digests.count);
>> -       if (count != digest_list->count)
>> -               return EFI_COMPROMISED_DATA;
>> -
>> -       pos = offsetof(struct tcg_pcr_event2, digests);
>> -       pos += offsetof(struct tpml_digest_values, digests);
>> -
>> -       for (int i = 0; i < digest_list->count; i++) {
>> -               u16 alg;
>> -               u16 hash_alg = digest_list->digests[i].hash_alg;
>> -               u8 *digest = (u8 *)&digest_list->digests[i].digest;
>> -
>> -               alg = get_unaligned_le16((void *)((uintptr_t)event + pos));
>> -
>> -               if (alg != hash_alg)
>> -                       return EFI_COMPROMISED_DATA;
>> -
>> -               pos += offsetof(struct tpmt_ha, digest);
>> -               memcpy(digest, (void *)((uintptr_t)event + pos), alg_to_len(hash_alg));
>> -               pos += alg_to_len(hash_alg);
>> -       }
>> -
>> -       size = get_unaligned_le32((void *)((uintptr_t)event + pos));
>> -       event_size += size;
>> -       pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
>> -       pos += size;
>> -
>> -       /* make sure the calculated buffer is what we checked against */
>> -       if (pos != event_size)
>> -               return EFI_COMPROMISED_DATA;
>> -
>> -       if (pos > log_size)
>> -               return EFI_COMPROMISED_DATA;
>> -
>> -       *offset += pos;
>> -
>> -       return EFI_SUCCESS;
>> -}
>> -
>> -/**
>> - * tcg2_get_fw_eventlog() -  Get the eventlog address and size
>> - *
>> - * If the previous firmware has passed some eventlog, this function get it's
>> - * location and check for it's validity.
>> - *
>> - * @dev:               udevice
>> - * @log_buffer:                eventlog address
>> - * @log_sz:            eventlog size
>> - *
>> - * Return:     status code
>> - */
>> -static efi_status_t tcg2_get_fw_eventlog(struct udevice *dev, void *log_buffer,
>> -                                        size_t *log_sz)
>> -{
>> -       struct tpml_digest_values digest_list;
>> -       void *buffer;
>> -       efi_status_t ret;
>> -       u32 pcr, pos;
>> -       u64 base;
>> -       u32 sz;
>> -       bool extend_pcr = false;
>> -       int i;
>> -
>> -       ret = platform_get_eventlog(dev, &base, &sz);
>> -       if (ret != EFI_SUCCESS)
>> -               return ret;
>> -
>> -       if (sz > TPM2_EVENT_LOG_SIZE)
>> -               return EFI_VOLUME_FULL;
>> -
>> -       buffer = (void *)(uintptr_t)base;
>> -       pos = 0;
>> -       /* Parse the eventlog to check for its validity */
>> -       ret = parse_event_log_header(buffer, sz, &pos);
>> -       if (ret)
>> -               return ret;
>> -
>> -       ret = parse_specid_event(dev, buffer, sz, &pos, &digest_list);
>> -       if (ret) {
>> -               log_err("Error parsing SPEC ID Event\n");
>> -               return ret;
>> -       }
>> -
>> -       ret = tcg2_pcr_read(dev, 0, &digest_list);
>> -       if (ret) {
>> -               log_err("Error reading PCR 0\n");
>> -               return ret;
>> -       }
>> -
>> -       /*
>> -        * If PCR0 is 0, previous firmware didn't have the capability
>> -        * to extend the PCR. In this scenario, extend the PCR as
>> -        * the eventlog is parsed.
>> -        */
>> -       for (i = 0; i < digest_list.count; i++) {
>> -               u8 hash_buf[TPM2_SHA512_DIGEST_SIZE] = { 0 };
>> -               u16 hash_alg = digest_list.digests[i].hash_alg;
>> -
>> -               if (!memcmp((u8 *)&digest_list.digests[i].digest, hash_buf,
>> -                           alg_to_len(hash_alg)))
>> -                       extend_pcr = true;
>> -       }
>> -
>> -       while (pos < sz) {
>> -               ret = tcg2_parse_event(dev, buffer, sz, &pos, &digest_list,
>> -                                      &pcr);
>> -               if (ret) {
>> -                       log_err("Error parsing event\n");
>> -                       return ret;
>> -               }
>> -               if (extend_pcr) {
>> -                       ret = tcg2_pcr_extend(dev, pcr, &digest_list);
>> -                       if (ret != EFI_SUCCESS) {
>> -                               log_err("Error in extending PCR\n");
>> -                               return ret;
>> -                       }
>> -
>> -                       /* Clear the digest for next event */
>> -                       for (i = 0; i < digest_list.count; i++) {
>> -                               u16 hash_alg = digest_list.digests[i].hash_alg;
>> -                               u8 *digest =
>> -                                  (u8 *)&digest_list.digests[i].digest;
>> -
>> -                               memset(digest, 0, alg_to_len(hash_alg));
>> -                       }
>> -               }
>> -       }
>> -
>> -       memcpy(log_buffer, buffer, sz);
>> -       *log_sz = sz;
>> -
>> -       return ret;
>> -}
>> -
>> -/**
>> - * create_specid_event() - Create the first event in the eventlog
>> - *
>> - * @dev:                       tpm device
>> - * @event_header:              Pointer to the final event header
>> - * @event_size:                        final spec event size
>> - *
>> - * Return:     status code
>> - */
>> -static efi_status_t create_specid_event(struct udevice *dev, void *buffer,
>> -                                       size_t *event_size)
>> -{
>> -       struct tcg_efi_spec_id_event *spec_event;
>> -       size_t spec_event_size;
>> -       efi_status_t ret = EFI_DEVICE_ERROR;
>> -       u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
>> -       int err;
>> -       size_t i;
>> -
>> -       /*
>> -        * Create Spec event. This needs to be the first event in the log
>> -        * according to the TCG EFI protocol spec
>> -        */
>> -
>> -       /* Setup specID event data */
>> -       spec_event = (struct tcg_efi_spec_id_event *)buffer;
>> -       memcpy(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
>> -              sizeof(spec_event->signature));
>> -       put_unaligned_le32(0, &spec_event->platform_class); /* type client */
>> -       spec_event->spec_version_minor =
>> -               TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
>> -       spec_event->spec_version_major =
>> -               TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
>> -       spec_event->spec_errata =
>> -               TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
>> -       spec_event->uintn_size = sizeof(efi_uintn_t) / sizeof(u32);
>> -
>> -       err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
>> -
>> -       if (err)
>> -               goto out;
>> -
>> -       for (i = 0; i < pcr_count; i++) {
>> -               u16 hash_alg = hash_algo_list[i].hash_alg;
>> -               u16 hash_len = hash_algo_list[i].hash_len;
>> -
>> -               if (active & alg_to_mask(hash_alg)) {
>> -                       put_unaligned_le16(hash_alg,
>> -                                          &spec_event->digest_sizes[alg_count].algorithm_id);
>> -                       put_unaligned_le16(hash_len,
>> -                                          &spec_event->digest_sizes[alg_count].digest_size);
>> -                       alg_count++;
>> -               }
>> -       }
>> -
>> -       spec_event->number_of_algorithms = alg_count;
>> -       if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
>> -           spec_event->number_of_algorithms < 1)
>> -               goto out;
>> -
>> -       /*
>> -        * the size of the spec event and placement of vendor_info_size
>> -        * depends on supported algoriths
>> -        */
>> -       spec_event_size =
>> -               offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
>> -               spec_event->number_of_algorithms * sizeof(spec_event->digest_sizes[0]);
>> -       /* no vendor info for us */
>> -       memset(buffer + spec_event_size, 0, 1);
>> -       /* add a byte for vendor_info_size in the spec event */
>> -       spec_event_size += 1;
>> -       *event_size = spec_event_size;
>> -
>> -       return EFI_SUCCESS;
>> -
>> -out:
>> -       return ret;
>> -}
>> -
>>   /**
>>    * tcg2_uninit - remove the final event table and free efi memory on failures
>>    */
>> @@ -1722,7 +840,7 @@ out:
>>   }
>>
>>   /**
>> - * tcg2_measure_event() - common function to add event log and extend PCR
>> + * measure_event() - common function to add event log and extend PCR
>>    *
>>    * @dev:               TPM device
>>    * @pcr_index:         PCR index
>> @@ -1732,14 +850,13 @@ out:
>>    *
>>    * Return:     status code
>>    */
>> -static efi_status_t
>> -tcg2_measure_event(struct udevice *dev, u32 pcr_index, u32 event_type,
>> -                  u32 size, u8 event[])
>> +static efi_status_t measure_event(struct udevice *dev, u32 pcr_index,
>> +                                 u32 event_type, u32 size, u8 event[])
>>   {
>>          struct tpml_digest_values digest_list;
>>          efi_status_t ret;
>>
>> -       ret = tcg2_create_digest(event, size, &digest_list);
>> +       ret = tcg2_create_digest(dev, event, size, &digest_list);
>>          if (ret != EFI_SUCCESS)
>>                  goto out;
>>
>> @@ -1766,9 +883,8 @@ static efi_status_t efi_append_scrtm_version(struct udevice *dev)
>>   {
>>          efi_status_t ret;
>>
>> -       ret = tcg2_measure_event(dev, 0, EV_S_CRTM_VERSION,
>> -                                strlen(version_string) + 1,
>> -                                (u8 *)version_string);
>> +       ret = measure_event(dev, 0, EV_S_CRTM_VERSION,
>> +                           strlen(version_string) + 1, (u8 *)version_string);
>>
>>          return ret;
>>   }
>> @@ -1784,12 +900,11 @@ static efi_status_t efi_init_event_log(void)
>>           * vendor_info_size is currently set to 0, we need to change the length
>>           * and allocate the flexible array member if this changes
>>           */
>> -       struct tcg_pcr_event *event_header = NULL;
>> +       struct tcg2_event_log elog;
>>          struct udevice *dev;
>> -       size_t spec_event_size;
>>          efi_status_t ret;
>>
>> -       ret = platform_get_tpm2_device(&dev);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>>          if (ret != EFI_SUCCESS)
>>                  return ret;
>>
>> @@ -1808,7 +923,6 @@ static efi_status_t efi_init_event_log(void)
>>           * The log header is defined to be in SHA1 event log entry format.
>>           * Setup event header
>>           */
>> -       event_header =  (struct tcg_pcr_event *)event_log.buffer;
>>          event_log.pos = 0;
>>          event_log.last_event_size = 0;
>>          event_log.get_event_called = false;
>> @@ -1819,34 +933,20 @@ static efi_status_t efi_init_event_log(void)
>>           * Check if earlier firmware have passed any eventlog. Different
>>           * platforms can use different ways to do so.
>>           */
>> -       ret = tcg2_get_fw_eventlog(dev, event_log.buffer, &event_log.pos);
>> +       elog.log = event_log.buffer;
>> +       elog.log_size = TPM2_EVENT_LOG_SIZE;
>> +       ret = tcg2_log_prepare_buffer(dev, &elog, false);
>> +       if (ret != EFI_SUCCESS)
>> +               goto free_pool;
>> +
>> +       event_log.pos = elog.log_position;
>> +
>>          /*
>> -        * If earlier firmware hasn't passed any eventlog, go ahead and
>> -        * create the eventlog header.
>> +        * Add SCRTM version to the log if previous firmmware
>> +        * doesn't pass an eventlog.
>>           */
>> -       if (ret == EFI_NOT_FOUND) {
>> -               put_unaligned_le32(0, &event_header->pcr_index);
>> -               put_unaligned_le32(EV_NO_ACTION, &event_header->event_type);
>> -               memset(&event_header->digest, 0, sizeof(event_header->digest));
>> -               ret = create_specid_event(dev,
>> -                                         (void *)((uintptr_t)event_log.buffer +
>> -                                                  sizeof(*event_header)),
>> -                                         &spec_event_size);
>> -               if (ret != EFI_SUCCESS)
>> -                       goto free_pool;
>> -               put_unaligned_le32(spec_event_size, &event_header->event_size);
>> -               event_log.pos = spec_event_size + sizeof(*event_header);
>> -               event_log.last_event_size = event_log.pos;
>> -
>> -               /*
>> -                * Add SCRTM version to the log if previous firmmware
>> -                * doesn't pass an eventlog.
>> -                */
>> +       if (!elog.found)
>>                  ret = efi_append_scrtm_version(dev);
>> -       }
>> -
>> -       if (ret != EFI_SUCCESS)
>> -               goto free_pool;
>>
>>          ret = create_final_event();
>>          if (ret != EFI_SUCCESS)
>> @@ -1899,8 +999,8 @@ static efi_status_t tcg2_measure_variable(struct udevice *dev, u32 pcr_index,
>>                  memcpy((u16 *)event->unicode_name + event->unicode_name_length,
>>                         data, data_size);
>>          }
>> -       ret = tcg2_measure_event(dev, pcr_index, event_type, event_size,
>> -                                (u8 *)event);
>> +       ret = measure_event(dev, pcr_index, event_type, event_size,
>> +                           (u8 *)event);
>>          free(event);
>>          return ret;
>>   }
>> @@ -2011,8 +1111,8 @@ tcg2_measure_smbios(struct udevice *dev,
>>
>>          smbios_prepare_measurement(entry, smbios_copy);
>>
>> -       ret = tcg2_measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
>> -                                (u8 *)event);
>> +       ret = measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
>> +                           (u8 *)event);
>>          if (ret != EFI_SUCCESS)
>>                  goto out;
>>
>> @@ -2163,7 +1263,7 @@ tcg2_measure_gpt_data(struct udevice *dev,
>>                  gpt_e = (gpt_entry *)((u8 *)gpt_e + gpt_h->sizeof_partition_entry);
>>          }
>>
>> -       ret = tcg2_measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8 *)event);
>> +       ret = measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8 *)event);
>>
>>   out2:
>>          free(gpt_h);
>> @@ -2217,7 +1317,7 @@ efi_status_t efi_tcg2_measure_dtb(void *dtb)
>>          if (!is_tcg2_protocol_installed())
>>                  return EFI_SUCCESS;
>>
>> -       ret = platform_get_tpm2_device(&dev);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>>          if (ret != EFI_SUCCESS)
>>                  return EFI_SECURITY_VIOLATION;
>>
>> @@ -2242,7 +1342,7 @@ efi_status_t efi_tcg2_measure_dtb(void *dtb)
>>          sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_mem_rsvmap(dtb), rsvmap_size);
>>          sha256_finish(&hash_ctx, blob->data + blob->blob_description_size);
>>
>> -       ret = tcg2_measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob);
>> +       ret = measure_event(dev, 0, EV_POST_CODE, event_size, (u8 *)blob);
>>
>>          free(blob);
>>          return ret;
>> @@ -2267,7 +1367,7 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
>>          if (tcg2_efi_app_invoked)
>>                  return EFI_SUCCESS;
>>
>> -       ret = platform_get_tpm2_device(&dev);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>>          if (ret != EFI_SUCCESS)
>>                  return EFI_SECURITY_VIOLATION;
>>
>> @@ -2275,9 +1375,9 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
>>          if (ret != EFI_SUCCESS)
>>                  goto out;
>>
>> -       ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION,
>> -                                strlen(EFI_CALLING_EFI_APPLICATION),
>> -                                (u8 *)EFI_CALLING_EFI_APPLICATION);
>> +       ret = measure_event(dev, 4, EV_EFI_ACTION,
>> +                           strlen(EFI_CALLING_EFI_APPLICATION),
>> +                           (u8 *)EFI_CALLING_EFI_APPLICATION);
>>          if (ret != EFI_SUCCESS)
>>                  goto out;
>>
>> @@ -2293,8 +1393,8 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
>>                  goto out;
>>
>>          for (pcr_index = 0; pcr_index <= 7; pcr_index++) {
>> -               ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR,
>> -                                        sizeof(event), (u8 *)&event);
>> +               ret = measure_event(dev, pcr_index, EV_SEPARATOR,
>> +                                   sizeof(event), (u8 *)&event);
>>                  if (ret != EFI_SUCCESS)
>>                          goto out;
>>          }
>> @@ -2317,13 +1417,13 @@ efi_status_t efi_tcg2_measure_efi_app_exit(void)
>>          if (!is_tcg2_protocol_installed())
>>                  return EFI_SUCCESS;
>>
>> -       ret = platform_get_tpm2_device(&dev);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>>          if (ret != EFI_SUCCESS)
>>                  return ret;
>>
>> -       ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION,
>> -                                strlen(EFI_RETURNING_FROM_EFI_APPLICATION),
>> -                                (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION);
>> +       ret = measure_event(dev, 4, EV_EFI_ACTION,
>> +                           strlen(EFI_RETURNING_FROM_EFI_APPLICATION),
>> +                           (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION);
>>          return ret;
>>   }
>>
>> @@ -2348,19 +1448,19 @@ efi_tcg2_notify_exit_boot_services(struct efi_event *event, void *context)
>>                  goto out;
>>          }
>>
>> -       ret = platform_get_tpm2_device(&dev);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>>          if (ret != EFI_SUCCESS)
>>                  goto out;
>>
>> -       ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
>> -                                strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
>> -                                (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
>> +       ret = measure_event(dev, 5, EV_EFI_ACTION,
>> +                           strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
>> +                           (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
>>          if (ret != EFI_SUCCESS)
>>                  goto out;
>>
>> -       ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
>> -                                strlen(EFI_EXIT_BOOT_SERVICES_SUCCEEDED),
>> -                                (u8 *)EFI_EXIT_BOOT_SERVICES_SUCCEEDED);
>> +       ret = measure_event(dev, 5, EV_EFI_ACTION,
>> +                           strlen(EFI_EXIT_BOOT_SERVICES_SUCCEEDED),
>> +                           (u8 *)EFI_EXIT_BOOT_SERVICES_SUCCEEDED);
>>
>>   out:
>>          EFI_EXIT(ret);
>> @@ -2380,19 +1480,19 @@ efi_status_t efi_tcg2_notify_exit_boot_services_failed(void)
>>          if (!is_tcg2_protocol_installed())
>>                  return EFI_SUCCESS;
>>
>> -       ret = platform_get_tpm2_device(&dev);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>>          if (ret != EFI_SUCCESS)
>>                  goto out;
>>
>> -       ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
>> -                                strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
>> -                                (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
>> +       ret = measure_event(dev, 5, EV_EFI_ACTION,
>> +                           strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
>> +                           (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
>>          if (ret != EFI_SUCCESS)
>>                  goto out;
>>
>> -       ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
>> -                                strlen(EFI_EXIT_BOOT_SERVICES_FAILED),
>> -                                (u8 *)EFI_EXIT_BOOT_SERVICES_FAILED);
>> +       ret = measure_event(dev, 5, EV_EFI_ACTION,
>> +                           strlen(EFI_EXIT_BOOT_SERVICES_FAILED),
>> +                           (u8 *)EFI_EXIT_BOOT_SERVICES_FAILED);
>>
>>   out:
>>          return ret;
>> @@ -2462,7 +1562,7 @@ efi_status_t efi_tcg2_do_initial_measurement(void)
>>          if (!is_tcg2_protocol_installed())
>>                  return EFI_SUCCESS;
>>
>> -       ret = platform_get_tpm2_device(&dev);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>>          if (ret != EFI_SUCCESS)
>>                  return EFI_SECURITY_VIOLATION;
>>
>> @@ -2488,7 +1588,7 @@ efi_status_t efi_tcg2_register(void)
>>          struct efi_event *event;
>>          u32 err;
>>
>> -       ret = platform_get_tpm2_device(&dev);
>> +       ret = tcg2_platform_get_tpm2(&dev);
>>          if (ret != EFI_SUCCESS) {
>>                  log_warning("Missing TPMv2 device for EFI_TCG_PROTOCOL\n");
>>                  return EFI_SUCCESS;
>> diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
>> index 9ab5b46df1..d22e21985b 100644
>> --- a/lib/tpm-v2.c
>> +++ b/lib/tpm-v2.c
>> @@ -1,16 +1,705 @@
>>   // SPDX-License-Identifier: GPL-2.0+
>>   /*
>> + * Copyright (c) 2023 Linaro Limited
>>    * Copyright (c) 2018 Bootlin
>>    * Author: Miquel Raynal <miquel.raynal@bootlin.com>
>>    */
>>
>>   #include <common.h>
>>   #include <dm.h>
>> +#include <dm/of_access.h>
>> +#include <tpm_api.h>
>>   #include <tpm-common.h>
>>   #include <tpm-v2.h>
>> +#include <u-boot/sha1.h>
>> +#include <u-boot/sha256.h>
>> +#include <u-boot/sha512.h>
>> +#include <version_string.h>
>> +#include <asm/io.h>
>>   #include <linux/bitops.h>
>> +#include <linux/unaligned/be_byteshift.h>
>> +#include <linux/unaligned/generic.h>
>> +#include <linux/unaligned/le_byteshift.h>
>> +
>>   #include "tpm-utils.h"
>>
>> +const enum tpm2_algorithms tpm2_supported_algorithms[4] = {
>> +       TPM2_ALG_SHA1,
>> +       TPM2_ALG_SHA256,
>> +       TPM2_ALG_SHA384,
>> +       TPM2_ALG_SHA512,
>> +};
>> +
>> +int tcg2_get_active_pcr_banks(struct udevice *dev, u32 *active_pcr_banks)
>> +{
>> +       u32 supported = 0;
>> +       u32 pcr_banks = 0;
>> +       u32 active = 0;
>> +       int rc;
>> +
>> +       rc = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
>> +       if (rc)
>> +               return rc;
>> +
>> +       *active_pcr_banks = active;
>> +
>> +       return 0;
>> +}
>> +
>> +u32 tcg2_event_get_size(struct tpml_digest_values *digest_list)
>> +{
>> +       u32 len;
>> +       size_t i;
>> +
>> +       len = offsetof(struct tcg_pcr_event2, digests);
>> +       len += offsetof(struct tpml_digest_values, digests);
>> +       for (i = 0; i < digest_list->count; ++i) {
>> +               u16 l = tpm2_algorithm_to_len(digest_list->digests[i].hash_alg);
>> +
>> +               if (!l)
>> +                       continue;
>> +
>> +               len += l + offsetof(struct tpmt_ha, digest);
>> +       }
>> +       len += sizeof(u32);
>> +
>> +       return len;
>> +}
>> +
>> +int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length,
>> +                      struct tpml_digest_values *digest_list)
>> +{
>> +       u8 final[sizeof(union tpmu_ha)];
>> +       sha256_context ctx_256;
>> +       sha512_context ctx_512;
>> +       sha1_context ctx;
>> +       u32 active;
>> +       size_t i;
>> +       u32 len;
>> +       int rc;
>> +
>> +       rc = tcg2_get_active_pcr_banks(dev, &active);
>> +       if (rc)
>> +               return rc;
>> +
>> +       digest_list->count = 0;
>> +       for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
>> +               u32 mask =
>> +                       tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
>> +
>> +               if (!(active & mask))
>> +                       continue;
>> +
>> +               switch (tpm2_supported_algorithms[i]) {
>> +               case TPM2_ALG_SHA1:
>> +                       sha1_starts(&ctx);
>> +                       sha1_update(&ctx, input, length);
>> +                       sha1_finish(&ctx, final);
>> +                       len = TPM2_SHA1_DIGEST_SIZE;
>> +                       break;
>> +               case TPM2_ALG_SHA256:
>> +                       sha256_starts(&ctx_256);
>> +                       sha256_update(&ctx_256, input, length);
>> +                       sha256_finish(&ctx_256, final);
>> +                       len = TPM2_SHA256_DIGEST_SIZE;
>> +                       break;
>> +               case TPM2_ALG_SHA384:
>> +                       sha384_starts(&ctx_512);
>> +                       sha384_update(&ctx_512, input, length);
>> +                       sha384_finish(&ctx_512, final);
>> +                       len = TPM2_SHA384_DIGEST_SIZE;
>> +                       break;
>> +               case TPM2_ALG_SHA512:
>> +                       sha512_starts(&ctx_512);
>> +                       sha512_update(&ctx_512, input, length);
>> +                       sha512_finish(&ctx_512, final);
>> +                       len = TPM2_SHA512_DIGEST_SIZE;
>> +                       break;
>> +               default:
>> +                       printf("%s: unsupported algorithm %x\n", __func__,
>> +                              tpm2_supported_algorithms[i]);
>> +                       continue;
>> +               }
>> +
>> +               digest_list->digests[digest_list->count].hash_alg =
>> +                       tpm2_supported_algorithms[i];
>> +               memcpy(&digest_list->digests[digest_list->count].digest, final,
>> +                      len);
>> +               digest_list->count++;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +void tcg2_log_append(u32 pcr_index, u32 event_type,
>> +                    struct tpml_digest_values *digest_list, u32 size,
>> +                    const u8 *event, u8 *log)
>> +{
>> +       size_t len;
>> +       size_t pos;
>> +       u32 i;
>> +
>> +       pos = offsetof(struct tcg_pcr_event2, pcr_index);
>> +       put_unaligned_le32(pcr_index, log);
>> +       pos = offsetof(struct tcg_pcr_event2, event_type);
>> +       put_unaligned_le32(event_type, log + pos);
>> +       pos = offsetof(struct tcg_pcr_event2, digests) +
>> +               offsetof(struct tpml_digest_values, count);
>> +       put_unaligned_le32(digest_list->count, log + pos);
>> +
>> +       pos = offsetof(struct tcg_pcr_event2, digests) +
>> +               offsetof(struct tpml_digest_values, digests);
>> +       for (i = 0; i < digest_list->count; ++i) {
>> +               u16 hash_alg = digest_list->digests[i].hash_alg;
>> +
>> +               len = tpm2_algorithm_to_len(hash_alg);
>> +               if (!len)
>> +                       continue;
>> +
>> +               pos += offsetof(struct tpmt_ha, hash_alg);
>> +               put_unaligned_le16(hash_alg, log + pos);
>> +               pos += offsetof(struct tpmt_ha, digest);
>> +               memcpy(log + pos, (u8 *)&digest_list->digests[i].digest, len);
>> +               pos += len;
>> +       }
>> +
>> +       put_unaligned_le32(size, log + pos);
>> +       pos += sizeof(u32);
>> +       memcpy(log + pos, event, size);
>> +}
>> +
>> +static int tcg2_log_append_check(struct tcg2_event_log *elog, u32 pcr_index,
>> +                                u32 event_type,
>> +                                struct tpml_digest_values *digest_list,
>> +                                u32 size, const u8 *event)
>> +{
>> +       u32 event_size;
>> +       u8 *log;
>> +
>> +       event_size = size + tcg2_event_get_size(digest_list);
>> +       if (elog->log_position + event_size > elog->log_size) {
>> +               printf("%s: log too large: %u + %u > %u\n", __func__,
>> +                      elog->log_position, event_size, elog->log_size);
>> +               return -ENOBUFS;
>> +       }
>> +
>> +       log = elog->log + elog->log_position;
>> +       elog->log_position += event_size;
>> +
>> +       tcg2_log_append(pcr_index, event_type, digest_list, size, event, log);
>> +
>> +       return 0;
>> +}
>> +
>> +static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog)
>> +{
>> +       struct tcg_efi_spec_id_event *ev;
>> +       struct tcg_pcr_event *log;
>> +       u32 event_size;
>> +       u32 count = 0;
>> +       u32 log_size;
>> +       u32 active;
>> +       u32 mask;
>> +       size_t i;
>> +       u16 len;
>> +       int rc;
>> +
>> +       rc = tcg2_get_active_pcr_banks(dev, &active);
>> +       if (rc)
>> +               return rc;
>> +
>> +       event_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes);
>> +       for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
>> +               mask = tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
>> +
>> +               if (!(active & mask))
>> +                       continue;
>> +
>> +               switch (tpm2_supported_algorithms[i]) {
>> +               case TPM2_ALG_SHA1:
>> +               case TPM2_ALG_SHA256:
>> +               case TPM2_ALG_SHA384:
>> +               case TPM2_ALG_SHA512:
>> +                       count++;
>> +                       break;
>> +               default:
>> +                       continue;
>> +               }
>> +       }
>> +
>> +       event_size += 1 +
>> +               (sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count);
>> +       log_size = offsetof(struct tcg_pcr_event, event) + event_size;
>> +
>> +       if (log_size > elog->log_size) {
>> +               printf("%s: log too large: %u > %u\n", __func__, log_size,
>> +                      elog->log_size);
>> +               return -ENOBUFS;
>> +       }
>> +
>> +       log = (struct tcg_pcr_event *)elog->log;
>> +       put_unaligned_le32(0, &log->pcr_index);
>> +       put_unaligned_le32(EV_NO_ACTION, &log->event_type);
>> +       memset(&log->digest, 0, sizeof(log->digest));
>> +       put_unaligned_le32(event_size, &log->event_size);
>> +
>> +       ev = (struct tcg_efi_spec_id_event *)log->event;
>> +       strlcpy((char *)ev->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
>> +               sizeof(ev->signature));
>> +       put_unaligned_le32(0, &ev->platform_class);
>> +       ev->spec_version_minor = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
>> +       ev->spec_version_major = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
>> +       ev->spec_errata = TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
>> +       ev->uintn_size = sizeof(size_t) / sizeof(u32);
>> +       put_unaligned_le32(count, &ev->number_of_algorithms);
>> +
>> +       count = 0;
>> +       for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
>> +               mask = tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
>> +
>> +               if (!(active & mask))
>> +                       continue;
>> +
>> +               len = tpm2_algorithm_to_len(tpm2_supported_algorithms[i]);
>> +               if (!len)
>> +                       continue;
>> +
>> +               put_unaligned_le16(tpm2_supported_algorithms[i],
>> +                                  &ev->digest_sizes[count].algorithm_id);
>> +               put_unaligned_le16(len, &ev->digest_sizes[count].digest_size);
>> +               count++;
>> +       }
>> +
>> +       *((u8 *)ev + (event_size - 1)) = 0;
>> +       elog->log_position = log_size;
>> +
>> +       return 0;
>> +}
>> +
>> +static int tcg2_replay_eventlog(struct tcg2_event_log *elog,
>> +                               struct udevice *dev,
>> +                               struct tpml_digest_values *digest_list,
>> +                               u32 log_position)
>> +{
>> +       const u32 offset = offsetof(struct tcg_pcr_event2, digests) +
>> +               offsetof(struct tpml_digest_values, digests);
>> +       u32 event_size;
>> +       u32 count;
>> +       u16 algo;
>> +       u32 pcr;
>> +       u32 pos;
>> +       u16 len;
>> +       u8 *log;
>> +       int rc;
>> +       u32 i;
>> +
>> +       while (log_position + offset < elog->log_size) {
>> +               log = elog->log + log_position;
>> +
>> +               pos = offsetof(struct tcg_pcr_event2, pcr_index);
>> +               pcr = get_unaligned_le32(log + pos);
>> +               pos = offsetof(struct tcg_pcr_event2, event_type);
>> +               if (!get_unaligned_le32(log + pos))
>> +                       return 0;
>> +
>> +               pos = offsetof(struct tcg_pcr_event2, digests) +
>> +                       offsetof(struct tpml_digest_values, count);
>> +               count = get_unaligned_le32(log + pos);
>> +               if (count > ARRAY_SIZE(tpm2_supported_algorithms) ||
>> +                   (digest_list->count && digest_list->count != count))
>> +                       return 0;
>> +
>> +               pos = offsetof(struct tcg_pcr_event2, digests) +
>> +                       offsetof(struct tpml_digest_values, digests);
>> +               for (i = 0; i < count; ++i) {
>> +                       pos += offsetof(struct tpmt_ha, hash_alg);
>> +                       if (log_position + pos + sizeof(u16) >= elog->log_size)
>> +                               return 0;
>> +
>> +                       algo = get_unaligned_le16(log + pos);
>> +                       pos += offsetof(struct tpmt_ha, digest);
>> +                       switch (algo) {
>> +                       case TPM2_ALG_SHA1:
>> +                       case TPM2_ALG_SHA256:
>> +                       case TPM2_ALG_SHA384:
>> +                       case TPM2_ALG_SHA512:
>> +                               len = tpm2_algorithm_to_len(algo);
>> +                               break;
>> +                       default:
>> +                               return 0;
>> +                       }
>> +
>> +                       if (digest_list->count) {
>> +                               if (algo != digest_list->digests[i].hash_alg ||
>> +                                   log_position + pos + len >= elog->log_size)
>> +                                       return 0;
>> +
>> +                               memcpy(digest_list->digests[i].digest.sha512,
>> +                                      log + pos, len);
>> +                       }
>> +
>> +                       pos += len;
>> +               }
>> +
>> +               if (log_position + pos + sizeof(u32) >= elog->log_size)
>> +                       return 0;
>> +
>> +               event_size = get_unaligned_le32(log + pos);
>> +               pos += event_size + sizeof(u32);
>> +               if (log_position + pos > elog->log_size)
>> +                       return 0;
>> +
>> +               if (digest_list->count) {
>> +                       rc = tcg2_pcr_extend(dev, pcr, digest_list);
>> +                       if (rc)
>> +                               return rc;
>> +               }
>> +
>> +               log_position += pos;
>> +       }
>> +
>> +       elog->log_position = log_position;
>> +       elog->found = true;
>> +       return 0;
>> +}
>> +
>> +static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog)
>> +{
>> +       struct tpml_digest_values digest_list;
>> +       struct tcg_efi_spec_id_event *event;
>> +       struct tcg_pcr_event *log;
>> +       u32 log_active;
>> +       u32 calc_size;
>> +       u32 active;
>> +       u32 count;
>> +       u32 evsz;
>> +       u32 mask;
>> +       u16 algo;
>> +       u16 len;
>> +       int rc;
>> +       u32 i;
>> +       u16 j;
>> +
>> +       if (elog->log_size <= offsetof(struct tcg_pcr_event, event))
>> +               return 0;
>> +
>> +       log = (struct tcg_pcr_event *)elog->log;
>> +       if (get_unaligned_le32(&log->pcr_index) != 0 ||
>> +           get_unaligned_le32(&log->event_type) != EV_NO_ACTION)
>> +               return 0;
>> +
>> +       for (i = 0; i < sizeof(log->digest); i++) {
>> +               if (log->digest[i])
>> +                       return 0;
>> +       }
>> +
>> +       evsz = get_unaligned_le32(&log->event_size);
>> +       if (evsz < offsetof(struct tcg_efi_spec_id_event, digest_sizes) ||
>> +           evsz + offsetof(struct tcg_pcr_event, event) > elog->log_size)
>> +               return 0;
>> +
>> +       event = (struct tcg_efi_spec_id_event *)log->event;
>> +       if (memcmp(event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
>> +                  sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03)))
>> +               return 0;
>> +
>> +       if (event->spec_version_minor != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
>> +           event->spec_version_major != TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
>> +               return 0;
>> +
>> +       count = get_unaligned_le32(&event->number_of_algorithms);
>> +       if (count > ARRAY_SIZE(tpm2_supported_algorithms))
>> +               return 0;
>> +
>> +       calc_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
>> +               (sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count) +
>> +               1;
>> +       if (evsz != calc_size)
>> +               return 0;
>> +
>> +       rc = tcg2_get_active_pcr_banks(dev, &active);
>> +       if (rc)
>> +               return rc;
>> +
>> +       digest_list.count = 0;
>> +       log_active = 0;
>> +
>> +       for (i = 0; i < count; ++i) {
>> +               algo = get_unaligned_le16(&event->digest_sizes[i].algorithm_id);
>> +               mask = tpm2_algorithm_to_mask(algo);
>> +
>> +               if (!(active & mask))
>> +                       return 0;
>> +
>> +               switch (algo) {
>> +               case TPM2_ALG_SHA1:
>> +               case TPM2_ALG_SHA256:
>> +               case TPM2_ALG_SHA384:
>> +               case TPM2_ALG_SHA512:
>> +                       len = get_unaligned_le16(&event->digest_sizes[i].digest_size);
>> +                       if (tpm2_algorithm_to_len(algo) != len)
>> +                               return 0;
>> +                       digest_list.digests[digest_list.count++].hash_alg = algo;
>> +                       break;
>> +               default:
>> +                       return 0;
>> +               }
>> +
>> +               log_active |= mask;
>> +       }
>> +
>> +       /* Ensure the previous firmware extended all the PCRs. */
>> +       if (log_active != active)
>> +               return 0;
>> +
>> +       /* Read PCR0 to check if previous firmware extended the PCRs or not. */
>> +       rc = tcg2_pcr_read(dev, 0, &digest_list);
>> +       if (rc)
>> +               return rc;
>> +
>> +       for (i = 0; i < digest_list.count; ++i) {
>> +               len = tpm2_algorithm_to_len(digest_list.digests[i].hash_alg);
>> +               for (j = 0; j < len; ++j) {
>> +                       if (digest_list.digests[i].digest.sha512[j])
>> +                               break;
>> +               }
>> +
>> +               /* PCR is non-zero; it has been extended, so skip extending. */
>> +               if (j != len) {
>> +                       digest_list.count = 0;
>> +                       break;
>> +               }
>> +       }
>> +
>> +       return tcg2_replay_eventlog(elog, dev, &digest_list,
>> +                                   offsetof(struct tcg_pcr_event, event) +
>> +                                   evsz);
>> +}
>> +
>> +int tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
>> +                   struct tpml_digest_values *digest_list)
>> +{
>> +       u32 rc;
>> +       u32 i;
>> +
>> +       for (i = 0; i < digest_list->count; i++) {
>> +               u32 alg = digest_list->digests[i].hash_alg;
>> +
>> +               rc = tpm2_pcr_extend(dev, pcr_index, alg,
>> +                                    (u8 *)&digest_list->digests[i].digest,
>> +                                    tpm2_algorithm_to_len(alg));
>> +               if (rc) {
>> +                       printf("%s: error pcr:%u alg:%08x\n", __func__,
>> +                              pcr_index, alg);
>> +                       return rc;
>> +               }
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +int tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
>> +                 struct tpml_digest_values *digest_list)
>> +{
>> +       struct tpm_chip_priv *priv;
>> +       u32 rc;
>> +       u32 i;
>> +
>> +       priv = dev_get_uclass_priv(dev);
>> +       if (!priv)
>> +               return -ENODEV;
>> +
>> +       for (i = 0; i < digest_list->count; i++) {
>> +               u32 alg = digest_list->digests[i].hash_alg;
>> +               u8 *digest = (u8 *)&digest_list->digests[i].digest;
>> +
>> +               rc = tpm2_pcr_read(dev, pcr_index, priv->pcr_select_min, alg,
>> +                                  digest, tpm2_algorithm_to_len(alg), NULL);
>> +               if (rc) {
>> +                       printf("%s: error pcr:%u alg:%08x\n", __func__,
>> +                              pcr_index, alg);
>> +                       return rc;
>> +               }
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +int tcg2_measure_data(struct udevice *dev, struct tcg2_event_log *elog,
>> +                     u32 pcr_index, u32 size, const u8 *data, u32 event_type,
>> +                     u32 event_size, const u8 *event)
>> +{
>> +       struct tpml_digest_values digest_list;
>> +       int rc;
>> +
>> +       if (data)
>> +               rc = tcg2_create_digest(dev, data, size, &digest_list);
>> +       else
>> +               rc = tcg2_create_digest(dev, event, event_size, &digest_list);
>> +       if (rc)
>> +               return rc;
>> +
>> +       rc = tcg2_pcr_extend(dev, pcr_index, &digest_list);
>> +       if (rc)
>> +               return rc;
>> +
>> +       return tcg2_log_append_check(elog, pcr_index, event_type, &digest_list,
>> +                                    event_size, event);
>> +}
>> +
>> +int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
>> +                           bool ignore_existing_log)
>> +{
>> +       struct tcg2_event_log log;
>> +       int rc;
>> +
>> +       elog->log_position = 0;
>> +       elog->found = false;
>> +
>> +       rc = tcg2_platform_get_log(dev, (void **)&log.log, &log.log_size);
>> +       if (!rc) {
>> +               log.log_position = 0;
>> +               log.found = false;
>> +
>> +               if (!ignore_existing_log) {
>> +                       rc = tcg2_log_parse(dev, &log);
>> +                       if (rc)
>> +                               return rc;
>> +               }
>> +
>> +               if (elog->log_size) {
>> +                       if (log.found) {
>> +                               if (elog->log_size < log.log_position)
>> +                                       return -ENOSPC;
>> +
>> +                               /*
>> +                                * Copy the discovered log into the user buffer
>> +                                * if there's enough space.
>> +                                */
>> +                               memcpy(elog->log, log.log, log.log_position);
>> +                       }
>> +
>> +                       unmap_physmem(log.log, MAP_NOCACHE);
>> +               } else {
>> +                       elog->log = log.log;
>> +                       elog->log_size = log.log_size;
>> +               }
>> +
>> +               elog->log_position = log.log_position;
>> +               elog->found = log.found;
>> +       }
>> +
>> +       /*
>> +        * Initialize the log buffer if no log was discovered and the buffer is
>> +        * valid. User's can pass in their own buffer as a fallback if no
>> +        * memory region is found.
>> +        */
>> +       if (!elog->found && elog->log_size)
>> +               rc = tcg2_log_init(dev, elog);
>> +
>> +       return rc;
>> +}
>> +
>> +int tcg2_measurement_init(struct udevice **dev, struct tcg2_event_log *elog,
>> +                         bool ignore_existing_log)
>> +{
>> +       int rc;
>> +
>> +       rc = tcg2_platform_get_tpm2(dev);
>> +       if (rc)
>> +               return rc;
>> +
>> +       rc = tpm_auto_start(*dev);
>> +       if (rc)
>> +               return rc;
>> +
>> +       rc = tcg2_log_prepare_buffer(*dev, elog, ignore_existing_log);
>> +       if (rc) {
>> +               tcg2_measurement_term(*dev, elog, true);
>> +               return rc;
>> +       }
>> +
>> +       rc = tcg2_measure_event(*dev, elog, 0, EV_S_CRTM_VERSION,
>> +                               strlen(version_string) + 1,
>> +                               (u8 *)version_string);
>> +       if (rc) {
>> +               tcg2_measurement_term(*dev, elog, true);
>> +               return rc;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
>> +                          bool error)
>> +{
>> +       u32 event = error ? 0x1 : 0xffffffff;
>> +       int i;
>> +
>> +       for (i = 0; i < 8; ++i)
>> +               tcg2_measure_event(dev, elog, i, EV_SEPARATOR, sizeof(event),
>> +                                  (const u8 *)&event);
>> +
>> +       if (elog->log)
>> +               unmap_physmem(elog->log, MAP_NOCACHE);
>> +}
>> +
>> +__weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size)
>> +{
>> +       const __be32 *addr_prop;
>> +       const __be32 *size_prop;
>> +       int asize;
>> +       int ssize;
>> +
>> +       *addr = NULL;
>> +       *size = 0;
>> +
>> +       addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize);
>> +       if (!addr_prop)
>> +               addr_prop = dev_read_prop(dev, "linux,sml-base", &asize);
>> +
>> +       size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize);
>> +       if (!size_prop)
>> +               size_prop = dev_read_prop(dev, "linux,sml-size", &ssize);
>> +
>> +       if (addr_prop && size_prop) {
>> +               u64 a = of_read_number(addr_prop, asize / sizeof(__be32));
>> +               u64 s = of_read_number(size_prop, ssize / sizeof(__be32));
>> +
>> +               *addr = map_physmem(a, s, MAP_NOCACHE);
>> +               *size = (u32)s;
>> +       } else {
>> +               struct ofnode_phandle_args args;
>> +               phys_addr_t a;
>> +               phys_size_t s;
>> +
>> +               if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0,
>> +                                              0, &args))
>> +                       return -ENODEV;
>> +
>> +               a = ofnode_get_addr_size(args.node, "reg", &s);
>> +               if (a == FDT_ADDR_T_NONE)
>> +                       return -ENOMEM;
>> +
>> +               *addr = map_physmem(a, s, MAP_NOCACHE);
>> +               *size = (u32)s;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +__weak int tcg2_platform_get_tpm2(struct udevice **dev)
>> +{
>> +       for_each_tpm_device(*dev) {
>> +               if (tpm_get_version(*dev) == TPM_V2)
>> +                       return 0;
>> +       }
>> +
>> +       return -ENODEV;
>> +}
>> +
>> +__weak void tcg2_platform_startup_error(struct udevice *dev, int rc) {}
>> +
>>   u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
>>   {
>>          const u8 command_v2[12] = {
>> @@ -359,6 +1048,131 @@ u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
>>          return 0;
>>   }
>>
>> +static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
>> +{
>> +       u8 response[(sizeof(struct tpms_capability_data) -
>> +               offsetof(struct tpms_capability_data, data))];
>> +       u32 properties_offset =
>> +               offsetof(struct tpml_tagged_tpm_property, tpm_property) +
>> +               offsetof(struct tpms_tagged_property, value);
>> +       u32 ret;
>> +
>> +       memset(response, 0, sizeof(response));
>> +       ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
>> +                                 TPM2_PT_PCR_COUNT, response, 1);
>> +       if (ret)
>> +               return ret;
>> +
>> +       *num_pcr = get_unaligned_be32(response + properties_offset);
>> +       if (*num_pcr > TPM2_MAX_PCRS) {
>> +               printf("%s: too many pcrs: %u\n", __func__, *num_pcr);
>> +               return -E2BIG;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection)
>> +{
>> +       int i;
>> +
>> +       /*
>> +        * check the pcr_select. If at least one of the PCRs supports the
>> +        * algorithm add it on the active ones
>> +        */
>> +       for (i = 0; i < selection->size_of_select; i++) {
>> +               if (selection->pcr_select[i])
>> +                       return true;
>> +       }
>> +
>> +       return false;
>> +}
>> +
>> +int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
>> +                     u32 *pcr_banks)
>> +{
>> +       u8 response[(sizeof(struct tpms_capability_data) -
>> +               offsetof(struct tpms_capability_data, data))];
>> +       struct tpml_pcr_selection pcrs;
>> +       u32 num_pcr;
>> +       size_t i;
>> +       u32 ret;
>> +
>> +       *supported_pcr = 0;
>> +       *active_pcr = 0;
>> +       *pcr_banks = 0;
>> +       memset(response, 0, sizeof(response));
>> +       ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
>> +       if (ret)
>> +               return ret;
>> +
>> +       pcrs.count = get_unaligned_be32(response);
>> +       /*
>> +        * We only support 5 algorithms for now so check against that
>> +        * instead of TPM2_NUM_PCR_BANKS
>> +        */
>> +       if (pcrs.count > ARRAY_SIZE(tpm2_supported_algorithms) ||
>> +           pcrs.count < 1) {
>> +               printf("%s: too many pcrs: %u\n", __func__, pcrs.count);
>> +               return -EMSGSIZE;
>> +       }
>> +
>> +       ret = tpm2_get_num_pcr(dev, &num_pcr);
>> +       if (ret)
>> +               return ret;
>> +
>> +       for (i = 0; i < pcrs.count; i++) {
>> +               /*
>> +                * Definition of TPMS_PCR_SELECTION Structure
>> +                * hash: u16
>> +                * size_of_select: u8
>> +                * pcr_select: u8 array
>> +                *
>> +                * The offsets depend on the number of the device PCRs
>> +                * so we have to calculate them based on that
>> +                */
>> +               u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
>> +                       i * offsetof(struct tpms_pcr_selection, pcr_select) +
>> +                       i * ((num_pcr + 7) / 8);
>> +               u32 size_select_offset =
>> +                       hash_offset + offsetof(struct tpms_pcr_selection,
>> +                                              size_of_select);
>> +               u32 pcr_select_offset =
>> +                       hash_offset + offsetof(struct tpms_pcr_selection,
>> +                                              pcr_select);
>> +
>> +               pcrs.selection[i].hash =
>> +                       get_unaligned_be16(response + hash_offset);
>> +               pcrs.selection[i].size_of_select =
>> +                       __get_unaligned_be(response + size_select_offset);
>> +               if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX) {
>> +                       printf("%s: pcrs selection too large: %u\n", __func__,
>> +                              pcrs.selection[i].size_of_select);
>> +                       return -ENOBUFS;
>> +               }
>> +               /* copy the array of pcr_select */
>> +               memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset,
>> +                      pcrs.selection[i].size_of_select);
>> +       }
>> +
>> +       for (i = 0; i < pcrs.count; i++) {
>> +               u32 hash_mask = tpm2_algorithm_to_mask(pcrs.selection[i].hash);
>> +
>> +               if (hash_mask) {
>> +                       *supported_pcr |= hash_mask;
>> +                       if (tpm2_is_active_pcr(&pcrs.selection[i]))
>> +                               *active_pcr |= hash_mask;
>> +               } else {
>> +                       printf("%s: unknown algorithm %x\n", __func__,
>> +                              pcrs.selection[i].hash);
>> +               }
>> +       }
>> +
>> +       *pcr_banks = pcrs.count;
>> +
>> +       return 0;
>> +}
>> +
>>   u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
>>   {
>>          u8 command_v2[COMMAND_BUFFER_SIZE] = {
>> --
>> 2.31.1
>>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v9 3/6] tpm: Support boot measurements
  2023-04-10 16:18     ` Eddie James
@ 2023-04-11  8:46       ` Ilias Apalodimas
  0 siblings, 0 replies; 16+ messages in thread
From: Ilias Apalodimas @ 2023-04-11  8:46 UTC (permalink / raw)
  To: Eddie James
  Cc: U-Boot Mailing List, Simon Glass, Heinrich Schuchardt, Joel Stanley

Ok thanks.

I am on PTO this week. I'll have a look once I get back

Cheers
Ilias

On Mon, Apr 10, 2023, 19:18 Eddie James <eajames@linux.ibm.com> wrote:

>
> On 4/6/23 04:18, Ilias Apalodimas wrote:
> > Hi Eddie,
> >
> > Do you plan on resending this?
> > If yes, I can spend some time trying to figure out the CI failures and
> > send you a patch.
>
>
> Hi,
>
> Yes I do, I have been short on time. I was a bit confused by the CI, it
> didn't seem to run with the updated v9? I believed I had fixed at least
> some of the failures with patch 2 to update the sandbox driver. I also
> haven't figured out how to run the ci suite locally
>
> Thanks,
>
> Eddie
>
> >
> > Thanks
> > /Ilias
> >
> >
> > On Wed, 8 Mar 2023 at 23:25, Eddie James <eajames@linux.ibm.com> wrote:
> >> Add TPM2 functions to support boot measurement. This includes
> >> starting up the TPM, initializing/appending the event log, and
> >> measuring the U-Boot version. Much of the code was used in the
> >> EFI subsystem, so remove it there and use the common functions.
> >>
> >> Signed-off-by: Eddie James <eajames@linux.ibm.com>
> >> ---
> >> Changes since v8:
> >>   - Fix log parsing again - any data corruption seen while replaying the
> >>     event log was failing the entire measurement.
> >>   - Added an option to ignore the existing log. This should only be used
> >>     for systems that know that U-Boot is the first stage bootloader.
> This
> >>     is necessary because the reserved memory region may persist through
> >>     resets and so U-Boot attempts to append to the previous boot's log.
> >>
> >> Changes since v7:
> >>   - Change name of tcg2_init_log and add more documentation
> >>   - Add a check, when parsing the event log header, to ensure that the
> >>     previous stage bootloader used all the active PCRs.
> >>   - Change name of tcg2_log_find_end
> >>   - Fix the greater than or equal to check to exit the log parsing
> >>   - Make sure log_position is 0 if there is any error discovering the
> log
> >>   - Return errors parsing the log if the data is corrupt so that we
> don't
> >>     end up with half a log
> >>
> >> Changes since v6:
> >>   - Added Linaro copyright for all the EFI moved code
> >>   - Changed tcg2_init_log (and by extension, tcg2_measurement_init) to
> >>     copy any discovered event log to the user's log if passed in.
> >>
> >> Changes since v5:
> >>   - Remove unused platform_get_eventlog in efi_tcg2.c
> >>   - First look for tpm_event_log_* properties instead of linux,sml-*
> >>   - Fix efi_tcg2.c compilation
> >>   - Select SHA* configs
> >>
> >> Changes since v4:
> >>   - Remove tcg2_measure_event function and check for NULL data in
> >>     tcg2_measure_data
> >>   - Use tpm_auto_startup
> >>   - Fix efi_tcg2.c compilation for removing tcg2_pcr_read function
> >>
> >> Changes since v3:
> >>   - Reordered headers
> >>   - Refactored more of EFI code into common code
> >>      Removed digest_info structure and instead used the common
> alg_to_mask
> >>        and alg_to_len
> >>      Improved event log parsing in common code to get it equivalent to
> EFI
> >>        Common code now extends PCR if previous bootloader stage couldn't
> >>        No need to allocate memory in the common code, so EFI copies the
> >>        discovered buffer like it did before
> >>      Rename efi measure_event function
> >>
> >> Changes since v1:
> >>   - Refactor TPM layer functions to allow EFI system to use them, and
> >>     remove duplicate EFI functions
> >>
> >>   include/efi_tcg2.h        |   44 --
> >>   include/tpm-v2.h          |  259 +++++++++
> >>   lib/Kconfig               |    4 +
> >>   lib/efi_loader/efi_tcg2.c | 1054 +++----------------------------------
> >>   lib/tpm-v2.c              |  814 ++++++++++++++++++++++++++++
> >>   5 files changed, 1154 insertions(+), 1021 deletions(-)
> >>
> >> diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
> >> index b1c3abd097..b21c5cb3dd 100644
> >> --- a/include/efi_tcg2.h
> >> +++ b/include/efi_tcg2.h
> >> @@ -129,50 +129,6 @@ struct efi_tcg2_boot_service_capability {
> >>   #define BOOT_SERVICE_CAPABILITY_MIN \
> >>          offsetof(struct efi_tcg2_boot_service_capability,
> number_of_pcr_banks)
> >>
> >> -#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03 "Spec ID Event03"
> >> -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2 2
> >> -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 0
> >> -#define TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2 2
> >> -
> >> -/**
> >> - *  struct TCG_EfiSpecIdEventAlgorithmSize - hashing algorithm
> information
> >> - *
> >> - *  @algorithm_id:     algorithm defined in enum tpm2_algorithms
> >> - *  @digest_size:      size of the algorithm
> >> - */
> >> -struct tcg_efi_spec_id_event_algorithm_size {
> >> -       u16      algorithm_id;
> >> -       u16      digest_size;
> >> -} __packed;
> >> -
> >> -/**
> >> - * struct TCG_EfiSpecIDEventStruct - content of the event log header
> >> - *
> >> - * @signature:                 signature, set to Spec ID Event03
> >> - * @platform_class:            class defined in TCG ACPI Specification
> >> - *                             Client  Common Header.
> >> - * @spec_version_minor:                minor version
> >> - * @spec_version_major:                major version
> >> - * @spec_version_errata:       major version
> >> - * @uintn_size:                        size of the efi_uintn_t fields
> used in various
> >> - *                             data structures used in this
> specification.
> >> - *                             0x01 indicates u32  and 0x02  indicates
> u64
> >> - * @number_of_algorithms:      hashing algorithms used in this event
> log
> >> - * @digest_sizes:              array of number_of_algorithms pairs
> >> - *                             1st member defines the algorithm id
> >> - *                             2nd member defines the algorithm size
> >> - */
> >> -struct tcg_efi_spec_id_event {
> >> -       u8 signature[16];
> >> -       u32 platform_class;
> >> -       u8 spec_version_minor;
> >> -       u8 spec_version_major;
> >> -       u8 spec_errata;
> >> -       u8 uintn_size;
> >> -       u32 number_of_algorithms;
> >> -       struct tcg_efi_spec_id_event_algorithm_size digest_sizes[];
> >> -} __packed;
> >> -
> >>   /**
> >>    * struct tdEFI_TCG2_FINAL_EVENTS_TABLE - log entries after Get Event
> Log
> >>    * @version:           version number for this structure
> >> diff --git a/include/tpm-v2.h b/include/tpm-v2.h
> >> index 6684033deb..33dd103767 100644
> >> --- a/include/tpm-v2.h
> >> +++ b/include/tpm-v2.h
> >> @@ -216,6 +216,50 @@ struct tcg_pcr_event2 {
> >>          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.
> >>    *
> >> @@ -342,6 +386,26 @@ enum tpm2_algorithms {
> >>          TPM2_ALG_SM3_256        = 0x12,
> >>   };
> >>
> >> +extern const enum tpm2_algorithms tpm2_supported_algorithms[4];
> >> +
> >> +static inline u16 tpm2_algorithm_to_len(enum tpm2_algorithms a)
> >> +{
> >> +       switch (a) {
> >> +       case TPM2_ALG_SHA1:
> >> +               return TPM2_SHA1_DIGEST_SIZE;
> >> +       case TPM2_ALG_SHA256:
> >> +               return TPM2_SHA256_DIGEST_SIZE;
> >> +       case TPM2_ALG_SHA384:
> >> +               return TPM2_SHA384_DIGEST_SIZE;
> >> +       case TPM2_ALG_SHA512:
> >> +               return TPM2_SHA512_DIGEST_SIZE;
> >> +       default:
> >> +               return 0;
> >> +       }
> >> +}
> >> +
> >> +#define tpm2_algorithm_to_mask(a)      (1 << (a))
> >> +
> >>   /* NV index attributes */
> >>   enum tpm_index_attrs {
> >>          TPMA_NV_PPWRITE         = 1UL << 0,
> >> @@ -421,6 +485,188 @@ enum {
> >>          HR_NV_INDEX             = TPM_HT_NV_INDEX << HR_SHIFT,
> >>   };
> >>
> >> +/**
> >> + * 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.
> >>    *
> >> @@ -540,6 +786,19 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx,
> unsigned int idx_min_sz,
> >>   u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32
> property,
> >>                          void *buf, size_t prop_count);
> >>
> >> +/**
> >> + * tpm2_get_pcr_info() - get the supported, active PCRs and number of
> banks
> >> + *
> >> + * @dev:               TPM device
> >> + * @supported_pcr:     bitmask with the algorithms supported
> >> + * @active_pcr:                bitmask with the active algorithms
> >> + * @pcr_banks:         number of PCR banks
> >> + *
> >> + * @return 0 on success, code of operation or negative errno on failure
> >> + */
> >> +int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32
> *active_pcr,
> >> +                     u32 *pcr_banks);
> >> +
> >>   /**
> >>    * Issue a TPM2_DictionaryAttackLockReset command.
> >>    *
> >> diff --git a/lib/Kconfig b/lib/Kconfig
> >> index 83e5edd73b..7a146c293f 100644
> >> --- a/lib/Kconfig
> >> +++ b/lib/Kconfig
> >> @@ -411,6 +411,10 @@ config TPM
> >>          bool "Trusted Platform Module (TPM) Support"
> >>          depends on DM
> >>          imply DM_RNG
> >> +       select SHA1
> >> +       select SHA256
> >> +       select SHA384
> >> +       select SHA512
> >>          help
> >>            This enables support for TPMs which can be used to provide
> security
> >>            features for your board. The TPM can be connected via LPC or
> I2C
> >> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> >> index a83ae7a46c..5f0f4b5dd2 100644
> >> --- a/lib/efi_loader/efi_tcg2.c
> >> +++ b/lib/efi_loader/efi_tcg2.c
> >> @@ -66,35 +66,6 @@ static bool tcg2_efi_app_invoked;
> >>   static const efi_guid_t efi_guid_tcg2_protocol =
> EFI_TCG2_PROTOCOL_GUID;
> >>   static const efi_guid_t efi_guid_final_events =
> EFI_TCG2_FINAL_EVENTS_TABLE_GUID;
> >>
> >> -struct digest_info {
> >> -       u16 hash_alg;
> >> -       u32 hash_mask;
> >> -       u16 hash_len;
> >> -};
> >> -
> >> -static const struct digest_info hash_algo_list[] = {
> >> -       {
> >> -               TPM2_ALG_SHA1,
> >> -               EFI_TCG2_BOOT_HASH_ALG_SHA1,
> >> -               TPM2_SHA1_DIGEST_SIZE,
> >> -       },
> >> -       {
> >> -               TPM2_ALG_SHA256,
> >> -               EFI_TCG2_BOOT_HASH_ALG_SHA256,
> >> -               TPM2_SHA256_DIGEST_SIZE,
> >> -       },
> >> -       {
> >> -               TPM2_ALG_SHA384,
> >> -               EFI_TCG2_BOOT_HASH_ALG_SHA384,
> >> -               TPM2_SHA384_DIGEST_SIZE,
> >> -       },
> >> -       {
> >> -               TPM2_ALG_SHA512,
> >> -               EFI_TCG2_BOOT_HASH_ALG_SHA512,
> >> -               TPM2_SHA512_DIGEST_SIZE,
> >> -       },
> >> -};
> >> -
> >>   struct variable_info {
> >>          const u16       *name;
> >>          bool            accept_empty;
> >> @@ -113,46 +84,6 @@ static struct variable_info secure_variables[] = {
> >>          {u"AuditMode",          false,  1},
> >>   };
> >>
> >> -#define MAX_HASH_COUNT ARRAY_SIZE(hash_algo_list)
> >> -
> >> -/**
> >> - * alg_to_mask - Get a TCG hash mask for algorithms
> >> - *
> >> - * @hash_alg: TCG defined algorithm
> >> - *
> >> - * @Return: TCG hashing algorithm bitmaps, 0 if the algorithm is not
> supported
> >> - */
> >> -static u32 alg_to_mask(u16 hash_alg)
> >> -{
> >> -       size_t i;
> >> -
> >> -       for (i = 0; i < MAX_HASH_COUNT; i++) {
> >> -               if (hash_algo_list[i].hash_alg == hash_alg)
> >> -                       return hash_algo_list[i].hash_mask;
> >> -       }
> >> -
> >> -       return 0;
> >> -}
> >> -
> >> -/**
> >> - * alg_to_len - Get a TCG hash len for algorithms
> >> - *
> >> - * @hash_alg: TCG defined algorithm
> >> - *
> >> - * @Return: len of chosen algorithm, 0 if the algorithm is not
> supported
> >> - */
> >> -static u16 alg_to_len(u16 hash_alg)
> >> -{
> >> -       size_t i;
> >> -
> >> -       for (i = 0; i < MAX_HASH_COUNT; i++) {
> >> -               if (hash_algo_list[i].hash_alg == hash_alg)
> >> -                       return hash_algo_list[i].hash_len;
> >> -       }
> >> -
> >> -       return 0;
> >> -}
> >> -
> >>   static bool is_tcg2_protocol_installed(void)
> >>   {
> >>          struct efi_handler *handler;
> >> @@ -162,145 +93,6 @@ static bool is_tcg2_protocol_installed(void)
> >>          return ret == EFI_SUCCESS;
> >>   }
> >>
> >> -static u32 tcg_event_final_size(struct tpml_digest_values *digest_list)
> >> -{
> >> -       u32 len;
> >> -       size_t i;
> >> -
> >> -       len = offsetof(struct tcg_pcr_event2, digests);
> >> -       len += offsetof(struct tpml_digest_values, digests);
> >> -       for (i = 0; i < digest_list->count; i++) {
> >> -               u16 hash_alg = digest_list->digests[i].hash_alg;
> >> -
> >> -               len += offsetof(struct tpmt_ha, digest);
> >> -               len += alg_to_len(hash_alg);
> >> -       }
> >> -       len += sizeof(u32); /* tcg_pcr_event2 event_size*/
> >> -
> >> -       return len;
> >> -}
> >> -
> >> -/* tcg2_pcr_extend - Extend PCRs for a TPM2 device for a given
> tpml_digest_values
> >> - *
> >> - * @dev:               device
> >> - * @digest_list:       list of digest algorithms to extend
> >> - *
> >> - * @Return: status code
> >> - */
> >> -static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
> >> -                                   struct tpml_digest_values
> *digest_list)
> >> -{
> >> -       u32 rc;
> >> -       size_t i;
> >> -
> >> -       for (i = 0; i < digest_list->count; i++) {
> >> -               u32 alg = digest_list->digests[i].hash_alg;
> >> -
> >> -               rc = tpm2_pcr_extend(dev, pcr_index, alg,
> >> -                                    (u8
> *)&digest_list->digests[i].digest,
> >> -                                    alg_to_len(alg));
> >> -               if (rc) {
> >> -                       EFI_PRINT("Failed to extend PCR\n");
> >> -                       return EFI_DEVICE_ERROR;
> >> -               }
> >> -       }
> >> -
> >> -       return EFI_SUCCESS;
> >> -}
> >> -
> >> -/* tcg2_pcr_read - Read PCRs for a TPM2 device for a given
> tpml_digest_values
> >> - *
> >> - * @dev:               device
> >> - * @pcr_index:         PCR index
> >> - * @digest_list:       list of digest algorithms to extend
> >> - *
> >> - * @Return: status code
> >> - */
> >> -static efi_status_t tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
> >> -                                 struct tpml_digest_values
> *digest_list)
> >> -{
> >> -       struct tpm_chip_priv *priv;
> >> -       unsigned int updates, pcr_select_min;
> >> -       u32 rc;
> >> -       size_t i;
> >> -
> >> -       priv = dev_get_uclass_priv(dev);
> >> -       if (!priv)
> >> -               return EFI_DEVICE_ERROR;
> >> -
> >> -       pcr_select_min = priv->pcr_select_min;
> >> -
> >> -       for (i = 0; i < digest_list->count; i++) {
> >> -               u16 hash_alg = digest_list->digests[i].hash_alg;
> >> -               u8 *digest = (u8 *)&digest_list->digests[i].digest;
> >> -
> >> -               rc = tpm2_pcr_read(dev, pcr_index, pcr_select_min,
> >> -                                  hash_alg, digest,
> alg_to_len(hash_alg),
> >> -                                  &updates);
> >> -               if (rc) {
> >> -                       EFI_PRINT("Failed to read PCR\n");
> >> -                       return EFI_DEVICE_ERROR;
> >> -               }
> >> -       }
> >> -
> >> -       return EFI_SUCCESS;
> >> -}
> >> -
> >> -/* put_event - Append an agile event to an eventlog
> >> - *
> >> - * @pcr_index:         PCR index
> >> - * @event_type:                type of event added
> >> - * @digest_list:       list of digest algorithms to add
> >> - * @size:              size of event
> >> - * @event:             event to add
> >> - * @log:               log buffer to append the event
> >> - *
> >> - */
> >> -static void put_event(u32 pcr_index, u32 event_type,
> >> -                     struct tpml_digest_values *digest_list, u32 size,
> >> -                     u8 event[], void *log)
> >> -{
> >> -       size_t pos;
> >> -       size_t i;
> >> -       u32 event_size;
> >> -
> >> -       /*
> >> -        * size refers to the length of event[] only, we need to check
> against
> >> -        * the final tcg_pcr_event2 size
> >> -        */
> >> -       event_size = size + tcg_event_final_size(digest_list);
> >> -
> >> -       put_unaligned_le32(pcr_index, log);
> >> -       pos = offsetof(struct tcg_pcr_event2, event_type);
> >> -       put_unaligned_le32(event_type, (void *)((uintptr_t)log + pos));
> >> -       pos = offsetof(struct tcg_pcr_event2, digests); /* count */
> >> -       put_unaligned_le32(digest_list->count, (void *)((uintptr_t)log
> + pos));
> >> -
> >> -       pos += offsetof(struct tpml_digest_values, digests);
> >> -       for (i = 0; i < digest_list->count; i++) {
> >> -               u16 hash_alg = digest_list->digests[i].hash_alg;
> >> -               u8 *digest = (u8 *)&digest_list->digests[i].digest;
> >> -
> >> -               put_unaligned_le16(hash_alg, (void *)((uintptr_t)log +
> pos));
> >> -               pos += offsetof(struct tpmt_ha, digest);
> >> -               memcpy((void *)((uintptr_t)log + pos), digest,
> alg_to_len(hash_alg));
> >> -               pos += alg_to_len(hash_alg);
> >> -       }
> >> -
> >> -       put_unaligned_le32(size, (void *)((uintptr_t)log + pos));
> >> -       pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
> >> -       memcpy((void *)((uintptr_t)log + pos), event, size);
> >> -       pos += size;
> >> -
> >> -       /*
> >> -        * make sure the calculated buffer is what we checked against
> >> -        * This check should never fail.  It checks the code above is
> >> -        * calculating the right length for the event we are adding
> >> -        */
> >> -       if (pos != event_size)
> >> -               log_err("Appending to the EventLog failed\n");
> >> -}
> >> -
> >>   /* tcg2_agile_log_append - Append an agile event to an eventlog
> >>    *
> >>    * @pcr_index:         PCR index
> >> @@ -317,7 +109,7 @@ static efi_status_t tcg2_agile_log_append(u32
> pcr_index, u32 event_type,
> >>                                            u32 size, u8 event[])
> >>   {
> >>          void *log = (void *)((uintptr_t)event_log.buffer +
> event_log.pos);
> >> -       u32 event_size = size + tcg_event_final_size(digest_list);
> >> +       u32 event_size = size + tcg2_event_get_size(digest_list);
> >>          struct efi_tcg2_final_events_table *final_event;
> >>          efi_status_t ret = EFI_SUCCESS;
> >>
> >> @@ -328,7 +120,7 @@ static efi_status_t tcg2_agile_log_append(u32
> pcr_index, u32 event_type,
> >>                          event_log.truncated = true;
> >>                          return EFI_VOLUME_FULL;
> >>                  }
> >> -               put_event(pcr_index, event_type, digest_list, size,
> event, log);
> >> +               tcg2_log_append(pcr_index, event_type, digest_list,
> size, event, log);
> >>                  event_log.pos += event_size;
> >>                  event_log.last_event_size = event_size;
> >>          }
> >> @@ -341,7 +133,7 @@ static efi_status_t tcg2_agile_log_append(u32
> pcr_index, u32 event_type,
> >>                  return EFI_VOLUME_FULL;
> >>
> >>          log = (void *)((uintptr_t)event_log.final_buffer +
> event_log.final_pos);
> >> -       put_event(pcr_index, event_type, digest_list, size, event, log);
> >> +       tcg2_log_append(pcr_index, event_type, digest_list, size,
> event, log);
> >>
> >>          final_event = event_log.final_buffer;
> >>          final_event->number_of_events++;
> >> @@ -350,66 +142,6 @@ static efi_status_t tcg2_agile_log_append(u32
> pcr_index, u32 event_type,
> >>          return ret;
> >>   }
> >>
> >> -/**
> >> - * platform_get_tpm_device() - retrieve TPM device
> >> - *
> >> - * This function retrieves the udevice implementing a TPM
> >> - *
> >> - * This function may be overridden if special initialization is needed.
> >> - *
> >> - * @dev:       udevice
> >> - * Return:     status code
> >> - */
> >> -__weak efi_status_t platform_get_tpm2_device(struct udevice **dev)
> >> -{
> >> -       for_each_tpm_device(*dev) {
> >> -               /* Only support TPMv2 devices */
> >> -               if (tpm_get_version(*dev) == TPM_V2)
> >> -                       return EFI_SUCCESS;
> >> -       }
> >> -
> >> -       return EFI_NOT_FOUND;
> >> -}
> >> -
> >> -/**
> >> - * platform_get_eventlog() - retrieve the eventlog address and size
> >> - *
> >> - * This function retrieves the eventlog address and size if the
> underlying
> >> - * firmware has done some measurements and passed them.
> >> - *
> >> - * This function may be overridden based on platform specific method of
> >> - * passing the eventlog address and size.
> >> - *
> >> - * @dev:       udevice
> >> - * @addr:      eventlog address
> >> - * @sz:                eventlog size
> >> - * Return:     status code
> >> - */
> >> -__weak efi_status_t platform_get_eventlog(struct udevice *dev, u64
> *addr,
> >> -                                         u32 *sz)
> >> -{
> >> -       const u64 *basep;
> >> -       const u32 *sizep;
> >> -
> >> -       basep = dev_read_prop(dev, "tpm_event_log_addr", NULL);
> >> -       if (!basep)
> >> -               return EFI_NOT_FOUND;
> >> -
> >> -       *addr = be64_to_cpup((__force __be64 *)basep);
> >> -
> >> -       sizep = dev_read_prop(dev, "tpm_event_log_size", NULL);
> >> -       if (!sizep)
> >> -               return EFI_NOT_FOUND;
> >> -
> >> -       *sz = be32_to_cpup((__force __be32 *)sizep);
> >> -       if (*sz == 0) {
> >> -               log_debug("event log empty\n");
> >> -               return EFI_NOT_FOUND;
> >> -       }
> >> -
> >> -       return EFI_SUCCESS;
> >> -}
> >> -
> >>   /**
> >>    * tpm2_get_max_command_size() - get the supported max command size
> >>    *
> >> @@ -485,239 +217,6 @@ static int tpm2_get_manufacturer_id(struct
> udevice *dev, u32 *manufacturer_id)
> >>          return 0;
> >>   }
> >>
> >> -/**
> >> - * tpm2_get_num_pcr() - get the number of PCRs
> >> - *
> >> - * @dev:               TPM device
> >> - * @manufacturer_id:   output buffer for the number
> >> - *
> >> - * Return: 0 on success, -1 on error
> >> - */
> >> -static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
> >> -{
> >> -       u8 response[TPM2_RESPONSE_BUFFER_SIZE];
> >> -       u32 ret;
> >> -
> >> -       memset(response, 0, sizeof(response));
> >> -       ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
> >> -                                 TPM2_PT_PCR_COUNT, response, 1);
> >> -       if (ret)
> >> -               return -1;
> >> -
> >> -       *num_pcr = get_unaligned_be32(response + properties_offset);
> >> -       if (*num_pcr > TPM2_MAX_PCRS)
> >> -               return -1;
> >> -
> >> -       return 0;
> >> -}
> >> -
> >> -/**
> >> - * is_active_pcr() - Check if a supported algorithm is active
> >> - *
> >> - * @dev:               TPM device
> >> - * @selection:         struct of PCR information
> >> - *
> >> - * Return: true if PCR is active
> >> - */
> >> -static bool is_active_pcr(struct tpms_pcr_selection *selection)
> >> -{
> >> -       int i;
> >> -       /*
> >> -        * check the pcr_select. If at least one of the PCRs supports
> the
> >> -        * algorithm add it on the active ones
> >> -        */
> >> -       for (i = 0; i < selection->size_of_select; i++) {
> >> -               if (selection->pcr_select[i])
> >> -                       return true;
> >> -       }
> >> -
> >> -       return false;
> >> -}
> >> -
> >> -/**
> >> - * tpm2_get_pcr_info() - get the supported, active PCRs and number of
> banks
> >> - *
> >> - * @dev:               TPM device
> >> - * @supported_pcr:     bitmask with the algorithms supported
> >> - * @active_pcr:                bitmask with the active algorithms
> >> - * @pcr_banks:         number of PCR banks
> >> - *
> >> - * Return: 0 on success, -1 on error
> >> - */
> >> -static int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr,
> >> -                            u32 *active_pcr, u32 *pcr_banks)
> >> -{
> >> -       u8 response[TPM2_RESPONSE_BUFFER_SIZE];
> >> -       struct tpml_pcr_selection pcrs;
> >> -       u32 ret, num_pcr;
> >> -       size_t i;
> >> -       int tpm_ret;
> >> -
> >> -       *supported_pcr = 0;
> >> -       *active_pcr = 0;
> >> -       *pcr_banks = 0;
> >> -       memset(response, 0, sizeof(response));
> >> -       ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
> >> -       if (ret)
> >> -               goto out;
> >> -
> >> -       pcrs.count = get_unaligned_be32(response);
> >> -       /*
> >> -        * We only support 5 algorithms for now so check against that
> >> -        * instead of TPM2_NUM_PCR_BANKS
> >> -        */
> >> -       if (pcrs.count > MAX_HASH_COUNT || pcrs.count < 1)
> >> -               goto out;
> >> -
> >> -       tpm_ret = tpm2_get_num_pcr(dev, &num_pcr);
> >> -       if (tpm_ret)
> >> -               goto out;
> >> -
> >> -       for (i = 0; i < pcrs.count; i++) {
> >> -               /*
> >> -                * Definition of TPMS_PCR_SELECTION Structure
> >> -                * hash: u16
> >> -                * size_of_select: u8
> >> -                * pcr_select: u8 array
> >> -                *
> >> -                * The offsets depend on the number of the device PCRs
> >> -                * so we have to calculate them based on that
> >> -                */
> >> -               u32 hash_offset = offsetof(struct tpml_pcr_selection,
> selection) +
> >> -                       i * offsetof(struct tpms_pcr_selection,
> pcr_select) +
> >> -                       i * ((num_pcr + 7) / 8);
> >> -               u32 size_select_offset =
> >> -                       hash_offset + offsetof(struct
> tpms_pcr_selection,
> >> -                                              size_of_select);
> >> -               u32 pcr_select_offset =
> >> -                       hash_offset + offsetof(struct
> tpms_pcr_selection,
> >> -                                              pcr_select);
> >> -
> >> -               pcrs.selection[i].hash =
> >> -                       get_unaligned_be16(response + hash_offset);
> >> -               pcrs.selection[i].size_of_select =
> >> -                       __get_unaligned_be(response +
> size_select_offset);
> >> -               if (pcrs.selection[i].size_of_select >
> TPM2_PCR_SELECT_MAX)
> >> -                       goto out;
> >> -               /* copy the array of pcr_select */
> >> -               memcpy(pcrs.selection[i].pcr_select, response +
> pcr_select_offset,
> >> -                      pcrs.selection[i].size_of_select);
> >> -       }
> >> -
> >> -       for (i = 0; i < pcrs.count; i++) {
> >> -               u32 hash_mask = alg_to_mask(pcrs.selection[i].hash);
> >> -
> >> -               if (hash_mask) {
> >> -                       *supported_pcr |= hash_mask;
> >> -                       if (is_active_pcr(&pcrs.selection[i]))
> >> -                               *active_pcr |= hash_mask;
> >> -               } else {
> >> -                       EFI_PRINT("Unknown algorithm %x\n",
> pcrs.selection[i].hash);
> >> -               }
> >> -       }
> >> -
> >> -       *pcr_banks = pcrs.count;
> >> -
> >> -       return 0;
> >> -out:
> >> -       return -1;
> >> -}
> >> -
> >> -/**
> >> - * __get_active_pcr_banks() - returns the currently active PCR banks
> >> - *
> >> - * @active_pcr_banks:          pointer for receiving the bitmap of
> currently
> >> - *                             active PCR banks
> >> - *
> >> - * Return:     status code
> >> - */
> >> -static efi_status_t __get_active_pcr_banks(u32 *active_pcr_banks)
> >> -{
> >> -       struct udevice *dev;
> >> -       u32 active = 0, supported = 0, pcr_banks = 0;
> >> -       efi_status_t ret;
> >> -       int err;
> >> -
> >> -       ret = platform_get_tpm2_device(&dev);
> >> -       if (ret != EFI_SUCCESS)
> >> -               goto out;
> >> -
> >> -       err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
> >> -       if (err) {
> >> -               ret = EFI_DEVICE_ERROR;
> >> -               goto out;
> >> -       }
> >> -
> >> -       *active_pcr_banks = active;
> >> -
> >> -out:
> >> -       return ret;
> >> -}
> >> -
> >> -/* tcg2_create_digest - create a list of digests of the supported PCR
> banks
> >> - *                     for a given memory range
> >> - *
> >> - * @input:             input memory
> >> - * @length:            length of buffer to calculate the digest
> >> - * @digest_list:       list of digests to fill in
> >> - *
> >> - * Return:             status code
> >> - */
> >> -static efi_status_t tcg2_create_digest(const u8 *input, u32 length,
> >> -                                      struct tpml_digest_values
> *digest_list)
> >> -{
> >> -       sha1_context ctx;
> >> -       sha256_context ctx_256;
> >> -       sha512_context ctx_512;
> >> -       u8 final[TPM2_SHA512_DIGEST_SIZE];
> >> -       efi_status_t ret;
> >> -       u32 active;
> >> -       size_t i;
> >> -
> >> -       ret = __get_active_pcr_banks(&active);
> >> -       if (ret != EFI_SUCCESS)
> >> -               return ret;
> >> -
> >> -       digest_list->count = 0;
> >> -       for (i = 0; i < MAX_HASH_COUNT; i++) {
> >> -               u16 hash_alg = hash_algo_list[i].hash_alg;
> >> -
> >> -               if (!(active & alg_to_mask(hash_alg)))
> >> -                       continue;
> >> -               switch (hash_alg) {
> >> -               case TPM2_ALG_SHA1:
> >> -                       sha1_starts(&ctx);
> >> -                       sha1_update(&ctx, input, length);
> >> -                       sha1_finish(&ctx, final);
> >> -                       break;
> >> -               case TPM2_ALG_SHA256:
> >> -                       sha256_starts(&ctx_256);
> >> -                       sha256_update(&ctx_256, input, length);
> >> -                       sha256_finish(&ctx_256, final);
> >> -                       break;
> >> -               case TPM2_ALG_SHA384:
> >> -                       sha384_starts(&ctx_512);
> >> -                       sha384_update(&ctx_512, input, length);
> >> -                       sha384_finish(&ctx_512, final);
> >> -                       break;
> >> -               case TPM2_ALG_SHA512:
> >> -                       sha512_starts(&ctx_512);
> >> -                       sha512_update(&ctx_512, input, length);
> >> -                       sha512_finish(&ctx_512, final);
> >> -                       break;
> >> -               default:
> >> -                       EFI_PRINT("Unsupported algorithm %x\n",
> hash_alg);
> >> -                       return EFI_INVALID_PARAMETER;
> >> -               }
> >> -               digest_list->digests[digest_list->count].hash_alg =
> hash_alg;
> >> -
>  memcpy(&digest_list->digests[digest_list->count].digest, final,
> >> -                      (u32)alg_to_len(hash_alg));
> >> -               digest_list->count++;
> >> -       }
> >> -
> >> -       return EFI_SUCCESS;
> >> -}
> >> -
> >>   /**
> >>    * efi_tcg2_get_capability() - protocol capability information and
> state information
> >>    *
> >> @@ -759,7 +258,7 @@ efi_tcg2_get_capability(struct efi_tcg2_protocol
> *this,
> >>          capability->protocol_version.major = 1;
> >>          capability->protocol_version.minor = 1;
> >>
> >> -       efi_ret = platform_get_tpm2_device(&dev);
> >> +       efi_ret = tcg2_platform_get_tpm2(&dev);
> >>          if (efi_ret != EFI_SUCCESS) {
> >>                  capability->supported_event_logs = 0;
> >>                  capability->hash_algorithm_bitmap = 0;
> >> @@ -855,7 +354,7 @@ efi_tcg2_get_eventlog(struct efi_tcg2_protocol
> *this,
> >>                  goto out;
> >>          }
> >>
> >> -       ret = platform_get_tpm2_device(&dev);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >>          if (ret != EFI_SUCCESS) {
> >>                  event_log_location = NULL;
> >>                  event_log_last_entry = NULL;
> >> @@ -890,6 +389,7 @@ static efi_status_t tcg2_hash_pe_image(void *efi,
> u64 efi_size,
> >>          struct efi_image_regions *regs = NULL;
> >>          void *new_efi = NULL;
> >>          u8 hash[TPM2_SHA512_DIGEST_SIZE];
> >> +       struct udevice *dev;
> >>          efi_status_t ret;
> >>          u32 active;
> >>          int i;
> >> @@ -905,16 +405,20 @@ static efi_status_t tcg2_hash_pe_image(void *efi,
> u64 efi_size,
> >>                  goto out;
> >>          }
> >>
> >> -       ret = __get_active_pcr_banks(&active);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >> +       if (ret != EFI_SUCCESS)
> >> +               goto out;
> >> +
> >> +       ret = tcg2_get_active_pcr_banks(dev, &active);
> >>          if (ret != EFI_SUCCESS) {
> >>                  goto out;
> >>          }
> >>
> >>          digest_list->count = 0;
> >> -       for (i = 0; i < MAX_HASH_COUNT; i++) {
> >> -               u16 hash_alg = hash_algo_list[i].hash_alg;
> >> +       for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); i++) {
> >> +               u16 hash_alg = tpm2_supported_algorithms[i];
> >>
> >> -               if (!(active & alg_to_mask(hash_alg)))
> >> +               if (!(active & tpm2_algorithm_to_mask(hash_alg)))
> >>                          continue;
> >>                  switch (hash_alg) {
> >>                  case TPM2_ALG_SHA1:
> >> @@ -935,7 +439,7 @@ static efi_status_t tcg2_hash_pe_image(void *efi,
> u64 efi_size,
> >>                  }
> >>                  digest_list->digests[digest_list->count].hash_alg =
> hash_alg;
> >>
> memcpy(&digest_list->digests[digest_list->count].digest, hash,
> >> -                      (u32)alg_to_len(hash_alg));
> >> +                      (u32)tpm2_algorithm_to_len(hash_alg));
> >>                  digest_list->count++;
> >>          }
> >>
> >> @@ -975,7 +479,7 @@ efi_status_t tcg2_measure_pe_image(void *efi, u64
> efi_size,
> >>          if (!is_tcg2_protocol_installed())
> >>                  return EFI_SUCCESS;
> >>
> >> -       ret = platform_get_tpm2_device(&dev);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >>          if (ret != EFI_SUCCESS)
> >>                  return EFI_SECURITY_VIOLATION;
> >>
> >> @@ -1084,7 +588,7 @@ efi_tcg2_hash_log_extend_event(struct
> efi_tcg2_protocol *this, u64 flags,
> >>                  goto out;
> >>          }
> >>
> >> -       ret = platform_get_tpm2_device(&dev);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >>          if (ret != EFI_SUCCESS)
> >>                  goto out;
> >>
> >> @@ -1119,7 +623,7 @@ efi_tcg2_hash_log_extend_event(struct
> efi_tcg2_protocol *this, u64 flags,
> >>                  ret = tcg2_hash_pe_image((void
> *)(uintptr_t)data_to_hash,
> >>                                           data_to_hash_len,
> &digest_list);
> >>          } else {
> >> -               ret = tcg2_create_digest((u8 *)(uintptr_t)data_to_hash,
> >> +               ret = tcg2_create_digest(dev, (u8
> *)(uintptr_t)data_to_hash,
> >>                                           data_to_hash_len,
> &digest_list);
> >>          }
> >>
> >> @@ -1182,7 +686,7 @@ efi_tcg2_submit_command(struct efi_tcg2_protocol
> *this,
> >>                  goto out;
> >>          }
> >>
> >> -       ret = platform_get_tpm2_device(&dev);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >>          if (ret != EFI_SUCCESS)
> >>                  goto out;
> >>
> >> @@ -1211,6 +715,7 @@ static efi_status_t EFIAPI
> >>   efi_tcg2_get_active_pcr_banks(struct efi_tcg2_protocol *this,
> >>                                u32 *active_pcr_banks)
> >>   {
> >> +       struct udevice *dev;
> >>          efi_status_t ret;
> >>
> >>          if (!this || !active_pcr_banks) {
> >> @@ -1218,8 +723,12 @@ efi_tcg2_get_active_pcr_banks(struct
> efi_tcg2_protocol *this,
> >>                  goto out;
> >>          }
> >>
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >> +       if (ret != EFI_SUCCESS)
> >> +               goto out;
> >> +
> >>          EFI_ENTRY("%p, %p", this, active_pcr_banks);
> >> -       ret = __get_active_pcr_banks(active_pcr_banks);
> >> +       ret = tcg2_get_active_pcr_banks(dev, active_pcr_banks);
> >>
> >>   out:
> >>          return EFI_EXIT(ret);
> >> @@ -1270,397 +779,6 @@ static const struct efi_tcg2_protocol
> efi_tcg2_protocol = {
> >>          .get_result_of_set_active_pcr_banks =
> efi_tcg2_get_result_of_set_active_pcr_banks,
> >>   };
> >>
> >> -/**
> >> - * parse_event_log_header() -  Parse and verify the event log header
> fields
> >> - *
> >> - * @buffer:                    Pointer to the start of the eventlog
> >> - * @size:                      Size of the eventlog
> >> - * @pos:                       Return offset of the next event in
> buffer right
> >> - *                             after the event header i.e specID
> >> - *
> >> - * Return:     status code
> >> - */
> >> -static efi_status_t parse_event_log_header(void *buffer, u32 size, u32
> *pos)
> >> -{
> >> -       struct tcg_pcr_event *event_header = (struct tcg_pcr_event
> *)buffer;
> >> -       int i = 0;
> >> -
> >> -       if (size < sizeof(*event_header))
> >> -               return EFI_COMPROMISED_DATA;
> >> -
> >> -       if (get_unaligned_le32(&event_header->pcr_index) != 0 ||
> >> -           get_unaligned_le32(&event_header->event_type) !=
> EV_NO_ACTION)
> >> -               return EFI_COMPROMISED_DATA;
> >> -
> >> -       for (i = 0; i < sizeof(event_header->digest); i++) {
> >> -               if (event_header->digest[i])
> >> -                       return EFI_COMPROMISED_DATA;
> >> -       }
> >> -
> >> -       *pos += sizeof(*event_header);
> >> -
> >> -       return EFI_SUCCESS;
> >> -}
> >> -
> >> -/**
> >> - * parse_specid_event() -  Parse and verify the specID Event in the
> eventlog
> >> - *
> >> - * @dev:               udevice
> >> - * @buffer:            Pointer to the start of the eventlog
> >> - * @log_size:          Size of the eventlog
> >> - * @pos:               [in] Offset of specID event in the eventlog
> buffer
> >> - *                     [out] Return offset of the next event in the
> buffer
> >> - *                     after the specID
> >> - * @digest_list:       list of digests in the event
> >> - *
> >> - * Return:             status code
> >> - * @pos                        Offset in the eventlog where the specID
> event ends
> >> - * @digest_list:       list of digests in the event
> >> - */
> >> -static efi_status_t parse_specid_event(struct udevice *dev, void
> *buffer,
> >> -                                      u32 log_size, u32 *pos,
> >> -                                      struct tpml_digest_values
> *digest_list)
> >> -{
> >> -       struct tcg_efi_spec_id_event *spec_event;
> >> -       struct tcg_pcr_event *event_header = (struct tcg_pcr_event
> *)buffer;
> >> -       size_t spec_event_size;
> >> -       u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
> >> -       u32 spec_active = 0;
> >> -       u16 hash_alg;
> >> -       u8 vendor_sz;
> >> -       int err, i;
> >> -
> >> -       if (*pos >= log_size || (*pos + sizeof(*spec_event)) > log_size)
> >> -               return EFI_COMPROMISED_DATA;
> >> -
> >> -       /* Check specID event data */
> >> -       spec_event = (struct tcg_efi_spec_id_event *)((uintptr_t)buffer
> + *pos);
> >> -       /* Check for signature */
> >> -       if (memcmp(spec_event->signature,
> TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
> >> -                  sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03))) {
> >> -               log_err("specID Event: Signature mismatch\n");
> >> -               return EFI_COMPROMISED_DATA;
> >> -       }
> >> -
> >> -       if (spec_event->spec_version_minor !=
> >> -                       TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
> >> -           spec_event->spec_version_major !=
> >> -                       TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
> >> -               return EFI_COMPROMISED_DATA;
> >> -
> >> -       if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
> >> -           spec_event->number_of_algorithms < 1) {
> >> -               log_err("specID Event: Number of algorithms
> incorrect\n");
> >> -               return EFI_COMPROMISED_DATA;
> >> -       }
> >> -
> >> -       alg_count = spec_event->number_of_algorithms;
> >> -
> >> -       err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
> >> -       if (err)
> >> -               return EFI_DEVICE_ERROR;
> >> -
> >> -       digest_list->count = 0;
> >> -       /*
> >> -        * We have to take care that the sequence of algorithms that we
> record
> >> -        * in digest_list matches the sequence in eventlog.
> >> -        */
> >> -       for (i = 0; i < alg_count; i++) {
> >> -               hash_alg =
> >> -
>  get_unaligned_le16(&spec_event->digest_sizes[i].algorithm_id);
> >> -
> >> -               if (!(supported & alg_to_mask(hash_alg))) {
> >> -                       log_err("specID Event: Unsupported
> algorithm\n");
> >> -                       return EFI_COMPROMISED_DATA;
> >> -               }
> >> -               digest_list->digests[digest_list->count++].hash_alg =
> hash_alg;
> >> -
> >> -               spec_active |= alg_to_mask(hash_alg);
> >> -       }
> >> -
> >> -       /*
> >> -        * TCG specification expects the event log to have hashes for
> all
> >> -        * active PCR's
> >> -        */
> >> -       if (spec_active != active) {
> >> -               /*
> >> -                * Previous stage bootloader should know all the active
> PCR's
> >> -                * and use them in the Eventlog.
> >> -                */
> >> -               log_err("specID Event: All active hash alg not
> present\n");
> >> -               return EFI_COMPROMISED_DATA;
> >> -       }
> >> -
> >> -       /*
> >> -        * the size of the spec event and placement of vendor_info_size
> >> -        * depends on supported algoriths
> >> -        */
> >> -       spec_event_size =
> >> -               offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
> >> -               alg_count * sizeof(spec_event->digest_sizes[0]);
> >> -
> >> -       if (*pos + spec_event_size >= log_size)
> >> -               return EFI_COMPROMISED_DATA;
> >> -
> >> -       vendor_sz = *(uint8_t *)((uintptr_t)buffer + *pos +
> spec_event_size);
> >> -
> >> -       spec_event_size += sizeof(vendor_sz) + vendor_sz;
> >> -       *pos += spec_event_size;
> >> -
> >> -       if (get_unaligned_le32(&event_header->event_size) !=
> spec_event_size) {
> >> -               log_err("specID event: header event size mismatch\n");
> >> -               /* Right way to handle this can be to call SetActive
> PCR's */
> >> -               return EFI_COMPROMISED_DATA;
> >> -       }
> >> -
> >> -       return EFI_SUCCESS;
> >> -}
> >> -
> >> -/**
> >> - * tcg2_parse_event() -  Parse the event in the eventlog
> >> - *
> >> - * @dev:               udevice
> >> - * @buffer:            Pointer to the start of the eventlog
> >> - * @log_size:          Size of the eventlog
> >> - * @offset:            [in] Offset of the event in the eventlog buffer
> >> - *                     [out] Return offset of the next event in the
> buffer
> >> - * @digest_list:       list of digests in the event
> >> - * @pcr                        Index of the PCR in the event
> >> - *
> >> - * Return:             status code
> >> - */
> >> -static efi_status_t tcg2_parse_event(struct udevice *dev, void *buffer,
> >> -                                    u32 log_size, u32 *offset,
> >> -                                    struct tpml_digest_values
> *digest_list,
> >> -                                    u32 *pcr)
> >> -{
> >> -       struct tcg_pcr_event2 *event = NULL;
> >> -       u32 count, size, event_size;
> >> -       size_t pos;
> >> -
> >> -       event_size = tcg_event_final_size(digest_list);
> >> -       if (*offset >= log_size || *offset + event_size > log_size) {
> >> -               log_err("Event exceeds log size\n");
> >> -               return EFI_COMPROMISED_DATA;
> >> -       }
> >> -
> >> -       event = (struct tcg_pcr_event2 *)((uintptr_t)buffer + *offset);
> >> -       *pcr = get_unaligned_le32(&event->pcr_index);
> >> -
> >> -       /* get the count */
> >> -       count = get_unaligned_le32(&event->digests.count);
> >> -       if (count != digest_list->count)
> >> -               return EFI_COMPROMISED_DATA;
> >> -
> >> -       pos = offsetof(struct tcg_pcr_event2, digests);
> >> -       pos += offsetof(struct tpml_digest_values, digests);
> >> -
> >> -       for (int i = 0; i < digest_list->count; i++) {
> >> -               u16 alg;
> >> -               u16 hash_alg = digest_list->digests[i].hash_alg;
> >> -               u8 *digest = (u8 *)&digest_list->digests[i].digest;
> >> -
> >> -               alg = get_unaligned_le16((void *)((uintptr_t)event +
> pos));
> >> -
> >> -               if (alg != hash_alg)
> >> -                       return EFI_COMPROMISED_DATA;
> >> -
> >> -               pos += offsetof(struct tpmt_ha, digest);
> >> -               memcpy(digest, (void *)((uintptr_t)event + pos),
> alg_to_len(hash_alg));
> >> -               pos += alg_to_len(hash_alg);
> >> -       }
> >> -
> >> -       size = get_unaligned_le32((void *)((uintptr_t)event + pos));
> >> -       event_size += size;
> >> -       pos += sizeof(u32); /* tcg_pcr_event2 event_size*/
> >> -       pos += size;
> >> -
> >> -       /* make sure the calculated buffer is what we checked against */
> >> -       if (pos != event_size)
> >> -               return EFI_COMPROMISED_DATA;
> >> -
> >> -       if (pos > log_size)
> >> -               return EFI_COMPROMISED_DATA;
> >> -
> >> -       *offset += pos;
> >> -
> >> -       return EFI_SUCCESS;
> >> -}
> >> -
> >> -/**
> >> - * tcg2_get_fw_eventlog() -  Get the eventlog address and size
> >> - *
> >> - * If the previous firmware has passed some eventlog, this function
> get it's
> >> - * location and check for it's validity.
> >> - *
> >> - * @dev:               udevice
> >> - * @log_buffer:                eventlog address
> >> - * @log_sz:            eventlog size
> >> - *
> >> - * Return:     status code
> >> - */
> >> -static efi_status_t tcg2_get_fw_eventlog(struct udevice *dev, void
> *log_buffer,
> >> -                                        size_t *log_sz)
> >> -{
> >> -       struct tpml_digest_values digest_list;
> >> -       void *buffer;
> >> -       efi_status_t ret;
> >> -       u32 pcr, pos;
> >> -       u64 base;
> >> -       u32 sz;
> >> -       bool extend_pcr = false;
> >> -       int i;
> >> -
> >> -       ret = platform_get_eventlog(dev, &base, &sz);
> >> -       if (ret != EFI_SUCCESS)
> >> -               return ret;
> >> -
> >> -       if (sz > TPM2_EVENT_LOG_SIZE)
> >> -               return EFI_VOLUME_FULL;
> >> -
> >> -       buffer = (void *)(uintptr_t)base;
> >> -       pos = 0;
> >> -       /* Parse the eventlog to check for its validity */
> >> -       ret = parse_event_log_header(buffer, sz, &pos);
> >> -       if (ret)
> >> -               return ret;
> >> -
> >> -       ret = parse_specid_event(dev, buffer, sz, &pos, &digest_list);
> >> -       if (ret) {
> >> -               log_err("Error parsing SPEC ID Event\n");
> >> -               return ret;
> >> -       }
> >> -
> >> -       ret = tcg2_pcr_read(dev, 0, &digest_list);
> >> -       if (ret) {
> >> -               log_err("Error reading PCR 0\n");
> >> -               return ret;
> >> -       }
> >> -
> >> -       /*
> >> -        * If PCR0 is 0, previous firmware didn't have the capability
> >> -        * to extend the PCR. In this scenario, extend the PCR as
> >> -        * the eventlog is parsed.
> >> -        */
> >> -       for (i = 0; i < digest_list.count; i++) {
> >> -               u8 hash_buf[TPM2_SHA512_DIGEST_SIZE] = { 0 };
> >> -               u16 hash_alg = digest_list.digests[i].hash_alg;
> >> -
> >> -               if (!memcmp((u8 *)&digest_list.digests[i].digest,
> hash_buf,
> >> -                           alg_to_len(hash_alg)))
> >> -                       extend_pcr = true;
> >> -       }
> >> -
> >> -       while (pos < sz) {
> >> -               ret = tcg2_parse_event(dev, buffer, sz, &pos,
> &digest_list,
> >> -                                      &pcr);
> >> -               if (ret) {
> >> -                       log_err("Error parsing event\n");
> >> -                       return ret;
> >> -               }
> >> -               if (extend_pcr) {
> >> -                       ret = tcg2_pcr_extend(dev, pcr, &digest_list);
> >> -                       if (ret != EFI_SUCCESS) {
> >> -                               log_err("Error in extending PCR\n");
> >> -                               return ret;
> >> -                       }
> >> -
> >> -                       /* Clear the digest for next event */
> >> -                       for (i = 0; i < digest_list.count; i++) {
> >> -                               u16 hash_alg =
> digest_list.digests[i].hash_alg;
> >> -                               u8 *digest =
> >> -                                  (u8 *)&digest_list.digests[i].digest;
> >> -
> >> -                               memset(digest, 0, alg_to_len(hash_alg));
> >> -                       }
> >> -               }
> >> -       }
> >> -
> >> -       memcpy(log_buffer, buffer, sz);
> >> -       *log_sz = sz;
> >> -
> >> -       return ret;
> >> -}
> >> -
> >> -/**
> >> - * create_specid_event() - Create the first event in the eventlog
> >> - *
> >> - * @dev:                       tpm device
> >> - * @event_header:              Pointer to the final event header
> >> - * @event_size:                        final spec event size
> >> - *
> >> - * Return:     status code
> >> - */
> >> -static efi_status_t create_specid_event(struct udevice *dev, void
> *buffer,
> >> -                                       size_t *event_size)
> >> -{
> >> -       struct tcg_efi_spec_id_event *spec_event;
> >> -       size_t spec_event_size;
> >> -       efi_status_t ret = EFI_DEVICE_ERROR;
> >> -       u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0;
> >> -       int err;
> >> -       size_t i;
> >> -
> >> -       /*
> >> -        * Create Spec event. This needs to be the first event in the
> log
> >> -        * according to the TCG EFI protocol spec
> >> -        */
> >> -
> >> -       /* Setup specID event data */
> >> -       spec_event = (struct tcg_efi_spec_id_event *)buffer;
> >> -       memcpy(spec_event->signature,
> TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
> >> -              sizeof(spec_event->signature));
> >> -       put_unaligned_le32(0, &spec_event->platform_class); /* type
> client */
> >> -       spec_event->spec_version_minor =
> >> -               TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2;
> >> -       spec_event->spec_version_major =
> >> -               TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2;
> >> -       spec_event->spec_errata =
> >> -               TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_ERRATA_TPM2;
> >> -       spec_event->uintn_size = sizeof(efi_uintn_t) / sizeof(u32);
> >> -
> >> -       err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count);
> >> -
> >> -       if (err)
> >> -               goto out;
> >> -
> >> -       for (i = 0; i < pcr_count; i++) {
> >> -               u16 hash_alg = hash_algo_list[i].hash_alg;
> >> -               u16 hash_len = hash_algo_list[i].hash_len;
> >> -
> >> -               if (active & alg_to_mask(hash_alg)) {
> >> -                       put_unaligned_le16(hash_alg,
> >> -
> &spec_event->digest_sizes[alg_count].algorithm_id);
> >> -                       put_unaligned_le16(hash_len,
> >> -
> &spec_event->digest_sizes[alg_count].digest_size);
> >> -                       alg_count++;
> >> -               }
> >> -       }
> >> -
> >> -       spec_event->number_of_algorithms = alg_count;
> >> -       if (spec_event->number_of_algorithms > MAX_HASH_COUNT ||
> >> -           spec_event->number_of_algorithms < 1)
> >> -               goto out;
> >> -
> >> -       /*
> >> -        * the size of the spec event and placement of vendor_info_size
> >> -        * depends on supported algoriths
> >> -        */
> >> -       spec_event_size =
> >> -               offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
> >> -               spec_event->number_of_algorithms *
> sizeof(spec_event->digest_sizes[0]);
> >> -       /* no vendor info for us */
> >> -       memset(buffer + spec_event_size, 0, 1);
> >> -       /* add a byte for vendor_info_size in the spec event */
> >> -       spec_event_size += 1;
> >> -       *event_size = spec_event_size;
> >> -
> >> -       return EFI_SUCCESS;
> >> -
> >> -out:
> >> -       return ret;
> >> -}
> >> -
> >>   /**
> >>    * tcg2_uninit - remove the final event table and free efi memory on
> failures
> >>    */
> >> @@ -1722,7 +840,7 @@ out:
> >>   }
> >>
> >>   /**
> >> - * tcg2_measure_event() - common function to add event log and extend
> PCR
> >> + * measure_event() - common function to add event log and extend PCR
> >>    *
> >>    * @dev:               TPM device
> >>    * @pcr_index:         PCR index
> >> @@ -1732,14 +850,13 @@ out:
> >>    *
> >>    * Return:     status code
> >>    */
> >> -static efi_status_t
> >> -tcg2_measure_event(struct udevice *dev, u32 pcr_index, u32 event_type,
> >> -                  u32 size, u8 event[])
> >> +static efi_status_t measure_event(struct udevice *dev, u32 pcr_index,
> >> +                                 u32 event_type, u32 size, u8 event[])
> >>   {
> >>          struct tpml_digest_values digest_list;
> >>          efi_status_t ret;
> >>
> >> -       ret = tcg2_create_digest(event, size, &digest_list);
> >> +       ret = tcg2_create_digest(dev, event, size, &digest_list);
> >>          if (ret != EFI_SUCCESS)
> >>                  goto out;
> >>
> >> @@ -1766,9 +883,8 @@ static efi_status_t
> efi_append_scrtm_version(struct udevice *dev)
> >>   {
> >>          efi_status_t ret;
> >>
> >> -       ret = tcg2_measure_event(dev, 0, EV_S_CRTM_VERSION,
> >> -                                strlen(version_string) + 1,
> >> -                                (u8 *)version_string);
> >> +       ret = measure_event(dev, 0, EV_S_CRTM_VERSION,
> >> +                           strlen(version_string) + 1, (u8
> *)version_string);
> >>
> >>          return ret;
> >>   }
> >> @@ -1784,12 +900,11 @@ static efi_status_t efi_init_event_log(void)
> >>           * vendor_info_size is currently set to 0, we need to change
> the length
> >>           * and allocate the flexible array member if this changes
> >>           */
> >> -       struct tcg_pcr_event *event_header = NULL;
> >> +       struct tcg2_event_log elog;
> >>          struct udevice *dev;
> >> -       size_t spec_event_size;
> >>          efi_status_t ret;
> >>
> >> -       ret = platform_get_tpm2_device(&dev);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >>          if (ret != EFI_SUCCESS)
> >>                  return ret;
> >>
> >> @@ -1808,7 +923,6 @@ static efi_status_t efi_init_event_log(void)
> >>           * The log header is defined to be in SHA1 event log entry
> format.
> >>           * Setup event header
> >>           */
> >> -       event_header =  (struct tcg_pcr_event *)event_log.buffer;
> >>          event_log.pos = 0;
> >>          event_log.last_event_size = 0;
> >>          event_log.get_event_called = false;
> >> @@ -1819,34 +933,20 @@ static efi_status_t efi_init_event_log(void)
> >>           * Check if earlier firmware have passed any eventlog.
> Different
> >>           * platforms can use different ways to do so.
> >>           */
> >> -       ret = tcg2_get_fw_eventlog(dev, event_log.buffer,
> &event_log.pos);
> >> +       elog.log = event_log.buffer;
> >> +       elog.log_size = TPM2_EVENT_LOG_SIZE;
> >> +       ret = tcg2_log_prepare_buffer(dev, &elog, false);
> >> +       if (ret != EFI_SUCCESS)
> >> +               goto free_pool;
> >> +
> >> +       event_log.pos = elog.log_position;
> >> +
> >>          /*
> >> -        * If earlier firmware hasn't passed any eventlog, go ahead and
> >> -        * create the eventlog header.
> >> +        * Add SCRTM version to the log if previous firmmware
> >> +        * doesn't pass an eventlog.
> >>           */
> >> -       if (ret == EFI_NOT_FOUND) {
> >> -               put_unaligned_le32(0, &event_header->pcr_index);
> >> -               put_unaligned_le32(EV_NO_ACTION,
> &event_header->event_type);
> >> -               memset(&event_header->digest, 0,
> sizeof(event_header->digest));
> >> -               ret = create_specid_event(dev,
> >> -                                         (void
> *)((uintptr_t)event_log.buffer +
> >> -
> sizeof(*event_header)),
> >> -                                         &spec_event_size);
> >> -               if (ret != EFI_SUCCESS)
> >> -                       goto free_pool;
> >> -               put_unaligned_le32(spec_event_size,
> &event_header->event_size);
> >> -               event_log.pos = spec_event_size + sizeof(*event_header);
> >> -               event_log.last_event_size = event_log.pos;
> >> -
> >> -               /*
> >> -                * Add SCRTM version to the log if previous firmmware
> >> -                * doesn't pass an eventlog.
> >> -                */
> >> +       if (!elog.found)
> >>                  ret = efi_append_scrtm_version(dev);
> >> -       }
> >> -
> >> -       if (ret != EFI_SUCCESS)
> >> -               goto free_pool;
> >>
> >>          ret = create_final_event();
> >>          if (ret != EFI_SUCCESS)
> >> @@ -1899,8 +999,8 @@ static efi_status_t tcg2_measure_variable(struct
> udevice *dev, u32 pcr_index,
> >>                  memcpy((u16 *)event->unicode_name +
> event->unicode_name_length,
> >>                         data, data_size);
> >>          }
> >> -       ret = tcg2_measure_event(dev, pcr_index, event_type, event_size,
> >> -                                (u8 *)event);
> >> +       ret = measure_event(dev, pcr_index, event_type, event_size,
> >> +                           (u8 *)event);
> >>          free(event);
> >>          return ret;
> >>   }
> >> @@ -2011,8 +1111,8 @@ tcg2_measure_smbios(struct udevice *dev,
> >>
> >>          smbios_prepare_measurement(entry, smbios_copy);
> >>
> >> -       ret = tcg2_measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2,
> event_size,
> >> -                                (u8 *)event);
> >> +       ret = measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
> >> +                           (u8 *)event);
> >>          if (ret != EFI_SUCCESS)
> >>                  goto out;
> >>
> >> @@ -2163,7 +1263,7 @@ tcg2_measure_gpt_data(struct udevice *dev,
> >>                  gpt_e = (gpt_entry *)((u8 *)gpt_e +
> gpt_h->sizeof_partition_entry);
> >>          }
> >>
> >> -       ret = tcg2_measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size,
> (u8 *)event);
> >> +       ret = measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8
> *)event);
> >>
> >>   out2:
> >>          free(gpt_h);
> >> @@ -2217,7 +1317,7 @@ efi_status_t efi_tcg2_measure_dtb(void *dtb)
> >>          if (!is_tcg2_protocol_installed())
> >>                  return EFI_SUCCESS;
> >>
> >> -       ret = platform_get_tpm2_device(&dev);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >>          if (ret != EFI_SUCCESS)
> >>                  return EFI_SECURITY_VIOLATION;
> >>
> >> @@ -2242,7 +1342,7 @@ efi_status_t efi_tcg2_measure_dtb(void *dtb)
> >>          sha256_update(&hash_ctx, (u8 *)dtb + fdt_off_mem_rsvmap(dtb),
> rsvmap_size);
> >>          sha256_finish(&hash_ctx, blob->data +
> blob->blob_description_size);
> >>
> >> -       ret = tcg2_measure_event(dev, 0, EV_POST_CODE, event_size, (u8
> *)blob);
> >> +       ret = measure_event(dev, 0, EV_POST_CODE, event_size, (u8
> *)blob);
> >>
> >>          free(blob);
> >>          return ret;
> >> @@ -2267,7 +1367,7 @@ efi_status_t
> efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
> >>          if (tcg2_efi_app_invoked)
> >>                  return EFI_SUCCESS;
> >>
> >> -       ret = platform_get_tpm2_device(&dev);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >>          if (ret != EFI_SUCCESS)
> >>                  return EFI_SECURITY_VIOLATION;
> >>
> >> @@ -2275,9 +1375,9 @@ efi_status_t
> efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
> >>          if (ret != EFI_SUCCESS)
> >>                  goto out;
> >>
> >> -       ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION,
> >> -                                strlen(EFI_CALLING_EFI_APPLICATION),
> >> -                                (u8 *)EFI_CALLING_EFI_APPLICATION);
> >> +       ret = measure_event(dev, 4, EV_EFI_ACTION,
> >> +                           strlen(EFI_CALLING_EFI_APPLICATION),
> >> +                           (u8 *)EFI_CALLING_EFI_APPLICATION);
> >>          if (ret != EFI_SUCCESS)
> >>                  goto out;
> >>
> >> @@ -2293,8 +1393,8 @@ efi_status_t
> efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha
> >>                  goto out;
> >>
> >>          for (pcr_index = 0; pcr_index <= 7; pcr_index++) {
> >> -               ret = tcg2_measure_event(dev, pcr_index, EV_SEPARATOR,
> >> -                                        sizeof(event), (u8 *)&event);
> >> +               ret = measure_event(dev, pcr_index, EV_SEPARATOR,
> >> +                                   sizeof(event), (u8 *)&event);
> >>                  if (ret != EFI_SUCCESS)
> >>                          goto out;
> >>          }
> >> @@ -2317,13 +1417,13 @@ efi_status_t efi_tcg2_measure_efi_app_exit(void)
> >>          if (!is_tcg2_protocol_installed())
> >>                  return EFI_SUCCESS;
> >>
> >> -       ret = platform_get_tpm2_device(&dev);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >>          if (ret != EFI_SUCCESS)
> >>                  return ret;
> >>
> >> -       ret = tcg2_measure_event(dev, 4, EV_EFI_ACTION,
> >> -
> strlen(EFI_RETURNING_FROM_EFI_APPLICATION),
> >> -                                (u8
> *)EFI_RETURNING_FROM_EFI_APPLICATION);
> >> +       ret = measure_event(dev, 4, EV_EFI_ACTION,
> >> +                           strlen(EFI_RETURNING_FROM_EFI_APPLICATION),
> >> +                           (u8 *)EFI_RETURNING_FROM_EFI_APPLICATION);
> >>          return ret;
> >>   }
> >>
> >> @@ -2348,19 +1448,19 @@ efi_tcg2_notify_exit_boot_services(struct
> efi_event *event, void *context)
> >>                  goto out;
> >>          }
> >>
> >> -       ret = platform_get_tpm2_device(&dev);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >>          if (ret != EFI_SUCCESS)
> >>                  goto out;
> >>
> >> -       ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
> >> -
> strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
> >> -                                (u8
> *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
> >> +       ret = measure_event(dev, 5, EV_EFI_ACTION,
> >> +                           strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
> >> +                           (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
> >>          if (ret != EFI_SUCCESS)
> >>                  goto out;
> >>
> >> -       ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
> >> -
> strlen(EFI_EXIT_BOOT_SERVICES_SUCCEEDED),
> >> -                                (u8
> *)EFI_EXIT_BOOT_SERVICES_SUCCEEDED);
> >> +       ret = measure_event(dev, 5, EV_EFI_ACTION,
> >> +                           strlen(EFI_EXIT_BOOT_SERVICES_SUCCEEDED),
> >> +                           (u8 *)EFI_EXIT_BOOT_SERVICES_SUCCEEDED);
> >>
> >>   out:
> >>          EFI_EXIT(ret);
> >> @@ -2380,19 +1480,19 @@ efi_status_t
> efi_tcg2_notify_exit_boot_services_failed(void)
> >>          if (!is_tcg2_protocol_installed())
> >>                  return EFI_SUCCESS;
> >>
> >> -       ret = platform_get_tpm2_device(&dev);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >>          if (ret != EFI_SUCCESS)
> >>                  goto out;
> >>
> >> -       ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
> >> -
> strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
> >> -                                (u8
> *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
> >> +       ret = measure_event(dev, 5, EV_EFI_ACTION,
> >> +                           strlen(EFI_EXIT_BOOT_SERVICES_INVOCATION),
> >> +                           (u8 *)EFI_EXIT_BOOT_SERVICES_INVOCATION);
> >>          if (ret != EFI_SUCCESS)
> >>                  goto out;
> >>
> >> -       ret = tcg2_measure_event(dev, 5, EV_EFI_ACTION,
> >> -                                strlen(EFI_EXIT_BOOT_SERVICES_FAILED),
> >> -                                (u8 *)EFI_EXIT_BOOT_SERVICES_FAILED);
> >> +       ret = measure_event(dev, 5, EV_EFI_ACTION,
> >> +                           strlen(EFI_EXIT_BOOT_SERVICES_FAILED),
> >> +                           (u8 *)EFI_EXIT_BOOT_SERVICES_FAILED);
> >>
> >>   out:
> >>          return ret;
> >> @@ -2462,7 +1562,7 @@ efi_status_t efi_tcg2_do_initial_measurement(void)
> >>          if (!is_tcg2_protocol_installed())
> >>                  return EFI_SUCCESS;
> >>
> >> -       ret = platform_get_tpm2_device(&dev);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >>          if (ret != EFI_SUCCESS)
> >>                  return EFI_SECURITY_VIOLATION;
> >>
> >> @@ -2488,7 +1588,7 @@ efi_status_t efi_tcg2_register(void)
> >>          struct efi_event *event;
> >>          u32 err;
> >>
> >> -       ret = platform_get_tpm2_device(&dev);
> >> +       ret = tcg2_platform_get_tpm2(&dev);
> >>          if (ret != EFI_SUCCESS) {
> >>                  log_warning("Missing TPMv2 device for
> EFI_TCG_PROTOCOL\n");
> >>                  return EFI_SUCCESS;
> >> diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> >> index 9ab5b46df1..d22e21985b 100644
> >> --- a/lib/tpm-v2.c
> >> +++ b/lib/tpm-v2.c
> >> @@ -1,16 +1,705 @@
> >>   // SPDX-License-Identifier: GPL-2.0+
> >>   /*
> >> + * Copyright (c) 2023 Linaro Limited
> >>    * Copyright (c) 2018 Bootlin
> >>    * Author: Miquel Raynal <miquel.raynal@bootlin.com>
> >>    */
> >>
> >>   #include <common.h>
> >>   #include <dm.h>
> >> +#include <dm/of_access.h>
> >> +#include <tpm_api.h>
> >>   #include <tpm-common.h>
> >>   #include <tpm-v2.h>
> >> +#include <u-boot/sha1.h>
> >> +#include <u-boot/sha256.h>
> >> +#include <u-boot/sha512.h>
> >> +#include <version_string.h>
> >> +#include <asm/io.h>
> >>   #include <linux/bitops.h>
> >> +#include <linux/unaligned/be_byteshift.h>
> >> +#include <linux/unaligned/generic.h>
> >> +#include <linux/unaligned/le_byteshift.h>
> >> +
> >>   #include "tpm-utils.h"
> >>
> >> +const enum tpm2_algorithms tpm2_supported_algorithms[4] = {
> >> +       TPM2_ALG_SHA1,
> >> +       TPM2_ALG_SHA256,
> >> +       TPM2_ALG_SHA384,
> >> +       TPM2_ALG_SHA512,
> >> +};
> >> +
> >> +int tcg2_get_active_pcr_banks(struct udevice *dev, u32
> *active_pcr_banks)
> >> +{
> >> +       u32 supported = 0;
> >> +       u32 pcr_banks = 0;
> >> +       u32 active = 0;
> >> +       int rc;
> >> +
> >> +       rc = tpm2_get_pcr_info(dev, &supported, &active, &pcr_banks);
> >> +       if (rc)
> >> +               return rc;
> >> +
> >> +       *active_pcr_banks = active;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +u32 tcg2_event_get_size(struct tpml_digest_values *digest_list)
> >> +{
> >> +       u32 len;
> >> +       size_t i;
> >> +
> >> +       len = offsetof(struct tcg_pcr_event2, digests);
> >> +       len += offsetof(struct tpml_digest_values, digests);
> >> +       for (i = 0; i < digest_list->count; ++i) {
> >> +               u16 l =
> tpm2_algorithm_to_len(digest_list->digests[i].hash_alg);
> >> +
> >> +               if (!l)
> >> +                       continue;
> >> +
> >> +               len += l + offsetof(struct tpmt_ha, digest);
> >> +       }
> >> +       len += sizeof(u32);
> >> +
> >> +       return len;
> >> +}
> >> +
> >> +int tcg2_create_digest(struct udevice *dev, const u8 *input, u32
> length,
> >> +                      struct tpml_digest_values *digest_list)
> >> +{
> >> +       u8 final[sizeof(union tpmu_ha)];
> >> +       sha256_context ctx_256;
> >> +       sha512_context ctx_512;
> >> +       sha1_context ctx;
> >> +       u32 active;
> >> +       size_t i;
> >> +       u32 len;
> >> +       int rc;
> >> +
> >> +       rc = tcg2_get_active_pcr_banks(dev, &active);
> >> +       if (rc)
> >> +               return rc;
> >> +
> >> +       digest_list->count = 0;
> >> +       for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
> >> +               u32 mask =
> >> +
>  tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
> >> +
> >> +               if (!(active & mask))
> >> +                       continue;
> >> +
> >> +               switch (tpm2_supported_algorithms[i]) {
> >> +               case TPM2_ALG_SHA1:
> >> +                       sha1_starts(&ctx);
> >> +                       sha1_update(&ctx, input, length);
> >> +                       sha1_finish(&ctx, final);
> >> +                       len = TPM2_SHA1_DIGEST_SIZE;
> >> +                       break;
> >> +               case TPM2_ALG_SHA256:
> >> +                       sha256_starts(&ctx_256);
> >> +                       sha256_update(&ctx_256, input, length);
> >> +                       sha256_finish(&ctx_256, final);
> >> +                       len = TPM2_SHA256_DIGEST_SIZE;
> >> +                       break;
> >> +               case TPM2_ALG_SHA384:
> >> +                       sha384_starts(&ctx_512);
> >> +                       sha384_update(&ctx_512, input, length);
> >> +                       sha384_finish(&ctx_512, final);
> >> +                       len = TPM2_SHA384_DIGEST_SIZE;
> >> +                       break;
> >> +               case TPM2_ALG_SHA512:
> >> +                       sha512_starts(&ctx_512);
> >> +                       sha512_update(&ctx_512, input, length);
> >> +                       sha512_finish(&ctx_512, final);
> >> +                       len = TPM2_SHA512_DIGEST_SIZE;
> >> +                       break;
> >> +               default:
> >> +                       printf("%s: unsupported algorithm %x\n",
> __func__,
> >> +                              tpm2_supported_algorithms[i]);
> >> +                       continue;
> >> +               }
> >> +
> >> +               digest_list->digests[digest_list->count].hash_alg =
> >> +                       tpm2_supported_algorithms[i];
> >> +
>  memcpy(&digest_list->digests[digest_list->count].digest, final,
> >> +                      len);
> >> +               digest_list->count++;
> >> +       }
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +void tcg2_log_append(u32 pcr_index, u32 event_type,
> >> +                    struct tpml_digest_values *digest_list, u32 size,
> >> +                    const u8 *event, u8 *log)
> >> +{
> >> +       size_t len;
> >> +       size_t pos;
> >> +       u32 i;
> >> +
> >> +       pos = offsetof(struct tcg_pcr_event2, pcr_index);
> >> +       put_unaligned_le32(pcr_index, log);
> >> +       pos = offsetof(struct tcg_pcr_event2, event_type);
> >> +       put_unaligned_le32(event_type, log + pos);
> >> +       pos = offsetof(struct tcg_pcr_event2, digests) +
> >> +               offsetof(struct tpml_digest_values, count);
> >> +       put_unaligned_le32(digest_list->count, log + pos);
> >> +
> >> +       pos = offsetof(struct tcg_pcr_event2, digests) +
> >> +               offsetof(struct tpml_digest_values, digests);
> >> +       for (i = 0; i < digest_list->count; ++i) {
> >> +               u16 hash_alg = digest_list->digests[i].hash_alg;
> >> +
> >> +               len = tpm2_algorithm_to_len(hash_alg);
> >> +               if (!len)
> >> +                       continue;
> >> +
> >> +               pos += offsetof(struct tpmt_ha, hash_alg);
> >> +               put_unaligned_le16(hash_alg, log + pos);
> >> +               pos += offsetof(struct tpmt_ha, digest);
> >> +               memcpy(log + pos, (u8
> *)&digest_list->digests[i].digest, len);
> >> +               pos += len;
> >> +       }
> >> +
> >> +       put_unaligned_le32(size, log + pos);
> >> +       pos += sizeof(u32);
> >> +       memcpy(log + pos, event, size);
> >> +}
> >> +
> >> +static int tcg2_log_append_check(struct tcg2_event_log *elog, u32
> pcr_index,
> >> +                                u32 event_type,
> >> +                                struct tpml_digest_values *digest_list,
> >> +                                u32 size, const u8 *event)
> >> +{
> >> +       u32 event_size;
> >> +       u8 *log;
> >> +
> >> +       event_size = size + tcg2_event_get_size(digest_list);
> >> +       if (elog->log_position + event_size > elog->log_size) {
> >> +               printf("%s: log too large: %u + %u > %u\n", __func__,
> >> +                      elog->log_position, event_size, elog->log_size);
> >> +               return -ENOBUFS;
> >> +       }
> >> +
> >> +       log = elog->log + elog->log_position;
> >> +       elog->log_position += event_size;
> >> +
> >> +       tcg2_log_append(pcr_index, event_type, digest_list, size,
> event, log);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log
> *elog)
> >> +{
> >> +       struct tcg_efi_spec_id_event *ev;
> >> +       struct tcg_pcr_event *log;
> >> +       u32 event_size;
> >> +       u32 count = 0;
> >> +       u32 log_size;
> >> +       u32 active;
> >> +       u32 mask;
> >> +       size_t i;
> >> +       u16 len;
> >> +       int rc;
> >> +
> >> +       rc = tcg2_get_active_pcr_banks(dev, &active);
> >> +       if (rc)
> >> +               return rc;
> >> +
> >> +       event_size = offsetof(struct tcg_efi_spec_id_event,
> digest_sizes);
> >> +       for (i = 0; i < ARRAY_SIZE(tpm2_supported_algorithms); ++i) {
> >> +               mask =
> tpm2_algorithm_to_mask(tpm2_supported_algorithms[i]);
> >> +
> >> +               if (!(active & mask))
> >> +                       continue;
> >> +
> >> +               switch (tpm2_supported_algorithms[i]) {
> >> +               case TPM2_ALG_SHA1:
> >> +               case TPM2_ALG_SHA256:
> >> +               case TPM2_ALG_SHA384:
> >> +               case TPM2_ALG_SHA512:
> >> +                       count++;
> >> +                       break;
> >> +               default:
> >> +                       continue;
> >> +               }
> >> +       }
> >> +
> >> +       event_size += 1 +
> >> +               (sizeof(struct tcg_efi_spec_id_event_algorithm_size) *
> count);
> >> +       log_size = offsetof(struct tcg_pcr_event, event) + event_size;
> >> +
> >> +       if (log_size > elog->log_size) {
> >> +               printf("%s: log too large: %u > %u\n", __func__,
> log_size,
> >> +                      elog->log_size);
> >> +               return -ENOBUFS;
> >>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v9 2/6] tpm: sandbox: Update for needed TPM2 capabilities
  2023-03-16  8:32   ` Ilias Apalodimas
@ 2023-05-09 13:49     ` Ilias Apalodimas
  0 siblings, 0 replies; 16+ messages in thread
From: Ilias Apalodimas @ 2023-05-09 13:49 UTC (permalink / raw)
  To: Eddie James; +Cc: u-boot, sjg, xypron.glpk, joel

Hi Eddie

On Thu, 16 Mar 2023 at 10:32, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Eddie,
>
> Apologies for the late reply, I am now getting back on this.
> There are some failures on the CI wrt to sandbox here [0].  Can you have a
> look ?
> Also I believe some of the existing tests are wrong because they are
> using PCR0 (which is always going to be extended).  Can you also pick up
> [1] with your series?
>
>
> [0] https://source.denx.de/u-boot/custodians/u-boot-tpm/-/pipelines/15471
> [1] https://source.denx.de/u-boot/custodians/u-boot-tpm/-/commit/0d28387cac5fafa59e4367d1548e021eeebe2004

I did manage to figure this out. You need this [0] with your patches.
Keep in mind that
("efi_loader: fix EFI_ENTRY point on get_active_pcr_banks ") needs to
be squashed with your patches as it's causing U-Boot to crash on
selftests.

You don't really need ("tpm: clean up tpm_init usage ") this is a WIP
i am exploring.  I'll go ahead and send the remaining patches and cc
you.  Once/if those are accepted, you can resend your series with the
fix I mentioned

[0] https://source.denx.de/u-boot/custodians/u-boot-tpm/-/commits/eddie
Regards
/Ilias
>
> Thanks
> /Ilias
>
> On Wed, Mar 08, 2023 at 03:25:33PM -0600, Eddie James wrote:
> > The driver needs to support getting the PCRs in the capabilities
> > command. Fix various other things and support the max number
> > of PCRs for TPM2.
> > Remove the !SANDBOX dependency for EFI TCG2 as well.
> >
> > Signed-off-by: Eddie James <eajames@linux.ibm.com>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> > Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > ---
> > Changes since v8:
> >  - Use >= for checking the property against TPM2_PROPERTIES_OFFSET
> >
> > Changes since v5:
> >  - Remove the !SANDBOX dependency for EFI TCG2
> >
> >  drivers/tpm/tpm2_tis_sandbox.c | 100 ++++++++++++++++++++++++---------
> >  lib/efi_loader/Kconfig         |   2 -
> >  2 files changed, 72 insertions(+), 30 deletions(-)
> >
> > diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c
> > index e4004cfcca..d15a28d9fc 100644
> > --- a/drivers/tpm/tpm2_tis_sandbox.c
> > +++ b/drivers/tpm/tpm2_tis_sandbox.c
> > @@ -22,11 +22,6 @@ enum tpm2_hierarchy {
> >       TPM2_HIERARCHY_NB,
> >  };
> >
> > -/* Subset of supported capabilities */
> > -enum tpm2_capability {
> > -     TPM_CAP_TPM_PROPERTIES = 0x6,
> > -};
> > -
> >  /* Subset of supported properties */
> >  #define TPM2_PROPERTIES_OFFSET 0x0000020E
> >
> > @@ -38,7 +33,8 @@ enum tpm2_cap_tpm_property {
> >       TPM2_PROPERTY_NB,
> >  };
> >
> > -#define SANDBOX_TPM_PCR_NB 1
> > +#define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS
> > +#define SANDBOX_TPM_PCR_SELECT_MAX   ((SANDBOX_TPM_PCR_NB + 7) / 8)
> >
> >  /*
> >   * Information about our TPM emulation. This is preserved in the sandbox
> > @@ -433,7 +429,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
> >       int i, j;
> >
> >       /* TPM2_GetProperty */
> > -     u32 capability, property, property_count;
> > +     u32 capability, property, property_count, val;
> >
> >       /* TPM2_PCR_Read/Extend variables */
> >       int pcr_index = 0;
> > @@ -542,19 +538,32 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
> >       case TPM2_CC_GET_CAPABILITY:
> >               capability = get_unaligned_be32(sent);
> >               sent += sizeof(capability);
> > -             if (capability != TPM_CAP_TPM_PROPERTIES) {
> > -                     printf("Sandbox TPM only support TPM_CAPABILITIES\n");
> > -                     return TPM2_RC_HANDLE;
> > -             }
> > -
> >               property = get_unaligned_be32(sent);
> >               sent += sizeof(property);
> > -             property -= TPM2_PROPERTIES_OFFSET;
> > -
> >               property_count = get_unaligned_be32(sent);
> >               sent += sizeof(property_count);
> > -             if (!property_count ||
> > -                 property + property_count > TPM2_PROPERTY_NB) {
> > +
> > +             switch (capability) {
> > +             case TPM2_CAP_PCRS:
> > +                     break;
> > +             case TPM2_CAP_TPM_PROPERTIES:
> > +                     if (!property_count) {
> > +                             rc = TPM2_RC_HANDLE;
> > +                             return sandbox_tpm2_fill_buf(recv, recv_len,
> > +                                                          tag, rc);
> > +                     }
> > +
> > +                     if (property >= TPM2_PROPERTIES_OFFSET &&
> > +                         ((property - TPM2_PROPERTIES_OFFSET) +
> > +                          property_count > TPM2_PROPERTY_NB)) {
> > +                             rc = TPM2_RC_HANDLE;
> > +                             return sandbox_tpm2_fill_buf(recv, recv_len,
> > +                                                          tag, rc);
> > +                     }
> > +                     break;
> > +             default:
> > +                     printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or "
> > +                            "TPM2_CAP_TPM_PROPERTIES\n");
> >                       rc = TPM2_RC_HANDLE;
> >                       return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
> >               }
> > @@ -578,18 +587,53 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
> >               put_unaligned_be32(capability, recv);
> >               recv += sizeof(capability);
> >
> > -             /* Give the number of properties that follow */
> > -             put_unaligned_be32(property_count, recv);
> > -             recv += sizeof(property_count);
> > -
> > -             /* Fill with the properties */
> > -             for (i = 0; i < property_count; i++) {
> > -                     put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
> > -                                        i, recv);
> > -                     recv += sizeof(property);
> > -                     put_unaligned_be32(tpm->properties[property + i],
> > -                                        recv);
> > -                     recv += sizeof(property);
> > +             switch (capability) {
> > +             case TPM2_CAP_PCRS:
> > +                     /* Give the number of algorithms supported - just SHA256 */
> > +                     put_unaligned_be32(1, recv);
> > +                     recv += sizeof(u32);
> > +
> > +                     /* Give SHA256 algorithm */
> > +                     put_unaligned_be16(TPM2_ALG_SHA256, recv);
> > +                     recv += sizeof(u16);
> > +
> > +                     /* Select the PCRs supported */
> > +                     *recv = SANDBOX_TPM_PCR_SELECT_MAX;
> > +                     recv++;
> > +
> > +                     /* Activate all the PCR bits */
> > +                     for (i = 0; i < SANDBOX_TPM_PCR_SELECT_MAX; ++i) {
> > +                             *recv = 0xff;
> > +                             recv++;
> > +                     }
> > +                     break;
> > +             case TPM2_CAP_TPM_PROPERTIES:
> > +                     /* Give the number of properties that follow */
> > +                     put_unaligned_be32(property_count, recv);
> > +                     recv += sizeof(property_count);
> > +
> > +                     /* Fill with the properties */
> > +                     for (i = 0; i < property_count; i++) {
> > +                             put_unaligned_be32(property + i, recv);
> > +                             recv += sizeof(property);
> > +                             if (property >= TPM2_PROPERTIES_OFFSET) {
> > +                                     val = tpm->properties[(property -
> > +                                             TPM2_PROPERTIES_OFFSET) + i];
> > +                             } else {
> > +                                     switch (property) {
> > +                                     case TPM2_PT_PCR_COUNT:
> > +                                             val = SANDBOX_TPM_PCR_NB;
> > +                                             break;
> > +                                     default:
> > +                                             val = 0xffffffff;
> > +                                             break;
> > +                                     }
> > +                             }
> > +
> > +                             put_unaligned_be32(val, recv);
> > +                             recv += sizeof(property);
> > +                     }
> > +                     break;
> >               }
> >
> >               /* Add trailing \0 */
> > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > index c5835e6ef6..605719d2b6 100644
> > --- a/lib/efi_loader/Kconfig
> > +++ b/lib/efi_loader/Kconfig
> > @@ -333,8 +333,6 @@ config EFI_TCG2_PROTOCOL
> >       bool "EFI_TCG2_PROTOCOL support"
> >       default y
> >       depends on TPM_V2
> > -     # Sandbox TPM currently fails on GetCapabilities needed for TCG2
> > -     depends on !SANDBOX
> >       select SHA1
> >       select SHA256
> >       select SHA384
> > --
> > 2.31.1
> >
>
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v9 4/6] bootm: Support boot measurement
  2023-03-08 21:25 ` [PATCH v9 4/6] bootm: Support boot measurement Eddie James
@ 2023-08-04 18:10   ` Sean Edmond
  2023-08-07 14:43     ` Eddie James
  0 siblings, 1 reply; 16+ messages in thread
From: Sean Edmond @ 2023-08-04 18:10 UTC (permalink / raw)
  To: Eddie James, u-boot; +Cc: sjg, ilias.apalodimas, xypron.glpk, joel

On 2023-03-08 1:25 p.m., Eddie James wrote:
> Add a configuration option to measure the boot through the bootm
> function. Add the measurement state to the booti and bootz paths
> as well.
>
> Signed-off-by: Eddie James <eajames@linux.ibm.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
> Changes since v8:
>   - Added a configuration option to select to ignore any existing
>     event log. This would only be selected for systems that know
>     that U-Boot is the first stage bootloader. This is necessary
>     because the reserved memory region may persist through resets
>     and so U-Boot attempts to append to the previous boot's log.
>
> Changes since v6:
>   - Added comment for bootm_measure
>   - Fixed line length in bootm_measure
>
>   boot/Kconfig    | 32 +++++++++++++++++++++
>   boot/bootm.c    | 74 +++++++++++++++++++++++++++++++++++++++++++++++++
>   cmd/booti.c     |  1 +
>   cmd/bootm.c     |  2 ++
>   cmd/bootz.c     |  1 +
>   include/bootm.h | 11 ++++++++
>   include/image.h |  1 +
>   7 files changed, 122 insertions(+)
>
> diff --git a/boot/Kconfig b/boot/Kconfig
> index 5f491625c8..8119519c9f 100644
> --- a/boot/Kconfig
> +++ b/boot/Kconfig
> @@ -629,6 +629,38 @@ config LEGACY_IMAGE_FORMAT
>   	  loaded. If a board needs the legacy image format support in this
>   	  case, enable it here.
>   
> +config MEASURED_BOOT
> +	bool "Measure boot images and configuration to TPM and event log"
> +	depends on HASH && TPM_V2
> +	help
> +	  This option enables measurement of the boot process. Measurement
> +	  involves creating cryptographic hashes of the binary images that
> +	  are booting and storing them in the TPM. In addition, a log of
> +	  these hashes is stored in memory for the OS to verify the booted
> +	  images and configuration. Enable this if the OS has configured
> +	  some memory area for the event log and you intend to use some
> +	  attestation tools on your system.
> +
> +if MEASURED_BOOT
> +	config MEASURE_DEVICETREE
> +	bool "Measure the devicetree image"
> +	default y if MEASURED_BOOT
> +	help
> +	  On some platforms, the devicetree is not static as it may contain
> +	  random MAC addresses or other such data that changes each boot.
> +	  Therefore, it should not be measured into the TPM. In that case,
> +	  disable the measurement here.
> +
> +	config MEASURE_IGNORE_LOG
> +	bool "Ignore the existing event log"
> +	default n
> +	help
> +	  On platforms that use an event log memory region that persists
> +	  through system resets and are the first stage bootloader, then
> +	  this option should be enabled to ignore any existing data in the
> +	  event log memory region.
> +endif # MEASURED_BOOT
> +
>   config SUPPORT_RAW_INITRD
>   	bool "Enable raw initrd images"
>   	help
> diff --git a/boot/bootm.c b/boot/bootm.c
> index 2eec60ec7b..2685bdbd74 100644
> --- a/boot/bootm.c
> +++ b/boot/bootm.c
> @@ -22,6 +22,7 @@
>   #include <asm/global_data.h>
>   #include <asm/io.h>
>   #include <linux/sizes.h>
> +#include <tpm-v2.h>
>   #if defined(CONFIG_CMD_USB)
>   #include <usb.h>
>   #endif
> @@ -659,6 +660,75 @@ int bootm_process_cmdline_env(int flags)
>   	return 0;
>   }
>   
> +int bootm_measure(struct bootm_headers *images)
> +{
> +	int ret = 0;
> +
> +	/* Skip measurement if EFI is going to do it */
> +	if (images->os.os == IH_OS_EFI &&
> +	    IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) &&
> +	    IS_ENABLED(CONFIG_BOOTM_EFI))
> +		return ret;
> +

it looks like your measured boot implementation is hardcoding the 
following PCR indexes:

PCR #8 - kernel image measurement
PCR #9 - initrd measurement
PCR #0 - kernel DTB measurement
PCR #1 - bootargs measurement

I wasn't able to find any specificaton on this measured boot "profile".  
Are you able to provide a reference?

We've implemented our own version of measured boot, which maps 
measurements to different PCR indexes.  In many cases, the data we're 
measuring is also different.

To make this feature more usable by others it would be nice to see a 
more generic interface that would allow the user to specify the PCR 
indexes, and the data to hash into these indexes.  This would allow 
everyone to create their own custom measured boot "profile".  This 
request is probably beyond the scope of your current efforts, but I 
except this implementation to evolve significantly if/when it's accepted.

> +	if (IS_ENABLED(CONFIG_MEASURED_BOOT)) {
> +		struct tcg2_event_log elog;
> +		struct udevice *dev;
> +		void *initrd_buf;
> +		void *image_buf;
> +		const char *s;
> +		u32 rd_len;
> +		bool ign;
> +
> +		elog.log_size = 0;
> +		ign = IS_ENABLED(CONFIG_MEASURE_IGNORE_LOG);
> +		ret = tcg2_measurement_init(&dev, &elog, ign);
> +		if (ret)
> +			return ret;
> +
> +		image_buf = map_sysmem(images->os.image_start,
> +				       images->os.image_len);
> +		ret = tcg2_measure_data(dev, &elog, 8, images->os.image_len,
> +					image_buf, EV_COMPACT_HASH,
> +					strlen("linux") + 1, (u8 *)"linux");
> +		if (ret)
> +			goto unmap_image;
> +
> +		rd_len = images->rd_end - images->rd_start;
> +		initrd_buf = map_sysmem(images->rd_start, rd_len);
> +		ret = tcg2_measure_data(dev, &elog, 9, rd_len, initrd_buf,
> +					EV_COMPACT_HASH, strlen("initrd") + 1,
> +					(u8 *)"initrd");
> +		if (ret)
> +			goto unmap_initrd;
> +
> +		if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) {
> +			ret = tcg2_measure_data(dev, &elog, 0, images->ft_len,
> +						(u8 *)images->ft_addr,
> +						EV_TABLE_OF_DEVICES,
> +						strlen("dts") + 1,
> +						(u8 *)"dts");
> +			if (ret)
> +				goto unmap_initrd;
> +		}
> +
> +		s = env_get("bootargs");
> +		if (!s)
> +			s = "";
> +		ret = tcg2_measure_data(dev, &elog, 1, strlen(s) + 1, (u8 *)s,
> +					EV_PLATFORM_CONFIG_FLAGS,
> +					strlen(s) + 1, (u8 *)s);
> +
> +unmap_initrd:
> +		unmap_sysmem(initrd_buf);
> +
> +unmap_image:
> +		unmap_sysmem(image_buf);
> +		tcg2_measurement_term(dev, &elog, ret != 0);
> +	}
> +
> +	return ret;
> +}
> +
>   /**
>    * Execute selected states of the bootm command.
>    *
> @@ -710,6 +780,10 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
>   	if (!ret && (states & BOOTM_STATE_FINDOTHER))
>   		ret = bootm_find_other(cmdtp, flag, argc, argv);
>   
> +	if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !ret &&
> +	    (states & BOOTM_STATE_MEASURE))
> +		bootm_measure(images);
> +
>   	/* Load the OS */
>   	if (!ret && (states & BOOTM_STATE_LOADOS)) {
>   		iflag = bootm_disable_interrupts();
> diff --git a/cmd/booti.c b/cmd/booti.c
> index 6ac39193db..659bb10549 100644
> --- a/cmd/booti.c
> +++ b/cmd/booti.c
> @@ -127,6 +127,7 @@ int do_booti(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>   #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
>   			      BOOTM_STATE_RAMDISK |
>   #endif
> +			      BOOTM_STATE_MEASURE |
>   			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
>   			      BOOTM_STATE_OS_GO,
>   			      &images, 1);
> diff --git a/cmd/bootm.c b/cmd/bootm.c
> index 37c2af96e0..0c4a713e02 100644
> --- a/cmd/bootm.c
> +++ b/cmd/bootm.c
> @@ -161,6 +161,8 @@ int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>   		BOOTM_STATE_OS_GO;
>   	if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
>   		states |= BOOTM_STATE_RAMDISK;
> +	if (IS_ENABLED(CONFIG_MEASURED_BOOT))
> +		states |= BOOTM_STATE_MEASURE;
>   	if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS))
>   		states |= BOOTM_STATE_OS_CMDLINE;
>   	ret = do_bootm_states(cmdtp, flag, argc, argv, states, &images, 1);
> diff --git a/cmd/bootz.c b/cmd/bootz.c
> index f1423573d2..87922bfc3c 100644
> --- a/cmd/bootz.c
> +++ b/cmd/bootz.c
> @@ -81,6 +81,7 @@ int do_bootz(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
>   #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
>   			      BOOTM_STATE_RAMDISK |
>   #endif
> +			      BOOTM_STATE_MEASURE |
>   			      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
>   			      BOOTM_STATE_OS_GO,
>   			      &images, 1);
> diff --git a/include/bootm.h b/include/bootm.h
> index 044a4797ed..76e8e38c82 100644
> --- a/include/bootm.h
> +++ b/include/bootm.h
> @@ -55,6 +55,17 @@ ulong bootm_disable_interrupts(void);
>   int bootm_find_images(int flag, int argc, char *const argv[], ulong start,
>   		      ulong size);
>   
> +/*
> + * Measure the boot images. Measurement is the process of hashing some binary
> + * data and storing it into secure memory, i.e. TPM PCRs. In addition, each
> + * measurement is logged into the platform event log such that the operating
> + * system can access it and perform attestation of the boot.
> + *
> + * @images:	The structure containing the various images to boot (linux,
> + *		initrd, dts, etc.)
> + */
> +int bootm_measure(struct bootm_headers *images);
> +
>   int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
>   		    char *const argv[], int states, struct bootm_headers *images,
>   		    int boot_progress);
> diff --git a/include/image.h b/include/image.h
> index 7717a4c13d..f7414b5338 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -407,6 +407,7 @@ struct bootm_headers {
>   #define BOOTM_STATE_OS_FAKE_GO	0x00000200	/* 'Almost' run the OS */
>   #define BOOTM_STATE_OS_GO	0x00000400
>   #define BOOTM_STATE_PRE_LOAD	0x00000800
> +#define BOOTM_STATE_MEASURE	0x00001000
>   	int		state;
>   
>   #if defined(CONFIG_LMB) && !defined(USE_HOSTCC)



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v9 4/6] bootm: Support boot measurement
  2023-08-04 18:10   ` Sean Edmond
@ 2023-08-07 14:43     ` Eddie James
  2023-08-07 14:52       ` Ilias Apalodimas
  0 siblings, 1 reply; 16+ messages in thread
From: Eddie James @ 2023-08-07 14:43 UTC (permalink / raw)
  To: Sean Edmond, u-boot; +Cc: sjg, ilias.apalodimas, xypron.glpk, joel


On 8/4/23 13:10, Sean Edmond wrote:
> On 2023-03-08 1:25 p.m., Eddie James wrote:
>> Add a configuration option to measure the boot through the bootm
>> function. Add the measurement state to the booti and bootz paths
>> as well.
>>
>> Signed-off-by: Eddie James <eajames@linux.ibm.com>
>> Reviewed-by: Simon Glass <sjg@chromium.org>
>> ---
>> Changes since v8:
>>   - Added a configuration option to select to ignore any existing
>>     event log. This would only be selected for systems that know
>>     that U-Boot is the first stage bootloader. This is necessary
>>     because the reserved memory region may persist through resets
>>     and so U-Boot attempts to append to the previous boot's log.
>>
>> Changes since v6:
>>   - Added comment for bootm_measure
>>   - Fixed line length in bootm_measure
>>
>>   boot/Kconfig    | 32 +++++++++++++++++++++
>>   boot/bootm.c    | 74 +++++++++++++++++++++++++++++++++++++++++++++++++
>>   cmd/booti.c     |  1 +
>>   cmd/bootm.c     |  2 ++
>>   cmd/bootz.c     |  1 +
>>   include/bootm.h | 11 ++++++++
>>   include/image.h |  1 +
>>   7 files changed, 122 insertions(+)
>>
>> diff --git a/boot/Kconfig b/boot/Kconfig
>> index 5f491625c8..8119519c9f 100644
>> --- a/boot/Kconfig
>> +++ b/boot/Kconfig
>> @@ -629,6 +629,38 @@ config LEGACY_IMAGE_FORMAT
>>         loaded. If a board needs the legacy image format support in this
>>         case, enable it here.
>>   +config MEASURED_BOOT
>> +    bool "Measure boot images and configuration to TPM and event log"
>> +    depends on HASH && TPM_V2
>> +    help
>> +      This option enables measurement of the boot process. Measurement
>> +      involves creating cryptographic hashes of the binary images that
>> +      are booting and storing them in the TPM. In addition, a log of
>> +      these hashes is stored in memory for the OS to verify the booted
>> +      images and configuration. Enable this if the OS has configured
>> +      some memory area for the event log and you intend to use some
>> +      attestation tools on your system.
>> +
>> +if MEASURED_BOOT
>> +    config MEASURE_DEVICETREE
>> +    bool "Measure the devicetree image"
>> +    default y if MEASURED_BOOT
>> +    help
>> +      On some platforms, the devicetree is not static as it may contain
>> +      random MAC addresses or other such data that changes each boot.
>> +      Therefore, it should not be measured into the TPM. In that case,
>> +      disable the measurement here.
>> +
>> +    config MEASURE_IGNORE_LOG
>> +    bool "Ignore the existing event log"
>> +    default n
>> +    help
>> +      On platforms that use an event log memory region that persists
>> +      through system resets and are the first stage bootloader, then
>> +      this option should be enabled to ignore any existing data in the
>> +      event log memory region.
>> +endif # MEASURED_BOOT
>> +
>>   config SUPPORT_RAW_INITRD
>>       bool "Enable raw initrd images"
>>       help
>> diff --git a/boot/bootm.c b/boot/bootm.c
>> index 2eec60ec7b..2685bdbd74 100644
>> --- a/boot/bootm.c
>> +++ b/boot/bootm.c
>> @@ -22,6 +22,7 @@
>>   #include <asm/global_data.h>
>>   #include <asm/io.h>
>>   #include <linux/sizes.h>
>> +#include <tpm-v2.h>
>>   #if defined(CONFIG_CMD_USB)
>>   #include <usb.h>
>>   #endif
>> @@ -659,6 +660,75 @@ int bootm_process_cmdline_env(int flags)
>>       return 0;
>>   }
>>   +int bootm_measure(struct bootm_headers *images)
>> +{
>> +    int ret = 0;
>> +
>> +    /* Skip measurement if EFI is going to do it */
>> +    if (images->os.os == IH_OS_EFI &&
>> +        IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) &&
>> +        IS_ENABLED(CONFIG_BOOTM_EFI))
>> +        return ret;
>> +
>
> it looks like your measured boot implementation is hardcoding the 
> following PCR indexes:
>
> PCR #8 - kernel image measurement
> PCR #9 - initrd measurement
> PCR #0 - kernel DTB measurement
> PCR #1 - bootargs measurement


Hi,


Yes, I followed this document as closely as I could: 
https://trustedcomputinggroup.org/wp-content/uploads/TCG_ServerManagementDomainFirmwareProfile_v1p00_11aug2020.pdf

Which provides what should go in what PCR. I can understand users 
wanting a different setup, but as you say, that's probably out of the 
scope of this series.


Thanks,

Eddie


>
> I wasn't able to find any specificaton on this measured boot 
> "profile".  Are you able to provide a reference?
>
> We've implemented our own version of measured boot, which maps 
> measurements to different PCR indexes.  In many cases, the data we're 
> measuring is also different.
>
> To make this feature more usable by others it would be nice to see a 
> more generic interface that would allow the user to specify the PCR 
> indexes, and the data to hash into these indexes.  This would allow 
> everyone to create their own custom measured boot "profile".  This 
> request is probably beyond the scope of your current efforts, but I 
> except this implementation to evolve significantly if/when it's accepted.
>
>> +    if (IS_ENABLED(CONFIG_MEASURED_BOOT)) {
>> +        struct tcg2_event_log elog;
>> +        struct udevice *dev;
>> +        void *initrd_buf;
>> +        void *image_buf;
>> +        const char *s;
>> +        u32 rd_len;
>> +        bool ign;
>> +
>> +        elog.log_size = 0;
>> +        ign = IS_ENABLED(CONFIG_MEASURE_IGNORE_LOG);
>> +        ret = tcg2_measurement_init(&dev, &elog, ign);
>> +        if (ret)
>> +            return ret;
>> +
>> +        image_buf = map_sysmem(images->os.image_start,
>> +                       images->os.image_len);
>> +        ret = tcg2_measure_data(dev, &elog, 8, images->os.image_len,
>> +                    image_buf, EV_COMPACT_HASH,
>> +                    strlen("linux") + 1, (u8 *)"linux");
>> +        if (ret)
>> +            goto unmap_image;
>> +
>> +        rd_len = images->rd_end - images->rd_start;
>> +        initrd_buf = map_sysmem(images->rd_start, rd_len);
>> +        ret = tcg2_measure_data(dev, &elog, 9, rd_len, initrd_buf,
>> +                    EV_COMPACT_HASH, strlen("initrd") + 1,
>> +                    (u8 *)"initrd");
>> +        if (ret)
>> +            goto unmap_initrd;
>> +
>> +        if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) {
>> +            ret = tcg2_measure_data(dev, &elog, 0, images->ft_len,
>> +                        (u8 *)images->ft_addr,
>> +                        EV_TABLE_OF_DEVICES,
>> +                        strlen("dts") + 1,
>> +                        (u8 *)"dts");
>> +            if (ret)
>> +                goto unmap_initrd;
>> +        }
>> +
>> +        s = env_get("bootargs");
>> +        if (!s)
>> +            s = "";
>> +        ret = tcg2_measure_data(dev, &elog, 1, strlen(s) + 1, (u8 *)s,
>> +                    EV_PLATFORM_CONFIG_FLAGS,
>> +                    strlen(s) + 1, (u8 *)s);
>> +
>> +unmap_initrd:
>> +        unmap_sysmem(initrd_buf);
>> +
>> +unmap_image:
>> +        unmap_sysmem(image_buf);
>> +        tcg2_measurement_term(dev, &elog, ret != 0);
>> +    }
>> +
>> +    return ret;
>> +}
>> +
>>   /**
>>    * Execute selected states of the bootm command.
>>    *
>> @@ -710,6 +780,10 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int 
>> flag, int argc,
>>       if (!ret && (states & BOOTM_STATE_FINDOTHER))
>>           ret = bootm_find_other(cmdtp, flag, argc, argv);
>>   +    if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !ret &&
>> +        (states & BOOTM_STATE_MEASURE))
>> +        bootm_measure(images);
>> +
>>       /* Load the OS */
>>       if (!ret && (states & BOOTM_STATE_LOADOS)) {
>>           iflag = bootm_disable_interrupts();
>> diff --git a/cmd/booti.c b/cmd/booti.c
>> index 6ac39193db..659bb10549 100644
>> --- a/cmd/booti.c
>> +++ b/cmd/booti.c
>> @@ -127,6 +127,7 @@ int do_booti(struct cmd_tbl *cmdtp, int flag, int 
>> argc, char *const argv[])
>>   #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
>>                     BOOTM_STATE_RAMDISK |
>>   #endif
>> +                  BOOTM_STATE_MEASURE |
>>                     BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
>>                     BOOTM_STATE_OS_GO,
>>                     &images, 1);
>> diff --git a/cmd/bootm.c b/cmd/bootm.c
>> index 37c2af96e0..0c4a713e02 100644
>> --- a/cmd/bootm.c
>> +++ b/cmd/bootm.c
>> @@ -161,6 +161,8 @@ int do_bootm(struct cmd_tbl *cmdtp, int flag, int 
>> argc, char *const argv[])
>>           BOOTM_STATE_OS_GO;
>>       if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
>>           states |= BOOTM_STATE_RAMDISK;
>> +    if (IS_ENABLED(CONFIG_MEASURED_BOOT))
>> +        states |= BOOTM_STATE_MEASURE;
>>       if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS))
>>           states |= BOOTM_STATE_OS_CMDLINE;
>>       ret = do_bootm_states(cmdtp, flag, argc, argv, states, &images, 
>> 1);
>> diff --git a/cmd/bootz.c b/cmd/bootz.c
>> index f1423573d2..87922bfc3c 100644
>> --- a/cmd/bootz.c
>> +++ b/cmd/bootz.c
>> @@ -81,6 +81,7 @@ int do_bootz(struct cmd_tbl *cmdtp, int flag, int 
>> argc, char *const argv[])
>>   #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
>>                     BOOTM_STATE_RAMDISK |
>>   #endif
>> +                  BOOTM_STATE_MEASURE |
>>                     BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
>>                     BOOTM_STATE_OS_GO,
>>                     &images, 1);
>> diff --git a/include/bootm.h b/include/bootm.h
>> index 044a4797ed..76e8e38c82 100644
>> --- a/include/bootm.h
>> +++ b/include/bootm.h
>> @@ -55,6 +55,17 @@ ulong bootm_disable_interrupts(void);
>>   int bootm_find_images(int flag, int argc, char *const argv[], ulong 
>> start,
>>                 ulong size);
>>   +/*
>> + * Measure the boot images. Measurement is the process of hashing 
>> some binary
>> + * data and storing it into secure memory, i.e. TPM PCRs. In 
>> addition, each
>> + * measurement is logged into the platform event log such that the 
>> operating
>> + * system can access it and perform attestation of the boot.
>> + *
>> + * @images:    The structure containing the various images to boot 
>> (linux,
>> + *        initrd, dts, etc.)
>> + */
>> +int bootm_measure(struct bootm_headers *images);
>> +
>>   int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
>>               char *const argv[], int states, struct bootm_headers 
>> *images,
>>               int boot_progress);
>> diff --git a/include/image.h b/include/image.h
>> index 7717a4c13d..f7414b5338 100644
>> --- a/include/image.h
>> +++ b/include/image.h
>> @@ -407,6 +407,7 @@ struct bootm_headers {
>>   #define BOOTM_STATE_OS_FAKE_GO    0x00000200    /* 'Almost' run the 
>> OS */
>>   #define BOOTM_STATE_OS_GO    0x00000400
>>   #define BOOTM_STATE_PRE_LOAD    0x00000800
>> +#define BOOTM_STATE_MEASURE    0x00001000
>>       int        state;
>>     #if defined(CONFIG_LMB) && !defined(USE_HOSTCC)
>
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v9 4/6] bootm: Support boot measurement
  2023-08-07 14:43     ` Eddie James
@ 2023-08-07 14:52       ` Ilias Apalodimas
  2023-08-07 14:57         ` Eddie James
  0 siblings, 1 reply; 16+ messages in thread
From: Ilias Apalodimas @ 2023-08-07 14:52 UTC (permalink / raw)
  To: Eddie James; +Cc: Sean Edmond, u-boot, sjg, xypron.glpk, joel

Hi,

On Mon, 7 Aug 2023 at 17:43, Eddie James <eajames@linux.ibm.com> wrote:
>
>
> On 8/4/23 13:10, Sean Edmond wrote:
> > On 2023-03-08 1:25 p.m., Eddie James wrote:
> >> Add a configuration option to measure the boot through the bootm
> >> function. Add the measurement state to the booti and bootz paths
> >> as well.
> >>
> >> Signed-off-by: Eddie James <eajames@linux.ibm.com>
> >> Reviewed-by: Simon Glass <sjg@chromium.org>
> >> ---
> >> Changes since v8:
> >>   - Added a configuration option to select to ignore any existing
> >>     event log. This would only be selected for systems that know
> >>     that U-Boot is the first stage bootloader. This is necessary
> >>     because the reserved memory region may persist through resets
> >>     and so U-Boot attempts to append to the previous boot's log.
> >>
> >> Changes since v6:
> >>   - Added comment for bootm_measure
> >>   - Fixed line length in bootm_measure
> >>
> >>   boot/Kconfig    | 32 +++++++++++++++++++++
> >>   boot/bootm.c    | 74 +++++++++++++++++++++++++++++++++++++++++++++++++
> >>   cmd/booti.c     |  1 +
> >>   cmd/bootm.c     |  2 ++
> >>   cmd/bootz.c     |  1 +
> >>   include/bootm.h | 11 ++++++++
> >>   include/image.h |  1 +
> >>   7 files changed, 122 insertions(+)
> >>
> >> diff --git a/boot/Kconfig b/boot/Kconfig
> >> index 5f491625c8..8119519c9f 100644
> >> --- a/boot/Kconfig
> >> +++ b/boot/Kconfig
> >> @@ -629,6 +629,38 @@ config LEGACY_IMAGE_FORMAT
> >>         loaded. If a board needs the legacy image format support in this
> >>         case, enable it here.
> >>   +config MEASURED_BOOT
> >> +    bool "Measure boot images and configuration to TPM and event log"
> >> +    depends on HASH && TPM_V2
> >> +    help
> >> +      This option enables measurement of the boot process. Measurement
> >> +      involves creating cryptographic hashes of the binary images that
> >> +      are booting and storing them in the TPM. In addition, a log of
> >> +      these hashes is stored in memory for the OS to verify the booted
> >> +      images and configuration. Enable this if the OS has configured
> >> +      some memory area for the event log and you intend to use some
> >> +      attestation tools on your system.
> >> +
> >> +if MEASURED_BOOT
> >> +    config MEASURE_DEVICETREE
> >> +    bool "Measure the devicetree image"
> >> +    default y if MEASURED_BOOT
> >> +    help
> >> +      On some platforms, the devicetree is not static as it may contain
> >> +      random MAC addresses or other such data that changes each boot.
> >> +      Therefore, it should not be measured into the TPM. In that case,
> >> +      disable the measurement here.
> >> +
> >> +    config MEASURE_IGNORE_LOG
> >> +    bool "Ignore the existing event log"
> >> +    default n
> >> +    help
> >> +      On platforms that use an event log memory region that persists
> >> +      through system resets and are the first stage bootloader, then
> >> +      this option should be enabled to ignore any existing data in the
> >> +      event log memory region.
> >> +endif # MEASURED_BOOT
> >> +
> >>   config SUPPORT_RAW_INITRD
> >>       bool "Enable raw initrd images"
> >>       help
> >> diff --git a/boot/bootm.c b/boot/bootm.c
> >> index 2eec60ec7b..2685bdbd74 100644
> >> --- a/boot/bootm.c
> >> +++ b/boot/bootm.c
> >> @@ -22,6 +22,7 @@
> >>   #include <asm/global_data.h>
> >>   #include <asm/io.h>
> >>   #include <linux/sizes.h>
> >> +#include <tpm-v2.h>
> >>   #if defined(CONFIG_CMD_USB)
> >>   #include <usb.h>
> >>   #endif
> >> @@ -659,6 +660,75 @@ int bootm_process_cmdline_env(int flags)
> >>       return 0;
> >>   }
> >>   +int bootm_measure(struct bootm_headers *images)
> >> +{
> >> +    int ret = 0;
> >> +
> >> +    /* Skip measurement if EFI is going to do it */
> >> +    if (images->os.os == IH_OS_EFI &&
> >> +        IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) &&
> >> +        IS_ENABLED(CONFIG_BOOTM_EFI))
> >> +        return ret;
> >> +
> >
> > it looks like your measured boot implementation is hardcoding the
> > following PCR indexes:
> >
> > PCR #8 - kernel image measurement
> > PCR #9 - initrd measurement
> > PCR #0 - kernel DTB measurement
> > PCR #1 - bootargs measurement
>
>
> Hi,
>
>
> Yes, I followed this document as closely as I could:
> https://trustedcomputinggroup.org/wp-content/uploads/TCG_ServerManagementDomainFirmwareProfile_v1p00_11aug2020.pdf
>
> Which provides what should go in what PCR. I can understand users
> wanting a different setup, but as you say, that's probably out of the
> scope of this series.
>

Completely out of scope* of the series.  The purpose is follow the TCG
spec.  The minor deviations is our choice of the DTB in PCR1 (but
that's what the spec does for ACPI tables) and the choice for initrd
(which is what we do in the linux kernel).

We can reuse the functions ofc to measure random blobs, but that would
require some kind of config (maybe in a dts??) of what to measure.


Eddie,  I've pinged you in the past.  I rebased and fixed a few issues
of your tree here [0]. Do you plan to resend it at some point?

[0]https://source.denx.de/u-boot/custodians/u-boot-tpm/-/commits/eddie2/

Cheers
/Ilias
>
> Thanks,
>
> Eddie
>
>
> >
> > I wasn't able to find any specificaton on this measured boot
> > "profile".  Are you able to provide a reference?
> >
> > We've implemented our own version of measured boot, which maps
> > measurements to different PCR indexes.  In many cases, the data we're
> > measuring is also different.
> >
> > To make this feature more usable by others it would be nice to see a
> > more generic interface that would allow the user to specify the PCR
> > indexes, and the data to hash into these indexes.  This would allow
> > everyone to create their own custom measured boot "profile".  This
> > request is probably beyond the scope of your current efforts, but I
> > except this implementation to evolve significantly if/when it's accepted.
> >
> >> +    if (IS_ENABLED(CONFIG_MEASURED_BOOT)) {
> >> +        struct tcg2_event_log elog;
> >> +        struct udevice *dev;
> >> +        void *initrd_buf;
> >> +        void *image_buf;
> >> +        const char *s;
> >> +        u32 rd_len;
> >> +        bool ign;
> >> +
> >> +        elog.log_size = 0;
> >> +        ign = IS_ENABLED(CONFIG_MEASURE_IGNORE_LOG);
> >> +        ret = tcg2_measurement_init(&dev, &elog, ign);
> >> +        if (ret)
> >> +            return ret;
> >> +
> >> +        image_buf = map_sysmem(images->os.image_start,
> >> +                       images->os.image_len);
> >> +        ret = tcg2_measure_data(dev, &elog, 8, images->os.image_len,
> >> +                    image_buf, EV_COMPACT_HASH,
> >> +                    strlen("linux") + 1, (u8 *)"linux");
> >> +        if (ret)
> >> +            goto unmap_image;
> >> +
> >> +        rd_len = images->rd_end - images->rd_start;
> >> +        initrd_buf = map_sysmem(images->rd_start, rd_len);
> >> +        ret = tcg2_measure_data(dev, &elog, 9, rd_len, initrd_buf,
> >> +                    EV_COMPACT_HASH, strlen("initrd") + 1,
> >> +                    (u8 *)"initrd");
> >> +        if (ret)
> >> +            goto unmap_initrd;
> >> +
> >> +        if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) {
> >> +            ret = tcg2_measure_data(dev, &elog, 0, images->ft_len,
> >> +                        (u8 *)images->ft_addr,
> >> +                        EV_TABLE_OF_DEVICES,
> >> +                        strlen("dts") + 1,
> >> +                        (u8 *)"dts");
> >> +            if (ret)
> >> +                goto unmap_initrd;
> >> +        }
> >> +
> >> +        s = env_get("bootargs");
> >> +        if (!s)
> >> +            s = "";
> >> +        ret = tcg2_measure_data(dev, &elog, 1, strlen(s) + 1, (u8 *)s,
> >> +                    EV_PLATFORM_CONFIG_FLAGS,
> >> +                    strlen(s) + 1, (u8 *)s);
> >> +
> >> +unmap_initrd:
> >> +        unmap_sysmem(initrd_buf);
> >> +
> >> +unmap_image:
> >> +        unmap_sysmem(image_buf);
> >> +        tcg2_measurement_term(dev, &elog, ret != 0);
> >> +    }
> >> +
> >> +    return ret;
> >> +}
> >> +
> >>   /**
> >>    * Execute selected states of the bootm command.
> >>    *
> >> @@ -710,6 +780,10 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int
> >> flag, int argc,
> >>       if (!ret && (states & BOOTM_STATE_FINDOTHER))
> >>           ret = bootm_find_other(cmdtp, flag, argc, argv);
> >>   +    if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !ret &&
> >> +        (states & BOOTM_STATE_MEASURE))
> >> +        bootm_measure(images);
> >> +
> >>       /* Load the OS */
> >>       if (!ret && (states & BOOTM_STATE_LOADOS)) {
> >>           iflag = bootm_disable_interrupts();
> >> diff --git a/cmd/booti.c b/cmd/booti.c
> >> index 6ac39193db..659bb10549 100644
> >> --- a/cmd/booti.c
> >> +++ b/cmd/booti.c
> >> @@ -127,6 +127,7 @@ int do_booti(struct cmd_tbl *cmdtp, int flag, int
> >> argc, char *const argv[])
> >>   #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
> >>                     BOOTM_STATE_RAMDISK |
> >>   #endif
> >> +                  BOOTM_STATE_MEASURE |
> >>                     BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
> >>                     BOOTM_STATE_OS_GO,
> >>                     &images, 1);
> >> diff --git a/cmd/bootm.c b/cmd/bootm.c
> >> index 37c2af96e0..0c4a713e02 100644
> >> --- a/cmd/bootm.c
> >> +++ b/cmd/bootm.c
> >> @@ -161,6 +161,8 @@ int do_bootm(struct cmd_tbl *cmdtp, int flag, int
> >> argc, char *const argv[])
> >>           BOOTM_STATE_OS_GO;
> >>       if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
> >>           states |= BOOTM_STATE_RAMDISK;
> >> +    if (IS_ENABLED(CONFIG_MEASURED_BOOT))
> >> +        states |= BOOTM_STATE_MEASURE;
> >>       if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS))
> >>           states |= BOOTM_STATE_OS_CMDLINE;
> >>       ret = do_bootm_states(cmdtp, flag, argc, argv, states, &images,
> >> 1);
> >> diff --git a/cmd/bootz.c b/cmd/bootz.c
> >> index f1423573d2..87922bfc3c 100644
> >> --- a/cmd/bootz.c
> >> +++ b/cmd/bootz.c
> >> @@ -81,6 +81,7 @@ int do_bootz(struct cmd_tbl *cmdtp, int flag, int
> >> argc, char *const argv[])
> >>   #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
> >>                     BOOTM_STATE_RAMDISK |
> >>   #endif
> >> +                  BOOTM_STATE_MEASURE |
> >>                     BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
> >>                     BOOTM_STATE_OS_GO,
> >>                     &images, 1);
> >> diff --git a/include/bootm.h b/include/bootm.h
> >> index 044a4797ed..76e8e38c82 100644
> >> --- a/include/bootm.h
> >> +++ b/include/bootm.h
> >> @@ -55,6 +55,17 @@ ulong bootm_disable_interrupts(void);
> >>   int bootm_find_images(int flag, int argc, char *const argv[], ulong
> >> start,
> >>                 ulong size);
> >>   +/*
> >> + * Measure the boot images. Measurement is the process of hashing
> >> some binary
> >> + * data and storing it into secure memory, i.e. TPM PCRs. In
> >> addition, each
> >> + * measurement is logged into the platform event log such that the
> >> operating
> >> + * system can access it and perform attestation of the boot.
> >> + *
> >> + * @images:    The structure containing the various images to boot
> >> (linux,
> >> + *        initrd, dts, etc.)
> >> + */
> >> +int bootm_measure(struct bootm_headers *images);
> >> +
> >>   int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
> >>               char *const argv[], int states, struct bootm_headers
> >> *images,
> >>               int boot_progress);
> >> diff --git a/include/image.h b/include/image.h
> >> index 7717a4c13d..f7414b5338 100644
> >> --- a/include/image.h
> >> +++ b/include/image.h
> >> @@ -407,6 +407,7 @@ struct bootm_headers {
> >>   #define BOOTM_STATE_OS_FAKE_GO    0x00000200    /* 'Almost' run the
> >> OS */
> >>   #define BOOTM_STATE_OS_GO    0x00000400
> >>   #define BOOTM_STATE_PRE_LOAD    0x00000800
> >> +#define BOOTM_STATE_MEASURE    0x00001000
> >>       int        state;
> >>     #if defined(CONFIG_LMB) && !defined(USE_HOSTCC)
> >
> >

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v9 4/6] bootm: Support boot measurement
  2023-08-07 14:52       ` Ilias Apalodimas
@ 2023-08-07 14:57         ` Eddie James
  0 siblings, 0 replies; 16+ messages in thread
From: Eddie James @ 2023-08-07 14:57 UTC (permalink / raw)
  To: Ilias Apalodimas; +Cc: Sean Edmond, u-boot, sjg, xypron.glpk, joel


On 8/7/23 09:52, Ilias Apalodimas wrote:
> Hi,
>
> On Mon, 7 Aug 2023 at 17:43, Eddie James <eajames@linux.ibm.com> wrote:
>>
>> On 8/4/23 13:10, Sean Edmond wrote:
>>> On 2023-03-08 1:25 p.m., Eddie James wrote:
>>>> Add a configuration option to measure the boot through the bootm
>>>> function. Add the measurement state to the booti and bootz paths
>>>> as well.
>>>>
>>>> Signed-off-by: Eddie James <eajames@linux.ibm.com>
>>>> Reviewed-by: Simon Glass <sjg@chromium.org>
>>>> ---
>>>> Changes since v8:
>>>>    - Added a configuration option to select to ignore any existing
>>>>      event log. This would only be selected for systems that know
>>>>      that U-Boot is the first stage bootloader. This is necessary
>>>>      because the reserved memory region may persist through resets
>>>>      and so U-Boot attempts to append to the previous boot's log.
>>>>
>>>> Changes since v6:
>>>>    - Added comment for bootm_measure
>>>>    - Fixed line length in bootm_measure
>>>>
>>>>    boot/Kconfig    | 32 +++++++++++++++++++++
>>>>    boot/bootm.c    | 74 +++++++++++++++++++++++++++++++++++++++++++++++++
>>>>    cmd/booti.c     |  1 +
>>>>    cmd/bootm.c     |  2 ++
>>>>    cmd/bootz.c     |  1 +
>>>>    include/bootm.h | 11 ++++++++
>>>>    include/image.h |  1 +
>>>>    7 files changed, 122 insertions(+)
>>>>
>>>> diff --git a/boot/Kconfig b/boot/Kconfig
>>>> index 5f491625c8..8119519c9f 100644
>>>> --- a/boot/Kconfig
>>>> +++ b/boot/Kconfig
>>>> @@ -629,6 +629,38 @@ config LEGACY_IMAGE_FORMAT
>>>>          loaded. If a board needs the legacy image format support in this
>>>>          case, enable it here.
>>>>    +config MEASURED_BOOT
>>>> +    bool "Measure boot images and configuration to TPM and event log"
>>>> +    depends on HASH && TPM_V2
>>>> +    help
>>>> +      This option enables measurement of the boot process. Measurement
>>>> +      involves creating cryptographic hashes of the binary images that
>>>> +      are booting and storing them in the TPM. In addition, a log of
>>>> +      these hashes is stored in memory for the OS to verify the booted
>>>> +      images and configuration. Enable this if the OS has configured
>>>> +      some memory area for the event log and you intend to use some
>>>> +      attestation tools on your system.
>>>> +
>>>> +if MEASURED_BOOT
>>>> +    config MEASURE_DEVICETREE
>>>> +    bool "Measure the devicetree image"
>>>> +    default y if MEASURED_BOOT
>>>> +    help
>>>> +      On some platforms, the devicetree is not static as it may contain
>>>> +      random MAC addresses or other such data that changes each boot.
>>>> +      Therefore, it should not be measured into the TPM. In that case,
>>>> +      disable the measurement here.
>>>> +
>>>> +    config MEASURE_IGNORE_LOG
>>>> +    bool "Ignore the existing event log"
>>>> +    default n
>>>> +    help
>>>> +      On platforms that use an event log memory region that persists
>>>> +      through system resets and are the first stage bootloader, then
>>>> +      this option should be enabled to ignore any existing data in the
>>>> +      event log memory region.
>>>> +endif # MEASURED_BOOT
>>>> +
>>>>    config SUPPORT_RAW_INITRD
>>>>        bool "Enable raw initrd images"
>>>>        help
>>>> diff --git a/boot/bootm.c b/boot/bootm.c
>>>> index 2eec60ec7b..2685bdbd74 100644
>>>> --- a/boot/bootm.c
>>>> +++ b/boot/bootm.c
>>>> @@ -22,6 +22,7 @@
>>>>    #include <asm/global_data.h>
>>>>    #include <asm/io.h>
>>>>    #include <linux/sizes.h>
>>>> +#include <tpm-v2.h>
>>>>    #if defined(CONFIG_CMD_USB)
>>>>    #include <usb.h>
>>>>    #endif
>>>> @@ -659,6 +660,75 @@ int bootm_process_cmdline_env(int flags)
>>>>        return 0;
>>>>    }
>>>>    +int bootm_measure(struct bootm_headers *images)
>>>> +{
>>>> +    int ret = 0;
>>>> +
>>>> +    /* Skip measurement if EFI is going to do it */
>>>> +    if (images->os.os == IH_OS_EFI &&
>>>> +        IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL) &&
>>>> +        IS_ENABLED(CONFIG_BOOTM_EFI))
>>>> +        return ret;
>>>> +
>>> it looks like your measured boot implementation is hardcoding the
>>> following PCR indexes:
>>>
>>> PCR #8 - kernel image measurement
>>> PCR #9 - initrd measurement
>>> PCR #0 - kernel DTB measurement
>>> PCR #1 - bootargs measurement
>>
>> Hi,
>>
>>
>> Yes, I followed this document as closely as I could:
>> https://trustedcomputinggroup.org/wp-content/uploads/TCG_ServerManagementDomainFirmwareProfile_v1p00_11aug2020.pdf
>>
>> Which provides what should go in what PCR. I can understand users
>> wanting a different setup, but as you say, that's probably out of the
>> scope of this series.
>>
> Completely out of scope* of the series.  The purpose is follow the TCG
> spec.  The minor deviations is our choice of the DTB in PCR1 (but
> that's what the spec does for ACPI tables) and the choice for initrd
> (which is what we do in the linux kernel).
>
> We can reuse the functions ofc to measure random blobs, but that would
> require some kind of config (maybe in a dts??) of what to measure.
>
>
> Eddie,  I've pinged you in the past.  I rebased and fixed a few issues
> of your tree here [0]. Do you plan to resend it at some point?
>
> [0]https://source.denx.de/u-boot/custodians/u-boot-tpm/-/commits/eddie2/


Yes, sorry for the delay. I'll resend it now. Thank you for rebasing!

Thanks,

Eddie


>
> Cheers
> /Ilias
>> Thanks,
>>
>> Eddie
>>
>>
>>> I wasn't able to find any specificaton on this measured boot
>>> "profile".  Are you able to provide a reference?
>>>
>>> We've implemented our own version of measured boot, which maps
>>> measurements to different PCR indexes.  In many cases, the data we're
>>> measuring is also different.
>>>
>>> To make this feature more usable by others it would be nice to see a
>>> more generic interface that would allow the user to specify the PCR
>>> indexes, and the data to hash into these indexes.  This would allow
>>> everyone to create their own custom measured boot "profile".  This
>>> request is probably beyond the scope of your current efforts, but I
>>> except this implementation to evolve significantly if/when it's accepted.
>>>
>>>> +    if (IS_ENABLED(CONFIG_MEASURED_BOOT)) {
>>>> +        struct tcg2_event_log elog;
>>>> +        struct udevice *dev;
>>>> +        void *initrd_buf;
>>>> +        void *image_buf;
>>>> +        const char *s;
>>>> +        u32 rd_len;
>>>> +        bool ign;
>>>> +
>>>> +        elog.log_size = 0;
>>>> +        ign = IS_ENABLED(CONFIG_MEASURE_IGNORE_LOG);
>>>> +        ret = tcg2_measurement_init(&dev, &elog, ign);
>>>> +        if (ret)
>>>> +            return ret;
>>>> +
>>>> +        image_buf = map_sysmem(images->os.image_start,
>>>> +                       images->os.image_len);
>>>> +        ret = tcg2_measure_data(dev, &elog, 8, images->os.image_len,
>>>> +                    image_buf, EV_COMPACT_HASH,
>>>> +                    strlen("linux") + 1, (u8 *)"linux");
>>>> +        if (ret)
>>>> +            goto unmap_image;
>>>> +
>>>> +        rd_len = images->rd_end - images->rd_start;
>>>> +        initrd_buf = map_sysmem(images->rd_start, rd_len);
>>>> +        ret = tcg2_measure_data(dev, &elog, 9, rd_len, initrd_buf,
>>>> +                    EV_COMPACT_HASH, strlen("initrd") + 1,
>>>> +                    (u8 *)"initrd");
>>>> +        if (ret)
>>>> +            goto unmap_initrd;
>>>> +
>>>> +        if (IS_ENABLED(CONFIG_MEASURE_DEVICETREE)) {
>>>> +            ret = tcg2_measure_data(dev, &elog, 0, images->ft_len,
>>>> +                        (u8 *)images->ft_addr,
>>>> +                        EV_TABLE_OF_DEVICES,
>>>> +                        strlen("dts") + 1,
>>>> +                        (u8 *)"dts");
>>>> +            if (ret)
>>>> +                goto unmap_initrd;
>>>> +        }
>>>> +
>>>> +        s = env_get("bootargs");
>>>> +        if (!s)
>>>> +            s = "";
>>>> +        ret = tcg2_measure_data(dev, &elog, 1, strlen(s) + 1, (u8 *)s,
>>>> +                    EV_PLATFORM_CONFIG_FLAGS,
>>>> +                    strlen(s) + 1, (u8 *)s);
>>>> +
>>>> +unmap_initrd:
>>>> +        unmap_sysmem(initrd_buf);
>>>> +
>>>> +unmap_image:
>>>> +        unmap_sysmem(image_buf);
>>>> +        tcg2_measurement_term(dev, &elog, ret != 0);
>>>> +    }
>>>> +
>>>> +    return ret;
>>>> +}
>>>> +
>>>>    /**
>>>>     * Execute selected states of the bootm command.
>>>>     *
>>>> @@ -710,6 +780,10 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int
>>>> flag, int argc,
>>>>        if (!ret && (states & BOOTM_STATE_FINDOTHER))
>>>>            ret = bootm_find_other(cmdtp, flag, argc, argv);
>>>>    +    if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !ret &&
>>>> +        (states & BOOTM_STATE_MEASURE))
>>>> +        bootm_measure(images);
>>>> +
>>>>        /* Load the OS */
>>>>        if (!ret && (states & BOOTM_STATE_LOADOS)) {
>>>>            iflag = bootm_disable_interrupts();
>>>> diff --git a/cmd/booti.c b/cmd/booti.c
>>>> index 6ac39193db..659bb10549 100644
>>>> --- a/cmd/booti.c
>>>> +++ b/cmd/booti.c
>>>> @@ -127,6 +127,7 @@ int do_booti(struct cmd_tbl *cmdtp, int flag, int
>>>> argc, char *const argv[])
>>>>    #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
>>>>                      BOOTM_STATE_RAMDISK |
>>>>    #endif
>>>> +                  BOOTM_STATE_MEASURE |
>>>>                      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
>>>>                      BOOTM_STATE_OS_GO,
>>>>                      &images, 1);
>>>> diff --git a/cmd/bootm.c b/cmd/bootm.c
>>>> index 37c2af96e0..0c4a713e02 100644
>>>> --- a/cmd/bootm.c
>>>> +++ b/cmd/bootm.c
>>>> @@ -161,6 +161,8 @@ int do_bootm(struct cmd_tbl *cmdtp, int flag, int
>>>> argc, char *const argv[])
>>>>            BOOTM_STATE_OS_GO;
>>>>        if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
>>>>            states |= BOOTM_STATE_RAMDISK;
>>>> +    if (IS_ENABLED(CONFIG_MEASURED_BOOT))
>>>> +        states |= BOOTM_STATE_MEASURE;
>>>>        if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS))
>>>>            states |= BOOTM_STATE_OS_CMDLINE;
>>>>        ret = do_bootm_states(cmdtp, flag, argc, argv, states, &images,
>>>> 1);
>>>> diff --git a/cmd/bootz.c b/cmd/bootz.c
>>>> index f1423573d2..87922bfc3c 100644
>>>> --- a/cmd/bootz.c
>>>> +++ b/cmd/bootz.c
>>>> @@ -81,6 +81,7 @@ int do_bootz(struct cmd_tbl *cmdtp, int flag, int
>>>> argc, char *const argv[])
>>>>    #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
>>>>                      BOOTM_STATE_RAMDISK |
>>>>    #endif
>>>> +                  BOOTM_STATE_MEASURE |
>>>>                      BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
>>>>                      BOOTM_STATE_OS_GO,
>>>>                      &images, 1);
>>>> diff --git a/include/bootm.h b/include/bootm.h
>>>> index 044a4797ed..76e8e38c82 100644
>>>> --- a/include/bootm.h
>>>> +++ b/include/bootm.h
>>>> @@ -55,6 +55,17 @@ ulong bootm_disable_interrupts(void);
>>>>    int bootm_find_images(int flag, int argc, char *const argv[], ulong
>>>> start,
>>>>                  ulong size);
>>>>    +/*
>>>> + * Measure the boot images. Measurement is the process of hashing
>>>> some binary
>>>> + * data and storing it into secure memory, i.e. TPM PCRs. In
>>>> addition, each
>>>> + * measurement is logged into the platform event log such that the
>>>> operating
>>>> + * system can access it and perform attestation of the boot.
>>>> + *
>>>> + * @images:    The structure containing the various images to boot
>>>> (linux,
>>>> + *        initrd, dts, etc.)
>>>> + */
>>>> +int bootm_measure(struct bootm_headers *images);
>>>> +
>>>>    int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
>>>>                char *const argv[], int states, struct bootm_headers
>>>> *images,
>>>>                int boot_progress);
>>>> diff --git a/include/image.h b/include/image.h
>>>> index 7717a4c13d..f7414b5338 100644
>>>> --- a/include/image.h
>>>> +++ b/include/image.h
>>>> @@ -407,6 +407,7 @@ struct bootm_headers {
>>>>    #define BOOTM_STATE_OS_FAKE_GO    0x00000200    /* 'Almost' run the
>>>> OS */
>>>>    #define BOOTM_STATE_OS_GO    0x00000400
>>>>    #define BOOTM_STATE_PRE_LOAD    0x00000800
>>>> +#define BOOTM_STATE_MEASURE    0x00001000
>>>>        int        state;
>>>>      #if defined(CONFIG_LMB) && !defined(USE_HOSTCC)
>>>

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2023-08-07 14:57 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-08 21:25 [PATCH v9 0/6] tpm: Support boot measurements Eddie James
2023-03-08 21:25 ` [PATCH v9 1/6] tpm: Fix spelling for tpmu_ha union Eddie James
2023-03-08 21:25 ` [PATCH v9 2/6] tpm: sandbox: Update for needed TPM2 capabilities Eddie James
2023-03-16  8:32   ` Ilias Apalodimas
2023-05-09 13:49     ` Ilias Apalodimas
2023-03-08 21:25 ` [PATCH v9 3/6] tpm: Support boot measurements Eddie James
2023-04-06  9:18   ` Ilias Apalodimas
2023-04-10 16:18     ` Eddie James
2023-04-11  8:46       ` Ilias Apalodimas
2023-03-08 21:25 ` [PATCH v9 4/6] bootm: Support boot measurement Eddie James
2023-08-04 18:10   ` Sean Edmond
2023-08-07 14:43     ` Eddie James
2023-08-07 14:52       ` Ilias Apalodimas
2023-08-07 14:57         ` Eddie James
2023-03-08 21:25 ` [PATCH v9 5/6] test: Add sandbox TPM " Eddie James
2023-03-08 21:25 ` [PATCH v9 6/6] doc: Add measured boot documentation Eddie James

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.