|
64 | 64 | #include <fcntl.h> |
65 | 65 | #include <unistd.h> |
66 | 66 | #include <errno.h> |
| 67 | + #ifdef WOLFTPM_HAL_RESET |
| 68 | + /* GPIO character-device uAPI for optional nRST control */ |
| 69 | + #include <linux/gpio.h> |
| 70 | + #include <time.h> /* nanosleep (usleep is undefined for >= 1s) */ |
| 71 | + #endif |
67 | 72 |
|
68 | 73 | #ifdef WOLFTPM_I2C |
69 | 74 | /* I2C - (Only tested with SLB9673 and ST33 I2C) */ |
|
415 | 420 | return ret; |
416 | 421 | } |
417 | 422 | #endif /* WOLFTPM_I2C */ |
| 423 | + |
| 424 | +#ifdef WOLFTPM_HAL_RESET |
| 425 | + /* Pulse the TPM nRST (active low) via the Linux GPIO char device (raw GPIO |
| 426 | + * v2 uAPI, no libgpiod). Default line: Raspberry Pi ST33 = GPIO24 (pin 18), |
| 427 | + * Nuvoton = GPIO4; override with WOLFTPM_RESET_GPIOCHIP / WOLFTPM_RESET_LINE. */ |
| 428 | + #ifndef WOLFTPM_RESET_GPIOCHIP |
| 429 | + #define WOLFTPM_RESET_GPIOCHIP "/dev/gpiochip0" |
| 430 | + #endif |
| 431 | + #ifndef WOLFTPM_RESET_LINE |
| 432 | + #if defined(WOLFTPM_NUVOTON) |
| 433 | + #define WOLFTPM_RESET_LINE 4 |
| 434 | + #else |
| 435 | + #define WOLFTPM_RESET_LINE 24 |
| 436 | + #endif |
| 437 | + #endif |
| 438 | + #ifndef WOLFTPM_RESET_HOLD_US |
| 439 | + #define WOLFTPM_RESET_HOLD_US 300000 /* reset asserted 300ms */ |
| 440 | + #endif |
| 441 | + #ifndef WOLFTPM_RESET_SETTLE_US |
| 442 | + #define WOLFTPM_RESET_SETTLE_US 1000000 /* TPM boot settle 1s */ |
| 443 | + #endif |
| 444 | + |
| 445 | + /* usleep() is undefined for values >= 1000000 (POSIX); nanosleep has no |
| 446 | + * such limit and handles the 1s settle and any larger override. */ |
| 447 | + static void TPM2_Reset_DelayUs(unsigned long us) |
| 448 | + { |
| 449 | + struct timespec ts; |
| 450 | + ts.tv_sec = (time_t)(us / 1000000UL); |
| 451 | + ts.tv_nsec = (long)((us % 1000000UL) * 1000UL); |
| 452 | + (void)nanosleep(&ts, NULL); |
| 453 | + } |
| 454 | + |
| 455 | + int TPM2_IoCb_Linux_Reset(TPM2_CTX* ctx, void* userCtx) |
| 456 | + { |
| 457 | + int ret = TPM_RC_FAILURE; |
| 458 | + int chipFd, reqFd; |
| 459 | + struct gpio_v2_line_request req; |
| 460 | + struct gpio_v2_line_values vals; |
| 461 | + |
| 462 | + (void)ctx; |
| 463 | + (void)userCtx; |
| 464 | + |
| 465 | + chipFd = open(WOLFTPM_RESET_GPIOCHIP, O_RDONLY); |
| 466 | + if (chipFd < 0) { |
| 467 | + #ifdef DEBUG_WOLFTPM |
| 468 | + printf("TPM Reset: open %s failed (errno %d)\n", |
| 469 | + WOLFTPM_RESET_GPIOCHIP, errno); |
| 470 | + #endif |
| 471 | + return TPM_RC_FAILURE; |
| 472 | + } |
| 473 | + |
| 474 | + /* Acquire the line as an output driven low (assert reset) */ |
| 475 | + XMEMSET(&req, 0, sizeof(req)); |
| 476 | + req.offsets[0] = (unsigned int)WOLFTPM_RESET_LINE; |
| 477 | + req.num_lines = 1; |
| 478 | + req.config.flags = GPIO_V2_LINE_FLAG_OUTPUT; |
| 479 | + req.config.num_attrs = 1; |
| 480 | + req.config.attrs[0].attr.id = GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES; |
| 481 | + req.config.attrs[0].attr.values = 0; /* drive low (assert reset) */ |
| 482 | + req.config.attrs[0].mask = 1; /* applies to line index 0 */ |
| 483 | + XMEMCPY(req.consumer, "wolfTPM-reset", sizeof("wolfTPM-reset")); |
| 484 | + |
| 485 | + if (ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req) < 0 || req.fd < 0) { |
| 486 | + #ifdef DEBUG_WOLFTPM |
| 487 | + printf("TPM Reset: GET_LINE ioctl failed (errno %d)\n", errno); |
| 488 | + #endif |
| 489 | + close(chipFd); |
| 490 | + return TPM_RC_FAILURE; |
| 491 | + } |
| 492 | + close(chipFd); |
| 493 | + reqFd = req.fd; |
| 494 | + |
| 495 | + /* Hold reset asserted, then release (drive high) and let the TPM boot */ |
| 496 | + TPM2_Reset_DelayUs(WOLFTPM_RESET_HOLD_US); |
| 497 | + |
| 498 | + XMEMSET(&vals, 0, sizeof(vals)); |
| 499 | + vals.mask = 1; |
| 500 | + vals.bits = 1; /* drive high = release reset */ |
| 501 | + if (ioctl(reqFd, GPIO_V2_LINE_SET_VALUES_IOCTL, &vals) < 0) { |
| 502 | + #ifdef DEBUG_WOLFTPM |
| 503 | + printf("TPM Reset: SET_VALUES ioctl failed (errno %d)\n", errno); |
| 504 | + #endif |
| 505 | + } |
| 506 | + else { |
| 507 | + ret = TPM_RC_SUCCESS; |
| 508 | + #ifdef DEBUG_WOLFTPM |
| 509 | + printf("TPM Reset: pulsed nRST on %s line %d\n", |
| 510 | + WOLFTPM_RESET_GPIOCHIP, (int)WOLFTPM_RESET_LINE); |
| 511 | + #endif |
| 512 | + } |
| 513 | + |
| 514 | + TPM2_Reset_DelayUs(WOLFTPM_RESET_SETTLE_US); |
| 515 | + close(reqFd); |
| 516 | + |
| 517 | + return ret; |
| 518 | + } |
| 519 | +#endif /* WOLFTPM_HAL_RESET */ |
| 520 | + |
418 | 521 | #endif /* __linux__ */ |
419 | 522 | #endif /* !(WOLFTPM_LINUX_DEV || WOLFTPM_SWTPM || WOLFTPM_WINAPI) */ |
420 | 523 | #endif /* WOLFTPM_INCLUDE_IO_FILE */ |
|
0 commit comments