From 4fbc680d149b09210145a87b610246fe2202e371 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 7 Jan 2026 21:59:05 +0000 Subject: [PATCH 1/2] Update tpm_io_uboot.c --- hal/tpm_io_uboot.c | 55 ++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/hal/tpm_io_uboot.c b/hal/tpm_io_uboot.c index 22cc66e9..752b1db5 100644 --- a/hal/tpm_io_uboot.c +++ b/hal/tpm_io_uboot.c @@ -43,32 +43,49 @@ #if defined(__UBOOT__) #include + #include + #include + #include + + /* Forward declarations */ + struct udevice; + struct tpm_ops; + + /* Get TPM device using driver model */ + static int uboot_get_tpm_dev(struct udevice **dev) + { + return uclass_first_device_err(UCLASS_TPM, dev); + } + + /* Keep track of opened device */ + static struct udevice *g_tpm_dev = NULL; + int TPM2_IoCb_Uboot_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, word16 xferSz, void* userCtx) { - int ret = 0; - struct udevice *dev; + int ret; + struct udevice *dev = NULL; + size_t recv_size = xferSz; + + (void)ctx; + (void)userCtx; /* Get the TPM device */ - if (ret == 0) { - ret = tcg2_platform_get_tpm2(&dev); - if ( ret != 0 || dev == NULL) { - #ifdef DEBUG_WOLFTPM - printf("Failed to get TPM device with error: %d\n", ret); - #endif - return TPM_RC_FAILURE; - } + ret = uboot_get_tpm_dev(&dev); + if (ret != 0 || dev == NULL) { + #ifdef DEBUG_WOLFTPM + printf("Failed to get TPM device: %d\n", ret); + #endif + return TPM_RC_FAILURE; } - /* Transfer the device data using tpm_xfer */ - if (ret == 0) { - ret = tpm_xfer(dev, txBuf, xferSz, rxBuf, &xferSz); - if (ret != 0) { - #ifdef DEBUG_WOLFTPM - printf("tpm_xfer failed with error: %d\n", ret); - #endif - return TPM_RC_FAILURE; - } + /* Use tpm_xfer which handles all the TIS protocol internally */ + ret = tpm_xfer(dev, txBuf, xferSz, rxBuf, &recv_size); + if (ret != 0) { + #ifdef DEBUG_WOLFTPM + printf("TPM xfer failed: %d\n", ret); + #endif + return TPM_RC_FAILURE; } return TPM_RC_SUCCESS; From 1955938612159325826329e1f7e6bb0d1e0f799f Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Thu, 8 Jan 2026 21:27:33 +0000 Subject: [PATCH 2/2] Update to working version of linux dev with swtpm --- hal/tpm_io_uboot.c | 155 ++++++++++++++++++++++++++++++++++++++------- src/tpm2.c | 2 +- 2 files changed, 133 insertions(+), 24 deletions(-) diff --git a/hal/tpm_io_uboot.c b/hal/tpm_io_uboot.c index 752b1db5..2ce68be5 100644 --- a/hal/tpm_io_uboot.c +++ b/hal/tpm_io_uboot.c @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -/* This example shows IO interfaces for U-boot */ +/* This example shows IO interfaces for U-boot using raw SPI */ #include #include @@ -43,53 +43,162 @@ #if defined(__UBOOT__) #include + #include #include #include - #include - /* Forward declarations */ - struct udevice; - struct tpm_ops; - - /* Get TPM device using driver model */ - static int uboot_get_tpm_dev(struct udevice **dev) + /* SPI bus and chip select configuration for TPM + * These can be overridden in user_settings.h or board config */ + #ifndef TPM_SPI_BUS + #define TPM_SPI_BUS 0 + #endif + #ifndef TPM_SPI_CS + #define TPM_SPI_CS 0 + #endif + #ifndef TPM_SPI_MAX_HZ + #define TPM_SPI_MAX_HZ 1000000 /* 1 MHz - safe default */ + #endif + #define TPM_SPI_MODE SPI_MODE_0 /* Mode 0 (CPOL=0, CPHA=0) */ + + /* Maximum SPI frame size */ + #define MAX_SPI_FRAMESIZE 64 + + /* Static SPI device handles */ + static struct udevice *g_spi_bus = NULL; + static struct spi_slave *g_spi_slave = NULL; + static int g_spi_initialized = 0; + + /* Initialize SPI for TPM communication */ + static int uboot_spi_init(void) { - return uclass_first_device_err(UCLASS_TPM, dev); - } + int ret; + + if (g_spi_initialized) { + return 0; /* Already initialized */ + } + + /* Get SPI bus and slave device */ + ret = spi_get_bus_and_cs(TPM_SPI_BUS, TPM_SPI_CS, + &g_spi_bus, &g_spi_slave); + if (ret != 0) { + #ifdef DEBUG_WOLFTPM + printf("Failed to get SPI bus %d cs %d: %d\n", + TPM_SPI_BUS, TPM_SPI_CS, ret); + #endif + return ret; + } + + g_spi_initialized = 1; + + #ifdef DEBUG_WOLFTPM + printf("TPM SPI initialized: bus %d, cs %d\n", TPM_SPI_BUS, TPM_SPI_CS); + #endif - /* Keep track of opened device */ - static struct udevice *g_tpm_dev = NULL; + return 0; + } + /* Raw SPI transfer for wolfTPM TIS layer + * This is called by wolfTPM's TIS implementation for register read/write. + * The txBuf/rxBuf contain TIS-formatted SPI data including the 4-byte header. + */ int TPM2_IoCb_Uboot_SPI(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf, word16 xferSz, void* userCtx) { int ret; - struct udevice *dev = NULL; - size_t recv_size = xferSz; + #ifdef WOLFTPM_CHECK_WAIT_STATE + int timeout = TPM_SPI_WAIT_RETRY; + byte tmp_rx; + #endif (void)ctx; (void)userCtx; - /* Get the TPM device */ - ret = uboot_get_tpm_dev(&dev); - if (ret != 0 || dev == NULL) { + /* Initialize SPI if needed */ + ret = uboot_spi_init(); + if (ret != 0) { + return TPM_RC_FAILURE; + } + + /* Claim the SPI bus */ + ret = spi_claim_bus(g_spi_slave); + if (ret != 0) { #ifdef DEBUG_WOLFTPM - printf("Failed to get TPM device: %d\n", ret); + printf("Failed to claim SPI bus: %d\n", ret); #endif return TPM_RC_FAILURE; } - /* Use tpm_xfer which handles all the TIS protocol internally */ - ret = tpm_xfer(dev, txBuf, xferSz, rxBuf, &recv_size); + #ifdef WOLFTPM_CHECK_WAIT_STATE + /* Send TIS header first (4 bytes) with CS held */ + ret = spi_xfer(g_spi_slave, TPM_TIS_HEADER_SZ * 8, + txBuf, rxBuf, SPI_XFER_BEGIN); if (ret != 0) { #ifdef DEBUG_WOLFTPM - printf("TPM xfer failed: %d\n", ret); + printf("SPI header xfer failed: %d\n", ret); #endif - return TPM_RC_FAILURE; + goto cleanup; + } + + /* Check for wait state - TPM holds ready bit low if busy */ + if ((rxBuf[TPM_TIS_HEADER_SZ - 1] & TPM_TIS_READY_MASK) == 0) { + /* Poll for ready */ + do { + ret = spi_xfer(g_spi_slave, 8, NULL, &tmp_rx, 0); + if (ret != 0) { + break; + } + if (tmp_rx & TPM_TIS_READY_MASK) { + break; + } + } while (--timeout > 0); + + if (timeout <= 0 || ret != 0) { + #ifdef DEBUG_WOLFTPM + printf("SPI wait state timeout\n"); + #endif + /* Deassert CS */ + spi_xfer(g_spi_slave, 0, NULL, NULL, SPI_XFER_END); + ret = TPM_RC_FAILURE; + goto cleanup; + } + } + + /* Transfer remainder of data with CS deasserted at end */ + if (xferSz > TPM_TIS_HEADER_SZ) { + ret = spi_xfer(g_spi_slave, (xferSz - TPM_TIS_HEADER_SZ) * 8, + &txBuf[TPM_TIS_HEADER_SZ], + &rxBuf[TPM_TIS_HEADER_SZ], + SPI_XFER_END); + } else { + /* Just deassert CS if no more data */ + ret = spi_xfer(g_spi_slave, 0, NULL, NULL, SPI_XFER_END); } - return TPM_RC_SUCCESS; + #else + /* No wait state handling - send entire message at once + * This works for Infineon TPMs (SLB9670/SLB9672) which guarantee + * no wait states */ + ret = spi_xfer(g_spi_slave, xferSz * 8, txBuf, rxBuf, + SPI_XFER_BEGIN | SPI_XFER_END); + #endif /* WOLFTPM_CHECK_WAIT_STATE */ + + if (ret != 0) { + #ifdef DEBUG_WOLFTPM + printf("SPI xfer failed: %d\n", ret); + #endif + ret = TPM_RC_FAILURE; + } else { + ret = TPM_RC_SUCCESS; + } + + #ifdef WOLFTPM_CHECK_WAIT_STATE + cleanup: + #endif + spi_release_bus(g_spi_slave); + + return ret; } + #endif /* __UBOOT__ */ #endif /* WOLFTPM_LINUX_DEV || WOLFTPM_SWTPM || WOLFTPM_WINAPI */ #endif /* WOLFTPM_INCLUDE_IO_FILE */ diff --git a/src/tpm2.c b/src/tpm2.c index 1e998278..b86aa904 100644 --- a/src/tpm2.c +++ b/src/tpm2.c @@ -729,7 +729,7 @@ TPM_RC TPM2_Cleanup(TPM2_CTX* ctx) } #endif /* !WOLFTPM2_NO_WOLFCRYPT */ -#ifdef WOLFTPM_LINUX_DEV +#if defined(WOLFTPM_LINUX_DEV) && !defined(__UBOOT__) if (ctx->fd >= 0) close(ctx->fd); #endif