feat: add logging infra w/ backend support

Add functions to support logging. This enables a user specifying their
own logging format for all functions. TF-A's logging format is supported
out of the box by specifying the `DEBUG_BACKEND_HEADER` as
`log_backed_tf.h`.

Implement digest helpers that avoid heap/libc as some end projects don't
have access to this.

Change-Id: I55410ab963ea4d0c1956ba41f94b67eced8621d5
Signed-off-by: Harrison Mutai <harrison.mutai@arm.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7291140..5c5312b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,7 +14,29 @@
 add_library(cxx_compiler_flags INTERFACE)
 target_compile_features(cxx_compiler_flags INTERFACE cxx_std_11)
 
-SET(TARGET_GROUP release CACHE STRING "Specify the Build Target [\"release\" by default]")
+set(
+    LOG_LEVEL "" CACHE STRING
+    "Log Level options:
+     0  - NONE
+     10 - ERROR
+     20 - NOTICE
+     30 - WARNING
+     40 - INFO
+     50 - VERBOSE"
+)
+
+if(LOG_LEVEL STREQUAL "")
+    if(CMAKE_BUILD_TYPE STREQUAL "Release")
+        set(LOG_LEVEL 20)
+    else()
+        set(LOG_LEVEL 40)
+    endif()
+endif()
+
+add_compile_definitions(EVLOG_LOG_LEVEL=${LOG_LEVEL})
+
+set(DEBUG_BACKEND_HEADER "log_backend_tf.h" CACHE STRING "Path to debug backend header")
+add_compile_definitions(DEBUG_BACKEND_HEADER="${DEBUG_BACKEND_HEADER}")
 
 if(HASH_ALGORITHM STREQUAL "SHA512")
     add_compile_definitions(TPM_ALG_ID=TPM_ALG_SHA512)
@@ -30,7 +52,11 @@
 add_library(eventlog STATIC
     ${PROJECT_SOURCE_DIR}/src/event_log.c
     ${PROJECT_SOURCE_DIR}/src/event_print.c
+    ${PROJECT_SOURCE_DIR}/src/digest.c
 )
 
 target_include_directories(eventlog PUBLIC ${CMAKE_SOURCE_DIR}/include)
+
+target_include_directories(eventlog PRIVATE ${CMAKE_SOURCE_DIR}/include/private)
+
 target_link_libraries(eventlog PUBLIC cxx_compiler_flags)
diff --git a/include/event_log.h b/include/event_log.h
index f97c580..ee54f9a 100644
--- a/include/event_log.h
+++ b/include/event_log.h
@@ -37,6 +37,12 @@
 	size_t count;
 };
 
+struct event_log_algorithm {
+	uint16_t id;
+	const char *name;
+	uint16_t size;
+};
+
 #define ID_EVENT_SIZE                                           \
 	(sizeof(id_event_headers_t) +                           \
 	 (sizeof(id_event_algorithm_size_t) * HASH_ALG_COUNT) + \
diff --git a/include/log_backend_printf.h b/include/log_backend_printf.h
new file mode 100644
index 0000000..1c7d581
--- /dev/null
+++ b/include/log_backend_printf.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef LOG_BACKEND_PRINTF_H
+#define LOG_BACKEND_PRINTF_H
+
+#include <stdio.h>
+
+#define evlog_log printf
+
+#define EVLOG_MARKER_ERROR "[ERROR] "
+#define EVLOG_MARKER_NOTICE "[NOTICE] "
+#define EVLOG_MARKER_WARNING "[WARNING] "
+#define EVLOG_MARKER_INFO "[INFO] "
+#define EVLOG_MARKER_VERBOSE "[VERBOSE] "
+
+#endif /* LOG_BACKEND_PRINTF_H */
diff --git a/include/log_backend_tf.h b/include/log_backend_tf.h
new file mode 100644
index 0000000..f9aa1a9
--- /dev/null
+++ b/include/log_backend_tf.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef LOG_BACKEND_TF_H
+#define LOG_BACKEND_TF_H
+
+#include <stdio.h>
+
+void evlog_log(const char *fmt, ...) __asm__("tf_log");
+
+#define EVLOG_MARKER_ERROR "\xa" /* 10 */
+#define EVLOG_MARKER_NOTICE "\x14" /* 20 */
+#define EVLOG_MARKER_WARNING "\x1e" /* 30 */
+#define EVLOG_MARKER_INFO "\x28" /* 40 */
+#define EVLOG_MARKER_VERBOSE "\x32" /* 50 */
+
+#endif /* LOG_BACKEND_TF_H */
diff --git a/include/private/debug.h b/include/private/debug.h
new file mode 100644
index 0000000..da10529
--- /dev/null
+++ b/include/private/debug.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include DEBUG_BACKEND_HEADER
+
+/*
+ * The log output macros print output to the console. These macros produce
+ * compiled log output only if the EVLOG_LOG_LEVEL defined in the makefile (or the
+ * make command line) is greater or equal than the level required for that
+ * type of log output.
+ *
+ * The format expected is the same as for printf(). For example:
+ * INFO("Info %s.\n", "message")    -> INFO:    Info message.
+ * WARN("Warning %s.\n", "message") -> WARNING: Warning message.
+ */
+
+#define EVLOG_LEVEL_NONE 0
+#define EVLOG_LEVEL_ERROR 10
+#define EVLOG_LEVEL_NOTICE 20
+#define EVLOG_LEVEL_WARNING 30
+#define EVLOG_LEVEL_INFO 40
+#define EVLOG_LEVEL_VERBOSE 50
+
+/*
+ * If the log output is too low then this macro is used in place of evlog_log()
+ * below. The intent is to get the compiler to evaluate the function call for
+ * type checking and format specifier correctness but let it optimize it out.
+ */
+#define no_evlog_log(fmt, ...)                         \
+	do {                                           \
+		if (false) {                           \
+			evlog_log(fmt, ##__VA_ARGS__); \
+		}                                      \
+	} while (false)
+
+#if EVLOG_LOG_LEVEL >= EVLOG_LEVEL_ERROR
+#define ERROR(...) evlog_log(EVLOG_MARKER_ERROR __VA_ARGS__)
+#else
+#define ERROR(...) no_evlog_log(EVLOG_MARKER_ERROR __VA_ARGS__)
+#endif
+
+#if EVLOG_LOG_LEVEL >= EVLOG_LEVEL_NOTICE
+#define NOTICE(...) evlog_log(EVLOG_MARKER_NOTICE __VA_ARGS__)
+#else
+#define NOTICE(...) no_evlog_log(EVLOG_MARKER_NOTICE __VA_ARGS__)
+#endif
+
+#if EVLOG_LOG_LEVEL >= EVLOG_LEVEL_WARNING
+#define WARN(...) evlog_log(EVLOG_MARKER_WARNING __VA_ARGS__)
+#else
+#define WARN(...) no_evlog_log(EVLOG_MARKER_WARNING __VA_ARGS__)
+#endif
+
+#if EVLOG_LOG_LEVEL >= EVLOG_LEVEL_INFO
+#define INFO(...) evlog_log(EVLOG_MARKER_INFO __VA_ARGS__)
+#else
+#define INFO(...) no_evlog_log(EVLOG_MARKER_INFO __VA_ARGS__)
+#endif
+
+#if EVLOG_LOG_LEVEL >= EVLOG_LEVEL_VERBOSE
+#define VERBOSE(...) evlog_log(EVLOG_MARKER_VERBOSE __VA_ARGS__)
+#else
+#define VERBOSE(...) no_evlog_log(EVLOG_MARKER_VERBOSE __VA_ARGS__)
+#endif
+
+#endif /* DEBUG_H */
diff --git a/include/private/digest.h b/include/private/digest.h
new file mode 100644
index 0000000..23567b8
--- /dev/null
+++ b/include/private/digest.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DIGEST_H
+#define DIGEST_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "event_log.h"
+
+/**
+ * @brief Lookup algorithm metadata by numeric identifier.
+ *
+ * Translates a TPM/TCG-style algorithm ID into a description structure
+ * containing name, digest length, and other properties.
+ *
+ * @param[in] algo_id  Numeric algorithm identifier (e.g. TPM2_ALG_SHA256).
+ *
+ * @return Pointer to a constant algorithm descriptor, or NULL if not found.
+ */
+const struct event_log_algorithm *
+event_log_algorithm_lookup(uint16_t algorithm_id);
+
+/**
+ * @brief Append a C-string to a growing buffer with running position.
+ *
+ * Appends as many characters from @p s as fit, ensuring NUL-termination if any
+ * bytes were copied. Advances @p *pos by the full length of @p s regardless of
+ * truncation, enabling “would-have-written” accounting at the call site.
+ *
+ * @param[in,out] dst  Destination buffer.
+ * @param[in]     cap  Total capacity of @p dst (bytes, incl. space for NUL).
+ * @param[in,out] pos  In: current logical length; Out: increased by strlen(@p s).
+ * @param[in]     s    NUL-terminated string to append.
+ *
+ * @return strlen(@p s).
+ *
+ * @note Intended usage pattern:
+ * @code
+ * size_t pos = 0; buf[0] = '\0';
+ * append_str(buf, cap, &pos, "prefix: ");
+ * append_str(buf, cap, &pos, value);
+ * bool truncated = (pos >= cap);
+ * @endcode
+ */
+size_t event_log_append_str(char *dst, size_t cap, size_t *pos, const char *s);
+
+/**
+ * @brief Convert bytes to lower-hex with spaces (e.g., "aa ff …").
+ *
+ * Writes at most @p dst_len bytes including the terminating NUL (if @p dst_len > 0).
+ * Always returns the number of characters that would have been written
+ * (excluding the NUL), so you can detect truncation by checking
+ * `return_value >= dst_len`.
+ *
+ * @param[out] dst      Destination buffer for ASCII hex; may be NULL only if @p dst_len == 0.
+ * @param[in]  dst_len  Capacity of @p dst in bytes (including room for NUL).
+ * @param[in]  nbytes   Number of input bytes to render.
+ * @param[in]  digest   Pointer to @p nbytes of data; not modified.
+ *
+ * @return Characters that would have been written (excluding the terminating NUL).
+ *
+ * Example:
+ * @code
+ * // For 3 bytes, required size is 3*3 - 1 + 1 (for NUL) = 9
+ * char buf[9];
+ * size_t need = write_hex_spaced(buf, sizeof buf, 3, in);
+ * bool truncated = (need >= sizeof buf);
+ * @endcode
+ */
+size_t event_log_write_hex_spaced(char *dst, size_t dst_len, size_t nbytes,
+				  const uint8_t *digest);
+
+#endif /* DIGEST_H */
diff --git a/src/digest.c b/src/digest.c
new file mode 100644
index 0000000..346679d
--- /dev/null
+++ b/src/digest.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "event_log.h"
+
+const struct event_log_algorithm algorithms[] = {
+	{ TPM_ALG_SHA256, "SHA256", SHA256_DIGEST_SIZE },
+	{ TPM_ALG_SHA384, "SHA384", SHA384_DIGEST_SIZE },
+	{ TPM_ALG_SHA512, "SHA512", SHA512_DIGEST_SIZE },
+};
+
+const struct event_log_algorithm *
+event_log_algorithm_lookup(uint16_t algorithm_id)
+{
+	for (size_t i = 0; i < sizeof(algorithms) / sizeof(algorithms[0]);
+	     i++) {
+		if (algorithms[i].id == algorithm_id) {
+			return &algorithms[i];
+		}
+	}
+
+	return NULL;
+}
+
+size_t event_log_append_str(char *dst, size_t cap, size_t *pos, const char *s)
+{
+	size_t n = strlen(s);
+	size_t room = (*pos < cap) ? (cap - *pos) : 0;
+
+	if (room) {
+		/* copy as much as fits, leave NUL handled by caller if needed */
+		size_t to_copy = (n < room) ? n : (room - 1);
+		memcpy(dst + *pos, s, to_copy);
+		dst[*pos + to_copy] = '\0';
+	}
+	*pos += n;
+	return n;
+}
+
+size_t event_log_write_hex_spaced(char *dst, size_t dst_len, size_t nbytes,
+				  const uint8_t *digest)
+{
+	static const char HEX[] = "0123456789abcdef";
+	size_t pos = 0;
+
+	if (nbytes > dst_len / 3) {
+		nbytes = dst_len / 3;
+	}
+
+	for (size_t i = 0; i < nbytes; i++) {
+		dst[pos++] = HEX[digest[i] >> 4];
+		dst[pos++] = HEX[digest[i] & 0x0F];
+		dst[pos++] = ' ';
+	}
+
+	if (dst_len > 0) {
+		if (pos >= dst_len) {
+			dst[dst_len - 1] = '\0';
+		} else {
+			dst[pos] = '\0';
+		}
+	}
+
+	return pos; /* count that WOULD have been written */
+}
diff --git a/src/event_print.c b/src/event_print.c
index 72a1c7c..6029548 100644
--- a/src/event_print.c
+++ b/src/event_print.c
@@ -6,11 +6,60 @@
 
 #include <errno.h>
 #include <stdbool.h>
-#include <stdio.h>
 #include <string.h>
 
+#include "debug.h"
+#include "digest.h"
 #include "event_log.h"
 
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * @brief Pretty-print a digest as 16-byte spaced hex rows with a
+ * header/continuation prefix.
+ *
+ * Emits one or more lines through the NOTICE() logging macro.
+ * Each line renders up to 16 bytes as "aa bb …".
+ *
+ * @param[in] buf         Byte array to print.
+ * @param[in] buf_len     Number of bytes in @p digest.
+ * @param[in] prefix      Prefix to append to the byte array (e.g. 'VendorInfo      :').
+ *
+ */
+static void event_log_print_spaced_hex(const uint8_t *buf, size_t buf_len,
+				       const char *prefix)
+{
+	char output_buf[256];
+	const size_t cap = sizeof(output_buf);
+	size_t pos = 0U;
+	size_t chunk;
+
+	/* Start from just after the prefix */
+	event_log_append_str(output_buf, cap, &pos, prefix);
+
+	for (size_t off = 0; off < buf_len; off += 16U) {
+		chunk = (buf_len - off >= 16U) ? 16U : (buf_len - off);
+
+		/* write the 16-byte (or tail) chunk */
+		pos += event_log_write_hex_spaced(output_buf + pos,
+						  (pos < cap) ? (cap - pos) : 0,
+						  chunk, buf + off);
+
+		NOTICE("  %s\n", output_buf);
+
+		/* prepare next line: reset to prefix only */
+		pos = 0;
+		output_buf[0] = '\0';
+		event_log_append_str(output_buf, cap, &pos, "\t\t      : ");
+	}
+}
+
+static void event_log_print_digest(const uint8_t *digest, size_t digest_len)
+{
+	event_log_print_spaced_hex(digest, digest_len, "Digest             : ");
+}
+
 /**
  * Print a TCG_EfiSpecIDEventStruct entry from the event log.
  *
@@ -34,6 +83,7 @@
 	uint32_t event_size, number_of_algorithms;
 	size_t digest_len;
 	const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size);
+	const struct event_log_algorithm *algo_info;
 
 	if (*log_size < sizeof(id_event_headers_t)) {
 		return -EINVAL;
@@ -43,48 +93,36 @@
 	 * EventType of EV_NO_ACTION, Digest of 20 bytes of 0, and
 	 * Event content defined as TCG_EfiSpecIDEventStruct.
 	 */
-	printf("TCG_EfiSpecIDEvent:\n");
-	printf("  PCRIndex           : %u\n", event->header.pcr_index);
+	NOTICE("TCG_EfiSpecIDEvent:\n");
+	NOTICE("  PCRIndex           : %u\n", event->header.pcr_index);
 	if (event->header.pcr_index != (uint32_t)PCR_0) {
 		return -EINVAL;
 	}
 
-	printf("  EventType          : %u\n", event->header.event_type);
+	NOTICE("  EventType          : %u\n", event->header.event_type);
 	if (event->header.event_type != EV_NO_ACTION) {
 		return -EINVAL;
 	}
 
-	printf("  Digest             :");
-	for (i = 0U; i < sizeof(event->header.digest); ++i) {
-		uint8_t val = event->header.digest[i];
-
-		(void)printf(" %02x", val);
-		if ((i & 0xFU) == 0U) {
-			(void)printf("\n");
-			printf("\t\t      :");
-		}
-	}
-
-	if ((i & 0xFU) != 0U) {
-		(void)printf("\n");
-	}
+	event_log_print_digest(event->header.digest,
+			       sizeof(event->header.digest));
 
 	/* EventSize */
 	event_size = event->header.event_size;
-	printf("  EventSize          : %u\n", event_size);
+	NOTICE("  EventSize          : %u\n", event_size);
 
-	printf("  Signature          : %s\n", event->struct_header.signature);
-	printf("  PlatformClass      : %u\n",
+	NOTICE("  Signature          : %s\n", event->struct_header.signature);
+	NOTICE("  PlatformClass      : %u\n",
 	       event->struct_header.platform_class);
-	printf("  SpecVersion        : %u.%u.%u\n",
+	NOTICE("  SpecVersion        : %u.%u.%u\n",
 	       event->struct_header.spec_version_major,
 	       event->struct_header.spec_version_minor,
 	       event->struct_header.spec_errata);
-	printf("  UintnSize          : %u\n", event->struct_header.uintn_size);
+	NOTICE("  UintnSize          : %u\n", event->struct_header.uintn_size);
 
 	/* NumberOfAlgorithms */
 	number_of_algorithms = event->struct_header.number_of_algorithms;
-	printf("  NumberOfAlgorithms : %u\n", number_of_algorithms);
+	NOTICE("  NumberOfAlgorithms : %u\n", number_of_algorithms);
 
 	/* Address of DigestSizes[] */
 	alg_ptr = event->struct_header.digest_size;
@@ -95,29 +133,20 @@
 		return -EFAULT;
 	}
 
-	printf("  DigestSizes        :\n");
-	for (i = 0U; i < number_of_algorithms; ++i) {
-		printf("    #%u AlgorithmId   : SHA", i);
-		uint16_t algorithm_id = alg_ptr[i].algorithm_id;
+	NOTICE("  DigestSizes        :\n");
 
-		switch (algorithm_id) {
-		case TPM_ALG_SHA256:
-			(void)printf("256\n");
-			break;
-		case TPM_ALG_SHA384:
-			(void)printf("384\n");
-			break;
-		case TPM_ALG_SHA512:
-			(void)printf("512\n");
-			break;
-		default:
-			(void)printf("?\n");
-			// ERROR("Algorithm 0x%x not found\n", algorithm_id);
-			printf("Algorithm 0x%x not found\n", algorithm_id);
+	for (i = 0U; i < number_of_algorithms; ++i) {
+		uint16_t algorithm_id = alg_ptr[i].algorithm_id;
+		algo_info = event_log_algorithm_lookup(algorithm_id);
+
+		if (algo_info == NULL) {
+			ERROR("    #%u AlgorithmId   : %d (unknown)\n", i,
+			      algorithm_id);
 			return -ENOENT;
 		}
 
-		printf("       DigestSize    : %u\n", alg_ptr[i].digest_size);
+		NOTICE("    #%u AlgorithmId   : %s\n", i, algo_info->name);
+		NOTICE("       DigestSize    : %u\n", alg_ptr[i].digest_size);
 	}
 
 	/* Address of VendorInfoSize */
@@ -127,7 +156,7 @@
 	}
 
 	info_size = *info_size_ptr++;
-	printf("  VendorInfoSize     : %u\n", info_size);
+	NOTICE("  VendorInfoSize     : %u\n", info_size);
 
 	/* Check VendorInfo end address */
 	if (((uintptr_t)info_size_ptr + info_size) > (uintptr_t)end_ptr) {
@@ -140,13 +169,8 @@
 		return -EFAULT;
 	}
 
-	if (info_size != 0U) {
-		printf("  VendorInfo         :");
-		for (i = 0U; i < info_size; ++i) {
-			(void)printf(" %02x", *info_size_ptr++);
-		}
-		(void)printf("\n");
-	}
+	event_log_print_spaced_hex(info_size_ptr, info_size,
+				   "  VendorInfo         : ");
 
 	*log_size -= (uintptr_t)info_size_ptr - (uintptr_t)*log_addr;
 	*log_addr = info_size_ptr;
@@ -170,27 +194,27 @@
 static int event_log_print_pcr_event2(uint8_t **log_addr, size_t *log_size)
 {
 	uint32_t event_size, count;
-	size_t sha_size, digests_size = 0U;
 	void *ptr = *log_addr;
+	const struct event_log_algorithm *algo_info;
 	const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size);
 
 	if (*log_size < sizeof(event2_header_t)) {
 		return -EINVAL;
 	}
 
-	printf("PCR_Event2:\n");
-	printf("  PCRIndex           : %u\n",
+	NOTICE("PCR_Event2:\n");
+	NOTICE("  PCRIndex           : %u\n",
 	       ((event2_header_t *)ptr)->pcr_index);
-	printf("  EventType          : %u\n",
+	NOTICE("  EventType          : %u\n",
 	       ((event2_header_t *)ptr)->event_type);
 
 	count = ((event2_header_t *)ptr)->digests.count;
 	if (count < 1U) {
-		printf("Invalid Digests Count      : %u\n", count);
+		NOTICE("Invalid Digests Count      : %u\n", count);
 		return -EINVAL;
 	}
 
-	printf("  Digests Count      : %u\n", count);
+	NOTICE("  Digests Count      : %u\n", count);
 
 	/* Address of TCG_PCR_EVENT2.Digests[] */
 	ptr = (uint8_t *)ptr + sizeof(event2_header_t);
@@ -205,46 +229,25 @@
 			return -EFAULT;
 		}
 
-		printf("    #%u AlgorithmId   : SHA", i);
-		switch (((tpmt_ha *)ptr)->algorithm_id) {
-		case TPM_ALG_SHA256:
-			sha_size = SHA256_DIGEST_SIZE;
-			(void)printf("256\n");
-			break;
-		case TPM_ALG_SHA384:
-			sha_size = SHA384_DIGEST_SIZE;
-			(void)printf("384\n");
-			break;
-		case TPM_ALG_SHA512:
-			sha_size = SHA512_DIGEST_SIZE;
-			(void)printf("512\n");
-			break;
-		default:
-			(void)printf("?\n");
-			printf("Algorithm 0x%x not found\n",
-			       ((tpmt_ha *)ptr)->algorithm_id);
+		algo_info = event_log_algorithm_lookup(
+			((tpmt_ha *)ptr)->algorithm_id);
+
+		if (algo_info == NULL) {
+			ERROR("    #%u AlgorithmId   : %d (unknown)\n", i,
+			      ((tpmt_ha *)ptr)->algorithm_id);
 			return -ENOENT;
 		}
 
+		NOTICE("    #%u AlgorithmId   : %s\n", i, algo_info->name);
+
 		/* End of Digest[] */
 		ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest));
-		if (((uintptr_t)ptr + sha_size) > (uintptr_t)end_ptr) {
+		if (((uintptr_t)ptr + algo_info->size) > (uintptr_t)end_ptr) {
 			return -EFAULT;
 		}
 
-		/* Total size of all digests */
-		digests_size += sha_size;
-
-		printf("       Digest        :");
-		for (unsigned int j = 0U; j < sha_size; ++j) {
-			(void)printf(" %02x", *(uint8_t *)ptr++);
-			if ((j & 0xFU) == 0xFU) {
-				(void)printf("\n");
-				if (j < (sha_size - 1U)) {
-					printf("\t\t      :");
-				}
-			}
-		}
+		event_log_print_digest(ptr, algo_info->size);
+		ptr += algo_info->size;
 	}
 
 	/* TCG_PCR_EVENT2.EventSize */
@@ -254,7 +257,7 @@
 	}
 
 	event_size = ((event2_data_t *)ptr)->event_size;
-	printf("  EventSize          : %u\n", event_size);
+	NOTICE("  EventSize          : %u\n", event_size);
 
 	/* Address of TCG_PCR_EVENT2.Event[EventSize] */
 	ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event));
@@ -266,12 +269,12 @@
 
 	if ((event_size == sizeof(startup_locality_event_t)) &&
 	    (strcmp((const char *)ptr, TCG_STARTUP_LOCALITY_SIGNATURE) == 0)) {
-		printf("  Signature          : %s\n",
+		NOTICE("  Signature          : %s\n",
 		       ((startup_locality_event_t *)ptr)->signature);
-		printf("  StartupLocality    : %u\n",
+		NOTICE("  StartupLocality    : %u\n",
 		       ((startup_locality_event_t *)ptr)->startup_locality);
 	} else {
-		printf("  Event              : %s\n", (uint8_t *)ptr);
+		NOTICE("  Event              : %s\n", (uint8_t *)ptr);
 	}
 
 	*log_size -= (uintptr_t)ptr + event_size - (uintptr_t)*log_addr;