feat: add support for lib based timer ops
Add timer functions based on POSIX clock_gettime().
Add option in CMake to use these functions.
Signed-off-by: Matthew Ellis <Matthew.Ellis@arm.com>
Change-Id: I8a08e1fc2f88bed823d802240d2846d546e817fe
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a89f4f3..718e785 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,6 +41,9 @@
set(DEBUG_BACKEND_HEADER "log_backend_printf.h" CACHE STRING "Path to debug backend header")
add_compile_definitions(DEBUG_BACKEND_HEADER="${DEBUG_BACKEND_HEADER}")
+set (LIB_TIMER "NONE" CACHE STRING "Option to use library timer, rather than explicitly pass one")
+set_property (CACHE LIB_TIMER PROPERTY STRINGS "NONE" "POSIX")
+
SET(TARGET_GROUP release CACHE STRING "Specify the Build Target [\"release\" by default]")
@@ -68,6 +71,15 @@
message(FATAL_ERROR "Unknown transport interface selected")
endif()
+if (${LIB_TIMER} STREQUAL "POSIX")
+ target_sources (tpm2
+ PRIVATE
+ ${PROJECT_SOURCE_DIR}/src/timer/posix_timer_ops.c
+ )
+ add_compile_definitions (HAS_LIB_TIMER=1)
+endif()
+
+
target_include_directories(tpm2
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
diff --git a/include/tpm2_private.h b/include/tpm2_private.h
index d5461da..17e925c 100644
--- a/include/tpm2_private.h
+++ b/include/tpm2_private.h
@@ -116,4 +116,12 @@
int tpm2_fifo_read_chunk(uint16_t tpm_reg, uint8_t len, void *val);
+/* HAS_LIB_TIMER is set if a standard library (e.g. POSIX) timer supplies
+ * the timeout functions, rather than being passed explicitly to the TPM
+ * library.
+ */
+#ifdef HAS_LIB_TIMER
+extern const struct tpm_timeout_ops tpm_lib_timeout_ops;
+#endif
+
#endif /* TPM2_PRIVATE_H */
diff --git a/src/timer/posix_timer_ops.c b/src/timer/posix_timer_ops.c
new file mode 100644
index 0000000..96f7d0d
--- /dev/null
+++ b/src/timer/posix_timer_ops.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "tpm2.h"
+
+/**
+ * @brief Gets the current time in microseconds using CLOCK_MONOTONIC.
+ *
+ * @return Time in microseconds since system boot (or an unspecified starting point).
+ */
+static uint64_t get_time_us(void)
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (uint64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
+}
+
+/**
+ * @brief Retrieves the current timer value as the lower 32 bits of microseconds.
+ *
+ * @return 32-bit timer value.
+ */
+static uint32_t get_timer_value_impl(void)
+{
+ return (uint32_t)(get_time_us() & 0xFFFFFFFF);
+}
+
+/**
+ * @brief Initializes a timeout by returning the expiration timestamp.
+ *
+ * @param usec Timeout duration in microseconds.
+ * @return Expiration timestamp in microseconds.
+ */
+static uint64_t timeout_init_us_impl(uint32_t usec)
+{
+ return get_time_us() + (uint64_t)usec;
+}
+
+/**
+ * @brief Determines if the specified timeout has elapsed.
+ *
+ * @param expiry_time_us The expiration time from timeout_init_us().
+ * @return true if the timeout has expired, false otherwise.
+ */
+static bool timeout_elapsed_impl(uint64_t expiry_time_us)
+{
+ return get_time_us() >= expiry_time_us;
+}
+
+/**
+ * @brief Global instance of the POSIX-based timer implementation.
+ *
+ */
+const struct tpm_timeout_ops tpm_lib_timeout_ops = {
+ .timeout_init_us = timeout_init_us_impl,
+ .timeout_elapsed = timeout_elapsed_impl
+};
diff --git a/src/tpm2_cmds.c b/src/tpm2_cmds.c
index 5fc7dc4..56fbc55 100644
--- a/src/tpm2_cmds.c
+++ b/src/tpm2_cmds.c
@@ -47,9 +47,16 @@
int err;
tpm_spidev = transport;
if (timeout_ops == NULL) {
+#ifdef HAS_LIB_TIMER
+ tpm_timeout_ops = tpm_lib_timeout_ops;
+#else
+ ERROR("%s: delay_ops required\n", __func__);
return TPM_INVALID_PARAM;
+#endif
}
- tpm_timeout_ops = *timeout_ops;
+ else {
+ tpm_timeout_ops = *timeout_ops;
+ }
interface = tpm_interface_getops(chip_data, locality);
err = interface->request_access(chip_data, locality);