Skip to content

Commit 8946234

Browse files
author
Dimitar Tomov
committed
Added GPIO examples for Nuvoton NPCT75x TPM 2.0 Modules
* Added GPIO configuration logic * Added more NV attributes per Nuvoton specification * Fixes from testing on the hardware * Improvements on tpm2.h definitions * Fixes after vendor feedback * Updated the examples README with NPCT75x information and ST33 differences Signed-off-by: Dimitar Tomov <dimi@wolfssl.com>
1 parent a02a744 commit 8946234

7 files changed

Lines changed: 349 additions & 22 deletions

File tree

examples/README.md

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The PKCS #7 and TLS examples require generating CSR's and signing them using a t
88

99
To enable parameter encryption use `-aes` for AES-CFB mode or `-xor` for XOR mode. Only some TPM commands / responses support parameter encryption. If the TPM2_ API has .flags `CMD_FLAG_ENC2` or `CMD_FLAG_DEC2` set then the command will use parameter encryption / decryption.
1010

11-
There are some vendor specific examples, like the TPM 2.0 extra GPIO examples for ST33.
11+
There are some vendor specific examples, like the TPM 2.0 extra GPIO examples for ST33 and NPCT75x.
1212

1313
## Native API Test
1414

@@ -433,13 +433,13 @@ Some TPM 2.0 modules have extra I/O functionalities and additional GPIO that the
433433

434434
Currently, the GPIO control examples support only ST33 TPM 2.0 modules.
435435

436-
There are three examples available: `gpio/gpio_config`, `gpio/gpio_set`, `gpio/gpio_read`.
436+
There are four examples available: `gpio/gpio_config` for ST33 and `gpio/gpio_nuvoton` for NPCT75x. Once configured, a GPIO can be controlled using `gpio/gpio_set` and `gpio/gpio_read`.
437437

438438
Every example has a help option `-h`. Please consult with `gpio_config -h` about the various GPIO modes.
439439

440-
Demo usage is available, when no parameters are supplied. Then, GPIO 0 is used in output mode.
441-
440+
Demo usage is available, when no parameters are supplied. Recommended is to use carefully selected options, because GPIO interact with the physical world.
442441

442+
ST33 supports 6 modes, information from `gpio/gpio_config` below:
443443
```
444444
445445
examples/gpio/gpio_config -h
@@ -458,8 +458,25 @@ Example usage, without parameters, configures GPIO0 as input with a pull down.
458458
459459
```
460460

461+
NPCT75x supports 3 output modes, information from `gpio/gpio_nuvoton` below:
462+
463+
```
464+
xpected usage:
465+
./examples/gpio/gpio_config [num] [mode]
466+
* num is a GPIO number between 3 and 4 (default 3)
467+
* mode is either push-pull, open-drain or open-drain with pull-up
468+
1. pushpull - output in push pull configuration
469+
2. opendrain - output in open drain configuration
470+
3. pullup - output in open drain with pull-up enabled
471+
4. unconfig - delete NV index for GPIO access
472+
Example usage, without parameters, configures GPIO3 as push-pull output.
473+
```
474+
475+
Please note that NPCT75x GPIO numbering starts from GPIO3, while ST33 starts from GPIO0.
476+
461477
Example usage for configuring a GPIO to output can be found below:
462478

479+
- ST33
463480
```
464481
465482
$ ./examples/gpio/gpio_config
@@ -476,9 +493,24 @@ GPIO0 set to high level
476493
477494
```
478495

479-
Switching a GPIO configuration is seamless, because gpio/config takes care of deleting existing NV Index, so a new GPIO configuration can be chosen.
496+
- NPCT75xx
497+
498+
```
499+
pi@raspberrypi:~/wolftpm $ sudo ./examples/gpio/gpio_nuvoton 4 1
500+
Example for GPIO configuration of a NPTC7xx TPM 2.0 module
501+
GPIO number: 4
502+
GPIO mode: 1
503+
wolfTPM2_Init: success
504+
First, the current NPCT7xx config will be read
505+
then modified with the new GPIO configuration
506+
Successfully read the current NPCT7xx configuration
507+
NTC2_PreConfig success
508+
NV Index for GPIO access created
509+
```
510+
511+
Switching a GPIO configuration is seamless. Because for ST33 `gpio/gpio_config` takes care of deleting existing NV Index, so a new GPIO configuration can be chosen. And for NPCT75xx `gpio/gpio_nuvoton` can reconfigure any GPIO without deleteing the creating NV index.
480512

481-
Example usage for configuring a GPIO as input with a pulp-up can be found below:
513+
Example usage for configuring a GPIO as input with a pull-up on ST33 can be found below:
482514

483515
```
484516

examples/gpio/gpio.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,24 @@
2626
extern "C" {
2727
#endif
2828

29-
#if defined(WOLFTPM_ST33) || defined(WOLFTPM_AUTODETECT)
29+
#if defined(WOLFTPM_ST33) || defined(WOLFTPM_NUVOTON) || defined(WOLFTPM_AUTODETECT)
3030
#define GPIO_NUM_MIN TPM_GPIO_A
31-
#define GPIO_NUM_MAX (TPM_GPIO_COUNT-1) /* see wolftpm/tpm2.h */
31+
#define GPIO_NUM_MAX TPM_GPIO_A+TPM_GPIO_COUNT-1 /* see wolftpm/tpm2.h */
32+
#endif
33+
34+
#ifdef WOLFTPM_NUVOTON
35+
/* Nuvoton GPIO Modes - only output */
36+
#define NUVOTON_GPIO_MODE_PUSHPULL 1
37+
#define NUVOTON_GPIO_MODE_OPENDRAIN 2
38+
#define NUVOTON_GPIO_MODE_PULLUP 3
39+
#define NUVOTON_GPIO_MODE_UNCONFIG 4 /* Not a real GPIO mode, deleting NV index */
40+
#define NUVOTON_GPIO_MODE_MAX 4
3241
#endif
3342

3443
int TPM2_GPIO_Config_Example(void* userCtx, int argc, char *argv[]);
3544
int TPM2_GPIO_Read_Example(void* userCtx, int argc, char *argv[]);
3645
int TPM2_GPIO_Set_Example(void* userCtx, int argc, char *argv[]);
46+
int TPM2_GPIO_Nuvoton_Example(void* userCtx, int argc, char *argv[]);
3747

3848
#ifdef __cplusplus
3949
} /* extern "C" */

examples/gpio/gpio_nuvoton.c

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
/* gpio_nuvoton.c
2+
*
3+
* Copyright (C) 2006-2021 wolfSSL Inc.
4+
*
5+
* This file is part of wolfTPM.
6+
*
7+
* wolfTPM is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 2 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* wolfTPM is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20+
*/
21+
22+
/* This examples demonstrates the use of GPIO available on
23+
* Nuvoton TPM 2.0 Modules, e.g. NPCT750 with FW version 7.2.3
24+
*/
25+
26+
#include <wolftpm/tpm2_wrap.h>
27+
28+
#if defined(WOLFTPM_NUVOTON)
29+
30+
#include <examples/gpio/gpio.h>
31+
#include <examples/tpm_io.h>
32+
#include <examples/tpm_test.h>
33+
34+
#include <stdio.h>
35+
#include <stdlib.h> /* atoi */
36+
37+
38+
/******************************************************************************/
39+
/* --- BEGIN TPM2.0 GPIO Configuration example -- */
40+
/******************************************************************************/
41+
42+
static void usage(void)
43+
{
44+
printf("Expected usage:\n");
45+
printf("./examples/gpio/gpio_config [num] [mode]\n");
46+
printf("* num is a GPIO number between 3 and 4 (default %d)\n", GPIO_NUM_MIN);
47+
printf("* mode is either push-pull, open-drain or open-drain with pull-up\n");
48+
printf("\t1. pushpull - output in push pull configuration\n");
49+
printf("\t2. opendrain - output in open drain configuration\n");
50+
printf("\t3. pullup - output in open drain with pull-up enabled\n");
51+
printf("\t4. unconfig - delete NV index for GPIO access\n");
52+
printf("Example usage, without parameters, configures GPIO3 as push-pull output.\n");
53+
}
54+
55+
int TPM2_GPIO_Nuvoton_Example(void* userCtx, int argc, char *argv[])
56+
{
57+
int rc = -1;
58+
WOLFTPM2_DEV dev;
59+
WOLFTPM2_CAPS caps;
60+
WOLFTPM2_NV nv;
61+
WOLFTPM2_HANDLE parent;
62+
TPM_HANDLE nvIndex = TPM_NV_GPIO_SPACE;
63+
word32 nvAttributes;
64+
int gpioNum = 0;
65+
int gpioMode = NUVOTON_GPIO_MODE_PUSHPULL;
66+
/* Nuvoton specific structures */
67+
CFG_STRUCT newConfig;
68+
NTC2_GetConfig_Out getConfig;
69+
NTC2_PreConfig_In preConfig;
70+
71+
if (argc >= 2) {
72+
if (XSTRNCMP(argv[1], "-?", 2) == 0 ||
73+
XSTRNCMP(argv[1], "-h", 2) == 0 ||
74+
XSTRNCMP(argv[1], "--help", 6) == 0) {
75+
usage();
76+
return 0;
77+
}
78+
if (argc == 3) {
79+
gpioMode = atoi(argv[2]);
80+
if (gpioMode > NUVOTON_GPIO_MODE_MAX) {
81+
printf("GPIO mode is out of range (1-3)\n");
82+
usage();
83+
goto exit_badargs;
84+
}
85+
/* Preparing to process next argument */
86+
argc--;
87+
}
88+
if (argc == 2) {
89+
gpioNum = atoi(argv[1]);
90+
if (gpioNum < GPIO_NUM_MIN || gpioNum > GPIO_NUM_MAX) {
91+
printf("GPIO is out of range (%d-%d)\n", GPIO_NUM_MIN, GPIO_NUM_MAX);
92+
usage();
93+
goto exit_badargs;
94+
}
95+
nvIndex = TPM_NV_GPIO_SPACE + (gpioNum-GPIO_NUM_MIN);
96+
/* all arguments processed */
97+
}
98+
}
99+
else if (argc == 1) {
100+
/* Default behavior, without arguments: GPIO 3 as pushpull output */
101+
gpioMode = NUVOTON_GPIO_MODE_PUSHPULL;
102+
gpioNum = GPIO_NUM_MIN;
103+
}
104+
else {
105+
printf("Incorrect arguments\n");
106+
usage();
107+
goto exit_badargs;
108+
}
109+
110+
printf("Example for GPIO configuration of a NPTC7xx TPM 2.0 module\n");
111+
112+
printf("GPIO number: %d\n", gpioNum);
113+
printf("GPIO mode: %d\n", gpioMode);
114+
115+
rc = wolfTPM2_Init(&dev, TPM2_IoCb, userCtx);
116+
if (rc != TPM_RC_SUCCESS) {
117+
printf("wolfTPM2_Init failed 0x%x: %s\n", rc, TPM2_GetRCString(rc));
118+
goto exit;
119+
}
120+
printf("wolfTPM2_Init: success\n");
121+
122+
/* Get TPM capabilities, to discover the TPM vendor */
123+
rc = wolfTPM2_GetCapabilities(&dev, &caps);
124+
if (rc != TPM_RC_SUCCESS) {
125+
printf("wolfTPM2_GetCapabilities failed 0x%x: %s\n", rc, TPM2_GetRCString(rc));
126+
}
127+
128+
/* Confirm the TPM vendor */
129+
if (caps.mfg != TPM_MFG_NUVOTON) {
130+
printf("TPM model mismatch. This example demonstrates extra GPIO on NPCT7xx.\n");
131+
goto exit;
132+
}
133+
134+
#if 0 /* TODO: Satisfy NV_POLICY_DELETE */
135+
#ifdef DEBUG_WOLFTPM
136+
printf("Trying to remove NV index 0x%8.8X used for GPIO\n", nvIndex);
137+
#endif
138+
/* Make sure NV Index for this GPIO is cleared before use
139+
* This way we make sure a new GPIO config can be set
140+
*/
141+
rc = wolfTPM2_NVDelete(&dev, TPM_RH_PLATFORM, nvIndex);
142+
if (rc == TPM_RC_SUCCESS) {
143+
printf("NV index undefined\n");
144+
}
145+
else if (rc == (TPM_RC_HANDLE | TPM_RC_2)) {
146+
printf("NV Index is available for GPIO use\n");
147+
}
148+
else {
149+
printf("wolfTPM2_NVDelete failed 0x%x: %s\n", rc, TPM2_GetRCString(rc));
150+
}
151+
#endif
152+
/* GPIO un-configuration is done using NVDelete, no further action needed */
153+
if (gpioMode == NUVOTON_GPIO_MODE_UNCONFIG) {
154+
printf("Reconfiguration does not require to NV index deletion\n");
155+
goto exit;
156+
}
157+
158+
printf("First, the current NPCT7xx config will be read\n" \
159+
"then modified with the new GPIO configuration\n");
160+
161+
XMEMSET(&newConfig, 0, sizeof(newConfig));
162+
XMEMSET(&getConfig, 0, sizeof(getConfig));
163+
rc = TPM2_NTC2_GetConfig(&getConfig);
164+
if (rc != TPM_RC_SUCCESS) {
165+
printf("NTC2_getConfig failed 0x%x: %s\n", rc, TPM2_GetRCString(rc));
166+
goto exit;
167+
}
168+
printf("Successfully read the current NPCT7xx configuration\n");
169+
XMEMCPY(&newConfig, &getConfig.preConfig, sizeof(newConfig));
170+
171+
#ifdef DEBUG_WOLFTPM
172+
printf("getConfig CFG_CONFIG structure:\n");
173+
TPM2_PrintBin((byte*)&getConfig.preConfig, sizeof(getConfig.preConfig));
174+
#endif
175+
176+
/* Prepare GPIO configuration according to Nuvoton requirements */
177+
if(gpioMode == NUVOTON_GPIO_MODE_PUSHPULL) {
178+
newConfig.GpioPushPull |= (1 << gpioNum);
179+
}
180+
else {
181+
/* NUVOTON_GPIO_MODE_OPENDRAIN || NUVOTON_GPIO_MODE_PULLUP */
182+
newConfig.GpioPushPull &= ~(1 << gpioNum);
183+
}
184+
185+
/* Set pull-up to disabled by default, configure below only if requested */
186+
newConfig.GpioPullUp &= ~(1 << gpioNum);
187+
188+
/* Extra step for open-drain with pull-up mode */
189+
if (gpioMode == NUVOTON_GPIO_MODE_PULLUP) {
190+
newConfig.GpioPullUp &= ~(1 << gpioNum);
191+
}
192+
193+
#ifdef DEBUG_WOLFTPM
194+
printf("newConfig CFG_CONFIG structure:\n");
195+
TPM2_PrintBin((byte*)&newConfig, sizeof(newConfig));
196+
#endif
197+
198+
/* Configuring a TPM GPIO requires a PLATFORM authorization. Afterwards,
199+
* using that GPIO is up to the user. Therefore, NV Indexes are operated
200+
* using OWNER authorization. See below NVCreateAuth.
201+
*/
202+
XMEMSET(&preConfig, 0, sizeof(preConfig));
203+
preConfig.authHandle = TPM_RH_PLATFORM;
204+
XMEMCPY(&preConfig.preConfig, &newConfig, sizeof(newConfig));
205+
rc = TPM2_NTC2_PreConfig(&preConfig);
206+
if (rc != TPM_RC_SUCCESS) {
207+
printf("TPM2_SetCommandSet failed 0x%x: %s\n", rc, TPM2_GetRCString(rc));
208+
goto exit;
209+
}
210+
printf("NTC2_PreConfig success\n");
211+
212+
/* Configure NV Index for access to this GPIO */
213+
XMEMSET(&nv, 0, sizeof(nv));
214+
XMEMSET(&parent, 0, sizeof(parent));
215+
/* Initial NV attributes */
216+
parent.hndl = TPM_RH_PLATFORM;
217+
rc = wolfTPM2_GetNvAttributesTemplate(parent.hndl, &nvAttributes);
218+
/* Add NV attributes required by Nuvoton specification */
219+
nvAttributes |= (TPMA_NV_PLATFORMCREATE | TPMA_NV_POLICY_DELETE);
220+
nvAttributes |= (TPM_NT_ORDINARY & TPMA_NV_TPM_NT);
221+
if (rc != 0) {
222+
printf("Setting NV attributes failed\n");
223+
goto exit;
224+
}
225+
#ifdef DEBUG_WOLFTPM
226+
printf("nvAttributes = 0x%8.8X\n", nvAttributes);
227+
#endif
228+
229+
/* Define NV Index for GPIO */
230+
rc = wolfTPM2_NVCreateAuth(&dev, &parent, &nv, nvIndex, nvAttributes,
231+
sizeof(BYTE), (byte*)gNvAuth, sizeof(gNvAuth)-1);
232+
if (rc != 0 && rc != TPM_RC_NV_DEFINED) {
233+
printf("Creating NV Index for GPIO acccess failed\n");
234+
goto exit;
235+
}
236+
printf("NV Index for GPIO access created\n");
237+
238+
exit:
239+
240+
wolfTPM2_Cleanup(&dev);
241+
242+
exit_badargs:
243+
244+
return rc;
245+
}
246+
247+
/******************************************************************************/
248+
/* --- END TPM2.0 GPIO Configuration example -- */
249+
/******************************************************************************/
250+
#endif /* WOLFTPM_NUVOTON */
251+
252+
#ifndef NO_MAIN_DRIVER
253+
int main(int argc, char *argv[])
254+
{
255+
int rc = -1;
256+
257+
#if defined(WOLFTPM_NUVOTON)
258+
rc = TPM2_GPIO_Nuvoton_Example(NULL, argc, argv);
259+
#else
260+
printf("This example demonstrates extra GPIO on Nuvoton TPM 2.0 modules.\n");
261+
(void)argc;
262+
(void)argv;
263+
#endif /* WOLFTPM_NUVOTON */
264+
265+
return rc;
266+
}
267+
#endif

0 commit comments

Comments
 (0)