Skip to content

Commit 41c585e

Browse files
Andrey Proninchrome-bot
authored andcommitted
tpm_lite: stub: retry in case of TPM comm error
This CL retries reads and writes from/to TPM device if an error is returned by read()/write(), up to 3 total attempts. This is useful case of transient TPM communication errors that go away after a single retry. Without this CL, after such errors the encstateful key might be regenerated and encstateful data wiped. BRANCH=none BUG=chromium:702724 TEST=1) normal boot still works; 2) simulate a single error, verify that it retries. Change-Id: I259882209df0aad66cd083729f746ea45909922b Reviewed-on: https://chromium-review.googlesource.com/1067939 Commit-Ready: Andrey Pronin <apronin@chromium.org> Tested-by: Andrey Pronin <apronin@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org>
1 parent ecda115 commit 41c585e

1 file changed

Lines changed: 45 additions & 7 deletions

File tree

firmware/stub/tpm_lite_stub.c

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
/* Retry failed open()s for 5 seconds in 10ms polling intervals. */
3434
#define OPEN_RETRY_DELAY_NS (10 * 1000 * 1000)
3535
#define OPEN_RETRY_MAX_NUM 500
36+
#define COMM_RETRY_MAX_NUM 3
3637

3738
/* TODO: these functions should pass errors back rather than returning void */
3839
/* TODO: if the only callers to these are just wrappers, should just
@@ -90,20 +91,57 @@ static VbError_t TpmExecute(const uint8_t *in, const uint32_t in_len,
9091
"the TPM device was not opened. " \
9192
"Forgot to call TlclLibInit?\n");
9293
} else {
93-
int n = write(tpm_fd, in, in_len);
94-
if (n != in_len) {
94+
int n;
95+
int retries = 0;
96+
int first_errno = 0;
97+
98+
/* Write command. Retry in case of communication errors.
99+
*/
100+
for ( ; retries < COMM_RETRY_MAX_NUM; ++retries) {
101+
n = write(tpm_fd, in, in_len);
102+
if (n >= 0) {
103+
break;
104+
}
105+
if (retries == 0) {
106+
first_errno = errno;
107+
}
108+
VB2_DEBUG("TPM: write attempt %d failed: %s\n",
109+
retries + 1, strerror(errno));
110+
}
111+
if (n < 0) {
112+
return DoError(TPM_E_WRITE_FAILURE,
113+
"write failure to TPM device: %s "
114+
"(first error %d)\n",
115+
strerror(errno), first_errno);
116+
} else if (n != in_len) {
95117
return DoError(TPM_E_WRITE_FAILURE,
96-
"write failure to TPM device: %s\n",
97-
strerror(errno));
118+
"bad write size to TPM device: %d vs %u "
119+
"(%d retries, first error %d)\n",
120+
n, in_len, retries, first_errno);
121+
}
122+
123+
/* Read response. Retry in case of communication errors.
124+
*/
125+
for (retries = 0, first_errno = 0;
126+
retries < COMM_RETRY_MAX_NUM; ++retries) {
127+
n = read(tpm_fd, response, sizeof(response));
128+
if (n >= 0) {
129+
break;
130+
}
131+
if (retries == 0) {
132+
first_errno = errno;
133+
}
134+
VB2_DEBUG("TPM: read attempt %d failed: %s\n",
135+
retries + 1, strerror(errno));
98136
}
99-
n = read(tpm_fd, response, sizeof(response));
100137
if (n == 0) {
101138
return DoError(TPM_E_READ_EMPTY,
102139
"null read from TPM device\n");
103140
} else if (n < 0) {
104141
return DoError(TPM_E_READ_FAILURE,
105-
"read failure from TPM device: %s\n",
106-
strerror(errno));
142+
"read failure from TPM device: %s "
143+
"(first error %d)\n",
144+
strerror(errno), first_errno);
107145
} else {
108146
if (n > *pout_len) {
109147
return DoError(TPM_E_RESPONSE_TOO_LARGE,

0 commit comments

Comments
 (0)