mirror of https://github.com/wolfSSL/wolfTPM.git
Add optional TPM nRST reset HAL and document ST33-on-Pi wiring
parent
30562ce46a
commit
a2345b471a
|
|
@ -99,6 +99,10 @@ jobs:
|
|||
# STMicro ST33KTPM2
|
||||
- name: st33ktpm2 firmware
|
||||
wolftpm_config: --enable-st33 --enable-firmware --disable-fwtpm
|
||||
# HAL nRST reset control (compile-only, no GPIO hardware in CI)
|
||||
- name: hal-reset
|
||||
wolftpm_config: --enable-st33 --enable-hal-reset --disable-fwtpm
|
||||
test_command: "true"
|
||||
# SPDM + Nuvoton (compile-only, no hardware in CI)
|
||||
- name: spdm-nuvoton
|
||||
wolfssl_config: --enable-wolftpm --enable-ecc --enable-sha384 --enable-aesgcm --enable-hkdf --enable-sp
|
||||
|
|
|
|||
|
|
@ -405,6 +405,8 @@ make
|
|||
|
||||
Note: The `--enable-firmware` option enables firmware upgrade support for ST33 TPMs. This adds the `st33_fw_update` example tool for performing firmware updates.
|
||||
|
||||
Raspberry Pi wiring: ST33KTPM2X SPI is on `/dev/spidev0.0` with `nRST` (active low) on GPIO24 (pin 18); Nuvoton uses GPIO4. Optionally drive nRST from code with `--enable-hal-reset` and `TPM2_IoCb_Reset()` (see `hal/README.md`).
|
||||
|
||||
### Building Microchip ATTPM20
|
||||
|
||||
Build wolfTPM:
|
||||
|
|
|
|||
29
configure.ac
29
configure.ac
|
|
@ -474,6 +474,34 @@ then
|
|||
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_ST33"
|
||||
fi
|
||||
|
||||
# Optional TPM hardware reset (nRST) HAL control via Linux GPIO char device.
|
||||
# Accepts an optional GPIO line number (default ST33 GPIO24 / Pi pin 18, Nuvoton GPIO4).
|
||||
AC_ARG_ENABLE([hal-reset],
|
||||
[AS_HELP_STRING([--enable-hal-reset@<:@=LINE@:>@],[Enable TPM nRST reset HAL (optional GPIO line; default ST33 GPIO24, Nuvoton GPIO4) (default: disabled)])],
|
||||
[ ENABLED_HAL_RESET=$enableval ],
|
||||
[ ENABLED_HAL_RESET=no ]
|
||||
)
|
||||
if test "x$ENABLED_HAL_RESET" != "xno"
|
||||
then
|
||||
# The reset HAL implementation (hal/tpm_io.c) only builds for the SPI/I2C
|
||||
# example HAL, not the native kernel (/dev/tpm0) or swtpm transports, so
|
||||
# reject those combinations rather than report "yes" with no callable API.
|
||||
# Note swtpm is the default on Linux x86_64/aarch64, so the hardware reset
|
||||
# HAL requires explicitly selecting a hardware interface (--enable-spi/-i2c).
|
||||
if test "x$ENABLED_DEVTPM" = "xyes" || test "x$ENABLED_SWTPM" = "xyes" || test "x$ENABLED_SWTPM" = "xuart"
|
||||
then
|
||||
AC_MSG_ERROR([--enable-hal-reset needs the SPI/I2C hardware HAL; it is not available with the swtpm simulator (default on Linux x86_64/aarch64) or --enable-devtpm. Select a hardware interface, e.g. --enable-spi or --enable-i2c.])
|
||||
fi
|
||||
AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_HAL_RESET"
|
||||
case "x$ENABLED_HAL_RESET" in
|
||||
xyes) ;;
|
||||
x|x*[[!0-9]]*)
|
||||
AC_MSG_ERROR([--enable-hal-reset=LINE requires a numeric GPIO line number (e.g. --enable-hal-reset=24).]) ;;
|
||||
*) AM_CFLAGS="$AM_CFLAGS -DWOLFTPM_RESET_LINE=$ENABLED_HAL_RESET" ;;
|
||||
esac
|
||||
ENABLED_HAL_RESET=yes
|
||||
fi
|
||||
|
||||
# Microchip ATTPM20
|
||||
AC_ARG_ENABLE([mchp],,
|
||||
[ ENABLED_MCHP=$enableval ],
|
||||
|
|
@ -1132,6 +1160,7 @@ if test "x$ENABLED_SWTPM" = "xyes"; then
|
|||
fi
|
||||
echo " * WINAPI: $ENABLED_WINAPI"
|
||||
echo " * TIS/SPI Check Wait State: $ENABLED_CHECKWAITSTATE"
|
||||
echo " * HAL Reset (nRST GPIO): $ENABLED_HAL_RESET"
|
||||
|
||||
echo " * Infineon SLB967X $ENABLED_INFINEON"
|
||||
echo " * STM ST33: $ENABLED_ST"
|
||||
|
|
|
|||
|
|
@ -98,15 +98,17 @@ effect. The reset pin must be connected and controllable by the host.
|
|||
to a host-controllable GPIO. Without reset pin control, SPDM mode changes
|
||||
cannot be applied and recovery from SPDM-only mode is not possible.
|
||||
|
||||
### Raspberry Pi Example (GPIO 4)
|
||||
The reset line is board specific. On a Raspberry Pi, Nuvoton uses GPIO4 and the
|
||||
ST33KTPM uses GPIO24 (pin 18); confirm your wiring before toggling.
|
||||
|
||||
```bash
|
||||
# Assert reset low, wait, release high, wait for TPM startup
|
||||
# Assert reset low, release high, wait for TPM startup (Nuvoton GPIO4 shown)
|
||||
gpioset gpiochip0 4=0 && sleep 0.1 && gpioset gpiochip0 4=1 && sleep 2
|
||||
# ST33: use line 24 instead of 4
|
||||
```
|
||||
|
||||
Other platforms will use their own GPIO control mechanism. The key requirement
|
||||
is toggling the TPM reset line (active low) with sufficient hold time.
|
||||
wolfTPM can also drive this from code: build with `--enable-hal-reset` and call
|
||||
`TPM2_IoCb_Reset()` (default line: ST33 GPIO24, Nuvoton GPIO4). See `hal/README.md`.
|
||||
|
||||
## Automated Test Suite
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,13 @@ int TPM2_IoCb(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf,
|
|||
* `WOLFTPM_CHECK_WAIT_STATE`: Enables check of the wait state during a SPI transaction. Most TPM 2.0 chips require this and typically only require 0-2 wait cycles depending on the command. Only the Infineon TPM's guarantee no wait states.
|
||||
* `WOLFTPM_ADV_IO`: Enables advanced IO callback mode that includes TIS register and read/write flag. This is requires for I2C, but can be used with SPI also.
|
||||
* `WOLFTPM_DEBUG_IO`: Enable logging of the IO (if using the example HAL).
|
||||
* `WOLFTPM_HAL_RESET`: Optional TPM hardware reset (nRST) control in the example HAL (`--enable-hal-reset`). On Linux, `TPM2_IoCb_Reset(&dev->ctx, userCtx)` pulses nRST (active low) via the GPIO char device (raw GPIO v2 uAPI, no libgpiod).
|
||||
|
||||
## TPM reset (nRST) HAL macros (when `WOLFTPM_HAL_RESET` is set)
|
||||
|
||||
* `WOLFTPM_RESET_GPIOCHIP`: GPIO char device. Default: `/dev/gpiochip0`
|
||||
* `WOLFTPM_RESET_LINE`: GPIO line wired to nRST. Default: ST33 = `24` (GPIO24, Pi pin 18), Nuvoton = `4` (GPIO4). Also settable via `--enable-hal-reset=<line>`.
|
||||
* `WOLFTPM_RESET_HOLD_US` / `WOLFTPM_RESET_SETTLE_US`: reset hold / post-reset settle time (us). Defaults: `300000` / `1000000`.
|
||||
|
||||
## Additional Compiler macros
|
||||
|
||||
|
|
|
|||
23
hal/tpm_io.c
23
hal/tpm_io.c
|
|
@ -239,6 +239,29 @@ int TPM2_IoCb(TPM2_CTX* ctx, const BYTE* txBuf, BYTE* rxBuf,
|
|||
}
|
||||
|
||||
#endif /* WOLFTPM_ADV_IO */
|
||||
|
||||
#ifdef WOLFTPM_HAL_RESET
|
||||
/* Pulse the TPM hardware reset (nRST) line to reset the TPM. Dispatches to the
|
||||
* platform implementation. Returns TPM_RC_SUCCESS on success. */
|
||||
int TPM2_IoCb_Reset(TPM2_CTX* ctx, void* userCtx)
|
||||
{
|
||||
int ret;
|
||||
#if defined(__linux__)
|
||||
ret = TPM2_IoCb_Linux_Reset(ctx, userCtx);
|
||||
#else
|
||||
/* No reset HAL for this OS - return NOT_COMPILED_IN so callers can tell it
|
||||
* apart from a genuine reset failure (TPM_RC_FAILURE) on a supported OS. */
|
||||
(void)ctx;
|
||||
(void)userCtx;
|
||||
ret = NOT_COMPILED_IN;
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("TPM reset HAL not implemented for this platform\n");
|
||||
#endif
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLFTPM_HAL_RESET */
|
||||
|
||||
#endif /* !(WOLFTPM_LINUX_DEV || WOLFTPM_SWTPM || WOLFTPM_WINAPI) */
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
|||
|
|
@ -145,6 +145,15 @@ WOLFTPM_LOCAL int TPM2_IoCb_FwTPM(TPM2_CTX* ctx, int isRead, word32 addr,
|
|||
byte* buf, word16 size, void* userCtx);
|
||||
#endif
|
||||
|
||||
#ifdef WOLFTPM_HAL_RESET
|
||||
/* Optional TPM hardware reset (nRST) control. Pulses the reset line to reset
|
||||
* the TPM. Enable with --enable-hal-reset (-DWOLFTPM_HAL_RESET). */
|
||||
WOLFTPM_API int TPM2_IoCb_Reset(TPM2_CTX* ctx, void* userCtx);
|
||||
#if defined(__linux__)
|
||||
WOLFTPM_LOCAL int TPM2_IoCb_Linux_Reset(TPM2_CTX* ctx, void* userCtx);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* WOLFTPM_EXAMPLE_HAL */
|
||||
#endif /* !(WOLFTPM_LINUX_DEV || WOLFTPM_SWTPM || WOLFTPM_WINAPI) */
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,11 @@
|
|||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#ifdef WOLFTPM_HAL_RESET
|
||||
/* GPIO character-device uAPI for optional nRST control */
|
||||
#include <linux/gpio.h>
|
||||
#include <time.h> /* nanosleep (usleep is undefined for >= 1s) */
|
||||
#endif
|
||||
|
||||
#ifdef WOLFTPM_I2C
|
||||
/* I2C - (Only tested with SLB9673 and ST33 I2C) */
|
||||
|
|
@ -415,6 +420,110 @@
|
|||
return ret;
|
||||
}
|
||||
#endif /* WOLFTPM_I2C */
|
||||
|
||||
#ifdef WOLFTPM_HAL_RESET
|
||||
/* Pulse the TPM nRST (active low) via the Linux GPIO char device (raw GPIO
|
||||
* v2 uAPI, no libgpiod). Default line: Raspberry Pi ST33 = GPIO24 (pin 18),
|
||||
* Nuvoton = GPIO4; override with WOLFTPM_RESET_GPIOCHIP / WOLFTPM_RESET_LINE. */
|
||||
#ifndef WOLFTPM_RESET_GPIOCHIP
|
||||
#define WOLFTPM_RESET_GPIOCHIP "/dev/gpiochip0"
|
||||
#endif
|
||||
#ifndef WOLFTPM_RESET_LINE
|
||||
#if defined(WOLFTPM_NUVOTON)
|
||||
#define WOLFTPM_RESET_LINE 4
|
||||
#else
|
||||
#define WOLFTPM_RESET_LINE 24
|
||||
#endif
|
||||
#endif
|
||||
#ifndef WOLFTPM_RESET_HOLD_US
|
||||
#define WOLFTPM_RESET_HOLD_US 300000 /* reset asserted 300ms */
|
||||
#endif
|
||||
#ifndef WOLFTPM_RESET_SETTLE_US
|
||||
#define WOLFTPM_RESET_SETTLE_US 1000000 /* TPM boot settle 1s */
|
||||
#endif
|
||||
|
||||
/* usleep() is undefined for values >= 1000000 (POSIX); nanosleep has no
|
||||
* such limit and handles the 1s settle and any larger override. */
|
||||
static void TPM2_Reset_DelayUs(unsigned long us)
|
||||
{
|
||||
struct timespec ts;
|
||||
ts.tv_sec = (time_t)(us / 1000000UL);
|
||||
ts.tv_nsec = (long)((us % 1000000UL) * 1000UL);
|
||||
(void)nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
/* Note: this reset HAL is only compile-checked in CI (no GPIO hardware or
|
||||
* gpio-sim there); the open/GET_LINE/SET_VALUES flow, the hold/settle
|
||||
* timing, and the fd lifecycle are functionally regression-verified on real
|
||||
* hardware - the ST33 on a Raspberry Pi 5, nRST wired to GPIO24 (pin 18). */
|
||||
int TPM2_IoCb_Linux_Reset(TPM2_CTX* ctx, void* userCtx)
|
||||
{
|
||||
int ret = TPM_RC_FAILURE;
|
||||
int chipFd, reqFd;
|
||||
struct gpio_v2_line_request req;
|
||||
struct gpio_v2_line_values vals;
|
||||
|
||||
(void)ctx;
|
||||
(void)userCtx;
|
||||
|
||||
chipFd = open(WOLFTPM_RESET_GPIOCHIP, O_RDONLY);
|
||||
if (chipFd < 0) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("TPM Reset: open %s failed (errno %d)\n",
|
||||
WOLFTPM_RESET_GPIOCHIP, errno);
|
||||
#endif
|
||||
return TPM_RC_FAILURE;
|
||||
}
|
||||
|
||||
/* Acquire the line as an output driven low (assert reset) */
|
||||
XMEMSET(&req, 0, sizeof(req));
|
||||
req.offsets[0] = (unsigned int)WOLFTPM_RESET_LINE;
|
||||
req.num_lines = 1;
|
||||
req.config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
|
||||
req.config.num_attrs = 1;
|
||||
req.config.attrs[0].attr.id = GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES;
|
||||
req.config.attrs[0].attr.values = 0; /* drive low (assert reset) */
|
||||
req.config.attrs[0].mask = 1; /* applies to line index 0 */
|
||||
XMEMCPY(req.consumer, "wolfTPM-reset", sizeof("wolfTPM-reset"));
|
||||
|
||||
if (ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req) < 0 || req.fd < 0) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("TPM Reset: GET_LINE ioctl failed (errno %d)\n", errno);
|
||||
#endif
|
||||
close(chipFd);
|
||||
return TPM_RC_FAILURE;
|
||||
}
|
||||
close(chipFd);
|
||||
reqFd = req.fd;
|
||||
|
||||
/* Hold reset asserted, then release (drive high) and let the TPM boot */
|
||||
TPM2_Reset_DelayUs(WOLFTPM_RESET_HOLD_US);
|
||||
|
||||
XMEMSET(&vals, 0, sizeof(vals));
|
||||
vals.mask = 1;
|
||||
vals.bits = 1; /* drive high = release reset */
|
||||
if (ioctl(reqFd, GPIO_V2_LINE_SET_VALUES_IOCTL, &vals) < 0) {
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("TPM Reset: SET_VALUES ioctl failed (errno %d)\n", errno);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
ret = TPM_RC_SUCCESS;
|
||||
#ifdef DEBUG_WOLFTPM
|
||||
printf("TPM Reset: pulsed nRST on %s line %d\n",
|
||||
WOLFTPM_RESET_GPIOCHIP, (int)WOLFTPM_RESET_LINE);
|
||||
#endif
|
||||
/* Only wait for the TPM to settle after a successful release; on a
|
||||
* failed release the delay would just stall the error path. */
|
||||
TPM2_Reset_DelayUs(WOLFTPM_RESET_SETTLE_US);
|
||||
}
|
||||
|
||||
close(reqFd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLFTPM_HAL_RESET */
|
||||
|
||||
#endif /* __linux__ */
|
||||
#endif /* !(WOLFTPM_LINUX_DEV || WOLFTPM_SWTPM || WOLFTPM_WINAPI) */
|
||||
#endif /* WOLFTPM_INCLUDE_IO_FILE */
|
||||
|
|
|
|||
Loading…
Reference in New Issue