[PATCH v2 3/3] tpm: allocate tpm event log if missing
Ilias Apalodimas
ilias.apalodimas at linaro.org
Thu Jun 11 11:57:09 CEST 2026
Hi Ludwig,
The CI [0] fails with this attached. You can run it in github by
opening a PR before v3. Also can you update the description and add
the use case you mention in the cover letter?
On Wed, 10 Jun 2026 at 13:52, Ludwig Nussel <ludwig.nussel at siemens.com> wrote:
>
> Allocate and attach the TPM event log to the TPM device if not
> initialized yet. The address is copied into the device tree for the
> kernel so the event log is accessible from Linux userspace too.
>
> Signed-off-by: Ludwig Nussel <ludwig.nussel at siemens.com>
>
> ---
>
> Changes in v2:
> - imply DEVRES in config TPM
> - use fdt_getprop for reading property
> - don't wrap #include in #if
> - fix memory leak in error case of tcg2_log_prepare_buffer
> - handle NULL elog parameter in tcg2_measurement_term
> - use CONFIG_TPM2_EVENT_LOG_SIZE
> - pass log_size instead of position in dt
>
> boot/bootm.c | 18 +++---
> boot/image-fdt.c | 69 +++++++++++++++++++++++
> include/tpm-common.h | 2 +
> include/tpm_tcg2.h | 9 +--
> lib/Kconfig | 1 +
> lib/tpm_tcg2.c | 130 ++++++++++++++++++++++++++++++++++---------
> 6 files changed, 188 insertions(+), 41 deletions(-)
>
[...]
> 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)
> + ret = tcg2_measurement_init(&dev, NULL);
I'd like the eventlog to be initialized before calling this (look below).
> + if (ret && ret != -EEXIST)
> 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,
> + ret = tcg2_measure_data(dev, NULL, 8, images->os.image_len,
> image_buf, EV_COMPACT_HASH,
> strlen("linux") + 1, (u8 *)"linux");
> if (ret)
> @@ -945,14 +941,14 @@ int bootm_measure(struct bootm_headers *images)
>
> 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,
> + ret = tcg2_measure_data(dev, NULL, 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, 1, images->ft_len,
> + ret = tcg2_measure_data(dev, NULL, 1, images->ft_len,
> (u8 *)images->ft_addr,
> EV_TABLE_OF_DEVICES,
> strlen("dts") + 1,
> @@ -964,7 +960,7 @@ int bootm_measure(struct bootm_headers *images)
> s = env_get("bootargs");
> if (!s)
> s = "";
> - ret = tcg2_measure_data(dev, &elog, 1, strlen(s) + 1, (u8 *)s,
> + ret = tcg2_measure_data(dev, NULL, 1, strlen(s) + 1, (u8 *)s,
> EV_PLATFORM_CONFIG_FLAGS,
> strlen(s) + 1, (u8 *)s);
>
> @@ -973,7 +969,7 @@ unmap_initrd:
>
> unmap_image:
> unmap_sysmem(image_buf);
> - tcg2_measurement_term(dev, &elog, ret != 0);
> + tcg2_measurement_term(dev, NULL, ret != 0);
> }
>
> return ret;
> diff --git a/boot/image-fdt.c b/boot/image-fdt.c
> index a3a4fb8b558..478158294ed 100644
> --- a/boot/image-fdt.c
> +++ b/boot/image-fdt.c
> @@ -24,6 +24,8 @@
> #include <asm/io.h>
> #include <dm/ofnode.h>
> #include <tee/optee.h>
> +#include <tpm_tcg2.h>
> +#include <dm/device.h>
>
> DECLARE_GLOBAL_DATA_PTR;
>
> @@ -589,6 +591,68 @@ __weak int arch_fixup_fdt(void *blob)
> return 0;
> }
>
> +static int copy_tpm_event_log(void *blob)
> +{
> + int rc;
> + struct udevice *dev;
> + ofnode node;
> + char path[256];
> + int off;
> + struct tcg2_event_log *log;
> +
> + if (!IS_ENABLED(CONFIG_MEASURED_BOOT))
> + return 0;
> +
> + rc = tcg2_platform_get_tpm2(&dev);
> + if (rc)
> + return rc;
> +
[...]
> /**
> diff --git a/include/tpm_tcg2.h b/include/tpm_tcg2.h
> index eb6afe49e77..db3f6f486e9 100644
> --- a/include/tpm_tcg2.h
> +++ b/include/tpm_tcg2.h
> @@ -162,12 +162,14 @@ struct tcg_efi_spec_id_event {
> * @log_position: Current entry position
> * @log_size: Log space available
> * @found: Boolean indicating if an existing log was discovered
> + * @allocated: Boolean indicating that the log was allocated by u-boot
> */
> struct tcg2_event_log {
> u8 *log;
> u32 log_position;
> u32 log_size;
> bool found;
> + bool allocated;
> };
I think it makes more sense to define an eventlog state with a u32 and
replace the found boolean with it. e.g
#define ELOG_FOUND BIT(0)
#define ELOG_ALLOCATED BIT(1) etc
>
> /**
> @@ -291,13 +293,10 @@ int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
> * 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);
> +int tcg2_measurement_init(struct udevice **dev, struct tcg2_event_log *elog);
>
> /**
> * Stop measurements and record separator events.
> @@ -345,4 +344,6 @@ void tcg2_platform_startup_error(struct udevice *dev, int rc);
> */
> u32 tcg2_algorithm_to_mask(enum tpm2_algorithms);
>
> +struct tcg2_event_log *tcg2_platform_get_dev_log(struct udevice *dev);
> +
> #endif /* __TPM_TCG_V2_H */
> diff --git a/lib/Kconfig b/lib/Kconfig
> index cf13ac1bdad..170621ae266 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -493,6 +493,7 @@ config TPM
> bool "Trusted Platform Module (TPM) Support"
> depends on DM
> imply DM_RNG
> + imply DEVRES
> select SHA1
> help
> This enables support for TPMs which can be used to provide security
> diff --git a/lib/tpm_tcg2.c b/lib/tpm_tcg2.c
> index d41228f75a9..2270b038cf5 100644
> --- a/lib/tpm_tcg2.c
> +++ b/lib/tpm_tcg2.c
> @@ -21,6 +21,7 @@
> #include <linux/unaligned/le_byteshift.h>
> #include "tpm-utils.h"
> #include <bloblist.h>
> +#include <dm/devres.h>
>
> int tcg2_get_pcr_info(struct udevice *dev, u32 *supported_bank, u32 *active_bank,
> u32 *bank_num)
> @@ -212,6 +213,9 @@ static int tcg2_log_append_check(struct tcg2_event_log *elog, u32 pcr_index,
> u32 event_size;
> u8 *log;
>
> + if (!elog || !elog->log_size)
> + return 0;
> +
> 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__,
> @@ -553,6 +557,9 @@ int tcg2_measure_data(struct udevice *dev, struct tcg2_event_log *elog,
> if (rc)
> return rc;
>
> + if (!elog)
> + elog = tcg2_platform_get_dev_log(dev);
> +
Initializing this here feels wrong. This is a function that just
measures and logs data. Why can't we fill in the eventlog address
early before calling this? If we do so some of the checks above are
also not needed
> return tcg2_log_append_check(elog, pcr_index, event_type, &digest_list,
> event_size, event);
> }
> @@ -560,15 +567,32 @@ int tcg2_measure_data(struct udevice *dev, struct tcg2_event_log *elog,
> int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
[...]
[0] https://source.denx.de/u-boot/custodians/u-boot-tpm/-/pipelines/30423
Thanks
/Ilias
More information about the U-Boot
mailing list